Browse Source

work on parsing type applications/signatures

pull/3/head
nisstyre56 11 years ago
parent
commit
b18d0a1eca
  1. 12
      closure_conversion.js
  2. 36
      parse.js
  3. 48
      pprint.js
  4. 50
      representation.js
  5. 52
      tokenize.js
  6. 15
      tools.js

12
closure_conversion.js

@ -2,7 +2,7 @@
* A closure is a triple of:
* the bound variables in a function or let
* the free variables in a function or let
* a function body or let body and bound values
* a function body or let body and bound values (if it is an escaping closure only)
* The closure has the property that all of the free variables of the function or let
* are in the environment, or an exception is raised because the variable is not bound
* in the current environment.
@ -12,6 +12,10 @@
* call the function with the environment associated with it.
* For the purposes of type checking it does not matter how the function gets called, the environment
* is only used for looking up the types of names. Formal parameters are given type variables.
*
* The first phase of closure conversion is not really closure conversion exactly.
* All it does is find out the free variables in scope and tie those up into a data structure with their types later.
* The second phase will be done to the CPS language and closures will actually lambda-lifted out potentially.
*/
var rep = require("./representation.js");
@ -102,7 +106,7 @@ function closure_convert(stx) {
return new rep.Closure(bound_vars, free_variables, stx, []);
}
function closure_convert_all(stx) {
function closure_convert_all(stx, env) {
var closure;
switch (stx.exprType) {
case "Let":
@ -147,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(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("def main (print let { a = def {f = (lambda a b -> (a+b))} f} (a 2 3))")[0]));
module.export = {
test : test,
closureConvert : closure_convert_all

36
parse.js

@ -553,27 +553,40 @@ function parse(tokens) {
}
var token = fst(tokens)[1];
tokens.pop();
if (toktype === "stringlit")
if (toktype === "stringlit") {
return new typ.StrT(token);
else if (toktype === "left_square")
}
else if (toktype === "left_square") {
return parseList(tokens);
else if (toktype === "lambda")
}
else if (toktype === "lambda") {
return parseLambda(tokens);
else if (toktype === "integer")
}
else if (toktype === "integer") {
return new typ.IntT(token);
else if (toktype === "float")
}
else if (toktype === "float") {
return new typ.FloatT(token);
else if (toktype === "identifier")
}
else if (toktype === "identifier") {
return new typ.Name(token);
else if (toktype === "truelit" || toktype === "falselit")
}
else if (toktype === "constructor") {
return new typ.TypeOp(token);
}
else if (toktype === "truelit" || toktype === "falselit") {
return new typ.BoolT(token);
}
else if (toktype === "def" ||
toktype === "let")
toktype === "let") {
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]);
else if (toktype === "ifexp")
}
else if (toktype === "ifexp") {
return parseIf(tokens);
}
else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") {
tokens.pop();
@ -610,4 +623,5 @@ module.exports = { parse : function(str) {
return parseFull(tokenizer.tokenize(str));
}
};
//var istr = fs.readFileSync('/dev/stdin').toString();
/*var istr = fs.readFileSync('/dev/stdin').toString();
console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint));*/

48
pprint.js

@ -27,38 +27,56 @@ function pprintIf(ifexp) {
}
function pprint(expr) {
if (expr.exprType === "Name")
if (expr.exprType === "Name") {
return expr.val;
else if (expr.exprType === "Bool")
if (expr.val)
}
else if (expr.exprType === "TypeOperator") {
return expr.val;
}
else if (expr.exprType === "Bool") {
if (expr.val) {
return "True";
else
}
else {
return "False";
else if (expr.exprType === "Integer")
}
}
else if (expr.exprType === "Integer") {
return "("+expr.val+")";
else if (expr.exprType === "Float")
}
else if (expr.exprType === "Float") {
return "("+expr.val+")";
else if (expr.exprType === "String")
}
else if (expr.exprType === "String") {
return '"'+expr.val+'"';
else if (expr.exprType === "Name")
}
else if (expr.exprType === "Name") {
return expr.val;
else if (expr.exprType === "Application")
}
else if (expr.exprType === "Application") {
return pprintApp(expr);
else if (expr.exprType === "Definition")
}
else if (expr.exprType === "Definition") {
return pprintDef(expr);
else if (expr.exprType === "If")
}
else if (expr.exprType === "If") {
return pprintIf(expr);
else if (expr.exprType === "Function")
}
else if (expr.exprType === "Function") {
return pprintFunc(expr);
else if (expr.exprType === "Nil")
}
else if (expr.exprType === "Nil") {
return "[]";
else if (expr.exprType === "Unary")
}
else if (expr.exprType === "Unary") {
return "("+expr.op.ident+" "+pprint(expr.val)+")";
else if (expr.exprType === "Let")
}
else if (expr.exprType === "Let") {
return "let {" + expr.pairs.map(
function (v) {
return pprint(v);
}).join(" ; ") + "} in " + pprint(expr.body);
}
}
module.exports = {pprint : pprint};

