static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg) { unsigned instr; BSTR bstr; bstr = alloc_bstr_arg(ctx, arg); if(!bstr) return E_OUTOFMEMORY; instr = push_instr(ctx, op); if(instr == -1) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.bstr = bstr; return S_OK; }
static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2) { unsigned instr; BSTR bstr; bstr = alloc_bstr_arg(ctx, arg2); if(!bstr) return E_OUTOFMEMORY; instr = push_instr(ctx, op); if(!instr) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.uint = arg1; instr_ptr(ctx, instr)->arg2.bstr = bstr; return S_OK; }
static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat) { statement_ctx_t loop_ctx = {2}; unsigned step_instr, instr; BSTR identifier; HRESULT hres; identifier = alloc_bstr_arg(ctx, stat->identifier); if(!identifier) return E_OUTOFMEMORY; hres = compile_expression(ctx, stat->from_expr); if(FAILED(hres)) return hres; instr = push_instr(ctx, OP_assign_ident); if(!instr) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.bstr = identifier; instr_ptr(ctx, instr)->arg2.uint = 0; hres = compile_expression(ctx, stat->to_expr); if(FAILED(hres)) return hres; if(!push_instr(ctx, OP_val)) return E_OUTOFMEMORY; if(stat->step_expr) { hres = compile_expression(ctx, stat->step_expr); if(FAILED(hres)) return hres; if(!push_instr(ctx, OP_val)) return E_OUTOFMEMORY; }else { hres = push_instr_int(ctx, OP_short, 1); if(FAILED(hres)) return hres; } loop_ctx.for_end_label = alloc_label(ctx); if(!loop_ctx.for_end_label) return E_OUTOFMEMORY; step_instr = push_instr(ctx, OP_step); if(!step_instr) return E_OUTOFMEMORY; instr_ptr(ctx, step_instr)->arg2.bstr = identifier; instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label; hres = compile_statement(ctx, &loop_ctx, stat->body); if(FAILED(hres)) return hres; instr = push_instr(ctx, OP_incc); if(!instr) return E_OUTOFMEMORY; instr_ptr(ctx, instr)->arg1.bstr = identifier; hres = push_instr_addr(ctx, OP_jmp, step_instr); if(FAILED(hres)) return hres; hres = push_instr_uint(ctx, OP_pop, 2); if(FAILED(hres)) return hres; label_set_addr(ctx, loop_ctx.for_end_label); return S_OK; }