merge OFTN version #20

Merged
weskerfoot merged 7 commits from master into master 11 years ago
  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) * 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 errors = require("./errors.js");
var rep = require("./representation.js"); var rep = require("./representation.js");
/*
* returns the new environment after mutating it
* values = [(identifier, JLambda expression)]
*/
function extend(env, values) { function extend(env, values) {
var new_env = {}; var new_env = {};
var env_keys = Object.keys(env); var env_keys = Object.keys(env);
@ -42,14 +43,7 @@ function lookup(name, env) {
return value; return value;
} }
var prelude = makeEnv("prelude", [[new rep.Name("e"), new rep.FloatT(Math.E)], module.exports = {
[new rep.Name("pi"), new rep.FloatT(Math.PI)]]); lookup : lookup,
extend : extend
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 };

12
example.jl

@ -1,7 +1,3 @@
defop 2 Left (a ++ b)
(a - b)
def foo# 3 def foo# 3
deftype Foo (A -> B) deftype Foo (A -> B)
@ -40,9 +36,9 @@ def empty []
def getFile def getFile
(readFile "./parse.js") (readFile "./parse.js")
def fileLines ;;def fileLines
(getFile >>= ;; (getFile >>=
((mapM_ putStrLn) . lines)) ;; ((mapM_ putStrLn) . lines))
def (testUnary n) def (testUnary n)
((-n) + n) ((-n) + n)
@ -94,3 +90,5 @@ def main
(unary + (unary +
fileLines + fileLines +
(print splitted)) (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: * 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
@ -19,10 +19,8 @@
*/ */
var rep = require("./representation.js"); var rep = require("./representation.js");
var env = require("./environments.js");
var errors = require("./errors.js"); var errors = require("./errors.js");
var parser = require("./parse.js"); var parser = require("./parse.js");
var pprint = require("./pprint.js");
var $ = require("./tools.js"); var $ = require("./tools.js");
var _ = require("underscore"); 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 /* Takes a stx object that is either
* a lambda * a lambda
* a let * a let
@ -106,40 +104,43 @@ 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) { /*
* This traverse the tree and gathers up all of the free variables of various functions/let bindings
*/
function annotate_fvs_all(stx) {
var closure; var closure;
switch (stx.exprType) { switch (stx.exprType) {
case "Let": case "Let":
closure = closure_convert(stx); closure = annotate_fvs(stx);
closure.body.pairs = closure.body.pairs.map(closure_convert_all); closure.body.pairs = closure.body.pairs.map(annotate_fvs_all);
closure.body = closure_convert_all(closure.body.body); closure.body = annotate_fvs_all(closure.body.body);
return closure; return closure;
case "Function": case "Function":
closure = closure_convert(stx); closure = annotate_fvs(stx);
closure.body.body = closure_convert_all(closure.body.body); closure.body.body = annotate_fvs_all(closure.body.body);
return closure; return closure;
case "Unary": case "Unary":
stx.val = closure_convert_all(stx.val); stx.val = annotate_fvs_all(stx.val);
return stx; return stx;
case "Application": case "Application":
stx.func = closure_convert_all(stx.func); stx.func = annotate_fvs_all(stx.func);
stx.p = closure_convert_all(stx.p); stx.p = annotate_fvs_all(stx.p);
return stx; return stx;
case "If": case "If":
if (stx.elseexp) { if (stx.elseexp) {
stx.condition = closure_convert_all(stx.condition); stx.condition = annotate_fvs_all(stx.condition);
stx.thenexp = closure_convert_all(stx.thenexp); stx.thenexp = annotate_fvs_all(stx.thenexp);
stx.elseexp = closure_convert_all(stx.elseexp); stx.elseexp = annotate_fvs_all(stx.elseexp);
return stx; return stx;
} }
else { else {
stx.condition = closure_convert_all(stx.condition); stx.condition = annotate_fvs_all(stx.condition);
stx.thenexp = closure_convert_all(stx.thenexp); stx.thenexp = annotate_fvs_all(stx.thenexp);
return stx; return stx;
} }
break; break;
case "Definition": case "Definition":
stx.val = closure_convert_all(stx.val); stx.val = annotate_fvs_all(stx.val);
return stx; return stx;
default: default:
return stx; return stx;
@ -149,11 +150,11 @@ function closure_convert_all(stx) {
function test(src) { function test(src) {
var ast = parser.parse(src)[0]; 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")); //console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing"));
module.export = { module.export = {
test : test, 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, typeName.charnum,
"Expected a type operator in data type definition"); "Expected a type operator in data type definition");
} }
parameters = parseMany(parse, if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse,
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
charnum, charnum,
linenum); linenum);
}
else {
parameters = [];
}
if (!tokens || (fst(tokens)[0]) !== "right_paren") { if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(_.last(parameters).linenum, throw error.JSyntaxError(_.last(parameters).linenum,
_.last(parameters).charnum, _.last(parameters).charnum,
@ -402,7 +407,7 @@ function parseDefType(tokens, linenum, charnum) {
} }
if (fst(tokens)[0] === "left_paren") { if (fst(tokens)[0] === "left_paren") {
/* It's an actual data type definition /* It's an actual data type definition
* i.e. not just a newtype * i.e. not just an alias
*/ */
tokens.pop(); tokens.pop();
return parseDataType(tokens, linenum, charnum); return parseDataType(tokens, linenum, charnum);
@ -424,7 +429,7 @@ function parseDefType(tokens, linenum, charnum) {
if (lhs.exprType !== "TypeOperator") { if (lhs.exprType !== "TypeOperator") {
throw error.JSyntaxError(lhs.linenum, throw error.JSyntaxError(lhs.linenum,
lhs.charnum, 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); rhs = parse(tokens, linenum, charnum);
@ -432,7 +437,7 @@ function parseDefType(tokens, linenum, charnum) {
rhs.exprType !== "TypeOperator") { rhs.exprType !== "TypeOperator") {
throw error.JSyntaxError(rhs.linenum, throw error.JSyntaxError(rhs.linenum,
rhs.charnum, 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); result = addSrcPos(new typ.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum);
return result; return result;

75
prelude.jl

@ -4,24 +4,29 @@
;; Type definitions ;; 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) deftype (List a)
(Empty | (Empty |
(Cons a (List a))) (Cons a (List a)))
deftype (Bottom)
Undefined
deftype (Maybe a) deftype (Maybe a)
(Nothing | (Nothing |
(Just a)) (Just a))
@ -55,3 +60,59 @@ deftype (Either a b)
;; I/O functions ;; I/O functions
(print :: (String -> (IO Void))) (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(); var gensym = makeGensym();
//console.log(isTypeExpr(new Name("T"))); OPInfo = {
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"], "::" : [2, "Left"],
":" : [1, "Left"],
"$" : [1, "Left"],
">>" : [1, "Left"],
">>=" : [1, "Left"],
"<$>" : [1, "Left"],
"." : [1, "Left"],
"," : [1, "Left"], "," : [1, "Left"],
"->" : [1, "Right"], "->" : [1, "Right"]
"|" : [1, "Left"]}; };
module.exports = module.exports =
{ {

9
tokenize.js

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

8
typecheck.js

@ -13,7 +13,7 @@
var rep = require("./representation.js"); var rep = require("./representation.js");
var env = require("./environments.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