Browse Source

switching to underscore.js for most functionality

pull/1/head
nisstyre56 11 years ago
parent
commit
13201d8662
  1. 44
      closure_conversion.js
  2. 8
      desugar.js
  3. 20
      parse.js
  4. 8
      patterns.js
  5. 3
      representation.js
  6. 22
      tokenize.js
  7. 172
      tools.js

44
closure_conversion.js

@ -20,8 +20,9 @@ var errors = require("./errors.js");
var parser = require("./parse.js"); var parser = require("./parse.js");
var pprint = require("./pprint.js"); var pprint = require("./pprint.js");
var $ = require("./tools.js"); var $ = require("./tools.js");
var _ = require("underscore");
var notEmpty = $.compose($.not, $.eq([])); var notEmpty = _.compose($.not, _.partial(_.equal, []));
function fvs(stx) { function fvs(stx) {
switch (stx.exprType) { switch (stx.exprType) {
@ -40,22 +41,22 @@ function fvs(stx) {
case "Let": case "Let":
return []; return [];
case "Unary": case "Unary":
return $.flatten([stx.op.ident, fvs(stx.val)]); return _.flatten([stx.op.ident, fvs(stx.val)]);
case "Definition": case "Definition":
return $.flatten(fvs(stx.val)); return _.flatten(fvs(stx.val));
case "Application": case "Application":
var vs = $.flatten(fvs(stx.p)); var vs = _.flatten(fvs(stx.p));
var f_fvs = $.flatten(fvs(stx.func)); var f_fvs = _.flatten(fvs(stx.func));
return $.flatten([vs, f_fvs]); return _.flatten([vs, f_fvs]);
case "If": case "If":
if (stx.elseexp) { if (stx.elseexp) {
var cond_fvs = fvs(stx.condition); var cond_fvs = fvs(stx.condition);
var then_fvs = fvs(stx.thenexp); var then_fvs = fvs(stx.thenexp);
var else_fvs = fvs(stx.elseexp); var else_fvs = fvs(stx.elseexp);
return $.flatten([cond_fvs, then_fvs, else_fvs]); return _.flatten([cond_fvs, then_fvs, else_fvs]);
} }
else { else {
return $.flatten([fvs(stx.condition), fvs(stx.thenexp)]); return _.flatten([fvs(stx.condition), fvs(stx.thenexp)]);
} }
break; break;
case "Name": case "Name":
@ -89,15 +90,15 @@ function closure_convert(stx) {
}); });
var let_fvs = stx.pairs.map(fvs); var let_fvs = stx.pairs.map(fvs);
var body_fvs = fvs(stx.body); var body_fvs = fvs(stx.body);
variables = $.flatten(let_fvs); variables = _.flatten(let_fvs);
$.extend(variables, $.flatten(body_fvs)); $.extend(variables, _.flatten(body_fvs));
break; break;
case "Function": case "Function":
bound_vars = [stx.p.ident,]; bound_vars = [stx.p.ident,];
variables = fvs(stx.body); variables = fvs(stx.body);
break; break;
} }
free_variables = $.difference($.unique(variables), bound_vars); free_variables = _.difference(_.uniq(variables), bound_vars);
return new rep.Closure(bound_vars, free_variables, stx, []); return new rep.Closure(bound_vars, free_variables, stx, []);
} }
@ -141,15 +142,14 @@ function closure_convert_all(stx) {
} }
//var ast = parser.parse("let { c = trtr a = let {tttt = (rtertret^yyyy) } let { dfsdf = let { asdsd = 3434 } gdfgdfg } (45+(asdddy*uyuy)) q = ((lambda x y -> (x+y)) 4 ui) } (^ wat (a+(ar*b*c^twerp+\"sdfdsfsdfsdfsdf\")*rtcccc))")[0]; function test(src) {
//var ast = parser.parse("let { a = let { b = let {dsdfgf = sddd } fdgfg } gggggg } t")[0]; var ast = parser.parse(src)[0];
//console.log(pprint.pprint(ast));
//var ast = parser.parse("let { a = 12 b = (a + t) } (a + b * d)")[0];
//console.log(fvs(ast));
//var ast = parser.parse("((lambda a b c -> (+ a b c)) 2 3.0 4)");
//var ast = parser.parse("def (f a b c) 12")[0];
//console.log(JSON.stringify(ast, null, 4));
//console.log(pprint.pprint(ast));
var ast = parser.parse("(lambda a -> if true then ((lambda b -> (+ a b)) q))")[0];
console.log(JSON.stringify(closure_convert_all(ast), null, 4)); console.log(JSON.stringify(closure_convert_all(ast), null, 4));
//console.log(pprint.pprint(ast)); }
test("(lambda a -> (+ a b c))");
module.export = {
test : test,
closureConvert : closure_convert_all
};

8
desugar.js

