Browse Source

Merge pull request #8 from oftn/master

merge OFTN version
pull/21/head
Wesley Kerfoot 11 years ago
parent
commit
61c07701c8
  1. 2
      closure_conversion.js
  2. 23
      desugar.js
  3. 11
      example.jl
  4. 270
      parse.js
  5. 12
      pprint.js
  6. 193
      representation.js

2
closure_conversion.js

@ -151,7 +151,7 @@ function test(src) {
console.log(JSON.stringify(closure_convert_all(ast), null, 4)); console.log(JSON.stringify(closure_convert_all(ast), null, 4));
} }
//console.log(test(pprint.pprint(parser.parse(pprint.pprint(parser.parse("if something then if a then if b then c else d else rtrrt else some_other_thing")[0]))[0]))); //console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing"));
module.export = { module.export = {
test : test, test : test,
closureConvert : closure_convert_all closureConvert : closure_convert_all

23
desugar.js

@ -26,7 +26,6 @@ function desugarDefFunc(def) {
def.body)); def.body));
} }
function curryFunc(ps, body) { function curryFunc(ps, body) {
if (_.isEmpty(ps)) { if (_.isEmpty(ps)) {
return desugar(body); return desugar(body);
@ -43,6 +42,15 @@ function desugarLet(stx) {
return new typ.LetExp(values, desugar(stx.body)); return new typ.LetExp(values, desugar(stx.body));
} }
function sugarTypeApp(stx) {
var type;
var expression;
type = stx.p;
expression = desugar(stx.func.p);
return new typ.TypeApp(expression, type);
}
function desugar(stx) { function desugar(stx) {
switch (stx.exprType) { switch (stx.exprType) {
case "If": case "If":
@ -56,10 +64,15 @@ function desugar(stx) {
case "Name": case "Name":
return stx; return stx;
case "Application": case "Application":
if (stx.func.ident === "::") { if ((stx.func.func != undefined ) &&
//It's a type binding (stx.func.func.ident === "::")) {
return desugarTypeBinding(stx); /* It's a type application probably (will be verified later)
} * In this case we actually *add* syntax here to differentiate type applications
* from normal applications
*/
return sugarTypeApp(stx);
}
if ((stx.func.ident === "-" || if ((stx.func.ident === "-" ||
stx.func.ident === "+") && stx.func.ident === "+") &&
stx.p) { stx.p) {

11
example.jl

@ -1,8 +1,9 @@
defop 2 Left (a ## b) defop 2 Left (a ++#$ b)
(a - b) (a - b)
def (f a b)
(a ++ b) (qat :: A)
def qat (lambda a b c -> (a + b))
def (add a b) def (add a b)
(a + b) (a + b)
@ -63,6 +64,6 @@ def main
if False if False
then undefined then undefined
else else
(unary >> (unary +
fileLines >> fileLines +
(print splitted)) (print splitted))

270
parse.js

@ -11,33 +11,33 @@ var error = require("./errors.js");
var print = console.log; var print = console.log;
function fst(ts) { function fst(ts) {
return ts[ts.length-1]; return ts[ts.length-1];
} }
function snd(ts) { function snd(ts) {
return ts[ts.length-2]; return ts[ts.length-2];
} }
/*Checks if the next token is not followed by any of ``checks'' */ /*Checks if the next token is not followed by any of ``checks'' */
function notFollowedBy(tokens, checks, linenum, charnum) { function notFollowedBy(tokens, checks, linenum, charnum) {
if (!fst(tokens)) { if (!fst(tokens)) {
throw error.JSyntaxError(0,0,"unexpected end of source"); throw error.JSyntaxError(0,0,"unexpected end of source");
} }
var nextT = fst(tokens)[0]; var nextT = fst(tokens)[0];
if (checks.some(function (x) { if (checks.some(function (x) {
return x === nextT; return x === nextT;
})) }))
return false; return false;
else else
return true; return true;
} }
/* returns a function that takes a parameter and /* returns a function that takes a parameter and
checks if it is in the array ``props''*/ checks if it is in the array ``props''*/
function makeChecker(props) { function makeChecker(props) {
return function(x) { return function(x) {
return x && props.some(function (y) {return y(x);}); return x && props.some(function (y) {return y(x);});
}; };
} }
function tokTypeCheck(name) { function tokTypeCheck(name) {
@ -61,43 +61,43 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
"Unexpected end of source"); "Unexpected end of source");
} }
var current = fst(tokens)[0]; var current = fst(tokens)[0];
var results = []; var results = [];
var parsed; var parsed;
if (valid(fst(tokens))) { if (valid(fst(tokens))) {
parsed = parse(tokens); parsed = parse(tokens);
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Unexpected token: ``"+fst(tokens)[0]+"''"); "Unexpected token: ``"+fst(tokens)[0]+"''");
} }
results.push(parsed); results.push(parsed);
//make sure there are at least 2 tokens to parse //make sure there are at least 2 tokens to parse
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) { if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens))) { while (valid(snd(tokens))) {
if (!(valid(fst(tokens)))) if (!(valid(fst(tokens))))
break; break;
results.push(parse(tokens)); results.push(parse(tokens));
if (!exprType(fst(results).exprType)) if (!exprType(fst(results).exprType))
break; break;
if (fst(tokens)) if (fst(tokens))
current = fst(tokens)[0]; current = fst(tokens)[0];
else else
throw error.JSyntaxError(charnum, linenum, "Unexpected end of source"); throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
if (tokens.length <= 1) if (tokens.length <= 1)
break; break;
} }
} }
//do the same validity check as before and in the loop //do the same validity check as before and in the loop
if (!fst(tokens)) if (!fst(tokens))
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"unexpected end of source"); "unexpected end of source");
if (valid(fst(tokens))) if (valid(fst(tokens)))
results.push(parse(tokens)); results.push(parse(tokens));
return results; return results;
} }
@ -149,7 +149,7 @@ function parseList(tokens) {
function parseDefFunction(tokens) { function parseDefFunction(tokens) {
var fname = parse(tokens); var fname = parse(tokens);
var parameters; var parameters;
if (fname.exprType != "Name") { if (fname.exprType != "Name") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
@ -285,7 +285,7 @@ function parseLetBinding(tokens, linenum, charnum) {
charnum, charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
return new typ.Def(name, bound); return new typ.Def(name, bound);
} }
function parseLetItem(tokens) { function parseLetItem(tokens) {
@ -321,12 +321,12 @@ function parseDef(tokens, linenum, charnum) {
fst(tokens)[2]); fst(tokens)[2]);
} }
if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) { if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"def must be followed by identifier, not "+fst(tokens)[0]); "def must be followed by identifier, not "+fst(tokens)[0]);
} }
else { else {
var identifier = parse(tokens); var identifier = parse(tokens);
if (!fst(tokens)) if (!fst(tokens))
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
@ -349,8 +349,8 @@ function parseDef(tokens, linenum, charnum) {
charnum, charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
return new typ.Def(identifier, bound); return new typ.Def(identifier, bound);
} }
} }
function parseDefOp(tokens, linenum, charnum) { function parseDefOp(tokens, linenum, charnum) {
@ -402,35 +402,35 @@ function parseDefOp(tokens, linenum, charnum) {
function parseIf(tokens) { function parseIf(tokens) {
var linenum = fst(tokens)[3]; var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2]; var charnum = fst(tokens)[2];
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["def","comma","lambda"], ["def","comma","lambda"],
linenum, linenum,
charnum)) { charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"``if'' cannot be followed by "+fst(tokens)[0]) ; "``if'' cannot be followed by "+fst(tokens)[0]) ;
} }
else { else {
var ifC = parse(tokens); var ifC = parse(tokens);
if (!fst(tokens) || fst(tokens)[0] !== "thenexp") { if (!fst(tokens) || fst(tokens)[0] !== "thenexp") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2], fst(tokens)[2],
"if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]); "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
} }
else { else {
tokens.pop(); tokens.pop();
var thenC = parse(tokens); var thenC = parse(tokens);
if (fst(tokens) && fst(tokens)[0] === "elsexp") { if (fst(tokens) && fst(tokens)[0] === "elsexp") {
tokens.pop(); tokens.pop();
if (_.size(tokens) < 1) { if (_.size(tokens) < 1) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
else { else {
var elseC = parse(tokens); var elseC = parse(tokens);
return new typ.If(ifC, thenC, elseC); return new typ.If(ifC, thenC, elseC);
} }
} }
else { else {
@ -452,20 +452,20 @@ function validFormPar(tok) {
function parseLambda(tokens) { function parseLambda(tokens) {
var linenum = fst(tokens)[2]; var linenum = fst(tokens)[2];
var charnum = fst(tokens)[3]; var charnum = fst(tokens)[3];
var parameters = parseMany(parse, var parameters = parseMany(parse,
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
charnum, charnum,
linenum); linenum);
if (fst(tokens)[1] !== "->") { if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2], fst(tokens)[2],
"arrow must follow parameters in lambda, not "+fst(tokens)[0]); "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
} }
tokens.pop(); tokens.pop();
var body = parse(tokens); var body = parse(tokens);
return new typ.FuncT(parameters, body); return new typ.FuncT(parameters, body);
} }
var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck); var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck);
@ -477,31 +477,31 @@ function computeApp(tokens, charnum, linenum) {
var lhs = parse(tokens); var lhs = parse(tokens);
var next; var next;
var result; var result;
if (fst(tokens)) { if (fst(tokens)) {
next = fst(tokens); next = fst(tokens);
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
if (typ.OPInfo[next[1]]) { if (typ.OPInfo[next[1]]) {
/* it's an infix expression */ /* it's an infix expression */
result = parseInfix(tokens, 1, lhs, linenum, charnum); result = parseInfix(tokens, 1, lhs, linenum, charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
tokens.pop(); tokens.pop();
return result; return result;
} }
} }
else { else {
/* it's a prefix application */ /* it's a prefix application */
var parameters; var parameters;
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse, parameters = parseMany(parse,
validArgTypes, validArgTypes,
validArgument, validArgument,
@ -512,16 +512,16 @@ function computeApp(tokens, charnum, linenum) {
else { else {
parameters = []; parameters = [];
} }
if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") { if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
tokens.pop(); tokens.pop();
return typ.makeApp(lhs, parameters); return typ.makeApp(lhs, parameters);
} }
} }
} }
/*Parses infix expressions by precedence climbing /*Parses infix expressions by precedence climbing
@ -529,81 +529,81 @@ function computeApp(tokens, charnum, linenum) {
http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/ http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/
*/ */
function parseInfix(tokens, minPrec, lhs, linenum, charnum) { function parseInfix(tokens, minPrec, lhs, linenum, charnum) {
if (!lhs) { if (!lhs) {
lhs = parse(tokens); lhs = parse(tokens);
} }
while (true) { while (true) {
var cur = fst(tokens); var cur = fst(tokens);
if (!cur) { if (!cur) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
var opinfo = typ.OPInfo[cur[1]]; var opinfo = typ.OPInfo[cur[1]];
if (!opinfo || opinfo[0] < minPrec) if (!opinfo || opinfo[0] < minPrec)
break; break;
var op = new typ.Name(cur[1]); var op = new typ.Name(cur[1]);
var prec = opinfo[0]; var prec = opinfo[0];
var assoc = opinfo[1]; var assoc = opinfo[1];
var nextMinPrec = assoc === "Left" ? prec + 1 : prec; var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
tokens.pop(); tokens.pop();
/*remove the operator token*/ /*remove the operator token*/
var rhs = parseInfix(tokens, nextMinPrec); var rhs = parseInfix(tokens, nextMinPrec);
lhs = typ.makeApp(op, [lhs, rhs]); lhs = typ.makeApp(op, [lhs, rhs]);
} }
return lhs; return lhs;
} }
function parse(tokens) { function parse(tokens) {
var charnum = fst(tokens)[2]; var charnum = fst(tokens)[2];
var linenum = fst(tokens)[3]; var linenum = fst(tokens)[3];
var toktype; var toktype;
if (fst(tokens)) { if (fst(tokens)) {
toktype = fst(tokens)[0]; toktype = fst(tokens)[0];
} }
else { else {
process.exit(code=1); process.exit(code=1);
} }
var token = fst(tokens)[1]; var token = fst(tokens)[1];
tokens.pop(); tokens.pop();
if (toktype === "stringlit") { if (toktype === "stringlit") {
return new typ.StrT(token); return new typ.StrT(token);
} }
else if (toktype === "left_square") { else if (toktype === "left_square") {
return parseList(tokens); return parseList(tokens);
} }
else if (toktype === "lambda") { else if (toktype === "lambda") {
return parseLambda(tokens); return parseLambda(tokens);
} }
else if (toktype === "integer") { else if (toktype === "integer") {
return new typ.IntT(token); return new typ.IntT(token);
} }
else if (toktype === "float") { else if (toktype === "float") {
return new typ.FloatT(token); return new typ.FloatT(token);
} }
else if (toktype === "identifier") { else if (toktype === "identifier") {
return new typ.Name(token); return new typ.Name(token);
} }
else if (toktype === "constructor") { else if (toktype === "constructor") {
return new typ.TypeOp(token); return new typ.TypeOp(token);
} }
else if (toktype === "truelit" || toktype === "falselit") { else if (toktype === "truelit" || toktype === "falselit") {
return new typ.BoolT(token); return new typ.BoolT(token);
} }
else if (toktype === "def" || else if (toktype === "def" ||
toktype === "let") { toktype === "let") {
return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]); return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
} }
else if (toktype === "defop") { else if (toktype === "defop") {
return parseDefOp(tokens, fst(tokens)[3], fst(tokens)[2]); return parseDefOp(tokens, fst(tokens)[3], fst(tokens)[2]);
} }
else if (toktype === "ifexp") { else if (toktype === "ifexp") {
return parseIf(tokens); return parseIf(tokens);
} }
else if (toktype === "left_paren") { else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") { if (fst(tokens)[0] === "lambda") {
tokens.pop(); tokens.pop();
var parsed = parseLambda(tokens); var parsed = parseLambda(tokens);
tokens.pop(); tokens.pop();

12
pprint.js

@ -30,9 +30,6 @@ function pprint(expr) {
if (expr.exprType === "Name") { if (expr.exprType === "Name") {
return expr.val; return expr.val;
} }
else if (expr.exprType === "TypeOperator") {
return expr.val;
}
else if (expr.exprType === "Bool") { else if (expr.exprType === "Bool") {
if (expr.val) { if (expr.val) {
return "True"; return "True";
@ -77,6 +74,15 @@ function pprint(expr) {
return pprint(v); return pprint(v);
}).join(" ; ") + "} in " + pprint(expr.body); }).join(" ; ") + "} in " + pprint(expr.body);
} }
else if (expr.exprType === "TypeOperator") {
return "("+expr.val+")";
}
else if (expr.exprType === "TypeVar") {
return "("+expr.name+")";
}
else if (expr.exprType === "TypeApplication") {
return "( " + pprint(expr.expression) + " :: " + pprint(expr.type) + " )";
}
} }
module.exports = {pprint : pprint}; module.exports = {pprint : pprint};

193
representation.js

@ -2,26 +2,26 @@ var errors = require("./errors.js");
var _ = require("underscore"); var _ = require("underscore");
var Expression = { var Expression = {
display : display :
function() { function() {
return this.exprType + " " + this.val; return this.exprType + " " + this.val;
}, },
type : type :
function () { function () {
return this.exprType; return this.exprType;
} }
}; };
var TypeExpression = { var TypeExpression = {
unify : unify :
function (t) { function (t) {
if (this.expr === t.expr) { if (this.expr === t.expr) {
return t.expr; return t.expr;
} }
else { else {
console.log("Could not unify " + this.expr + " with " + t.expr); console.log("Could not unify " + this.expr + " with " + t.expr);
} }
}, },
isTypeExpr : true isTypeExpr : true
}; };
@ -41,7 +41,9 @@ function LetExp(pairs, body) {
return (x.exprType === "Definition" || return (x.exprType === "Definition" ||
x.exprType === "FunctionDefinition"); x.exprType === "FunctionDefinition");
})) { })) {
throw "let can only be used to bind things to names or functions"; throw Errors.JInternalError(
"let can only be used to bind things to names or functions"
);
} }
this.exprType = "Let"; this.exprType = "Let";
this.val = [pairs, body]; this.val = [pairs, body];
@ -60,46 +62,46 @@ function UnaryOp(op, v) {
UnaryOp.prototype = Expression; UnaryOp.prototype = Expression;
function IntT(v) { function IntT(v) {
this.exprType = "Integer"; this.exprType = "Integer";
this.val = parseInt(v, 10); this.val = parseInt(v, 10);
return this; return this;
} }
IntT.prototype = Expression; IntT.prototype = Expression;
function FloatT(v) { function FloatT(v) {
this.exprType = "Float"; this.exprType = "Float";
this.val = parseFloat(v, 10); this.val = parseFloat(v, 10);
return this; return this;
} }
FloatT.prototype = Expression; FloatT.prototype = Expression;
function StrT(v) { function StrT(v) {
this.exprType = "String"; this.exprType = "String";
this.val = v; this.val = v;
return this; return this;
} }
StrT.prototype = Expression; StrT.prototype = Expression;
function BoolT(b) { function BoolT(b) {
if (b === "true") { if (b === "true") {
this.val = true; this.val = true;
} }
else { else {
this.val = false; this.val = false;
} }
this.exprType = "Bool"; this.exprType = "Bool";
return this; return this;
} }
BoolT.prototype = Expression; BoolT.prototype = Expression;
function ListT(xs) { function ListT(xs) {
this.xs = xs; this.xs = xs;
this.val = xs; this.val = xs;
this.exprType = "List"; this.exprType = "List";
return this; return this;
} }
function Nil() { function Nil() {
@ -111,47 +113,47 @@ Nil.prototype = Expression;
ListT.prototype = Expression; ListT.prototype = Expression;
function FuncT(p, body) { function FuncT(p, body) {
this.p = p; this.p = p;
this.body = body; this.body = body;
this.val = [p, body]; this.val = [p, body];
this.exprType = "Function"; this.exprType = "Function";
return this; return this;
} }
FuncT.prototype = Expression; FuncT.prototype = Expression;
//Wrapper for function objects //Wrapper for function objects
function OpT(operator) { function OpT(operator) {
this.op = operator; this.op = operator;
this.val = this.op; this.val = this.op;
this.exprType = "Function"; this.exprType = "Function";
return this; return this;
} }
OpT.prototype = Expression; OpT.prototype = Expression;
// Applications separate from other types // Applications separate from other types
function App(func, p) { function App(func, p) {
this.func = func; this.func = func;
this.exprType = "Application"; this.exprType = "Application";
if (p) if (p)
this.p = p; this.p = p;
return this; return this;
} }
// Names are not types // Names are not types
function Name(identifier) { function Name(identifier) {
this.ident = identifier; this.ident = identifier;
this.val = this.ident; this.val = this.ident;
this.exprType = "Name"; this.exprType = "Name";
return this; return this;
} }
function Def(ident, exp) { function Def(ident, exp) {
this.ident = ident; this.ident = ident;
this.val = exp; this.val = exp;
this.exprType = "Definition"; this.exprType = "Definition";
return this; return this;
} }
function DefFunc(ident, params, body) { function DefFunc(ident, params, body) {
@ -164,55 +166,69 @@ function DefFunc(ident, params, body) {
} }
function If(condition, thenexp, elseexp) { function If(condition, thenexp, elseexp) {
this.condition = condition; this.condition = condition;
this.thenexp = thenexp; this.thenexp = thenexp;
this.elseexp = elseexp; this.elseexp = elseexp;
this.exprType = "If"; this.exprType = "If";
return this; return this;
} }
function TypeVar(name) { function TypeVar(name) {
this.exprtype = "TypeVar"; this.exprtype = "TypeVar";
this.name = name; this.name = name;
this.exprType = "TypeVar";
return this; return this;
} }
TypeVar.prototype = TypeExpression; TypeVar.prototype = TypeExpression;
function TypeOp(name, params, body) { function TypeOp(name) {
if (!_.every(params, _.compose(
_.partial(_.isEqual, "TypeVar"),
_.property("exprtype")))) {
throw errors.JInternalError(
"Parameters to a type operator must be type variables"
);
}
this.name = name; this.name = name;
this.params = params; this.val = name;
this.body = body; this.exprType = "TypeOperator";
return this; return this;
} }
function isTypeExpr(expr) {
if (!expr.exprType) {
throw errors.JInternalError(expr);
}
return ((expr.exprType === "TypeOperator") ||
(expr.exprType === "TypeVar") ||
(expr.exprType === "TypeApplication"));
}
TypeOp.prototype = TypeExpression; TypeOp.prototype = TypeExpression;
function TypeBinding(expression, type) { function TypeApp(expression, type) {
this.expr = expression; if (isTypeExpr(expression)) {
throw errors.JInternalError(
"Left-hand-side of type application must not be in the type language"
);
}
if (!isTypeExpr(type)) {
throw errors.JInternalError(
"Right-hand-side of type application must be a type expression"
);
}
this.expression = expression;
this.type = type; this.type = type;
this.exprType = "TypeApplication";
return this; return this;
} }
TypeBinding.prototype = TypeExpression; TypeApp.prototype = TypeExpression;
//Applies the function ``name'' to the list of parameters //Applies the function ``name'' to the list of parameters
function makeApp(name, parameters) { function makeApp(name, parameters) {
if (parameters) { if (parameters) {
return parameters.slice(1).reduce(function(f, ident) { return parameters.slice(1).reduce(function(f, ident) {
return new App(f, ident); return new App(f, ident);
}, new App(name, parameters[0])); }, new App(name, parameters[0]));
} }
else { else {
return new App(name); return new App(name);
} }
} }
function makeGensym() { function makeGensym() {
@ -246,7 +262,8 @@ OPInfo = {"+" : [3, "Left"],
">>=" : [1, "Left"], ">>=" : [1, "Left"],
"<$>" : [1, "Left"], "<$>" : [1, "Left"],
"." : [1, "Left"], "." : [1, "Left"],
"," : [1, "Left"]}; "," : [1, "Left"],
"->" : [1, "Right"]};
module.exports = module.exports =
{ {
@ -270,6 +287,6 @@ module.exports =
gensym : gensym, gensym : gensym,
TypeVar : TypeVar, TypeVar : TypeVar,
TypeOp : TypeOp, TypeOp : TypeOp,
TypeBinding : TypeBinding, TypeApp: TypeApp,
Closure : Closure Closure : Closure
}; };

Loading…
Cancel
Save