Browse Source

switching to underscore.js for most functionality

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

46
closure_conversion.js

@ -20,8 +20,9 @@ var errors = require("./errors.js");
var parser = require("./parse.js");
var pprint = require("./pprint.js");
var $ = require("./tools.js");
var _ = require("underscore");
var notEmpty = $.compose($.not, $.eq([]));
var notEmpty = _.compose($.not, _.partial(_.equal, []));
function fvs(stx) {
switch (stx.exprType) {
@ -40,22 +41,22 @@ function fvs(stx) {
case "Let":
return [];
case "Unary":
return $.flatten([stx.op.ident, fvs(stx.val)]);
return _.flatten([stx.op.ident, fvs(stx.val)]);
case "Definition":
return $.flatten(fvs(stx.val));
return _.flatten(fvs(stx.val));
case "Application":
var vs = $.flatten(fvs(stx.p));
var f_fvs = $.flatten(fvs(stx.func));
return $.flatten([vs, f_fvs]);
var vs = _.flatten(fvs(stx.p));
var f_fvs = _.flatten(fvs(stx.func));
return _.flatten([vs, f_fvs]);
case "If":
if (stx.elseexp) {
var cond_fvs = fvs(stx.condition);
var then_fvs = fvs(stx.thenexp);
var else_fvs = fvs(stx.elseexp);
return $.flatten([cond_fvs, then_fvs, else_fvs]);
return _.flatten([cond_fvs, then_fvs, else_fvs]);
}
else {
return $.flatten([fvs(stx.condition), fvs(stx.thenexp)]);
return _.flatten([fvs(stx.condition), fvs(stx.thenexp)]);
}
break;
case "Name":
@ -89,15 +90,15 @@ function closure_convert(stx) {
});
var let_fvs = stx.pairs.map(fvs);
var body_fvs = fvs(stx.body);
variables = $.flatten(let_fvs);
$.extend(variables, $.flatten(body_fvs));
variables = _.flatten(let_fvs);
$.extend(variables, _.flatten(body_fvs));
break;
case "Function":
bound_vars = [stx.p.ident,];
variables = fvs(stx.body);
break;
}
free_variables = $.difference($.unique(variables), bound_vars);
free_variables = _.difference(_.uniq(variables), bound_vars);
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];
//var ast = parser.parse("let { a = let { b = let {dsdfgf = sddd } fdgfg } gggggg } t")[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(pprint.pprint(ast));
function test(src) {
var ast = parser.parse(src)[0];
console.log(JSON.stringify(closure_convert_all(ast), null, 4));
}
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 $ = require("./tools.js");
var _ = require("underscore");
// Lists get desugared to nested function calls
// i.e. (cons (cons (cons ...)))
@ -27,12 +27,12 @@ function desugarDefFunc(def) {
}
function curryFunc(ps, body) {
if ($.empty(ps)) {
if (_.isEmpty(ps)) {
return desugar(body);
}
else {
return new typ.FuncT(desugar($.fst(ps)),
curryFunc($.rst(ps), body));
return new typ.FuncT(desugar(_.first(ps)),
curryFunc(_.rest(ps), body));
}
}

20
parse.js

@ -2,7 +2,8 @@
var fs = require("fs");
var typ = require("./representation.js");
var tool = require("./tools.js");
var $ = require("./tools.js");
var _ = require("underscore");
var tokenizer = require("./tokenize.js");
var desugarer = require("./desugar.js");
var pprint = require("./pprint.js");
@ -166,7 +167,7 @@ function parseDefFunction(tokens) {
}
validLet = makeChecker(["Definition", "FunctionDefinition"]);
letEnd = tool.compose(tool.not, makeChecker(["right_brace"]));
letEnd = _.compose($.not, makeChecker(["right_brace"]));
function parseLetForm(tokens, linenum, charnum) {
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 validArgument = tool.compose(tool.not, makeChecker(invalidArguments));
var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"]));
var validArgument = _.compose($.not, makeChecker(invalidArguments));
var validArgTypes = _.compose($.not, makeChecker(["Definition"]));
var validOperator = makeChecker(["identifier"]);
/* Parses function application (either infix or prefix) */
@ -576,7 +577,7 @@ function parse(tokens) {
}
}
var istr = fs.readFileSync('/dev/stdin').toString();
function parseFull(tokenized) {
var ast = [];
try {
@ -595,11 +596,4 @@ module.exports = { parse : function(str) {
return parseFull(tokenizer.tokenize(str));
}
};
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) };
//var istr = fs.readFileSync('/dev/stdin').toString();

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 = {
display :
function() {
@ -25,6 +23,7 @@ function Closure(bound_vars, free_vars, body, env) {
this.free_vars = free_vars;
this.body = body;
this.env = env;
this.exprType = "Closure";
return this;
}

24
tokenize.js

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

182
tools.js

@ -1,131 +1,34 @@
function empty(xs) {
return xs.length === 0;
}
function identity(a) {
return a;
}
var _ = require("underscore");
function compose(f, g) {
return function(x) {
return f(g(x));
};
function empty(xs) {
return _.size(xs) < 1;
}
function not(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) {
if (a < b)
if (a < b) {
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;
else if (a > b) {
return -1;
}
return xs.slice(i);
}
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;
};
}
function groupBy(eq, xs) {
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];
else {
return 0;
}
return groups;
}
function groupOps(ops) {
return groupBy(function (x) { return function(y) { return x === y; };}, ops.sort());
}
function unique(ops) {
return groupOps(ops).map(fst);
return _.groupBy(ops.sort(), _.isEqual);
}
function find(f, haystack) {
for(var i = 0; i < haystack.length; i++) {
if (f(haystack[i]))
if (f(haystack[i])) {
return i;
}
}
return false;
}
@ -139,10 +42,14 @@ function dict(pairs) {
}
function flatten(xs) {
if (!(xs instanceof Array))
if (!(xs instanceof Array)) {
return xs;
if (xs.every(function (x) { return !(x instanceof Array); }))
}
if (xs.every(function (x) {
return !(x instanceof Array);
})) {
return xs;
}
return [].concat.apply([], xs);
}
@ -151,21 +58,6 @@ function extend(xs, ys) {
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) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
@ -178,36 +70,20 @@ function operatorMatch(ops) {
var reg = new RegExp(rstring);
return function(x) {
var matched = reg.exec(x);
if (matched[0])
if (matched[0]) {
return matched[0];
else
}
else {
return false;
}
};
}
/*
var print = console.log;
var testOps = [">>", ">>&", ">", "aaaaa:", ">="];
var matcher = operatorMatch(testOps);
print(matcher(">="));
*/
module.exports = {compose : compose,
not : not,
on : on,
maxBy : maxBy,
len : len,
groupOps : groupOps,
opMatch : operatorMatch,
dict: dict,
unique : unique,
fst : fst,
rst : rst,
eq: eq,
extend : extend,
flatten : flatten,
difference : difference,
empty : empty };
module.exports = {
not : not,
groupOps : groupOps,
opMatch : operatorMatch,
dict: dict,
extend : extend,
empty : empty,
};

Loading…
Cancel
Save