blob: 618c6f09da0d82d11a09498e7d7db1fae713eb9c [file] [log] [blame]
/*
* Copyright 2008,2011 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
typedef struct _source_elements_t source_elements_t;
typedef struct _expression_t expression_t;
typedef struct _statement_t statement_t;
typedef struct {
const WCHAR *begin;
const WCHAR *end;
const WCHAR *ptr;
script_ctx_t *script;
source_elements_t *source;
BOOL nl;
BOOL implicit_nl_semicolon;
BOOL is_html;
BOOL lexer_error;
HRESULT hres;
heap_pool_t heap;
} parser_ctx_t;
#define OP_LIST \
X(add, 1, 0,0) \
X(and, 1, 0,0) \
X(array, 1, 0,0) \
X(assign, 1, 0,0) \
X(assign_call,1, ARG_UINT, 0) \
X(bool, 1, ARG_INT, 0) \
X(bneg, 1, 0,0) \
X(call, 1, ARG_UINT, ARG_UINT) \
X(call_member,1, ARG_UINT, ARG_UINT) \
X(carray, 1, ARG_UINT, 0) \
X(case, 0, ARG_ADDR, 0) \
X(cnd_nz, 0, ARG_ADDR, 0) \
X(cnd_z, 0, ARG_ADDR, 0) \
X(delete, 1, 0,0) \
X(delete_ident,1,ARG_BSTR, 0) \
X(div, 1, 0,0) \
X(double, 1, ARG_DBL, 0) \
X(end_finally,1, 0,0) \
X(eq, 1, 0,0) \
X(eq2, 1, 0,0) \
X(forin, 0, ARG_ADDR, 0) \
X(func, 1, ARG_UINT, 0) \
X(gt, 1, 0,0) \
X(gteq, 1, 0,0) \
X(ident, 1, ARG_BSTR, 0) \
X(identid, 1, ARG_BSTR, ARG_INT) \
X(in, 1, 0,0) \
X(instanceof, 1, 0,0) \
X(int, 1, ARG_INT, 0) \
X(jmp, 0, ARG_ADDR, 0) \
X(jmp_z, 0, ARG_ADDR, 0) \
X(lshift, 1, 0,0) \
X(lt, 1, 0,0) \
X(lteq, 1, 0,0) \
X(member, 1, ARG_BSTR, 0) \
X(memberid, 1, ARG_UINT, 0) \
X(minus, 1, 0,0) \
X(mod, 1, 0,0) \
X(mul, 1, 0,0) \
X(neg, 1, 0,0) \
X(neq, 1, 0,0) \
X(neq2, 1, 0,0) \
X(new, 1, ARG_UINT, 0) \
X(new_obj, 1, 0,0) \
X(null, 1, 0,0) \
X(obj_prop, 1, ARG_BSTR, 0) \
X(or, 1, 0,0) \
X(pop, 1, ARG_UINT, 0) \
X(pop_except, 1, 0,0) \
X(pop_scope, 1, 0,0) \
X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \
X(push_except,1, ARG_ADDR, ARG_BSTR) \
X(push_scope, 1, 0,0) \
X(regexp, 1, ARG_STR, ARG_UINT) \
X(rshift, 1, 0,0) \
X(rshift2, 1, 0,0) \
X(str, 1, ARG_STR, 0) \
X(this, 1, 0,0) \
X(throw, 0, 0,0) \
X(throw_ref, 0, ARG_UINT, 0) \
X(throw_type, 0, ARG_UINT, ARG_STR) \
X(tonum, 1, 0,0) \
X(typeof, 1, 0,0) \
X(typeofid, 1, 0,0) \
X(typeofident,1, 0,0) \
X(refval, 1, 0,0) \
X(ret, 0, 0,0) \
X(setret, 1, 0,0) \
X(sub, 1, 0,0) \
X(undefined, 1, 0,0) \
X(var_set, 1, ARG_BSTR, 0) \
X(void, 1, 0,0) \
X(xor, 1, 0,0)
typedef enum {
#define X(x,a,b,c) OP_##x,
OP_LIST
#undef X
OP_LAST
} jsop_t;
typedef union {
BSTR bstr;
LONG lng;
jsstr_t *str;
unsigned uint;
} instr_arg_t;
typedef enum {
ARG_NONE = 0,
ARG_ADDR,
ARG_BSTR,
ARG_DBL,
ARG_FUNC,
ARG_INT,
ARG_STR,
ARG_UINT
} instr_arg_type_t;
typedef struct {
jsop_t op;
union {
instr_arg_t arg[2];
double dbl;
} u;
} instr_t;
typedef struct _function_code_t {
BSTR name;
unsigned instr_off;
const WCHAR *source;
unsigned source_len;
unsigned func_cnt;
struct _function_code_t *funcs;
unsigned var_cnt;
BSTR *variables;
unsigned param_cnt;
BSTR *params;
} function_code_t;
typedef struct _bytecode_t {
LONG ref;
instr_t *instrs;
heap_pool_t heap;
function_code_t global_code;
WCHAR *source;
BSTR *bstr_pool;
unsigned bstr_pool_size;
unsigned bstr_cnt;
jsstr_t **str_pool;
unsigned str_pool_size;
unsigned str_cnt;
struct _bytecode_t *next;
} bytecode_t;
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN;
void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN;
static inline void bytecode_addref(bytecode_t *code)
{
code->ref++;
}
HRESULT script_parse(script_ctx_t*,const WCHAR*,const WCHAR*,BOOL,parser_ctx_t**) DECLSPEC_HIDDEN;
void parser_release(parser_ctx_t*) DECLSPEC_HIDDEN;
int parser_lex(void*,parser_ctx_t*) DECLSPEC_HIDDEN;
static inline void *parser_alloc(parser_ctx_t *ctx, DWORD size)
{
return heap_pool_alloc(&ctx->heap, size);
}
static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size)
{
return heap_pool_alloc(&ctx->script->tmp_heap, size);
}
typedef struct _scope_chain_t {
LONG ref;
jsdisp_t *jsobj;
IDispatch *obj;
struct _scope_chain_t *next;
} scope_chain_t;
HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN;
void scope_release(scope_chain_t*) DECLSPEC_HIDDEN;
static inline void scope_addref(scope_chain_t *scope)
{
scope->ref++;
}
typedef struct _except_frame_t except_frame_t;
struct _exec_ctx_t {
LONG ref;
parser_ctx_t *parser;
bytecode_t *code;
script_ctx_t *script;
scope_chain_t *scope_chain;
jsdisp_t *var_disp;
IDispatch *this_obj;
function_code_t *func_code;
BOOL is_global;
jsval_t *stack;
unsigned stack_size;
unsigned top;
except_frame_t *except_frame;
jsval_t ret;
unsigned ip;
};
static inline void exec_addref(exec_ctx_t *ctx)
{
ctx->ref++;
}
void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN;
HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN;
HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsval_t*) DECLSPEC_HIDDEN;
HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;
typedef enum {
LT_DOUBLE,
LT_STRING,
LT_BOOL,
LT_NULL,
LT_REGEXP
}literal_type_t;
typedef struct {
literal_type_t type;
union {
double dval;
const WCHAR *wstr;
BOOL bval;
struct {
const WCHAR *str;
DWORD str_len;
DWORD flags;
} regexp;
} u;
} literal_t;
literal_t *parse_regexp(parser_ctx_t*) DECLSPEC_HIDDEN;
literal_t *new_boolean_literal(parser_ctx_t*,BOOL) DECLSPEC_HIDDEN;
typedef struct _variable_declaration_t {
const WCHAR *identifier;
expression_t *expr;
struct _variable_declaration_t *next;
struct _variable_declaration_t *global_next; /* for compiler */
} variable_declaration_t;
typedef enum {
STAT_BLOCK,
STAT_BREAK,
STAT_CONTINUE,
STAT_EMPTY,
STAT_EXPR,
STAT_FOR,
STAT_FORIN,
STAT_IF,
STAT_LABEL,
STAT_RETURN,
STAT_SWITCH,
STAT_THROW,
STAT_TRY,
STAT_VAR,
STAT_WHILE,
STAT_WITH
} statement_type_t;
struct _statement_t {
statement_type_t type;
statement_t *next;
};
typedef struct {
statement_t stat;
statement_t *stat_list;
} block_statement_t;
typedef struct {
statement_t stat;
variable_declaration_t *variable_list;
} var_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
} expression_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
statement_t *if_stat;
statement_t *else_stat;
} if_statement_t;
typedef struct {
statement_t stat;
BOOL do_while;
expression_t *expr;
statement_t *statement;
} while_statement_t;
typedef struct {
statement_t stat;
variable_declaration_t *variable_list;
expression_t *begin_expr;
expression_t *expr;
expression_t *end_expr;
statement_t *statement;
} for_statement_t;
typedef struct {
statement_t stat;
variable_declaration_t *variable;
expression_t *expr;
expression_t *in_expr;
statement_t *statement;
} forin_statement_t;
typedef struct {
statement_t stat;
const WCHAR *identifier;
} branch_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
statement_t *statement;
} with_statement_t;
typedef struct {
statement_t stat;
const WCHAR *identifier;
statement_t *statement;
} labelled_statement_t;
typedef struct _case_clausule_t {
expression_t *expr;
statement_t *stat;
struct _case_clausule_t *next;
} case_clausule_t;
typedef struct {
statement_t stat;
expression_t *expr;
case_clausule_t *case_list;
} switch_statement_t;
typedef struct {
const WCHAR *identifier;
statement_t *statement;
} catch_block_t;
typedef struct {
statement_t stat;
statement_t *try_statement;
catch_block_t *catch_block;
statement_t *finally_statement;
} try_statement_t;
typedef struct {
enum {
EXPRVAL_JSVAL,
EXPRVAL_IDREF,
EXPRVAL_INVALID
} type;
union {
jsval_t val;
struct {
IDispatch *disp;
DISPID id;
} idref;
} u;
} exprval_t;
typedef enum {
EXPR_COMMA,
EXPR_OR,
EXPR_AND,
EXPR_BOR,
EXPR_BXOR,
EXPR_BAND,
EXPR_INSTANCEOF,
EXPR_IN,
EXPR_ADD,
EXPR_SUB,
EXPR_MUL,
EXPR_DIV,
EXPR_MOD,
EXPR_DELETE,
EXPR_VOID,
EXPR_TYPEOF,
EXPR_MINUS,
EXPR_PLUS,
EXPR_POSTINC,
EXPR_POSTDEC,
EXPR_PREINC,
EXPR_PREDEC,
EXPR_EQ,
EXPR_EQEQ,
EXPR_NOTEQ,
EXPR_NOTEQEQ,
EXPR_LESS,
EXPR_LESSEQ,
EXPR_GREATER,
EXPR_GREATEREQ,
EXPR_BITNEG,
EXPR_LOGNEG,
EXPR_LSHIFT,
EXPR_RSHIFT,
EXPR_RRSHIFT,
EXPR_ASSIGN,
EXPR_ASSIGNLSHIFT,
EXPR_ASSIGNRSHIFT,
EXPR_ASSIGNRRSHIFT,
EXPR_ASSIGNADD,
EXPR_ASSIGNSUB,
EXPR_ASSIGNMUL,
EXPR_ASSIGNDIV,
EXPR_ASSIGNMOD,
EXPR_ASSIGNAND,
EXPR_ASSIGNOR,
EXPR_ASSIGNXOR,
EXPR_COND,
EXPR_ARRAY,
EXPR_MEMBER,
EXPR_NEW,
EXPR_CALL,
EXPR_THIS,
EXPR_FUNC,
EXPR_IDENT,
EXPR_ARRAYLIT,
EXPR_PROPVAL,
EXPR_LITERAL
} expression_type_t;
struct _expression_t {
expression_type_t type;
};
typedef struct _parameter_t {
const WCHAR *identifier;
struct _parameter_t *next;
} parameter_t;
struct _source_elements_t {
statement_t *statement;
statement_t *statement_tail;
};
typedef struct _function_expression_t {
expression_t expr;
const WCHAR *identifier;
parameter_t *parameter_list;
source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
struct _function_expression_t *next; /* for compiler */
} function_expression_t;
typedef struct {
expression_t expr;
expression_t *expression1;
expression_t *expression2;
} binary_expression_t;
typedef struct {
expression_t expr;
expression_t *expression;
} unary_expression_t;
typedef struct {
expression_t expr;
expression_t *expression;
expression_t *true_expression;
expression_t *false_expression;
} conditional_expression_t;
typedef struct {
expression_t expr;
expression_t *expression;
const WCHAR *identifier;
} member_expression_t;
typedef struct _argument_t {
expression_t *expr;
struct _argument_t *next;
} argument_t;
typedef struct {
expression_t expr;
expression_t *expression;
argument_t *argument_list;
} call_expression_t;
typedef struct {
expression_t expr;
const WCHAR *identifier;
} identifier_expression_t;
typedef struct {
expression_t expr;
literal_t *literal;
} literal_expression_t;
typedef struct _array_element_t {
int elision;
expression_t *expr;
struct _array_element_t *next;
} array_element_t;
typedef struct {
expression_t expr;
array_element_t *element_list;
int length;
} array_literal_expression_t;
typedef struct _prop_val_t {
literal_t *name;
expression_t *value;
struct _prop_val_t *next;
} prop_val_t;
typedef struct {
expression_t expr;
prop_val_t *property_list;
} property_value_expression_t;