Browse Source

Merge pull request #10 from oftn/master

merge OFTN version
pull/21/head
Wesley Kerfoot 10 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 errors = require("./errors.js");
var _ = require("underscore");
// Lists get desugared to nested function calls
@ -54,8 +55,9 @@ function sugarTypeApp(stx) {
function desugar(stx) {
switch (stx.exprType) {
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));
case "FunctionDefinition":
return desugarDefFunc(stx);
@ -70,6 +72,9 @@ function desugar(stx) {
* In this case we actually *add* syntax here to differentiate type applications
* from normal applications
*/
if (!typ.isTypeExpr(stx.p)) {
throw errors.JInternalError("Type application error");
}
return sugarTypeApp(stx);
}
@ -78,8 +83,9 @@ function desugar(stx) {
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(stx.func);
case "Function":
return curryFunc(stx.p, stx.body);

2
example.jl

@ -2,7 +2,7 @@ defop 2 Left (a ++#$ b)
(a - b)
(qat :: A)
(qat :: (A -> B))
def qat (lambda a b c -> (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
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens))) {
if (!(valid(fst(tokens))))
if (!(valid(fst(tokens)))) {
break;
}
results.push(parse(tokens));
if (!exprType(fst(results).exprType))
if (!exprType(fst(results).exprType)) {
break;
if (fst(tokens))
}
if (fst(tokens)) {
current = fst(tokens)[0];
else
}
else {
throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
if (tokens.length <= 1)
}
if (tokens.length <= 1) {
break;
}
}
}
//do the same validity check as before and in the loop
if (!fst(tokens))
if (!fst(tokens)) {
throw error.JSyntaxError(linenum,
charnum,
"unexpected end of source");
if (valid(fst(tokens)))
}
if (valid(fst(tokens))) {
results.push(parse(tokens));
}
return results;
}
@ -136,7 +143,9 @@ function parseList(tokens) {
xs = [];
}
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") {
throw error.JSyntaxError(fst(tokens)[3],
@ -151,7 +160,7 @@ function parseList(tokens) {
function parseDefFunction(tokens) {
var fname = parse(tokens);
var parameters;
if (fname.exprType != "Name") {
if (fname.exprType !== "Name") {
throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2],
"Expected an identifier in function definition");
@ -629,7 +638,12 @@ function parseFull(tokenized) {
}
return ast;
} catch (e) {
e.stxerror();
if (e.stxerror !== undefined) {
e.stxerror();
}
else {
console.log(e.errormessage);
}
process.exit(1);
}
}
@ -640,4 +654,4 @@ module.exports = { parse : function(str) {
tokenize : tokenizer.tokenize
};
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
};
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) {
this.bound_vars = bound_vars;
@ -41,7 +76,7 @@ function LetExp(pairs, body) {
return (x.exprType === "Definition" ||
x.exprType === "FunctionDefinition");
})) {
throw Errors.JInternalError(
throw errors.JInternalError(
"let can only be used to bind things to names or functions"
);
}
@ -189,6 +224,8 @@ function TypeOp(name) {
return this;
}
TypeOp.prototype = TypeExpression;
function isTypeExpr(expr) {
if (!expr.exprType) {
throw errors.JInternalError(expr);
@ -198,15 +235,13 @@ function isTypeExpr(expr) {
(expr.exprType === "TypeApplication"));
}
TypeOp.prototype = TypeExpression;
function TypeApp(expression, type) {
if (isTypeExpr(expression)) {
if (isTypeExprRec(expression)) {
throw errors.JInternalError(
"Left-hand-side of type application must not be in the type language"
);
}
if (!isTypeExpr(type)) {
if (!isTypeExprRec(type)) {
throw errors.JInternalError(
"Right-hand-side of type application must be a type expression"
);
@ -242,6 +277,8 @@ function makeGensym() {
var gensym = makeGensym();
//console.log(isTypeExpr(new Name("T")));
OPInfo = {"+" : [3, "Left"],
"-" : [3, "Left"],
"*" : [4, "Left"],
@ -288,5 +325,6 @@ module.exports =
TypeVar : TypeVar,
TypeOp : TypeOp,
TypeApp: TypeApp,
Closure : Closure
Closure : Closure,
isTypeExpr : isTypeExprRec
};

10
tokenize.js

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

2
tools.js

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

Loading…
Cancel
Save