Generate bytecode while parsing
This commit is contained in:
@@ -166,6 +166,11 @@ OP_CODE_DECL (b_xor, T_IDX_IDX_IDX,
|
|||||||
var_left,
|
var_left,
|
||||||
var_right)
|
var_right)
|
||||||
|
|
||||||
|
/** dst = ~ R */
|
||||||
|
OP_CODE_DECL (b_not, T_IDX_IDX,
|
||||||
|
dst,
|
||||||
|
var_right)
|
||||||
|
|
||||||
// Binary logical operators.
|
// Binary logical operators.
|
||||||
// Operands are booleans.
|
// Operands are booleans.
|
||||||
// Return boolean.
|
// Return boolean.
|
||||||
@@ -182,6 +187,11 @@ OP_CODE_DECL (logical_or, T_IDX_IDX_IDX,
|
|||||||
var_left,
|
var_left,
|
||||||
var_right)
|
var_right)
|
||||||
|
|
||||||
|
/** dst = ! R */
|
||||||
|
OP_CODE_DECL (logical_not, T_IDX_IDX,
|
||||||
|
dst,
|
||||||
|
var_right)
|
||||||
|
|
||||||
// Equality operations.
|
// Equality operations.
|
||||||
|
|
||||||
/** dst = L == R. */
|
/** dst = L == R. */
|
||||||
@@ -234,6 +244,18 @@ OP_CODE_DECL (greater_or_equal_than, T_IDX_IDX_IDX,
|
|||||||
var_left,
|
var_left,
|
||||||
var_right)
|
var_right)
|
||||||
|
|
||||||
|
/** dst = L instanceof R. */
|
||||||
|
OP_CODE_DECL (instanceof, T_IDX_IDX_IDX,
|
||||||
|
dst,
|
||||||
|
var_left,
|
||||||
|
var_right)
|
||||||
|
|
||||||
|
/** dst = L in R. */
|
||||||
|
OP_CODE_DECL (in, T_IDX_IDX_IDX,
|
||||||
|
dst,
|
||||||
|
var_left,
|
||||||
|
var_right)
|
||||||
|
|
||||||
// Assignment operators.
|
// Assignment operators.
|
||||||
// Assign value to LEFT operand based on value of RIGHT operand.
|
// Assign value to LEFT operand based on value of RIGHT operand.
|
||||||
|
|
||||||
@@ -244,22 +266,43 @@ OP_CODE_DECL (assignment, T_IDX_IDX,
|
|||||||
|
|
||||||
// Functions calls, declarations and argument handling
|
// Functions calls, declarations and argument handling
|
||||||
|
|
||||||
/** name(arg1); */
|
/** a = name(); */
|
||||||
OP_CODE_DECL (call_1, T_IDX_IDX,
|
OP_CODE_DECL (call_0, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx)
|
||||||
|
|
||||||
|
/** a = name(arg1); */
|
||||||
|
OP_CODE_DECL (call_1, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
name_lit_idx,
|
name_lit_idx,
|
||||||
arg1_lit_idx)
|
arg1_lit_idx)
|
||||||
|
|
||||||
/** name(arg1, arg2); */
|
/** a = name(arg1, ... */
|
||||||
OP_CODE_DECL (call_2, T_IDX_IDX_IDX,
|
|
||||||
name_lit_idx,
|
|
||||||
arg1_lit_idx,
|
|
||||||
arg2_lit_idx)
|
|
||||||
|
|
||||||
/** name(arg1, arg2, ... */
|
|
||||||
OP_CODE_DECL (call_n, T_IDX_IDX_IDX,
|
OP_CODE_DECL (call_n, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
name_lit_idx,
|
name_lit_idx,
|
||||||
arg1_lit_idx,
|
arg1_lit_idx)
|
||||||
arg2_lit_idx)
|
|
||||||
|
/** a = new name(); */
|
||||||
|
OP_CODE_DECL (construct_0, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx)
|
||||||
|
|
||||||
|
/** a = new name(arg1); */
|
||||||
|
OP_CODE_DECL (construct_1, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx,
|
||||||
|
arg1_lit_idx)
|
||||||
|
|
||||||
|
/** a = new name(arg1, ... */
|
||||||
|
OP_CODE_DECL (construct_n, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx,
|
||||||
|
arg1_lit_idx)
|
||||||
|
|
||||||
|
/** name(); */
|
||||||
|
OP_CODE_DECL (func_decl_0, T_IDX,
|
||||||
|
name_lit_idx)
|
||||||
|
|
||||||
/** name(arg1); */
|
/** name(arg1); */
|
||||||
OP_CODE_DECL (func_decl_1, T_IDX_IDX,
|
OP_CODE_DECL (func_decl_1, T_IDX_IDX,
|
||||||
@@ -278,19 +321,27 @@ OP_CODE_DECL (func_decl_n, T_IDX_IDX_IDX,
|
|||||||
arg1_lit_idx,
|
arg1_lit_idx,
|
||||||
arg2_lit_idx)
|
arg2_lit_idx)
|
||||||
|
|
||||||
/** ..., arg1, ... */
|
/** a = name(); */
|
||||||
OP_CODE_DECL (varg_1, T_IDX,
|
OP_CODE_DECL (func_expr_0, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx)
|
||||||
|
|
||||||
|
/** a = name(arg1); */
|
||||||
|
OP_CODE_DECL (func_expr_1, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx,
|
||||||
|
arg1_lit_idx)
|
||||||
|
|
||||||
|
/** a = name(arg1, ... */
|
||||||
|
OP_CODE_DECL (func_expr_n, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name_lit_idx,
|
||||||
arg1_lit_idx)
|
arg1_lit_idx)
|
||||||
|
|
||||||
/** ..., arg1); */
|
/** ..., arg1); */
|
||||||
OP_CODE_DECL (varg_1_end, T_IDX,
|
OP_CODE_DECL (varg_1_end, T_IDX,
|
||||||
arg1_lit_idx)
|
arg1_lit_idx)
|
||||||
|
|
||||||
/** ..., arg1, arg2, ... */
|
|
||||||
OP_CODE_DECL (varg_2, T_IDX_IDX,
|
|
||||||
arg1_lit_idx,
|
|
||||||
arg2_lit_idx)
|
|
||||||
|
|
||||||
/** ..., arg1, arg2); */
|
/** ..., arg1, arg2); */
|
||||||
OP_CODE_DECL (varg_2_end, T_IDX_IDX,
|
OP_CODE_DECL (varg_2_end, T_IDX_IDX,
|
||||||
arg1_lit_idx,
|
arg1_lit_idx,
|
||||||
@@ -356,26 +407,91 @@ OP_CODE_DECL (loop_postcond, T_IDX_IDX,
|
|||||||
condition,
|
condition,
|
||||||
body_root)
|
body_root)
|
||||||
|
|
||||||
///** for vars...in iter, state, ctl */
|
/** a = [] */
|
||||||
//OP_CODE_DECL (loop_init, T_IDX_IDX_IDX,
|
OP_CODE_DECL (array_0, T_IDX,
|
||||||
// start_idx, stop_idx, step_idx)
|
lhs)
|
||||||
///** loop (condition) */
|
|
||||||
//OP_CODE_DECL (loop_cond_pre_begin, T_IDX_IDX,
|
|
||||||
// condition, body_root)
|
|
||||||
///** i++;*/
|
|
||||||
//OP_CODE_DECL (loop_cond_pre_end, T_IDX,
|
|
||||||
// iterator, body_root)
|
|
||||||
|
|
||||||
// Property accessors (array, objects, strings)
|
/** a = [b] */
|
||||||
/** Array ops for ILMIR*/
|
OP_CODE_DECL (array_1, T_IDX_IDX,
|
||||||
//OP_CODE_DECL (array_copy, T_IDX_IDX, /** L = R */
|
lhs,
|
||||||
// var_left, var_right)
|
elem1)
|
||||||
//OP_CODE_DECL (array_set, T_IDX_IDX_IDX, /** array[index] = src */
|
|
||||||
// dst, var_left, var_right)
|
|
||||||
//OP_CODE_DECL (array_get, T_IDX_IDX_IDX, /** dst = array[index] */
|
|
||||||
// dst, array, index)
|
|
||||||
|
|
||||||
//// TODO
|
/** a = [b, c] */
|
||||||
|
OP_CODE_DECL (array_2, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
elem1,
|
||||||
|
elem2)
|
||||||
|
|
||||||
|
/** a = [b, c ... */
|
||||||
|
OP_CODE_DECL (array_n, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
elem1,
|
||||||
|
elem2)
|
||||||
|
|
||||||
|
/** a = b : c */
|
||||||
|
OP_CODE_DECL (prop, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
name,
|
||||||
|
value)
|
||||||
|
|
||||||
|
/** a = b.c OR a = b[c] */
|
||||||
|
OP_CODE_DECL (prop_access, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
obj,
|
||||||
|
prop)
|
||||||
|
|
||||||
|
/** a = get prop () */
|
||||||
|
OP_CODE_DECL (prop_get_decl, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
prop)
|
||||||
|
|
||||||
|
/** a = set prop (arg) */
|
||||||
|
OP_CODE_DECL (prop_set_decl, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
prop,
|
||||||
|
arg)
|
||||||
|
|
||||||
|
/** a = { } */
|
||||||
|
OP_CODE_DECL (obj_0, T_IDX,
|
||||||
|
lhs)
|
||||||
|
|
||||||
|
/** a = { b } */
|
||||||
|
OP_CODE_DECL (obj_1, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
arg1)
|
||||||
|
|
||||||
|
/** a = { b, c } */
|
||||||
|
OP_CODE_DECL (obj_2, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
arg1,
|
||||||
|
arg2)
|
||||||
|
|
||||||
|
/** a = { b, c ... */
|
||||||
|
OP_CODE_DECL (obj_n, T_IDX_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
arg1,
|
||||||
|
arg2)
|
||||||
|
|
||||||
|
/** a = this */
|
||||||
|
OP_CODE_DECL (this, T_IDX,
|
||||||
|
lhs)
|
||||||
|
|
||||||
|
/** a = delete b */
|
||||||
|
OP_CODE_DECL (delete, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
obj)
|
||||||
|
|
||||||
|
/** a = delete b */
|
||||||
|
OP_CODE_DECL (typeof, T_IDX_IDX,
|
||||||
|
lhs,
|
||||||
|
obj)
|
||||||
|
|
||||||
|
/** with (b) { */
|
||||||
|
OP_CODE_DECL (with, T_IDX,
|
||||||
|
expr)
|
||||||
|
|
||||||
|
/** } */
|
||||||
|
OP_CODE_DECL_VOID (end_with)
|
||||||
|
|
||||||
// Variable declaration
|
// Variable declaration
|
||||||
OP_CODE_DECL (decl_var, T_IDX,
|
OP_CODE_DECL (decl_var, T_IDX,
|
||||||
|
|||||||
@@ -22,19 +22,42 @@ void opfunc_loop_init_num (OPCODE opdata __unused, struct __int_data *int_data _
|
|||||||
void opfunc_loop_precond_begin_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_loop_precond_begin_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_loop_precond_end_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_loop_precond_end_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_loop_postcond (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_loop_postcond (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_call_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_call_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_call_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_call_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_construct_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_construct_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_construct_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_func_decl_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_func_decl_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_func_decl_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_func_decl_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_func_decl_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_func_decl_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_func_decl_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_varg_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_func_expr_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_func_expr_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_func_expr_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_varg_1_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_varg_1_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_varg_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
|
||||||
void opfunc_varg_2_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_varg_2_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_varg_3 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_varg_3 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_varg_3_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_varg_3_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_retval (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_retval (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_ret (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_ret (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_array_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_array_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_array_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_array_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_obj_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_obj_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_obj_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_obj_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_prop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_prop_access (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_prop_get_decl (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_prop_set_decl (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_this (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_delete (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_typeof (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_with (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_end_with (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_decl_var (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_nop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_nop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_not_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_not_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
@@ -44,6 +67,8 @@ void opfunc_less_than (OPCODE opdata __unused, struct __int_data *int_data __unu
|
|||||||
void opfunc_greater_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_greater_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_less_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_less_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_greater_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_greater_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_instanceof (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_in (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
|
||||||
void
|
void
|
||||||
opfunc_assignment(OPCODE opdata __unused,
|
opfunc_assignment(OPCODE opdata __unused,
|
||||||
@@ -54,9 +79,11 @@ opfunc_assignment(OPCODE opdata __unused,
|
|||||||
|
|
||||||
void opfunc_logical_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_logical_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_logical_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_logical_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_logical_not (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_xor (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_xor (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
|
void opfunc_b_not (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_shift_left (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_shift_left (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_shift_right (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_shift_right (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
void opfunc_b_shift_uright (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
void opfunc_b_shift_uright (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
|
||||||
@@ -124,8 +151,10 @@ GETOP_IMPL_3 (b_shift_uright, dst, var_left, var_right)
|
|||||||
GETOP_IMPL_3 (b_and, dst, var_left, var_right)
|
GETOP_IMPL_3 (b_and, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (b_or, dst, var_left, var_right)
|
GETOP_IMPL_3 (b_or, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (b_xor, dst, var_left, var_right)
|
GETOP_IMPL_3 (b_xor, dst, var_left, var_right)
|
||||||
|
GETOP_IMPL_2 (b_not, dst, var_right)
|
||||||
GETOP_IMPL_3 (logical_and, dst, var_left, var_right)
|
GETOP_IMPL_3 (logical_and, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (logical_or, dst, var_left, var_right)
|
GETOP_IMPL_3 (logical_or, dst, var_left, var_right)
|
||||||
|
GETOP_IMPL_2 (logical_not, dst, var_right)
|
||||||
GETOP_IMPL_3 (equal_value, dst, var_left, var_right)
|
GETOP_IMPL_3 (equal_value, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (not_equal_value, dst, var_left, var_right)
|
GETOP_IMPL_3 (not_equal_value, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (equal_value_type, dst, var_left, var_right)
|
GETOP_IMPL_3 (equal_value_type, dst, var_left, var_right)
|
||||||
@@ -134,16 +163,23 @@ GETOP_IMPL_3 (less_than, dst, var_left, var_right)
|
|||||||
GETOP_IMPL_3 (greater_than, dst, var_left, var_right)
|
GETOP_IMPL_3 (greater_than, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (less_or_equal_than, dst, var_left, var_right)
|
GETOP_IMPL_3 (less_or_equal_than, dst, var_left, var_right)
|
||||||
GETOP_IMPL_3 (greater_or_equal_than, dst, var_left, var_right)
|
GETOP_IMPL_3 (greater_or_equal_than, dst, var_left, var_right)
|
||||||
|
GETOP_IMPL_3 (instanceof, dst, var_left, var_right)
|
||||||
|
GETOP_IMPL_3 (in, dst, var_left, var_right)
|
||||||
GETOP_IMPL_2 (assignment, value_left, value_right)
|
GETOP_IMPL_2 (assignment, value_left, value_right)
|
||||||
GETOP_IMPL_2 (call_1, name_lit_idx, arg1_lit_idx)
|
GETOP_IMPL_2 (call_0, lhs, name_lit_idx)
|
||||||
GETOP_IMPL_3 (call_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
GETOP_IMPL_3 (call_1, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
GETOP_IMPL_3 (call_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
GETOP_IMPL_3 (call_n, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
|
GETOP_IMPL_2 (construct_0, lhs, name_lit_idx)
|
||||||
|
GETOP_IMPL_3 (construct_1, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
|
GETOP_IMPL_3 (construct_n, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
|
GETOP_IMPL_1 (func_decl_0, name_lit_idx)
|
||||||
GETOP_IMPL_2 (func_decl_1, name_lit_idx, arg1_lit_idx)
|
GETOP_IMPL_2 (func_decl_1, name_lit_idx, arg1_lit_idx)
|
||||||
GETOP_IMPL_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
GETOP_IMPL_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||||
GETOP_IMPL_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
GETOP_IMPL_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||||
GETOP_IMPL_1 (varg_1, arg1_lit_idx)
|
GETOP_IMPL_2 (func_expr_0, lhs, name_lit_idx)
|
||||||
|
GETOP_IMPL_3 (func_expr_1, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
|
GETOP_IMPL_3 (func_expr_n, lhs, name_lit_idx, arg1_lit_idx)
|
||||||
GETOP_IMPL_1 (varg_1_end, arg1_lit_idx)
|
GETOP_IMPL_1 (varg_1_end, arg1_lit_idx)
|
||||||
GETOP_IMPL_2 (varg_2, arg1_lit_idx, arg2_lit_idx)
|
|
||||||
GETOP_IMPL_2 (varg_2_end, arg1_lit_idx, arg2_lit_idx)
|
GETOP_IMPL_2 (varg_2_end, arg1_lit_idx, arg2_lit_idx)
|
||||||
GETOP_IMPL_3 (varg_3, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
GETOP_IMPL_3 (varg_3, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
||||||
GETOP_IMPL_3 (varg_3_end, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
GETOP_IMPL_3 (varg_3_end, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
||||||
@@ -155,4 +191,22 @@ GETOP_IMPL_3 (loop_init_num, start, stop, step)
|
|||||||
GETOP_IMPL_2 (loop_precond_begin_num, condition, after_loop_op)
|
GETOP_IMPL_2 (loop_precond_begin_num, condition, after_loop_op)
|
||||||
GETOP_IMPL_3 (loop_precond_end_num, iterator, step, precond_begin)
|
GETOP_IMPL_3 (loop_precond_end_num, iterator, step, precond_begin)
|
||||||
GETOP_IMPL_2 (loop_postcond, condition, body_root)
|
GETOP_IMPL_2 (loop_postcond, condition, body_root)
|
||||||
|
GETOP_IMPL_1 (array_0, lhs)
|
||||||
|
GETOP_IMPL_2 (array_1, lhs, elem1)
|
||||||
|
GETOP_IMPL_3 (array_2, lhs, elem1, elem2)
|
||||||
|
GETOP_IMPL_3 (array_n, lhs, elem1, elem2)
|
||||||
|
GETOP_IMPL_3 (prop, lhs, name, value)
|
||||||
|
GETOP_IMPL_3 (prop_access, lhs, obj, prop)
|
||||||
|
GETOP_IMPL_2 (prop_get_decl, lhs, prop)
|
||||||
|
GETOP_IMPL_3 (prop_set_decl, lhs, prop, arg)
|
||||||
|
GETOP_IMPL_1 (obj_0, lhs)
|
||||||
|
GETOP_IMPL_2 (obj_1, lhs, arg1)
|
||||||
|
GETOP_IMPL_3 (obj_2, lhs, arg1, arg2)
|
||||||
|
GETOP_IMPL_3 (obj_n, lhs, arg1, arg2)
|
||||||
|
GETOP_IMPL_1 (this, lhs)
|
||||||
|
GETOP_IMPL_2 (delete, lhs, obj)
|
||||||
|
GETOP_IMPL_2 (typeof, lhs, obj)
|
||||||
|
GETOP_IMPL_1 (with, expr)
|
||||||
|
GETOP_IMPL_0 (end_with)
|
||||||
|
GETOP_IMPL_1 (decl_var, variable)
|
||||||
|
|
||||||
|
|||||||
@@ -42,21 +42,46 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
|
|||||||
op(loop_postcond)
|
op(loop_postcond)
|
||||||
|
|
||||||
#define OP_CALLS_AND_ARGS(op) \
|
#define OP_CALLS_AND_ARGS(op) \
|
||||||
|
op(call_0) \
|
||||||
op(call_1) \
|
op(call_1) \
|
||||||
op(call_2) \
|
|
||||||
op(call_n) \
|
op(call_n) \
|
||||||
|
op(construct_0) \
|
||||||
|
op(construct_1) \
|
||||||
|
op(construct_n) \
|
||||||
|
op(func_decl_0) \
|
||||||
op(func_decl_1) \
|
op(func_decl_1) \
|
||||||
op(func_decl_2) \
|
op(func_decl_2) \
|
||||||
op(func_decl_n) \
|
op(func_decl_n) \
|
||||||
op(varg_1) \
|
op(func_expr_0) \
|
||||||
|
op(func_expr_1) \
|
||||||
|
op(func_expr_n) \
|
||||||
op(varg_1_end) \
|
op(varg_1_end) \
|
||||||
op(varg_2) \
|
|
||||||
op(varg_2_end) \
|
op(varg_2_end) \
|
||||||
op(varg_3) \
|
op(varg_3) \
|
||||||
op(varg_3_end) \
|
op(varg_3_end) \
|
||||||
op(retval) \
|
op(retval) \
|
||||||
op(ret)
|
op(ret)
|
||||||
|
|
||||||
|
#define OP_INITS(op) \
|
||||||
|
op(array_0) \
|
||||||
|
op(array_1) \
|
||||||
|
op(array_2) \
|
||||||
|
op(array_n) \
|
||||||
|
op(prop) \
|
||||||
|
op(prop_access) \
|
||||||
|
op(prop_get_decl) \
|
||||||
|
op(prop_set_decl) \
|
||||||
|
op(obj_0) \
|
||||||
|
op(obj_1) \
|
||||||
|
op(obj_2) \
|
||||||
|
op(obj_n) \
|
||||||
|
op(this) \
|
||||||
|
op(delete) \
|
||||||
|
op(typeof) \
|
||||||
|
op(with) \
|
||||||
|
op(end_with) \
|
||||||
|
op(decl_var)
|
||||||
|
|
||||||
#define OP_ASSIGNMENTS(op) \
|
#define OP_ASSIGNMENTS(op) \
|
||||||
op(assignment)
|
op(assignment)
|
||||||
|
|
||||||
@@ -68,11 +93,13 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
|
|||||||
#define OP_B_BITWISE(op) \
|
#define OP_B_BITWISE(op) \
|
||||||
op(b_and) \
|
op(b_and) \
|
||||||
op(b_or) \
|
op(b_or) \
|
||||||
op(b_xor)
|
op(b_xor) \
|
||||||
|
op(b_not)
|
||||||
|
|
||||||
#define OP_B_LOGICAL(op) \
|
#define OP_B_LOGICAL(op) \
|
||||||
op(logical_and) \
|
op(logical_and) \
|
||||||
op(logical_or)
|
op(logical_or) \
|
||||||
|
op(logical_not)
|
||||||
|
|
||||||
#define OP_EQUALITY(op) \
|
#define OP_EQUALITY(op) \
|
||||||
op(equal_value) \
|
op(equal_value) \
|
||||||
@@ -84,7 +111,9 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
|
|||||||
op(less_than) \
|
op(less_than) \
|
||||||
op(greater_than) \
|
op(greater_than) \
|
||||||
op(less_or_equal_than) \
|
op(less_or_equal_than) \
|
||||||
op(greater_or_equal_than)
|
op(greater_or_equal_than) \
|
||||||
|
op(instanceof) \
|
||||||
|
op(in)
|
||||||
|
|
||||||
#define OP_ARITHMETIC(op) \
|
#define OP_ARITHMETIC(op) \
|
||||||
op(addition) \
|
op(addition) \
|
||||||
@@ -106,6 +135,7 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
|
|||||||
#define OP_LIST(op) \
|
#define OP_LIST(op) \
|
||||||
OP_LOOPS(op) \
|
OP_LOOPS(op) \
|
||||||
OP_CALLS_AND_ARGS(op) \
|
OP_CALLS_AND_ARGS(op) \
|
||||||
|
OP_INITS(op) \
|
||||||
OP_ASSIGNMENTS(op) \
|
OP_ASSIGNMENTS(op) \
|
||||||
OP_B_LOGICAL(op) \
|
OP_B_LOGICAL(op) \
|
||||||
OP_B_BITWISE(op) \
|
OP_B_BITWISE(op) \
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This allocator only allocates a memmory and doesn't free it.
|
|
||||||
Use it only in dedicated parser, otherwise use jerry fixed pool allocator. */
|
|
||||||
#ifndef ALLOCATOR_H
|
|
||||||
#define ALLOCATOR_H
|
|
||||||
|
|
||||||
#include "../globals.h"
|
|
||||||
|
|
||||||
#define ALLOCATION_BUFFER_SIZE 4096
|
|
||||||
|
|
||||||
char allocation_buffer[ALLOCATION_BUFFER_SIZE];
|
|
||||||
char *free_memory;
|
|
||||||
|
|
||||||
static void *
|
|
||||||
geppetto_allocate_memory (size_t size)
|
|
||||||
{
|
|
||||||
void *res;
|
|
||||||
if (!free_memory)
|
|
||||||
free_memory = allocation_buffer;
|
|
||||||
|
|
||||||
res = free_memory;
|
|
||||||
free_memory += size;
|
|
||||||
JERRY_ASSERT (free_memory - allocation_buffer < ALLOCATION_BUFFER_SIZE);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *
|
|
||||||
malloc (size_t size)
|
|
||||||
{
|
|
||||||
return geppetto_allocate_memory (size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
free (void *mem __unused)
|
|
||||||
{
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ALLOCATOR_H
|
|
||||||
@@ -1,418 +0,0 @@
|
|||||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "bytecode-generator.h"
|
|
||||||
#include "globals.h"
|
|
||||||
#include "libcoreint/opcodes.h"
|
|
||||||
#include "libruntime/serializer.h"
|
|
||||||
#include "libruntime/jerry-libc.h"
|
|
||||||
|
|
||||||
static uint8_t opcode_index;
|
|
||||||
|
|
||||||
#define MAX_STACK_SIZE 10
|
|
||||||
|
|
||||||
static uint8_t opcode_stack[10];
|
|
||||||
static uint8_t stack_head;
|
|
||||||
|
|
||||||
static void
|
|
||||||
push_opcode (uint8_t opcode)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (stack_head < MAX_STACK_SIZE);
|
|
||||||
opcode_stack[stack_head++] = opcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
pop_opcode (void)
|
|
||||||
{
|
|
||||||
return opcode_stack[--stack_head];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
generator_init (void)
|
|
||||||
{
|
|
||||||
opcode_index = 0;
|
|
||||||
stack_head = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
generator_dump_strings (const char **strings, uint8_t num)
|
|
||||||
{
|
|
||||||
uint8_t len = num, i;
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
serializer_dump_data (&len, 1);
|
|
||||||
len = (uint8_t) (len + __strlen (strings[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
serializer_dump_data (strings[i], __strlen (strings[i]) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
is_expression (statement stmt)
|
|
||||||
{
|
|
||||||
switch (stmt.type)
|
|
||||||
{
|
|
||||||
case STMT_IF:
|
|
||||||
case STMT_ELSE_IF:
|
|
||||||
case STMT_END_DO_WHILE:
|
|
||||||
case STMT_WHILE:
|
|
||||||
case STMT_RETURN:
|
|
||||||
case STMT_WITH:
|
|
||||||
case STMT_SWITCH:
|
|
||||||
case STMT_CASE:
|
|
||||||
case STMT_THROW:
|
|
||||||
case STMT_EXPRESSION:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
is_assignment (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (is_expression (stmt));
|
|
||||||
return stmt.data.expr.oper != AO_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static expression_type
|
|
||||||
get_expression_type (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (is_expression (stmt));
|
|
||||||
return stmt.data.expr.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
expression_has_operands (statement stmt)
|
|
||||||
{
|
|
||||||
switch (get_expression_type (stmt))
|
|
||||||
{
|
|
||||||
case ET_OBJECT:
|
|
||||||
case ET_FUNCTION:
|
|
||||||
case ET_ARRAY:
|
|
||||||
case ET_SUBEXPRESSION:
|
|
||||||
case ET_NONE:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static operand
|
|
||||||
first_operand (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (expression_has_operands (stmt));
|
|
||||||
return stmt.data.expr.data.ops.op1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static literal
|
|
||||||
first_operand_as_literal (statement stmt)
|
|
||||||
{
|
|
||||||
operand oper = first_operand (stmt);
|
|
||||||
|
|
||||||
JERRY_ASSERT (oper.is_literal);
|
|
||||||
|
|
||||||
return oper.data.lit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
first_operand_id (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (expression_has_operands (stmt));
|
|
||||||
if (first_operand (stmt).is_literal)
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
return first_operand (stmt).data.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static operand
|
|
||||||
second_operand (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (expression_has_operands (stmt));
|
|
||||||
return stmt.data.expr.data.ops.op2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
second_operand_id (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (expression_has_operands (stmt));
|
|
||||||
if (second_operand (stmt).is_literal)
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
return second_operand (stmt).data.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
lhs (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (is_assignment (stmt));
|
|
||||||
|
|
||||||
return stmt.data.expr.var;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dump_opcode (OPCODE *opcode)
|
|
||||||
{
|
|
||||||
serializer_dump_data (opcode, sizeof (OPCODE));
|
|
||||||
opcode_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static assignment_operator
|
|
||||||
get_assignment_operator (statement stmt)
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (is_assignment (stmt));
|
|
||||||
|
|
||||||
return stmt.data.expr.oper;
|
|
||||||
}
|
|
||||||
|
|
||||||
static OPCODE
|
|
||||||
generate_triple_address (OPCODE (*getop)(T_IDX, T_IDX, T_IDX), statement stmt)
|
|
||||||
{
|
|
||||||
return (*getop) (lhs (stmt), first_operand_id (stmt), second_operand_id (stmt));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
generator_dump_statement (statement stmt)
|
|
||||||
{
|
|
||||||
OPCODE opcode = getop_nop ();
|
|
||||||
JERRY_STATIC_ASSERT (sizeof (OPCODE) <= sizeof (uint32_t));
|
|
||||||
|
|
||||||
switch (stmt.type)
|
|
||||||
{
|
|
||||||
case STMT_EMPTY:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STMT_WHILE:
|
|
||||||
if (!is_assignment (stmt))
|
|
||||||
{
|
|
||||||
literal lit;
|
|
||||||
|
|
||||||
switch (get_expression_type (stmt))
|
|
||||||
{
|
|
||||||
case ET_LITERAL:
|
|
||||||
lit = first_operand_as_literal (stmt);
|
|
||||||
if (lit.type == LIT_BOOL && lit.data.is_true)
|
|
||||||
{
|
|
||||||
opcode = getop_loop_inf ((uint8_t) (opcode_index + 1));
|
|
||||||
push_opcode ((uint8_t) (opcode_index + 1));
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STMT_EXPRESSION:
|
|
||||||
if (is_assignment (stmt))
|
|
||||||
{
|
|
||||||
switch (get_expression_type (stmt))
|
|
||||||
{
|
|
||||||
case ET_NONE:
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LOGICAL_OR:
|
|
||||||
opcode = generate_triple_address (getop_logical_or, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LOGICAL_AND:
|
|
||||||
opcode = generate_triple_address (getop_logical_and, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_BITWISE_OR:
|
|
||||||
opcode = generate_triple_address (getop_b_or, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_BITWISE_XOR:
|
|
||||||
opcode = generate_triple_address (getop_b_xor, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_BITWISE_AND:
|
|
||||||
opcode = generate_triple_address (getop_b_and, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_DOUBLE_EQ:
|
|
||||||
opcode = generate_triple_address (getop_equal_value, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_NOT_EQ:
|
|
||||||
opcode = generate_triple_address (getop_not_equal_value, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_TRIPLE_EQ:
|
|
||||||
opcode = generate_triple_address (getop_equal_value_type, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_NOT_DOUBLE_EQ:
|
|
||||||
opcode = generate_triple_address (getop_not_equal_value_type, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LESS:
|
|
||||||
opcode = generate_triple_address (getop_less_than, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_GREATER:
|
|
||||||
opcode = generate_triple_address (getop_greater_than, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LESS_EQ:
|
|
||||||
opcode = generate_triple_address (getop_less_or_equal_than, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_GREATER_EQ:
|
|
||||||
opcode = generate_triple_address (getop_greater_or_equal_than, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_INSTANCEOF:
|
|
||||||
case ET_IN:
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LSHIFT:
|
|
||||||
opcode = generate_triple_address (getop_b_shift_left, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_RSHIFT:
|
|
||||||
opcode = generate_triple_address (getop_b_shift_right, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_RSHIFT_EX:
|
|
||||||
opcode = generate_triple_address (getop_b_shift_uright, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_PLUS:
|
|
||||||
opcode = generate_triple_address (getop_addition, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_MINUS:
|
|
||||||
opcode = generate_triple_address (getop_substraction, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_MULT:
|
|
||||||
opcode = generate_triple_address (getop_multiplication, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_DIV:
|
|
||||||
opcode = generate_triple_address (getop_division, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_MOD:
|
|
||||||
opcode = generate_triple_address (getop_remainder, stmt);
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_UNARY_DELETE:
|
|
||||||
case ET_UNARY_VOID:
|
|
||||||
case ET_UNARY_TYPEOF:
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_UNARY_INCREMENT:
|
|
||||||
// opcode = getop_addition (first_operand_id (stmt), first_operand_id (stmt), INTEGER_ONE);
|
|
||||||
case ET_UNARY_DECREMENT:
|
|
||||||
case ET_UNARY_PLUS:
|
|
||||||
case ET_UNARY_MINUS:
|
|
||||||
case ET_UNARY_COMPL:
|
|
||||||
case ET_UNARY_NOT:
|
|
||||||
case ET_POSTFIX_INCREMENT:
|
|
||||||
case ET_POSTFIX_DECREMENT:
|
|
||||||
case ET_CALL:
|
|
||||||
case ET_NEW:
|
|
||||||
case ET_INDEX:
|
|
||||||
case ET_PROP_REF:
|
|
||||||
case ET_OBJECT:
|
|
||||||
case ET_FUNCTION:
|
|
||||||
case ET_ARRAY:
|
|
||||||
case ET_SUBEXPRESSION:
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ET_LITERAL:
|
|
||||||
case ET_IDENTIFIER:
|
|
||||||
switch (get_assignment_operator (stmt))
|
|
||||||
{
|
|
||||||
case AO_NONE:
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AO_EQ:
|
|
||||||
opcode = getop_assignment (lhs (stmt), first_operand_id (stmt));
|
|
||||||
dump_opcode (&opcode);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
}
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
|
|
||||||
default:
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_assignment_operator (stmt) != AO_EQ)
|
|
||||||
JERRY_UNIMPLEMENTED ();
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
call_expression expr = stmt.data.expr.data.call_expr;
|
|
||||||
JERRY_ASSERT (!is_operand_list_empty (expr.args));
|
|
||||||
if (!is_operand_empty (expr.args.ops[1]))
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
if (expr.args.ops[0].is_literal)
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
opcode = getop_call_1 (expr.name, expr.args.ops[0].data.name);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STMT_END_WHILE:
|
|
||||||
opcode = getop_jmp (pop_opcode ());
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
__printf (" generator_dump_statement: %d ", stmt.type);
|
|
||||||
JERRY_UNREACHABLE ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BYTECODE_GENERATOR_H
|
|
||||||
#define BYTECODE_GENERATOR_H
|
|
||||||
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
void generator_init (void);
|
|
||||||
void generator_dump_strings (const char **, uint8_t);
|
|
||||||
void generator_dump_statement (statement);
|
|
||||||
|
|
||||||
#endif // BYTECODE_GENERATOR_H
|
|
||||||
+113
-41
@@ -13,14 +13,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "mem-allocator.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "jerry-libc.h"
|
#include "jerry-libc.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
static token saved_token;
|
static token saved_token;
|
||||||
static token empty_token = { .type = TOK_EMPTY, .data.none = NULL };
|
static token empty_token = { .type = TOK_EMPTY, .data.uid = 0 };
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ static string_and_token keyword_tokens[] =
|
|||||||
{ .str = "enum", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "enum", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "export", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "export", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "extends", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "extends", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "false", .tok = { .type = TOK_BOOL, .data.is_true = false } },
|
{ .str = "false", .tok = { .type = TOK_BOOL, .data.uid = false } },
|
||||||
{ .str = "finally", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FINALLY } },
|
{ .str = "finally", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FINALLY } },
|
||||||
{ .str = "for", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FOR } },
|
{ .str = "for", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FOR } },
|
||||||
{ .str = "function", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FUNCTION } },
|
{ .str = "function", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FUNCTION } },
|
||||||
@@ -57,7 +57,7 @@ static string_and_token keyword_tokens[] =
|
|||||||
{ .str = "implements", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "implements", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "let", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "let", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "new", .tok = { .type = TOK_KEYWORD, .data.kw = KW_NEW } },
|
{ .str = "new", .tok = { .type = TOK_KEYWORD, .data.kw = KW_NEW } },
|
||||||
{ .str = "null", .tok = { .type = TOK_NULL, .data.none = NULL } },
|
{ .str = "null", .tok = { .type = TOK_NULL, .data.uid = 0 } },
|
||||||
{ .str = "package", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "package", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "private", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "private", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
{ .str = "protected", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
{ .str = "protected", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||||
@@ -68,7 +68,7 @@ static string_and_token keyword_tokens[] =
|
|||||||
{ .str = "switch", .tok = { .type = TOK_KEYWORD, .data.kw = KW_SWITCH } },
|
{ .str = "switch", .tok = { .type = TOK_KEYWORD, .data.kw = KW_SWITCH } },
|
||||||
{ .str = "this", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THIS } },
|
{ .str = "this", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THIS } },
|
||||||
{ .str = "throw", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THROW } },
|
{ .str = "throw", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THROW } },
|
||||||
{ .str = "true", .tok = { .type = TOK_BOOL, .data.is_true = true } },
|
{ .str = "true", .tok = { .type = TOK_BOOL, .data.uid = true } },
|
||||||
{ .str = "try", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TRY } },
|
{ .str = "try", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TRY } },
|
||||||
{ .str = "typeof", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TYPEOF } },
|
{ .str = "typeof", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TYPEOF } },
|
||||||
{ .str = "var", .tok = { .type = TOK_KEYWORD, .data.kw = KW_VAR } },
|
{ .str = "var", .tok = { .type = TOK_KEYWORD, .data.kw = KW_VAR } },
|
||||||
@@ -78,10 +78,25 @@ static string_and_token keyword_tokens[] =
|
|||||||
{ .str = "yield", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }
|
{ .str = "yield", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
token tok;
|
||||||
|
}
|
||||||
|
num_and_token;
|
||||||
|
|
||||||
#define MAX_NAMES 100
|
#define MAX_NAMES 100
|
||||||
|
#define MAX_NUMS 25
|
||||||
|
|
||||||
static string_and_token seen_names[MAX_NAMES];
|
static string_and_token seen_names[MAX_NAMES];
|
||||||
static uint8_t seen_names_num;
|
static uint8_t seen_names_count = 0;
|
||||||
|
|
||||||
|
static num_and_token seen_nums[MAX_NAMES] =
|
||||||
|
{
|
||||||
|
[0] = { .num = 0, .tok = { .type = TOK_INT, .data.uid = 0 } },
|
||||||
|
[1] = { .num = 1, .tok = { .type = TOK_INT, .data.uid = 1 } }
|
||||||
|
};
|
||||||
|
static uint8_t seen_nums_count = 2;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_empty (token tok)
|
is_empty (token tok)
|
||||||
@@ -114,7 +129,7 @@ get_char (size_t i)
|
|||||||
|
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
{
|
{
|
||||||
buffer = (char *) malloc (BUFFER_SIZE);
|
buffer = (char *) mem_HeapAllocBlock (BUFFER_SIZE, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||||
error = __fread (buffer, 1, BUFFER_SIZE, file);
|
error = __fread (buffer, 1, BUFFER_SIZE, file);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
return '\0';
|
return '\0';
|
||||||
@@ -184,7 +199,7 @@ decode_keyword (void)
|
|||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
if (!__strncmp (keyword_tokens[i].str, token_start, __strlen (keyword_tokens[i].str)))
|
if (!__strncmp (keyword_tokens[i].str, token_start, (size_t) (buffer - token_start)))
|
||||||
return keyword_tokens[i].tok;
|
return keyword_tokens[i].tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,9 +211,9 @@ convert_seen_name_to_token (void)
|
|||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < seen_names_num; i++)
|
for (i = 0; i < seen_names_count; i++)
|
||||||
{
|
{
|
||||||
if (!__strncmp (seen_names[i].str, token_start, __strlen (seen_names[i].str)))
|
if (!__strncmp (seen_names[i].str, token_start, (size_t) (buffer - token_start)))
|
||||||
return seen_names[i].tok;
|
return seen_names[i].tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +221,33 @@ convert_seen_name_to_token (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_to_seen_tokens (string_and_token snt)
|
add_name_to_seen_tokens (string_and_token snt)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (seen_names_num < MAX_NAMES);
|
JERRY_ASSERT (seen_names_count < MAX_NAMES);
|
||||||
|
|
||||||
snt.tok.data.name = (string_id) seen_names_num;
|
seen_names[seen_names_count++] = snt;
|
||||||
seen_names[seen_names_num++] = snt;
|
}
|
||||||
|
|
||||||
|
static token
|
||||||
|
convert_seen_num_to_token (int num)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < seen_nums_count; i++)
|
||||||
|
{
|
||||||
|
if (seen_nums[i].num == num)
|
||||||
|
return seen_nums[i].tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_num_to_seen_tokens (num_and_token nat)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (seen_nums_count < MAX_NUMS);
|
||||||
|
|
||||||
|
seen_nums[seen_nums_count++] = nat;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
@@ -219,20 +255,32 @@ lexer_get_strings (const char **strings)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < seen_names_num; i++)
|
if (strings)
|
||||||
strings[i] = seen_names[i].str;
|
for (i = 0; i < seen_names_count; i++)
|
||||||
|
strings[i] = seen_names[i].str;
|
||||||
|
|
||||||
return seen_names_num;
|
return seen_names_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
lexer_get_string_by_id (string_id id)
|
lexer_get_string_by_id (uint8_t id)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (id < seen_names_num);
|
JERRY_ASSERT (id < seen_names_count);
|
||||||
|
|
||||||
return seen_names[id].str;
|
return seen_names[id].str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
lexer_get_nums (int *nums)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < seen_nums_count; i++)
|
||||||
|
nums[i] = seen_nums[i].num;
|
||||||
|
|
||||||
|
return seen_nums_count;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
new_token (void)
|
new_token (void)
|
||||||
{
|
{
|
||||||
@@ -254,7 +302,7 @@ current_token (void)
|
|||||||
JERRY_ASSERT (token_start);
|
JERRY_ASSERT (token_start);
|
||||||
JERRY_ASSERT (token_start <= buffer);
|
JERRY_ASSERT (token_start <= buffer);
|
||||||
size_t length = (size_t) (buffer - token_start);
|
size_t length = (size_t) (buffer - token_start);
|
||||||
char *res = (char *) malloc (length + 1);
|
char *res = (char *) mem_HeapAllocBlock (length + 1, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||||
__strncpy (res, token_start, length);
|
__strncpy (res, token_start, length);
|
||||||
res[length] = '\0';
|
res[length] = '\0';
|
||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
@@ -265,7 +313,7 @@ current_token (void)
|
|||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
buffer += NUM; \
|
buffer += NUM; \
|
||||||
return (token) { .type = TOK, .data.none = NULL }; \
|
return (token) { .type = TOK, .data.uid = 0 }; \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
@@ -338,9 +386,9 @@ parse_name (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
string = current_token ();
|
string = current_token ();
|
||||||
known_token = (token) { .type = TOK_NAME, .data.name = seen_names_num };
|
known_token = (token) { .type = TOK_NAME, .data.uid = seen_names_count };
|
||||||
|
|
||||||
add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
add_name_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
||||||
|
|
||||||
return known_token;
|
return known_token;
|
||||||
}
|
}
|
||||||
@@ -387,6 +435,7 @@ parse_number (void)
|
|||||||
bool is_exp = false;
|
bool is_exp = false;
|
||||||
size_t tok_length = 0, i;
|
size_t tok_length = 0, i;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
token known_token;
|
||||||
|
|
||||||
JERRY_ASSERT (__isdigit (c) || c == '.');
|
JERRY_ASSERT (__isdigit (c) || c == '.');
|
||||||
|
|
||||||
@@ -423,7 +472,14 @@ parse_number (void)
|
|||||||
res = (res << 4) + hex_to_int (token_start[i]);
|
res = (res << 4) + hex_to_int (token_start[i]);
|
||||||
|
|
||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
return (token) { .type = TOK_INT, .data.num = res };
|
|
||||||
|
known_token = convert_seen_num_to_token (res);
|
||||||
|
if (!is_empty (known_token))
|
||||||
|
return known_token;
|
||||||
|
|
||||||
|
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
|
||||||
|
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
|
||||||
|
return known_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
JERRY_ASSERT (!is_hex && !is_exp);
|
JERRY_ASSERT (!is_hex && !is_exp);
|
||||||
@@ -475,7 +531,8 @@ parse_number (void)
|
|||||||
{
|
{
|
||||||
float res = __strtof (token_start, NULL);
|
float res = __strtof (token_start, NULL);
|
||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
return (token) { .type = TOK_FLOAT, .data.fp_num = res };
|
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (res);
|
||||||
|
return empty_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
tok_length = (size_t) (buffer - token_start);;
|
tok_length = (size_t) (buffer - token_start);;
|
||||||
@@ -484,7 +541,13 @@ parse_number (void)
|
|||||||
|
|
||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
|
|
||||||
return (token) { .type = TOK_INT, .data.num = res };
|
known_token = convert_seen_num_to_token (res);
|
||||||
|
if (!is_empty (known_token))
|
||||||
|
return known_token;
|
||||||
|
|
||||||
|
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
|
||||||
|
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
|
||||||
|
return known_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char
|
static char
|
||||||
@@ -513,7 +576,7 @@ parse_string (void)
|
|||||||
char *tok = NULL;
|
char *tok = NULL;
|
||||||
char *index = NULL;
|
char *index = NULL;
|
||||||
const char *i;
|
const char *i;
|
||||||
size_t length;
|
size_t length, num;
|
||||||
token res = empty_token;
|
token res = empty_token;
|
||||||
|
|
||||||
JERRY_ASSERT (c == '\'' || c == '"');
|
JERRY_ASSERT (c == '\'' || c == '"');
|
||||||
@@ -553,7 +616,7 @@ parse_string (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
length = (size_t) (buffer - token_start);
|
length = (size_t) (buffer - token_start);
|
||||||
tok = (char *) malloc (length);
|
tok = (char *) mem_HeapAllocBlock (length, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||||
index = tok;
|
index = tok;
|
||||||
|
|
||||||
for (i = token_start; i < buffer; i++)
|
for (i = token_start; i < buffer; i++)
|
||||||
@@ -581,9 +644,18 @@ parse_string (void)
|
|||||||
// Eat up '"'
|
// Eat up '"'
|
||||||
consume_char ();
|
consume_char ();
|
||||||
|
|
||||||
res = (token) { .type = TOK_STRING, .data.str = seen_names_num };
|
for (num = 0; num < seen_names_count; num++)
|
||||||
|
{
|
||||||
|
if (!__strncmp (seen_names[num].str, tok, __strlen (tok)))
|
||||||
|
{
|
||||||
|
mem_HeapFreeBlock ((uint8_t*) tok);
|
||||||
|
return seen_names[num].tok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
res = (token) { .type = TOK_STRING, .data.uid = seen_names_count };
|
||||||
|
|
||||||
|
add_name_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -593,7 +665,7 @@ grobble_whitespaces (void)
|
|||||||
{
|
{
|
||||||
char c = LA (0);
|
char c = LA (0);
|
||||||
|
|
||||||
while ((__isspace (c) && c != '\n') || c == '\0')
|
while ((__isspace (c) && c != '\n'))
|
||||||
{
|
{
|
||||||
consume_char ();
|
consume_char ();
|
||||||
c = LA (0);
|
c = LA (0);
|
||||||
@@ -685,11 +757,11 @@ lexer_next_token (void)
|
|||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
consume_char ();
|
consume_char ();
|
||||||
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
|
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
return (token) { .type = TOK_EOF, .data.none = NULL };;
|
return (token) { .type = TOK_EOF, .data.uid = 0 };;
|
||||||
|
|
||||||
if (c == '\'' || c == '"')
|
if (c == '\'' || c == '"')
|
||||||
return parse_string ();
|
return parse_string ();
|
||||||
@@ -708,7 +780,7 @@ lexer_next_token (void)
|
|||||||
if (c == '/' && LA (1) == '*')
|
if (c == '/' && LA (1) == '*')
|
||||||
{
|
{
|
||||||
if (replace_comment_by_newline ())
|
if (replace_comment_by_newline ())
|
||||||
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
|
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
@@ -803,11 +875,11 @@ lexer_next_token (void)
|
|||||||
token tok = lexer_next_token_private ();
|
token tok = lexer_next_token_private ();
|
||||||
if (tok.type == TOK_NEWLINE)
|
if (tok.type == TOK_NEWLINE)
|
||||||
return tok;
|
return tok;
|
||||||
// if (tok.type == TOK_CLOSE_BRACE)
|
if (tok.type == TOK_CLOSE_PAREN)
|
||||||
{
|
{
|
||||||
// if (i == 300)
|
// if (i == 300)
|
||||||
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
|
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
@@ -816,10 +888,10 @@ lexer_next_token (void)
|
|||||||
void
|
void
|
||||||
lexer_save_token (token tok)
|
lexer_save_token (token tok)
|
||||||
{
|
{
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
// if (tok.type == TOK_CLOSE_BRACE)
|
if (tok.type == TOK_CLOSE_PAREN)
|
||||||
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
|
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
|
||||||
#endif
|
#endif
|
||||||
saved_token = tok;
|
saved_token = tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+104
-112
@@ -18,121 +18,120 @@
|
|||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
typedef uint8_t string_id;
|
|
||||||
|
|
||||||
/* Keywords. */
|
/* Keywords. */
|
||||||
typedef enum
|
typedef uint8_t keyword;
|
||||||
{
|
|
||||||
/* Not a keyword. */
|
|
||||||
KW_NONE = 0,
|
|
||||||
/* Future reserved keyword. */
|
|
||||||
KW_RESERVED,
|
|
||||||
|
|
||||||
KW_BREAK,
|
/* Not a keyword. */
|
||||||
KW_CASE,
|
#define KW_NONE 0
|
||||||
KW_CATCH,
|
/* Future reserved keyword. */
|
||||||
KW_CONTINUE,
|
#define KW_RESERVED 1
|
||||||
KW_DEBUGGER,
|
#define KW_BREAK 2
|
||||||
KW_DEFAULT,
|
#define KW_CASE 3
|
||||||
KW_DELETE,
|
#define KW_CATCH 4
|
||||||
|
|
||||||
KW_DO,
|
#define KW_CONTINUE 5
|
||||||
KW_ELSE,
|
#define KW_DEBUGGER 6
|
||||||
KW_FINALLY,
|
#define KW_DEFAULT 7
|
||||||
KW_FOR,
|
#define KW_DELETE 8
|
||||||
KW_FUNCTION,
|
#define KW_DO 9
|
||||||
KW_IF,
|
|
||||||
KW_IN,
|
|
||||||
|
|
||||||
KW_INSTANCEOF,
|
#define KW_ELSE 10
|
||||||
KW_NEW,
|
#define KW_FINALLY 11
|
||||||
KW_RETURN,
|
#define KW_FOR 12
|
||||||
KW_SWITCH,
|
#define KW_FUNCTION 13
|
||||||
KW_THIS,
|
#define KW_IF 14
|
||||||
KW_THROW,
|
|
||||||
KW_TRY,
|
#define KW_IN 15
|
||||||
|
#define KW_INSTANCEOF 16
|
||||||
|
#define KW_NEW 17
|
||||||
|
#define KW_RETURN 18
|
||||||
|
#define KW_SWITCH 19
|
||||||
|
|
||||||
|
#define KW_THIS 20
|
||||||
|
#define KW_THROW 21
|
||||||
|
#define KW_TRY 22
|
||||||
|
#define KW_TYPEOF 23
|
||||||
|
#define KW_VAR 24
|
||||||
|
|
||||||
|
#define KW_VOID 25
|
||||||
|
#define KW_WHILE 26
|
||||||
|
#define KW_WITH 27
|
||||||
|
|
||||||
KW_TYPEOF,
|
|
||||||
KW_VAR,
|
|
||||||
KW_VOID,
|
|
||||||
KW_WHILE,
|
|
||||||
KW_WITH
|
|
||||||
}
|
|
||||||
keyword;
|
|
||||||
|
|
||||||
/* Type of tokens. */
|
/* Type of tokens. */
|
||||||
typedef enum
|
typedef uint8_t token_type;
|
||||||
{
|
|
||||||
TOK_EOF = 0x0, // End of file
|
|
||||||
TOK_NAME = 0x1, // Identifier
|
|
||||||
TOK_KEYWORD = 0x2, // Keyword
|
|
||||||
TOK_INT = 0x3,
|
|
||||||
TOK_FLOAT = 0x4,
|
|
||||||
TOK_NULL = 0x5,
|
|
||||||
TOK_BOOL = 0x6,
|
|
||||||
TOK_NEWLINE = 0x7,
|
|
||||||
TOK_STRING = 0x8,
|
|
||||||
|
|
||||||
/* Punctuators. */
|
#define TOK_EOF 0 // End of file
|
||||||
TOK_OPEN_BRACE = 0x9, // {
|
#define TOK_NAME 1 // Identifier
|
||||||
TOK_CLOSE_BRACE = 0xa, // }
|
#define TOK_KEYWORD 2 // Keyword
|
||||||
TOK_OPEN_PAREN = 0xb, // (
|
#define TOK_INT 3
|
||||||
TOK_CLOSE_PAREN = 0xc, // )
|
#define TOK_FLOAT 4
|
||||||
TOK_OPEN_SQUARE, // [
|
|
||||||
TOK_CLOSE_SQUARE, // [
|
|
||||||
|
|
||||||
TOK_DOT, // .
|
#define TOK_NULL 5
|
||||||
TOK_SEMICOLON, // ;
|
#define TOK_BOOL 6
|
||||||
TOK_COMMA, // ,
|
#define TOK_NEWLINE 7
|
||||||
TOK_LESS, // <
|
#define TOK_STRING 8
|
||||||
TOK_GREATER, // >
|
#define TOK_OPEN_BRACE 9 // {
|
||||||
TOK_LESS_EQ, // <=
|
|
||||||
|
|
||||||
TOK_GREATER_EQ, // <=
|
#define TOK_CLOSE_BRACE 10 // }
|
||||||
TOK_DOUBLE_EQ, // ==
|
#define TOK_OPEN_PAREN 11 // (
|
||||||
TOK_NOT_EQ, // !=
|
#define TOK_CLOSE_PAREN 12 // )
|
||||||
TOK_TRIPLE_EQ, // ===
|
#define TOK_OPEN_SQUARE 13 // [
|
||||||
TOK_NOT_DOUBLE_EQ, // !==
|
#define TOK_CLOSE_SQUARE 14 // [
|
||||||
|
|
||||||
TOK_PLUS, // +
|
#define TOK_DOT 15 // .
|
||||||
TOK_MINUS, // -
|
#define TOK_SEMICOLON 16 // ;
|
||||||
TOK_MULT, // *
|
#define TOK_COMMA 17 // ,
|
||||||
TOK_MOD, // %
|
#define TOK_LESS 18 // <
|
||||||
TOK_DOUBLE_PLUS, // ++
|
#define TOK_GREATER 19 // >
|
||||||
TOK_DOUBLE_MINUS, // --
|
|
||||||
|
|
||||||
TOK_LSHIFT, // <<
|
#define TOK_LESS_EQ 20 // <=
|
||||||
TOK_RSHIFT, // >>
|
#define TOK_GREATER_EQ 21 // <=
|
||||||
TOK_RSHIFT_EX, // >>>
|
#define TOK_DOUBLE_EQ 22 // ==
|
||||||
TOK_AND, // &
|
#define TOK_NOT_EQ 23 // !=
|
||||||
TOK_OR, // |
|
#define TOK_TRIPLE_EQ 24 // ===
|
||||||
TOK_XOR, // ^
|
|
||||||
|
|
||||||
TOK_NOT, // !
|
#define TOK_NOT_DOUBLE_EQ 25 // !==
|
||||||
TOK_COMPL, // ~
|
#define TOK_PLUS 26 // +
|
||||||
TOK_DOUBLE_AND, // &&
|
#define TOK_MINUS 27 // -
|
||||||
TOK_DOUBLE_OR, // ||
|
#define TOK_MULT 28 // *
|
||||||
TOK_QUERY, // ?
|
#define TOK_MOD 29 // %
|
||||||
TOK_COLON, // :
|
|
||||||
|
|
||||||
TOK_EQ, // =
|
#define TOK_DOUBLE_PLUS 30 // ++
|
||||||
TOK_PLUS_EQ, // +=
|
#define TOK_DOUBLE_MINUS 31 // --
|
||||||
TOK_MINUS_EQ, // -=
|
#define TOK_LSHIFT 32 // <<
|
||||||
TOK_MULT_EQ, // *=
|
#define TOK_RSHIFT 33 // >>
|
||||||
TOK_MOD_EQ, // %=
|
#define TOK_RSHIFT_EX 34 // >>>
|
||||||
TOK_LSHIFT_EQ, // <<=
|
|
||||||
|
|
||||||
TOK_RSHIFT_EQ, // >>=
|
#define TOK_AND 35 // &
|
||||||
TOK_RSHIFT_EX_EQ, // >>>=
|
#define TOK_OR 36 // |
|
||||||
TOK_AND_EQ, // &=
|
#define TOK_XOR 37 // ^
|
||||||
TOK_OR_EQ, // |=
|
#define TOK_NOT 38 // !
|
||||||
TOK_XOR_EQ, // ^=
|
#define TOK_COMPL 39 // ~
|
||||||
|
|
||||||
|
#define TOK_DOUBLE_AND 40 // &&
|
||||||
|
#define TOK_DOUBLE_OR 41 // ||
|
||||||
|
#define TOK_QUERY 42 // ?
|
||||||
|
#define TOK_COLON 43 // :
|
||||||
|
#define TOK_EQ 44 // =
|
||||||
|
|
||||||
|
#define TOK_PLUS_EQ 45 // +=
|
||||||
|
#define TOK_MINUS_EQ 46 // -=
|
||||||
|
#define TOK_MULT_EQ 47 // *=
|
||||||
|
#define TOK_MOD_EQ 48 // %=
|
||||||
|
#define TOK_LSHIFT_EQ 49 // <<=
|
||||||
|
|
||||||
|
#define TOK_RSHIFT_EQ 50 // >>=
|
||||||
|
#define TOK_RSHIFT_EX_EQ 51 // >>>=
|
||||||
|
#define TOK_AND_EQ 52 // &=
|
||||||
|
#define TOK_OR_EQ 53 // |=
|
||||||
|
#define TOK_XOR_EQ 54 // ^=
|
||||||
|
|
||||||
|
#define TOK_DIV 55 // /
|
||||||
|
#define TOK_DIV_EQ 56 // /=
|
||||||
|
#define TOK_EMPTY 57
|
||||||
|
|
||||||
TOK_DIV, // /
|
|
||||||
TOK_DIV_EQ, // /=
|
|
||||||
TOK_EMPTY
|
|
||||||
}
|
|
||||||
token_type;
|
|
||||||
|
|
||||||
/* Represents the contents of a token. */
|
/* Represents the contents of a token. */
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -140,17 +139,12 @@ typedef struct
|
|||||||
token_type type;
|
token_type type;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
void *none;
|
keyword kw;
|
||||||
keyword kw;
|
uint8_t uid;
|
||||||
string_id name;
|
}
|
||||||
bool is_true;
|
|
||||||
int num;
|
|
||||||
float fp_num;
|
|
||||||
string_id str;
|
|
||||||
}
|
|
||||||
data;
|
data;
|
||||||
}
|
} __packed
|
||||||
token;
|
token;
|
||||||
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
@@ -160,11 +154,9 @@ void lexer_set_source (const char *);
|
|||||||
#endif
|
#endif
|
||||||
token lexer_next_token (void);
|
token lexer_next_token (void);
|
||||||
void lexer_save_token (token);
|
void lexer_save_token (token);
|
||||||
|
|
||||||
void lexer_dump_buffer_state (void);
|
void lexer_dump_buffer_state (void);
|
||||||
|
|
||||||
uint8_t lexer_get_strings (const char **);
|
uint8_t lexer_get_strings (const char **);
|
||||||
|
const char *lexer_get_string_by_id (uint8_t);
|
||||||
const char *lexer_get_string_by_id (string_id id);
|
uint8_t lexer_get_nums (int *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1367
-964
File diff suppressed because it is too large
Load Diff
+1
-420
@@ -18,427 +18,8 @@
|
|||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#define null_string 255
|
|
||||||
#define MAX_PARAMS 5
|
|
||||||
#define MAX_EXPRS 2
|
|
||||||
#define MAX_PROPERTIES 5
|
|
||||||
#define MAX_DECLS 5
|
|
||||||
#define MAX_SUFFIXES 2
|
|
||||||
|
|
||||||
/** Represents list of parameters. */
|
|
||||||
typedef struct formal_parameter_list
|
|
||||||
{
|
|
||||||
/** Identifiers of a parameter. Next after last parameter is NULL. */
|
|
||||||
uint8_t names[MAX_PARAMS];
|
|
||||||
}
|
|
||||||
formal_parameter_list;
|
|
||||||
|
|
||||||
static const formal_parameter_list
|
|
||||||
empty_formal_parameter_list =
|
|
||||||
{
|
|
||||||
.names = { [0] = null_string }
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_formal_parameter_list_empty (formal_parameter_list);
|
|
||||||
|
|
||||||
/** @function_declaration represents both declaration and expression of a function.
|
|
||||||
After this parser must return a block of statements. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Identifier: name of a function. Can be NULL for anonimous functions. */
|
|
||||||
uint8_t name;
|
|
||||||
/** List of parameter of a function. Can be NULL. */
|
|
||||||
formal_parameter_list params;
|
|
||||||
}
|
|
||||||
function_declaration;
|
|
||||||
|
|
||||||
typedef function_declaration function_expression;
|
|
||||||
|
|
||||||
/** Types of literals: null, bool, decimal and string.
|
|
||||||
Decimal type is represented by LIT_INT and supports only double-word sized integers. */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
LIT_NULL,
|
|
||||||
LIT_BOOL,
|
|
||||||
LIT_INT,
|
|
||||||
LIT_STR
|
|
||||||
}
|
|
||||||
literal_type;
|
|
||||||
|
|
||||||
/** Represents different literals, contains a data of them. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Type of a literal. */
|
|
||||||
literal_type type;
|
|
||||||
|
|
||||||
/** Value of a literal. */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
/** Used by null literal, always NULL. */
|
|
||||||
void *none;
|
|
||||||
/** String literal value. */
|
|
||||||
uint8_t str;
|
|
||||||
/** Number value. */
|
|
||||||
int num;
|
|
||||||
/** Boolean value. */
|
|
||||||
bool is_true;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
literal;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool is_literal;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
void *none;
|
|
||||||
literal lit;
|
|
||||||
uint8_t name;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
operand;
|
|
||||||
|
|
||||||
typedef operand property_name;
|
|
||||||
|
|
||||||
static const operand
|
|
||||||
empty_operand =
|
|
||||||
{
|
|
||||||
.is_literal = false,
|
|
||||||
.data.none = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_operand_empty (operand);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
operand op1, op2;
|
|
||||||
}
|
|
||||||
operand_pair;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
operand ops[MAX_PARAMS];
|
|
||||||
}
|
|
||||||
operand_list;
|
|
||||||
|
|
||||||
static const operand_list
|
|
||||||
empty_operand_list =
|
|
||||||
{
|
|
||||||
.ops = { [0] = { .is_literal = false, .data.none = NULL } }
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_operand_list_empty (operand_list);
|
|
||||||
|
|
||||||
typedef operand_list array_literal;
|
|
||||||
typedef operand_list argument_list;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t name;
|
|
||||||
argument_list args;
|
|
||||||
}
|
|
||||||
call_expression;
|
|
||||||
|
|
||||||
/** Represents a single property. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Name of property. */
|
|
||||||
property_name name;
|
|
||||||
/** Value of property. */
|
|
||||||
operand value;
|
|
||||||
}
|
|
||||||
property;
|
|
||||||
|
|
||||||
static const property empty_property =
|
|
||||||
{
|
|
||||||
.name = { .is_literal = false, .data.none = NULL },
|
|
||||||
.value = { .is_literal = false, .data.none = NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_property_empty (property);
|
|
||||||
|
|
||||||
/** List of properties. Represents ObjectLiteral. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Properties. */
|
|
||||||
property props[MAX_PROPERTIES];
|
|
||||||
}
|
|
||||||
property_list;
|
|
||||||
|
|
||||||
static const property_list
|
|
||||||
empty_property_list =
|
|
||||||
{
|
|
||||||
.props =
|
|
||||||
{ [0] =
|
|
||||||
{ .name =
|
|
||||||
{ .is_literal = false, .data.none = NULL },
|
|
||||||
.value =
|
|
||||||
{ .is_literal = false, .data.none = NULL }}}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_property_list_empty (property_list);
|
|
||||||
|
|
||||||
typedef property_list object_literal;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
AO_NONE,
|
|
||||||
AO_EQ,
|
|
||||||
AO_MULT_EQ,
|
|
||||||
AO_DIV_EQ,
|
|
||||||
AO_MOD_EQ,
|
|
||||||
AO_PLUS_EQ,
|
|
||||||
AO_MINUS_EQ,
|
|
||||||
AO_LSHIFT_EQ,
|
|
||||||
AO_RSHIFT_EQ,
|
|
||||||
AO_RSHIFT_EX_EQ,
|
|
||||||
AO_AND_EQ,
|
|
||||||
AO_XOR_EQ,
|
|
||||||
AO_OR_EQ
|
|
||||||
}
|
|
||||||
assignment_operator;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ET_NONE,
|
|
||||||
ET_LOGICAL_OR,
|
|
||||||
ET_LOGICAL_AND,
|
|
||||||
ET_BITWISE_OR,
|
|
||||||
ET_BITWISE_XOR,
|
|
||||||
ET_BITWISE_AND,
|
|
||||||
ET_DOUBLE_EQ,
|
|
||||||
ET_NOT_EQ,
|
|
||||||
ET_TRIPLE_EQ,
|
|
||||||
ET_NOT_DOUBLE_EQ,
|
|
||||||
ET_LESS,
|
|
||||||
ET_GREATER,
|
|
||||||
ET_LESS_EQ,
|
|
||||||
ET_GREATER_EQ,
|
|
||||||
ET_INSTANCEOF,
|
|
||||||
ET_IN,
|
|
||||||
ET_LSHIFT,
|
|
||||||
ET_RSHIFT,
|
|
||||||
ET_RSHIFT_EX,
|
|
||||||
ET_PLUS,
|
|
||||||
ET_MINUS,
|
|
||||||
ET_MULT,
|
|
||||||
ET_DIV,
|
|
||||||
ET_MOD,
|
|
||||||
ET_UNARY_DELETE,
|
|
||||||
ET_UNARY_VOID,
|
|
||||||
ET_UNARY_TYPEOF,
|
|
||||||
ET_UNARY_INCREMENT,
|
|
||||||
ET_UNARY_DECREMENT,
|
|
||||||
ET_UNARY_PLUS,
|
|
||||||
ET_UNARY_MINUS,
|
|
||||||
ET_UNARY_COMPL,
|
|
||||||
ET_UNARY_NOT,
|
|
||||||
ET_POSTFIX_INCREMENT,
|
|
||||||
ET_POSTFIX_DECREMENT,
|
|
||||||
ET_CALL,
|
|
||||||
ET_NEW,
|
|
||||||
ET_INDEX,
|
|
||||||
ET_PROP_REF,
|
|
||||||
ET_OBJECT,
|
|
||||||
ET_FUNCTION,
|
|
||||||
ET_ARRAY,
|
|
||||||
ET_SUBEXPRESSION,
|
|
||||||
ET_LITERAL,
|
|
||||||
ET_IDENTIFIER
|
|
||||||
}
|
|
||||||
expression_type;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
assignment_operator oper;
|
|
||||||
expression_type type;
|
|
||||||
|
|
||||||
/** NUllable. */
|
|
||||||
uint8_t var;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
void *none;
|
|
||||||
operand_pair ops;
|
|
||||||
call_expression call_expr;
|
|
||||||
array_literal arr_lit;
|
|
||||||
object_literal obj_lit;
|
|
||||||
function_expression func_expr;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
assignment_expression;
|
|
||||||
|
|
||||||
static const assignment_expression
|
|
||||||
empty_expression =
|
|
||||||
{
|
|
||||||
.oper = AO_NONE,
|
|
||||||
.type = ET_NONE,
|
|
||||||
.data.none = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_expression_empty (assignment_expression);
|
|
||||||
|
|
||||||
/** Represents expression, array literal and list of argument. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Single assignment expression. Cannot be NULL for expression and list of arguments.
|
|
||||||
But can be NULL for array literal. */
|
|
||||||
assignment_expression exprs[MAX_EXPRS];
|
|
||||||
}
|
|
||||||
expression_list;
|
|
||||||
|
|
||||||
typedef expression_list expression;
|
|
||||||
|
|
||||||
/* Statements. */
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t name;
|
|
||||||
assignment_expression assign_expr;
|
|
||||||
}
|
|
||||||
variable_declaration;
|
|
||||||
|
|
||||||
static const variable_declaration
|
|
||||||
empty_variable_declaration =
|
|
||||||
{
|
|
||||||
.name = null_string,
|
|
||||||
.assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_variable_declaration_empty (variable_declaration);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
variable_declaration decls[MAX_DECLS];
|
|
||||||
}
|
|
||||||
variable_declaration_list;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool is_decl;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
expression expr;
|
|
||||||
variable_declaration_list decl_list;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
for_statement_initialiser_part;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
for_statement_initialiser_part init;
|
|
||||||
assignment_expression limit, incr;
|
|
||||||
}
|
|
||||||
for_statement;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool is_decl;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
assignment_expression left_hand_expr;
|
|
||||||
variable_declaration decl;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
for_in_statement_initializer_part;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
for_in_statement_initializer_part init;
|
|
||||||
expression list_expr;
|
|
||||||
}
|
|
||||||
for_in_statement;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool is_for_in;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
for_statement for_stmt;
|
|
||||||
for_in_statement for_in_stmt;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
for_or_for_in_statement;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
STMT_NULL,
|
|
||||||
STMT_VARIABLE,
|
|
||||||
STMT_EMPTY,
|
|
||||||
STMT_IF,
|
|
||||||
STMT_ELSE,
|
|
||||||
STMT_ELSE_IF,
|
|
||||||
STMT_END_IF,
|
|
||||||
STMT_DO_WHILE,
|
|
||||||
STMT_END_DO_WHILE,
|
|
||||||
STMT_WHILE,
|
|
||||||
|
|
||||||
STMT_END_WHILE,
|
|
||||||
STMT_FOR_OR_FOR_IN,
|
|
||||||
STMT_END_FOR_OR_FOR_IN,
|
|
||||||
STMT_CONTINUE,
|
|
||||||
STMT_BREAK,
|
|
||||||
STMT_RETURN,
|
|
||||||
STMT_WITH,
|
|
||||||
STMT_END_WITH,
|
|
||||||
STMT_LABELLED,
|
|
||||||
STMT_SWITCH,
|
|
||||||
|
|
||||||
STMT_END_SWITCH,
|
|
||||||
STMT_CASE,
|
|
||||||
STMT_THROW,
|
|
||||||
STMT_TRY,
|
|
||||||
STMT_CATCH,
|
|
||||||
STMT_END_CATCH,
|
|
||||||
STMT_FINALLY,
|
|
||||||
STMT_END_FINALLY,
|
|
||||||
STMT_EXPRESSION,
|
|
||||||
STMT_END_SUBEXPRESSION,
|
|
||||||
|
|
||||||
STMT_FUNCTION,
|
|
||||||
STMT_END_FUNCTION,
|
|
||||||
STMT_EOF
|
|
||||||
}
|
|
||||||
statement_type;
|
|
||||||
|
|
||||||
typedef struct statement
|
|
||||||
{
|
|
||||||
statement_type type;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
void *none;
|
|
||||||
variable_declaration_list var_stmt;
|
|
||||||
assignment_expression expr;
|
|
||||||
for_or_for_in_statement for_stmt;
|
|
||||||
uint8_t name;
|
|
||||||
function_declaration fun_decl;
|
|
||||||
}
|
|
||||||
data;
|
|
||||||
}
|
|
||||||
statement;
|
|
||||||
|
|
||||||
static const statement
|
|
||||||
null_statement =
|
|
||||||
{
|
|
||||||
.type = STMT_NULL,
|
|
||||||
.data.none = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_statement_null (statement);
|
|
||||||
|
|
||||||
void parser_init (void);
|
void parser_init (void);
|
||||||
statement parser_parse_statement (void);
|
void parser_parse_program (void);
|
||||||
|
|
||||||
void parser_fatal (jerry_Status_t code);
|
void parser_fatal (jerry_Status_t code);
|
||||||
|
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ jerry_Exit( jerry_Status_t code) /**< status code */
|
|||||||
case ERR_GENERAL:
|
case ERR_GENERAL:
|
||||||
__printf("ERR_GENERAL\n");
|
__printf("ERR_GENERAL\n");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
__printf( "Return code is zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
jerry_AssertFail( "Return code is zero", __FILE__, __LINE__);
|
|
||||||
}
|
}
|
||||||
#endif /* !JERRY_NDEBUG */
|
#endif /* !JERRY_NDEBUG */
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
|||||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PRETTY_PRINTER_H
|
|
||||||
#define PRETTY_PRINTER_H
|
|
||||||
|
|
||||||
#include "lexer.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
void pp_reset (void);
|
|
||||||
void pp_finish (void);
|
|
||||||
void pp_token (token);
|
|
||||||
void pp_keyword (keyword);
|
|
||||||
void pp_statement (statement);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -22,4 +22,6 @@ void serializer_init (void);
|
|||||||
|
|
||||||
void serializer_dump_data (const void *, size_t);
|
void serializer_dump_data (const void *, size_t);
|
||||||
|
|
||||||
|
void serializer_rewrite_data (const int8_t, const void *, size_t);
|
||||||
|
|
||||||
#endif // SERIALIZER_H
|
#endif // SERIALIZER_H
|
||||||
@@ -15,17 +15,39 @@
|
|||||||
|
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "jerry-libc.h"
|
#include "jerry-libc.h"
|
||||||
|
#include "opcodes.h"
|
||||||
|
|
||||||
|
FILE *dump;
|
||||||
|
|
||||||
|
#define OPCODE_STR(op) \
|
||||||
|
#op,
|
||||||
|
|
||||||
|
static char* massive[] = {
|
||||||
|
OP_LIST (OPCODE_STR)
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
serializer_init (void)
|
serializer_init (void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int opcode_counter = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
serializer_dump_data (const void *data, size_t size)
|
serializer_dump_data (const void *data, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
__printf ("%03d: %20s ", opcode_counter++, massive[(int)((char*)data)[0]]);
|
||||||
__putchar (((char *) data)[i]);
|
for (i = 1; i < size; i++)
|
||||||
|
__printf ("%4d ", ((char*)data)[i]);
|
||||||
|
|
||||||
|
__printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serializer_rewrite_data (const int8_t offset __unused, const void *data __unused, size_t size __unused)
|
||||||
|
{
|
||||||
|
TODO (implement);
|
||||||
}
|
}
|
||||||
+19
-85
@@ -35,8 +35,6 @@
|
|||||||
#include "jerry-libc.h"
|
#include "jerry-libc.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "pretty-printer.h"
|
|
||||||
#include "bytecode-generator.h"
|
|
||||||
|
|
||||||
#define DUMP_TOKENS (1u << 0)
|
#define DUMP_TOKENS (1u << 0)
|
||||||
#define DUMP_AST (1u << 1)
|
#define DUMP_AST (1u << 1)
|
||||||
@@ -99,27 +97,9 @@ fake_exit (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
check_for_several_dumps (uint8_t dump)
|
|
||||||
{
|
|
||||||
bool was_bit = 0;
|
|
||||||
for (; dump; dump >>= 1)
|
|
||||||
{
|
|
||||||
if (dump & 1u)
|
|
||||||
{
|
|
||||||
if (was_bit)
|
|
||||||
jerry_Exit (ERR_SEVERAL_FILES);
|
|
||||||
else
|
|
||||||
was_bit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
statement st;
|
|
||||||
uint8_t dump = 0;
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
const char *file_name = NULL;
|
const char *file_name = NULL;
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
@@ -127,27 +107,15 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
mem_Init ();
|
mem_Init ();
|
||||||
|
|
||||||
if (argc > 0)
|
|
||||||
for (int i = 1; i < argc; i++)
|
|
||||||
{
|
|
||||||
if (!__strcmp ("-t", argv[i]))
|
|
||||||
dump |= DUMP_TOKENS;
|
|
||||||
else if (!__strcmp ("-a", argv[i]))
|
|
||||||
dump |= DUMP_AST;
|
|
||||||
else if (!__strcmp ("-b", argv[i]))
|
|
||||||
dump |= DUMP_BYTECODE;
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
else if (file_name == NULL)
|
if (argc > 0)
|
||||||
file_name = argv[i];
|
{
|
||||||
#endif
|
if (file_name == NULL)
|
||||||
|
file_name = argv[1];
|
||||||
else
|
else
|
||||||
jerry_Exit (ERR_SEVERAL_FILES);
|
jerry_Exit (ERR_SEVERAL_FILES);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
check_for_several_dumps (dump);
|
|
||||||
|
|
||||||
if (!dump)
|
|
||||||
dump |= DUMP_BYTECODE;
|
|
||||||
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
if (file_name == NULL)
|
if (file_name == NULL)
|
||||||
@@ -165,60 +133,26 @@ main (int argc, char **argv)
|
|||||||
lexer_set_source (generated_source);
|
lexer_set_source (generated_source);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dump & DUMP_AST)
|
// const char *strings[MAX_STRINGS];
|
||||||
{
|
// uint8_t strings_num;
|
||||||
parser_init ();
|
// First run parser to fill list of strings
|
||||||
st = parser_parse_statement ();
|
token tok = lexer_next_token ();
|
||||||
JERRY_ASSERT (!is_statement_null (st));
|
while (tok.type != TOK_EOF)
|
||||||
while (st.type != STMT_EOF)
|
tok = lexer_next_token ();
|
||||||
{
|
|
||||||
pp_statement (st);
|
|
||||||
st = parser_parse_statement ();
|
|
||||||
JERRY_ASSERT (!is_statement_null (st));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dump & DUMP_TOKENS)
|
// strings_num = lexer_get_strings (strings);
|
||||||
{
|
|
||||||
token tok = lexer_next_token ();
|
|
||||||
while (tok.type != TOK_EOF)
|
|
||||||
{
|
|
||||||
pp_token (tok);
|
|
||||||
tok = lexer_next_token ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dump & DUMP_BYTECODE)
|
// Reset lexer
|
||||||
{
|
|
||||||
const char *strings[MAX_STRINGS];
|
|
||||||
uint8_t strings_num;
|
|
||||||
// First run parser to fill list of strings
|
|
||||||
token tok = lexer_next_token ();
|
|
||||||
while (tok.type != TOK_EOF)
|
|
||||||
tok = lexer_next_token ();
|
|
||||||
|
|
||||||
strings_num = lexer_get_strings (strings);
|
|
||||||
|
|
||||||
// Reset lexer
|
|
||||||
#ifdef __HOST
|
#ifdef __HOST
|
||||||
__rewind (file);
|
__rewind (file);
|
||||||
lexer_set_file (file);
|
lexer_set_file (file);
|
||||||
#else
|
#else
|
||||||
lexer_set_source (generated_source);
|
lexer_set_source (generated_source);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
parser_init ();
|
parser_init ();
|
||||||
generator_init ();
|
TODO (serializer_dump_data (strings strings_num));
|
||||||
generator_dump_strings (strings, strings_num);
|
parser_parse_program ();
|
||||||
st = parser_parse_statement ();
|
|
||||||
JERRY_ASSERT (!is_statement_null (st));
|
|
||||||
while (st.type != STMT_EOF)
|
|
||||||
{
|
|
||||||
generator_dump_statement (st);
|
|
||||||
st = parser_parse_statement ();
|
|
||||||
JERRY_ASSERT (!is_statement_null (st));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//gen_bytecode (generated_source);
|
//gen_bytecode (generated_source);
|
||||||
//gen_bytecode ();
|
//gen_bytecode ();
|
||||||
|
|||||||
Reference in New Issue
Block a user