Created
April 30, 2025 11:24
-
-
Save cometkim/f4043044f815299240609c1d07fd6eb4 to your computer and use it in GitHub Desktop.
ReScript v11 to v12 compile output diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by ReScript, PLEASE EDIT WITH CARE | |
import * as Objects from "./Objects.res.mjs"; | |
import * as Caml_obj from "rescript/lib/es6/caml_obj.js"; | |
import * as Caml_int32 from "rescript/lib/es6/caml_int32.js"; | |
import * as Environment from "./Environment.res.mjs"; | |
var cTRUE = { | |
TAG: "MBoolean", | |
_0: { | |
value: true | |
} | |
}; | |
var cFALSE = { | |
TAG: "MBoolean", | |
_0: { | |
value: false | |
} | |
}; | |
function ifNotError(obj, body) { | |
if (obj !== undefined) { | |
if (typeof obj !== "object" || obj.TAG !== "MError") { | |
return body(obj); | |
} else { | |
return obj; | |
} | |
} | |
} | |
function isError(obj) { | |
if (obj !== undefined && !(typeof obj !== "object" || obj.TAG !== "MError")) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
function evalIntegerInfixExpression(operator, left, right) { | |
switch (operator) { | |
case "!=" : | |
if (left !== right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case "*" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: Math.imul(left, right) | |
} | |
}; | |
case "+" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: left + right | 0 | |
} | |
}; | |
case "-" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: left - right | 0 | |
} | |
}; | |
case "/" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: Caml_int32.div(left, right) | |
} | |
}; | |
case "<" : | |
if (left < right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case "==" : | |
if (left === right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case ">" : | |
if (left > right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
default: | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unknown operator MInteger " + operator + " MInteger" | |
} | |
}; | |
} | |
} | |
function extendFunctionEnv(fun, args) { | |
var env = Environment.newEnclosedEnvironment(fun.env); | |
var params = fun.parameters; | |
if (params !== undefined) { | |
var i = 0; | |
var len = params.length; | |
while(i < len) { | |
var identifier = params[i]; | |
var arg = args[i]; | |
Environment.set(env, identifier.value, arg); | |
i = i + 1 | 0; | |
}; | |
} | |
return env; | |
} | |
function evaluateStatement(_statement, env) { | |
while(true) { | |
var statement = _statement; | |
if (statement !== undefined) { | |
switch (statement.TAG) { | |
case "Identifier" : | |
var value = statement._0.value; | |
var v = Environment.get(env, value); | |
if (v !== undefined) { | |
return v; | |
} | |
var fn = Objects.builtins.get(value); | |
if (fn !== undefined) { | |
return { | |
TAG: "MBuiltinFunction", | |
_0: fn | |
}; | |
} else { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "identifier not found: " + value | |
} | |
}; | |
} | |
case "StringLiteral" : | |
return { | |
TAG: "MString", | |
_0: { | |
value: statement._0.value | |
} | |
}; | |
case "LetStatement" : | |
var match = statement._0; | |
var name = match.name; | |
return ifNotError(evaluateStatement(match.value, env), (function(name){ | |
return function (v) { | |
return Environment.put(env, name.value, v); | |
} | |
}(name))); | |
case "IntegerLiteral" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: statement._0.value | |
} | |
}; | |
case "BooleanLiteral" : | |
return statement._0.value ? cTRUE : cFALSE; | |
case "ReturnStatement" : | |
return ifNotError(evaluateStatement(statement._0.returnValue, env), (function (value) { | |
return { | |
TAG: "MReturnValue", | |
_0: { | |
value: value | |
} | |
}; | |
})); | |
case "ExpressionStatement" : | |
_statement = statement._0.expression; | |
continue ; | |
case "PrefixExpression" : | |
var match$1 = statement._0; | |
var operator = match$1.operator; | |
return ifNotError(evaluateStatement(match$1.right, env), (function(operator){ | |
return function (r) { | |
switch (operator) { | |
case "!" : | |
return Caml_obj.equal(r, cTRUE) || !(Caml_obj.equal(r, cFALSE) || Caml_obj.equal(r, "MNull")) ? cFALSE : cTRUE; | |
case "-" : | |
var tmp; | |
var exit = 0; | |
if (typeof r !== "object" || r.TAG !== "MInteger") { | |
exit = 1; | |
} else { | |
tmp = { | |
TAG: "MInteger", | |
_0: { | |
value: -r._0.value | 0 | |
} | |
}; | |
} | |
if (exit === 1) { | |
tmp = { | |
TAG: "MError", | |
_0: { | |
message: "unknown operator: -" + Objects.typeDesc(r) | |
} | |
}; | |
} | |
return tmp; | |
default: | |
return { | |
TAG: "MError", | |
_0: { | |
message: "Unknown operator: " + operator + Objects.typeDesc(r) | |
} | |
}; | |
} | |
} | |
}(operator))); | |
case "InfixExpression" : | |
var match$2 = statement._0; | |
var right = match$2.right; | |
var operator$1 = match$2.operator; | |
return ifNotError(evaluateStatement(match$2.left, env), (function(operator$1,right){ | |
return function (l) { | |
return ifNotError(evaluateStatement(right, env), (function (r) { | |
var tmp; | |
var exit = 0; | |
var exit$1 = 0; | |
if (typeof l !== "object") { | |
exit$1 = 2; | |
} else { | |
switch (l.TAG) { | |
case "MInteger" : | |
if (typeof r !== "object" || r.TAG !== "MInteger") { | |
exit$1 = 2; | |
} else { | |
tmp = evalIntegerInfixExpression(operator$1, l._0.value, r._0.value); | |
} | |
break; | |
case "MString" : | |
if (operator$1 === "+") { | |
if (typeof r !== "object" || r.TAG !== "MString") { | |
exit = 1; | |
} else { | |
tmp = { | |
TAG: "MString", | |
_0: { | |
value: l._0.value + r._0.value | |
} | |
}; | |
} | |
} else { | |
exit$1 = 2; | |
} | |
break; | |
default: | |
exit$1 = 2; | |
} | |
} | |
if (exit$1 === 2) { | |
switch (operator$1) { | |
case "!=" : | |
var b = Caml_obj.notequal(l, r); | |
tmp = b ? cTRUE : cFALSE; | |
break; | |
case "==" : | |
var b$1 = Caml_obj.equal(l, r); | |
tmp = b$1 ? cTRUE : cFALSE; | |
break; | |
default: | |
exit = 1; | |
} | |
} | |
if (exit === 1) { | |
tmp = Caml_obj.notequal(Objects.typeDesc(l), Objects.typeDesc(r)) ? ({ | |
TAG: "MError", | |
_0: { | |
message: "type mismatch: " + Objects.typeDesc(l) + " " + operator$1 + " " + Objects.typeDesc(r) | |
} | |
}) : ({ | |
TAG: "MError", | |
_0: { | |
message: "unknown operator: " + Objects.typeDesc(l) + " " + operator$1 + " " + Objects.typeDesc(r) | |
} | |
}); | |
} | |
return tmp; | |
})); | |
} | |
}(operator$1,right))); | |
case "CallExpression" : | |
var match$3 = statement._0; | |
var $$arguments = match$3.arguments; | |
return ifNotError(evaluateStatement(match$3.function, env), (function($$arguments){ | |
return function (fun) { | |
var args = evalExpressions($$arguments, env); | |
if (args.length === 1 && isError(args[0])) { | |
return args[0]; | |
} else { | |
if (typeof fun === "object") { | |
switch (fun.TAG) { | |
case "MFunction" : | |
var mFun = fun._0; | |
var extendEnv = extendFunctionEnv(mFun, args); | |
var body = mFun.body; | |
var body$1 = body !== undefined ? ({ | |
TAG: "BlockStatement", | |
_0: body | |
}) : undefined; | |
var $$eval = evaluateStatement(body$1, extendEnv); | |
if ($$eval !== undefined) { | |
if (typeof $$eval !== "object" || $$eval.TAG !== "MReturnValue") { | |
return $$eval; | |
} else { | |
return $$eval._0.value; | |
} | |
} else { | |
return ; | |
} | |
case "MBuiltinFunction" : | |
var result = fun._0.fn(args); | |
if (result !== undefined) { | |
return result; | |
} else { | |
return "MNull"; | |
} | |
default: | |
} | |
} | |
return { | |
TAG: "MError", | |
_0: { | |
message: "Not a function: " + Objects.typeDesc(fun) | |
} | |
}; | |
} | |
} | |
}($$arguments))); | |
case "ArrayLiteral" : | |
var evalElements = evalExpressions(statement._0.elements, env); | |
if (evalElements.length === 1 && isError(evalElements[0])) { | |
return evalElements[0]; | |
} else { | |
return { | |
TAG: "MArray", | |
_0: { | |
elements: evalElements | |
} | |
}; | |
} | |
case "IndexExpression" : | |
var match$4 = statement._0; | |
var leftEvaluated = evaluateStatement(match$4.left, env); | |
if (isError(leftEvaluated)) { | |
return leftEvaluated; | |
} | |
var indexEvaluated = evaluateStatement(match$4.index, env); | |
if (isError(indexEvaluated)) { | |
return indexEvaluated; | |
} | |
if (leftEvaluated !== undefined && typeof leftEvaluated === "object") { | |
switch (leftEvaluated.TAG) { | |
case "MArray" : | |
if (indexEvaluated !== undefined && typeof indexEvaluated === "object" && indexEvaluated.TAG === "MInteger") { | |
var elements = leftEvaluated._0.elements; | |
var index = indexEvaluated._0.value; | |
var max = elements.length - 1 | 0; | |
if (index < 0 || index > max) { | |
return "MNull"; | |
} else { | |
return elements[index]; | |
} | |
} | |
break; | |
case "MHash" : | |
var pairs = leftEvaluated._0.pairs; | |
if (indexEvaluated === undefined) { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: null" | |
} | |
}; | |
} | |
if (!Objects.isHashable(indexEvaluated)) { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: " + Objects.typeDesc(indexEvaluated) | |
} | |
}; | |
} | |
var pair = pairs.get(Objects.hashKey(indexEvaluated)); | |
if (pair !== undefined) { | |
return pair.value; | |
} else { | |
return "MNull"; | |
} | |
default: | |
} | |
} | |
return { | |
TAG: "MError", | |
_0: { | |
message: "index operator not supported: " + ( | |
leftEvaluated !== undefined ? Objects.typeDesc(leftEvaluated) : "" | |
) | |
} | |
}; | |
break; | |
case "BlockStatement" : | |
return evaluateBlockStatement(statement._0, env); | |
case "IfExpression" : | |
var match$5 = statement._0; | |
var alternative = match$5.alternative; | |
var consequence = match$5.consequence; | |
var isTruthy = function (c) { | |
return !(Caml_obj.equal(c, "MNull") || Caml_obj.equal(c, cFALSE)); | |
}; | |
return ifNotError(evaluateStatement(match$5.condition, env), (function(consequence,alternative){ | |
return function (c) { | |
var match = isTruthy(c); | |
if (!match) { | |
if (alternative !== undefined) { | |
return evaluateBlockStatement(alternative, env); | |
} else { | |
return "MNull"; | |
} | |
} | |
var consequence$1 = consequence !== undefined ? ({ | |
TAG: "BlockStatement", | |
_0: consequence | |
}) : undefined; | |
return evaluateStatement(consequence$1, env); | |
} | |
}(consequence,alternative))); | |
case "FunctionLiteral" : | |
var match$6 = statement._0; | |
return { | |
TAG: "MFunction", | |
_0: { | |
parameters: match$6.parameters, | |
body: match$6.body, | |
env: env | |
} | |
}; | |
case "HashLiteral" : | |
var bodyPairs = new Map(); | |
var keep = { | |
contents: true | |
}; | |
var returnValue = { | |
contents: undefined | |
}; | |
statement._0.pairs.forEach((function(bodyPairs,keep,returnValue){ | |
return function (value, key) { | |
if (!keep.contents) { | |
return ; | |
} | |
var keyEvaluated = evaluateStatement(key, env); | |
if (isError(keyEvaluated)) { | |
keep.contents = false; | |
returnValue.contents = keyEvaluated; | |
return ; | |
} | |
if (keyEvaluated !== undefined) { | |
if (Objects.isHashable(keyEvaluated)) { | |
var valueEvaluated = evaluateStatement(value, env); | |
if (isError(valueEvaluated)) { | |
keep.contents = false; | |
returnValue.contents = valueEvaluated; | |
} else { | |
bodyPairs.set(Objects.hashKey(keyEvaluated), { | |
key: keyEvaluated, | |
value: valueEvaluated | |
}); | |
} | |
return ; | |
} | |
keep.contents = false; | |
returnValue.contents = { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: " + Objects.typeDesc(keyEvaluated) | |
} | |
}; | |
return ; | |
} | |
keep.contents = false; | |
returnValue.contents = { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: null" | |
} | |
}; | |
} | |
}(bodyPairs,keep,returnValue))); | |
var value$1 = returnValue.contents; | |
if (value$1 !== undefined) { | |
return value$1; | |
} else { | |
return { | |
TAG: "MHash", | |
_0: { | |
pairs: bodyPairs | |
} | |
}; | |
} | |
} | |
} else { | |
throw { | |
RE_EXN_ID: "Failure", | |
_1: "statement shouldn't be None", | |
Error: new Error() | |
}; | |
} | |
}; | |
} | |
function evaluateBlockStatement(st, env) { | |
var result; | |
var keep = true; | |
var statements = st.statements; | |
if (statements !== undefined) { | |
var i = 0; | |
var len = statements.length; | |
while(keep && i < len) { | |
var statement = statements[i]; | |
result = evaluateStatement(statement, env); | |
var match = result; | |
if (match !== undefined && typeof match === "object") { | |
switch (match.TAG) { | |
case "MReturnValue" : | |
case "MError" : | |
keep = false; | |
break; | |
default: | |
} | |
} | |
i = i + 1 | 0; | |
}; | |
} | |
return result; | |
} | |
function evalExpressions(args, env) { | |
var evalList = []; | |
var keep = true; | |
if (args !== undefined) { | |
var i = 0; | |
var len = args.length; | |
while(keep && i < len) { | |
var arg = args[i]; | |
var evaluated = evaluateStatement(arg, env); | |
if (isError(evaluated)) { | |
keep = false; | |
evalList = [evaluated]; | |
} else { | |
var evalListContents = evalList; | |
evalListContents.push(evaluated); | |
evalList = evalListContents; | |
} | |
i = i + 1 | 0; | |
}; | |
} | |
return evalList; | |
} | |
function $$eval(program, env) { | |
var result; | |
var keep = true; | |
var i = 0; | |
var len = program.statements.length; | |
while(keep && i < len) { | |
var statement = program.statements[i]; | |
result = evaluateStatement(statement, env); | |
var match = result; | |
if (match !== undefined && typeof match === "object") { | |
switch (match.TAG) { | |
case "MReturnValue" : | |
result = match._0.value; | |
keep = false; | |
break; | |
case "MError" : | |
keep = false; | |
break; | |
default: | |
} | |
} | |
i = i + 1 | 0; | |
}; | |
return result; | |
} | |
var Eval = { | |
$$eval: $$eval, | |
cNULL: "MNull", | |
cTRUE: cTRUE, | |
cFALSE: cFALSE | |
}; | |
export { | |
Eval , | |
} | |
/* Objects Not a pure module */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by ReScript, PLEASE EDIT WITH CARE | |
import * as Objects from "./Objects.res.mjs"; | |
import * as Environment from "./Environment.res.mjs"; | |
import * as Primitive_int from "rescript/lib/es6/Primitive_int.js"; | |
import * as Primitive_object from "rescript/lib/es6/Primitive_object.js"; | |
let cTRUE = { | |
TAG: "MBoolean", | |
_0: { | |
value: true | |
} | |
}; | |
let cFALSE = { | |
TAG: "MBoolean", | |
_0: { | |
value: false | |
} | |
}; | |
function ifNotError(obj, body) { | |
if (obj !== undefined) { | |
if (typeof obj !== "object" || obj.TAG !== "MError") { | |
return body(obj); | |
} else { | |
return obj; | |
} | |
} | |
} | |
function isError(obj) { | |
if (typeof obj === "object") { | |
return obj.TAG === "MError"; | |
} else { | |
return false; | |
} | |
} | |
function evalIntegerInfixExpression(operator, left, right) { | |
switch (operator) { | |
case "!=" : | |
if (left !== right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case "*" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: left * right | 0 | |
} | |
}; | |
case "+" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: left + right | 0 | |
} | |
}; | |
case "-" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: left - right | 0 | |
} | |
}; | |
case "/" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: Primitive_int.div(left, right) | |
} | |
}; | |
case "<" : | |
if (left < right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case "==" : | |
if (left === right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
case ">" : | |
if (left > right) { | |
return cTRUE; | |
} else { | |
return cFALSE; | |
} | |
default: | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unknown operator MInteger " + operator + " MInteger" | |
} | |
}; | |
} | |
} | |
function extendFunctionEnv(fun, args) { | |
let env = Environment.newEnclosedEnvironment(fun.env); | |
let params = fun.parameters; | |
if (params !== undefined) { | |
let i = 0; | |
let len = params.length; | |
while (i < len) { | |
let identifier = params[i]; | |
let arg = args[i]; | |
Environment.set(env, identifier.value, arg); | |
i = i + 1 | 0; | |
}; | |
} | |
return env; | |
} | |
function evaluateStatement(_statement, env) { | |
while (true) { | |
let statement = _statement; | |
if (statement !== undefined) { | |
switch (statement.TAG) { | |
case "Identifier" : | |
let value = statement._0.value; | |
let v = Environment.get(env, value); | |
if (v !== undefined) { | |
return v; | |
} | |
let fn = Objects.builtins.get(value); | |
if (fn !== undefined) { | |
return { | |
TAG: "MBuiltinFunction", | |
_0: fn | |
}; | |
} else { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "identifier not found: " + value | |
} | |
}; | |
} | |
case "StringLiteral" : | |
return { | |
TAG: "MString", | |
_0: { | |
value: statement._0.value | |
} | |
}; | |
case "LetStatement" : | |
let match = statement._0; | |
let name = match.name; | |
return ifNotError(evaluateStatement(match.value, env), v => Environment.put(env, name.value, v)); | |
case "IntegerLiteral" : | |
return { | |
TAG: "MInteger", | |
_0: { | |
value: statement._0.value | |
} | |
}; | |
case "BooleanLiteral" : | |
return statement._0.value ? cTRUE : cFALSE; | |
case "ReturnStatement" : | |
return ifNotError(evaluateStatement(statement._0.returnValue, env), value => ({ | |
TAG: "MReturnValue", | |
_0: { | |
value: value | |
} | |
})); | |
case "ExpressionStatement" : | |
_statement = statement._0.expression; | |
continue; | |
case "PrefixExpression" : | |
let match$1 = statement._0; | |
let operator = match$1.operator; | |
return ifNotError(evaluateStatement(match$1.right, env), r => { | |
switch (operator) { | |
case "!" : | |
return Primitive_object.equal(r, cTRUE) || !(Primitive_object.equal(r, cFALSE) || Primitive_object.equal(r, "MNull")) ? cFALSE : cTRUE; | |
case "-" : | |
let tmp; | |
let exit = 0; | |
if (typeof r !== "object" || r.TAG !== "MInteger") { | |
exit = 1; | |
} else { | |
tmp = { | |
TAG: "MInteger", | |
_0: { | |
value: -r._0.value | 0 | |
} | |
}; | |
} | |
if (exit === 1) { | |
tmp = { | |
TAG: "MError", | |
_0: { | |
message: "unknown operator: -" + Objects.typeDesc(r) | |
} | |
}; | |
} | |
return tmp; | |
default: | |
return { | |
TAG: "MError", | |
_0: { | |
message: "Unknown operator: " + operator + Objects.typeDesc(r) | |
} | |
}; | |
} | |
}); | |
case "InfixExpression" : | |
let match$2 = statement._0; | |
let right = match$2.right; | |
let operator$1 = match$2.operator; | |
return ifNotError(evaluateStatement(match$2.left, env), l => ifNotError(evaluateStatement(right, env), r => { | |
let tmp; | |
let exit = 0; | |
let exit$1 = 0; | |
if (typeof l !== "object") { | |
exit$1 = 2; | |
} else { | |
switch (l.TAG) { | |
case "MInteger" : | |
if (typeof r !== "object" || r.TAG !== "MInteger") { | |
exit$1 = 2; | |
} else { | |
tmp = evalIntegerInfixExpression(operator$1, l._0.value, r._0.value); | |
} | |
break; | |
case "MString" : | |
if (operator$1 === "+") { | |
if (typeof r !== "object" || r.TAG !== "MString") { | |
exit = 1; | |
} else { | |
tmp = { | |
TAG: "MString", | |
_0: { | |
value: l._0.value + r._0.value | |
} | |
}; | |
} | |
} else { | |
exit$1 = 2; | |
} | |
break; | |
default: | |
exit$1 = 2; | |
} | |
} | |
if (exit$1 === 2) { | |
switch (operator$1) { | |
case "!=" : | |
tmp = Primitive_object.notequal(l, r) ? cTRUE : cFALSE; | |
break; | |
case "==" : | |
tmp = Primitive_object.equal(l, r) ? cTRUE : cFALSE; | |
break; | |
default: | |
exit = 1; | |
} | |
} | |
if (exit === 1) { | |
tmp = Primitive_object.notequal(Objects.typeDesc(l), Objects.typeDesc(r)) ? ({ | |
TAG: "MError", | |
_0: { | |
message: "type mismatch: " + Objects.typeDesc(l) + " " + operator$1 + " " + Objects.typeDesc(r) | |
} | |
}) : ({ | |
TAG: "MError", | |
_0: { | |
message: "unknown operator: " + Objects.typeDesc(l) + " " + operator$1 + " " + Objects.typeDesc(r) | |
} | |
}); | |
} | |
return tmp; | |
})); | |
case "CallExpression" : | |
let match$3 = statement._0; | |
let $$arguments = match$3.arguments; | |
return ifNotError(evaluateStatement(match$3.function, env), fun => { | |
let args = evalExpressions($$arguments, env); | |
if (args.length === 1 && isError(args[0])) { | |
return args[0]; | |
} else { | |
if (typeof fun === "object") { | |
switch (fun.TAG) { | |
case "MFunction" : | |
let mFun = fun._0; | |
let extendEnv = extendFunctionEnv(mFun, args); | |
let body = mFun.body; | |
let body$1 = body !== undefined ? ({ | |
TAG: "BlockStatement", | |
_0: body | |
}) : undefined; | |
let $$eval = evaluateStatement(body$1, extendEnv); | |
if ($$eval !== undefined) { | |
if (typeof $$eval !== "object" || $$eval.TAG !== "MReturnValue") { | |
return $$eval; | |
} else { | |
return $$eval._0.value; | |
} | |
} else { | |
return; | |
} | |
case "MBuiltinFunction" : | |
let result = fun._0.fn(args); | |
if (result !== undefined) { | |
return result; | |
} else { | |
return "MNull"; | |
} | |
} | |
} | |
return { | |
TAG: "MError", | |
_0: { | |
message: "Not a function: " + Objects.typeDesc(fun) | |
} | |
}; | |
} | |
}); | |
case "ArrayLiteral" : | |
let evalElements = evalExpressions(statement._0.elements, env); | |
if (evalElements.length === 1 && isError(evalElements[0])) { | |
return evalElements[0]; | |
} else { | |
return { | |
TAG: "MArray", | |
_0: { | |
elements: evalElements | |
} | |
}; | |
} | |
case "IndexExpression" : | |
let match$4 = statement._0; | |
let leftEvaluated = evaluateStatement(match$4.left, env); | |
if (isError(leftEvaluated)) { | |
return leftEvaluated; | |
} | |
let indexEvaluated = evaluateStatement(match$4.index, env); | |
if (isError(indexEvaluated)) { | |
return indexEvaluated; | |
} | |
if (typeof leftEvaluated === "object") { | |
switch (leftEvaluated.TAG) { | |
case "MArray" : | |
if (typeof indexEvaluated === "object" && indexEvaluated.TAG === "MInteger") { | |
let elements = leftEvaluated._0.elements; | |
let index = indexEvaluated._0.value; | |
let max = elements.length - 1 | 0; | |
if (index < 0 || index > max) { | |
return "MNull"; | |
} else { | |
return elements[index]; | |
} | |
} | |
break; | |
case "MHash" : | |
let pairs = leftEvaluated._0.pairs; | |
if (indexEvaluated === undefined) { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: null" | |
} | |
}; | |
} | |
if (!Objects.isHashable(indexEvaluated)) { | |
return { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: " + Objects.typeDesc(indexEvaluated) | |
} | |
}; | |
} | |
let pair = pairs.get(Objects.hashKey(indexEvaluated)); | |
if (pair !== undefined) { | |
return pair.value; | |
} else { | |
return "MNull"; | |
} | |
} | |
} | |
return { | |
TAG: "MError", | |
_0: { | |
message: "index operator not supported: " + ( | |
leftEvaluated !== undefined ? Objects.typeDesc(leftEvaluated) : "" | |
) | |
} | |
}; | |
break; | |
case "BlockStatement" : | |
return evaluateBlockStatement(statement._0, env); | |
case "IfExpression" : | |
let match$5 = statement._0; | |
let alternative = match$5.alternative; | |
let consequence = match$5.consequence; | |
let isTruthy = c => !(Primitive_object.equal(c, "MNull") || Primitive_object.equal(c, cFALSE)); | |
return ifNotError(evaluateStatement(match$5.condition, env), c => { | |
let match = isTruthy(c); | |
if (!match) { | |
if (alternative !== undefined) { | |
return evaluateBlockStatement(alternative, env); | |
} else { | |
return "MNull"; | |
} | |
} | |
let consequence$1 = consequence !== undefined ? ({ | |
TAG: "BlockStatement", | |
_0: consequence | |
}) : undefined; | |
return evaluateStatement(consequence$1, env); | |
}); | |
case "FunctionLiteral" : | |
let match$6 = statement._0; | |
return { | |
TAG: "MFunction", | |
_0: { | |
parameters: match$6.parameters, | |
body: match$6.body, | |
env: env | |
} | |
}; | |
case "HashLiteral" : | |
let bodyPairs = new Map(); | |
let keep = { | |
contents: true | |
}; | |
let returnValue = { | |
contents: undefined | |
}; | |
statement._0.pairs.forEach((value, key) => { | |
if (!keep.contents) { | |
return; | |
} | |
let keyEvaluated = evaluateStatement(key, env); | |
if (isError(keyEvaluated)) { | |
keep.contents = false; | |
returnValue.contents = keyEvaluated; | |
return; | |
} | |
if (keyEvaluated !== undefined) { | |
if (Objects.isHashable(keyEvaluated)) { | |
let valueEvaluated = evaluateStatement(value, env); | |
if (isError(valueEvaluated)) { | |
keep.contents = false; | |
returnValue.contents = valueEvaluated; | |
} else { | |
bodyPairs.set(Objects.hashKey(keyEvaluated), { | |
key: keyEvaluated, | |
value: valueEvaluated | |
}); | |
} | |
return; | |
} | |
keep.contents = false; | |
returnValue.contents = { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: " + Objects.typeDesc(keyEvaluated) | |
} | |
}; | |
return; | |
} | |
keep.contents = false; | |
returnValue.contents = { | |
TAG: "MError", | |
_0: { | |
message: "unusable as a hash key: null" | |
} | |
}; | |
}); | |
let value$1 = returnValue.contents; | |
if (value$1 !== undefined) { | |
return value$1; | |
} else { | |
return { | |
TAG: "MHash", | |
_0: { | |
pairs: bodyPairs | |
} | |
}; | |
} | |
} | |
} else { | |
throw { | |
RE_EXN_ID: "Failure", | |
_1: "statement shouldn't be None", | |
Error: new Error() | |
}; | |
} | |
}; | |
} | |
function evalExpressions(args, env) { | |
let evalList = []; | |
let keep = true; | |
if (args !== undefined) { | |
let i = 0; | |
let len = args.length; | |
while (keep && i < len) { | |
let arg = args[i]; | |
let evaluated = evaluateStatement(arg, env); | |
if (isError(evaluated)) { | |
keep = false; | |
evalList = [evaluated]; | |
} else { | |
let evalListContents = evalList; | |
evalListContents.push(evaluated); | |
evalList = evalListContents; | |
} | |
i = i + 1 | 0; | |
}; | |
} | |
return evalList; | |
} | |
function evaluateBlockStatement(st, env) { | |
let result; | |
let keep = true; | |
let statements = st.statements; | |
if (statements !== undefined) { | |
let i = 0; | |
let len = statements.length; | |
while (keep && i < len) { | |
let statement = statements[i]; | |
result = evaluateStatement(statement, env); | |
let match = result; | |
if (typeof match === "object") { | |
switch (match.TAG) { | |
case "MReturnValue" : | |
case "MError" : | |
keep = false; | |
break; | |
} | |
} | |
i = i + 1 | 0; | |
}; | |
} | |
return result; | |
} | |
function $$eval(program, env) { | |
let result; | |
let keep = true; | |
let i = 0; | |
let len = program.statements.length; | |
while (keep && i < len) { | |
let statement = program.statements[i]; | |
result = evaluateStatement(statement, env); | |
let match = result; | |
if (typeof match === "object") { | |
switch (match.TAG) { | |
case "MReturnValue" : | |
result = match._0.value; | |
keep = false; | |
break; | |
case "MError" : | |
keep = false; | |
break; | |
} | |
} | |
i = i + 1 | 0; | |
}; | |
return result; | |
} | |
let Eval = { | |
$$eval: $$eval, | |
cNULL: "MNull", | |
cTRUE: cTRUE, | |
cFALSE: cFALSE | |
}; | |
export { | |
Eval, | |
} | |
/* Objects Not a pure module */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment