merge OFTN version #18

Merged
weskerfoot merged 6 commits from master into master 11 years ago
  1. 14
      desugar.js
  2. 4
      example.jl
  3. 166
      parse.js
  4. 2
      pprint.js
  5. 50
      prelude.jl
  6. 28
      representation.js
  7. 2
      tokenize.js

14
desugar.js

@ -47,14 +47,14 @@ function desugarLet(stx) {
return new typ.LetExp(values, desugar(stx.body)); return new typ.LetExp(values, desugar(stx.body));
} }
function sugarTypeApp(stx) { function sugarTypeDecl(stx) {
var type; var type;
var expression; var expression;
type = stx.p; type = stx.p;
expression = desugar(stx.func.p); expression = desugar(stx.func.p);
expression.linenum = stx.linenum; expression.linenum = stx.linenum;
expression.charnum = stx.charnum; expression.charnum = stx.charnum;
return new typ.TypeApp(expression, type); return new typ.TypeDecl(expression, type);
} }
function desugarDefType(stx) { function desugarDefType(stx) {
@ -86,19 +86,19 @@ function desugar(stx) {
case "Application": case "Application":
if ((stx.func.func !== undefined ) && if ((stx.func.func !== undefined ) &&
(stx.func.func.ident === "::")) { (stx.func.func.ident === "::")) {
/* It's a type application probably (will be verified later) /* It's a type declaration probably (will be verified later)
* In this case we actually *add* syntax here to differentiate type applications * In this case we actually *add* syntax here to differentiate type declarations
* from normal applications * from normal function application
*/ */
typeExpTest = typ.isTypeExpr(stx.p); typeExpTest = typ.isTypeExpr(stx.p);
if (typeExpTest.failed !== undefined && if (typeExpTest.failed !== undefined &&
typeExpTest.failed) { typeExpTest.failed) {
throw errors.JInternalError( throw errors.JInternalError(
"Type application error near line " + stx.linenum + " at character #"+stx.charnum + "Type declaration error near line " + stx.linenum + " at character #"+stx.charnum +
"\n"+typeExpTest.stx.exprType+" (" + typeExpTest.stx.val + ") found where a type operator or type application was expected"); "\n"+typeExpTest.stx.exprType+" (" + typeExpTest.stx.val + ") found where a type operator or type application was expected");
} }
return sugarTypeApp(stx); return sugarTypeDecl(stx);
} }
if ((stx.func.ident === "-" || if ((stx.func.ident === "-" ||

4
example.jl

@ -1,6 +1,9 @@
defop 2 Left (a ++ b) defop 2 Left (a ++ b)
(a - b) (a - b)
def foo# 3
deftype Foo (A -> B) deftype Foo (A -> B)
;; here is a comment ;; here is a comment
@ -79,6 +82,7 @@ def r def
def main def main
let { let {
(f a) -> a
unary = (print (testUnary 6)) unary = (print (testUnary 6))
splitted = def { splitted = def {
xs = (fst (splitxs [12,3,4,56])) xs = (fst (splitxs [12,3,4,56]))

166
parse.js

@ -192,8 +192,8 @@ function parseDefFunction(tokens, linenum, charnum) {
var body; var body;
if (fname.exprType !== "Name") { if (fname.exprType !== "Name") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Expected an identifier in function definition"); "Expected an identifier in function definition");
} }
if (fst(tokens)[0] === "right_paren") { if (fst(tokens)[0] === "right_paren") {
@ -204,17 +204,17 @@ function parseDefFunction(tokens, linenum, charnum) {
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], charnum,
fst(tokens)[3]); linenum);
} }
if (!tokens || (fst(tokens)[0]) !== "right_paren") { if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Formal parameters must be followed by )"); "Formal parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
body = parse(tokens); body = parse(tokens);
result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, linenum, charnum); result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -235,32 +235,32 @@ function parseLetForm(tokens, linenum, charnum) {
validLet, validLet,
letEnd, letEnd,
tokens, tokens,
linenum, charnum,
charnum); linenum);
if (fst(tokens) && fst(tokens)[0] !== "right_brace") { if (fst(tokens) && fst(tokens)[0] !== "right_brace") {
throw error.JSyntaxError(fst(tokens)[2], throw error.JSyntaxError(fst(tokens)[2],
fst(tokens)[3], fst(tokens)[3],
"let/def form must have a closing }"); "let/def form must have a closing }");
} }
if (!fst(tokens)) { if (!fst(tokens)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(_.last(pairs).linenum,
charnum, _.last(pairs).charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
tokens.pop(); tokens.pop();
if (tokens.length <= 0) { if (tokens.length <= 0) {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(pairs).linenum,
fst(tokens)[2], _.last(pairs).charnum,
"let/def form must have a body"); "let/def form must have a body");
} }
body = parse(tokens); body = parse(tokens);
if (body.exprType === "Definition" || if (body.exprType === "Definition" ||
body.exprType === "FunctionDefinition") { body.exprType === "FunctionDefinition") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(body.linenum,
fst(tokens)[2], body.charnum,
"Body of a let/def expression cannot be a definition"); "Body of a let/def expression cannot be a definition");
} }
result = addSrcPos(new typ.LetExp(pairs, body), tokens, linenum, charnum); result = addSrcPos(new typ.LetExp(pairs, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -284,12 +284,12 @@ function parseLetFunction(tokens, linenum, charnum) {
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], charnum,
fst(tokens)[3]); linenum);
} }
if ((fst(tokens)[0]) !== "right_paren") { if ((fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Formal parameters must be followed by )"); "Formal parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
@ -300,7 +300,7 @@ function parseLetFunction(tokens, linenum, charnum) {
} }
tokens.pop(); tokens.pop();
body = parse(tokens); body = parse(tokens);
result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, linenum, charnum); result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -310,46 +310,49 @@ function parseLetBinding(tokens, linenum, charnum) {
var bound; var bound;
if (name.exprType != "Name") { if (name.exprType != "Name") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"Expected an identifier in let/def binding"); "Expected an identifier in let/def binding");
} }
if (!fst(tokens) || fst(tokens)[1] !== "=") { if (!fst(tokens) || fst(tokens)[1] !== "=") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"An identifier in a let/def binding must be followed by ``=''"); "An identifier in a let/def binding must be followed by ``=''");
} }
tokens.pop(); tokens.pop();
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, name.linenum,
charnum)) { name.charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); "The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]);
} }
bound = parse(tokens); bound = parse(tokens);
if (bound.exprType === "Definition" || if (bound.exprType === "Definition" ||
bound.exprType === "FunctionDefinition") { bound.exprType === "FunctionDefinition") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(bound.linenum,
charnum, bound.charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
result = addSrcPos(new typ.Def(name, bound), tokens, linenum, charnum); result = addSrcPos(new typ.Def(name, bound), tokens, bound.linenum, bound.charnum);
return result; return result;
} }
function parseLetItem(tokens) { function parseLetItem(tokens) {
var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2];
if (fst(tokens) && fst(tokens)[0] === "left_paren") { if (fst(tokens) && fst(tokens)[0] === "left_paren") {
tokens.pop(); tokens.pop();
return parseLetFunction(tokens, return parseLetFunction(tokens,
fst(tokens)[3], linenum,
fst(tokens)[2]); charnum);
} }
else { else {
return parseLetBinding(tokens, return parseLetBinding(tokens,
fst(tokens)[3], linenum,
fst(tokens)[2]); charnum);
} }
} }
@ -371,8 +374,8 @@ function parseDataType(tokens, linenum, charnum) {
charnum, charnum,
linenum); linenum);
if (!tokens || (fst(tokens)[0]) !== "right_paren") { if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(parameters).linenum,
fst(tokens)[2], _.last(parameters).charnum,
"Data type parameters must be followed by )"); "Data type parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
@ -414,8 +417,8 @@ function parseDefType(tokens, linenum, charnum) {
else { else {
lhs = parse(tokens, linenum, charnum); lhs = parse(tokens, linenum, charnum);
if (!tokens) { if (!tokens) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(lhs.linenum,
charnum, lhs.charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
if (lhs.exprType !== "TypeOperator") { if (lhs.exprType !== "TypeOperator") {
@ -431,7 +434,7 @@ function parseDefType(tokens, linenum, charnum) {
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 definition");
} }
result = addSrcPos(new typ.DefType(lhs, rhs), tokens, linenum, charnum); result = addSrcPos(new typ.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum);
return result; return result;
} }
} }
@ -475,24 +478,22 @@ function parseDef(tokens, linenum, charnum) {
else { else {
identifier = parse(tokens); identifier = parse(tokens);
if (!fst(tokens)) if (!fst(tokens))
throw error.JSyntaxError(linenum, throw error.JSyntaxError(identifier.linenum,
charnum, identifier.charnum,
"Unexpected end of source"); "Unexpected end of source");
linenum = fst(tokens)[3];
charnum = fst(tokens)[2];
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, identifier.linenum,
charnum)) { identifier.charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(identifier.linenum,
charnum, identifier.charnum,
"def " + identifier.val + " must not be followed by " + fst(tokens)[0]); "def " + identifier.val + " must not be followed by " + fst(tokens)[0]);
} }
bound = parse(tokens); bound = parse(tokens);
if (bound.exprType === "Definition" || if (bound.exprType === "Definition" ||
bound.exprType === "FunctionDefinition") { bound.exprType === "FunctionDefinition") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(bound.linenum,
charnum, bound.charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
result = addSrcPos(new typ.Def(identifier, bound), tokens, bound.linenum, bound.charnum); result = addSrcPos(new typ.Def(identifier, bound), tokens, bound.linenum, bound.charnum);
@ -503,6 +504,7 @@ function parseDef(tokens, linenum, charnum) {
function parseDefOp(tokens, linenum, charnum) { function parseDefOp(tokens, linenum, charnum) {
var result; var result;
var names; var names;
var pattern;
if (fst(tokens)[0] !== "integer" || if (fst(tokens)[0] !== "integer" ||
fst(tokens)[1] < 1) { fst(tokens)[1] < 1) {
@ -532,7 +534,7 @@ function parseDefOp(tokens, linenum, charnum) {
charnum, charnum,
"defop must be surrounded by exactly 3 identifiers"); "defop must be surrounded by exactly 3 identifiers");
} }
var pattern = tokens.slice(tokens.length-3, pattern = tokens.slice(tokens.length-3,
tokens.length); tokens.length);
tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop();
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
@ -554,17 +556,19 @@ function parseDefOp(tokens, linenum, charnum) {
names.slice(1,3), names.slice(1,3),
parse(tokens)), parse(tokens)),
tokens, tokens,
linenum, _.last(names).linenum,
charnum); _.last(names).charnum);
return result; return result;
} }
function parseIf(tokens) { function parseIf(tokens, linenum, charnum) {
var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2];
var result; var result;
var ifC;
var thenC;
var elseC;
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["def","comma","lambda"], ["def","comma","lambda"],
linenum, linenum,
@ -574,32 +578,32 @@ function parseIf(tokens) {
"``if'' cannot be followed by "+fst(tokens)[0]) ; "``if'' cannot be followed by "+fst(tokens)[0]) ;
} }
else { else {
var ifC = parse(tokens); ifC = parse(tokens);
if (!fst(tokens) || fst(tokens)[0] !== "thenexp") { if (!fst(tokens) || fst(tokens)[0] !== "thenexp") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(ifC.linenum,
fst(tokens)[2], ifC.charnum,
"if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]); "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
} }
else { else {
tokens.pop(); tokens.pop();
var thenC = parse(tokens); thenC = parse(tokens);
if (fst(tokens) && fst(tokens)[0] === "elsexp") { if (fst(tokens) && fst(tokens)[0] === "elsexp") {
tokens.pop(); tokens.pop();
if (_.size(tokens) < 1) { if (_.size(tokens) < 1) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(thenC.linenum,
charnum, thenC.charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
else { else {
var elseC = parse(tokens); elseC = parse(tokens);
result = addSrcPos(new typ.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum); result = addSrcPos(new typ.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum);
return result; return result;
} }
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(thenC.linenum,
charnum, thenC.charnum,
"If expression must include an else variant"); "If expression must include an else variant");
} }
} }
@ -613,9 +617,7 @@ function validFormPar(tok) {
tok[1] !== "->"; tok[1] !== "->";
} }
function parseLambda(tokens) { function parseLambda(tokens, linenum, charnum) {
var linenum = fst(tokens)[2];
var charnum = fst(tokens)[3];
var result; var result;
var parameters = parseMany(parse, var parameters = parseMany(parse,
validName, validName,
@ -624,8 +626,8 @@ function parseLambda(tokens) {
charnum, charnum,
linenum); linenum);
if (fst(tokens)[1] !== "->") { if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(parameters).linenum,
fst(tokens)[2], _.last(parameters).charnum,
"arrow must follow parameters in lambda, not "+fst(tokens)[0]); "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
} }
tokens.pop(); tokens.pop();
@ -643,20 +645,22 @@ function computeApp(tokens, charnum, linenum) {
var lhs = parse(tokens); var lhs = parse(tokens);
var next; var next;
var result; var result;
var parameters;
if (fst(tokens)) { if (fst(tokens)) {
next = fst(tokens); next = fst(tokens);
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(lhs.linenum,
charnum, lhs.charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
if (typ.OPInfo[next[1]]) { if (typ.OPInfo[next[1]]) {
/* it's an infix expression */ /* it's an infix expression */
result = parseInfix(tokens, 1, lhs, linenum, charnum); result = parseInfix(tokens, 1, lhs, lhs.linenum, lhs.charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(lhs.linenum,
fst(tokens)[2], lhs.charnum,
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
@ -666,7 +670,6 @@ function computeApp(tokens, charnum, linenum) {
} }
else { else {
/* it's a prefix application */ /* it's a prefix application */
var parameters;
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse, parameters = parseMany(parse,
validArgTypes, validArgTypes,
@ -744,7 +747,7 @@ function parse(tokens) {
return parseList(tokens, linenum, charnum); return parseList(tokens, linenum, charnum);
} }
else if (toktype === "lambda") { else if (toktype === "lambda") {
return parseLambda(tokens); return parseLambda(tokens, linenum, charnum);
} }
else if (toktype === "integer") { else if (toktype === "integer") {
result = addSrcPos(new typ.IntT(token), tokens, linenum, charnum); result = addSrcPos(new typ.IntT(token), tokens, linenum, charnum);
@ -777,12 +780,12 @@ function parse(tokens) {
return parseDefOp(tokens, linenum, charnum); return parseDefOp(tokens, linenum, charnum);
} }
else if (toktype === "ifexp") { else if (toktype === "ifexp") {
return parseIf(tokens); return parseIf(tokens, linenum, charnum);
} }
else if (toktype === "left_paren") { else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") { if (fst(tokens)[0] === "lambda") {
tokens.pop(); tokens.pop();
var parsed = parseLambda(tokens); var parsed = parseLambda(tokens, linenum, charnum);
tokens.pop(); tokens.pop();
return parsed; return parsed;
} }
@ -801,8 +804,7 @@ function parseFull(tokenized) {
var ast = []; var ast = [];
try { try {
while (tokenized.length > 0) { while (tokenized.length > 0) {
var parsed = desugarer.desugar(parse(tokenized)); ast.push(desugarer.desugar(parse(tokenized)));
ast.push(parsed);
} }
return ast; return ast;
} catch (e) { } catch (e) {

2
pprint.js

@ -94,7 +94,7 @@ function pprint(expr) {
else if (expr.exprType === "TypeVar") { else if (expr.exprType === "TypeVar") {
return "("+expr.name+")"; return "("+expr.name+")";
} }
else if (expr.exprType === "TypeApplication") { else if (expr.exprType === "TypeDeclaration") {
return "( " + pprint(expr.expression) + " :: " + pprint(expr.type) + " )"; return "( " + pprint(expr.expression) + " :: " + pprint(expr.type) + " )";
} }
} }

50
prelude.jl

@ -2,8 +2,56 @@
;; It is sort of special in that it doesn't care whether there are any associated definitions ;; It is sort of special in that it doesn't care whether there are any associated definitions
;; just that there are type definitions for that particular binding's name ;; just that there are type definitions for that particular binding's name
deftype String (List Char)
;; Type definitions
deftype String (A300 Char)
deftype Int Intrinsic
deftype Float Intrinsic
deftype Char Intrinsic
deftype Byte Intrinsic
deftype Void Intrinsic
deftype IO Intrinsic
deftype (List a) deftype (List a)
(Empty | (Empty |
(Cons a (List a))) (Cons a (List a)))
deftype (Maybe a)
(Nothing |
(Just a))
deftype (Either a b)
((Left a) |
(Right b))
;; List functions
(: :: (a -> (List a) -> (List a)))
(map :: ((a -> b) -> (List a) -> (List b)))
(head :: ((List a) -> a))
(tail :: ((List a) -> (List a)))
(!! :: (Int -> (List a) -> a))
(take :: (Int -> (List a) -> (Maybe (List a))))
(drop :: (Int -> (List a) -> (Maybe (List a))))
;; Optional functions
(maybe :: (b -> (a -> b) -> (Maybe a) -> b))
(either :: ((b -> c) -> (b -> c) -> (Either a b) -> c))
;; I/O functions
(print :: (String -> (IO Void)))

28
representation.js

@ -37,17 +37,17 @@ function isIrregularTypeOp(x) {
return (x === "->"); return (x === "->");
} }
function flattenTypeApp(stx) { function flattenTypeDecl(stx) {
if (isTypeExpr(stx)) { if (isTypeExpr(stx)) {
return true; return true;
} }
if (stx.exprType === "Application") { if (stx.exprType === "Application") {
/* it might be a type application so recursively check it */ /* it might be a type application so recursively check it */
if (stx.p !== undefined) { if (stx.p !== undefined) {
return _.flatten([flattenTypeApp(stx.p), flattenTypeApp(stx.func)]); return _.flatten([flattenTypeDecl(stx.p), flattenTypeDecl(stx.func)]);
} }
else { else {
return _.flatten([flattenTypeApp(stx.func)]); return _.flatten([flattenTypeDecl(stx.func)]);
} }
} }
if (stx.exprType === "Name") { if (stx.exprType === "Name") {
@ -66,7 +66,7 @@ function flattenTypeApp(stx) {
function isTypeExprRec(stx) { function isTypeExprRec(stx) {
var flattened = flattenTypeApp(stx); var flattened = flattenTypeDecl(stx);
for(var i = 0; i < flattened.length; i++) { for(var i = 0; i < flattened.length; i++) {
if (flattened[i].failed !== undefined && if (flattened[i].failed !== undefined &&
flattened[i].failed) { flattened[i].failed) {
@ -266,36 +266,36 @@ function isTypeExpr(expr) {
} }
return ((expr.exprType === "TypeOperator") || return ((expr.exprType === "TypeOperator") ||
(expr.exprType === "TypeVar") || (expr.exprType === "TypeVar") ||
(expr.exprType === "TypeApplication")); (expr.exprType === "TypeDeclaration"));
} }
function TypeApp(expression, type) { function TypeDecl(expression, type) {
if (isTypeExprRec(expression) && if (isTypeExprRec(expression) &&
expression.exprType !== "Name") { expression.exprType !== "Name") {
throw errors.JSyntaxError( throw errors.JSyntaxError(
expression.linenum, expression.linenum,
expression.charnum, expression.charnum,
"Left-hand-side of type application must not be in the type language" "Left-hand-side of type declaration must not be in the type language"
); );
} }
if (!isTypeExprRec(type)) { if (isTypeExprRec(type).failed) {
throw errors.JInternalError( throw errors.JInternalError(
"Right-hand-side of type application must be a type expression" "Right-hand-side of type declaration must be a type expression"
); );
} }
this.expression = expression; this.expression = expression;
this.type = type; this.type = type;
this.exprType = "TypeApplication"; this.exprType = "TypeDeclaration";
return this; return this;
} }
TypeApp.prototype = TypeExpression; TypeDecl.prototype = TypeExpression;
function DefType(lhs, rhs) { function DefType(lhs, rhs) {
/* Both rhs and lhs are expected /* Both rhs and lhs are expected
* to be fully desugared already * to be fully desugared already
*/ */
if (!isTypeExprRec(rhs) || if (isTypeExprRec(rhs).failed ||
!isTypeExpr(lhs)) { !isTypeExpr(lhs)) {
throw errors.JSyntaxError( throw errors.JSyntaxError(
rhs.linenum, rhs.linenum,
@ -331,7 +331,7 @@ function DataType(name, params, type) {
"which is a type operator"); "which is a type operator");
} }
_.each(params, checkName); _.each(params, checkName);
if (!isTypeExprRec(type)) { if (isTypeExprRec(type).failed) {
throw errors.JSyntaxError( throw errors.JSyntaxError(
type.linenum, type.linenum,
type.charnum, type.charnum,
@ -416,7 +416,7 @@ module.exports =
gensym : gensym, gensym : gensym,
TypeVar : TypeVar, TypeVar : TypeVar,
TypeOp : TypeOp, TypeOp : TypeOp,
TypeApp: TypeApp, TypeDecl : TypeDecl,
Closure : Closure, Closure : Closure,
isTypeExpr : isTypeExprRec, isTypeExpr : isTypeExprRec,
DefType : DefType, DefType : DefType,

2
tokenize.js

@ -310,7 +310,7 @@ function tokenize(tokstream, matchop) {
if (deftype) { if (deftype) {
tokens.push(["deftype", "deftype", charnum, linenum]); tokens.push(["deftype", "deftype", charnum, linenum]);
tokstream = tokstream.substr(7); tokstream = tokstream.substr(7);
break break;
} }
var def = peek(tokstream, "def", "def"); var def = peek(tokstream, "def", "def");
if (def) { if (def) {

Loading…
Cancel
Save