diff --git a/closure_conversion.js b/closure_conversion.js index 994ed67..4865aea 100644 --- a/closure_conversion.js +++ b/closure_conversion.js @@ -106,7 +106,7 @@ function closure_convert(stx) { return new rep.Closure(bound_vars, free_variables, stx, []); } -function closure_convert_all(stx, env) { +function closure_convert_all(stx) { var closure; switch (stx.exprType) { case "Let": @@ -151,8 +151,8 @@ function test(src) { console.log(JSON.stringify(closure_convert_all(ast), null, 4)); } -console.log(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(pprint.pprint(parser.parse("def main (print let { a = def {f = (lambda a b -> (a+b))} f} (a 2 3))")[0])); +//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(pprint.pprint(parser.parse("defop 1 Right (a $# b) (a - b) def main (4 $# b $# c)")[1])); module.export = { test : test, closureConvert : closure_convert_all diff --git a/desugar.js b/desugar.js index cf79a35..f640814 100644 --- a/desugar.js +++ b/desugar.js @@ -26,6 +26,7 @@ function desugarDefFunc(def) { def.body)); } + function curryFunc(ps, body) { if (_.isEmpty(ps)) { return desugar(body); @@ -55,6 +56,10 @@ function desugar(stx) { case "Name": return stx; case "Application": + if (stx.func.ident === "::") { + //It's a type binding + return desugarTypeBinding(stx); + } if ((stx.func.ident === "-" || stx.func.ident === "+") && stx.p) { diff --git a/representation.js b/representation.js index ebe8dd7..666e12f 100644 --- a/representation.js +++ b/representation.js @@ -1,3 +1,6 @@ +var errors = require("./errors.js"); +var _ = require("underscore"); + var Expression = { display : function() { @@ -6,18 +9,24 @@ var Expression = { type : function () { return this.exprType; - }, - unify : + } +}; + +var TypeExpression = { + unify : function (t) { - if (this.exprType === t.exprType) { - return t.exprType; + if (this.expr === t.expr) { + return t.expr; } else { - console.log("Could not unify " + this.exprType + " with " + t.exprType); + console.log("Could not unify " + this.expr + " with " + t.expr); } - } + }, + isTypeExpr : true }; +var isTypeExpr = _.property("isTypeExpr"); + function Closure(bound_vars, free_vars, body, env) { this.bound_vars = bound_vars; this.free_vars = free_vars; @@ -163,25 +172,37 @@ function If(condition, thenexp, elseexp) { } function TypeVar(name) { + this.exprtype = "TypeVar"; this.name = name; - this.exprType = "TypeVariable"; return this; } -function TypeOp(name) { +TypeVar.prototype = TypeExpression; + +function TypeOp(name, params, body) { + 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.val = name; - this.exprType = "TypeOperator" + this.params = params; + this.body = body; return this; } -//convenience function to construct binary operators -//assumes that the identifier refers to the name of a primitive -//operation -function makeBin(ident) { - return new OpT(new FuncT (new Name("a"), new FuncT(new Name("b"), new App(new App(ident, "a"), "b")))); +TypeOp.prototype = TypeExpression; + +function TypeBinding(expression, type) { + this.expr = expression; + this.type = type; + return this; } +TypeBinding.prototype = TypeExpression; + //Applies the function ``name'' to the list of parameters function makeApp(name, parameters) { if (parameters) { @@ -192,7 +213,6 @@ function makeApp(name, parameters) { else { return new App(name); } - } function makeGensym() { @@ -206,49 +226,50 @@ function makeGensym() { var gensym = makeGensym(); -OPInfo = {"+" : [4, "Left"], - "-" : [4, "Left"], - "*" : [5, "Left"], - "/" : [5, "Left"], - "^" : [6, "Right"], - "++" : [4, "Left"], - "==" : [3, "Left"], - ">" : [3, "Left"], - ">=" : [3, "Left"], - "<" : [3, "Left"], - "<=" : [3, "Left"], - "&&" : [3, "Left"], - "||" : [3, "Left"], - "::" : [1, "Left"], - ":" : [2, "Left"], - "$" : [2, "Left"], - ">>" : [2, "Left"], - ">>=" : [2, "Left"], - "<$>" : [2, "Left"], - "." : [2, "Left"], - "," : [2, "Left"], - "->" : [2, "Right"]} +OPInfo = {"+" : [3, "Left"], + "-" : [3, "Left"], + "*" : [4, "Left"], + "/" : [4, "Left"], + "^" : [5, "Right"], + "++" : [3, "Left"], + "==" : [2, "Left"], + ">" : [2, "Left"], + ">=" : [2, "Left"], + "<" : [2, "Left"], + "<=" : [2, "Left"], + "&&" : [2, "Left"], + "||" : [2, "Left"], + "::" : [2, "Left"], + ":" : [1, "Left"], + "$" : [1, "Left"], + ">>" : [1, "Left"], + ">>=" : [1, "Left"], + "<$>" : [1, "Left"], + "." : [1, "Left"], + "," : [1, "Left"]}; module.exports = - { IntT : IntT, - FloatT : FloatT, - StrT : StrT, - BoolT : BoolT, - ListT : ListT, - FuncT : FuncT, - App : App, - Name : Name, - Def : Def, - OpT : OpT, - OPInfo : OPInfo, - makeApp : makeApp, - If : If, - DefFunc : DefFunc, - UnaryOp : UnaryOp, - Nil : Nil, - LetExp : LetExp, - gensym : gensym, - TypeVar : TypeVar, - TypeOp : TypeOp, - Closure : Closure + { + IntT : IntT, + FloatT : FloatT, + StrT : StrT, + BoolT : BoolT, + ListT : ListT, + FuncT : FuncT, + App : App, + Name : Name, + Def : Def, + OpT : OpT, + OPInfo : OPInfo, + makeApp : makeApp, + If : If, + DefFunc : DefFunc, + UnaryOp : UnaryOp, + Nil : Nil, + LetExp : LetExp, + gensym : gensym, + TypeVar : TypeVar, + TypeOp : TypeOp, + TypeBinding : TypeBinding, + Closure : Closure }; diff --git a/treegen.js b/treegen.js deleted file mode 100644 index f85a2aa..0000000 --- a/treegen.js +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/node - -var parser = require("./parse.js"); -var pprint = require("./pprint.js"); -var repr = require("./representation.js"); -var lex = require("./tokenize.js"); - -var qc = require("quickcheck"); - -function arbIdentifier() { - var st = qc.arbString() - if (lex.isIdentifier(st)) { - return new repr.Name(st); - } - else { - return arbIdentifier(); - } -} - -console.log(arbIdentifier());