Browse Source

Merge pull request #20 from oftn/master

merge OFTN version
pull/21/head
Wesley Kerfoot 10 years ago
parent
commit
815573ac6e
  1. 22
      environments.js
  2. 12
      example.jl
  3. 43
      free_vars.js
  4. 13
      parse.js
  5. 75
      prelude.jl
  6. 26
      representation.js
  7. 9
      tokenize.js
  8. 8
      typecheck.js

22
environments.js

@ -3,13 +3,14 @@
* with a few built-in (a standard Prelude environment)
*/
// returns the new environment after mutating it
// values = [(identifier, JLambda expression)]
var errors = require("./errors.js");
var rep = require("./representation.js");
/*
* returns the new environment after mutating it
* values = [(identifier, JLambda expression)]
*/
function extend(env, values) {
var new_env = {};
var env_keys = Object.keys(env);
@ -42,14 +43,7 @@ function lookup(name, env) {
return value;
}
var prelude = makeEnv("prelude", [[new rep.Name("e"), new rep.FloatT(Math.E)],
[new rep.Name("pi"), new rep.FloatT(Math.PI)]]);
var prelude_types = makeEnv("prelude_types",
[[new rep.Name("e"), new rep.TypeOp("Float", [], false)],
[new rep.Name("pi"), new rep.TypeOp("Float", [], false)]]);
module.exports = { prelude : prelude,
prelude_types : prelude_types,
lookup : lookup,
extend : extend };
module.exports = {
lookup : lookup,
extend : extend
};

12
example.jl

@ -1,7 +1,3 @@
defop 2 Left (a ++ b)
(a - b)
def foo# 3
deftype Foo (A -> B)
@ -40,9 +36,9 @@ def empty []
def getFile
(readFile "./parse.js")
def fileLines
(getFile >>=
((mapM_ putStrLn) . lines))
;;def fileLines
;; (getFile >>=
;; ((mapM_ putStrLn) . lines))
def (testUnary n)
((-n) + n)
@ -94,3 +90,5 @@ def main
(unary +
fileLines +
(print splitted))
def blah (3 / 4)

43
closure_conversion.js → free_vars.js

@ -1,4 +1,4 @@
/* Takes an AST and converts all of the functions into closures.
/* Takes an AST and converts all of the functions into "closures"
* A closure is a triple of:
* the bound variables in a function or let
* the free variables in a function or let
@ -19,10 +19,8 @@
*/
var rep = require("./representation.js");
var env = require("./environments.js");
var errors = require("./errors.js");
var parser = require("./parse.js");
var pprint = require("./pprint.js");
var $ = require("./tools.js");
var _ = require("underscore");
@ -68,7 +66,7 @@ function fvs(stx) {
}
}
function closure_convert(stx) {
function annotate_fvs(stx) {
/* Takes a stx object that is either
* a lambda
* a let
@ -106,40 +104,43 @@ function closure_convert(stx) {
return new rep.Closure(bound_vars, free_variables, stx, []);
}
function closure_convert_all(stx) {
/*
* This traverse the tree and gathers up all of the free variables of various functions/let bindings
*/
function annotate_fvs_all(stx) {
var closure;
switch (stx.exprType) {
case "Let":
closure = closure_convert(stx);
closure.body.pairs = closure.body.pairs.map(closure_convert_all);
closure.body = closure_convert_all(closure.body.body);
closure = annotate_fvs(stx);
closure.body.pairs = closure.body.pairs.map(annotate_fvs_all);
closure.body = annotate_fvs_all(closure.body.body);
return closure;
case "Function":
closure = closure_convert(stx);
closure.body.body = closure_convert_all(closure.body.body);
closure = annotate_fvs(stx);
closure.body.body = annotate_fvs_all(closure.body.body);
return closure;
case "Unary":
stx.val = closure_convert_all(stx.val);
stx.val = annotate_fvs_all(stx.val);
return stx;
case "Application":
stx.func = closure_convert_all(stx.func);
stx.p = closure_convert_all(stx.p);
stx.func = annotate_fvs_all(stx.func);
stx.p = annotate_fvs_all(stx.p);
return stx;
case "If":
if (stx.elseexp) {
stx.condition = closure_convert_all(stx.condition);
stx.thenexp = closure_convert_all(stx.thenexp);
stx.elseexp = closure_convert_all(stx.elseexp);
stx.condition = annotate_fvs_all(stx.condition);
stx.thenexp = annotate_fvs_all(stx.thenexp);
stx.elseexp = annotate_fvs_all(stx.elseexp);
return stx;
}
else {
stx.condition = closure_convert_all(stx.condition);
stx.thenexp = closure_convert_all(stx.thenexp);
stx.condition = annotate_fvs_all(stx.condition);
stx.thenexp = annotate_fvs_all(stx.thenexp);
return stx;
}
break;
case "Definition":
stx.val = closure_convert_all(stx.val);
stx.val = annotate_fvs_all(stx.val);
return stx;
default:
return stx;
@ -149,11 +150,11 @@ function closure_convert_all(stx) {
function test(src) {
var ast = parser.parse(src)[0];
console.log(JSON.stringify(closure_convert_all(ast), null, 4));
console.log(JSON.stringify(annotate_fvs_all(ast), null, 4));
}
//console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing"));
module.export = {
test : test,
closureConvert : closure_convert_all
annotate_fvs: annotate_fvs_all
};

13
parse.js

@ -367,12 +367,17 @@ function parseDataType(tokens, linenum, charnum) {
typeName.charnum,
"Expected a type operator in data type definition");
}
parameters = parseMany(parse,
if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse,
validName,
validFormPar,
tokens,
charnum,
linenum);
}
else {
parameters = [];
}
if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(_.last(parameters).linenum,
_.last(parameters).charnum,
@ -402,7 +407,7 @@ function parseDefType(tokens, linenum, charnum) {
}
if (fst(tokens)[0] === "left_paren") {
/* It's an actual data type definition
* i.e. not just a newtype
* i.e. not just an alias
*/
tokens.pop();
return parseDataType(tokens, linenum, charnum);
@ -424,7 +429,7 @@ function parseDefType(tokens, linenum, charnum) {
if (lhs.exprType !== "TypeOperator") {
throw error.JSyntaxError(lhs.linenum,
lhs.charnum,
"left-hand side of type definition was not a type operator");
"left-hand side of type alias was not a type operator");
}
rhs = parse(tokens, linenum, charnum);
@ -432,7 +437,7 @@ function parseDefType(tokens, linenum, charnum) {
rhs.exprType !== "TypeOperator") {
throw error.JSyntaxError(rhs.linenum,
rhs.charnum,
"was expecting an application or type operator on the right-hand side of a type definition");
"was expecting an application or type operator on the right-hand side of a type alias");
}
result = addSrcPos(new typ.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum);
return result;

75
prelude.jl

@ -4,24 +4,29 @@
;; Type definitions
deftype String (A300 Char)
deftype String (Vector Char)
deftype Int Intrinsic
deftype (Int) Intrinsic
deftype Float Intrinsic
deftype (Float) Intrinsic
deftype Char Intrinsic
deftype (Char) Intrinsic
deftype Byte Intrinsic
deftype (Byte) Intrinsic
deftype Void Intrinsic
deftype (Void) Intrinsic
deftype IO Intrinsic
deftype (IO a) Intrinsic
deftype (Vector a) Intrinsic
deftype (List a)
(Empty |
(Cons a (List a)))
deftype (Bottom)
Undefined
deftype (Maybe a)
(Nothing |
(Just a))
@ -55,3 +60,59 @@ deftype (Either a b)
;; I/O functions
(print :: (String -> (IO Void)))
;; Operator definitions
defop 3 Left (a + b)
(add a b)
defop 3 Left (a - b)
(minus a b)
defop 4 Left (a * b)
(mul a b)
defop 4 Left (a / b)
(div a b)
defop 5 Right (a ^ b)
(pow a b)
defop 3 Left (a ++ b)
(listConcat a b)
defop 2 Left (a == b)
(eq a b)
defop 2 Left (a > b)
(gt a b)
defop 2 Left (a >= b)
(gte a b)
defop 2 Left (a < b)
(lt a b)
defop 2 Left (a <= b)
(lte a b)
defop 2 Left (a && b)
(and a b)
defop 2 Left (a || b)
(or a b)
defop 1 Left (x : xs)
(cons x xs)
defop 1 Left (f $ x)
(fapply f x)
defop 1 Left (f . g)
(compose f g)
defop 1 Left (a | b)
(bitwiseOr a b)
defop 1 Left (a & b)
(bitwiseAnd a b)

26
representation.js

@ -368,31 +368,11 @@ function makeGensym() {
var gensym = makeGensym();
//console.log(isTypeExpr(new Name("T")));
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"],
OPInfo = {
"::" : [2, "Left"],
":" : [1, "Left"],
"$" : [1, "Left"],
">>" : [1, "Left"],
">>=" : [1, "Left"],
"<$>" : [1, "Left"],
"." : [1, "Left"],
"," : [1, "Left"],
"->" : [1, "Right"],
"|" : [1, "Left"]};
"->" : [1, "Right"]
};
module.exports =
{

9
tokenize.js

@ -1,5 +1,6 @@
#! /usr/bin/node
var fs = require("fs");
var rep = require("./representation.js");
var $ = require("./tools.js");
var error = require("./errors.js");
@ -13,10 +14,7 @@ function isDigit(c) {
if (isNaN(code)) {
return false;
}
return (46 < code &&
code < 58 ||
code < 58 &&
code > 46);
return (47 < code && code < 58);
}
function isWhitespace(c) {
@ -411,8 +409,11 @@ function checkPattern(x, i) {
}
function tokenizeFull(input) {
var preludeSrc = fs.readFileSync("./prelude.jl");
var matchop;
var initialPass = tokenizeHelp(input, _.constant(false), true).reverse();
input = [preludeSrc, input].join("");
for (var i = 0; i < initialPass.length; i++) {
if (initialPass.slice(i, i+8).
map(_.first).

8
typecheck.js

@ -13,7 +13,7 @@
var rep = require("./representation.js");
var env = require("./environments.js");
var TypeOp = rep.TypeOp;
var TypeVar = rep.TypeVar;
/*
* Map all bindings with explicit type annotations in the environment
*/
function gather_annotations(stx) {

Loading…
Cancel
Save