Generate bytecode while parsing

This commit is contained in:
Ilmir Usmanov 2014-07-22 20:49:51 +04:00
parent 9a0b54313d
commit efb7009cfb
16 changed files with 1882 additions and 3281 deletions

View File

@ -166,6 +166,11 @@ OP_CODE_DECL (b_xor, T_IDX_IDX_IDX,
var_left,
var_right)
/** dst = ~ R */
OP_CODE_DECL (b_not, T_IDX_IDX,
dst,
var_right)
// Binary logical operators.
// Operands are booleans.
// Return boolean.
@ -182,6 +187,11 @@ OP_CODE_DECL (logical_or, T_IDX_IDX_IDX,
var_left,
var_right)
/** dst = ! R */
OP_CODE_DECL (logical_not, T_IDX_IDX,
dst,
var_right)
// Equality operations.
/** dst = L == R. */
@ -234,6 +244,18 @@ OP_CODE_DECL (greater_or_equal_than, T_IDX_IDX_IDX,
var_left,
var_right)
/** dst = L instanceof R. */
OP_CODE_DECL (instanceof, T_IDX_IDX_IDX,
dst,
var_left,
var_right)
/** dst = L in R. */
OP_CODE_DECL (in, T_IDX_IDX_IDX,
dst,
var_left,
var_right)
// Assignment operators.
// Assign value to LEFT operand based on value of RIGHT operand.
@ -244,22 +266,43 @@ OP_CODE_DECL (assignment, T_IDX_IDX,
// Functions calls, declarations and argument handling
/** name(arg1); */
OP_CODE_DECL (call_1, T_IDX_IDX,
/** a = name(); */
OP_CODE_DECL (call_0, T_IDX_IDX,
lhs,
name_lit_idx)
/** a = name(arg1); */
OP_CODE_DECL (call_1, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx)
/** name(arg1, arg2); */
OP_CODE_DECL (call_2, T_IDX_IDX_IDX,
name_lit_idx,
arg1_lit_idx,
arg2_lit_idx)
/** name(arg1, arg2, ... */
/** a = name(arg1, ... */
OP_CODE_DECL (call_n, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx,
arg2_lit_idx)
arg1_lit_idx)
/** a = new name(); */
OP_CODE_DECL (construct_0, T_IDX_IDX,
lhs,
name_lit_idx)
/** a = new name(arg1); */
OP_CODE_DECL (construct_1, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx)
/** a = new name(arg1, ... */
OP_CODE_DECL (construct_n, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx)
/** name(); */
OP_CODE_DECL (func_decl_0, T_IDX,
name_lit_idx)
/** name(arg1); */
OP_CODE_DECL (func_decl_1, T_IDX_IDX,
@ -278,19 +321,27 @@ OP_CODE_DECL (func_decl_n, T_IDX_IDX_IDX,
arg1_lit_idx,
arg2_lit_idx)
/** ..., arg1, ... */
OP_CODE_DECL (varg_1, T_IDX,
/** a = name(); */
OP_CODE_DECL (func_expr_0, T_IDX_IDX,
lhs,
name_lit_idx)
/** a = name(arg1); */
OP_CODE_DECL (func_expr_1, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx)
/** a = name(arg1, ... */
OP_CODE_DECL (func_expr_n, T_IDX_IDX_IDX,
lhs,
name_lit_idx,
arg1_lit_idx)
/** ..., arg1); */
OP_CODE_DECL (varg_1_end, T_IDX,
arg1_lit_idx)
/** ..., arg1, arg2, ... */
OP_CODE_DECL (varg_2, T_IDX_IDX,
arg1_lit_idx,
arg2_lit_idx)
/** ..., arg1, arg2); */
OP_CODE_DECL (varg_2_end, T_IDX_IDX,
arg1_lit_idx,
@ -356,26 +407,91 @@ OP_CODE_DECL (loop_postcond, T_IDX_IDX,
condition,
body_root)
///** for vars...in iter, state, ctl */
//OP_CODE_DECL (loop_init, T_IDX_IDX_IDX,
// start_idx, stop_idx, step_idx)
///** loop (condition) */
//OP_CODE_DECL (loop_cond_pre_begin, T_IDX_IDX,
// condition, body_root)
///** i++;*/
//OP_CODE_DECL (loop_cond_pre_end, T_IDX,
// iterator, body_root)
/** a = [] */
OP_CODE_DECL (array_0, T_IDX,
lhs)
// Property accessors (array, objects, strings)
/** Array ops for ILMIR*/
//OP_CODE_DECL (array_copy, T_IDX_IDX, /** L = R */
// var_left, var_right)
//OP_CODE_DECL (array_set, T_IDX_IDX_IDX, /** array[index] = src */
// dst, var_left, var_right)
//OP_CODE_DECL (array_get, T_IDX_IDX_IDX, /** dst = array[index] */
// dst, array, index)
/** a = [b] */
OP_CODE_DECL (array_1, T_IDX_IDX,
lhs,
elem1)
//// TODO
/** a = [b, c] */
OP_CODE_DECL (array_2, T_IDX_IDX_IDX,
lhs,
elem1,
elem2)
/** a = [b, c ... */
OP_CODE_DECL (array_n, T_IDX_IDX_IDX,
lhs,
elem1,
elem2)
/** a = b : c */
OP_CODE_DECL (prop, T_IDX_IDX_IDX,
lhs,
name,
value)
/** a = b.c OR a = b[c] */
OP_CODE_DECL (prop_access, T_IDX_IDX_IDX,
lhs,
obj,
prop)
/** a = get prop () */
OP_CODE_DECL (prop_get_decl, T_IDX_IDX,
lhs,
prop)
/** a = set prop (arg) */
OP_CODE_DECL (prop_set_decl, T_IDX_IDX_IDX,
lhs,
prop,
arg)
/** a = { } */
OP_CODE_DECL (obj_0, T_IDX,
lhs)
/** a = { b } */
OP_CODE_DECL (obj_1, T_IDX_IDX,
lhs,
arg1)
/** a = { b, c } */
OP_CODE_DECL (obj_2, T_IDX_IDX_IDX,
lhs,
arg1,
arg2)
/** a = { b, c ... */
OP_CODE_DECL (obj_n, T_IDX_IDX_IDX,
lhs,
arg1,
arg2)
/** a = this */
OP_CODE_DECL (this, T_IDX,
lhs)
/** a = delete b */
OP_CODE_DECL (delete, T_IDX_IDX,
lhs,
obj)
/** a = delete b */
OP_CODE_DECL (typeof, T_IDX_IDX,
lhs,
obj)
/** with (b) { */
OP_CODE_DECL (with, T_IDX,
expr)
/** } */
OP_CODE_DECL_VOID (end_with)
// Variable declaration
OP_CODE_DECL (decl_var, T_IDX,

View File

@ -22,19 +22,42 @@ void opfunc_loop_init_num (OPCODE opdata __unused, struct __int_data *int_data _
void opfunc_loop_precond_begin_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_loop_precond_end_num (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_loop_postcond (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_call_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_call_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_call_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_construct_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_construct_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_construct_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_decl_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_decl_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_decl_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_decl_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_expr_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_expr_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_func_expr_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_1_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_2_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_3 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_varg_3_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_retval (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_ret (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_array_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_array_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_array_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_array_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_obj_0 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_obj_1 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_obj_2 (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_obj_n (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_prop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_prop_access (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_prop_get_decl (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_prop_set_decl (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_this (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_delete (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_typeof (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_with (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_end_with (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_decl_var (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_nop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_not_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
@ -44,6 +67,8 @@ void opfunc_less_than (OPCODE opdata __unused, struct __int_data *int_data __unu
void opfunc_greater_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_less_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_greater_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_instanceof (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_in (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void
opfunc_assignment(OPCODE opdata __unused,
@ -54,9 +79,11 @@ opfunc_assignment(OPCODE opdata __unused,
void opfunc_logical_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_logical_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_logical_not (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_xor (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_not (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_shift_left (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_shift_right (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
void opfunc_b_shift_uright (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); }
@ -124,8 +151,10 @@ GETOP_IMPL_3 (b_shift_uright, dst, var_left, var_right)
GETOP_IMPL_3 (b_and, dst, var_left, var_right)
GETOP_IMPL_3 (b_or, dst, var_left, var_right)
GETOP_IMPL_3 (b_xor, dst, var_left, var_right)
GETOP_IMPL_2 (b_not, dst, var_right)
GETOP_IMPL_3 (logical_and, dst, var_left, var_right)
GETOP_IMPL_3 (logical_or, dst, var_left, var_right)
GETOP_IMPL_2 (logical_not, dst, var_right)
GETOP_IMPL_3 (equal_value, dst, var_left, var_right)
GETOP_IMPL_3 (not_equal_value, dst, var_left, var_right)
GETOP_IMPL_3 (equal_value_type, dst, var_left, var_right)
@ -134,16 +163,23 @@ GETOP_IMPL_3 (less_than, dst, var_left, var_right)
GETOP_IMPL_3 (greater_than, dst, var_left, var_right)
GETOP_IMPL_3 (less_or_equal_than, dst, var_left, var_right)
GETOP_IMPL_3 (greater_or_equal_than, dst, var_left, var_right)
GETOP_IMPL_3 (instanceof, dst, var_left, var_right)
GETOP_IMPL_3 (in, dst, var_left, var_right)
GETOP_IMPL_2 (assignment, value_left, value_right)
GETOP_IMPL_2 (call_1, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_3 (call_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_3 (call_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_2 (call_0, lhs, name_lit_idx)
GETOP_IMPL_3 (call_1, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_3 (call_n, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_2 (construct_0, lhs, name_lit_idx)
GETOP_IMPL_3 (construct_1, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_3 (construct_n, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_1 (func_decl_0, name_lit_idx)
GETOP_IMPL_2 (func_decl_1, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_1 (varg_1, arg1_lit_idx)
GETOP_IMPL_2 (func_expr_0, lhs, name_lit_idx)
GETOP_IMPL_3 (func_expr_1, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_3 (func_expr_n, lhs, name_lit_idx, arg1_lit_idx)
GETOP_IMPL_1 (varg_1_end, arg1_lit_idx)
GETOP_IMPL_2 (varg_2, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_2 (varg_2_end, arg1_lit_idx, arg2_lit_idx)
GETOP_IMPL_3 (varg_3, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
GETOP_IMPL_3 (varg_3_end, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
@ -155,4 +191,22 @@ GETOP_IMPL_3 (loop_init_num, start, stop, step)
GETOP_IMPL_2 (loop_precond_begin_num, condition, after_loop_op)
GETOP_IMPL_3 (loop_precond_end_num, iterator, step, precond_begin)
GETOP_IMPL_2 (loop_postcond, condition, body_root)
GETOP_IMPL_1 (array_0, lhs)
GETOP_IMPL_2 (array_1, lhs, elem1)
GETOP_IMPL_3 (array_2, lhs, elem1, elem2)
GETOP_IMPL_3 (array_n, lhs, elem1, elem2)
GETOP_IMPL_3 (prop, lhs, name, value)
GETOP_IMPL_3 (prop_access, lhs, obj, prop)
GETOP_IMPL_2 (prop_get_decl, lhs, prop)
GETOP_IMPL_3 (prop_set_decl, lhs, prop, arg)
GETOP_IMPL_1 (obj_0, lhs)
GETOP_IMPL_2 (obj_1, lhs, arg1)
GETOP_IMPL_3 (obj_2, lhs, arg1, arg2)
GETOP_IMPL_3 (obj_n, lhs, arg1, arg2)
GETOP_IMPL_1 (this, lhs)
GETOP_IMPL_2 (delete, lhs, obj)
GETOP_IMPL_2 (typeof, lhs, obj)
GETOP_IMPL_1 (with, expr)
GETOP_IMPL_0 (end_with)
GETOP_IMPL_1 (decl_var, variable)

View File

@ -42,21 +42,46 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
op(loop_postcond)
#define OP_CALLS_AND_ARGS(op) \
op(call_0) \
op(call_1) \
op(call_2) \
op(call_n) \
op(construct_0) \
op(construct_1) \
op(construct_n) \
op(func_decl_0) \
op(func_decl_1) \
op(func_decl_2) \
op(func_decl_n) \
op(varg_1) \
op(func_expr_0) \
op(func_expr_1) \
op(func_expr_n) \
op(varg_1_end) \
op(varg_2) \
op(varg_2_end) \
op(varg_3) \
op(varg_3_end) \
op(retval) \
op(ret)
#define OP_INITS(op) \
op(array_0) \
op(array_1) \
op(array_2) \
op(array_n) \
op(prop) \
op(prop_access) \
op(prop_get_decl) \
op(prop_set_decl) \
op(obj_0) \
op(obj_1) \
op(obj_2) \
op(obj_n) \
op(this) \
op(delete) \
op(typeof) \
op(with) \
op(end_with) \
op(decl_var)
#define OP_ASSIGNMENTS(op) \
op(assignment)
@ -68,11 +93,13 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
#define OP_B_BITWISE(op) \
op(b_and) \
op(b_or) \
op(b_xor)
op(b_xor) \
op(b_not)
#define OP_B_LOGICAL(op) \
op(logical_and) \
op(logical_or)
op(logical_or) \
op(logical_not)
#define OP_EQUALITY(op) \
op(equal_value) \
@ -84,7 +111,9 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
op(less_than) \
op(greater_than) \
op(less_or_equal_than) \
op(greater_or_equal_than)
op(greater_or_equal_than) \
op(instanceof) \
op(in)
#define OP_ARITHMETIC(op) \
op(addition) \
@ -106,6 +135,7 @@ typedef void (*opfunc)(OPCODE, struct __int_data *);
#define OP_LIST(op) \
OP_LOOPS(op) \
OP_CALLS_AND_ARGS(op) \
OP_INITS(op) \
OP_ASSIGNMENTS(op) \
OP_B_LOGICAL(op) \
OP_B_BITWISE(op) \

View File

@ -1,53 +0,0 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This allocator only allocates a memmory and doesn't free it.
Use it only in dedicated parser, otherwise use jerry fixed pool allocator. */
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include "../globals.h"
#define ALLOCATION_BUFFER_SIZE 4096
char allocation_buffer[ALLOCATION_BUFFER_SIZE];
char *free_memory;
static void *
geppetto_allocate_memory (size_t size)
{
void *res;
if (!free_memory)
free_memory = allocation_buffer;
res = free_memory;
free_memory += size;
JERRY_ASSERT (free_memory - allocation_buffer < ALLOCATION_BUFFER_SIZE);
return res;
}
static inline void *
malloc (size_t size)
{
return geppetto_allocate_memory (size);
}
static inline void
free (void *mem __unused)
{
JERRY_UNREACHABLE ();
}
#endif // ALLOCATOR_H

View File

@ -1,418 +0,0 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bytecode-generator.h"
#include "globals.h"
#include "libcoreint/opcodes.h"
#include "libruntime/serializer.h"
#include "libruntime/jerry-libc.h"
static uint8_t opcode_index;
#define MAX_STACK_SIZE 10
static uint8_t opcode_stack[10];
static uint8_t stack_head;
static void
push_opcode (uint8_t opcode)
{
JERRY_ASSERT (stack_head < MAX_STACK_SIZE);
opcode_stack[stack_head++] = opcode;
}
static uint8_t
pop_opcode (void)
{
return opcode_stack[--stack_head];
}
void
generator_init (void)
{
opcode_index = 0;
stack_head = 0;
}
void
generator_dump_strings (const char **strings, uint8_t num)
{
uint8_t len = num, i;
for (i = 0; i < num; i++)
{
serializer_dump_data (&len, 1);
len = (uint8_t) (len + __strlen (strings[i]));
}
for (i = 0; i < num; i++)
serializer_dump_data (strings[i], __strlen (strings[i]) + 1);
}
static bool
is_expression (statement stmt)
{
switch (stmt.type)
{
case STMT_IF:
case STMT_ELSE_IF:
case STMT_END_DO_WHILE:
case STMT_WHILE:
case STMT_RETURN:
case STMT_WITH:
case STMT_SWITCH:
case STMT_CASE:
case STMT_THROW:
case STMT_EXPRESSION:
return true;
default:
return false;
}
}
static bool
is_assignment (statement stmt)
{
JERRY_ASSERT (is_expression (stmt));
return stmt.data.expr.oper != AO_NONE;
}
static expression_type
get_expression_type (statement stmt)
{
JERRY_ASSERT (is_expression (stmt));
return stmt.data.expr.type;
}
static bool
expression_has_operands (statement stmt)
{
switch (get_expression_type (stmt))
{
case ET_OBJECT:
case ET_FUNCTION:
case ET_ARRAY:
case ET_SUBEXPRESSION:
case ET_NONE:
return false;
default:
return true;
}
}
static operand
first_operand (statement stmt)
{
JERRY_ASSERT (expression_has_operands (stmt));
return stmt.data.expr.data.ops.op1;
}
static literal
first_operand_as_literal (statement stmt)
{
operand oper = first_operand (stmt);
JERRY_ASSERT (oper.is_literal);
return oper.data.lit;
}
static uint8_t
first_operand_id (statement stmt)
{
JERRY_ASSERT (expression_has_operands (stmt));
if (first_operand (stmt).is_literal)
JERRY_UNIMPLEMENTED ();
return first_operand (stmt).data.name;
}
static operand
second_operand (statement stmt)
{
JERRY_ASSERT (expression_has_operands (stmt));
return stmt.data.expr.data.ops.op2;
}
static uint8_t
second_operand_id (statement stmt)
{
JERRY_ASSERT (expression_has_operands (stmt));
if (second_operand (stmt).is_literal)
JERRY_UNIMPLEMENTED ();
return second_operand (stmt).data.name;
}
static uint8_t
lhs (statement stmt)
{
JERRY_ASSERT (is_assignment (stmt));
return stmt.data.expr.var;
}
static void
dump_opcode (OPCODE *opcode)
{
serializer_dump_data (opcode, sizeof (OPCODE));
opcode_index++;
}
static assignment_operator
get_assignment_operator (statement stmt)
{
JERRY_ASSERT (is_assignment (stmt));
return stmt.data.expr.oper;
}
static OPCODE
generate_triple_address (OPCODE (*getop)(T_IDX, T_IDX, T_IDX), statement stmt)
{
return (*getop) (lhs (stmt), first_operand_id (stmt), second_operand_id (stmt));
}
void
generator_dump_statement (statement stmt)
{
OPCODE opcode = getop_nop ();
JERRY_STATIC_ASSERT (sizeof (OPCODE) <= sizeof (uint32_t));
switch (stmt.type)
{
case STMT_EMPTY:
break;
case STMT_WHILE:
if (!is_assignment (stmt))
{
literal lit;
switch (get_expression_type (stmt))
{
case ET_LITERAL:
lit = first_operand_as_literal (stmt);
if (lit.type == LIT_BOOL && lit.data.is_true)
{
opcode = getop_loop_inf ((uint8_t) (opcode_index + 1));
push_opcode ((uint8_t) (opcode_index + 1));
dump_opcode (&opcode);
return;
}
else
JERRY_UNIMPLEMENTED ();
break;
default:
JERRY_UNIMPLEMENTED ();
}
}
else
JERRY_UNIMPLEMENTED ();
break;
case STMT_EXPRESSION:
if (is_assignment (stmt))
{
switch (get_expression_type (stmt))
{
case ET_NONE:
JERRY_UNREACHABLE ();
break;
case ET_LOGICAL_OR:
opcode = generate_triple_address (getop_logical_or, stmt);
dump_opcode (&opcode);
break;
case ET_LOGICAL_AND:
opcode = generate_triple_address (getop_logical_and, stmt);
dump_opcode (&opcode);
break;
case ET_BITWISE_OR:
opcode = generate_triple_address (getop_b_or, stmt);
dump_opcode (&opcode);
break;
case ET_BITWISE_XOR:
opcode = generate_triple_address (getop_b_xor, stmt);
dump_opcode (&opcode);
break;
case ET_BITWISE_AND:
opcode = generate_triple_address (getop_b_and, stmt);
dump_opcode (&opcode);
break;
case ET_DOUBLE_EQ:
opcode = generate_triple_address (getop_equal_value, stmt);
dump_opcode (&opcode);
break;
case ET_NOT_EQ:
opcode = generate_triple_address (getop_not_equal_value, stmt);
dump_opcode (&opcode);
break;
case ET_TRIPLE_EQ:
opcode = generate_triple_address (getop_equal_value_type, stmt);
dump_opcode (&opcode);
break;
case ET_NOT_DOUBLE_EQ:
opcode = generate_triple_address (getop_not_equal_value_type, stmt);
dump_opcode (&opcode);
break;
case ET_LESS:
opcode = generate_triple_address (getop_less_than, stmt);
dump_opcode (&opcode);
break;
case ET_GREATER:
opcode = generate_triple_address (getop_greater_than, stmt);
dump_opcode (&opcode);
break;
case ET_LESS_EQ:
opcode = generate_triple_address (getop_less_or_equal_than, stmt);
dump_opcode (&opcode);
break;
case ET_GREATER_EQ:
opcode = generate_triple_address (getop_greater_or_equal_than, stmt);
dump_opcode (&opcode);
break;
case ET_INSTANCEOF:
case ET_IN:
JERRY_UNIMPLEMENTED ();
break;
case ET_LSHIFT:
opcode = generate_triple_address (getop_b_shift_left, stmt);
dump_opcode (&opcode);
break;
case ET_RSHIFT:
opcode = generate_triple_address (getop_b_shift_right, stmt);
dump_opcode (&opcode);
break;
case ET_RSHIFT_EX:
opcode = generate_triple_address (getop_b_shift_uright, stmt);
dump_opcode (&opcode);
break;
case ET_PLUS:
opcode = generate_triple_address (getop_addition, stmt);
dump_opcode (&opcode);
break;
case ET_MINUS:
opcode = generate_triple_address (getop_substraction, stmt);
dump_opcode (&opcode);
break;
case ET_MULT:
opcode = generate_triple_address (getop_multiplication, stmt);
dump_opcode (&opcode);
break;
case ET_DIV:
opcode = generate_triple_address (getop_division, stmt);
dump_opcode (&opcode);
break;
case ET_MOD:
opcode = generate_triple_address (getop_remainder, stmt);
dump_opcode (&opcode);
break;
case ET_UNARY_DELETE:
case ET_UNARY_VOID:
case ET_UNARY_TYPEOF:
JERRY_UNIMPLEMENTED ();
break;
case ET_UNARY_INCREMENT:
// opcode = getop_addition (first_operand_id (stmt), first_operand_id (stmt), INTEGER_ONE);
case ET_UNARY_DECREMENT:
case ET_UNARY_PLUS:
case ET_UNARY_MINUS:
case ET_UNARY_COMPL:
case ET_UNARY_NOT:
case ET_POSTFIX_INCREMENT:
case ET_POSTFIX_DECREMENT:
case ET_CALL:
case ET_NEW:
case ET_INDEX:
case ET_PROP_REF:
case ET_OBJECT:
case ET_FUNCTION:
case ET_ARRAY:
case ET_SUBEXPRESSION:
JERRY_UNIMPLEMENTED ();
break;
case ET_LITERAL:
case ET_IDENTIFIER:
switch (get_assignment_operator (stmt))
{
case AO_NONE:
JERRY_UNREACHABLE ();
break;
case AO_EQ:
opcode = getop_assignment (lhs (stmt), first_operand_id (stmt));
dump_opcode (&opcode);
return;
default:
JERRY_UNIMPLEMENTED ();
}
JERRY_UNREACHABLE ();
default:
JERRY_UNREACHABLE ();
}
if (get_assignment_operator (stmt) != AO_EQ)
JERRY_UNIMPLEMENTED ();
}
else
{
call_expression expr = stmt.data.expr.data.call_expr;
JERRY_ASSERT (!is_operand_list_empty (expr.args));
if (!is_operand_empty (expr.args.ops[1]))
JERRY_UNREACHABLE ();
if (expr.args.ops[0].is_literal)
JERRY_UNREACHABLE ();
opcode = getop_call_1 (expr.name, expr.args.ops[0].data.name);
}
break;
case STMT_END_WHILE:
opcode = getop_jmp (pop_opcode ());
break;
default:
__printf (" generator_dump_statement: %d ", stmt.type);
JERRY_UNREACHABLE ();
}
}

View File

@ -1,25 +0,0 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BYTECODE_GENERATOR_H
#define BYTECODE_GENERATOR_H
#include "parser.h"
void generator_init (void);
void generator_dump_strings (const char **, uint8_t);
void generator_dump_statement (statement);
#endif // BYTECODE_GENERATOR_H

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
#include "allocator.h"
#include "mem-allocator.h"
#include "globals.h"
#include "jerry-libc.h"
#include "lexer.h"
#include "parser.h"
static token saved_token;
static token empty_token = { .type = TOK_EMPTY, .data.none = NULL };
static token empty_token = { .type = TOK_EMPTY, .data.uid = 0 };
typedef struct
{
@ -45,7 +45,7 @@ static string_and_token keyword_tokens[] =
{ .str = "enum", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "export", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "extends", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "false", .tok = { .type = TOK_BOOL, .data.is_true = false } },
{ .str = "false", .tok = { .type = TOK_BOOL, .data.uid = false } },
{ .str = "finally", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FINALLY } },
{ .str = "for", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FOR } },
{ .str = "function", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FUNCTION } },
@ -57,7 +57,7 @@ static string_and_token keyword_tokens[] =
{ .str = "implements", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "let", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "new", .tok = { .type = TOK_KEYWORD, .data.kw = KW_NEW } },
{ .str = "null", .tok = { .type = TOK_NULL, .data.none = NULL } },
{ .str = "null", .tok = { .type = TOK_NULL, .data.uid = 0 } },
{ .str = "package", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "private", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
{ .str = "protected", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
@ -68,7 +68,7 @@ static string_and_token keyword_tokens[] =
{ .str = "switch", .tok = { .type = TOK_KEYWORD, .data.kw = KW_SWITCH } },
{ .str = "this", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THIS } },
{ .str = "throw", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THROW } },
{ .str = "true", .tok = { .type = TOK_BOOL, .data.is_true = true } },
{ .str = "true", .tok = { .type = TOK_BOOL, .data.uid = true } },
{ .str = "try", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TRY } },
{ .str = "typeof", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TYPEOF } },
{ .str = "var", .tok = { .type = TOK_KEYWORD, .data.kw = KW_VAR } },
@ -78,10 +78,25 @@ static string_and_token keyword_tokens[] =
{ .str = "yield", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }
};
typedef struct
{
int num;
token tok;
}
num_and_token;
#define MAX_NAMES 100
#define MAX_NUMS 25
static string_and_token seen_names[MAX_NAMES];
static uint8_t seen_names_num;
static uint8_t seen_names_count = 0;
static num_and_token seen_nums[MAX_NAMES] =
{
[0] = { .num = 0, .tok = { .type = TOK_INT, .data.uid = 0 } },
[1] = { .num = 1, .tok = { .type = TOK_INT, .data.uid = 1 } }
};
static uint8_t seen_nums_count = 2;
static bool
is_empty (token tok)
@ -114,7 +129,7 @@ get_char (size_t i)
if (buffer == NULL)
{
buffer = (char *) malloc (BUFFER_SIZE);
buffer = (char *) mem_HeapAllocBlock (BUFFER_SIZE, MEM_HEAP_ALLOC_SHORT_TERM);
error = __fread (buffer, 1, BUFFER_SIZE, file);
if (error == 0)
return '\0';
@ -184,7 +199,7 @@ decode_keyword (void)
for (i = 0; i < size; i++)
{
if (!__strncmp (keyword_tokens[i].str, token_start, __strlen (keyword_tokens[i].str)))
if (!__strncmp (keyword_tokens[i].str, token_start, (size_t) (buffer - token_start)))
return keyword_tokens[i].tok;
}
@ -196,9 +211,9 @@ convert_seen_name_to_token (void)
{
size_t i;
for (i = 0; i < seen_names_num; i++)
for (i = 0; i < seen_names_count; i++)
{
if (!__strncmp (seen_names[i].str, token_start, __strlen (seen_names[i].str)))
if (!__strncmp (seen_names[i].str, token_start, (size_t) (buffer - token_start)))
return seen_names[i].tok;
}
@ -206,12 +221,33 @@ convert_seen_name_to_token (void)
}
static void
add_to_seen_tokens (string_and_token snt)
add_name_to_seen_tokens (string_and_token snt)
{
JERRY_ASSERT (seen_names_num < MAX_NAMES);
JERRY_ASSERT (seen_names_count < MAX_NAMES);
snt.tok.data.name = (string_id) seen_names_num;
seen_names[seen_names_num++] = snt;
seen_names[seen_names_count++] = snt;
}
static token
convert_seen_num_to_token (int num)
{
size_t i;
for (i = 0; i < seen_nums_count; i++)
{
if (seen_nums[i].num == num)
return seen_nums[i].tok;
}
return empty_token;
}
static void
add_num_to_seen_tokens (num_and_token nat)
{
JERRY_ASSERT (seen_nums_count < MAX_NUMS);
seen_nums[seen_nums_count++] = nat;
}
uint8_t
@ -219,20 +255,32 @@ lexer_get_strings (const char **strings)
{
int i;
for (i = 0; i < seen_names_num; i++)
strings[i] = seen_names[i].str;
if (strings)
for (i = 0; i < seen_names_count; i++)
strings[i] = seen_names[i].str;
return seen_names_num;
return seen_names_count;
}
const char *
lexer_get_string_by_id (string_id id)
lexer_get_string_by_id (uint8_t id)
{
JERRY_ASSERT (id < seen_names_num);
JERRY_ASSERT (id < seen_names_count);
return seen_names[id].str;
}
uint8_t
lexer_get_nums (int *nums)
{
int i;
for (i = 0; i < seen_nums_count; i++)
nums[i] = seen_nums[i].num;
return seen_nums_count;
}
static void
new_token (void)
{
@ -254,7 +302,7 @@ current_token (void)
JERRY_ASSERT (token_start);
JERRY_ASSERT (token_start <= buffer);
size_t length = (size_t) (buffer - token_start);
char *res = (char *) malloc (length + 1);
char *res = (char *) mem_HeapAllocBlock (length + 1, MEM_HEAP_ALLOC_SHORT_TERM);
__strncpy (res, token_start, length);
res[length] = '\0';
token_start = NULL;
@ -265,7 +313,7 @@ current_token (void)
do \
{ \
buffer += NUM; \
return (token) { .type = TOK, .data.none = NULL }; \
return (token) { .type = TOK, .data.uid = 0 }; \
} \
while (0)
@ -338,9 +386,9 @@ parse_name (void)
}
string = current_token ();
known_token = (token) { .type = TOK_NAME, .data.name = seen_names_num };
known_token = (token) { .type = TOK_NAME, .data.uid = seen_names_count };
add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
add_name_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
return known_token;
}
@ -387,6 +435,7 @@ parse_number (void)
bool is_exp = false;
size_t tok_length = 0, i;
int res = 0;
token known_token;
JERRY_ASSERT (__isdigit (c) || c == '.');
@ -423,7 +472,14 @@ parse_number (void)
res = (res << 4) + hex_to_int (token_start[i]);
token_start = NULL;
return (token) { .type = TOK_INT, .data.num = res };
known_token = convert_seen_num_to_token (res);
if (!is_empty (known_token))
return known_token;
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
return known_token;
}
JERRY_ASSERT (!is_hex && !is_exp);
@ -475,7 +531,8 @@ parse_number (void)
{
float res = __strtof (token_start, NULL);
token_start = NULL;
return (token) { .type = TOK_FLOAT, .data.fp_num = res };
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (res);
return empty_token;
}
tok_length = (size_t) (buffer - token_start);;
@ -484,7 +541,13 @@ parse_number (void)
token_start = NULL;
return (token) { .type = TOK_INT, .data.num = res };
known_token = convert_seen_num_to_token (res);
if (!is_empty (known_token))
return known_token;
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
return known_token;
}
static char
@ -513,7 +576,7 @@ parse_string (void)
char *tok = NULL;
char *index = NULL;
const char *i;
size_t length;
size_t length, num;
token res = empty_token;
JERRY_ASSERT (c == '\'' || c == '"');
@ -553,7 +616,7 @@ parse_string (void)
}
length = (size_t) (buffer - token_start);
tok = (char *) malloc (length);
tok = (char *) mem_HeapAllocBlock (length, MEM_HEAP_ALLOC_SHORT_TERM);
index = tok;
for (i = token_start; i < buffer; i++)
@ -581,9 +644,18 @@ parse_string (void)
// Eat up '"'
consume_char ();
res = (token) { .type = TOK_STRING, .data.str = seen_names_num };
for (num = 0; num < seen_names_count; num++)
{
if (!__strncmp (seen_names[num].str, tok, __strlen (tok)))
{
mem_HeapFreeBlock ((uint8_t*) tok);
return seen_names[num].tok;
}
}
add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
res = (token) { .type = TOK_STRING, .data.uid = seen_names_count };
add_name_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
return res;
}
@ -593,7 +665,7 @@ grobble_whitespaces (void)
{
char c = LA (0);
while ((__isspace (c) && c != '\n') || c == '\0')
while ((__isspace (c) && c != '\n'))
{
consume_char ();
c = LA (0);
@ -685,11 +757,11 @@ lexer_next_token (void)
if (c == '\n')
{
consume_char ();
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
}
if (c == '\0')
return (token) { .type = TOK_EOF, .data.none = NULL };;
return (token) { .type = TOK_EOF, .data.uid = 0 };;
if (c == '\'' || c == '"')
return parse_string ();
@ -708,7 +780,7 @@ lexer_next_token (void)
if (c == '/' && LA (1) == '*')
{
if (replace_comment_by_newline ())
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
else
return
#ifdef __HOST
@ -803,11 +875,11 @@ lexer_next_token (void)
token tok = lexer_next_token_private ();
if (tok.type == TOK_NEWLINE)
return tok;
// if (tok.type == TOK_CLOSE_BRACE)
if (tok.type == TOK_CLOSE_PAREN)
{
// if (i == 300)
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
i++;
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
i++;
}
return tok;
}
@ -816,10 +888,10 @@ lexer_next_token (void)
void
lexer_save_token (token tok)
{
#ifdef __HOST
// if (tok.type == TOK_CLOSE_BRACE)
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
#endif
#ifdef __HOST
if (tok.type == TOK_CLOSE_PAREN)
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
#endif
saved_token = tok;
}

View File

@ -18,121 +18,120 @@
#include "globals.h"
typedef uint8_t string_id;
/* Keywords. */
typedef enum
{
/* Not a keyword. */
KW_NONE = 0,
/* Future reserved keyword. */
KW_RESERVED,
typedef uint8_t keyword;
KW_BREAK,
KW_CASE,
KW_CATCH,
KW_CONTINUE,
KW_DEBUGGER,
KW_DEFAULT,
KW_DELETE,
/* Not a keyword. */
#define KW_NONE 0
/* Future reserved keyword. */
#define KW_RESERVED 1
#define KW_BREAK 2
#define KW_CASE 3
#define KW_CATCH 4
KW_DO,
KW_ELSE,
KW_FINALLY,
KW_FOR,
KW_FUNCTION,
KW_IF,
KW_IN,
#define KW_CONTINUE 5
#define KW_DEBUGGER 6
#define KW_DEFAULT 7
#define KW_DELETE 8
#define KW_DO 9
KW_INSTANCEOF,
KW_NEW,
KW_RETURN,
KW_SWITCH,
KW_THIS,
KW_THROW,
KW_TRY,
#define KW_ELSE 10
#define KW_FINALLY 11
#define KW_FOR 12
#define KW_FUNCTION 13
#define KW_IF 14
#define KW_IN 15
#define KW_INSTANCEOF 16
#define KW_NEW 17
#define KW_RETURN 18
#define KW_SWITCH 19
#define KW_THIS 20
#define KW_THROW 21
#define KW_TRY 22
#define KW_TYPEOF 23
#define KW_VAR 24
#define KW_VOID 25
#define KW_WHILE 26
#define KW_WITH 27
KW_TYPEOF,
KW_VAR,
KW_VOID,
KW_WHILE,
KW_WITH
}
keyword;
/* Type of tokens. */
typedef enum
{
TOK_EOF = 0x0, // End of file
TOK_NAME = 0x1, // Identifier
TOK_KEYWORD = 0x2, // Keyword
TOK_INT = 0x3,
TOK_FLOAT = 0x4,
TOK_NULL = 0x5,
TOK_BOOL = 0x6,
TOK_NEWLINE = 0x7,
TOK_STRING = 0x8,
typedef uint8_t token_type;
/* Punctuators. */
TOK_OPEN_BRACE = 0x9, // {
TOK_CLOSE_BRACE = 0xa, // }
TOK_OPEN_PAREN = 0xb, // (
TOK_CLOSE_PAREN = 0xc, // )
TOK_OPEN_SQUARE, // [
TOK_CLOSE_SQUARE, // [
#define TOK_EOF 0 // End of file
#define TOK_NAME 1 // Identifier
#define TOK_KEYWORD 2 // Keyword
#define TOK_INT 3
#define TOK_FLOAT 4
TOK_DOT, // .
TOK_SEMICOLON, // ;
TOK_COMMA, // ,
TOK_LESS, // <
TOK_GREATER, // >
TOK_LESS_EQ, // <=
#define TOK_NULL 5
#define TOK_BOOL 6
#define TOK_NEWLINE 7
#define TOK_STRING 8
#define TOK_OPEN_BRACE 9 // {
TOK_GREATER_EQ, // <=
TOK_DOUBLE_EQ, // ==
TOK_NOT_EQ, // !=
TOK_TRIPLE_EQ, // ===
TOK_NOT_DOUBLE_EQ, // !==
#define TOK_CLOSE_BRACE 10 // }
#define TOK_OPEN_PAREN 11 // (
#define TOK_CLOSE_PAREN 12 // )
#define TOK_OPEN_SQUARE 13 // [
#define TOK_CLOSE_SQUARE 14 // [
TOK_PLUS, // +
TOK_MINUS, // -
TOK_MULT, // *
TOK_MOD, // %
TOK_DOUBLE_PLUS, // ++
TOK_DOUBLE_MINUS, // --
#define TOK_DOT 15 // .
#define TOK_SEMICOLON 16 // ;
#define TOK_COMMA 17 // ,
#define TOK_LESS 18 // <
#define TOK_GREATER 19 // >
TOK_LSHIFT, // <<
TOK_RSHIFT, // >>
TOK_RSHIFT_EX, // >>>
TOK_AND, // &
TOK_OR, // |
TOK_XOR, // ^
#define TOK_LESS_EQ 20 // <=
#define TOK_GREATER_EQ 21 // <=
#define TOK_DOUBLE_EQ 22 // ==
#define TOK_NOT_EQ 23 // !=
#define TOK_TRIPLE_EQ 24 // ===
TOK_NOT, // !
TOK_COMPL, // ~
TOK_DOUBLE_AND, // &&
TOK_DOUBLE_OR, // ||
TOK_QUERY, // ?
TOK_COLON, // :
#define TOK_NOT_DOUBLE_EQ 25 // !==
#define TOK_PLUS 26 // +
#define TOK_MINUS 27 // -
#define TOK_MULT 28 // *
#define TOK_MOD 29 // %
TOK_EQ, // =
TOK_PLUS_EQ, // +=
TOK_MINUS_EQ, // -=
TOK_MULT_EQ, // *=
TOK_MOD_EQ, // %=
TOK_LSHIFT_EQ, // <<=
#define TOK_DOUBLE_PLUS 30 // ++
#define TOK_DOUBLE_MINUS 31 // --
#define TOK_LSHIFT 32 // <<
#define TOK_RSHIFT 33 // >>
#define TOK_RSHIFT_EX 34 // >>>
TOK_RSHIFT_EQ, // >>=
TOK_RSHIFT_EX_EQ, // >>>=
TOK_AND_EQ, // &=
TOK_OR_EQ, // |=
TOK_XOR_EQ, // ^=
#define TOK_AND 35 // &
#define TOK_OR 36 // |
#define TOK_XOR 37 // ^
#define TOK_NOT 38 // !
#define TOK_COMPL 39 // ~
#define TOK_DOUBLE_AND 40 // &&
#define TOK_DOUBLE_OR 41 // ||
#define TOK_QUERY 42 // ?
#define TOK_COLON 43 // :
#define TOK_EQ 44 // =
#define TOK_PLUS_EQ 45 // +=
#define TOK_MINUS_EQ 46 // -=
#define TOK_MULT_EQ 47 // *=
#define TOK_MOD_EQ 48 // %=
#define TOK_LSHIFT_EQ 49 // <<=
#define TOK_RSHIFT_EQ 50 // >>=
#define TOK_RSHIFT_EX_EQ 51 // >>>=
#define TOK_AND_EQ 52 // &=
#define TOK_OR_EQ 53 // |=
#define TOK_XOR_EQ 54 // ^=
#define TOK_DIV 55 // /
#define TOK_DIV_EQ 56 // /=
#define TOK_EMPTY 57
TOK_DIV, // /
TOK_DIV_EQ, // /=
TOK_EMPTY
}
token_type;
/* Represents the contents of a token. */
typedef struct
@ -140,17 +139,12 @@ typedef struct
token_type type;
union
{
void *none;
keyword kw;
string_id name;
bool is_true;
int num;
float fp_num;
string_id str;
}
{
keyword kw;
uint8_t uid;
}
data;
}
} __packed
token;
#ifdef __HOST
@ -160,11 +154,9 @@ void lexer_set_source (const char *);
#endif
token lexer_next_token (void);
void lexer_save_token (token);
void lexer_dump_buffer_state (void);
uint8_t lexer_get_strings (const char **);
const char *lexer_get_string_by_id (string_id id);
const char *lexer_get_string_by_id (uint8_t);
uint8_t lexer_get_nums (int *);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,427 +18,8 @@
#include "globals.h"
#define null_string 255
#define MAX_PARAMS 5
#define MAX_EXPRS 2
#define MAX_PROPERTIES 5
#define MAX_DECLS 5
#define MAX_SUFFIXES 2
/** Represents list of parameters. */
typedef struct formal_parameter_list
{
/** Identifiers of a parameter. Next after last parameter is NULL. */
uint8_t names[MAX_PARAMS];
}
formal_parameter_list;
static const formal_parameter_list
empty_formal_parameter_list =
{
.names = { [0] = null_string }
};
bool is_formal_parameter_list_empty (formal_parameter_list);
/** @function_declaration represents both declaration and expression of a function.
After this parser must return a block of statements. */
typedef struct
{
/** Identifier: name of a function. Can be NULL for anonimous functions. */
uint8_t name;
/** List of parameter of a function. Can be NULL. */
formal_parameter_list params;
}
function_declaration;
typedef function_declaration function_expression;
/** Types of literals: null, bool, decimal and string.
Decimal type is represented by LIT_INT and supports only double-word sized integers. */
typedef enum
{
LIT_NULL,
LIT_BOOL,
LIT_INT,
LIT_STR
}
literal_type;
/** Represents different literals, contains a data of them. */
typedef struct
{
/** Type of a literal. */
literal_type type;
/** Value of a literal. */
union
{
/** Used by null literal, always NULL. */
void *none;
/** String literal value. */
uint8_t str;
/** Number value. */
int num;
/** Boolean value. */
bool is_true;
}
data;
}
literal;
typedef struct
{
bool is_literal;
union
{
void *none;
literal lit;
uint8_t name;
}
data;
}
operand;
typedef operand property_name;
static const operand
empty_operand =
{
.is_literal = false,
.data.none = NULL
};
bool is_operand_empty (operand);
typedef struct
{
operand op1, op2;
}
operand_pair;
typedef struct
{
operand ops[MAX_PARAMS];
}
operand_list;
static const operand_list
empty_operand_list =
{
.ops = { [0] = { .is_literal = false, .data.none = NULL } }
};
bool is_operand_list_empty (operand_list);
typedef operand_list array_literal;
typedef operand_list argument_list;
typedef struct
{
uint8_t name;
argument_list args;
}
call_expression;
/** Represents a single property. */
typedef struct
{
/** Name of property. */
property_name name;
/** Value of property. */
operand value;
}
property;
static const property empty_property =
{
.name = { .is_literal = false, .data.none = NULL },
.value = { .is_literal = false, .data.none = NULL }
};
bool is_property_empty (property);
/** List of properties. Represents ObjectLiteral. */
typedef struct
{
/** Properties. */
property props[MAX_PROPERTIES];
}
property_list;
static const property_list
empty_property_list =
{
.props =
{ [0] =
{ .name =
{ .is_literal = false, .data.none = NULL },
.value =
{ .is_literal = false, .data.none = NULL }}}
};
bool is_property_list_empty (property_list);
typedef property_list object_literal;
typedef enum
{
AO_NONE,
AO_EQ,
AO_MULT_EQ,
AO_DIV_EQ,
AO_MOD_EQ,
AO_PLUS_EQ,
AO_MINUS_EQ,
AO_LSHIFT_EQ,
AO_RSHIFT_EQ,
AO_RSHIFT_EX_EQ,
AO_AND_EQ,
AO_XOR_EQ,
AO_OR_EQ
}
assignment_operator;
typedef enum
{
ET_NONE,
ET_LOGICAL_OR,
ET_LOGICAL_AND,
ET_BITWISE_OR,
ET_BITWISE_XOR,
ET_BITWISE_AND,
ET_DOUBLE_EQ,
ET_NOT_EQ,
ET_TRIPLE_EQ,
ET_NOT_DOUBLE_EQ,
ET_LESS,
ET_GREATER,
ET_LESS_EQ,
ET_GREATER_EQ,
ET_INSTANCEOF,
ET_IN,
ET_LSHIFT,
ET_RSHIFT,
ET_RSHIFT_EX,
ET_PLUS,
ET_MINUS,
ET_MULT,
ET_DIV,
ET_MOD,
ET_UNARY_DELETE,
ET_UNARY_VOID,
ET_UNARY_TYPEOF,
ET_UNARY_INCREMENT,
ET_UNARY_DECREMENT,
ET_UNARY_PLUS,
ET_UNARY_MINUS,
ET_UNARY_COMPL,
ET_UNARY_NOT,
ET_POSTFIX_INCREMENT,
ET_POSTFIX_DECREMENT,
ET_CALL,
ET_NEW,
ET_INDEX,
ET_PROP_REF,
ET_OBJECT,
ET_FUNCTION,
ET_ARRAY,
ET_SUBEXPRESSION,
ET_LITERAL,
ET_IDENTIFIER
}
expression_type;
typedef struct
{
assignment_operator oper;
expression_type type;
/** NUllable. */
uint8_t var;
union
{
void *none;
operand_pair ops;
call_expression call_expr;
array_literal arr_lit;
object_literal obj_lit;
function_expression func_expr;
}
data;
}
assignment_expression;
static const assignment_expression
empty_expression =
{
.oper = AO_NONE,
.type = ET_NONE,
.data.none = NULL
};
bool is_expression_empty (assignment_expression);
/** Represents expression, array literal and list of argument. */
typedef struct
{
/** Single assignment expression. Cannot be NULL for expression and list of arguments.
But can be NULL for array literal. */
assignment_expression exprs[MAX_EXPRS];
}
expression_list;
typedef expression_list expression;
/* Statements. */
typedef struct
{
uint8_t name;
assignment_expression assign_expr;
}
variable_declaration;
static const variable_declaration
empty_variable_declaration =
{
.name = null_string,
.assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL }
};
bool is_variable_declaration_empty (variable_declaration);
typedef struct
{
variable_declaration decls[MAX_DECLS];
}
variable_declaration_list;
typedef struct
{
bool is_decl;
union
{
expression expr;
variable_declaration_list decl_list;
}
data;
}
for_statement_initialiser_part;
typedef struct
{
for_statement_initialiser_part init;
assignment_expression limit, incr;
}
for_statement;
typedef struct
{
bool is_decl;
union
{
assignment_expression left_hand_expr;
variable_declaration decl;
}
data;
}
for_in_statement_initializer_part;
typedef struct
{
for_in_statement_initializer_part init;
expression list_expr;
}
for_in_statement;
typedef struct
{
bool is_for_in;
union
{
for_statement for_stmt;
for_in_statement for_in_stmt;
}
data;
}
for_or_for_in_statement;
typedef enum
{
STMT_NULL,
STMT_VARIABLE,
STMT_EMPTY,
STMT_IF,
STMT_ELSE,
STMT_ELSE_IF,
STMT_END_IF,
STMT_DO_WHILE,
STMT_END_DO_WHILE,
STMT_WHILE,
STMT_END_WHILE,
STMT_FOR_OR_FOR_IN,
STMT_END_FOR_OR_FOR_IN,
STMT_CONTINUE,
STMT_BREAK,
STMT_RETURN,
STMT_WITH,
STMT_END_WITH,
STMT_LABELLED,
STMT_SWITCH,
STMT_END_SWITCH,
STMT_CASE,
STMT_THROW,
STMT_TRY,
STMT_CATCH,
STMT_END_CATCH,
STMT_FINALLY,
STMT_END_FINALLY,
STMT_EXPRESSION,
STMT_END_SUBEXPRESSION,
STMT_FUNCTION,
STMT_END_FUNCTION,
STMT_EOF
}
statement_type;
typedef struct statement
{
statement_type type;
union
{
void *none;
variable_declaration_list var_stmt;
assignment_expression expr;
for_or_for_in_statement for_stmt;
uint8_t name;
function_declaration fun_decl;
}
data;
}
statement;
static const statement
null_statement =
{
.type = STMT_NULL,
.data.none = NULL
};
bool is_statement_null (statement);
void parser_init (void);
statement parser_parse_statement (void);
void parser_parse_program (void);
void parser_fatal (jerry_Status_t code);

View File

@ -69,9 +69,9 @@ jerry_Exit( jerry_Status_t code) /**< status code */
case ERR_GENERAL:
__printf("ERR_GENERAL\n");
break;
default:
__printf( "Return code is zero");
}
jerry_AssertFail( "Return code is zero", __FILE__, __LINE__);
}
#endif /* !JERRY_NDEBUG */

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PRETTY_PRINTER_H
#define PRETTY_PRINTER_H
#include "lexer.h"
#include "parser.h"
void pp_reset (void);
void pp_finish (void);
void pp_token (token);
void pp_keyword (keyword);
void pp_statement (statement);
#endif

View File

@ -22,4 +22,6 @@ void serializer_init (void);
void serializer_dump_data (const void *, size_t);
void serializer_rewrite_data (const int8_t, const void *, size_t);
#endif // SERIALIZER_H

View File

@ -15,17 +15,39 @@
#include "serializer.h"
#include "jerry-libc.h"
#include "opcodes.h"
FILE *dump;
#define OPCODE_STR(op) \
#op,
static char* massive[] = {
OP_LIST (OPCODE_STR)
""
};
void
serializer_init (void)
{
}
static int opcode_counter = 0;
void
serializer_dump_data (const void *data, size_t size)
{
size_t i;
for (i = 0; i < size; i++)
__putchar (((char *) data)[i]);
__printf ("%03d: %20s ", opcode_counter++, massive[(int)((char*)data)[0]]);
for (i = 1; i < size; i++)
__printf ("%4d ", ((char*)data)[i]);
__printf ("\n");
}
void
serializer_rewrite_data (const int8_t offset __unused, const void *data __unused, size_t size __unused)
{
TODO (implement);
}

View File

@ -35,8 +35,6 @@
#include "jerry-libc.h"
#include "lexer.h"
#include "parser.h"
#include "pretty-printer.h"
#include "bytecode-generator.h"
#define DUMP_TOKENS (1u << 0)
#define DUMP_AST (1u << 1)
@ -99,27 +97,9 @@ fake_exit (void)
#endif
}
static inline void
check_for_several_dumps (uint8_t dump)
{
bool was_bit = 0;
for (; dump; dump >>= 1)
{
if (dump & 1u)
{
if (was_bit)
jerry_Exit (ERR_SEVERAL_FILES);
else
was_bit = true;
}
}
}
int
main (int argc, char **argv)
{
statement st;
uint8_t dump = 0;
#ifdef __HOST
const char *file_name = NULL;
FILE *file = NULL;
@ -127,27 +107,15 @@ main (int argc, char **argv)
mem_Init ();
if (argc > 0)
for (int i = 1; i < argc; i++)
{
if (!__strcmp ("-t", argv[i]))
dump |= DUMP_TOKENS;
else if (!__strcmp ("-a", argv[i]))
dump |= DUMP_AST;
else if (!__strcmp ("-b", argv[i]))
dump |= DUMP_BYTECODE;
#ifdef __HOST
else if (file_name == NULL)
file_name = argv[i];
#endif
if (argc > 0)
{
if (file_name == NULL)
file_name = argv[1];
else
jerry_Exit (ERR_SEVERAL_FILES);
}
check_for_several_dumps (dump);
if (!dump)
dump |= DUMP_BYTECODE;
#endif
#ifdef __HOST
if (file_name == NULL)
@ -165,60 +133,26 @@ main (int argc, char **argv)
lexer_set_source (generated_source);
#endif
if (dump & DUMP_AST)
{
parser_init ();
st = parser_parse_statement ();
JERRY_ASSERT (!is_statement_null (st));
while (st.type != STMT_EOF)
{
pp_statement (st);
st = parser_parse_statement ();
JERRY_ASSERT (!is_statement_null (st));
}
}
// const char *strings[MAX_STRINGS];
// uint8_t strings_num;
// First run parser to fill list of strings
token tok = lexer_next_token ();
while (tok.type != TOK_EOF)
tok = lexer_next_token ();
if (dump & DUMP_TOKENS)
{
token tok = lexer_next_token ();
while (tok.type != TOK_EOF)
{
pp_token (tok);
tok = lexer_next_token ();
}
}
// strings_num = lexer_get_strings (strings);
if (dump & DUMP_BYTECODE)
{
const char *strings[MAX_STRINGS];
uint8_t strings_num;
// First run parser to fill list of strings
token tok = lexer_next_token ();
while (tok.type != TOK_EOF)
tok = lexer_next_token ();
strings_num = lexer_get_strings (strings);
// Reset lexer
// Reset lexer
#ifdef __HOST
__rewind (file);
lexer_set_file (file);
__rewind (file);
lexer_set_file (file);
#else
lexer_set_source (generated_source);
lexer_set_source (generated_source);
#endif
parser_init ();
generator_init ();
generator_dump_strings (strings, strings_num);
st = parser_parse_statement ();
JERRY_ASSERT (!is_statement_null (st));
while (st.type != STMT_EOF)
{
generator_dump_statement (st);
st = parser_parse_statement ();
JERRY_ASSERT (!is_statement_null (st));
}
}
parser_init ();
TODO (serializer_dump_data (strings strings_num));
parser_parse_program ();
//gen_bytecode (generated_source);
//gen_bytecode ();