@ -5,7 +5,7 @@
*/ */
var typ = require("./representation.js"); var typ = require("./representation.js");
var $ = require("./tools.js"); var _ = require("underscore");
// Lists get desugared to nested function calls // Lists get desugared to nested function calls
// i.e. (cons (cons (cons ...))) // i.e. (cons (cons (cons ...)))
@ -27,12 +27,12 @@ function desugarDefFunc(def) {
} }
function curryFunc(ps, body) { function curryFunc(ps, body) {
if ($.empty(ps)) { if (_.isEmpty(ps)) {
return desugar(body); return desugar(body);
} }
else { else {
return new typ.FuncT(desugar($.fst(ps)), return new typ.FuncT(desugar(_.first(ps)),
curryFunc($.rst(ps), body)); curryFunc(_.rest(ps), body));
} }
} }

20
parse.js

@ -2,7 +2,8 @@
var fs = require("fs"); var fs = require("fs");
var typ = require("./representation.js"); var typ = require("./representation.js");
var tool = require("./tools.js"); var $ = require("./tools.js");
var _ = require("underscore");
var tokenizer = require("./tokenize.js"); var tokenizer = require("./tokenize.js");
var desugarer = require("./desugar.js"); var desugarer = require("./desugar.js");
var pprint = require("./pprint.js"); var pprint = require("./pprint.js");
@ -166,7 +167,7 @@ function parseDefFunction(tokens) {
} }
validLet = makeChecker(["Definition", "FunctionDefinition"]); validLet = makeChecker(["Definition", "FunctionDefinition"]);
letEnd = tool.compose(tool.not, makeChecker(["right_brace"])); letEnd = _.compose($.not, makeChecker(["right_brace"]));
function parseLetForm(tokens, linenum, charnum) { function parseLetForm(tokens, linenum, charnum) {
if (!fst(tokens)) { if (!fst(tokens)) {
@ -444,8 +445,8 @@ function parseLambda(tokens) {
} }
var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"]; var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"];
var validArgument = tool.compose(tool.not, makeChecker(invalidArguments)); var validArgument = _.compose($.not, makeChecker(invalidArguments));
var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"])); var validArgTypes = _.compose($.not, makeChecker(["Definition"]));
var validOperator = makeChecker(["identifier"]); var validOperator = makeChecker(["identifier"]);
/* Parses function application (either infix or prefix) */ /* Parses function application (either infix or prefix) */
@ -576,7 +577,7 @@ function parse(tokens) {
} }
} }
var istr = fs.readFileSync('/dev/stdin').toString();
function parseFull(tokenized) { function parseFull(tokenized) {
var ast = []; var ast = [];
try { try {
@ -595,11 +596,4 @@ module.exports = { parse : function(str) {
return parseFull(tokenizer.tokenize(str)); return parseFull(tokenizer.tokenize(str));
} }
}; };
//var istr = fs.readFileSync('/dev/stdin').toString();
console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint).join("\n"));
//console.log(tokenizer.tokenize(istr));
//console.log(parseFull(tokenizer.tokenize(istr)));
//module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) };

8
patterns.js

@ -0,0 +1,8 @@
/* Lightweight pattern matching for lists of strings
*
*/
var $ = require("./tools.js");

3
representation.js

