diff options
| -rw-r--r-- | compiler.d | 48 | ||||
| -rw-r--r-- | functions.txt | 8 | ||||
| -rw-r--r-- | parser.d | 46 |
3 files changed, 91 insertions, 11 deletions
@@ -555,6 +555,36 @@ class Compiler { // create a copy of the list } + void compileLambda(Form form) { + Lambda lamb = cast(Lambda)form; + Compiler compiler = new Compiler(ObjType.FUNCTION, this.parser, "<lambda>"); + compiler.beginScope(); + + if (lamb.args.type != FormType.NIL) { + Symbol sym = cast(Symbol)lamb.args.head; + int constant = compiler.parseVariable(sym); + compiler.defineVariable(constant); + + foreach (Form inner ; lamb.args.tail) { + sym = cast(Symbol)inner; + constant = compiler.parseVariable(sym); + compiler.defineVariable(constant); + } + } + + advance(); // ?? + + Block b = new Block(lamb.line); + b.blockBody = lamb.lambdaBody; + compiler.compileBlock(b); + + // write the function as a Value + Function outFunc = compiler.finish(); + this.func.chunk.writeOp(OpCode.OP_CONSTANT, lamb.line); + int funcAddr = this.func.chunk.addConstant(makeObjValue(outFunc)); + this.func.chunk.writeOp(to!ubyte(funcAddr), lamb.line); + } + void compileFunc(Form form) { Func f = cast(Func)form; @@ -576,13 +606,6 @@ class Compiler { } } - /* - // compile each inner Form - foreach (Form inner; f.funcBody) { - compiler.resolve(inner); - } - */ - advance(); // ?? Block b = new Block(f.line); @@ -602,6 +625,14 @@ class Compiler { ValueType compileCons(Form form, ValueType expected) { Cons cons = cast(Cons)form; Form head = cons.head; + + if (head.type == FormType.LAMBDA) { + this.resolve(head); + this.call(cons.tail); + this.advance(); + return ValueType.NIL; + } + if (head.type != FormType.SYMBOL) { writeln("cons must start with a symbol"); this.advance(); @@ -700,6 +731,9 @@ class Compiler { case FormType.FUNC: this.compileFunc(form); break; + case FormType.LAMBDA: + this.compileLambda(form); + break; default: write("not sure how to resolve: "); printForm(form); diff --git a/functions.txt b/functions.txt index 986164f..6c18c60 100644 --- a/functions.txt +++ b/functions.txt @@ -39,20 +39,20 @@ LISP-Y: [x] block [ ] parse-neb [ ] eval -[ ] lambda +[x] lambda [ ] quote LISTS: [ ] append [ ] empty? -[ ] first +[x] first [ ] in? [ ] last [ ] length -[-] list (works, but adds every item as a constant?) +[x] list [ ] most [ ] prepend -[ ] rest +[x] rest [ ] reverse [ ] shuf [ ] slice @@ -12,6 +12,7 @@ enum FormType { NIL, SYMBOL, FUNC, + LAMBDA, DEF, BLOCK, IF, @@ -211,6 +212,21 @@ class Func : Form { } } +class Lambda : Form { + + Cons args; + Form[] lambdaBody; + + this (int line) { + this.line = line; + this.type = FormType.LAMBDA; + } + + void addToBody(Form f) { + this.lambdaBody ~= f; + } +} + class Def : Form { Symbol name; @@ -449,6 +465,34 @@ class Parser { return def; } + Form parseLambda() { + // we've parsed `lambda` already + Form args = parseForm(); + if (args.type != FormType.CONS && args.type != FormType.NIL) { + return new ParseError("func definitions expect a list of arguments", line); + } + + Lambda lamb = new Lambda(line); + lamb.args = cast(Cons)args; + + char next; + while(peekable()) { + next = peek(); + if (next == ')') { + break; + } + lamb.addToBody(this.parseForm()); + } + + if (!peekable()) { + return new ParseError("unterminated lambda", line); + } + + advance(); // consume closing paren + + return lamb; + } + Form parseFunc() { // we've parsed `func`, but not the symbol yet Form sym = parseForm(); @@ -579,6 +623,8 @@ class Parser { switch (s.name) { case "func": return parseFunc(); + case "lambda": + return parseLambda(); case "def": return parseDef(); case "block": |
