static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat) { /* It's challenging for parser to distinguish parameterized assignment with one argument from call * with equality expression argument, so we do it in compiler. */ if(!stat->is_strict && stat->expr->args && !stat->expr->args->next && stat->expr->args->type == EXPR_EQUAL) { binary_expression_t *eqexpr = (binary_expression_t*)stat->expr->args; if(eqexpr->left->type == EXPR_BRACKETS) { member_expression_t new_member = *stat->expr; WARN("converting call expr to assign expr\n"); new_member.args = ((unary_expression_t*)eqexpr->left)->subexpr; return compile_assignment(ctx, &new_member, eqexpr->right, FALSE); } } return compile_member_expression(ctx, stat->expr, FALSE); }
static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) { HRESULT hres; while(stat) { switch(stat->type) { case STAT_ASSIGN: hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE); break; case STAT_CALL: hres = compile_member_expression(ctx, ((call_statement_t*)stat)->expr, FALSE); break; case STAT_DIM: hres = compile_dim_statement(ctx, (dim_statement_t*)stat); break; case STAT_DOWHILE: case STAT_DOUNTIL: hres = compile_dowhile_statement(ctx, (while_statement_t*)stat); break; case STAT_EXITDO: hres = compile_exitdo_statement(ctx); break; case STAT_EXITFUNC: hres = compile_exitfunc_statement(ctx); break; case STAT_EXITPROP: hres = compile_exitprop_statement(ctx); break; case STAT_EXITSUB: hres = compile_exitsub_statement(ctx); break; case STAT_FUNC: hres = compile_function_statement(ctx, (function_statement_t*)stat); break; case STAT_IF: hres = compile_if_statement(ctx, (if_statement_t*)stat); break; case STAT_ONERROR: hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat); break; case STAT_SET: hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE); break; case STAT_STOP: hres = push_instr(ctx, OP_stop) == -1 ? E_OUTOFMEMORY : S_OK; break; case STAT_UNTIL: case STAT_WHILE: case STAT_WHILELOOP: hres = compile_while_statement(ctx, (while_statement_t*)stat); break; default: FIXME("Unimplemented statement type %d\n", stat->type); hres = E_NOTIMPL; } if(FAILED(hres)) return hres; stat = stat->next; } return S_OK; }
static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr) { switch(expr->type) { case EXPR_ADD: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add); case EXPR_AND: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and); case EXPR_BOOL: return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value); case EXPR_CONCAT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat); case EXPR_DIV: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div); case EXPR_DOUBLE: return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value); case EXPR_EMPTY: return push_instr(ctx, OP_empty) != -1 ? S_OK : E_OUTOFMEMORY; case EXPR_EQUAL: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal); case EXPR_EQV: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv); case EXPR_EXP: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp); case EXPR_GT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); case EXPR_GTEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq); case EXPR_IDIV: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv); case EXPR_IS: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is); case EXPR_IMP: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp); case EXPR_LT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt); case EXPR_LTEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq); case EXPR_ME: return push_instr(ctx, OP_me) != -1 ? S_OK : E_OUTOFMEMORY; case EXPR_MEMBER: return compile_member_expression(ctx, (member_expression_t*)expr, TRUE); case EXPR_MOD: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod); case EXPR_MUL: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul); case EXPR_NEG: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg); case EXPR_NEQUAL: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal); case EXPR_NEW: return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value); case EXPR_NOT: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not); case EXPR_NOTHING: return push_instr(ctx, OP_nothing) != -1 ? S_OK : E_OUTOFMEMORY; case EXPR_NULL: return push_instr(ctx, OP_null) != -1 ? S_OK : E_OUTOFMEMORY; case EXPR_OR: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or); case EXPR_STRING: return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value); case EXPR_SUB: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); case EXPR_USHORT: return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value); case EXPR_ULONG: return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value); case EXPR_XOR: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); default: FIXME("Unimplemented expression type %d\n", expr->type); return E_NOTIMPL; } return S_OK; }
static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, BOOL *no_ret) { switch(expr->type) { case EXPR_ADD: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add); case EXPR_AND: return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z); case EXPR_ARRAY: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array); case EXPR_ARRAYLIT: return compile_array_literal(ctx, (array_literal_expression_t*)expr); case EXPR_ASSIGN: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST); case EXPR_ASSIGNADD: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add); case EXPR_ASSIGNAND: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and); case EXPR_ASSIGNSUB: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub); case EXPR_ASSIGNMUL: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul); case EXPR_ASSIGNDIV: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div); case EXPR_ASSIGNMOD: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod); case EXPR_ASSIGNOR: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or); case EXPR_ASSIGNLSHIFT: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift); case EXPR_ASSIGNRSHIFT: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift); case EXPR_ASSIGNRRSHIFT: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2); case EXPR_ASSIGNXOR: return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor); case EXPR_BAND: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and); case EXPR_BITNEG: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg); case EXPR_BOR: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or); case EXPR_CALL: return compile_call_expression(ctx, (call_expression_t*)expr, no_ret); case EXPR_COMMA: return compile_comma_expression(ctx, (binary_expression_t*)expr); case EXPR_COND: return compile_conditional_expression(ctx, (conditional_expression_t*)expr); case EXPR_DELETE: return compile_delete_expression(ctx, (unary_expression_t*)expr); case EXPR_DIV: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div); case EXPR_EQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq); case EXPR_EQEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2); case EXPR_FUNC: return compile_function_expression(ctx, (function_expression_t*)expr); case EXPR_GREATER: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); case EXPR_GREATEREQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq); case EXPR_IDENT: return push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier); case EXPR_IN: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in); case EXPR_INSTANCEOF: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof); case EXPR_LESS: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt); case EXPR_LESSEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq); case EXPR_LITERAL: return compile_literal(ctx, ((literal_expression_t*)expr)->literal); case EXPR_LOGNEG: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg); case EXPR_LSHIFT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift); case EXPR_MEMBER: return compile_member_expression(ctx, (member_expression_t*)expr); case EXPR_MINUS: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus); case EXPR_MOD: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod); case EXPR_MUL: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul); case EXPR_NEW: return compile_new_expression(ctx, (call_expression_t*)expr); case EXPR_NOTEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq); case EXPR_NOTEQEQ: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2); case EXPR_OR: return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz); case EXPR_PLUS: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum); case EXPR_POSTDEC: return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1); case EXPR_POSTINC: return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1); case EXPR_PREDEC: return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1); case EXPR_PREINC: return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1); case EXPR_PROPVAL: return compile_object_literal(ctx, (property_value_expression_t*)expr); case EXPR_RSHIFT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift); case EXPR_RRSHIFT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2); case EXPR_SUB: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); case EXPR_THIS: return push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY; case EXPR_TYPEOF: return compile_typeof_expression(ctx, (unary_expression_t*)expr); case EXPR_VOID: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void); case EXPR_BXOR: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); default: assert(0); } return S_OK; }