@ -1,5 +1,3 @@
var tool = require("./tools.js");
var Expression = { var Expression = {
display : display :
function() { function() {
@ -25,6 +23,7 @@ function Closure(bound_vars, free_vars, body, env) {
this.free_vars = free_vars; this.free_vars = free_vars;
this.body = body; this.body = body;
this.env = env; this.env = env;
this.exprType = "Closure";
return this; return this;
} }

22
tokenize.js

@ -1,9 +1,10 @@
#! /usr/bin/node #! /usr/bin/node
var rep = require("./representation.js"); var rep = require("./representation.js");
var tools = require("./tools.js"); var $ = require("./tools.js");
var error = require("./errors.js"); var error = require("./errors.js");
var operators = Object.keys(rep.OPInfo); var operators = Object.keys(rep.OPInfo);
var _ = require("underscore");
function isDigit(a) { function isDigit(a) {
if (!a) if (!a)
@ -337,25 +338,31 @@ function tokenize(tokstream, matchop) {
return tokens; return tokens;
} }
function tokenizeHelp(input, matchop) { function tokenizeHelp(input, matchop, strip_whitespace) {
try { try {
return tokenize(input, matchop).reverse().filter(function(x) { return tokenize(input, matchop).reverse().filter(function(x) {
if (strip_whitespace) {
return x[0] !== "whitespace"; return x[0] !== "whitespace";
}
else {
return true;
}
}); });
} catch (e) { } catch (e) {
console.log(e.stxerror()); console.log(e.stxerror());
process.exit(1); process.exit(1);
} }
} }
var defop_pattern = ["defop", "integer", "identifier", var defop_pattern = ["defop", "integer", "identifier",
"left_paren", "identifier", "left_paren", "identifier",
"identifier", "identifier", "right_paren"]; "identifier", "identifier", "right_paren"];
function tokenizeFull(input) { function tokenizeFull(input) {
var matchop = tools.opMatch(operators); var matchop = $.opMatch(operators);
var initialPass = tokenizeHelp(input, matchop).reverse(); var initialPass = tokenizeHelp(input, _.constant(false), true).reverse();
for (var i = 0; i < initialPass.length; i++) { for (var i = 0; i < initialPass.length; i++) {
if (initialPass.slice(i, i+8).map(tools.fst).every( if (initialPass.slice(i, i+8).map(_.first).every(
function(x, i) { function(x, i) {
return x === defop_pattern[i]; return x === defop_pattern[i];
})) { })) {
@ -365,9 +372,8 @@ function tokenizeFull(input) {
} }
operators = Object.keys(rep.OPInfo); operators = Object.keys(rep.OPInfo);
matchop = tools.opMatch(operators); matchop = $.opMatch(operators);
return tokenizeHelp(input, matchop); return tokenizeHelp(input, matchop, true);
} }
module.exports = {tokenize : tokenizeFull}; module.exports = {tokenize : tokenizeFull};

172
tools.js

@ -1,132 +1,35 @@
function empty(xs) { var _ = require("underscore");
return xs.length === 0;
}
function identity(a) {
return a;
}
function compose(f, g) { function empty(xs) {
return function(x) { return _.size(xs) < 1;
return f(g(x));
};
} }
function not(x) { function not(x) {
return !x; return !x;
} }
function on(g, f) {
return function(x,y) {
return g(f(x), f(y));
};
}
function maxf(f, a, b) {
if (f(a) >= f(b))
return a;
return b;
}
function max(a, b) {
if (a > b)
return 1;
else if (a < b)
return -1;
else
return 0;
}
function min(a, b) { function min(a, b) {
if (a < b) if (a < b) {
return 1; return 1;
else if (a > b)
return -1;
else
return 0;
}
function maxBy(f, xs) {
if (xs.length < 1)
return false;
return xs.reduce(function(maxval, a) { return maxf(f, maxval, a); });
}
function sortBy(f, xs) {
return xs.sort(f);
}
function len(xs) {
return xs.length;
}
function takeWhile(f, xs) {
var result = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i]))
result.push(xs[i]);
else
break;
}
return result;
}
function dropWhile(f, xs) {
for (i = 0; i < xs.length; i++) {
if (!f(xs[i]))
break;
} }
return xs.slice(i); else if (a > b) {
} return -1;
function span(f, xs) {
return [takeWhile(f, xs), dropWhile(f, xs)];
}
function eq(a) {
return function(b) {
return a[0] === b[0];
};
}
function fst(xs) {
return xs[0];
}
function rst(xs) {
return xs.slice(1,xs.length);
}
function equal(a) {
return function(b) {
return a === b;
};
} }
else {
function groupBy(eq, xs) { return 0;
var groups = [];
var spanned;
while (xs.length > 0) {
spanned = span(eq(xs[0]), xs.slice(1));
groups.push([xs[0]].concat(spanned[0]));
xs = spanned[1];
} }
return groups;
} }
function groupOps(ops) { function groupOps(ops) {
return groupBy(function (x) { return function(y) { return x === y; };}, ops.sort()); return _.groupBy(ops.sort(), _.isEqual);
}
function unique(ops) {
return groupOps(ops).map(fst);
} }
function find(f, haystack) { function find(f, haystack) {
for(var i = 0; i < haystack.length; i++) { for(var i = 0; i < haystack.length; i++) {
if (f(haystack[i])) if (f(haystack[i])) {
return i; return i;
} }
}
return false; return false;
} }
@ -139,10 +42,14 @@ function dict(pairs) {
} }
function flatten(xs) { function flatten(xs) {
if (!(xs instanceof Array)) if (!(xs instanceof Array)) {
return xs; return xs;
if (xs.every(function (x) { return !(x instanceof Array); })) }
if (xs.every(function (x) {
return !(x instanceof Array);
})) {
return xs; return xs;
}
return [].concat.apply([], xs); return [].concat.apply([], xs);
} }
@ -151,21 +58,6 @@ function extend(xs, ys) {
return xs; return xs;
} }
function difference(xs, ys) {
var difflist = groupOps(extend(xs, ys));
return difflist.filter(function (group) {
if (group.length > 1) {
return false;
}
return true;
}).map(fst);
}
/*
* Problem:
* >> > >>^ <- longest one must be matched
* regex?
*/
RegExp.escape= function(s) { RegExp.escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}; };
@ -178,36 +70,20 @@ function operatorMatch(ops) {
var reg = new RegExp(rstring); var reg = new RegExp(rstring);
return function(x) { return function(x) {
var matched = reg.exec(x); var matched = reg.exec(x);
if (matched[0]) if (matched[0]) {
return matched[0]; return matched[0];
else }
else {
return false; return false;
}
}; };
} }
module.exports = {
/*
var print = console.log;
var testOps = [">>", ">>&", ">", "aaaaa:", ">="];
var matcher = operatorMatch(testOps);
print(matcher(">="));
*/
module.exports = {compose : compose,
not : not, not : not,
on : on,
maxBy : maxBy,
len : len,
groupOps : groupOps, groupOps : groupOps,
opMatch : operatorMatch, opMatch : operatorMatch,
dict: dict, dict: dict,
unique : unique,
fst : fst,
rst : rst,
eq: eq,
extend : extend, extend : extend,
flatten : flatten, empty : empty,
difference : difference, };
empty : empty };

Loading…
Cancel
Save