diff --git a/desugar.js b/desugar.js index 0f3fdd8..2a1d19e 100644 --- a/desugar.js +++ b/desugar.js @@ -20,11 +20,16 @@ function desugarList(lst) { } function desugarDefFunc(def) { - return new typ.Def(def.ident, new typ.FuncT(desugar(def.params), desugar(def.body))); + return new typ.Def(def.ident, + new typ.FuncT(desugar(def.params), + desugar(def.body))); } -//function desugarString(str) { +function desugarLet(stx) { + var values = stx.pairs.map(desugar); + return new typ.LetExp(values, desugar(stx.body)); +} function desugar(stx) { switch (stx.exprType) { @@ -59,6 +64,8 @@ function desugar(stx) { return stx; case "Integer": return stx; + case "Let": + return desugarLet(stx); default: return stx; } diff --git a/parse.js b/parse.js index fa88765..9f6ca87 100755 --- a/parse.js +++ b/parse.js @@ -188,8 +188,8 @@ function parseLetForm(tokens, linenum, charnum) { charnum, "Unexpected end of source"); } - linenum = fst(tokens)[2]; - charnum = fst(tokens)[3]; + linenum = fst(tokens)[3]; + charnum = fst(tokens)[2]; tokens.pop(); if (tokens.length <= 0) { throw error.JSyntaxError(linenum, @@ -197,6 +197,12 @@ function parseLetForm(tokens, linenum, charnum) { "let/def form must have a body"); } var body = parse(tokens); + if (body.exprType === "Definition" || + body.exprType === "FunctionDefinition") { + throw error.JSyntaxError(linenum, + charnum, + "Body of a let/def expression cannot be a definition"); + } return new typ.LetExp(pairs, body); } @@ -250,14 +256,21 @@ function parseLetBinding(tokens, linenum, charnum) { } tokens.pop(); if (!notFollowedBy(tokens, - ["def", "comma", "arrow", "right_brace", "right_square"], + ["comma", "arrow", "right_brace", "right_square"], linenum, charnum)) { throw error.JSyntaxError(linenum, charnum, "The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); } - return new typ.Def(name, parse(tokens)); + var bound = parse(tokens); + if (bound.exprType === "Definition" || + bound.exprType === "FunctionDefinition") { + throw error.JSyntaxError(linenum, + charnum, + "A definition cannot be the value of a binding"); + } + return new typ.Def(name, bound); } function parseLetItem(tokens) { @@ -289,8 +302,8 @@ function parseDef(tokens, linenum, charnum) { /* It's a let/def form */ tokens.pop(); return parseLetForm(tokens, - fst(tokens)[2], - fst(tokens)[3]); + fst(tokens)[3], + fst(tokens)[2]); } if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) { @@ -307,14 +320,21 @@ function parseDef(tokens, linenum, charnum) { linenum = fst(tokens)[3]; charnum = fst(tokens)[2]; if (!notFollowedBy(tokens, - ["def", "comma", "arrow", "right_brace", "right_square"], + ["comma", "arrow", "right_brace", "right_square"], linenum, charnum)) { throw error.JSyntaxError(linenum, charnum, "def " + identifier.val + " must not be followed by " + fst(tokens)[0]); } - return new typ.Def(identifier, parse(tokens)); + var bound = parse(tokens); + if (bound.exprType === "Definition" || + bound.exprType === "FunctionDefinition") { + throw error.JSyntaxError(linenum, + charnum, + "A definition cannot be the value of a binding"); + } + return new typ.Def(identifier, bound); } } @@ -517,9 +537,9 @@ function parseFull(tokenized) { process.exit(1); } } -//console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint).join("\n")); +console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint).join("\n")); //console.log(tokenizer.tokenize(istr)); -console.log(parseFull(tokenizer.tokenize(istr))); +//console.log(parseFull(tokenizer.tokenize(istr))); //module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) }; diff --git a/pprint.js b/pprint.js index a5cdf36..19a94a8 100644 --- a/pprint.js +++ b/pprint.js @@ -55,6 +55,11 @@ function pprint(expr) { return "[]"; else if (expr.exprType === "Unary") return "("+expr.op.ident+" "+pprint(expr.val)+")"; + else if (expr.exprType === "Let") + return "let {" + expr.pairs.map( + function (v) { + return pprint(v) + }).join(" ; ") + "} in " + pprint(expr.body); } module.exports = {pprint : pprint}; diff --git a/representation.js b/representation.js index 3f56eab..bc19d72 100644 --- a/representation.js +++ b/representation.js @@ -215,4 +215,5 @@ module.exports = DefFunc : DefFunc, UnaryOp : UnaryOp, Nil : Nil, - LetExp : LetExp} + LetExp : LetExp + } diff --git a/test.jl b/test.jl index 288a449..ae33ebe 100644 --- a/test.jl +++ b/test.jl @@ -44,12 +44,22 @@ def (splitHelp acc xs ys) def (splitxs xs) (splitHelp [] xs xs) +def r def + { + a = 4 + } + a + def main - ((print (testUnary 6)) >> - if False - then - undefined - else fileLines - >> - (print - (splitxs [12,3,4,56]))) + let { + unary = (print (testUnary 6)) + splitted = def { + xs = (fst (splitxs [12,3,4,56])) + } (xs ++ [0,9]) + } + if False + then undefined + else + (unary >> + fileLines >> + (print splitted))