mondo: def node

This commit is contained in:
Felix Roos 2025-03-30 11:43:01 +02:00
parent b4027fd92a
commit a0fb8fb37f
No known key found for this signature in database
3 changed files with 27 additions and 11 deletions

View file

@ -175,10 +175,10 @@ export class MondoParser {
return children;
}
get_lambda(args, children) {
// (.fast 2) = (lambda (_) (fast _ 2))
// (.fast 2) = (fn (_) (fast _ 2))
children = this.desugar(children);
const body = children.length === 1 ? children[0] : { type: 'list', children };
return [{ type: 'plain', value: 'lambda' }, { type: 'list', children: args }, body];
return [{ type: 'plain', value: 'fn' }, { type: 'list', children: args }, body];
}
// returns location range of given ast (even if desugared)
get_range(ast, range = [Infinity, 0]) {
@ -322,7 +322,7 @@ export class MondoRunner {
console.log(printAst(ast));
return this.evaluate(ast);
}
evaluate(ast, scope = []) {
evaluate(ast, scope = {}) {
if (ast.type !== 'list') {
// is leaf
if (ast.type === 'number') {
@ -333,7 +333,20 @@ export class MondoRunner {
return this.evaluator(ast, scope);
}
if (ast.children[0]?.value === 'lambda') {
if (ast.children[0]?.value === 'def') {
if (ast.children.length !== 3) {
throw new Error(`expected "def" to have 3 children, but got ${ast.children.length}`);
}
// (def myfn (fn (_) (ply 2 _)))
// ^name ^body
const name = ast.children[1].value;
const body = this.evaluate(ast.children[2], scope);
scope[name] = body;
return this.evaluator(ast, scope);
}
if (ast.children[0]?.value === 'fn') {
// (fn (_) (ply 2 _)
// ^args ^ body
const [_, args, body] = ast.children;
const argNames = args.children.map((child) => child.value);
return (x) => {

View file

@ -119,10 +119,10 @@ describe('mondo sugar', () => {
'(speed .8 (s (square bd (* 2 hh) (crush 4 cp) (angle mt ht lt))))',
));
it('should desugar (.)', () => expect(desguar('(.)')).toEqual('(lambda (_) _)'));
it('should desugar lambda', () => expect(desguar('(.fast 2)')).toEqual('(lambda (_) (fast 2 _))'));
it('should desugar (.)', () => expect(desguar('(.)')).toEqual('(fn (_) _)'));
it('should desugar lambda', () => expect(desguar('(.fast 2)')).toEqual('(fn (_) (fast 2 _))'));
it('should desugar lambda with pipe', () =>
expect(desguar('(.fast 2 .room 1)')).toEqual('(lambda (_) (room 1 (fast 2 _)))'));
expect(desguar('(.fast 2 .room 1)')).toEqual('(fn (_) (room 1 (fast 2 _)))'));
/* const lambda = parser.parse('(lambda (_) (fast 2 _))');
const target = { type: 'plain', value: 'xyz' };
it('should desugar_lambda', () =>

View file

@ -49,15 +49,19 @@ function evaluator(node, scope) {
if (type === 'list') {
const { children } = node;
const [name, ...args] = children;
if (name.value === 'def') {
return silence;
}
// name is expected to be a pattern of functions!
const first = name.firstCycle(true)[0];
if (typeof first?.value !== 'function') {
throw new Error(`[mondough] "${first}" is not a function`);
const type = typeof first?.value;
if (type !== 'function') {
throw new Error(`[mondough] "${first}" is not a function, got ${type} ...`);
}
return name
.fmap((fn) => {
if (typeof fn !== 'function') {
throw new Error(`[mondough] "${fn}" is not a function`);
throw new Error(`[mondough] "${fn}" is not a function b`);
}
return fn(...args);
})
@ -80,7 +84,6 @@ function evaluator(node, scope) {
if (node.loc) {
pat = pat.withLoc(node.loc[0], node.loc[1]);
}
pat.foo = true;
return pat;
}