diff --git a/.gitignore b/.gitignore deleted file mode 100644 index da23d0d..0000000 --- a/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directory -# Deployed apps should consider commenting this line out: -# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git -node_modules diff --git a/README.md b/README.md index 57ad6bb..69e5928 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ -JLambda -======= - JLambda is a functional language in the spirit of languages such as Scheme, SML, or Clean. It aims to have a very flexible syntax and a clean and easy to understand type system. Another goal is to generate very efficient JavaScript @@ -14,18 +11,3 @@ JLambda also aims to support concurrency which will be built on a continuation-passing style intermediate language. I have not figured out how scheduling threads will work, or whether I will provide any programmer directed way of scheduling (i.e. yield). - -Installation ------------- - - git clone git@github.com:nisstyre56/JLambda.git - cd JLambda - npm install - -Usage ------ - -Since the language is currently under heavy construction, the parser is the -entry point for now: - - cat example.jl | ./parse.js diff --git a/desugar.js b/desugar.js index 9da5d4e..a404fef 100644 --- a/desugar.js +++ b/desugar.js @@ -57,30 +57,34 @@ function sugarTypeDecl(stx) { return new typ.TypeDecl(expression, type); } -function desugarDefType(stx) { +function desugarDefType(stx, typeEnv) { var result; - result = new typ.DefType(desugar(stx.lhs), desugar(stx.rhs)); + var rhs = desugar(stx.rhs); + var name = stx.lhs.name; + typeEnv[name] = rhs; + + result = new typ.DefType(stx.lhs, desugar(stx.rhs)); result.linenum = stx.linenum; result.charnum = stx.charnum; return result; } -function desugar(stx) { +function desugar(stx, typeEnv) { var typeExpTest; switch (stx.exprType) { case "If": if (stx.elseexp) { - return new typ.If(desugar(stx.condition), desugar(stx.thenexp), desugar(stx.elseexp)); + return new typ.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv), desugar(stx.elseexp, typeEnv)); } - return new typ.If(desugar(stx.condition), desugar(stx.thenexp)); + return new typ.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv)); case "FunctionDefinition": return desugarDefFunc(stx); case "Definition": - return new typ.Def(stx.ident, desugar(stx.val)); + return new typ.Def(stx.ident, desugar(stx.val, typeEnv)); case "TypeDefinition": - return desugarDefType(stx); + return desugarDefType(stx, typeEnv); case "Name": return stx; case "Application": @@ -104,10 +108,10 @@ function desugar(stx) { if ((stx.func.ident === "-" || stx.func.ident === "+") && stx.p) { - return new typ.UnaryOp(desugar(stx.func), desugar(stx.p)); + return new typ.UnaryOp(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); } if (stx.p) { - return new typ.App(desugar(stx.func), desugar(stx.p)); + return new typ.App(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); } return new typ.App(stx.func); case "Function": diff --git a/free_vars.js b/free_vars.js index 602c31d..caf3198 100644 --- a/free_vars.js +++ b/free_vars.js @@ -149,8 +149,7 @@ function annotate_fvs_all(stx) { function test(src) { - var ast = parser.parse(src)[0]; - console.log(JSON.stringify(annotate_fvs_all(ast), null, 4)); + var ast = parser.parse(src); } //console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing")); diff --git a/package.json b/package.json deleted file mode 100644 index f3044c2..0000000 --- a/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "JLambda", - "version": "0.0.0", - "description": "yet another static functional language implemented in JS", - "scripts": { - "test": "./test.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/nisstyre56/JLambda.git" - }, - "keywords": [ - "static", - "functional", - "language" - ], - "author": "nisstyre56", - "license": "ΩF:∅", - "bugs": { - "url": "https://github.com/nisstyre56/JLambda/issues" - }, - "homepage": "https://github.com/nisstyre56/JLambda", - "dependencies": { - "underscore": "^1.6.0" - } -} diff --git a/parse.js b/parse.js index 2c4e23a..08b6052 100755 --- a/parse.js +++ b/parse.js @@ -807,11 +807,12 @@ function parse(tokens) { function parseFull(tokenized) { var ast = []; + var typeBindings = {}; try { while (tokenized.length > 0) { - ast.push(desugarer.desugar(parse(tokenized))); + ast.push(desugarer.desugar(parse(tokenized), typeBindings)); } - return ast; + return [ast, typeBindings]; } catch (e) { if (e.stxerror !== undefined) { e.stxerror(); @@ -830,4 +831,6 @@ module.exports = { parse : function(str) { tokenize : tokenizer.tokenize }; var istr = fs.readFileSync('/dev/stdin').toString(); -console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint)); +var testParse = parseFull(tokenizer.tokenize(istr)); +console.log(testParse[1]); +console.log(testParse[0].map(pprint.pprint)); diff --git a/prelude.jl b/prelude.jl index 1ed259f..2099588 100644 --- a/prelude.jl +++ b/prelude.jl @@ -63,56 +63,56 @@ deftype (Either a b) ;; Operator definitions -defop 3 Left (a + b) +defop 1 Left (a + b) (add a b) -defop 3 Left (a - b) +defop 1 Left (a - b) (minus a b) -defop 4 Left (a * b) +defop 2 Left (a * b) (mul a b) -defop 4 Left (a / b) +defop 2 Left (a / b) (div a b) -defop 5 Right (a ^ b) +defop 2 Right (a ^ b) (pow a b) defop 3 Left (a ++ b) (listConcat a b) -defop 2 Left (a == b) +defop 3 Left (a == b) (eq a b) -defop 2 Left (a > b) +defop 3 Left (a > b) (gt a b) -defop 2 Left (a >= b) +defop 3 Left (a >= b) (gte a b) -defop 2 Left (a < b) +defop 3 Left (a < b) (lt a b) -defop 2 Left (a <= b) +defop 3 Left (a <= b) (lte a b) -defop 2 Left (a && b) +defop 3 Left (a && b) (and a b) -defop 2 Left (a || b) +defop 3 Left (a || b) (or a b) -defop 1 Left (x : xs) +defop 4 Left (x : xs) (cons x xs) -defop 1 Left (f $ x) +defop 5 Left (f $ x) (fapply f x) -defop 1 Left (f . g) +defop 5 Left (f . g) (compose f g) -defop 1 Left (a | b) +defop 3 Left (a | b) (bitwiseOr a b) -defop 1 Left (a & b) +defop 3 Left (a & b) (bitwiseAnd a b) diff --git a/tokenize.js b/tokenize.js index c522acd..cbe748a 100755 --- a/tokenize.js +++ b/tokenize.js @@ -14,7 +14,7 @@ function isDigit(c) { if (isNaN(code)) { return false; } - return (47 < code && code < 58); + return (47 < code) && (code < 58) } function isWhitespace(c) { @@ -411,9 +411,9 @@ function checkPattern(x, i) { function tokenizeFull(input) { var preludeSrc = fs.readFileSync("./prelude.jl"); var matchop; + input = [preludeSrc, input].join(""); 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). diff --git a/typecheck.js b/typecheck.js index e105e94..c39306c 100644 --- a/typecheck.js +++ b/typecheck.js @@ -16,4 +16,3 @@ var env = require("./environments.js"); /* * Map all bindings with explicit type annotations in the environment */ -function gather_annotations(stx) {