mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -08:00
refactor
This commit is contained in:
10
src/eval.js
10
src/eval.js
@@ -414,16 +414,6 @@ const assign_code = (modules, call) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const eval_tree = node => {
|
|
||||||
return eval_modules(
|
|
||||||
{
|
|
||||||
modules: {'': node},
|
|
||||||
sorted: ['']
|
|
||||||
}
|
|
||||||
).calltree
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------- Metacircular interpreter ---------------------------- */
|
/* ------------- Metacircular interpreter ---------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
87
test/test.js
87
test/test.js
@@ -1,6 +1,6 @@
|
|||||||
import {find_leaf, ancestry, find_node} from '../src/ast_utils.js'
|
import {find_leaf, ancestry, find_node} from '../src/ast_utils.js'
|
||||||
import {parse, print_debug_node} from '../src/parse_js.js'
|
import {parse, print_debug_node} from '../src/parse_js.js'
|
||||||
import {eval_tree, eval_frame, eval_modules} from '../src/eval.js'
|
import {eval_frame, eval_modules} from '../src/eval.js'
|
||||||
import {COMMANDS} from '../src/cmd.js'
|
import {COMMANDS} from '../src/cmd.js'
|
||||||
import {
|
import {
|
||||||
root_calltree_node,
|
root_calltree_node,
|
||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
test_only,
|
test_only,
|
||||||
assert_equal,
|
assert_equal,
|
||||||
stringify,
|
stringify,
|
||||||
|
eval_tree,
|
||||||
assert_code_evals_to, assert_code_evals_to_async,
|
assert_code_evals_to, assert_code_evals_to_async,
|
||||||
assert_code_error, assert_code_error_async,
|
assert_code_error, assert_code_error_async,
|
||||||
parse_modules,
|
parse_modules,
|
||||||
@@ -53,9 +54,7 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('empty program', () => {
|
test('empty program', () => {
|
||||||
const parse_result = parse('')
|
const tree = eval_tree('')
|
||||||
assert_equal(parse_result.ok, true)
|
|
||||||
const tree = eval_tree(parse_result.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children, [])
|
assert_equal(frame.children, [])
|
||||||
assert_equal(frame.result, {ok: true})
|
assert_equal(frame.result, {ok: true})
|
||||||
@@ -76,9 +75,7 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('Only semicolons', () => {
|
test('Only semicolons', () => {
|
||||||
const parse_result = parse(';;;;')
|
const tree = eval_tree(';;;;')
|
||||||
assert_equal(parse_result.ok, true)
|
|
||||||
const tree = eval_tree(parse_result.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children, [])
|
assert_equal(frame.children, [])
|
||||||
assert_equal(frame.result, {ok: true})
|
assert_equal(frame.result, {ok: true})
|
||||||
@@ -167,14 +164,13 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('closure', () => {
|
test('closure', () => {
|
||||||
const parsed = parse(
|
const tree = eval_tree(
|
||||||
`
|
`
|
||||||
const x = 1
|
const x = 1
|
||||||
const y = () => x;
|
const y = () => x;
|
||||||
y()
|
y()
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree.children[0])
|
const frame = eval_frame(tree.children[0])
|
||||||
assert_equal(frame.children[1].result.value, 1)
|
assert_equal(frame.children[1].result.value, 1)
|
||||||
}),
|
}),
|
||||||
@@ -362,30 +358,23 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('out of order decl', () => {
|
test('out of order decl', () => {
|
||||||
const code =
|
const tree = eval_tree( `
|
||||||
`
|
|
||||||
const y = () => x;
|
const y = () => x;
|
||||||
const x = 1;
|
const x = 1;
|
||||||
y();
|
y();
|
||||||
`
|
`)
|
||||||
const parsed = parse(code)
|
|
||||||
assert_equal(parsed.ok, true)
|
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(tree.children[0].value, 1)
|
assert_equal(tree.children[0].value, 1)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('nested closure', () => {
|
test('nested closure', () => {
|
||||||
const code =
|
assert_code_evals_to(
|
||||||
`
|
`
|
||||||
const x = () => () => y;
|
const x = () => () => y
|
||||||
x();
|
const y = 1
|
||||||
const y = 1;
|
x()()
|
||||||
`
|
`,
|
||||||
const parsed = parse(code)
|
1
|
||||||
assert_equal(parsed.ok, true)
|
)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(tree.ok, true)
|
|
||||||
// TODO assert
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('Simple expression ASI', () => {
|
test('Simple expression ASI', () => {
|
||||||
@@ -668,10 +657,9 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame binary', () => {
|
test('eval_frame binary', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
1 + 1
|
1 + 1
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree).children[0].result.value, 2)
|
assert_equal(eval_frame(tree).children[0].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -681,50 +669,44 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame grouping', () => {
|
test('eval_frame grouping', () => {
|
||||||
const parsed = parse('(1+1)')
|
const tree = eval_tree('(1+1)')
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree).children[0].result.value, 2)
|
assert_equal(eval_frame(tree).children[0].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame member_access', () => {
|
test('eval_frame member_access', () => {
|
||||||
const parsed = parse('{foo: "bar"}["foo"]')
|
const tree = eval_tree('{foo: "bar"}["foo"]')
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree).children[0].result.value, 'bar')
|
assert_equal(eval_frame(tree).children[0].result.value, 'bar')
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame new', () => {
|
test('eval_frame new', () => {
|
||||||
const parsed = parse('new Error("foobar")')
|
const tree = eval_tree('new Error("foobar")')
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree).children[0].result.value.message, 'foobar')
|
assert_equal(eval_frame(tree).children[0].result.value.message, 'foobar')
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame function_call', () => {
|
test('eval_frame function_call', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = () => 1;
|
const x = () => 1;
|
||||||
2 * x();
|
2 * x();
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree).children[1].result.value, 2)
|
assert_equal(eval_frame(tree).children[1].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame function_body_expr', () => {
|
test('eval_frame function_body_expr', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = y => y;
|
const x = y => y;
|
||||||
x(2);
|
x(2);
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
assert_equal(eval_frame(tree.children[0]).children[1].result, {ok: true, value: 2})
|
assert_equal(eval_frame(tree.children[0]).children[1].result, {ok: true, value: 2})
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame function_body_do', () => {
|
test('eval_frame function_body_do', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = y => {
|
const x = y => {
|
||||||
return y;
|
return y;
|
||||||
const z = 1;
|
const z = 1;
|
||||||
};
|
};
|
||||||
x(2);
|
x(2);
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree.children[0])
|
const frame = eval_frame(tree.children[0])
|
||||||
const ret = frame.children[1].children[0]
|
const ret = frame.children[1].children[0]
|
||||||
const z_after_ret = frame.children[1].children[1]
|
const z_after_ret = frame.children[1].children[1]
|
||||||
@@ -733,14 +715,13 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame if', () => {
|
test('eval_frame if', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
if(1) {
|
if(1) {
|
||||||
const x = 1;
|
const x = 1;
|
||||||
} else {
|
} else {
|
||||||
const x = 1;
|
const x = 1;
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
const _if = frame.children[0]
|
const _if = frame.children[0]
|
||||||
assert_equal(_if.children[0].result, {ok: true, value: 1})
|
assert_equal(_if.children[0].result, {ok: true, value: 1})
|
||||||
@@ -749,12 +730,11 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame if without else', () => {
|
test('eval_frame if without else', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
if(1) {
|
if(1) {
|
||||||
const x = 1;
|
const x = 1;
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
const _if = frame.children[0]
|
const _if = frame.children[0]
|
||||||
assert_equal(_if.children.length, 2)
|
assert_equal(_if.children.length, 2)
|
||||||
@@ -777,71 +757,64 @@ export const tests = [
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame error', () => {
|
test('eval_frame error', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = ({a}) => 0;
|
const x = ({a}) => 0;
|
||||||
x(null);
|
x(null);
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree.children[0])
|
const frame = eval_frame(tree.children[0])
|
||||||
assert_equal(frame.result, {ok: false})
|
assert_equal(frame.result, {ok: false})
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame binary &&', () => {
|
test('eval_frame binary &&', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = () => 1;
|
const x = () => 1;
|
||||||
const y = () => 2;
|
const y = () => 2;
|
||||||
false && x();
|
false && x();
|
||||||
y();
|
y();
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children[3].result.value, 2)
|
assert_equal(frame.children[3].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame binary ||', () => {
|
test('eval_frame binary ||', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = () => 1;
|
const x = () => 1;
|
||||||
const y = () => 2;
|
const y = () => 2;
|
||||||
true || x();
|
true || x();
|
||||||
y();
|
y();
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children[3].result.value, 2)
|
assert_equal(frame.children[3].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame binary ??', () => {
|
test('eval_frame binary ??', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = () => 1;
|
const x = () => 1;
|
||||||
const y = () => 2;
|
const y = () => 2;
|
||||||
1 ?? x();
|
1 ?? x();
|
||||||
y();
|
y();
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children[3].result.value, 2)
|
assert_equal(frame.children[3].result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame null call', () => {
|
test('eval_frame null call', () => {
|
||||||
const parsed = parse(`null()`)
|
const tree = eval_tree(`null()`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children[0].result.ok, false)
|
assert_equal(frame.children[0].result.ok, false)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame non-function call bug', () => {
|
test('eval_frame non-function call bug', () => {
|
||||||
const parsed = parse(`Object.assign({}, {}); null()`)
|
const tree = eval_tree(`Object.assign({}, {}); null()`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree)
|
const frame = eval_frame(tree)
|
||||||
assert_equal(frame.children[frame.children.length - 1].result.ok, false)
|
assert_equal(frame.children[frame.children.length - 1].result.ok, false)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('eval_frame destructuring args', () => {
|
test('eval_frame destructuring args', () => {
|
||||||
const parsed = parse(`
|
const tree = eval_tree(`
|
||||||
const x = (...a) => a;
|
const x = (...a) => a;
|
||||||
x(1,2,3);
|
x(1,2,3);
|
||||||
`)
|
`)
|
||||||
const tree = eval_tree(parsed.node)
|
|
||||||
const frame = eval_frame(tree.children[0])
|
const frame = eval_frame(tree.children[0])
|
||||||
assert_equal(frame.children[0].children[0].children[0].result.value, [1,2,3])
|
assert_equal(frame.children[0].children[0].children[0].result.value, [1,2,3])
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {print_debug_node, load_modules} from '../src/parse_js.js'
|
import {parse, print_debug_node, load_modules} from '../src/parse_js.js'
|
||||||
|
import {eval_modules} from '../src/eval.js'
|
||||||
import {active_frame, pp_calltree} from '../src/calltree.js'
|
import {active_frame, pp_calltree} from '../src/calltree.js'
|
||||||
import {COMMANDS} from '../src/cmd.js'
|
import {COMMANDS} from '../src/cmd.js'
|
||||||
|
|
||||||
@@ -48,6 +49,17 @@ export const original_setTimeout = globalThis.run_window.__original_setTimeout
|
|||||||
export const parse_modules = (entry, modules) =>
|
export const parse_modules = (entry, modules) =>
|
||||||
load_modules(entry, module_name => modules[module_name])
|
load_modules(entry, module_name => modules[module_name])
|
||||||
|
|
||||||
|
export const eval_tree = code => {
|
||||||
|
const parse_result = parse(code)
|
||||||
|
assert_equal(parse_result.ok, true)
|
||||||
|
return eval_modules(
|
||||||
|
{
|
||||||
|
modules: {'': parse_result.node},
|
||||||
|
sorted: ['']
|
||||||
|
}
|
||||||
|
).calltree
|
||||||
|
}
|
||||||
|
|
||||||
export const assert_code_evals_to = (codestring, expected) => {
|
export const assert_code_evals_to = (codestring, expected) => {
|
||||||
const s = test_initial_state(codestring)
|
const s = test_initial_state(codestring)
|
||||||
const frame = active_frame(s)
|
const frame = active_frame(s)
|
||||||
|
|||||||
Reference in New Issue
Block a user