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: * A closure is a triple of:
* the bound variables in a function or let * the bound variables in a function or let
* the free 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 * 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 * are in the environment, or an exception is raised because the variable is not bound
* in the current environment. * in the current environment.
@ -12,6 +12,10 @@
* call the function with the environment associated with it. * 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 * 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. * 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"); var rep = require("./representation.js");
@ -102,7 +106,7 @@ function closure_convert(stx) {
return new rep.Closure(bound_vars, free_variables, stx, []); return new rep.Closure(bound_vars, free_variables, stx, []);
} }
function closure_convert_all(stx) { function closure_convert_all(stx, env) {
var closure; var closure;
switch (stx.exprType) { switch (stx.exprType) {
case "Let": case "Let":
@ -147,8 +151,8 @@ 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(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 = { module.export = {
test : test, test : test,
closureConvert : closure_convert_all closureConvert : closure_convert_all

36
parse.js

@ -553,27 +553,40 @@ function parse(tokens) {
} }
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 === "truelit" || toktype === "falselit") }
else if (toktype === "constructor") {
return new typ.TypeOp(token);
}
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();
@ -610,4 +623,5 @@ module.exports = { parse : function(str) {
return parseFull(tokenizer.tokenize(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) { function pprint(expr) {
if (expr.exprType === "Name") if (expr.exprType === "Name") {
return expr.val; 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"; return "True";
else }
else {
return "False"; return "False";
else if (expr.exprType === "Integer") }
}
else if (expr.exprType === "Integer") {
return "("+expr.val+")"; return "("+expr.val+")";
else if (expr.exprType === "Float") }
else if (expr.exprType === "Float") {
return "("+expr.val+")"; return "("+expr.val+")";
else if (expr.exprType === "String") }
else if (expr.exprType === "String") {
return '"'+expr.val+'"'; return '"'+expr.val+'"';
else if (expr.exprType === "Name") }
else if (expr.exprType === "Name") {
return expr.val; return expr.val;
else if (expr.exprType === "Application") }
else if (expr.exprType === "Application") {
return pprintApp(expr); return pprintApp(expr);
else if (expr.exprType === "Definition") }
else if (expr.exprType === "Definition") {
return pprintDef(expr); return pprintDef(expr);
else if (expr.exprType === "If") }
else if (expr.exprType === "If") {
return pprintIf(expr); return pprintIf(expr);
else if (expr.exprType === "Function") }
else if (expr.exprType === "Function") {
return pprintFunc(expr); return pprintFunc(expr);
else if (expr.exprType === "Nil") }
else if (expr.exprType === "Nil") {
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") }
else if (expr.exprType === "Let") {
return "let {" + expr.pairs.map( return "let {" + expr.pairs.map(
function (v) { function (v) {
return pprint(v); return pprint(v);
}).join(" ; ") + "} in " + pprint(expr.body); }).join(" ; ") + "} in " + pprint(expr.body);
}
} }
module.exports = {pprint : pprint}; module.exports = {pprint : pprint};

50
representation.js

@ -164,13 +164,14 @@ function If(condition, thenexp, elseexp) {
function TypeVar(name) { function TypeVar(name) {
this.name = name; this.name = name;
this.exprType = "TypeVariable";
return this; return this;
} }
function TypeOp(name, params, body) { function TypeOp(name) {
this.name = name; this.name = name;
this.params = params; this.val = name;
this.body = body; this.exprType = "TypeOperator"
return this; return this;
} }
@ -205,27 +206,28 @@ function makeGensym() {
var gensym = makeGensym(); var gensym = makeGensym();
OPInfo = {"+" : [3, "Left"], OPInfo = {"+" : [4, "Left"],
"-" : [3, "Left"], "-" : [4, "Left"],
"*" : [4, "Left"], "*" : [5, "Left"],
"/" : [4, "Left"], "/" : [5, "Left"],
"^" : [5, "Right"], "^" : [6, "Right"],
"++" : [3, "Left"], "++" : [4, "Left"],
"==" : [2, "Left"], "==" : [3, "Left"],
">" : [2, "Left"], ">" : [3, "Left"],
">=" : [2, "Left"], ">=" : [3, "Left"],
"<" : [2, "Left"], "<" : [3, "Left"],
"<=" : [2, "Left"], "<=" : [3, "Left"],
"&&" : [2, "Left"], "&&" : [3, "Left"],
"||" : [2, "Left"], "||" : [3, "Left"],
"::" : [2, "Left"], "::" : [1, "Left"],
":" : [1, "Left"], ":" : [2, "Left"],
"$" : [1, "Left"], "$" : [2, "Left"],
">>" : [1, "Left"], ">>" : [2, "Left"],
">>=" : [1, "Left"], ">>=" : [2, "Left"],
"<$>" : [1, "Left"], "<$>" : [2, "Left"],
"." : [1, "Left"], "." : [2, "Left"],
"," : [1, "Left"]}; "," : [2, "Left"],
"->" : [2, "Right"]}
module.exports = module.exports =
{ IntT : IntT, { IntT : IntT,

52
tokenize.js

@ -6,10 +6,10 @@ var error = require("./errors.js");
var operators = Object.keys(rep.OPInfo); var operators = Object.keys(rep.OPInfo);
var _ = require("underscore"); var _ = require("underscore");
function isDigit(a) { function isDigit(c) {
if (!a) if (!c)
return false; return false;
var code = a.charCodeAt(); var code = c.charCodeAt();
if (isNaN(code)) { if (isNaN(code)) {
return false; return false;
} }
@ -19,11 +19,11 @@ function isDigit(a) {
code > 46); code > 46);
} }
function isWhitespace(a) { function isWhitespace(c) {
if (!a) if (!c)
return true; return true;
var code = a.charCodeAt(); var code = c.charCodeAt();
if (isNaN(code)) { if (isNaN(code)) {
return false; return false;
} }
@ -34,8 +34,8 @@ function isWhitespace(a) {
code === 11); code === 11);
} }
function isIdentifier(a) { function isIdentifier(c) {
var code = a.charCodeAt(); var code = c.charCodeAt();
return (!isNaN(code) && return (!isNaN(code) &&
code !== 41 && code !== 41 &&
code !== 40 && code !== 40 &&
@ -46,6 +46,13 @@ function isIdentifier(a) {
code !== 44); code !== 44);
} }
function isUpper(c) {
var code = c.charCodeAt();
return (!isNaN(code) &&
(code >= 65) &&
(code <= 90));
}
function tokenizeNum(tokstream, charnum, linenum) { function tokenizeNum(tokstream, charnum, linenum) {
var number = []; var number = [];
var code = tokstream[0].charCodeAt(); 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 * 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 identifier = [];
var n = 0; var n = 0;
while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) { 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]]]; 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) { function tokenizeStr(tokstream, charnum, linenum) {
var stringlit = []; var stringlit = [];
var n = 1; var n = 1;
@ -232,9 +254,9 @@ function tokenize(tokstream, matchop) {
break; break;
/* falls through */ /* falls through */
case 45: // '-' /*case 45: // '-'
lambda = peek(tokstream, "arrow", "->"); lambda = peek(tokstream, "arrow", "->");
if (lambda) { if (false) {
tokens.push($.extend(lambda, [charnum, linenum])); tokens.push($.extend(lambda, [charnum, linenum]));
tokstream = tokstream.substr(2); tokstream = tokstream.substr(2);
break; break;
@ -346,7 +368,12 @@ function tokenize(tokstream, matchop) {
tokens.push(["identifier", op, charnum, linenum]); tokens.push(["identifier", op, charnum, linenum]);
} }
else { 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++) { for(var index = 0; index < result.length; index++) {
charnum++; charnum++;
tokens.push(result[index][1]); tokens.push(result[index][1]);
@ -396,5 +423,6 @@ function tokenizeFull(input) {
return tokenizeHelp(input, matchop, true); return tokenizeHelp(input, matchop, true);
} }
module.exports = {tokenize : tokenizeFull, module.exports = {tokenize : tokenizeFull,
isIdentifier : isIdentifier}; 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) { function groupOps(ops) {
return _.groupBy(ops.sort(), _.isEqual); return _.groupBy(ops.sort(), _.isEqual);
} }
@ -56,7 +68,8 @@ function operatorMatch(ops) {
function (op) { function (op) {
return op.length > 0; return op.length > 0;
}); });
var rstring = ops.sort(min).reduce( ops.sort(min);
var rstring = ops.reduce(
function(acc, x) { function(acc, x) {
if (!x || x.length < 1) { if (!x || x.length < 1) {
return ""; return "";

Loading…
Cancel
Save