complete compilation.
also rename misleading names "execution" to "compilation".
This commit is contained in:
parent
9a5597813c
commit
64a01d4abf
|
@ -0,0 +1,113 @@
|
|||
import Line from "./Line.mjs";
|
||||
import Expr from "./Expr.mjs";
|
||||
|
||||
|
||||
|
||||
export function compile (program) {
|
||||
let env = new Map();
|
||||
|
||||
for (const line of program) {
|
||||
const result = compile_line(env, line);
|
||||
|
||||
if (!result.valid) {
|
||||
return {
|
||||
valid: false,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
env = result.env;
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
function compile_line (env, line) {
|
||||
function invalid (current_env = env) {
|
||||
return {
|
||||
valid: false,
|
||||
env: current_env,
|
||||
};
|
||||
}
|
||||
|
||||
if (line.type === Line.Invalid) return invalid();
|
||||
|
||||
if (line.type === Line.Empty || line.type === Line.Comment) {
|
||||
return {
|
||||
valid: true,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
if (line.type === Line.Special) {
|
||||
// as there are currently no reserved special lines,
|
||||
// and this implementation adds no custom ones,
|
||||
// every special line is invalid.
|
||||
return invalid();
|
||||
}
|
||||
|
||||
if (line.type === Line.Binding) {
|
||||
let value;
|
||||
let valid = true;
|
||||
|
||||
try {
|
||||
value = evaluate(env, line.body);
|
||||
} catch (e) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid) return invalid();
|
||||
|
||||
const new_env = new Map(env);
|
||||
new_env.set(line.name, value);
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
env: new_env,
|
||||
};
|
||||
}
|
||||
|
||||
return invalid();
|
||||
}
|
||||
|
||||
function evaluate (env, expr, locals = []) {
|
||||
if (expr.type === Expr.Token) {
|
||||
const token = expr.value;
|
||||
|
||||
if (has_local(locals, token)) {
|
||||
return get_local(locals, token);
|
||||
}
|
||||
|
||||
if (env.has(token)) {
|
||||
return env.get(token);
|
||||
}
|
||||
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (expr.type === Expr.Application) {
|
||||
const fn = evaluate(env, expr.fn, locals);
|
||||
const arg = evaluate(env, expr.arg, locals);
|
||||
return([fn, arg]);
|
||||
}
|
||||
|
||||
if (expr.type === Expr.Fn) {
|
||||
const args = [ ...expr.args ].reverse();
|
||||
const body = evaluate(env, expr.body, args);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
function has_local (locals, name) {
|
||||
return locals.includes(name);
|
||||
}
|
||||
|
||||
function get_local (locals, name) {
|
||||
return locals.indexOf(name);
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
import Line from "./Line.mjs";
|
||||
|
||||
|
||||
|
||||
export function execute (program) {
|
||||
let env = new Map();
|
||||
|
||||
for (const line of program) {
|
||||
const result = execute_line(env, line);
|
||||
|
||||
if (!result.valid) {
|
||||
return {
|
||||
valid: false,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
env = result.env;
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
function execute_line (env, line) {
|
||||
function invalid () {
|
||||
return {
|
||||
valid: false,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
if (line.type === Line.Invalid) return invalid();
|
||||
|
||||
if (line.type === Line.Empty || line.type === Line.Comment) {
|
||||
return {
|
||||
valid: true,
|
||||
env: env,
|
||||
};
|
||||
}
|
||||
|
||||
if (line.type === Line.Special) {
|
||||
// as there are currently no reserved special lines,
|
||||
// and this implementation adds no custom ones,
|
||||
// every special line is invalid.
|
||||
return invalid();
|
||||
}
|
||||
|
||||
if (line.type === Line.Binding) {
|
||||
const new_env = new Map(env);
|
||||
new_env.set(line.name, evaluate(env, line.body));
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
env: new_env,
|
||||
};
|
||||
}
|
||||
|
||||
return invalid();
|
||||
}
|
||||
|
||||
function evaluate (env, expr) {
|
||||
return expr;
|
||||
}
|
Loading…
Reference in New Issue