Merge branch 'mach' into mqbe
This commit is contained in:
1
mcode.ce
1
mcode.ce
@@ -1,4 +1,5 @@
|
|||||||
var fd = use("fd")
|
var fd = use("fd")
|
||||||
|
var json = use("json")
|
||||||
var tokenize = use("tokenize")
|
var tokenize = use("tokenize")
|
||||||
var parse = use("parse")
|
var parse = use("parse")
|
||||||
var mcode = use("mcode")
|
var mcode = use("mcode")
|
||||||
|
|||||||
352
mcode.cm
352
mcode.cm
@@ -1142,31 +1142,87 @@ var mcode = function(ast) {
|
|||||||
|
|
||||||
// Statement compilation
|
// Statement compilation
|
||||||
gen_statement = function(stmt) {
|
gen_statement = function(stmt) {
|
||||||
|
var kind = null
|
||||||
|
var left = null
|
||||||
|
var right = null
|
||||||
|
var name = null
|
||||||
|
var local_slot = 0
|
||||||
|
var arr_expr = null
|
||||||
|
var arr_slot = 0
|
||||||
|
var val_slot = 0
|
||||||
|
var list = null
|
||||||
|
var _i = 0
|
||||||
|
var stmts = null
|
||||||
|
var cond = null
|
||||||
|
var then_stmts = null
|
||||||
|
var else_stmts = null
|
||||||
|
var else_label = null
|
||||||
|
var end_label = null
|
||||||
|
var cond_slot = 0
|
||||||
|
var start_label = null
|
||||||
|
var old_break = null
|
||||||
|
var old_continue = null
|
||||||
|
var cond_label = null
|
||||||
|
var init = null
|
||||||
|
var test = null
|
||||||
|
var update = null
|
||||||
|
var update_label = null
|
||||||
|
var init_kind = null
|
||||||
|
var test_slot = 0
|
||||||
|
var expr = null
|
||||||
|
var slot = 0
|
||||||
|
var null_slot = 0
|
||||||
|
var call_expr = null
|
||||||
|
var callee = null
|
||||||
|
var args_list = null
|
||||||
|
var arg_slots = null
|
||||||
|
var nargs = 0
|
||||||
|
var callee_kind = null
|
||||||
|
var obj_node = null
|
||||||
|
var prop = null
|
||||||
|
var obj_slot = 0
|
||||||
|
var func_slot = 0
|
||||||
|
var cases = null
|
||||||
|
var switch_val = 0
|
||||||
|
var default_label = null
|
||||||
|
var case_labels = null
|
||||||
|
var case_node = null
|
||||||
|
var case_kind = null
|
||||||
|
var case_label = null
|
||||||
|
var case_expr = null
|
||||||
|
var case_val = 0
|
||||||
|
var cmp_slot = 0
|
||||||
|
var case_stmts = null
|
||||||
|
var _j = 0
|
||||||
|
var func = null
|
||||||
|
var func_id = 0
|
||||||
|
var dest = 0
|
||||||
|
|
||||||
if (stmt == null) {
|
if (stmt == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
set_pos(stmt)
|
set_pos(stmt)
|
||||||
var kind = stmt.kind
|
kind = stmt.kind
|
||||||
if (kind == null) {
|
if (kind == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "var" || kind == "def") {
|
if (kind == "var" || kind == "def") {
|
||||||
var left = stmt.left
|
left = stmt.left
|
||||||
var right = stmt.right
|
right = stmt.right
|
||||||
var name = left.name
|
name = left.name
|
||||||
var local_slot = find_var(name)
|
local_slot = find_var(name)
|
||||||
// Pop: var val = arr[]
|
// Pop: var val = arr[]
|
||||||
if (stmt.pop == true && right != null) {
|
if (stmt.pop == true && right != null) {
|
||||||
var arr_expr = right.left
|
arr_expr = right.left
|
||||||
var arr_slot = gen_expr(arr_expr, -1)
|
arr_slot = gen_expr(arr_expr, -1)
|
||||||
if (local_slot >= 0) {
|
if (local_slot >= 0) {
|
||||||
emit_2("pop", local_slot, arr_slot)
|
emit_2("pop", local_slot, arr_slot)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
var val_slot = gen_expr(right, local_slot)
|
val_slot = gen_expr(right, local_slot)
|
||||||
if (local_slot >= 0 && val_slot != local_slot) {
|
if (local_slot >= 0 && val_slot != local_slot) {
|
||||||
emit_2("move", local_slot, val_slot)
|
emit_2("move", local_slot, val_slot)
|
||||||
}
|
}
|
||||||
@@ -1177,8 +1233,8 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "var_list" || kind == "def_list") {
|
if (kind == "var_list" || kind == "def_list") {
|
||||||
var list = stmt.list
|
list = stmt.list
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(list)) {
|
while (_i < length(list)) {
|
||||||
gen_statement(list[_i])
|
gen_statement(list[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
@@ -1187,8 +1243,8 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "block") {
|
if (kind == "block") {
|
||||||
var stmts = stmt.statements
|
stmts = stmt.statements
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(stmts)) {
|
while (_i < length(stmts)) {
|
||||||
gen_statement(stmts[_i])
|
gen_statement(stmts[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
@@ -1197,17 +1253,17 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "if") {
|
if (kind == "if") {
|
||||||
var cond = stmt.expression
|
cond = stmt.expression
|
||||||
var then_stmts = stmt.then
|
then_stmts = stmt.then
|
||||||
var else_stmts = stmt["else"]
|
else_stmts = stmt["else"]
|
||||||
if (else_stmts == null) {
|
if (else_stmts == null) {
|
||||||
else_stmts = stmt.list
|
else_stmts = stmt.list
|
||||||
}
|
}
|
||||||
var else_label = gen_label("if_else")
|
else_label = gen_label("if_else")
|
||||||
var end_label = gen_label("if_end")
|
end_label = gen_label("if_end")
|
||||||
var cond_slot = gen_expr(cond, -1)
|
cond_slot = gen_expr(cond, -1)
|
||||||
emit_jump_cond("jump_false", cond_slot, else_label)
|
emit_jump_cond("jump_false", cond_slot, else_label)
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(then_stmts)) {
|
while (_i < length(then_stmts)) {
|
||||||
gen_statement(then_stmts[_i])
|
gen_statement(then_stmts[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
@@ -1226,18 +1282,18 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "while") {
|
if (kind == "while") {
|
||||||
var cond = stmt.expression
|
cond = stmt.expression
|
||||||
var stmts = stmt.statements
|
stmts = stmt.statements
|
||||||
var start_label = gen_label("while_start")
|
start_label = gen_label("while_start")
|
||||||
var end_label = gen_label("while_end")
|
end_label = gen_label("while_end")
|
||||||
var old_break = s_loop_break
|
old_break = s_loop_break
|
||||||
var old_continue = s_loop_continue
|
old_continue = s_loop_continue
|
||||||
s_loop_break = end_label
|
s_loop_break = end_label
|
||||||
s_loop_continue = start_label
|
s_loop_continue = start_label
|
||||||
emit_label(start_label)
|
emit_label(start_label)
|
||||||
var cond_slot = gen_expr(cond, -1)
|
cond_slot = gen_expr(cond, -1)
|
||||||
emit_jump_cond("jump_false", cond_slot, end_label)
|
emit_jump_cond("jump_false", cond_slot, end_label)
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(stmts)) {
|
while (_i < length(stmts)) {
|
||||||
gen_statement(stmts[_i])
|
gen_statement(stmts[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
@@ -1250,23 +1306,23 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "do") {
|
if (kind == "do") {
|
||||||
var cond = stmt.expression
|
cond = stmt.expression
|
||||||
var stmts = stmt.statements
|
stmts = stmt.statements
|
||||||
var start_label = gen_label("do_start")
|
start_label = gen_label("do_start")
|
||||||
var cond_label = gen_label("do_cond")
|
cond_label = gen_label("do_cond")
|
||||||
var end_label = gen_label("do_end")
|
end_label = gen_label("do_end")
|
||||||
var old_break = s_loop_break
|
old_break = s_loop_break
|
||||||
var old_continue = s_loop_continue
|
old_continue = s_loop_continue
|
||||||
s_loop_break = end_label
|
s_loop_break = end_label
|
||||||
s_loop_continue = cond_label
|
s_loop_continue = cond_label
|
||||||
emit_label(start_label)
|
emit_label(start_label)
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(stmts)) {
|
while (_i < length(stmts)) {
|
||||||
gen_statement(stmts[_i])
|
gen_statement(stmts[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
}
|
}
|
||||||
emit_label(cond_label)
|
emit_label(cond_label)
|
||||||
var cond_slot = gen_expr(cond, -1)
|
cond_slot = gen_expr(cond, -1)
|
||||||
emit_jump_cond("jump_true", cond_slot, start_label)
|
emit_jump_cond("jump_true", cond_slot, start_label)
|
||||||
emit_label(end_label)
|
emit_label(end_label)
|
||||||
s_loop_break = old_break
|
s_loop_break = old_break
|
||||||
@@ -1275,19 +1331,19 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "for") {
|
if (kind == "for") {
|
||||||
var init = stmt.init
|
init = stmt.init
|
||||||
var test = stmt.test
|
test = stmt.test
|
||||||
var update = stmt.update
|
update = stmt.update
|
||||||
var stmts = stmt.statements
|
stmts = stmt.statements
|
||||||
var start_label = gen_label("for_start")
|
start_label = gen_label("for_start")
|
||||||
var update_label = gen_label("for_update")
|
update_label = gen_label("for_update")
|
||||||
var end_label = gen_label("for_end")
|
end_label = gen_label("for_end")
|
||||||
var old_break = s_loop_break
|
old_break = s_loop_break
|
||||||
var old_continue = s_loop_continue
|
old_continue = s_loop_continue
|
||||||
s_loop_break = end_label
|
s_loop_break = end_label
|
||||||
s_loop_continue = update_label
|
s_loop_continue = update_label
|
||||||
if (init != null) {
|
if (init != null) {
|
||||||
var init_kind = init.kind
|
init_kind = init.kind
|
||||||
if (init_kind == "var" || init_kind == "def") {
|
if (init_kind == "var" || init_kind == "def") {
|
||||||
gen_statement(init)
|
gen_statement(init)
|
||||||
} else {
|
} else {
|
||||||
@@ -1296,10 +1352,10 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
emit_label(start_label)
|
emit_label(start_label)
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
var test_slot = gen_expr(test, -1)
|
test_slot = gen_expr(test, -1)
|
||||||
emit_jump_cond("jump_false", test_slot, end_label)
|
emit_jump_cond("jump_false", test_slot, end_label)
|
||||||
}
|
}
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(stmts)) {
|
while (_i < length(stmts)) {
|
||||||
gen_statement(stmts[_i])
|
gen_statement(stmts[_i])
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
@@ -1316,12 +1372,12 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "return") {
|
if (kind == "return") {
|
||||||
var expr = stmt.expression
|
expr = stmt.expression
|
||||||
if (expr != null) {
|
if (expr != null) {
|
||||||
var slot = gen_expr(expr, -1)
|
slot = gen_expr(expr, -1)
|
||||||
emit_1("return", slot)
|
emit_1("return", slot)
|
||||||
} else {
|
} else {
|
||||||
var null_slot = alloc_slot()
|
null_slot = alloc_slot()
|
||||||
emit_1("null", null_slot)
|
emit_1("null", null_slot)
|
||||||
emit_1("return", null_slot)
|
emit_1("return", null_slot)
|
||||||
}
|
}
|
||||||
@@ -1329,27 +1385,27 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "go") {
|
if (kind == "go") {
|
||||||
var call_expr = stmt.expression
|
call_expr = stmt.expression
|
||||||
if (call_expr == null || call_expr.kind != "(") {
|
if (call_expr == null || call_expr.kind != "(") {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
var callee = call_expr.expression
|
callee = call_expr.expression
|
||||||
var args_list = call_expr.list
|
args_list = call_expr.list
|
||||||
var arg_slots = []
|
arg_slots = []
|
||||||
var _i = 0
|
_i = 0
|
||||||
var nargs = args_list != null ? length(args_list) : 0
|
nargs = args_list != null ? length(args_list) : 0
|
||||||
while (_i < nargs) {
|
while (_i < nargs) {
|
||||||
push(arg_slots, gen_expr(args_list[_i], -1))
|
push(arg_slots, gen_expr(args_list[_i], -1))
|
||||||
_i = _i + 1
|
_i = _i + 1
|
||||||
}
|
}
|
||||||
var callee_kind = callee.kind
|
callee_kind = callee.kind
|
||||||
if (callee_kind == ".") {
|
if (callee_kind == ".") {
|
||||||
var obj_node = callee.left
|
obj_node = callee.left
|
||||||
var prop = callee.right
|
prop = callee.right
|
||||||
var obj_slot = gen_expr(obj_node, -1)
|
obj_slot = gen_expr(obj_node, -1)
|
||||||
emit_go_call_method(obj_slot, prop, arg_slots)
|
emit_go_call_method(obj_slot, prop, arg_slots)
|
||||||
} else {
|
} else {
|
||||||
var func_slot = gen_expr(callee, -1)
|
func_slot = gen_expr(callee, -1)
|
||||||
emit_go_call(func_slot, arg_slots)
|
emit_go_call(func_slot, arg_slots)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -1375,27 +1431,27 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "switch") {
|
if (kind == "switch") {
|
||||||
var expr = stmt.expression
|
expr = stmt.expression
|
||||||
var cases = stmt.cases
|
cases = stmt.cases
|
||||||
var switch_val = gen_expr(expr, -1)
|
switch_val = gen_expr(expr, -1)
|
||||||
var end_label = gen_label("switch_end")
|
end_label = gen_label("switch_end")
|
||||||
var default_label = null
|
default_label = null
|
||||||
var old_break = s_loop_break
|
old_break = s_loop_break
|
||||||
s_loop_break = end_label
|
s_loop_break = end_label
|
||||||
// Phase 1: emit comparisons, collect labels
|
// Phase 1: emit comparisons, collect labels
|
||||||
var case_labels = []
|
case_labels = []
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(cases)) {
|
while (_i < length(cases)) {
|
||||||
var case_node = cases[_i]
|
case_node = cases[_i]
|
||||||
var case_kind = case_node.kind
|
case_kind = case_node.kind
|
||||||
if (case_kind == "default") {
|
if (case_kind == "default") {
|
||||||
default_label = gen_label("switch_default")
|
default_label = gen_label("switch_default")
|
||||||
push(case_labels, default_label)
|
push(case_labels, default_label)
|
||||||
} else {
|
} else {
|
||||||
var case_label = gen_label("switch_case")
|
case_label = gen_label("switch_case")
|
||||||
var case_expr = case_node.expression
|
case_expr = case_node.expression
|
||||||
var case_val = gen_expr(case_expr, -1)
|
case_val = gen_expr(case_expr, -1)
|
||||||
var cmp_slot = alloc_slot()
|
cmp_slot = alloc_slot()
|
||||||
emit_3("eq", cmp_slot, switch_val, case_val)
|
emit_3("eq", cmp_slot, switch_val, case_val)
|
||||||
emit_jump_cond("jump_true", cmp_slot, case_label)
|
emit_jump_cond("jump_true", cmp_slot, case_label)
|
||||||
push(case_labels, case_label)
|
push(case_labels, case_label)
|
||||||
@@ -1411,8 +1467,8 @@ var mcode = function(ast) {
|
|||||||
_i = 0
|
_i = 0
|
||||||
while (_i < length(cases)) {
|
while (_i < length(cases)) {
|
||||||
emit_label(case_labels[_i])
|
emit_label(case_labels[_i])
|
||||||
var case_stmts = cases[_i].statements
|
case_stmts = cases[_i].statements
|
||||||
var _j = 0
|
_j = 0
|
||||||
while (_j < length(case_stmts)) {
|
while (_j < length(case_stmts)) {
|
||||||
gen_statement(case_stmts[_j])
|
gen_statement(case_stmts[_j])
|
||||||
_j = _j + 1
|
_j = _j + 1
|
||||||
@@ -1425,14 +1481,14 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kind == "function") {
|
if (kind == "function") {
|
||||||
var name = stmt.name
|
name = stmt.name
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
var func = gen_function(stmt)
|
func = gen_function(stmt)
|
||||||
var func_id = s_func_counter
|
func_id = s_func_counter
|
||||||
s_func_counter = s_func_counter + 1
|
s_func_counter = s_func_counter + 1
|
||||||
push(s_functions, func)
|
push(s_functions, func)
|
||||||
var local_slot = find_var(name)
|
local_slot = find_var(name)
|
||||||
var dest = alloc_slot()
|
dest = alloc_slot()
|
||||||
emit_2("function", dest, func_id)
|
emit_2("function", dest, func_id)
|
||||||
if (local_slot >= 0) {
|
if (local_slot >= 0) {
|
||||||
emit_2("move", local_slot, dest)
|
emit_2("move", local_slot, dest)
|
||||||
@@ -1453,6 +1509,38 @@ var mcode = function(ast) {
|
|||||||
// Function compilation
|
// Function compilation
|
||||||
gen_function = function(func_node) {
|
gen_function = function(func_node) {
|
||||||
var saved = save_state()
|
var saved = save_state()
|
||||||
|
var is_arrow = func_node.arrow == true
|
||||||
|
var fn_nr_node = func_node.function_nr
|
||||||
|
var params = func_node.list
|
||||||
|
var nr_params = 0
|
||||||
|
var param_slot = 1
|
||||||
|
var _i = 0
|
||||||
|
var param = null
|
||||||
|
var param_name = null
|
||||||
|
var ps = 1
|
||||||
|
var default_expr = null
|
||||||
|
var end_label = null
|
||||||
|
var default_slot = 0
|
||||||
|
var hoisted = null
|
||||||
|
var fn = null
|
||||||
|
var fname = null
|
||||||
|
var compiled = null
|
||||||
|
var func_id = 0
|
||||||
|
var local_slot = 0
|
||||||
|
var dest = 0
|
||||||
|
var stmts = null
|
||||||
|
var body = null
|
||||||
|
var null_slot = 0
|
||||||
|
var disruption_start = 0
|
||||||
|
var disrupt_clause = func_node.disruption
|
||||||
|
var null_slot2 = null
|
||||||
|
var fn_name = func_node.name
|
||||||
|
var fn_scope = null
|
||||||
|
var nr_cs = 0
|
||||||
|
var result = null
|
||||||
|
var saved_label = 0
|
||||||
|
var saved_func = 0
|
||||||
|
|
||||||
push(parent_states, saved)
|
push(parent_states, saved)
|
||||||
|
|
||||||
s_instructions = []
|
s_instructions = []
|
||||||
@@ -1461,28 +1549,25 @@ var mcode = function(ast) {
|
|||||||
s_loop_break = null
|
s_loop_break = null
|
||||||
s_loop_continue = null
|
s_loop_continue = null
|
||||||
|
|
||||||
var is_arrow = func_node.arrow == true
|
|
||||||
s_is_arrow = is_arrow
|
s_is_arrow = is_arrow
|
||||||
|
|
||||||
var fn_nr_node = func_node.function_nr
|
|
||||||
s_function_nr = fn_nr_node != null ? fn_nr_node : 0
|
s_function_nr = fn_nr_node != null ? fn_nr_node : 0
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
var params = func_node.list
|
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
params = func_node.parameters
|
params = func_node.parameters
|
||||||
}
|
}
|
||||||
var nr_params = params != null ? length(params) : 0
|
nr_params = params != null ? length(params) : 0
|
||||||
s_nr_args = nr_params
|
s_nr_args = nr_params
|
||||||
s_this_slot = 0
|
s_this_slot = 0
|
||||||
s_nr_close_slots = 0
|
s_nr_close_slots = 0
|
||||||
s_nr_local_slots = 0
|
s_nr_local_slots = 0
|
||||||
|
|
||||||
var param_slot = 1
|
param_slot = 1
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < nr_params) {
|
while (_i < nr_params) {
|
||||||
var param = params[_i]
|
param = params[_i]
|
||||||
var param_name = param.name
|
param_name = param.name
|
||||||
if (param_name == null && is_text(param)) {
|
if (param_name == null && is_text(param)) {
|
||||||
param_name = param
|
param_name = param
|
||||||
}
|
}
|
||||||
@@ -1505,15 +1590,15 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default parameter initialization
|
// Default parameter initialization
|
||||||
var ps = 1
|
ps = 1
|
||||||
_i = 0
|
_i = 0
|
||||||
while (_i < nr_params) {
|
while (_i < nr_params) {
|
||||||
var param = params[_i]
|
param = params[_i]
|
||||||
var default_expr = param.expression
|
default_expr = param.expression
|
||||||
if (default_expr != null) {
|
if (default_expr != null) {
|
||||||
var end_label = gen_label("default_end")
|
end_label = gen_label("default_end")
|
||||||
emit_jump_cond("jump_not_null", ps, end_label)
|
emit_jump_cond("jump_not_null", ps, end_label)
|
||||||
var default_slot = gen_expr(default_expr, -1)
|
default_slot = gen_expr(default_expr, -1)
|
||||||
emit_2("move", ps, default_slot)
|
emit_2("move", ps, default_slot)
|
||||||
emit_label(end_label)
|
emit_label(end_label)
|
||||||
}
|
}
|
||||||
@@ -1525,19 +1610,19 @@ var mcode = function(ast) {
|
|||||||
load_intrinsics(func_node.intrinsics)
|
load_intrinsics(func_node.intrinsics)
|
||||||
|
|
||||||
// Compile hoisted function declarations
|
// Compile hoisted function declarations
|
||||||
var hoisted = func_node.functions
|
hoisted = func_node.functions
|
||||||
if (hoisted != null) {
|
if (hoisted != null) {
|
||||||
_i = 0
|
_i = 0
|
||||||
while (_i < length(hoisted)) {
|
while (_i < length(hoisted)) {
|
||||||
var fn = hoisted[_i]
|
fn = hoisted[_i]
|
||||||
var fname = fn.name
|
fname = fn.name
|
||||||
if (fname != null) {
|
if (fname != null) {
|
||||||
var compiled = gen_function(fn)
|
compiled = gen_function(fn)
|
||||||
var func_id = s_func_counter
|
func_id = s_func_counter
|
||||||
s_func_counter = s_func_counter + 1
|
s_func_counter = s_func_counter + 1
|
||||||
push(s_functions, compiled)
|
push(s_functions, compiled)
|
||||||
var local_slot = find_var(fname)
|
local_slot = find_var(fname)
|
||||||
var dest = alloc_slot()
|
dest = alloc_slot()
|
||||||
emit_2("function", dest, func_id)
|
emit_2("function", dest, func_id)
|
||||||
if (local_slot >= 0) {
|
if (local_slot >= 0) {
|
||||||
emit_2("move", local_slot, dest)
|
emit_2("move", local_slot, dest)
|
||||||
@@ -1548,9 +1633,9 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile body
|
// Compile body
|
||||||
var stmts = func_node.statements
|
stmts = func_node.statements
|
||||||
if (stmts == null) {
|
if (stmts == null) {
|
||||||
var body = func_node.body
|
body = func_node.body
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
stmts = body.statements
|
stmts = body.statements
|
||||||
if (stmts == null) {
|
if (stmts == null) {
|
||||||
@@ -1567,14 +1652,11 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implicit return null
|
// Implicit return null
|
||||||
var null_slot = alloc_slot()
|
null_slot = alloc_slot()
|
||||||
emit_1("null", null_slot)
|
emit_1("null", null_slot)
|
||||||
emit_1("return", null_slot)
|
emit_1("return", null_slot)
|
||||||
|
|
||||||
// Compile disruption clause
|
// Compile disruption clause
|
||||||
var disruption_start = 0
|
|
||||||
var disrupt_clause = func_node.disruption
|
|
||||||
var null_slot2 = null
|
|
||||||
if (disrupt_clause != null && is_array(disrupt_clause)) {
|
if (disrupt_clause != null && is_array(disrupt_clause)) {
|
||||||
disruption_start = length(s_instructions)
|
disruption_start = length(s_instructions)
|
||||||
_i = 0
|
_i = 0
|
||||||
@@ -1588,18 +1670,16 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build result
|
// Build result
|
||||||
var fn_name = func_node.name
|
|
||||||
if (fn_name == null) {
|
if (fn_name == null) {
|
||||||
fn_name = "<anonymous>"
|
fn_name = "<anonymous>"
|
||||||
}
|
}
|
||||||
|
|
||||||
var fn_scope = find_scope_record(s_function_nr)
|
fn_scope = find_scope_record(s_function_nr)
|
||||||
var nr_cs = 0
|
|
||||||
if (fn_scope != null && fn_scope.nr_close_slots != null) {
|
if (fn_scope != null && fn_scope.nr_close_slots != null) {
|
||||||
nr_cs = fn_scope.nr_close_slots
|
nr_cs = fn_scope.nr_close_slots
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = {
|
result = {
|
||||||
name: fn_name,
|
name: fn_name,
|
||||||
nr_args: nr_params,
|
nr_args: nr_params,
|
||||||
nr_close_slots: nr_cs,
|
nr_close_slots: nr_cs,
|
||||||
@@ -1613,8 +1693,8 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Propagate counters back
|
// Propagate counters back
|
||||||
var saved_label = s_label_counter
|
saved_label = s_label_counter
|
||||||
var saved_func = s_func_counter
|
saved_func = s_func_counter
|
||||||
|
|
||||||
// Pop parent state
|
// Pop parent state
|
||||||
pop(parent_states)
|
pop(parent_states)
|
||||||
@@ -1628,6 +1708,21 @@ var mcode = function(ast) {
|
|||||||
// Program compilation (top-level entry)
|
// Program compilation (top-level entry)
|
||||||
var gen_program = function(ast) {
|
var gen_program = function(ast) {
|
||||||
var filename = ast.filename
|
var filename = ast.filename
|
||||||
|
var hoisted = ast.functions
|
||||||
|
var _i = 0
|
||||||
|
var fn = null
|
||||||
|
var name = null
|
||||||
|
var compiled = null
|
||||||
|
var func_id = 0
|
||||||
|
var local_slot = 0
|
||||||
|
var dest = 0
|
||||||
|
var statements = ast.statements
|
||||||
|
var last_expr_slot = -1
|
||||||
|
var stmt = null
|
||||||
|
var kind = null
|
||||||
|
var null_slot = 0
|
||||||
|
var result = null
|
||||||
|
|
||||||
s_filename = filename
|
s_filename = filename
|
||||||
|
|
||||||
s_instructions = []
|
s_instructions = []
|
||||||
@@ -1657,19 +1752,18 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile hoisted function declarations from ast.functions
|
// Compile hoisted function declarations from ast.functions
|
||||||
var hoisted = ast.functions
|
|
||||||
if (hoisted != null) {
|
if (hoisted != null) {
|
||||||
var _i = 0
|
_i = 0
|
||||||
while (_i < length(hoisted)) {
|
while (_i < length(hoisted)) {
|
||||||
var fn = hoisted[_i]
|
fn = hoisted[_i]
|
||||||
var name = fn.name
|
name = fn.name
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
var compiled = gen_function(fn)
|
compiled = gen_function(fn)
|
||||||
var func_id = s_func_counter
|
func_id = s_func_counter
|
||||||
s_func_counter = s_func_counter + 1
|
s_func_counter = s_func_counter + 1
|
||||||
push(s_functions, compiled)
|
push(s_functions, compiled)
|
||||||
var local_slot = find_var(name)
|
local_slot = find_var(name)
|
||||||
var dest = alloc_slot()
|
dest = alloc_slot()
|
||||||
emit_2("function", dest, func_id)
|
emit_2("function", dest, func_id)
|
||||||
if (local_slot >= 0) {
|
if (local_slot >= 0) {
|
||||||
emit_2("move", local_slot, dest)
|
emit_2("move", local_slot, dest)
|
||||||
@@ -1680,12 +1774,10 @@ var mcode = function(ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate main code
|
// Generate main code
|
||||||
var statements = ast.statements
|
_i = 0
|
||||||
var last_expr_slot = -1
|
|
||||||
var _i = 0
|
|
||||||
while (_i < length(statements)) {
|
while (_i < length(statements)) {
|
||||||
var stmt = statements[_i]
|
stmt = statements[_i]
|
||||||
var kind = stmt.kind
|
kind = stmt.kind
|
||||||
if (kind != null) {
|
if (kind != null) {
|
||||||
if (kind == "call") {
|
if (kind == "call") {
|
||||||
last_expr_slot = gen_expr(stmt.expression, -1)
|
last_expr_slot = gen_expr(stmt.expression, -1)
|
||||||
@@ -1713,12 +1805,12 @@ var mcode = function(ast) {
|
|||||||
if (last_expr_slot >= 0) {
|
if (last_expr_slot >= 0) {
|
||||||
emit_1("return", last_expr_slot)
|
emit_1("return", last_expr_slot)
|
||||||
} else {
|
} else {
|
||||||
var null_slot = alloc_slot()
|
null_slot = alloc_slot()
|
||||||
emit_1("null", null_slot)
|
emit_1("null", null_slot)
|
||||||
emit_1("return", null_slot)
|
emit_1("return", null_slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = {}
|
result = {}
|
||||||
result.name = filename != null ? filename : "<eval>"
|
result.name = filename != null ? filename : "<eval>"
|
||||||
result.data = s_data
|
result.data = s_data
|
||||||
result.functions = s_functions
|
result.functions = s_functions
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ static void print_usage(const char *prog)
|
|||||||
printf(" --ast <code|file> Output AST as JSON\n");
|
printf(" --ast <code|file> Output AST as JSON\n");
|
||||||
printf(" --tokenize <code|file> Output token array as JSON\n");
|
printf(" --tokenize <code|file> Output token array as JSON\n");
|
||||||
printf(" --mcode <script> [args] Run through mcode compilation pipeline\n");
|
printf(" --mcode <script> [args] Run through mcode compilation pipeline\n");
|
||||||
printf(" --run-mcode <code|file> Compile and run through MCODE interpreter\n");
|
printf(" --mcode-print <code|file> Compile to MCODE JSON and print it\n");
|
||||||
printf(" --mach <code|file> Output MACH bytecode\n");
|
printf(" --mach <code|file> Output MACH bytecode\n");
|
||||||
printf(" --mach-run <code|file> Compile and run through MACH VM\n");
|
printf(" --mach-run <code|file> Compile and run through MACH VM\n");
|
||||||
printf(" --test [heap_size] Run C test suite\n");
|
printf(" --test [heap_size] Run C test suite\n");
|
||||||
@@ -420,70 +420,69 @@ int cell_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for --run-mcode flag to execute via MCODE interpreter */
|
/* Check for --mcode-print flag to compile a script to MCODE JSON and print it */
|
||||||
if (argc >= 3 && strcmp(argv[1], "--run-mcode") == 0) {
|
if (argc >= 3 && strcmp(argv[1], "--mcode-print") == 0) {
|
||||||
const char *filename = argv[2];
|
const char *script_or_file = argv[2];
|
||||||
if (!find_cell_shop()) return 1;
|
char *script = NULL;
|
||||||
|
char *allocated_script = NULL;
|
||||||
|
const char *filename = "<eval>";
|
||||||
|
|
||||||
size_t boot_size;
|
struct stat st;
|
||||||
char *boot_data = load_core_file("internal/bootstrap.cm", &boot_size);
|
if (stat(script_or_file, &st) == 0 && S_ISREG(st.st_mode)) {
|
||||||
if (!boot_data) {
|
FILE *f = fopen(script_or_file, "r");
|
||||||
printf("ERROR: Could not load internal/bootstrap.cm from %s\n", core_path);
|
if (!f) {
|
||||||
|
printf("Failed to open file: %s\n", script_or_file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
allocated_script = malloc(st.st_size + 1);
|
||||||
|
if (!allocated_script) {
|
||||||
|
fclose(f);
|
||||||
|
printf("Failed to allocate memory for script\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
size_t read_size = fread(allocated_script, 1, st.st_size, f);
|
||||||
|
fclose(f);
|
||||||
|
allocated_script[read_size] = '\0';
|
||||||
|
script = allocated_script;
|
||||||
|
filename = script_or_file;
|
||||||
|
} else {
|
||||||
|
script = (char *)script_or_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON *ast = JS_ASTTree(script, strlen(script), filename);
|
||||||
|
if (!ast) {
|
||||||
|
printf("Failed to parse AST\n");
|
||||||
|
free(allocated_script);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON *boot_ast = JS_ASTTree(boot_data, boot_size, "internal/bootstrap.cm");
|
if (print_tree_errors(ast)) {
|
||||||
free(boot_data);
|
cJSON_Delete(ast);
|
||||||
if (!boot_ast) {
|
free(allocated_script);
|
||||||
printf("Failed to parse internal/bootstrap.cm\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_tree_errors(boot_ast)) {
|
cJSON *mcode = JS_McodeTree(ast);
|
||||||
cJSON_Delete(boot_ast);
|
cJSON_Delete(ast);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON *mcode = JS_McodeTree(boot_ast);
|
|
||||||
cJSON_Delete(boot_ast);
|
|
||||||
|
|
||||||
if (!mcode) {
|
if (!mcode) {
|
||||||
printf("Failed to generate MCODE\n");
|
printf("Failed to generate MCODE\n");
|
||||||
|
free(allocated_script);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_tree_errors(mcode)) {
|
if (print_tree_errors(mcode)) {
|
||||||
cJSON_Delete(mcode);
|
cJSON_Delete(mcode);
|
||||||
|
free(allocated_script);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSRuntime *rt = JS_NewRuntime();
|
char *pretty = cJSON_Print(mcode);
|
||||||
if (!rt) { printf("Failed to create JS runtime\n"); cJSON_Delete(mcode); return 1; }
|
cJSON_Delete(mcode);
|
||||||
JSContext *ctx = JS_NewContextWithHeapSize(rt, 256 * 1024);
|
printf("%s\n", pretty);
|
||||||
if (!ctx) { printf("Failed to create execution context\n"); cJSON_Delete(mcode); JS_FreeRuntime(rt); return 1; }
|
free(pretty);
|
||||||
|
free(allocated_script);
|
||||||
JS_FreeValue(ctx, js_blob_use(ctx));
|
return 0;
|
||||||
|
|
||||||
JSValue hidden_env = JS_NewObject(ctx);
|
|
||||||
JS_SetPropertyStr(ctx, hidden_env, "os", js_os_use(ctx));
|
|
||||||
JS_SetPropertyStr(ctx, hidden_env, "program", JS_NewString(ctx, filename));
|
|
||||||
hidden_env = JS_Stone(ctx, hidden_env);
|
|
||||||
|
|
||||||
JSValue result = JS_CallMcodeTreeEnv(ctx, mcode, hidden_env);
|
|
||||||
|
|
||||||
int exit_code = 0;
|
|
||||||
if (JS_IsException(result)) {
|
|
||||||
/* Error already printed to stderr by JS_Throw* */
|
|
||||||
JS_GetException(ctx);
|
|
||||||
exit_code = 1;
|
|
||||||
} else if (!JS_IsNull(result)) {
|
|
||||||
const char *str = JS_ToCString(ctx, result);
|
|
||||||
if (str) { printf("%s\n", str); JS_FreeCString(ctx, str); }
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_FreeContext(ctx);
|
|
||||||
JS_FreeRuntime(rt);
|
|
||||||
return exit_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for --mach flag to dump MACH bytecode */
|
/* Check for --mach flag to dump MACH bytecode */
|
||||||
|
|||||||
@@ -10505,7 +10505,7 @@ static JSValue js_mcode_run (JSContext *ctx, JSValue this_val, int argc, JSValue
|
|||||||
|
|
||||||
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
|
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
|
||||||
JSValue result = JS_CallMcodeTreeEnv (ctx, mcode, env);
|
JSValue result = JS_CallMcodeTreeEnv (ctx, mcode, env);
|
||||||
cJSON_Delete (mcode);
|
/* mcode tree ownership transferred to JS_CallMcodeTreeEnv — do not free */
|
||||||
JS_FreeCString (ctx, name);
|
JS_FreeCString (ctx, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user