50
representation.js

@ -164,13 +164,14 @@ function If(condition, thenexp, elseexp) {
function TypeVar(name) {
this.name = name;
this.exprType = "TypeVariable";
return this;
}
function TypeOp(name, params, body) {
function TypeOp(name) {
this.name = name;
this.params = params;
this.body = body;
this.val = name;
this.exprType = "TypeOperator"
return this;
}
@ -205,27 +206,28 @@ function makeGensym() {
var gensym = makeGensym();
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"]};
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"]}
module.exports =
{ IntT : IntT,

52
tokenize.js

@ -6,10 +6,10 @@ var error = require("./errors.js");
var operators = Object.keys(rep.OPInfo);
var _ = require("underscore");
function isDigit(a) {
if (!a)
function isDigit(c) {
if (!c)
return false;
var code = a.charCodeAt();
var code = c.charCodeAt();
if (isNaN(code)) {
return false;
}
@ -19,11 +19,11 @@ function isDigit(a) {
code > 46);
}
function isWhitespace(a) {
if (!a)
function isWhitespace(c) {
if (!c)
return true;
var code = a.charCodeAt();
var code = c.charCodeAt();
if (isNaN(code)) {
return false;
}
@ -34,8 +34,8 @@ function isWhitespace(a) {
code === 11);
}
function isIdentifier(a) {
var code = a.charCodeAt();
function isIdentifier(c) {
var code = c.charCodeAt();
return (!isNaN(code) &&
code !== 41 &&
code !== 40 &&
@ -46,6 +46,13 @@ function isIdentifier(a) {
code !== 44);
}
function isUpper(c) {
var code = c.charCodeAt();
return (!isNaN(code) &&
(code >= 65) &&
(code <= 90));
}
function tokenizeNum(tokstream, charnum, linenum) {
var number = [];
var code = tokstream[0].charCodeAt();
@ -99,7 +106,10 @@ function tokenizeNum(tokstream, charnum, linenum) {
* Everything after the operator goes back on to the token stream
*/
function tokenizeIdent(tokstream, matchop, charnum, linenum) {
function tokenizeIdent(tokstream,
matchop,
charnum,
linenum) {
var identifier = [];
var n = 0;
while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) {
@ -113,6 +123,18 @@ function tokenizeIdent(tokstream, matchop, charnum, linenum) {
return [[n, ["identifier", identifier, charnum, linenum]]];
}
function tokenizeCtor(tokstream,
matchop,
charnum,
linenum) {
var ident = tokenizeIdent(tokstream,
matchop,
charnum,
linenum);
ident[0][1][0] = "constructor";
return ident;
}
function tokenizeStr(tokstream, charnum, linenum) {
var stringlit = [];
var n = 1;
@ -232,9 +254,9 @@ function tokenize(tokstream, matchop) {
break;
/* falls through */
case 45: // '-'
/*case 45: // '-'
lambda = peek(tokstream, "arrow", "->");
if (lambda) {
if (false) {
tokens.push($.extend(lambda, [charnum, linenum]));
tokstream = tokstream.substr(2);
break;
@ -346,7 +368,12 @@ function tokenize(tokstream, matchop) {
tokens.push(["identifier", op, charnum, linenum]);
}
else {
result = tokenizeIdent(tokstream, matchop, charnum, linenum);
if (isUpper(tokstream[0])) {
result = tokenizeCtor(tokstream, matchop, charnum, linenum);
}
else {
result = tokenizeIdent(tokstream, matchop, charnum, linenum);
}
for(var index = 0; index < result.length; index++) {
charnum++;
tokens.push(result[index][1]);
@ -396,5 +423,6 @@ function tokenizeFull(input) {
return tokenizeHelp(input, matchop, true);
}
module.exports = {tokenize : tokenizeFull,
isIdentifier : isIdentifier};

15
tools.js

@ -20,6 +20,18 @@ function min(a, b) {
}
}
function max(a, b) {
if (a > b) {
return 1;
}
else if (a < b) {
return -1;
}
else {
return 0;
}
}
function groupOps(ops) {
return _.groupBy(ops.sort(), _.isEqual);
}
@ -56,7 +68,8 @@ function operatorMatch(ops) {
function (op) {
return op.length > 0;
});
var rstring = ops.sort(min).reduce(
ops.sort(min);
var rstring = ops.reduce(
function(acc, x) {
if (!x || x.length < 1) {
return "";

Loading…
Cancel
Save