Browse Source

desugaring for let/def expressions, more error handling, expanded test cases

pull/1/head
Wesley Kerfoot 11 years ago
parent
commit
7589d5c4d2
  1. 11
      desugar.js
  2. 40
      parse.js
  3. 5
      pprint.js
  4. 3
      representation.js
  5. 26
      test.jl

11
desugar.js

@ -20,11 +20,16 @@ function desugarList(lst) {
} }
function desugarDefFunc(def) { 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) { function desugar(stx) {
switch (stx.exprType) { switch (stx.exprType) {
@ -59,6 +64,8 @@ function desugar(stx) {
return stx; return stx;
case "Integer": case "Integer":
return stx; return stx;
case "Let":
return desugarLet(stx);
default: default:
return stx; return stx;
} }

40
parse.js

@ -188,8 +188,8 @@ function parseLetForm(tokens, linenum, charnum) {
charnum, charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
linenum = fst(tokens)[2]; linenum = fst(tokens)[3];
charnum = fst(tokens)[3]; charnum = fst(tokens)[2];
tokens.pop(); tokens.pop();
if (tokens.length <= 0) { if (tokens.length <= 0) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
@ -197,6 +197,12 @@ function parseLetForm(tokens, linenum, charnum) {
"let/def form must have a body"); "let/def form must have a body");
} }
var body = parse(tokens); 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); return new typ.LetExp(pairs, body);
} }
@ -250,14 +256,21 @@ function parseLetBinding(tokens, linenum, charnum) {
} }
tokens.pop(); tokens.pop();
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["def", "comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, linenum,
charnum)) { charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); "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) { function parseLetItem(tokens) {
@ -289,8 +302,8 @@ function parseDef(tokens, linenum, charnum) {
/* It's a let/def form */ /* It's a let/def form */
tokens.pop(); tokens.pop();
return parseLetForm(tokens, return parseLetForm(tokens,
fst(tokens)[2], fst(tokens)[3],
fst(tokens)[3]); fst(tokens)[2]);
} }
if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) { if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
@ -307,14 +320,21 @@ function parseDef(tokens, linenum, charnum) {
linenum = fst(tokens)[3]; linenum = fst(tokens)[3];
charnum = fst(tokens)[2]; charnum = fst(tokens)[2];
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["def", "comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, linenum,
charnum)) { charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"def " + identifier.val + " must not be followed by " + fst(tokens)[0]); "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); 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(tokenizer.tokenize(istr));
console.log(parseFull(tokenizer.tokenize(istr))); //console.log(parseFull(tokenizer.tokenize(istr)));
//module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) }; //module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) };

5
pprint.js

@ -55,6 +55,11 @@ function pprint(expr) {
return "[]"; return "[]";
else if (expr.exprType === "Unary") else if (expr.exprType === "Unary")
return "("+expr.op.ident+" "+pprint(expr.val)+")"; 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}; module.exports = {pprint : pprint};

3
representation.js

@ -215,4 +215,5 @@ module.exports =
DefFunc : DefFunc, DefFunc : DefFunc,
UnaryOp : UnaryOp, UnaryOp : UnaryOp,
Nil : Nil, Nil : Nil,
LetExp : LetExp} LetExp : LetExp
}

26
test.jl

@ -44,12 +44,22 @@ def (splitHelp acc xs ys)
def (splitxs xs) def (splitxs xs)
(splitHelp [] xs xs) (splitHelp [] xs xs)
def r def
{
a = 4
}
a
def main def main
((print (testUnary 6)) >> let {
if False unary = (print (testUnary 6))
then splitted = def {
undefined xs = (fst (splitxs [12,3,4,56]))
else fileLines } (xs ++ [0,9])
>> }
(print if False
(splitxs [12,3,4,56]))) then undefined
else
(unary >>
fileLines >>
(print splitted))

Loading…
Cancel
Save