static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) { switch(literal->type) { case LT_BOOL: return push_instr_int(ctx, OP_bool, literal->u.bval); case LT_DOUBLE: return push_instr_double(ctx, OP_double, literal->u.dval); case LT_INT: return push_instr_int(ctx, OP_int, literal->u.lval); case LT_NULL: return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY; case LT_STRING: return push_instr_str(ctx, OP_str, literal->u.wstr); case LT_REGEXP: { unsigned instr; WCHAR *str; str = compiler_alloc(ctx->code, (literal->u.regexp.str_len+1)*sizeof(WCHAR)); if(!str) return E_OUTOFMEMORY; memcpy(str, literal->u.regexp.str, literal->u.regexp.str_len*sizeof(WCHAR)); str[literal->u.regexp.str_len] = 0; instr = push_instr(ctx, OP_regexp); if(!instr) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.str = str; instr_ptr(ctx, instr)->arg2.lng = literal->u.regexp.flags; return S_OK; } default: assert(0); } }
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_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags) { HRESULT hres = S_OK; switch(expr->type) { case EXPR_IDENT: { identifier_expression_t *ident_expr = (identifier_expression_t*)expr; hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags); break; } case EXPR_ARRAY: { binary_expression_t *array_expr = (binary_expression_t*)expr; hres = compile_expression(ctx, array_expr->expression1); if(FAILED(hres)) return hres; hres = compile_expression(ctx, array_expr->expression2); if(FAILED(hres)) return hres; hres = push_instr_uint(ctx, OP_memberid, flags); break; } case EXPR_MEMBER: { member_expression_t *member_expr = (member_expression_t*)expr; 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; hres = push_instr_uint(ctx, OP_memberid, flags); break; } default: assert(0); } return hres; }
static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr) { jsop_t op; HRESULT hres; if(is_memberid_expr(expr->expression->type)) { if(expr->expression->type == EXPR_IDENT) return push_instr_str(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier); op = OP_typeofid; hres = compile_memberid_expression(ctx, expr->expression, 0); }else { op = OP_typeof; hres = compile_expression(ctx, expr->expression); } if(FAILED(hres)) return hres; return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; }
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; }