Browse Source

Merge pull request #10 from oftn/master

merge OFTN version
pull/21/head
Wesley Kerfoot 11 years ago
parent
commit
9c6eab9eea
  1. 10
      desugar.js
  2. 2
      example.jl
  3. 36
      parse.js
  4. 52
      representation.js
  5. 10
      tokenize.js
  6. 2
      tools.js

10
desugar.js

@ -5,6 +5,7 @@
*/ */
var typ = require("./representation.js"); var typ = require("./representation.js");
var errors = require("./errors.js");
var _ = require("underscore"); var _ = require("underscore");
// Lists get desugared to nested function calls // Lists get desugared to nested function calls
@ -54,8 +55,9 @@ function sugarTypeApp(stx) {
function desugar(stx) { function desugar(stx) {
switch (stx.exprType) { switch (stx.exprType) {
case "If": case "If":
if (stx.elseexp) if (stx.elseexp) {
return new typ.If(desugar(stx.condition), desugar(stx.thenexp), desugar(stx.elseexp)); return new typ.If(desugar(stx.condition), desugar(stx.thenexp), desugar(stx.elseexp));
}
return new typ.If(desugar(stx.condition), desugar(stx.thenexp)); return new typ.If(desugar(stx.condition), desugar(stx.thenexp));
case "FunctionDefinition": case "FunctionDefinition":
return desugarDefFunc(stx); return desugarDefFunc(stx);
@ -70,6 +72,9 @@ function desugar(stx) {
* In this case we actually *add* syntax here to differentiate type applications * In this case we actually *add* syntax here to differentiate type applications
* from normal applications * from normal applications
*/ */
if (!typ.isTypeExpr(stx.p)) {
throw errors.JInternalError("Type application error");
}
return sugarTypeApp(stx); return sugarTypeApp(stx);
} }
@ -78,8 +83,9 @@ function desugar(stx) {
stx.p) { stx.p) {
return new typ.UnaryOp(desugar(stx.func), desugar(stx.p)); return new typ.UnaryOp(desugar(stx.func), desugar(stx.p));
} }
if (stx.p) if (stx.p) {
return new typ.App(desugar(stx.func), desugar(stx.p)); return new typ.App(desugar(stx.func), desugar(stx.p));
}
return new typ.App(stx.func); return new typ.App(stx.func);
case "Function": case "Function":
return curryFunc(stx.p, stx.body); return curryFunc(stx.p, stx.body);

2
example.jl

@ -2,7 +2,7 @@ defop 2 Left (a ++#$ b)
(a - b) (a - b)
(qat :: A) (qat :: (A -> B))
def qat (lambda a b c -> (a + b)) def qat (lambda a b c -> (a + b))
def (add a b) def (add a b)

36
parse.js

@ -77,26 +77,33 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
//make sure there are at least 2 tokens to parse //make sure there are at least 2 tokens to parse
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) { if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens))) { while (valid(snd(tokens))) {
if (!(valid(fst(tokens)))) if (!(valid(fst(tokens)))) {
break; break;
}
results.push(parse(tokens)); results.push(parse(tokens));
if (!exprType(fst(results).exprType)) if (!exprType(fst(results).exprType)) {
break; break;
if (fst(tokens)) }
if (fst(tokens)) {
current = fst(tokens)[0]; current = fst(tokens)[0];
else }
else {
throw error.JSyntaxError(charnum, linenum, "Unexpected end of source"); throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
if (tokens.length <= 1) }
if (tokens.length <= 1) {
break; break;
}
} }
} }
//do the same validity check as before and in the loop //do the same validity check as before and in the loop
if (!fst(tokens)) if (!fst(tokens)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"unexpected end of source"); "unexpected end of source");
if (valid(fst(tokens))) }
if (valid(fst(tokens))) {
results.push(parse(tokens)); results.push(parse(tokens));
}
return results; return results;
} }
@ -136,7 +143,9 @@ function parseList(tokens) {
xs = []; xs = [];
} }
else { else {
xs = parseBetween(function (x) { return true; }, "comma", tokens, fst(tokens)[3], fst(tokens)[2]); xs = parseBetween(function (x) {
return true;
}, "comma", tokens, fst(tokens)[3], fst(tokens)[2]);
} }
if (!fst(tokens) || fst(tokens)[0] !== "right_square") { if (!fst(tokens) || fst(tokens)[0] !== "right_square") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
@ -151,7 +160,7 @@ function parseList(tokens) {
function parseDefFunction(tokens) { function parseDefFunction(tokens) {
var fname = parse(tokens); var fname = parse(tokens);
var parameters; var parameters;
if (fname.exprType != "Name") { if (fname.exprType !== "Name") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2], fst(tokens)[2],
"Expected an identifier in function definition"); "Expected an identifier in function definition");
@ -629,7 +638,12 @@ function parseFull(tokenized) {
} }
return ast; return ast;
} catch (e) { } catch (e) {
e.stxerror(); if (e.stxerror !== undefined) {
e.stxerror();
}
else {
console.log(e.errormessage);
}
process.exit(1); process.exit(1);
} }
} }
@ -640,4 +654,4 @@ module.exports = { parse : function(str) {
tokenize : tokenizer.tokenize tokenize : tokenizer.tokenize
}; };
var istr = fs.readFileSync('/dev/stdin').toString(); var istr = fs.readFileSync('/dev/stdin').toString();
parseFull(tokenizer.tokenize(istr)).map(pprint.pprint); console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint));

