aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler.d48
-rw-r--r--functions.txt8
-rw-r--r--parser.d46
3 files changed, 91 insertions, 11 deletions
diff --git a/compiler.d b/compiler.d
index 6f5f0fd..92711f1 100644
--- a/compiler.d
+++ b/compiler.d
@@ -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
diff --git a/parser.d b/parser.d
index 68f5093..e51b5e1 100644
--- a/parser.d
+++ b/parser.d
@@ -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":