bare return statements

This commit is contained in:
Dmitry Vasilev
2024-02-02 03:13:21 +08:00
parent e94eee537e
commit e1f7dd437c
4 changed files with 54 additions and 13 deletions

View File

@@ -624,7 +624,12 @@ const get_stmt_value_explorer = (state, stmt) => {
if(stmt.result.ok) { if(stmt.result.ok) {
if(stmt.type == 'return') { 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)) { } else if(['let', 'const', 'assignment'].includes(stmt.type)) {
if(stmt.children.find(c => c.type == 'assignment_pair') != null) { if(stmt.children.find(c => c.type == 'assignment_pair') != null) {

View File

@@ -192,7 +192,11 @@ const codegen = (node, node_cxt) => {
'' ''
) )
} else if(node.type == 'return') { } 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') { } else if(node.type == 'throw') {
return 'throw ' + do_codegen(node.expr) + ';' return 'throw ' + do_codegen(node.expr) + ';'
} else if(node.type == 'if') { } else if(node.type == 'if') {
@@ -1278,6 +1282,15 @@ const eval_statement = (s, eval_cxt, frame_cxt) => {
} }
} else if(s.type == 'return') { } 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} = const {node, eval_cxt: next_eval_cxt} =
eval_frame_expr(s.expr, eval_cxt, frame_cxt) eval_frame_expr(s.expr, eval_cxt, frame_cxt)

View File

@@ -1225,15 +1225,10 @@ const assignment = if_ok(
) )
const return_statement = const return_statement = either(
// return expr
if_ok( if_ok(
seq_select(1, [ 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( not_followed_by(
literal('return'), literal('return'),
newline, newline,
@@ -1245,7 +1240,19 @@ const return_statement =
type: 'return', type: 'return',
children: [value], children: [value],
}) })
) ),
// bare return statement
if_ok(
literal('return'),
node => ({
...node,
type: 'return',
children: [],
value: null,
})
),
)
const if_branch = if_ok( const if_branch = if_ok(
seq_select(1, [ seq_select(1, [

View File

@@ -487,14 +487,13 @@ export const tests = [
) )
}), }),
test('ASI_restrited', () => { test('ASI_restricted', () => {
// Currently we forbid bare return statement, TODO
assert_equal( assert_equal(
do_parse(` do_parse(`
return return
1 1
`).ok, `).ok,
false true
) )
assert_equal( assert_equal(
do_parse(` do_parse(`
@@ -945,6 +944,23 @@ export const tests = [
assert_equal(x.result.version_number, 0) 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', () => { test('array spread not iterable', () => {
assert_code_error( assert_code_error(
`[...null]`, `[...null]`,