Last active
November 11, 2016 23:22
-
-
Save erikroyall/a8c54f806c9b6bbafcbef9ce5a60e650 to your computer and use it in GitHub Desktop.
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
function parse(code) { | |
const flow = []; | |
const state = { | |
expectingNextLine: false | |
}; | |
// Remove blank lines and generate an array containing | |
// each line of code | |
const xcode = | |
code | |
.split("\n") | |
.map(line => line.trim()) | |
.filter(line => line !== ""); | |
for (let cur = 0; cur < xcode.length; cur++) { | |
const line = xcode[cur]; | |
const xline = | |
line | |
.split(" ") | |
.map(op => op.trim()) | |
.filter(op => op !== ""); | |
// Check for labels | |
if (xline[0].split(":").length === 2) { | |
// Check if previous statement was a LabelExpression | |
if (state.expectingNextLine) { | |
console.error("Expected a FunctionApplication, encountered a LabelExpression"); | |
break; | |
} | |
// Check if this is the last line of code | |
if (cur + 1 === xcode.length) { | |
console.error("Expected a FunctionApplication, reached end of input"); | |
break; | |
} | |
flow.push({ | |
line: cur, | |
type: "LabelExpression", | |
code: xline[0], | |
name: xline[0].split(":")[0], | |
pointsTo: cur + 1 | |
}); | |
// If it's a label, next label must be a FunctionApplication | |
state.expectingNextLine = true; | |
continue; | |
} | |
flow.push({ | |
line: cur, | |
type: "FunctionApplication", | |
code: xline.join(" "), | |
name: xline[0], | |
args: xline.slice(1) | |
}); | |
state.expectingNextLine = false; | |
} | |
return flow; | |
} | |
var handlers = { | |
add: function addHandler (args) { | |
return args.reduce((acc,cur) => +acc + +cur, 0); | |
}, | |
sub: function subHandler (args) { | |
return args.reduce((acc,cur) => +acc - +cur, 0); | |
}, | |
mul: function mulHandler (args) { | |
return args.reduce((acc,cur) => +acc * +cur, 0); | |
}, | |
div: function divHandler (args) { | |
return args.reduce((acc,cur) => +acc / +cur, 0); | |
}, | |
print: function printHandler (args, state) { | |
let out = ""; | |
if (args.length === 0) { | |
out += "\n"; | |
return 0; | |
} | |
args.forEach(function (arg) { | |
if (arg[0] === ":") { | |
out += state.vars[arg.slice(1)] + " "; | |
} else if (arg[0] === "%") { | |
out += state.data[arg.slice(1)] + " "; | |
} else { | |
out += arg + " "; | |
} | |
}); | |
state.output += out; | |
return 0; | |
}, | |
let: function letHandler (arg, state, code) { | |
if (arg.length !== 2) { | |
console.error("let() takes 2 parameters, " + arg.length + " passed"); | |
console.error(code); | |
console.error(" ^"); | |
return -1; | |
} | |
else if (arg[1][0] === ":") { | |
state.vars[arg[0]] = state.vars[arg[1].slice(1)]; | |
} else if (arg[1][0] === "%") { | |
state.vars[arg[0]] = state.data[arg[1].slice(1)]; | |
} else { | |
state.vars[arg[0]] = arg[1]; | |
} | |
return 0; | |
} | |
}; | |
function evaluate(tree) { | |
const labelTable = {}; | |
const state = { | |
output: "", | |
vars: {}, // Program-defined variables | |
data: { | |
retval: null | |
} | |
}; | |
// Populate the label table | |
for (let cur = 0; cur < tree.length; cur++) { | |
let ins = tree[cur]; | |
if (ins.type === "LabelExpression") { | |
labelTable[ins.name] = ins.pointsTo; | |
} | |
} | |
for (let cur = 0; cur < tree.length; cur++) { | |
let ins = tree[cur]; | |
if (ins.type === "FunctionApplication") { | |
// handle goto | |
if (ins.name === "goto") { | |
cur = labelTable[ins.args[0]] - 1; | |
continue; | |
} | |
// call the handler | |
state.data.retval = handlers[ins.name](ins.args, state, ins.code); | |
} | |
} | |
return state.output; | |
} | |
let out = evaluate(parse(` | |
let god pootis | |
let name :god | |
goto main | |
ignored | |
main: | |
print hello :name | |
print %ln | |
print 1 + 1 = | |
add 1 1 | |
print %retval | |
`)); | |
console.log(out); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment