mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
bare return statements
This commit is contained in:
@@ -624,7 +624,12 @@ const get_stmt_value_explorer = (state, stmt) => {
|
||||
|
||||
if(stmt.result.ok) {
|
||||
if(stmt.type == 'return') {
|
||||
result = stmt.children[0].result
|
||||
if(stmt.expr == null) {
|
||||
// add fake version number
|
||||
result = {ok: true, value: undefined, version_number: 0}
|
||||
} else {
|
||||
result = stmt.children[0].result
|
||||
}
|
||||
} else if(['let', 'const', 'assignment'].includes(stmt.type)) {
|
||||
|
||||
if(stmt.children.find(c => c.type == 'assignment_pair') != null) {
|
||||
|
||||
15
src/eval.js
15
src/eval.js
@@ -192,7 +192,11 @@ const codegen = (node, node_cxt) => {
|
||||
''
|
||||
)
|
||||
} else if(node.type == 'return') {
|
||||
return 'return ' + do_codegen(node.expr) + ';'
|
||||
if(node.expr == null) {
|
||||
return 'return ;'
|
||||
} else {
|
||||
return 'return ' + do_codegen(node.expr) + ';'
|
||||
}
|
||||
} else if(node.type == 'throw') {
|
||||
return 'throw ' + do_codegen(node.expr) + ';'
|
||||
} else if(node.type == 'if') {
|
||||
@@ -1278,6 +1282,15 @@ const eval_statement = (s, eval_cxt, frame_cxt) => {
|
||||
}
|
||||
} else if(s.type == 'return') {
|
||||
|
||||
if(s.expr == null) {
|
||||
return {
|
||||
ok: true,
|
||||
returned: true,
|
||||
node: {...s, result: {ok: true}},
|
||||
eval_cxt,
|
||||
}
|
||||
}
|
||||
|
||||
const {node, eval_cxt: next_eval_cxt} =
|
||||
eval_frame_expr(s.expr, eval_cxt, frame_cxt)
|
||||
|
||||
|
||||
@@ -1225,15 +1225,10 @@ const assignment = if_ok(
|
||||
)
|
||||
|
||||
|
||||
const return_statement =
|
||||
const return_statement = either(
|
||||
// return expr
|
||||
if_ok(
|
||||
seq_select(1, [
|
||||
|
||||
// We forbid bare return statement
|
||||
// TODO bare return statement
|
||||
// TODO implement bare return statement compatible with ASI
|
||||
// see https://riptutorial.com/javascript/example/15248/rules-of-automatic-semicolon-insertion
|
||||
// see ASI_restrited unit test
|
||||
not_followed_by(
|
||||
literal('return'),
|
||||
newline,
|
||||
@@ -1245,7 +1240,19 @@ const return_statement =
|
||||
type: 'return',
|
||||
children: [value],
|
||||
})
|
||||
)
|
||||
),
|
||||
|
||||
// bare return statement
|
||||
if_ok(
|
||||
literal('return'),
|
||||
node => ({
|
||||
...node,
|
||||
type: 'return',
|
||||
children: [],
|
||||
value: null,
|
||||
})
|
||||
),
|
||||
)
|
||||
|
||||
const if_branch = if_ok(
|
||||
seq_select(1, [
|
||||
|
||||
22
test/test.js
22
test/test.js
@@ -487,14 +487,13 @@ export const tests = [
|
||||
)
|
||||
}),
|
||||
|
||||
test('ASI_restrited', () => {
|
||||
// Currently we forbid bare return statement, TODO
|
||||
test('ASI_restricted', () => {
|
||||
assert_equal(
|
||||
do_parse(`
|
||||
return
|
||||
1
|
||||
`).ok,
|
||||
false
|
||||
true
|
||||
)
|
||||
assert_equal(
|
||||
do_parse(`
|
||||
@@ -945,6 +944,23 @@ export const tests = [
|
||||
assert_equal(x.result.version_number, 0)
|
||||
}),
|
||||
|
||||
test('bare return statement', () => {
|
||||
const code = `
|
||||
function test() {
|
||||
return
|
||||
}
|
||||
test() /*call*/
|
||||
`
|
||||
assert_value_explorer(
|
||||
test_initial_state(code, code.indexOf('test() /*call*/')),
|
||||
undefined,
|
||||
)
|
||||
assert_value_explorer(
|
||||
test_initial_state(code, code.indexOf('return')),
|
||||
undefined,
|
||||
)
|
||||
}),
|
||||
|
||||
test('array spread not iterable', () => {
|
||||
assert_code_error(
|
||||
`[...null]`,
|
||||
|
||||
Reference in New Issue
Block a user