Skip to content

Commit

Permalink
Adding type inference for variable lookups and doing some cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Mattis Jeppsson committed Apr 19, 2010
1 parent 2ae9fd5 commit 09e5995
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 112 deletions.
171 changes: 93 additions & 78 deletions haskell.typechecker.js
@@ -1,31 +1,15 @@
(function (typechecker, ast) { (function (typechecker, ast) {
var astt = new ast.Module([
new ast.Variable(new ast.VariableBinding("inc"),
new ast.Lambda(new ast.VariableBinding("x"),
new ast.Application(new ast.Application(new ast.VariableLookup("+"),
new ast.VariableLookup("x")),
new ast.Constant(new ast.Num(1))))),
new ast.Variable(new ast.VariableBinding("inc2"),
new ast.Lambda(new ast.VariableBinding("x"),
new ast.Application(new ast.VariableLookup("inc"),
new ast.Application(new ast.VariableLookup("inc"),
new ast.VariableLookup("x"))))),
new ast.Variable(new ast.VariableBinding("main"),
new ast.Application(new ast.VariableLookup("alert"),
new ast.Application(new ast.VariableLookup("inc2"),
new ast.Constant(new ast.Num(2)))))
]);
var asttt = new ast.Application(new ast.Application(new ast.VariableLookup("+"),
new ast.VariableLookup("x")),
new ast.Constant(new ast.Num(1))); // ((x + :: (Num -> Num)) 1 :: Num)
// asttt = new ast.Constant(new ast.Num(1));

ast.Num.prototype.infer = function(env) { ast.Num.prototype.infer = function(env) {
return new typechecker.Pred( return new typechecker.Pred(
"Num", "Num",
new typechecker.TVar("a1", new typechecker.Star())); env.newTVar(new typechecker.Star(), env));
}; };


ast.VariableLookup.prototype.infer = function(env) {
if(env[this.identifier] != undefined) {
return new typechecker.Pred("Num", new typechecker.TVar("a3", new typechecker.Star()));
}
};


/* /*
* data Kind = Star | Kfun Kind Kind * data Kind = Star | Kfun Kind Kind
Expand All @@ -34,26 +18,16 @@
*/ */
typechecker.Star = function() { typechecker.Star = function() {
this.toString = function() { return "*"; }; this.toString = function() { return "*"; };
this.toStringNested = this.toString;
}; };
typechecker.Kfun = function(kind1, kind2) { typechecker.Kfun = function(kind1, kind2) {
this.kind1 = kind1; this.kind1 = kind1;
this.kind2 = kind2; this.kind2 = kind2;
this.toString = function() { return kind1.toString() + "->" + kind2.toString(); }; this.toString = function() {
}; return kind1.toStringNested() + "->" + kind2.toStringNested();

};
/* this.toStringNested = function() {
* data Tyvar = Tyvar Id Kind return "(" + this.toString() + ")"; };
* deriving Eq
*
*/
typechecker.Tyvar = function(id, kind) {
this.id = function () { return id; };
this.kind = function() { return kind; };
};

typechecker.Tycon = function(id, kind) {
this.id = function() { return id; };
this.kind = function() { return kind; };
}; };


/* /*
Expand All @@ -67,7 +41,6 @@
}; };
this.id = function () { return id; }; this.id = function () { return id; };
this.kind = function() { return kind; }; this.kind = function() { return kind; };
// this.kind = function() { return tyvar.kind(); };
this.apply = function(subst) { this.apply = function(subst) {
if (subst[this] != undefined) { if (subst[this] != undefined) {
return subst[this]; return subst[this];
Expand All @@ -76,25 +49,36 @@
}; };
this.tv = function() { return [tyvar]; }; this.tv = function() { return [tyvar]; };
}; };

/*
typechecker.newTVar = function(kind, env) {
return new typechecker.TVar(env.nextName(), kind);
};
*/

typechecker.TCon = function(id, kind) { typechecker.TCon = function(id, kind) {
this.id = function() { return id; }; this.id = function() { return id; };
this.kind = function() { return kind; }; this.kind = function() { return kind; };
// this.kind = function() { return tycon.kind(); };
this.apply = function(subst) { return this; }; this.apply = function(subst) { return this; };
this.tv = function() { return []; }; this.tv = function() { return []; };
}; };

typechecker.TAp = function(t1, t2) { typechecker.TAp = function(t1, t2) {
this.kind = function() { return t1.kind().kind2; }; this.kind = function() { return t1.kind().kind2; };
this.apply = function(subst) { return new typechecker.TAp(t1.apply(),t2.apply()); }; this.apply = function(subst) {
this.tv = function() { return [].concat(t1.tv()).concat(t2.tv()).unique(); }; return new typechecker.TAp(t1.apply(),t2.apply());
};
this.tv = function() {
return [].concat(t1.tv()).concat(t2.tv()).unique();
};
}; };
typechecker.TGen = function(id) { typechecker.TGen = function(id) {
// this.kind = function() { }; - should probably throw an exception
this.id = function() { return id; }; this.id = function() { return id; };
this.apply = function(subst) { return this; }; this.apply = function(subst) { return this; };
this.tv = function() { return []; }; this.tv = function() { return []; };
};


};
/*
typechecker.Class = function(ids, insts) { typechecker.Class = function(ids, insts) {
this.ids = function() { return ids; }; this.ids = function() { return ids; };
this.insts = function() { return insts; }; this.insts = function() { return insts; };
Expand All @@ -103,9 +87,10 @@
typechecker.Inst = function() { typechecker.Inst = function() {
}; };
*/


typechecker.Qual = function(pred, t) { typechecker.Qual = function(preds, t) {
this.pred = function() { return pred; }; this.pred = function() { return preds; };
this.t = function() { return t; }; this.t = function() { return t; };
}; };


Expand All @@ -115,16 +100,21 @@
this.toString = function() { this.toString = function() {
return this.class().toString() + return this.class().toString() +
" " + " " +
this.type().id() + this.type().id();
" => " + this.type().toString();
}; };
}; };


typechecker.Scheme = function(kinds, qual) { typechecker.Scheme = function(kinds, qual) {
this.kinds = function() { return kinds; }; this.kinds = function() { return kinds; };
this.qual = function() { return qual; }; this.qual = function() { return qual; };
this.freshInst = function() {};
};

typechecker.toScheme = function(type) {
return new typechecker.Scheme([], new typechecker.Qual([], type));
}; };


/*
typechecker.ClassEnv = function(classes, defaults) { typechecker.ClassEnv = function(classes, defaults) {
this.classes = function() { return classes; }; this.classes = function() { return classes; };
this.defaults = function() { return defaults; }; this.defaults = function() { return defaults; };
Expand All @@ -135,44 +125,43 @@
return this.classes(id).insts(); return this.classes(id).insts();
}; };
}; };
*/


/* /*
* Some built-in types * Some built-in types
* *
*/ */
/* typechecker.tUnit
typechecker.tUnit = new typechecker.TCon( = new typechecker.TCon("()", new typechecker.Star());
new typechecker.Tycon("()", new typechecker.Star())); typechecker.tChar
typechecker.tChar = new typechecker.TCon( = new typechecker.TCon("Char", new typechecker.Star());
new typechecker.Tycon("Char", new typechecker.Star())); typechecker.tInt
typechecker.tInt = new typechecker.TCon( = new typechecker.TCon("Int", new typechecker.Star());
new typechecker.Tycon("Int", new typechecker.Star())); typechecker.tInteger
typechecker.tInteger = new typechecker.TCon( = new typechecker.TCon("Integer", new typechecker.Star());
new typechecker.Tycon("Integer", new typechecker.Star())); typechecker.tFloat
typechecker.tFloat = new typechecker.TCon( = new typechecker.TCon("Float", new typechecker.Star());
new typechecker.Tycon("Float", new typechecker.Star())); typechecker.tDouble
typechecker.tDouble = new typechecker.TCon( = new typechecker.TCon("Double", new typechecker.Star());
new typechecker.Tycon("Double", new typechecker.Star()));


typechecker.tList = new typechecker.TCon( typechecker.tList = new typechecker.TCon(
new typechecker.Tycon("[]", "[]",
new typechecker.Kfun(new typechecker.Star(), new typechecker.Kfun(new typechecker.Star(),
new typechecker.Star()))); new typechecker.Star()));
typechecker.tArrow = new typechecker.TCon( typechecker.tArrow = new typechecker.TCon(
new typechecker.Tycon("(->)", "(->)",
new typechecker.Kfun( new typechecker.Kfun(
new typechecker.Star(), new typechecker.Star(),
new typechecker.Kfun( new typechecker.Kfun(
new typechecker.Star(), new typechecker.Star(),
new typechecker.Star())))); new typechecker.Star())));
typechecker.tTuple2 = new typechecker.TCon( typechecker.tTuple2 = new typechecker.TCon(
new typechecker.Tycon ("(,)", "(,)",
new typechecker.Kfun( new typechecker.Kfun(
new typechecker.Star(), new typechecker.Star(),
new typechecker.Kfun( new typechecker.Kfun(
new typechecker.Star(), new typechecker.Star(),
new typechecker.Star())))); new typechecker.Star())));
*/
/* /*
* Substitutions * Substitutions
* *
Expand All @@ -181,6 +170,7 @@
* We use a map (JavaScript Object) instead * We use a map (JavaScript Object) instead
* *
*/ */
/*
typechecker.nullSubst = {}; typechecker.nullSubst = {};
typechecker.singleSubst = function(u,t) { return {u: t}; }; typechecker.singleSubst = function(u,t) { return {u: t}; };
typechecker.composeSubst = function(s1, s2) { typechecker.composeSubst = function(s1, s2) {
Expand All @@ -193,7 +183,32 @@
} }
return s3; return s3;
}; };
*/



typechecker.NameGen = function(startAt) {
this.next = function(env) {
while(env["a" + startAt] != undefined) {
startAt++;
}
return "a" + startAt;
};
};

typechecker.Environment = function(init) {
if(init != undefined) {
for(i in init) {
this[i]=init[i];
}
}
var gen = new typechecker.NameGen(1);
this.nextName = function() { return gen.next(this); };
this.newTVar = function (kind) {
return new typechecker.TVar(this.nextName(), kind);
};
};

typechecker.emptyEnv = function() {
return new typechecker.Environment();
};


}) (haskell.typechecker, haskell.ast); }) (haskell.typechecker, haskell.ast);

0 comments on commit 09e5995

Please sign in to comment.