static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set) { HRESULT hres; hres = compile_expression(ctx, stat->value_expr); if(FAILED(hres)) return hres; if(stat->member_expr->args) { FIXME("arguments support not implemented\n"); return E_NOTIMPL; } if(stat->member_expr->obj_expr) { hres = compile_expression(ctx, stat->member_expr->obj_expr); if(FAILED(hres)) return hres; hres = push_instr_bstr(ctx, is_set ? OP_set_member : OP_assign_member, stat->member_expr->identifier); }else { hres = push_instr_bstr(ctx, is_set ? OP_set_ident : OP_assign_ident, stat->member_expr->identifier); } return hres; }
static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat) { const_decl_t *decl, *next_decl = stat->decls; do { decl = next_decl; if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name) || lookup_dim_decls(ctx, decl->name)) { FIXME("%s redefined\n", debugstr_w(decl->name)); return E_FAIL; } if(ctx->func->type == FUNC_GLOBAL) { HRESULT hres; hres = compile_expression(ctx, decl->value_expr); if(FAILED(hres)) return hres; hres = push_instr_bstr(ctx, OP_const, decl->name); if(FAILED(hres)) return hres; } next_decl = decl->next; decl->next = ctx->const_decls; ctx->const_decls = decl; } while(next_decl); return S_OK; }
/* ECMA-262 3rd Edition 11.2.1 */ static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr) { HRESULT hres; hres = compile_expression(ctx, expr->expression); if(FAILED(hres)) return hres; return push_instr_bstr(ctx, OP_member, expr->identifier); }
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr) { HRESULT hres; switch(expr->expression->type) { case EXPR_ARRAY: { binary_expression_t *array_expr = (binary_expression_t*)expr->expression; hres = compile_expression(ctx, array_expr->expression1); if(FAILED(hres)) return hres; hres = compile_expression(ctx, array_expr->expression2); if(FAILED(hres)) return hres; if(!push_instr(ctx, OP_delete)) return E_OUTOFMEMORY; break; } case EXPR_MEMBER: { member_expression_t *member_expr = (member_expression_t*)expr->expression; hres = compile_expression(ctx, member_expr->expression); if(FAILED(hres)) return hres; /* FIXME: Potential optimization */ hres = push_instr_str(ctx, OP_str, member_expr->identifier); if(FAILED(hres)) return hres; if(!push_instr(ctx, OP_delete)) return E_OUTOFMEMORY; break; } case EXPR_IDENT: return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier); default: { const WCHAR fixmeW[] = {'F','I','X','M','E',0}; WARN("invalid delete, unimplemented exception message\n"); hres = compile_expression(ctx, expr->expression); if(FAILED(hres)) return hres; return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW); } } return S_OK; }
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) { unsigned instr; /* FIXME: not exactly right */ if(expr->identifier) return push_instr_bstr(ctx, OP_ident, expr->identifier); instr = push_instr(ctx, OP_func); if(!instr) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.func = expr; return S_OK; }
/* ECMA-262 3rd Edition 12.2 */ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list) { variable_declaration_t *iter; HRESULT hres; for(iter = list; iter; iter = iter->next) { if(!iter->expr) continue; hres = compile_expression(ctx, iter->expr); if(FAILED(hres)) return hres; hres = push_instr_bstr(ctx, OP_var_set, iter->identifier); if(FAILED(hres)) return hres; } 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; }