52
representation.js

@ -25,7 +25,42 @@ var TypeExpression = {
isTypeExpr : true isTypeExpr : true
}; };
var isTypeExpr = _.property("isTypeExpr"); function isTypeExpr(x) {
return x.isTypeExpr !== undefined;
}
function isIrregularTypeOp(x) {
return (x === "->");
}
function isTypeExprRec(stx, isTypeOp) {
if (isTypeExpr(stx)) {
return true;
}
if (stx.exprType === "Application") {
/* it might be a type application so recursively check it */
if (stx.p !== undefined) {
return (isTypeExprRec(stx.p) &&
isTypeExprRec(stx.func));
}
else {
return isTypeExprRec(stx.func);
}
}
if (stx.exprType === "Name") {
/* Check if it might be a type operator that is not capitalized */
return isIrregularTypeOp(stx.ident);
}
return false;
}
function App(func, p) {
this.func = func;
this.exprType = "Application";
if (p)
this.p = p;
return this;
}
function Closure(bound_vars, free_vars, body, env) { function Closure(bound_vars, free_vars, body, env) {
this.bound_vars = bound_vars; this.bound_vars = bound_vars;
@ -41,7 +76,7 @@ function LetExp(pairs, body) {
return (x.exprType === "Definition" || return (x.exprType === "Definition" ||
x.exprType === "FunctionDefinition"); x.exprType === "FunctionDefinition");
})) { })) {
throw Errors.JInternalError( throw errors.JInternalError(
"let can only be used to bind things to names or functions" "let can only be used to bind things to names or functions"
); );
} }
@ -189,6 +224,8 @@ function TypeOp(name) {
return this; return this;
} }
TypeOp.prototype = TypeExpression;
function isTypeExpr(expr) { function isTypeExpr(expr) {
if (!expr.exprType) { if (!expr.exprType) {
throw errors.JInternalError(expr); throw errors.JInternalError(expr);
@ -198,15 +235,13 @@ function isTypeExpr(expr) {
(expr.exprType === "TypeApplication")); (expr.exprType === "TypeApplication"));
} }
TypeOp.prototype = TypeExpression;
function TypeApp(expression, type) { function TypeApp(expression, type) {
if (isTypeExpr(expression)) { if (isTypeExprRec(expression)) {
throw errors.JInternalError( throw errors.JInternalError(
"Left-hand-side of type application must not be in the type language" "Left-hand-side of type application must not be in the type language"
); );
} }
if (!isTypeExpr(type)) { if (!isTypeExprRec(type)) {
throw errors.JInternalError( throw errors.JInternalError(
"Right-hand-side of type application must be a type expression" "Right-hand-side of type application must be a type expression"
); );
@ -242,6 +277,8 @@ function makeGensym() {
var gensym = makeGensym(); var gensym = makeGensym();
//console.log(isTypeExpr(new Name("T")));
OPInfo = {"+" : [3, "Left"], OPInfo = {"+" : [3, "Left"],
"-" : [3, "Left"], "-" : [3, "Left"],
"*" : [4, "Left"], "*" : [4, "Left"],
@ -288,5 +325,6 @@ module.exports =
TypeVar : TypeVar, TypeVar : TypeVar,
TypeOp : TypeOp, TypeOp : TypeOp,
TypeApp: TypeApp, TypeApp: TypeApp,
Closure : Closure Closure : Closure,
isTypeExpr : isTypeExprRec
}; };

10
tokenize.js

@ -400,11 +400,13 @@ function tokenizeFull(input) {
var matchop; var matchop;
var initialPass = tokenizeHelp(input, _.constant(false), true).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(_.first).every(checkPattern)) { if (initialPass.slice(i, i+8).
rep.OPInfo[initialPass[i+5][1]] = [parseInt(initialPass[i+1][1], 10), map(_.first).
initialPass[i+2][1]]; every(checkPattern)) {
rep.OPInfo[initialPass[i+5][1]] =
[parseInt(initialPass[i+1][1], 10),
initialPass[i+2][1]];
} }
} }
operators = Object.keys(rep.OPInfo); operators = Object.keys(rep.OPInfo);
matchop = $.opMatch(operators); matchop = $.opMatch(operators);

2
tools.js

@ -5,7 +5,7 @@ function empty(xs) {
} }
function not(x) { function not(x) {
return !x; return !x;
} }
function min(a, b) { function min(a, b) {

Loading…
Cancel
Save