2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
29 struct _compiler_ctx_t
{
37 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
39 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
41 assert(ctx
->code_size
>= ctx
->code_off
);
44 ctx
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
45 if(!ctx
->code
->instrs
)
48 }else if(ctx
->code_size
== ctx
->code_off
) {
51 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
55 ctx
->code
->instrs
= new_instrs
;
59 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
60 return ctx
->code_off
++;
63 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
65 assert(off
< ctx
->code_off
);
66 return ctx
->code
->instrs
+ off
;
69 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
73 instr
= push_instr(ctx
, op
);
77 instr_ptr(ctx
, instr
)->arg1
.lng
= arg
;
81 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
85 hres
= compile_expression(ctx
, expr
->expression1
);
89 hres
= compile_expression(ctx
, expr
->expression2
);
93 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
96 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
100 hres
= compile_expression(ctx
, expr
->expression
);
104 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
107 static HRESULT
compile_interp_fallback(compiler_ctx_t
*ctx
, expression_t
*expr
)
111 instr
= push_instr(ctx
, OP_tree
);
113 return E_OUTOFMEMORY
;
115 instr_ptr(ctx
, instr
)->arg1
.expr
= expr
;
119 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_expression_t
*expr
)
121 literal_t
*literal
= expr
->literal
;
123 switch(literal
->type
) {
125 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
127 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
129 return compile_interp_fallback(ctx
, &expr
->expr
);
133 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
137 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
139 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
141 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
143 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
145 return compile_literal(ctx
, (literal_expression_t
*)expr
);
147 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
149 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
151 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
153 assert(expr
->eval
!= compiled_expression_eval
);
154 return compile_interp_fallback(ctx
, expr
);
160 void release_bytecode(bytecode_t
*code
)
162 heap_free(code
->instrs
);
166 void release_compiler(compiler_ctx_t
*ctx
)
171 HRESULT
compile_subscript(parser_ctx_t
*parser
, expression_t
*expr
, unsigned *ret_off
)
176 parser
->code
= heap_alloc_zero(sizeof(bytecode_t
));
178 return E_OUTOFMEMORY
;
181 if(!parser
->compiler
) {
182 parser
->compiler
= heap_alloc_zero(sizeof(compiler_ctx_t
));
183 if(!parser
->compiler
)
184 return E_OUTOFMEMORY
;
186 parser
->compiler
->parser
= parser
;
187 parser
->compiler
->code
= parser
->code
;
190 *ret_off
= parser
->compiler
->code_off
;
191 hres
= compile_expression(parser
->compiler
, expr
);
195 return push_instr(parser
->compiler
, OP_ret
) == -1 ? E_OUTOFMEMORY
: S_OK
;