diff --git a/.gitignore b/.gitignore index 700b816ac..5a40c0c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ nbproject # Random Trash *~ +js.files +core diff --git a/Makefile b/Makefile index 6072ba1ed..dc81b69ab 100644 --- a/Makefile +++ b/Makefile @@ -83,8 +83,8 @@ CFLAGS ?= $(INCLUDES) -std=c99 -m32 #-fdiagnostics-color=always #CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard #CFLAGS += -ffunction-sections -fdata-sections -DEBUG_OPTIONS = -g3 -O0 -DDEBUG# -fsanitize=address -RELEASE_OPTIONS = -Os -Werror -DNDEBUG +DEBUG_OPTIONS = -g3 -O0 -DJERRY_NDEBUG# -fsanitize=address +RELEASE_OPTIONS = -Os -Werror -DJERRY_NDEBUG DEFINES = -DMEM_HEAP_CHUNK_SIZE=256 -DMEM_HEAP_AREA_SIZE=32768 TARGET_HOST = -D__HOST diff --git a/src/error.h b/src/error.h index e6a85202c..8b30d7092 100644 --- a/src/error.h +++ b/src/error.h @@ -16,20 +16,16 @@ #ifndef ERROR_H #define ERROR_H -#include -#include -#include +#include "mappings.h" -void lexer_dump_buffer_state (); - -#define unreachable() assert(0) +extern void lexer_dump_buffer_state (); static inline void fatal (int code) { printf ("FATAL: %d\n", code); lexer_dump_buffer_state (); - unreachable (); + JERRY_UNREACHABLE (); exit (code); } diff --git a/src/globals.h b/src/globals.h index 40ee240dc..f421c9623 100644 --- a/src/globals.h +++ b/src/globals.h @@ -73,7 +73,7 @@ extern uint32_t jerry_UnreferencedExpression; /** * Mark for unreachable points and unimplemented cases */ -#define JERRY_UNREACHABLE() { JERRY_ASSERT( false); __builtin_trap(); } +#define JERRY_UNREACHABLE() do { JERRY_ASSERT( false); __builtin_trap(); } while (0) #define JERRY_UNIMPLEMENTED() JERRY_UNREACHABLE() /** diff --git a/src/jerry-libc.c b/src/jerry-libc.c index 7924b1d5d..f8b599a88 100644 --- a/src/jerry-libc.c +++ b/src/jerry-libc.c @@ -29,7 +29,7 @@ extern int vprintf (__const char *__restrict __format, __builtin_va_list __arg); * @return @s */ void* -libc_memset(void *s, /**< area to set values in */ +__memset(void *s, /**< area to set values in */ int c, /**< value to set */ size_t n) /**< area size */ { @@ -40,7 +40,7 @@ libc_memset(void *s, /**< area to set values in */ } return s; -} /* libc_memset */ +} /* __memset */ /** * memcmp @@ -50,7 +50,7 @@ libc_memset(void *s, /**< area to set values in */ * 1, otherwise */ int -libc_memcmp(const void *s1, /**< first area */ +__memcmp(const void *s1, /**< first area */ const void *s2, /**< second area */ size_t n) /**< area size */ { @@ -67,15 +67,15 @@ libc_memcmp(const void *s1, /**< first area */ } return 0; -} /* libc_memcmp */ +} /* __memcmp */ /** * memcpy */ -void -libc_memcpy(void *s1, /**< destination */ - const void *s2, /**< source */ - size_t n) /**< bytes number */ +void * +__memcpy(void *s1, /**< destination */ + const void *s2, /**< source */ + size_t n) /**< bytes number */ { uint8_t *pArea1 = s1; const uint8_t *pArea2 = s2; @@ -84,7 +84,9 @@ libc_memcpy(void *s1, /**< destination */ { pArea1[ index ] = pArea2[ index ]; } -} /* libc_memcpy */ + + return s1; +} /* __memcpy */ /** * printf @@ -92,7 +94,7 @@ libc_memcpy(void *s1, /**< destination */ * @return number of characters printed */ int -libc_printf(const char *format, /**< format string */ +__printf(const char *format, /**< format string */ ...) /**< parameters' values */ { va_list args; @@ -104,4 +106,167 @@ libc_printf(const char *format, /**< format string */ va_end( args); return ret; -} /* libc_printf */ +} /* __printf */ + +/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */ +int +__putchar (int c) +{ + return __printf ("%c", c); +} + +/** exit - cause normal process termination. Infinite loop. */ +void +__exit (int status __unused) +{ + for (;;) + ; +} + +/** Compare two strings. return an integer less than, equal to, or greater than zero + if s1 is found, respectively, to be less than, to match, or be greater than s2. */ +int +__strcmp (const char *s1, const char *s2) +{ + size_t i; + if (s1 == NULL) + { + if (s2 != NULL) + return -1; + else + return 0; + } + if (s2 == NULL) + return 1; + + for (i = 0; s1[i]; i++) + { + if (s1[i] > s2[i]) + return 1; + else if (s1[i] < s2[i]) + return -1; + } + + if (s2[i]) + return -1; + + return 0; +} + +/** Compare two strings. return an integer less than, equal to, or greater than zero + if the first n character of s1 is found, respectively, to be less than, to match, + or be greater than the first n character of s2. */ +int +__strncmp (const char *s1, const char *s2, size_t n) +{ + size_t i; + if (s1 == NULL) + { + if (s2 != NULL) + return -1; + else + return 0; + } + if (s2 == NULL) + return 1; + + for (i = 0; i < n; i++) + { + if (s1[i] > s2[i]) + return 1; + else if (s1[i] < s2[i]) + return -1; + } + + return 0; +} + +/** Copy a string. At most n bytes of src are copied. Warning: If there is no + null byte among the first n bytes of src, the string placed in dest will not be null-terminated. + @return a pointer to the destination string dest. */ +char * +__strncpy(char *dest, const char *src, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + dest[i] = src[i]; + + return dest; +} + +/** Convert the initial portion of the string pointed to by nptr to float representation. */ +float +__strtof (const char *nptr, char **endptr) +{ + (void) nptr; + (void) endptr; + + JERRY_UNIMPLEMENTED (); +} + +/** Calculate the length of a string. */ +size_t +__strlen (const char *s) +{ + size_t i; + for (i = 0; s[i]; i++) + ; + return i; +} + +/** Checks for white-space characters. In the "C" and "POSIX" locales, these are: space, + form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). */ +int +__isspace (int c) +{ + switch (c) + { + case ' ': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + return 1; + default: + return 0; + } +} + +/** Checks for an uppercase letter. */ +int +__isupper (int c) +{ + return c >= 'A' && c <= 'Z'; +} + +/** Checks for an lowercase letter. */ +int +__islower (int c) +{ + return c >= 'a' && c <= 'z'; +} + +/** Checks for an alphabetic character. + In the standard "C" locale, it is equivalent to (isupper(c) || islower(c)). */ +int +__isalpha (int c) +{ + return __isupper (c) || __islower (c); +} + +/** Checks for a digit (0 through 9). */ +int +__isdigit (int c) +{ + return c >= '0' && c <= '9'; +} + +/** checks for a hexadecimal digits, that is, one of + 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F. */ +int +__isxdigit (int c) +{ + return __isdigit (c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} diff --git a/src/jerry-libc.h b/src/jerry-libc.h index 32a791406..09619e95f 100644 --- a/src/jerry-libc.h +++ b/src/jerry-libc.h @@ -21,9 +21,30 @@ #include "globals.h" -extern void *libc_memset(void *s, int c, size_t n); -extern int libc_memcmp(const void *s1, const void *s2, size_t n); -extern void libc_memcpy(void *s1, const void *s2, size_t n); -extern int libc_printf(const char *format, ...); +extern void *__memset (void *s, int c, size_t n); +extern int __memcmp (const void *s1, const void *s2, size_t n); +extern void *__memcpy (void *s1, const void *s2, size_t n); +extern int __printf (const char *format, ...); +extern int __putchar (int); +extern void __exit (int); + +extern int __strcmp (const char *, const char *); +extern int __strncmp (const char *, const char *, size_t); +extern char *__strncpy (char *, const char *, size_t); +extern float __strtof (const char *, char **); +extern size_t __strlen (const char *); + +extern int __isspace (int); +extern int __isupper (int); +extern int __islower (int); +extern int __isalpha (int); +extern int __isdigit (int); +extern int __isxdigit (int); + +#define DBL_MANT_DIG ( 52) +#define DBL_DIG ( 10) +#define DBL_MIN_EXP (-324) +#define DBL_MAX_EXP ( 308) +#define HUGE_VAL (1e37) #endif /* JERRY_LIBC_H */ diff --git a/src/liballocator/mem-heap.c b/src/liballocator/mem-heap.c index 252307e0c..99c060c3d 100644 --- a/src/liballocator/mem-heap.c +++ b/src/liballocator/mem-heap.c @@ -346,7 +346,7 @@ mem_HeapPrint( bool dumpBlockData) /**< print block with data (true) { mem_CheckHeap(); - libc_printf("Heap: start=%p size=%lu, first block->%p, last block->%p\n", + __printf("Heap: start=%p size=%lu, first block->%p, last block->%p\n", mem_Heap.m_HeapStart, mem_Heap.m_HeapSize, (void*) mem_Heap.m_pFirstBlock, @@ -356,7 +356,7 @@ mem_HeapPrint( bool dumpBlockData) /**< print block with data (true) pBlock != NULL; pBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ] ) { - libc_printf("Block (%p): magic num=0x%08x, size in chunks=%lu, previous block->%p next block->%p\n", + __printf("Block (%p): magic num=0x%08x, size in chunks=%lu, previous block->%p next block->%p\n", (void*) pBlock, pBlock->m_MagicNum, pBlock->m_SizeInChunks, @@ -370,13 +370,13 @@ mem_HeapPrint( bool dumpBlockData) /**< print block with data (true) offset < mem_GetHeapBlockDataSpaceSizeInBytes( pBlock); offset++ ) { - libc_printf("%02x ", pBlockData[ offset ]); + __printf("%02x ", pBlockData[ offset ]); } - libc_printf("\n"); + __printf("\n"); } } - libc_printf("\n"); + __printf("\n"); } /* mem_PrintHeap */ /** diff --git a/src/liballocator/mem-pool.c b/src/liballocator/mem-pool.c index 50ff836c9..3f46c3563 100644 --- a/src/liballocator/mem-pool.c +++ b/src/liballocator/mem-pool.c @@ -111,10 +111,10 @@ mem_PoolInit(mem_PoolState_t *pPool, /**< pool */ * All chunks are free right after initialization */ pPool->m_FreeChunksNumber = chunksNumber; - libc_memset( pPool->m_pBitmap, 0, bitmapAreaSize); + __memset( pPool->m_pBitmap, 0, bitmapAreaSize); #ifndef JERRY_NDEBUG - libc_memset( pPool->m_pChunks, mem_PoolFreeChunkMagicNum, chunksAreaSize); + __memset( pPool->m_pChunks, mem_PoolFreeChunkMagicNum, chunksAreaSize); #endif /* JERRY_NDEBUG */ mem_CheckPool( pPool); @@ -198,7 +198,7 @@ mem_PoolFreeChunk(mem_PoolState_t *pPool, /**< pool */ mword_t bitMask = ( 1lu << bitmapBitInBlock ); #ifndef JERRY_NDEBUG - libc_memset( (uint8_t*) pChunk, mem_PoolFreeChunkMagicNum, pPool->m_ChunkSize); + __memset( (uint8_t*) pChunk, mem_PoolFreeChunkMagicNum, pPool->m_ChunkSize); #endif /* JERRY_NDEBUG */ JERRY_ASSERT( pPool->m_pBitmap[ bitmapBlockIndex ] & bitMask ); @@ -221,7 +221,7 @@ mem_CheckPool( mem_PoolState_t __unused *pPool) /**< pool (unused #ifdef JERRY_N JERRY_ASSERT( (uint8_t*) pPool->m_pChunks > pPool->m_pPoolStart ); uint8_t freeChunkTemplate[ pPool->m_ChunkSize ]; - libc_memset( &freeChunkTemplate, mem_PoolFreeChunkMagicNum, sizeof (freeChunkTemplate)); + __memset( &freeChunkTemplate, mem_PoolFreeChunkMagicNum, sizeof (freeChunkTemplate)); size_t metFreeChunksNumber = 0; @@ -242,7 +242,7 @@ mem_CheckPool( mem_PoolState_t __unused *pPool) /**< pool (unused #ifdef JERRY_N { metFreeChunksNumber++; - JERRY_ASSERT( libc_memcmp( &pPool->m_pChunks[ chunkIndex * pPool->m_ChunkSize ], freeChunkTemplate, pPool->m_ChunkSize) == 0 ); + JERRY_ASSERT( __memcmp( &pPool->m_pChunks[ chunkIndex * pPool->m_ChunkSize ], freeChunkTemplate, pPool->m_ChunkSize) == 0 ); } } } diff --git a/src/libcoreint/interpreter.c b/src/libcoreint/interpreter.c index d841fdf6f..5eb1a34ef 100644 --- a/src/libcoreint/interpreter.c +++ b/src/libcoreint/interpreter.c @@ -31,13 +31,13 @@ gen_bytecode () wait(500); } - */ save_op_data (0, getop_loop_inf (1)); save_op_data (1, getop_call_1 (0, 12)); save_op_data (2, getop_call_1 (0, 13)); save_op_data (3, getop_call_1 (0, 14)); save_op_data (4, getop_call_1 (0, 15)); save_op_data (5, getop_jmp (0)); + */ #ifdef __MCU // It's mandatory to restart app! diff --git a/src/libcoreint/interpreter.h b/src/libcoreint/interpreter.h index 01916337f..620f43549 100644 --- a/src/libcoreint/interpreter.h +++ b/src/libcoreint/interpreter.h @@ -16,7 +16,7 @@ #ifndef INTERPRETER_H #define INTERPRETER_H -#ifdef __HOST +#ifdef JERRY_NDEBUG #include #include #include diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 50b2e1070..f5bf62469 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -23,60 +23,60 @@ save_op_data (int pos, OPCODE opdata) __program[pos] = opdata; } -void opfunc_loop_init_num (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_loop_precond_begin_num (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_loop_precond_end_num (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_loop_postcond (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_call_2 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_call_n (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_func_decl_1 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_func_decl_2 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_func_decl_n (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_1 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_1_end (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_2 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_2_end (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_3 (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_varg_3_end (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_retval (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_ret (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_multiplication (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_devision (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_remainder (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_addition (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_substruction (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_shift_left (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_shift_right (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_shift_uright (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_b_and (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_b_xor (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_assignment_b_or (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_logical_and (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_logical_or (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_and (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_or (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_xor (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_shift_left (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_shift_right (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_b_shift_uright (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_addition (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_substraction (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_division (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_multiplication (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_remainder (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_jmp_up (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_jmp_down (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_true_jmp (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_false_jmp (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_less_than (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_less_or_equal (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_greater_than (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_greater_or_equal (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_equal_value (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_not_equal_value (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_equal_value_type (OPCODE opdata, struct __int_data *int_data) { unreachable (); } -void opfunc_is_not_equal_value_type (OPCODE opdata, struct __int_data *int_data) { unreachable (); } +void opfunc_loop_init_num (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_loop_precond_begin_num (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_loop_precond_end_num (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_loop_postcond (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_call_2 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_call_n (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_func_decl_1 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_func_decl_2 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_func_decl_n (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_1 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_1_end (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_2 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_2_end (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_3 (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_varg_3_end (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_retval (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_ret (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_multiplication (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_devision (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_remainder (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_addition (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_substruction (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_shift_left (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_shift_right (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_shift_uright (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_b_and (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_b_xor (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_assignment_b_or (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_logical_and (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_logical_or (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_and (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_or (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_xor (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_shift_left (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_shift_right (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_b_shift_uright (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_addition (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_substraction (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_division (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_multiplication (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_remainder (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_jmp_up (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_jmp_down (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_true_jmp (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_false_jmp (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_less_than (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_less_or_equal (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_greater_than (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_greater_or_equal (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_equal_value (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_not_equal_value (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_equal_value_type (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } +void opfunc_is_not_equal_value_type (OPCODE opdata, struct __int_data *int_data) { JERRY_UNREACHABLE (); } void opfunc_loop_inf (OPCODE opdata, struct __int_data *int_data) diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index fd027e7c8..cf0c3216e 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -16,7 +16,7 @@ #ifndef OPCODES_H #define OPCODES_H -#ifdef __HOST +#ifdef JERRY_NDEBUG #include #endif diff --git a/src/libecmaobjects/ctx-manager.c b/src/libecmaobjects/ctx-manager.c index b4621eaa2..488ec509d 100644 --- a/src/libecmaobjects/ctx-manager.c +++ b/src/libecmaobjects/ctx-manager.c @@ -167,7 +167,7 @@ ctx_Init(void) JERRY_ASSERT( ctx_ContextsNumber == 0 ); #ifndef JERRY_NDEBUG - libc_memset( ctx_Stack, 0, sizeof (ctx_Stack)); + __memset( ctx_Stack, 0, sizeof (ctx_Stack)); #endif /* !JERRY_NDEBUG */ ctx_InitGlobalObject(); @@ -382,7 +382,7 @@ ctx_CopyVariable(ctx_SyntacticReference_t *pVarFrom, /**< source variable */ case ECMA_TYPE_NUMBER: { ecma_Number_t *pNumberCopy = ecma_AllocNumber(); - libc_memcpy( pNumberCopy, + __memcpy( pNumberCopy, ecma_GetPointer( sourceVariableValue.m_Value), sizeof (ecma_Number_t)); ecma_SetPointer( destinationVariableValue.m_Value, pNumberCopy); diff --git a/src/libecmaobjects/ecma-helpers.c b/src/libecmaobjects/ecma-helpers.c index c2d3625b1..65a9497ce 100644 --- a/src/libecmaobjects/ecma-helpers.c +++ b/src/libecmaobjects/ecma-helpers.c @@ -221,7 +221,7 @@ ecma_NewEcmaString(const ecma_Char_t *pString, /**< buffer of characters */ uint8_t *copyPointer = (uint8_t*) pString; size_t charsLeft = length; size_t charsToCopy = JERRY_MIN( length, sizeof (pStringFirstChunk->m_Elements) / sizeof (ecma_Char_t)); - libc_memcpy(pStringFirstChunk->m_Elements, copyPointer, charsToCopy * sizeof (ecma_Char_t)); + __memcpy(pStringFirstChunk->m_Elements, copyPointer, charsToCopy * sizeof (ecma_Char_t)); charsLeft -= charsToCopy; copyPointer += charsToCopy * sizeof (ecma_Char_t); @@ -233,7 +233,7 @@ ecma_NewEcmaString(const ecma_Char_t *pString, /**< buffer of characters */ pStringNonFirstChunk = ecma_AllocArrayNonFirstChunk(); size_t charsToCopy = JERRY_MIN( charsLeft, sizeof (pStringNonFirstChunk->m_Elements) / sizeof (ecma_Char_t)); - libc_memcpy(pStringNonFirstChunk->m_Elements, copyPointer, charsToCopy * sizeof (ecma_Char_t)); + __memcpy(pStringNonFirstChunk->m_Elements, copyPointer, charsToCopy * sizeof (ecma_Char_t)); charsLeft -= charsToCopy; copyPointer += charsToCopy * sizeof (ecma_Char_t); @@ -274,7 +274,7 @@ ecma_CopyEcmaStringCharsToBuffer(ecma_ArrayFirstChunk_t *pFirstChunk, /**< first uint8_t *destPointer = pBuffer + sizeof (ecma_Length_t); size_t copyChunkChars = JERRY_MIN(sizeof (pFirstChunk->m_Elements) / sizeof (ecma_Char_t), charsLeft); - libc_memcpy( destPointer, pFirstChunk->m_Elements, copyChunkChars * sizeof (ecma_Char_t)); + __memcpy( destPointer, pFirstChunk->m_Elements, copyChunkChars * sizeof (ecma_Char_t)); destPointer += copyChunkChars * sizeof (ecma_Char_t); charsLeft -= copyChunkChars; @@ -286,7 +286,7 @@ ecma_CopyEcmaStringCharsToBuffer(ecma_ArrayFirstChunk_t *pFirstChunk, /**< first copyChunkChars = JERRY_MIN(sizeof (pNonFirstChunk->m_Elements) / sizeof (ecma_Char_t), charsLeft); - libc_memcpy( destPointer, pNonFirstChunk->m_Elements, copyChunkChars * sizeof (ecma_Char_t)); + __memcpy( destPointer, pNonFirstChunk->m_Elements, copyChunkChars * sizeof (ecma_Char_t)); destPointer += copyChunkChars * sizeof (ecma_Char_t); charsLeft -= copyChunkChars; @@ -307,7 +307,7 @@ ecma_DuplicateEcmaString( ecma_ArrayFirstChunk_t *pFirstChunk) /**< first chunk JERRY_ASSERT( pFirstChunk != NULL ); ecma_ArrayFirstChunk_t *pFirstChunkCopy = ecma_AllocArrayFirstChunk(); - libc_memcpy( pFirstChunkCopy, pFirstChunk, sizeof (ecma_ArrayFirstChunk_t)); + __memcpy( pFirstChunkCopy, pFirstChunk, sizeof (ecma_ArrayFirstChunk_t)); ecma_ArrayNonFirstChunk_t *pNonFirstChunk, *pNonFirstChunkCopy; pNonFirstChunk = ecma_GetPointer( pFirstChunk->m_Header.m_pNextChunk); @@ -319,7 +319,7 @@ ecma_DuplicateEcmaString( ecma_ArrayFirstChunk_t *pFirstChunk) /**< first chunk ecma_SetPointer( *pNextPointer, pNonFirstChunkCopy); pNextPointer = &pNonFirstChunkCopy->m_pNextChunk; - libc_memcpy( pNonFirstChunkCopy, pNonFirstChunk, sizeof (ecma_ArrayNonFirstChunk_t)); + __memcpy( pNonFirstChunkCopy, pNonFirstChunk, sizeof (ecma_ArrayNonFirstChunk_t)); pNonFirstChunk = ecma_GetPointer( pNonFirstChunk->m_pNextChunk); } diff --git a/src/libjsparser/allocator.h b/src/libjsparser/allocator.h new file mode 100644 index 000000000..b8bdac751 --- /dev/null +++ b/src/libjsparser/allocator.h @@ -0,0 +1,53 @@ +/* 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 diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index c4029e21f..2e9faf9a1 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -13,96 +13,90 @@ * limitations under the License. */ -#include -#include -#include - #include "error.h" #include "lexer.h" +#include "mappings.h" static token saved_token; +static token empty_token = { .type = TOK_EMPTY, .data.none = NULL }; -#ifdef DEBUG +typedef struct +{ + const char *str; + token tok; +} +string_and_token; + +static string_and_token keyword_tokens[] = +{ + { .str = "break", .tok = { .type = TOK_KEYWORD, .data.kw = KW_BREAK } }, + { .str = "case", .tok = { .type = TOK_KEYWORD, .data.kw = KW_CASE } }, + { .str = "catch", .tok = { .type = TOK_KEYWORD, .data.kw = KW_CATCH } }, + { .str = "class", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .str = "const", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .str = "continue", .tok = { .type = TOK_KEYWORD, .data.kw = KW_CONTINUE } }, + { .str = "debugger", .tok = { .type = TOK_KEYWORD, .data.kw = KW_DEBUGGER } }, + { .str = "default", .tok = { .type = TOK_KEYWORD, .data.kw = KW_DEFAULT } }, + { .str = "delete", .tok = { .type = TOK_KEYWORD, .data.kw = KW_DELETE } }, + { .str = "do", .tok = { .type = TOK_KEYWORD, .data.kw = KW_DO } }, + { .str = "else", .tok = { .type = TOK_KEYWORD, .data.kw = KW_ELSE } }, + { .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 = "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 } }, + { .str = "if", .tok = { .type = TOK_KEYWORD, .data.kw = KW_IF } }, + { .str = "instanceof", .tok = { .type = TOK_KEYWORD, .data.kw = KW_INSTANCEOF } }, + { .str = "interface", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .str = "in", .tok = { .type = TOK_KEYWORD, .data.kw = KW_IN } }, + { .str = "import", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .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 = "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 } }, + { .str = "public", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .str = "return", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RETURN } }, + { .str = "static", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .str = "super", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }, + { .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 = "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 } }, + { .str = "void", .tok = { .type = TOK_KEYWORD, .data.kw = KW_VOID } }, + { .str = "while", .tok = { .type = TOK_KEYWORD, .data.kw = KW_WHILE } }, + { .str = "with", .tok = { .type = TOK_KEYWORD, .data.kw = KW_WITH } }, + { .str = "yield", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } } +}; + +#define MAX_NAMES 100 + +static string_and_token seen_names[MAX_NAMES]; +static size_t seen_names_num; + +static inline bool +is_empty (token tok) +{ + return tok.type == TOK_EMPTY; +} + +#ifdef JERRY_NDEBUG FILE *lexer_debug_log; #endif -/* If TOKEN represents a keyword, return decoded keyword, - if TOKEN represents a Future Reserved Word, return KW_RESERVED, - otherwise return KW_NONE. */ -static keyword -decode_keyword (const char *tok) -{ - assert (tok); - - if (!strcmp ("break", tok)) - return KW_BREAK; - else if (!strcmp ("case", tok)) - return KW_CASE; - else if (!strcmp ("catch", tok)) - return KW_CATCH; - else if (!strcmp ("continue", tok)) - return KW_CONTINUE; - else if (!strcmp ("debugger", tok)) - return KW_DEBUGGER; - else if (!strcmp ("default", tok)) - return KW_DEFAULT; - else if (!strcmp ("delete", tok)) - return KW_DELETE; - else if (!strcmp ("do", tok)) - return KW_DO; - else if (!strcmp ("else", tok)) - return KW_ELSE; - else if (!strcmp ("finally", tok)) - return KW_FINALLY; - else if (!strcmp ("for", tok)) - return KW_FOR; - else if (!strcmp ("function", tok)) - return KW_FUNCTION; - else if (!strcmp ("if", tok)) - return KW_IF; - else if (!strcmp ("in", tok)) - return KW_IN; - else if (!strcmp ("instanceof", tok)) - return KW_INSTANCEOF; - else if (!strcmp ("new", tok)) - return KW_NEW; - else if (!strcmp ("return", tok)) - return KW_RETURN; - else if (!strcmp ("switch", tok)) - return KW_SWITCH; - else if (!strcmp ("this", tok)) - return KW_THIS; - else if (!strcmp ("throw", tok)) - return KW_THROW; - else if (!strcmp ("try", tok)) - return KW_TRY; - else if (!strcmp ("typeof", tok)) - return KW_TYPEOF; - else if (!strcmp ("var", tok)) - return KW_VAR; - else if (!strcmp ("void", tok)) - return KW_VOID; - else if (!strcmp ("while", tok)) - return KW_WHILE; - else if (!strcmp ("with", tok)) - return KW_WITH; - else if (!strcmp ("class", tok) || !strcmp ("const", tok) - || !strcmp ("enum", tok) || !strcmp ("export", tok) - || !strcmp ("extends", tok) || !strcmp ("import", tok) - || !strcmp ("super", tok) || !strcmp ("implements", tok) - || !strcmp ("interface", tok) || !strcmp ("let", tok) - || !strcmp ("package", tok) || !strcmp ("private", tok) - || !strcmp ("protected", tok) || !strcmp ("public", tok) - || !strcmp ("static", tok) || !strcmp ("yield", tok)) - return KW_RESERVED; - else - return KW_NONE; -} +#ifdef JERRY_NDEBUG static FILE *file; +static char *buffer_start; /* Represents the contents of a file. */ static char *buffer = NULL; -static char *buffer_start; static char *token_start; #define BUFFER_SIZE 1024 @@ -113,83 +107,133 @@ get_char (int i) int error; const int tail_size = BUFFER_SIZE - (buffer - buffer_start); - assert (file); + JERRY_ASSERT (file); if (buffer == NULL) - { - buffer = (char *) malloc (BUFFER_SIZE); - error = fread (buffer, 1, BUFFER_SIZE, file); - if (error < 0) - fatal (ERR_IO); - if (error == 0) - return '\0'; - if (error < BUFFER_SIZE) - memset (buffer + error, '\0', BUFFER_SIZE - error); - buffer_start = buffer; - } + { + buffer = (char *) malloc (BUFFER_SIZE); + error = fread (buffer, 1, BUFFER_SIZE, file); + if (error < 0) + fatal (ERR_IO); + if (error == 0) + return '\0'; + if (error < BUFFER_SIZE) + memset (buffer + error, '\0', BUFFER_SIZE - error); + buffer_start = buffer; + } if (tail_size <= i) - { + { /* We are almost at the end of the buffer. */ - if (token_start) - { - const int token_size = buffer - token_start; - /* Whole buffer contains single token. */ - if (token_start == buffer_start) - fatal (ERR_BUFFER_SIZE); - /* Move parsed token and tail of buffer to head. */ - memmove (buffer_start, token_start, tail_size + token_size); - /* Adjust pointers. */ - token_start = buffer_start; - buffer = buffer_start + token_size; - /* Read more characters form input file. */ - error = fread (buffer + tail_size, 1, BUFFER_SIZE - tail_size - token_size, file); - if (error < 0) - fatal (ERR_IO); - if (error == 0) - return '\0'; - if (error < BUFFER_SIZE - tail_size - token_size) - memset (buffer + tail_size + error, '\0', - BUFFER_SIZE - tail_size - token_size - error); + if (token_start) + { + const int token_size = buffer - token_start; + /* Whole buffer contains single token. */ + if (token_start == buffer_start) + fatal (ERR_BUFFER_SIZE); + /* Move parsed token and tail of buffer to head. */ + memmove (buffer_start, token_start, tail_size + token_size); + /* Adjust pointers. */ + token_start = buffer_start; + buffer = buffer_start + token_size; + /* Read more characters form input file. */ + error = fread (buffer + tail_size, 1, BUFFER_SIZE - tail_size - token_size, file); + if (error < 0) + fatal (ERR_IO); + if (error == 0) + return '\0'; + if (error < BUFFER_SIZE - tail_size - token_size) + memset (buffer + tail_size + error, '\0', + BUFFER_SIZE - tail_size - token_size - error); + } + else + { + memmove (buffer_start, buffer, tail_size); + buffer = buffer_start; + error = fread (buffer + tail_size, 1, BUFFER_SIZE - tail_size, file); + if (error < 0) + fatal (ERR_IO); + if (error == 0) + return '\0'; + if (error < BUFFER_SIZE - tail_size) + memset (buffer + tail_size + error, '\0', BUFFER_SIZE - tail_size - error); + } } - else - { - memmove (buffer_start, buffer, tail_size); - buffer = buffer_start; - error = fread (buffer + tail_size, 1, BUFFER_SIZE - tail_size, file); - if (error < 0) - fatal (ERR_IO); - if (error == 0) - return '\0'; - if (error < BUFFER_SIZE - tail_size) - memset (buffer + tail_size + error, '\0', BUFFER_SIZE - tail_size - error); - } - } return *(buffer + i); } #define LA(I) (get_char (I)) +#else + +/* Represents the contents of a file. */ +static const char *buffer = NULL; +static const char *token_start; + +#define LA(I) (*(buffer + I)) + +#endif // JERRY_NDEBUG + +/* If TOKEN represents a keyword, return decoded keyword, + if TOKEN represents a Future Reserved Word, return KW_RESERVED, + otherwise return KW_NONE. */ +static token +decode_keyword () +{ + size_t size = sizeof (keyword_tokens) / sizeof (string_and_token); + size_t i; + + for (i = 0; i < size; i++) + { + if (!strncmp (keyword_tokens[i].str, token_start, strlen (keyword_tokens[i].str))) + return keyword_tokens[i].tok; + } + + return empty_token; +} + +static token +convert_seen_name_to_token () +{ + size_t i; + + for (i = 0; i < seen_names_num; i++) + { + if (!strncmp (seen_names[i].str, token_start, strlen (seen_names[i].str))) + return seen_names[i].tok; + } + + return empty_token; +} + +static void +add_to_seen_tokens (string_and_token snt) +{ + JERRY_ASSERT (seen_names_num < MAX_NAMES); + + seen_names[seen_names_num++] = snt; +} + static inline void new_token () { - assert (buffer); + JERRY_ASSERT (buffer); token_start = buffer; } static inline void consume_char () { - assert (buffer); + JERRY_ASSERT (buffer); buffer++; } static inline const char * current_token () { - assert (buffer); - assert (token_start); + JERRY_ASSERT (buffer); + JERRY_ASSERT (token_start); int length = buffer - token_start; char *res = (char *) malloc (length + 1); strncpy (res, token_start, length); @@ -237,82 +281,49 @@ static token parse_name () { char c = LA (0); - bool every_char_islower = isalpha (c) && islower (c); - const char *tok = NULL; + bool every_char_islower = islower (c); + const char *string = NULL; + token known_token = empty_token; - assert (isalpha (c) || c == '$' || c == '_'); + JERRY_ASSERT (isalpha (c) || c == '$' || c == '_'); new_token (); consume_char (); while (true) - { - c = LA (0); - if (c == '\0') - c = c; - if (!isalpha (c) && !isdigit (c) && c != '$' && c != '_') - break; - if (every_char_islower && (!isalpha (c) || !islower (c))) - every_char_islower = false; - consume_char (); - } + { + c = LA (0); + if (c == '\0') + c = c; + if (!isalpha (c) && !isdigit (c) && c != '$' && c != '_') + break; + if (every_char_islower && (!islower (c))) + every_char_islower = false; + consume_char (); + } - tok = current_token (); if (every_char_islower) - { - keyword kw = decode_keyword (tok); - if (kw != KW_NONE) { - free ((char *) tok); - - return (token) - { - .type = TOK_KEYWORD, .data.kw = kw - }; + known_token = decode_keyword (); + if (!is_empty (known_token)) + { + token_start = NULL; + return known_token; + } } - if (!strcmp ("null", tok)) + known_token = convert_seen_name_to_token (); + if (!is_empty (known_token)) { - free ((char *) tok); - - return (token) - { - .type = TOK_NULL, .data.none = NULL - }; + token_start = NULL; + return known_token; } - if (!strcmp ("true", tok)) - { - free ((char *) tok); + string = current_token (); + known_token = (token) { .type = TOK_NAME, .data.name = string }; + + add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token }); - return (token) - { - .type = TOK_BOOL, .data.is_true = true - }; - } - - if (!strcmp ("false", tok)) - { - free ((char *) tok); - - return (token) - { - .type = TOK_BOOL, .data.is_true = false - }; - } - } - - return (token) - { - .type = TOK_NAME, .data.name = tok - }; -} - -static bool -is_hex_digit (char c) -{ - return isdigit (c) || c == 'a' || c == 'A' || c == 'b' || c == 'B' - || c == 'c' || c == 'C' || c == 'd' || c == 'D' - || c == 'e' || c == 'E' || c == 'f' || c == 'F'; + return known_token; } static int @@ -320,29 +331,29 @@ hex_to_int (char hex) { switch (hex) { - case '0': return 0x0; - case '1': return 0x1; - case '2': return 0x2; - case '3': return 0x3; - case '4': return 0x4; - case '5': return 0x5; - case '6': return 0x6; - case '7': return 0x7; - case '8': return 0x8; - case '9': return 0x9; - case 'a': - case 'A': return 0xA; - case 'b': - case 'B': return 0xB; - case 'c': - case 'C': return 0xC; - case 'd': - case 'D': return 0xD; - case 'e': - case 'E': return 0xE; - case 'f': - case 'F': return 0xF; - default: unreachable (); + case '0': return 0x0; + case '1': return 0x1; + case '2': return 0x2; + case '3': return 0x3; + case '4': return 0x4; + case '5': return 0x5; + case '6': return 0x6; + case '7': return 0x7; + case '8': return 0x8; + case '9': return 0x9; + case 'a': + case 'A': return 0xA; + case 'b': + case 'B': return 0xB; + case 'c': + case 'C': return 0xC; + case 'd': + case 'D': return 0xD; + case 'e': + case 'E': return 0xE; + case 'f': + case 'F': return 0xF; + default: JERRY_UNREACHABLE (); } } @@ -355,54 +366,48 @@ parse_number () bool is_hex = false; bool is_fp = false; bool is_exp = false; - const char *tok = NULL; int tok_length = 0; int res = 0; - assert (isdigit (c) || c == '.'); + JERRY_ASSERT (isdigit (c) || c == '.'); if (c == '0') if (LA (1) == 'x' || LA (1) == 'X') is_hex = true; if (c == '.') - { - assert (!isalpha (LA (1))); - is_fp = true; - } - - if (is_hex) - { - // Eat up '0x' - consume_char (); - consume_char (); - new_token (); - while (true) { - c = LA (0); - if (!is_hex_digit (c)) - break; - consume_char (); + JERRY_ASSERT (!isalpha (LA (1))); + is_fp = true; } - if (isalpha (c) || c == '_' || c == '$') - fatal (ERR_INT_LITERAL); - - tok_length = buffer - token_start; - tok = current_token (); - // OK, I know that integer overflow can occur here - for (int i = 0; i < tok_length; i++) - res = (res << 4) + hex_to_int (tok[i]); - - free ((char *) tok); - - return (token) + if (is_hex) { - .type = TOK_INT, .data.num = res - }; - } + // Eat up '0x' + consume_char (); + consume_char (); + new_token (); + while (true) + { + c = LA (0); + if (!isxdigit (c)) + break; + consume_char (); + } - assert (!is_hex && !is_exp); + if (isalpha (c) || c == '_' || c == '$') + fatal (ERR_INT_LITERAL); + + tok_length = buffer - token_start; + // OK, I know that integer overflow can occur here + for (int i = 0; i < tok_length; i++) + res = (res << 4) + hex_to_int (token_start[i]); + + token_start = NULL; + return (token) { .type = TOK_INT, .data.num = res }; + } + + JERRY_ASSERT (!is_hex && !is_exp); new_token (); @@ -411,66 +416,56 @@ parse_number () consume_char (); while (true) - { - c = LA (0); - if (is_fp && c == '.') - fatal (ERR_INT_LITERAL); - if (is_exp && (c == 'e' || c == 'E')) - fatal (ERR_INT_LITERAL); - - if (c == '.') { - if (isalpha (LA (1)) || LA (1) == '_' || LA (1) == '$') + c = LA (0); + if (is_fp && c == '.') fatal (ERR_INT_LITERAL); - is_fp = true; - consume_char (); - continue; - } - - if (c == 'e' || c == 'E') - { - if (LA (1) == '-' || LA (1) == '+') - consume_char (); - if (!isdigit (LA (1))) + if (is_exp && (c == 'e' || c == 'E')) fatal (ERR_INT_LITERAL); - is_exp = true; + + if (c == '.') + { + if (isalpha (LA (1)) || LA (1) == '_' || LA (1) == '$') + fatal (ERR_INT_LITERAL); + is_fp = true; + consume_char (); + continue; + } + + if (c == 'e' || c == 'E') + { + if (LA (1) == '-' || LA (1) == '+') + consume_char (); + if (!isdigit (LA (1))) + fatal (ERR_INT_LITERAL); + is_exp = true; + consume_char (); + continue; + } + + if (isalpha (c) || c == '_' || c == '$') + fatal (ERR_INT_LITERAL); + + if (!isdigit (c)) + break; + consume_char (); - continue; } - if (isalpha (c) || c == '_' || c == '$') - fatal (ERR_INT_LITERAL); - - if (!isdigit (c)) - break; - - consume_char (); - } - if (is_fp || is_exp) - { - tok = current_token (); - float res = strtof (tok, NULL); - free ((char *) tok); - - return (token) { - .type = TOK_FLOAT, .data.fp_num = res - }; - } + float res = strtof (token_start, NULL); + token_start = NULL; + return (token) { .type = TOK_FLOAT, .data.fp_num = res }; + } tok_length = buffer - token_start; - tok = current_token (); - for (int i = 0; i < tok_length; i++) - res = res * 10 + hex_to_int (tok[i]); + res = res * 10 + hex_to_int (token_start[i]); - free ((char *) tok); + token_start = NULL; - return (token) - { - .type = TOK_INT, .data.num = res - }; + return (token) { .type = TOK_INT, .data.num = res }; } static char @@ -478,16 +473,16 @@ escape_char (char c) { switch (c) { - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'v': return '\v'; - case '\'': - case '"': - case '\\': - default: return c; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + case '\'': + case '"': + case '\\': + default: return c; } } @@ -499,8 +494,9 @@ parse_string () char *tok = NULL; char *index = NULL; int length; + token res = empty_token; - assert (c == '\'' || c == '"'); + JERRY_ASSERT (c == '\'' || c == '"'); is_double_quoted = (c == '"'); @@ -509,55 +505,55 @@ parse_string () new_token (); while (true) - { - c = LA (0); - if (c == '\0') - fatal (ERR_UNCLOSED); - if (c == '\n') - fatal (ERR_STRING); - if (c == '\\') { - /* Only single escape character is allowed. */ - if (LA (1) == 'x' || LA (1) == 'u' || isdigit (LA (1))) + c = LA (0); + if (c == '\0') + fatal (ERR_UNCLOSED); + if (c == '\n') fatal (ERR_STRING); - if ((LA (1) == '\'' && !is_double_quoted) - || (LA (1) == '"' && is_double_quoted) - || LA (1) == '\n') - { - consume_char (); - consume_char (); - continue; - } - } - else if ((c == '\'' && !is_double_quoted) - || (c == '"' && is_double_quoted)) - break; + if (c == '\\') + { + /* Only single escape character is allowed. */ + if (LA (1) == 'x' || LA (1) == 'u' || isdigit (LA (1))) + fatal (ERR_STRING); + if ((LA (1) == '\'' && !is_double_quoted) + || (LA (1) == '"' && is_double_quoted) + || LA (1) == '\n') + { + consume_char (); + consume_char (); + continue; + } + } + else if ((c == '\'' && !is_double_quoted) + || (c == '"' && is_double_quoted)) + break; - consume_char (); - } + consume_char (); + } length = buffer - token_start; tok = (char *) malloc (length); index = tok; - for (char *i = token_start; i < buffer; i++) - { - if (*i == '\\') + for (const char *i = token_start; i < buffer; i++) { - if (*(i + 1) == '\n') - { - i++; - continue; - } - *index = escape_char (*(i + 1)); - index++; - i++; - continue; - } + if (*i == '\\') + { + if (*(i+1) == '\n') + { + i++; + continue; + } + *index = escape_char (*(i+1)); + index++; + i++; + continue; + } - *index = *i; - index++; - } + *index = *i; + index++; + } memset (index, '\0', length - (index - tok)); @@ -565,10 +561,11 @@ parse_string () // Eat up '"' consume_char (); - return (token) - { - .type = TOK_STRING, .data.str = tok - }; + res = (token) { .type = TOK_STRING, .data.str = tok }; + + add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res }); + + return res; } static void @@ -577,21 +574,30 @@ grobble_whitespaces () char c = LA (0); while ((isspace (c) && c != '\n') || c == '\0') - { - consume_char (); - c = LA (0); - } + { + consume_char (); + c = LA (0); + } } +#ifdef JERRY_NDEBUG void lexer_set_file (FILE *ex_file) { - assert (ex_file); + JERRY_ASSERT (ex_file); file = ex_file; -#ifdef DEBUG lexer_debug_log = fopen ("lexer.log", "w"); -#endif + saved_token = empty_token; } +#else +void +lexer_set_source (const char * source) +{ + buffer = source; + saved_token = empty_token; +} + +#endif static bool replace_comment_by_newline () @@ -600,8 +606,8 @@ replace_comment_by_newline () bool multiline; bool was_newlines = false; - assert (LA (0) == '/'); - assert (LA (1) == '/' || LA (1) == '*'); + JERRY_ASSERT (LA (0) == '/'); + JERRY_ASSERT (LA (1) == '/' || LA (1) == '*'); multiline = (LA (1) == '*'); @@ -609,29 +615,29 @@ replace_comment_by_newline () consume_char (); while (true) - { - c = LA (0); - if (!multiline && (c == '\n' || c == '\0')) - return false; - if (multiline && c == '*' && LA (1) == '/') { - consume_char (); - consume_char (); - if (was_newlines) - return true; - else + c = LA (0); + if (!multiline && (c == '\n' || c == '\0')) return false; + if (multiline && c == '*' && LA (1) == '/') + { + consume_char (); + consume_char (); + if (was_newlines) + return true; + else + return false; + } + if (multiline && c == '\n') + was_newlines = true; + if (multiline && c == '\0') + fatal (ERR_UNCLOSED); + consume_char (); } - if (multiline && c == '\n') - was_newlines = true; - if (multiline && c == '\0') - fatal (ERR_UNCLOSED); - consume_char (); - } } token -#ifdef DEBUG +#ifdef JERRY_NDEBUG lexer_next_token_private () #else lexer_next_token () @@ -639,14 +645,14 @@ lexer_next_token () { char c = LA (0); - if (saved_token.type != TOK_EOF) - { - token res = saved_token; - saved_token.type = TOK_EOF; - return res; - } + if (!is_empty (saved_token)) + { + token res = saved_token; + saved_token = empty_token; + return res; + } - assert (token_start == NULL); + JERRY_ASSERT (token_start == NULL); if (isalpha (c) || c == '$' || c == '_') return parse_name (); @@ -655,113 +661,118 @@ lexer_next_token () return parse_number (); if (c == '\n') - { - consume_char (); - - return (token) { - .type = TOK_NEWLINE, .data.none = NULL - }; - } + consume_char (); + return (token) { .type = TOK_NEWLINE, .data.none = NULL }; + } if (c == '\0') - return (token) - { - .type = TOK_EOF, .data.none = NULL - }; + return (token) { .type = TOK_EOF, .data.none = NULL };; if (c == '\'' || c == '"') return parse_string (); if (isspace (c)) - { - grobble_whitespaces (); - return lexer_next_token (); - } + { + grobble_whitespaces (); + return +#ifdef JERRY_NDEBUG + lexer_next_token_private (); +#else + lexer_next_token (); +#endif + } if (c == '/' && LA (1) == '*') - { - if (replace_comment_by_newline ()) - return (token) { - .type = TOK_NEWLINE, .data.none = NULL - }; - else - return lexer_next_token (); - } + if (replace_comment_by_newline ()) + return (token) { .type = TOK_NEWLINE, .data.none = NULL }; + else + return +#ifdef JERRY_NDEBUG + lexer_next_token_private (); +#else + lexer_next_token (); +#endif + } if (c == '/' && LA (1) == '/') - { - replace_comment_by_newline (); - return lexer_next_token (); - } + { + replace_comment_by_newline ();; + return +#ifdef JERRY_NDEBUG + lexer_next_token_private (); +#else + lexer_next_token (); +#endif + } switch (c) { - case '{': RETURN_PUNC (TOK_OPEN_BRACE); - case '}': RETURN_PUNC (TOK_CLOSE_BRACE); - case '(': RETURN_PUNC (TOK_OPEN_PAREN); - case ')': RETURN_PUNC (TOK_CLOSE_PAREN); - case '[': RETURN_PUNC (TOK_OPEN_SQUARE); - case ']': RETURN_PUNC (TOK_CLOSE_SQUARE); - case '.': RETURN_PUNC (TOK_DOT); - case ';': RETURN_PUNC (TOK_SEMICOLON); - case ',': RETURN_PUNC (TOK_COMMA); - case '~': RETURN_PUNC (TOK_COMPL); - case ':': RETURN_PUNC (TOK_COLON); - case '?': RETURN_PUNC (TOK_QUERY); + case '{': RETURN_PUNC (TOK_OPEN_BRACE); + case '}': RETURN_PUNC (TOK_CLOSE_BRACE); + case '(': RETURN_PUNC (TOK_OPEN_PAREN); + case ')': RETURN_PUNC (TOK_CLOSE_PAREN); + case '[': RETURN_PUNC (TOK_OPEN_SQUARE); + case ']': RETURN_PUNC (TOK_CLOSE_SQUARE); + case '.': RETURN_PUNC (TOK_DOT); + case ';': RETURN_PUNC (TOK_SEMICOLON); + case ',': RETURN_PUNC (TOK_COMMA); + case '~': RETURN_PUNC (TOK_COMPL); + case ':': RETURN_PUNC (TOK_COLON); + case '?': RETURN_PUNC (TOK_QUERY); - case '*': IF_LA_IS ('=', TOK_MULT_EQ, TOK_MULT); - case '/': IF_LA_IS ('=', TOK_DIV_EQ, TOK_DIV); - case '^': IF_LA_IS ('=', TOK_XOR_EQ, TOK_XOR); - case '%': IF_LA_IS ('=', TOK_MOD_EQ, TOK_MOD); + case '*': IF_LA_IS ('=', TOK_MULT_EQ, TOK_MULT); + case '/': IF_LA_IS ('=', TOK_DIV_EQ, TOK_DIV); + case '^': IF_LA_IS ('=', TOK_XOR_EQ, TOK_XOR); + case '%': IF_LA_IS ('=', TOK_MOD_EQ, TOK_MOD); - case '+': IF_LA_IS_OR ('+', TOK_DOUBLE_PLUS, '=', TOK_PLUS_EQ, TOK_PLUS); - case '-': IF_LA_IS_OR ('-', TOK_DOUBLE_MINUS, '=', TOK_MINUS_EQ, TOK_MINUS); - case '&': IF_LA_IS_OR ('&', TOK_DOUBLE_AND, '=', TOK_AND_EQ, TOK_AND); - case '|': IF_LA_IS_OR ('|', TOK_DOUBLE_OR, '=', TOK_OR_EQ, TOK_OR); + case '+': IF_LA_IS_OR ('+', TOK_DOUBLE_PLUS, '=', TOK_PLUS_EQ, TOK_PLUS); + case '-': IF_LA_IS_OR ('-', TOK_DOUBLE_MINUS, '=', TOK_MINUS_EQ, TOK_MINUS); + case '&': IF_LA_IS_OR ('&', TOK_DOUBLE_AND, '=', TOK_AND_EQ, TOK_AND); + case '|': IF_LA_IS_OR ('|', TOK_DOUBLE_OR, '=', TOK_OR_EQ, TOK_OR); - case '<': - switch (LA (1)) - { - case '<': IF_LA_N_IS ('=', TOK_LSHIFT_EQ, TOK_LSHIFT, 2); - case '=': RETURN_PUNC_EX (TOK_LESS_EQ, 2); - default: RETURN_PUNC (TOK_LESS); - } - - case '>': - switch (LA (1)) - { - case '>': - switch (LA (2)) + case '<': + switch (LA (1)) { - case '>': IF_LA_N_IS ('=', TOK_RSHIFT_EX_EQ, TOK_RSHIFT_EX, 3); - case '=': RETURN_PUNC_EX (TOK_RSHIFT_EQ, 3); - default: RETURN_PUNC_EX (TOK_RSHIFT, 2); + case '<': IF_LA_N_IS ('=', TOK_LSHIFT_EQ, TOK_LSHIFT, 2); + case '=': RETURN_PUNC_EX (TOK_LESS_EQ, 2); + default: RETURN_PUNC (TOK_LESS); } - case '=': RETURN_PUNC_EX (TOK_GREATER_EQ, 2); - default: RETURN_PUNC (TOK_GREATER); - } - case '=': - if (LA (1) == '=') - IF_LA_N_IS ('=', TOK_TRIPLE_EQ, TOK_DOUBLE_EQ, 2); - else - RETURN_PUNC (TOK_EQ); + case '>': + switch (LA (1)) + { + case '>': + switch (LA (2)) + { + case '>': IF_LA_N_IS ('=', TOK_RSHIFT_EX_EQ, TOK_RSHIFT_EX, 3); + case '=': RETURN_PUNC_EX (TOK_RSHIFT_EQ, 3); + default: RETURN_PUNC_EX (TOK_RSHIFT, 2); + } + case '=': RETURN_PUNC_EX (TOK_GREATER_EQ, 2); + default: RETURN_PUNC (TOK_GREATER); + } - case '!': - if (LA (1) == '=') - IF_LA_N_IS ('=', TOK_NOT_DOUBLE_EQ, TOK_NOT_EQ, 2); - else - RETURN_PUNC (TOK_NOT); + case '=': + if (LA (1) == '=') + IF_LA_N_IS ('=', TOK_TRIPLE_EQ, TOK_DOUBLE_EQ, 2); + else + RETURN_PUNC (TOK_EQ); - default: - unreachable (); + case '!': + if (LA (1) == '=') + IF_LA_N_IS ('=', TOK_NOT_DOUBLE_EQ, TOK_NOT_EQ, 2); + else + RETURN_PUNC (TOK_NOT); + + default: + JERRY_UNREACHABLE (); } fatal (ERR_NON_CHAR); } -#ifdef DEBUG +#ifdef JERRY_NDEBUG static int i = 0; token @@ -770,12 +781,12 @@ lexer_next_token () token tok = lexer_next_token_private (); if (tok.type == TOK_NEWLINE) return tok; - if (tok.type == TOK_CLOSE_BRACE) - { - if (i == 300) - fprintf (lexer_debug_log, "lexer_next_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none); - i++; - } + // if (tok.type == TOK_CLOSE_BRACE) + { + // if (i == 300) + fprintf (lexer_debug_log, "lexer_next_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none); + i++; + } return tok; } #endif @@ -783,15 +794,15 @@ lexer_next_token () void lexer_save_token (token tok) { -#ifdef DEBUG - if (tok.type == TOK_CLOSE_BRACE) + #ifdef JERRY_NDEBUG + // 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 + #endif saved_token = tok; } void lexer_dump_buffer_state () { - //printf ("%s\n", buffer); + printf ("%s\n", buffer); } \ No newline at end of file diff --git a/src/libjsparser/lexer.h b/src/libjsparser/lexer.h index cbc802a20..f6f786028 100644 --- a/src/libjsparser/lexer.h +++ b/src/libjsparser/lexer.h @@ -16,8 +16,7 @@ #ifndef LEXER_H #define LEXER_H -#include -#include +#include "mappings.h" /* Keywords. */ typedef enum @@ -128,7 +127,8 @@ typedef enum TOK_XOR_EQ, // ^= TOK_DIV, // / - TOK_DIV_EQ // /= + TOK_DIV_EQ, // /= + TOK_EMPTY } token_type; @@ -151,7 +151,11 @@ typedef struct } token; +#ifdef JERRY_NDEBUG void lexer_set_file (FILE *); +#else +void lexer_set_source (const char *); +#endif token lexer_next_token (); void lexer_save_token (token); diff --git a/src/libjsparser/mappings.h b/src/libjsparser/mappings.h new file mode 100644 index 000000000..4a57a9c2d --- /dev/null +++ b/src/libjsparser/mappings.h @@ -0,0 +1,139 @@ +/* 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 MAPPINGS_H +#define MAPPINGS_H + +#ifndef JERRY_NDEBUG +#include "../jerry-libc.h" +#include "allocator.h" +#include + +static inline void * +memset (void *s, int n1, size_t n2) +{ + return __memset (s, n1, n2); +} + +static inline int +memcmp (const void *s1, const void *s2, size_t n) +{ + return __memcmp (s1, s2, n); +} + +static inline void * +memcpy (void *s1, const void *s2, size_t n) +{ + return __memcpy (s1, s2, n); +} + +static inline int +printf (const char *s, ...) +{ + va_list args; + va_start (args, s); + int ret = __printf (s, args); + va_end (args); + return ret; +} + +static inline int +putchar (int c) +{ + return __putchar (c); +} + +static inline void +exit (int status) +{ + return __exit (status); +} + +static inline int +strcmp (const char *s1, const char *s2) +{ + return __strcmp (s1, s2); +} + +static inline int +strncmp (const char *s1, const char *s2, size_t n) +{ + return __strncmp (s1, s2, n); +} + +static inline char * +strncpy (char *s1, const char *s2, size_t n) +{ + return __strncpy (s1, s2, n); +} + +static inline float +strtof (const char *s1, char **s2) +{ + return __strtof (s1, s2); +} + +static inline size_t +strlen (const char *s) +{ + return __strlen (s); +} + +static inline int +isspace (int s) +{ + return __isspace (s); +} + +static inline int +isupper (int s) +{ + return __isupper (s); +} + +static inline int +islower (int s) +{ + return __islower (s); +} + +static inline int +isalpha (int s) +{ + return __isalpha (s); +} + +static inline int +isdigit (int s) +{ + return __isdigit (s); +} + +static inline int +isxdigit (int s) +{ + return __isxdigit (s); +} + +#else +#undef NULL +#include "../globals.h" +#include +#include +#include +#include +#endif + +#endif // MAPPINGS_H diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 50f1af011..ef23c323e 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -13,23 +13,18 @@ * limitations under the License. */ -#include #include "parser.h" #include "error.h" #include "lexer.h" static token tok; -#ifdef DEBUG +#ifdef JERRY_NDEBUG FILE *debug_file; #endif -static expression *parse_expression (bool); -static assignment_expression *parse_assigment_expression (bool); - -#define ALLOCATE(T) (T*) malloc (sizeof (T)) - -#define RETURN_NULL_IF_NULL(T) do { if (T == NULL) { free (res); return NULL; } } while (0) +static expression parse_expression (); +static assignment_expression parse_assigment_expression (); typedef enum { @@ -56,22 +51,24 @@ typedef struct scope { scope_type type; bool was_stmt; - - struct scope *prev; } scope; -static scope *current_scope; +#define MAX_SCOPES 10 + +static scope current_scopes[MAX_SCOPES]; + +static int scope_index; static inline void scope_must_be (int scopes) { - scope *sc = current_scope; - while (sc) + int i; + + for (i = 0; i < scope_index; i++) { - if (scopes & sc->type) + if (scopes & current_scopes[i].type) return; - sc = sc->prev; } fatal (ERR_PARSER); } @@ -79,7 +76,7 @@ scope_must_be (int scopes) static inline void current_scope_must_be (int scopes) { - if (scopes & current_scope->type) + if (scopes & current_scopes[scope_index - 1].type) return; fatal (ERR_PARSER); } @@ -87,32 +84,26 @@ current_scope_must_be (int scopes) static inline void current_scope_must_be_global () { - if (current_scope->prev) + if (scope_index != 0) fatal (ERR_PARSER); } static void push_scope (int type) { -#ifdef DEBUG +#ifdef JERRY_NDEBUG fprintf (debug_file, "push_scope: 0x%x\n", type); #endif - scope *sc = ALLOCATE (scope); - sc->type = type; - sc->prev = current_scope; - sc->was_stmt = false; - current_scope = sc; + current_scopes[scope_index++] = (scope) { .type = type, .was_stmt = false }; } static void pop_scope () { -#ifdef DEBUG - fprintf (debug_file, "pop_scope: 0x%x\n", current_scope->type); +#ifdef JERRY_NDEBUG + fprintf (debug_file, "pop_scope: 0x%x\n", current_scopes[scope_index - 1].type); #endif - scope *sc = current_scope->prev; - free (current_scope); - current_scope = sc; + scope_index--; } static inline void @@ -120,8 +111,10 @@ assert_keyword (keyword kw) { if (tok.type != TOK_KEYWORD || tok.data.kw != kw) { +#ifdef JERRY_NDEBUG printf ("assert_keyword: 0x%x\n", kw); - unreachable (); +#endif + JERRY_UNREACHABLE (); } } @@ -136,7 +129,9 @@ current_token_must_be(token_type tt) { if (tok.type != tt) { +#ifdef JERRY_NDEBUG printf ("current_token_must_be: 0x%x\n", tt); +#endif fatal (ERR_PARSER); } } @@ -155,7 +150,9 @@ next_token_must_be (token_type tt) tok = lexer_next_token (); if (tok.type != tt) { +#ifdef JERRY_NDEBUG printf ("next_token_must_be: 0x%x\n", tt); +#endif fatal (ERR_PARSER); } } @@ -176,13 +173,6 @@ token_after_newlines_must_be_keyword (keyword kw) fatal (ERR_PARSER); } -static inline void -fatal_if_null (void * what) -{ - if (!what) - fatal (ERR_PARSER); -} - static inline void insert_semicolon () { @@ -194,26 +184,28 @@ insert_semicolon () /* formal_parameter_list : LT!* Identifier (LT!* ',' LT!* Identifier)* ; */ -static formal_parameter_list * +static formal_parameter_list parse_formal_parameter_list () { - formal_parameter_list *res = ALLOCATE (formal_parameter_list); + int i; + formal_parameter_list res; current_token_must_be (TOK_NAME); - res->name = tok.data.name; - skip_newlines (); - if (tok.type == TOK_COMMA) + for (i = 0; i < MAX_PARAMS; i++) { + res.names[i] = tok.data.name; + skip_newlines (); - res->next = parse_formal_parameter_list (); - } - else - { - lexer_save_token (tok); - res->next = NULL; - } + if (tok.type != TOK_COMMA) + { + lexer_save_token (tok); + if (i != MAX_PARAMS - 1) + res.names[i + 1] = NULL; + break; + } + } return res; } @@ -224,26 +216,26 @@ parse_formal_parameter_list () function_body : '{' LT!* sourceElements LT!* '}' */ -static function_declaration* +static function_declaration parse_function_declaration () { - function_declaration *res = ALLOCATE (function_declaration); + function_declaration res; assert_keyword (KW_FUNCTION); token_after_newlines_must_be (TOK_NAME); - res->name = tok.data.name; + res.name = tok.data.name; token_after_newlines_must_be (TOK_OPEN_PAREN); skip_newlines (); if (tok.type != TOK_CLOSE_PAREN) { - res->params = parse_formal_parameter_list (); + res.params = parse_formal_parameter_list (); next_token_must_be (TOK_CLOSE_PAREN); } else - res->params = NULL; + res.params = empty_formal_parameter_list; return res; } @@ -251,1194 +243,559 @@ parse_function_declaration () /* function_expression : 'function' LT!* Identifier? LT!* '(' formal_parameter_list? LT!* ')' LT!* function_body ; */ -static function_expression * +static function_expression parse_function_expression () { - function_expression *res = ALLOCATE (function_expression); + function_expression res; assert_keyword (KW_FUNCTION); skip_newlines (); if (tok.type == TOK_NAME) { - res->name = tok.data.name; + res.name = tok.data.name; skip_newlines (); } else - res->name = NULL; + res.name = NULL; current_token_must_be (TOK_OPEN_PAREN); skip_newlines (); if (tok.type != TOK_CLOSE_PAREN) { - res->params = parse_formal_parameter_list (); + res.params = parse_formal_parameter_list (); next_token_must_be (TOK_CLOSE_PAREN); } else - res->params = NULL; + res.params = empty_formal_parameter_list; push_scope (SCOPE_FUNCTION); return res; } -/* array_literal - : assignment_expression? (LT!* ',' (LT!* assignment_expression)?)* LT!* - ; */ -static array_literal * -parse_array_literal () +static literal +parse_literal () { - array_literal *res = NULL; - assignment_expression *assign_expr = parse_assigment_expression (false); - if (assign_expr != NULL) + literal res; + + switch (tok.type) + { + case TOK_NULL: + res.type = LIT_NULL; + res.data.none = NULL; + return res; + + case TOK_BOOL: + res.type = LIT_BOOL; + res.data.is_true = tok.data.is_true; + return res; + + case TOK_INT: + res.type = LIT_INT; + res.data.num = tok.data.num; + return res; + + case TOK_STRING: + res.type = LIT_STR; + res.data.str = tok.data.str; + return res; + + default: + JERRY_UNREACHABLE (); + } +} + +static operand +parse_operand () +{ + operand res; + + switch (tok.type) + { + case TOK_NULL: + case TOK_BOOL: + case TOK_INT: + case TOK_STRING: + res.is_literal = true; + res.data.lit = parse_literal (); + return res; + + case TOK_NAME: + res.is_literal = false; + res.data.name = tok.data.name; + return res; + + default: + return empty_operand; + } +} + +/* arguments + : operand LT!* ( ',' LT!* operand * LT!* )* + ;*/ +static argument_list +parse_argument_list () +{ + argument_list res; + int i; + + for (i = 0; i < MAX_PARAMS; i++) { - res = ALLOCATE (array_literal); - res->assign_expr = assign_expr; - } - skip_newlines (); - if (tok.type == TOK_COMMA) - { - if (res == NULL) - res = ALLOCATE (array_literal); + res.ops[i] = parse_operand (); + skip_newlines (); - res->next = parse_array_literal (); + if (tok.type != TOK_COMMA) + { + lexer_save_token (tok); + + if (i != MAX_PARAMS - 1) + res.ops[i + 1] = empty_operand; + break; + } + + skip_newlines (); + } + return res; +} + +/* call_expression + : identifier LT!* '(' LT!* arguments * LT!* ')' LT!* + ;*/ +static call_expression +parse_call_expression () +{ + call_expression res; + + current_token_must_be (TOK_NAME); + res.name = tok.data.name; + + token_after_newlines_must_be (TOK_OPEN_PAREN); + + skip_newlines (); + if (tok.type != TOK_CLOSE_PAREN) + { + res.args = parse_argument_list (); + next_token_must_be (TOK_CLOSE_PAREN); } + else + res.args = empty_operand_list; + + skip_newlines (); + if (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE + || tok.type == TOK_DOT) + JERRY_UNREACHABLE (); else lexer_save_token (tok); return res; } +/* array_literal + : [ arguments ] + ; */ +static array_literal +parse_array_literal () +{ + array_literal res; + + current_token_must_be (TOK_OPEN_SQUARE); + + skip_newlines (); + if (tok.type != TOK_CLOSE_SQUARE) + { + res = parse_argument_list (); + next_token_must_be (TOK_CLOSE_SQUARE); + } + else + res = empty_operand_list; + + return res; +} + /* property_name : Identifier | StringLiteral | NumericLiteral ; */ -static property_name * +static inline property_name parse_property_name () { - property_name *res = ALLOCATE (property_name); - switch (tok.type) { case TOK_NAME: - res->type = PN_NAME; - res->data.name = tok.data.name; - return res; - case TOK_STRING: - res->type = PN_STRING; - res->data.str = tok.data.str; - return res; - case TOK_INT: - res->type = PN_NUM; - res->data.num = tok.data.num; - return res; - + return parse_operand (); + default: - unreachable (); + JERRY_UNREACHABLE (); } } /* property_name_and_value - : property_name LT!* ':' LT!* assignment_expression + : property_name LT!* ':' LT!* operand ; */ -static property_name_and_value * -parse_property_name_and_value () +static property +parse_property () { - property_name_and_value *res = ALLOCATE (property_name_and_value); + property res; - res->name = parse_property_name (); - assert (res->name); + res.name = parse_property_name (); token_after_newlines_must_be (TOK_COLON); skip_newlines (); - res->assign_expr = parse_assigment_expression (true); - fatal_if_null (res->assign_expr); + res.value = parse_operand (); return res; } /* object_literal - : LT!* property_name_and_value (LT!* ',' LT!* property_name_and_value)* LT!* + : LT!* property (LT!* ',' LT!* property)* LT!* ; */ -static object_literal * +static object_literal parse_object_literal () { - object_literal *res = ALLOCATE (object_literal); + object_literal res; + int i; - res->nav = parse_property_name_and_value (); - assert (res->nav); - - skip_newlines (); - if (tok.type == TOK_COMMA) - { - skip_newlines (); - res->next = parse_object_literal (); - assert (res->next); - } - else - { - lexer_save_token (tok); - res->next = NULL; - } - return res; -} - -static literal * -parse_literal () -{ - literal *res = ALLOCATE (literal); - - switch (tok.type) - { - case TOK_NULL: - res->type = LIT_NULL; - res->data.data = NULL; - return res; - - case TOK_BOOL: - res->type = LIT_BOOL; - res->data.is_true = tok.data.is_true; - return res; - - case TOK_INT: - res->type = LIT_INT; - res->data.num = tok.data.num; - return res; - - case TOK_STRING: - res->type = LIT_STR; - res->data.str = tok.data.str; - return res; - - default: - unreachable (); - } -} - -/* primary_expression - : 'this' - | Identifier - | literal - | '[' LT!* array_literal LT!* ']' - | '{' LT!* object_literal LT!* '}' - | '(' LT!* expression LT!* ')' - ; */ -static primary_expression * -parse_primary_expression () -{ - primary_expression *res = ALLOCATE (primary_expression); - - if (is_keyword (KW_THIS)) - { - res->type = PE_THIS; - res->data.none = NULL; - return res; - } - else if (tok.type == TOK_NAME) - { - res->type = PE_NAME; - res->data.name = tok.data.name; - return res; - } - else if (tok.type == TOK_NULL || tok.type == TOK_BOOL - || tok.type == TOK_INT || tok.type == TOK_STRING) - { - res->type = PE_LITERAL; - res->data.lit = parse_literal (); - assert (res->data.lit); - return res; - } - else if (tok.type == TOK_OPEN_SQUARE) - { - res->type = PE_ARRAY; - skip_newlines (); - if (tok.type != TOK_CLOSE_SQUARE) - { - res->data.array_lit = parse_array_literal (); - assert (res->data.array_lit); - token_after_newlines_must_be (TOK_CLOSE_SQUARE); - } - else - res->data.array_lit = NULL; - return res; - } - else if (tok.type == TOK_OPEN_BRACE) - { - res->type = PE_OBJECT; - skip_newlines (); - if (tok.type != TOK_CLOSE_BRACE) - { - res->data.object_lit = parse_object_literal (); - assert (res->data.object_lit); - token_after_newlines_must_be (TOK_CLOSE_BRACE); - } - else - res->data.object_lit = NULL; - return res; - } - else if (tok.type == TOK_OPEN_PAREN) - { - res->type = PE_EXPR; - skip_newlines (); - if (tok.type != TOK_CLOSE_PAREN) - { - scope *old_scope; - push_scope (SCOPE_SUBEXPRESSION); - old_scope = current_scope; - - res->data.expr = parse_expression (false); - if (current_scope == old_scope) - { - next_token_must_be (TOK_CLOSE_PAREN); - pop_scope (); - } - assert (res->data.expr); - } - else - res->data.expr = NULL; - - return res; - } - else - { - free (res); - return NULL; - } -} - -/* member_expression_suffix - : index_suffix - | property_reference_suffix - ; - - index_suffix - : '[' LT!* expression LT!* ']' - ; - - property_reference_suffix - : '.' LT!* Identifier - ; */ -static member_expression_suffix * -parse_member_expression_suffix () -{ - member_expression_suffix *res = ALLOCATE (member_expression_suffix); - - if (tok.type == TOK_OPEN_SQUARE) - { - res->type = MES_INDEX; + for (i = 0; i < MAX_PROPERTIES; i++) + { + res.props[i] = parse_property (); skip_newlines (); - res->data.index_expr = parse_expression (true); - fatal_if_null (res->data.index_expr); - token_after_newlines_must_be (TOK_CLOSE_SQUARE); - } - else if (tok.type == TOK_DOT) - { - res->type = MES_PROPERTY; - - skip_newlines (); - if (tok.type != TOK_NAME) - fatal (ERR_PARSER); - res->data.name = tok.data.name; - } - else - unreachable (); - - return res; -} - -/* member_expression_suffix_list - : member_expression_suffix + - ; */ -static member_expression_suffix_list * -parse_member_expression_suffix_list () -{ - member_expression_suffix_list *res = ALLOCATE (member_expression_suffix_list); - - if (tok.type == TOK_OPEN_SQUARE || tok.type == TOK_DOT) - { - res->suffix = parse_member_expression_suffix (); - assert (res->suffix); - } - else - unreachable (); - - skip_newlines (); - if (tok.type == TOK_OPEN_SQUARE || tok.type == TOK_DOT) - { - res->next = parse_member_expression_suffix_list (); - assert (res->next); - } - else - { - lexer_save_token (tok); - res->next = NULL; - } - - return res; -} - -/* member_expression - : (primary_expression | function_expression | 'new' LT!* member_expression (LT!* '(' LT!* arguments? LT!* ')') - (LT!* member_expression_suffix)* - ; - - arguments - : assignment_expression (LT!* ',' LT!* assignment_expression)*)? - ;*/ -static member_expression * -parse_member_expression () -{ - member_expression *res = ALLOCATE (member_expression); - - if (is_keyword (KW_FUNCTION)) - { - res->type = ME_FUNCTION; - res->data.function_expr = parse_function_expression (); - assert (res->data.function_expr); - } - else if (is_keyword (KW_NEW)) - { - member_expression_with_arguments *expr - = ALLOCATE (member_expression_with_arguments); - res->type = ME_ARGS; - - skip_newlines (); - expr->member_expr = parse_member_expression (); - fatal_if_null (expr->member_expr); - - token_after_newlines_must_be (TOK_OPEN_PAREN); - skip_newlines (); - if (tok.type != TOK_CLOSE_PAREN) - { - expr->args = parse_expression (true); - assert (expr->args); - token_after_newlines_must_be (TOK_CLOSE_PAREN); - } - else - expr->args = NULL; - - res->data.args = expr; - } - else - { - res->type = ME_PRIMARY; - res->data.primary_expr = parse_primary_expression (); - RETURN_NULL_IF_NULL (res->data.primary_expr); - } - - skip_newlines (); - if (tok.type == TOK_OPEN_SQUARE || tok.type == TOK_DOT) - { - res->suffix_list = parse_member_expression_suffix_list (); - assert (res->suffix_list); - } - else - { - lexer_save_token (tok); - res->suffix_list = NULL; - } - - return res; -} - -/* new_expression - : member_expression - | 'new' LT!* new_expression - ; */ -static new_expression * -parse_new_expression () -{ - new_expression *res = ALLOCATE (new_expression); - - if (is_keyword (KW_NEW)) - { - member_expression *expr = parse_member_expression (); - if (expr == NULL) - { - res->type = NE_NEW; - - skip_newlines (); - res->data.new_expr = parse_new_expression (); - assert (res->data.new_expr); - return res; - } - else - { - res->type = NE_MEMBER; - res->data.member_expr = expr; - return res; - } - } - else - { - res->type = NE_MEMBER; - res->data.member_expr = parse_member_expression (); - RETURN_NULL_IF_NULL (res->data.member_expr); - return res; - } -} - -/* call_expression_suffix - : arguments - | index_suffix - | property_reference_suffix - ; */ -static call_expression_suffix * -parse_call_expression_suffix () -{ - call_expression_suffix *res = ALLOCATE (call_expression_suffix); - - if (tok.type == TOK_OPEN_PAREN) - { - res->type = CAS_ARGS; - - skip_newlines (); - res->data.args = parse_expression (true); - fatal_if_null (res->data.args); - token_after_newlines_must_be (TOK_CLOSE_PAREN); - - return res; - } - else if (tok.type == TOK_OPEN_SQUARE) - { - res->type = CAS_INDEX; - - skip_newlines (); - res->data.index_expr = parse_expression (true); - fatal_if_null (res->data.index_expr); - token_after_newlines_must_be (TOK_CLOSE_SQUARE); - - return res; - } - else if (tok.type == TOK_DOT) - { - res->type = CAS_PROPERTY; - - token_after_newlines_must_be (TOK_NAME); - res->data.name = tok.data.name; - return res; - } - else - unreachable (); -} - -/* call_expression_suffix_list - : call_expression_suffix+ - ; */ -static call_expression_suffix_list * -parse_call_expression_suffix_list () -{ - call_expression_suffix_list *res = ALLOCATE (call_expression_suffix_list); - - if (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE - || tok.type == TOK_DOT) - { - res->suffix = parse_call_expression_suffix (); - assert (res->suffix); - } - else - unreachable (); - - skip_newlines (); - if (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE - || tok.type == TOK_DOT) - { - res->next = parse_call_expression_suffix_list (); - assert (res->next); - } - else - { - lexer_save_token (tok); - res->next = NULL; - } - - return res; -} - -/* call_expression - : member_expression LT!* arguments (LT!* call_expression_suffix)* - ;*/ -static call_expression * -parse_call_expression (member_expression *member_expr) -{ - call_expression *res = ALLOCATE (call_expression); - - assert (member_expr); - res->member_expr = member_expr; - - assert (tok.type == TOK_OPEN_PAREN); - skip_newlines (); - if (tok.type != TOK_CLOSE_PAREN) - { - res->args = parse_expression (true); - token_after_newlines_must_be (TOK_CLOSE_PAREN); - } - else - res->args = NULL; - - skip_newlines (); - if (tok.type == TOK_OPEN_PAREN || tok.type == TOK_OPEN_SQUARE - || tok.type == TOK_DOT) - { - res->suffix_list = parse_call_expression_suffix_list (); - assert (res->suffix_list); - } - else - lexer_save_token (tok); - - return res; -} - -/* left_hand_side_expression - : call_expression - | new_expression - ; */ -static left_hand_side_expression * -parse_left_hand_side_expression () -{ - left_hand_side_expression *res = ALLOCATE (left_hand_side_expression); - - if (is_keyword (KW_NEW)) - { - res->type = LHSE_NEW; - res->data.new_expr = parse_new_expression (); - assert (res->data.new_expr); - return res; - } - else - { - member_expression *member_expr = parse_member_expression (); - RETURN_NULL_IF_NULL (member_expr); - skip_newlines (); - if (tok.type == TOK_OPEN_PAREN) - { - res->type = LHSE_CALL; - res->data.call_expr = parse_call_expression (member_expr); - assert (res->data.call_expr); - return res; - } - else + if (tok.type != TOK_COMMA) { lexer_save_token (tok); - res->type = LHSE_NEW; - res->data.new_expr = ALLOCATE (new_expression); - res->data.new_expr->type = NE_MEMBER; - res->data.new_expr->data.member_expr = member_expr; - return res; - } - } -} -/* postfix_expression - : left_hand_side_expression ('++' | '--')? - ; */ -static postfix_expression * -parse_postfix_expression () -{ - postfix_expression *res = ALLOCATE (postfix_expression); - - res->expr = parse_left_hand_side_expression (); - RETURN_NULL_IF_NULL (res->expr); - - tok = lexer_next_token (); - if (tok.type == TOK_DOUBLE_PLUS) - res->type = PE_INCREMENT; - else if (tok.type == TOK_DOUBLE_MINUS) - res->type = PE_DECREMENT; - else - { - lexer_save_token (tok); - res->type = PE_NONE; - } - - return res; -} - -/* unary_expression - : postfix_expression - | ('delete' | 'void' | 'typeof' | '++' | '--' | '+' | '-' | '~' | '!') unary_expression - ; */ -static unary_expression * -parse_unary_expression () -{ - unary_expression *res = ALLOCATE (unary_expression); - - switch (tok.type) - { - case TOK_DOUBLE_PLUS: res->type = UE_INCREMENT; break; - case TOK_DOUBLE_MINUS: res->type = UE_DECREMENT; break; - case TOK_PLUS: res->type = UE_PLUS; break; - case TOK_MINUS: res->type = UE_MINUS; break; - case TOK_COMPL: res->type = UE_COMPL; break; - case TOK_NOT: res->type = UE_NOT; break; - case TOK_KEYWORD: - if (is_keyword (KW_DELETE)) { res->type = UE_DELETE; break; } - if (is_keyword (KW_VOID)) { res->type = UE_VOID; break; } - if (is_keyword (KW_TYPEOF)) { res->type = UE_TYPEOF; break; } - /* FALLTHRU. */ - - default: - /* It is postfix_expression. */ - res->type = UE_POSTFIX; - res->data.postfix_expr = parse_postfix_expression (); - RETURN_NULL_IF_NULL (res->data.postfix_expr); - return res; - } - - skip_newlines (); - res->data.unary_expr = parse_unary_expression (); - assert (res->data.unary_expr); - return res; -} - -/* multiplicative_expression_list - : unary_expression (LT!* ('*' | '/' | '%') LT!* unary_expression)* - ; */ -static multiplicative_expression_list * -parse_multiplicative_expression_list () -{ - multiplicative_expression_list *res = ALLOCATE (multiplicative_expression_list); - - res->unary_expr = parse_unary_expression (); - RETURN_NULL_IF_NULL (res->unary_expr); - - skip_newlines (); - switch (tok.type) - { - case TOK_MULT: res->type = ME_MULT; break; - case TOK_DIV: res->type = ME_DIV; break; - case TOK_MOD: res->type = ME_MOD; break; - default: - lexer_save_token (tok); - res->type = ME_NONE; - res->next = NULL; - return res; - } - - skip_newlines (); - res->next = parse_multiplicative_expression_list (); - assert (res->next); - return res; -} - -/* additive_expression_list - : multiplicative_expression_list (LT!* ('+' | '-') LT!* multiplicative_expression_list)* - ; */ -static additive_expression_list * -parse_additive_expression_list () -{ - additive_expression_list *res = ALLOCATE (additive_expression_list); - - res->mult_expr = parse_multiplicative_expression_list (); - RETURN_NULL_IF_NULL (res->mult_expr); - - skip_newlines (); - switch (tok.type) - { - case TOK_PLUS: res->type = AE_PLUS; break; - case TOK_MINUS: res->type = AE_MINUS; break; - default: - lexer_save_token (tok); - res->type = AE_NONE; - res->next = NULL; - return res; - } - - skip_newlines (); - res->next = parse_additive_expression_list (); - assert (res->next); - return res; -} - -/* shift_expression_list - : additive_expression_list (LT!* ('<<' | '>>' | '>>>') LT!* additive_expression_list)* - ; */ -static shift_expression_list * -parse_shift_expression_list () -{ - shift_expression_list *res = ALLOCATE (shift_expression_list); - - res->add_expr = parse_additive_expression_list (); - RETURN_NULL_IF_NULL (res->add_expr); - - skip_newlines (); - switch (tok.type) - { - case TOK_LSHIFT: res->type = SE_LSHIFT; break; - case TOK_RSHIFT: res->type = SE_RSHIFT; break; - case TOK_RSHIFT_EX: res->type = SE_RSHIFT_EX; break; - default: - lexer_save_token (tok); - res->type = SE_NONE; - res->next = NULL; - return res; - } - - skip_newlines (); - res->next = parse_shift_expression_list (); - assert (res->next); - return res; -} - -/* relational_expression_list - : shift_expression_list (LT!* ('<' | '>' | '<=' | '>=' | 'instanceof' | 'in') LT!* shift_expression_list)* - ; - - relational_expression_no_in - : shift_expression_list (LT!* ('<' | '>' | '<=' | '>=' | 'instanceof') LT!* shift_expression_list)* - ; */ -static relational_expression_list * -parse_relational_expression_list (bool in_allowed) -{ - relational_expression_list *res = ALLOCATE (relational_expression_list); - - res->shift_expr = parse_shift_expression_list (); - RETURN_NULL_IF_NULL (res->shift_expr); - - skip_newlines (); - switch (tok.type) - { - case TOK_LESS: res->type = RE_LESS; break; - case TOK_GREATER: res->type = RE_GREATER; break; - case TOK_LESS_EQ: res->type = RE_LESS_EQ; break; - case TOK_GREATER_EQ: res->type = RE_GREATER_EQ; break; - case TOK_KEYWORD: - if (is_keyword (KW_INSTANCEOF)) - { - res->type = RE_INSTANCEOF; - break; - } - if (is_keyword (KW_IN)) - { - if (!in_allowed) - fatal (ERR_PARSER); - res->type = RE_IN; + if (i != MAX_PROPERTIES - 1) + res.props[i + 1] = empty_property; break; } - default: - lexer_save_token (tok); - res->type = RE_NONE; - res->next = NULL; - return res; - } + } - skip_newlines (); - res->next = parse_relational_expression_list (in_allowed); - assert (res->next); return res; } -/* equality_expression_list - : relational_expression_list (LT!* ('==' | '!=' | '===' | '!==') LT!* relational_expression_list)* - ; - - equality_expression_no_in - : relational_expression_no_in (LT!* ('==' | '!=' | '===' | '!==') LT!* relational_expression_no_in)* - ; */ -static equality_expression_list * -parse_equality_expression_list (bool in_allowed) +static void +parse_unary_expression (assignment_expression *res, expression_type type) { - equality_expression_list *res = ALLOCATE (equality_expression_list); + res->type = type; + token_after_newlines_must_be (TOK_NAME); + res->data.ops.op1 = parse_operand (); + res->data.ops.op2 = empty_operand; +} - res->rel_expr = parse_relational_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->rel_expr); +static assignment_expression +parse_assigment_expression () +{ + assignment_expression res; + if (tok.type != TOK_NAME) + goto parse_operands; + + current_token_must_be (TOK_NAME); + + token saved_token = tok; + + skip_newlines (); + if (tok.type == TOK_OPEN_PAREN) + { + lexer_save_token (tok); + tok = saved_token; + return (assignment_expression) + { + .oper = AO_NONE, + .type = ET_CALL, + .var = NULL, + .data.call_expr = parse_call_expression () + }; + } + + res.var = saved_token.data.name; + + // Assume that this is assignment + skip_newlines (); + switch (tok.type) + { + case TOK_EQ: + res.oper = AO_EQ; + break; + case TOK_MULT_EQ: + res.oper = AO_MULT_EQ; + break; + case TOK_DIV_EQ: + res.oper = AO_DIV_EQ; + break; + case TOK_MOD_EQ: + res.oper = AO_MOD_EQ; + break; + case TOK_PLUS_EQ: + res.oper = AO_PLUS_EQ; + break; + case TOK_MINUS_EQ: + res.oper = AO_MINUS_EQ; + break; + case TOK_LSHIFT_EQ: + res.oper = AO_LSHIFT_EQ; + break; + case TOK_RSHIFT_EQ: + res.oper = AO_RSHIFT_EQ; + break; + case TOK_RSHIFT_EX_EQ: + res.oper = AO_RSHIFT_EX_EQ; + break; + case TOK_AND_EQ: + res.oper = AO_AND_EQ; + break; + case TOK_XOR_EQ: + res.oper = AO_XOR_EQ; + break; + case TOK_OR_EQ: + res.oper = AO_OR_EQ; + break; + + default: + res.oper = AO_NONE; + res.data.ops.op1 = (operand) { .is_literal = false, .data.name = res.var }; + res.var = NULL; + goto parse_operator; + } + + skip_newlines (); + +parse_operands: + saved_token = tok; + switch (tok.type) + { + case TOK_NAME: + case TOK_STRING: + case TOK_INT: + case TOK_NULL: + case TOK_BOOL: + res.data.ops.op1 = parse_operand (); + break; + + case TOK_OPEN_PAREN: + res.type = ET_SUBEXPRESSION; + res.data.none = NULL; + return res; + + case TOK_OPEN_BRACE: + res.type = ET_OBJECT; + res.data.obj_lit = parse_object_literal (); + next_token_must_be (TOK_CLOSE_BRACE); + return res; + + case TOK_OPEN_SQUARE: + res.type = ET_ARRAY; + res.data.arr_lit = parse_array_literal (); + next_token_must_be (TOK_CLOSE_SQUARE); + return res; + + case TOK_DOUBLE_PLUS: + parse_unary_expression (&res, ET_UNARY_INCREMENT); + return res; + + case TOK_DOUBLE_MINUS: + parse_unary_expression (&res, ET_UNARY_DECREMENT); + return res; + + case TOK_PLUS: + parse_unary_expression (&res, ET_UNARY_PLUS); + return res; + + case TOK_MINUS: + parse_unary_expression (&res, ET_UNARY_MINUS); + return res; + + case TOK_COMPL: + parse_unary_expression (&res, ET_UNARY_COMPL); + return res; + + case TOK_NOT: + parse_unary_expression (&res, ET_UNARY_NOT); + return res; + + case TOK_KEYWORD: + switch (tok.data.kw) + { + case KW_DELETE: + parse_unary_expression (&res, ET_UNARY_DELETE); + return res; + case KW_VOID: + parse_unary_expression (&res, ET_UNARY_VOID); + return res; + case KW_TYPEOF: + parse_unary_expression (&res, ET_UNARY_TYPEOF); + return res; + + case KW_FUNCTION: + res.type = ET_FUNCTION; + res.data.func_expr = parse_function_expression (); + return res; + + case KW_NEW: + parse_unary_expression (&res, ET_NEW); + return res; + + default: + JERRY_UNREACHABLE (); + } + + default: + JERRY_UNREACHABLE (); + } + +parse_operator: skip_newlines (); switch (tok.type) { - case TOK_DOUBLE_EQ: res->type = EE_DOUBLE_EQ; break; - case TOK_NOT_EQ: res->type = EE_NOT_EQ; break; - case TOK_TRIPLE_EQ: res->type = EE_TRIPLE_EQ; break; - case TOK_NOT_DOUBLE_EQ: res->type = EE_NOT_DOUBLE_EQ; break; + case TOK_DOUBLE_OR: + res.type = ET_LOGICAL_OR; + break; + case TOK_DOUBLE_AND: + res.type = ET_LOGICAL_AND; + break; + case TOK_OR: + res.type = ET_BITWISE_OR; + break; + case TOK_XOR: + res.type = ET_BITWISE_XOR; + break; + case TOK_AND: + res.type = ET_BITWISE_AND; + break; + case TOK_DOUBLE_EQ: + res.type = ET_DOUBLE_EQ; + break; + case TOK_NOT_EQ: + res.type = ET_NOT_EQ; + break; + case TOK_TRIPLE_EQ: + res.type = ET_TRIPLE_EQ; + break; + case TOK_NOT_DOUBLE_EQ: + res.type = ET_NOT_DOUBLE_EQ; + break; + case TOK_LESS: + res.type = ET_LESS; + break; + case TOK_GREATER: + res.type = ET_GREATER; + break; + case TOK_LESS_EQ: + res.type = ET_LESS_EQ; + break; + case TOK_GREATER_EQ: + res.type = ET_GREATER_EQ; + break; + case TOK_LSHIFT: + res.type = ET_LSHIFT; + break; + case TOK_RSHIFT: + res.type = ET_RSHIFT; + break; + case TOK_RSHIFT_EX: + res.type = ET_RSHIFT_EX; + break; + case TOK_PLUS: + res.type = ET_PLUS; + break; + case TOK_MINUS: + res.type = ET_MINUS; + break; + case TOK_MULT: + res.type = ET_MULT; + break; + case TOK_DIV: + res.type = ET_DIV; + break; + case TOK_MOD: + res.type = ET_MOD; + break; + + case TOK_DOUBLE_PLUS: + res.type = ET_POSTFIX_INCREMENT; + res.data.ops.op2 = empty_operand; + return res; + + case TOK_DOUBLE_MINUS: + res.type = ET_POSTFIX_DECREMENT; + res.data.ops.op2 = empty_operand; + return res; + + case TOK_OPEN_PAREN: + res.type = ET_CALL; + lexer_save_token (tok); + tok = saved_token; + res.data.call_expr = parse_call_expression (); + return res; + + case TOK_DOT: + res.type = ET_PROP_REF; + skip_newlines (); + res.data.ops.op2 = parse_operand (); + assert (!res.data.ops.op2.is_literal); + return res; + + case TOK_OPEN_SQUARE: + res.type = ET_INDEX; + skip_newlines (); + res.data.ops.op2 = parse_operand (); + token_after_newlines_must_be (TOK_CLOSE_SQUARE); + return res; + + case TOK_KEYWORD: + switch (tok.data.kw) + { + case KW_INSTANCEOF: + res.type = ET_INSTANCEOF; + break; + case KW_IN: + res.type = ET_IN; + break; + + default: + JERRY_UNREACHABLE (); + } + break; + default: lexer_save_token (tok); - res->type = EE_NONE; - res->next = NULL; + res.oper = AO_NONE; + res.type = ET_NONE; + res.data.ops.op2 = empty_operand; return res; } skip_newlines (); - res->next = parse_equality_expression_list (in_allowed); - assert (res->next); - return res; -} - -/* bitwise_and_expression_list - : equality_expression_list (LT!* '&' LT!* equality_expression_list)* - ; - - bitwise_and_expression_no_in - : equality_expression_no_in (LT!* '&' LT!* equality_expression_no_in)* - ; */ -static bitwise_and_expression_list * -parse_bitwise_and_expression_list (bool in_allowed) -{ - bitwise_and_expression_list *res = ALLOCATE (bitwise_and_expression_list); - - res->eq_expr = parse_equality_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->eq_expr); - - skip_newlines (); - if (tok.type == TOK_AND) - { - skip_newlines (); - res->next = parse_bitwise_and_expression_list (in_allowed); - assert (res->next); - return res; - } - else - { - lexer_save_token (tok); - res->next = NULL; - return res; - } -} - -/* bitwise_xor_expression_list - : bitwise_and_expression_list (LT!* '^' LT!* bitwise_and_expression_list)* - ; - - bitwise_xor_expression_no_in - : bitwise_and_expression_no_in (LT!* '^' LT!* bitwise_and_expression_no_in)* - ; */ -static bitwise_xor_expression_list * -parse_bitwise_xor_expression_list (bool in_allowed) -{ - bitwise_xor_expression_list *res = ALLOCATE (bitwise_xor_expression_list); - - res->and_expr = parse_bitwise_and_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->and_expr); - - skip_newlines (); - if (tok.type == TOK_XOR) - { - skip_newlines (); - res->next = parse_bitwise_xor_expression_list (in_allowed); - assert (res->next); - return res; - } - else - { - lexer_save_token (tok); - res->next = NULL; - return res; - } -} - -/* bitwise_or_expression_list - : bitwise_xor_expression_list (LT!* '|' LT!* bitwise_xor_expression_list)* - ; - - bitwise_or_expression_no_in - : bitwise_xor_expression_no_in (LT!* '|' LT!* bitwise_xor_expression_no_in)* - ; */ -static bitwise_or_expression_list * -parse_bitwise_or_expression_list (bool in_allowed) -{ - bitwise_or_expression_list *res = ALLOCATE (bitwise_or_expression_list); - - res->xor_expr = parse_bitwise_xor_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->xor_expr); - - skip_newlines (); - if (tok.type == TOK_OR) - { - skip_newlines (); - res->next = parse_bitwise_or_expression_list (in_allowed); - assert (res->next); - return res; - } - else - { - lexer_save_token (tok); - res->next = NULL; - return res; - } -} - -/* logical_and_expression_list - : bitwise_or_expression_list (LT!* '&&' LT!* bitwise_or_expression_list)* - ; - - logical_and_expression_no_in - : bitwise_or_expression_no_in (LT!* '&&' LT!* bitwise_or_expression_no_in)* - ;*/ -static logical_and_expression_list * -parse_logical_and_expression_list (bool in_allowed) -{ - logical_and_expression_list *res = ALLOCATE (logical_and_expression_list); - - res->or_expr = parse_bitwise_or_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->or_expr); - - skip_newlines (); - if (tok.type == TOK_DOUBLE_AND) - { - skip_newlines (); - res->next = parse_logical_and_expression_list (in_allowed); - assert (res->next); - return res; - } - else - { - lexer_save_token (tok); - res->next = NULL; - return res; - } -} - -/* logical_or_expression_list - : logical_and_expression_list (LT!* '||' LT!* logical_and_expression_list)* - ; - - logical_or_expression_no_in - : logical_and_expression_no_in (LT!* '||' LT!* logical_and_expression_no_in)* - ; */ -static logical_or_expression_list * -parse_logical_or_expression_list (bool in_allowed) -{ - logical_or_expression_list *res = ALLOCATE (logical_or_expression_list); - - res->and_expr = parse_logical_and_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->and_expr); - - skip_newlines (); - if (tok.type == TOK_DOUBLE_OR) - { - skip_newlines (); - res->next = parse_logical_or_expression_list (in_allowed); - assert (res->next); - return res; - } - else - { - lexer_save_token (tok); - res->next = NULL; - return res; - } -} - -/* conditional_expression - : logical_or_expression_list (LT!* '?' LT!* assignment_expression LT!* ':' LT!* assignment_expression)? - ; - - conditional_expression_no_in - : logical_or_expression_no_in (LT!* '?' LT!* assignment_expression_no_in LT!* ':' LT!* assignment_expression_no_in)? - ; */ -static conditional_expression * -parse_conditional_expression (bool in_allowed) -{ - conditional_expression *res = ALLOCATE (conditional_expression); - - res->or_expr = parse_logical_or_expression_list (in_allowed); - RETURN_NULL_IF_NULL (res->or_expr); - - skip_newlines (); - if (tok.type == TOK_QUERY) - { - skip_newlines (); - res->then_expr = parse_assigment_expression (in_allowed); - assert (res->then_expr); - token_after_newlines_must_be (TOK_COLON); - - skip_newlines (); - res->else_expr = parse_assigment_expression (in_allowed); - assert (res->else_expr); - return res; - } - else - { - lexer_save_token (tok); - res->then_expr = res->else_expr = NULL; - return res; - } -} - -/* assignment_expression - : conditional_expression - | left_hand_side_expression LT!* assignment_operator LT!* assignment_expression - ; - - assignment_expression_no_in - : conditional_expression_no_in - | left_hand_side_expression LT!* assignment_operator LT!* assignment_expression_no_in - ; - - assignmentOperator - : '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=' - ;*/ -static assignment_expression * -parse_assigment_expression (bool in_allowed) -{ - assignment_expression *res = ALLOCATE (assignment_expression); - - /* OK, assignment_expression contains conditional_expression, - conditional_expression contains logical_or_expression_list, - logical_or_expression_list contains logical_and_expression_list, - logical_and_expression_list contains bitwise_or_expression_list, - bitwise_or_expression_list contains bitwise_xor_expression_list, - bitwise_xor_expression_list contains bitwise_and_expression_list, - bitwise_and_expression_list contains equality_expression_list, - equality_expression_list contains relational_expression_list, - relational_expression_list contains shift_expression_list, - shift_expression_list contains additive_expression_list, - additive_expression_list contains multiplicative_expression_list, - multiplicative_expression_list contains unary_expression, - unary_expression contains postfix_expression, - postfix_expression contains left_hand_side_expression. - - So, we can try parse conditional_expression and check if there is only left_hand_side_expression. */ - conditional_expression *cond_expr = parse_conditional_expression (in_allowed); - const logical_or_expression_list *lor_expr; - const logical_and_expression_list *land_expr; - const bitwise_or_expression_list *bor_expr; - const bitwise_xor_expression_list *xor_expr; - const bitwise_and_expression_list *band_expr; - const equality_expression_list *eq_expr; - const relational_expression_list *rel_expr; - const shift_expression_list *shift_expr; - const additive_expression_list *add_expr; - const multiplicative_expression_list *mult_expr; - const unary_expression *unary_expr; - const postfix_expression *postfix_expr; - left_hand_side_expression *left_hand_expr; - - RETURN_NULL_IF_NULL (cond_expr); - - if (cond_expr->then_expr) - goto cond; - assert (cond_expr->else_expr == NULL); - assert (cond_expr->or_expr); - - lor_expr = cond_expr->or_expr; - if (lor_expr->next) - goto cond; - assert (lor_expr->and_expr); - - land_expr = lor_expr->and_expr; - if (land_expr->next) - goto cond; - assert (land_expr->or_expr); - - bor_expr = land_expr->or_expr; - if (bor_expr->next) - goto cond; - assert (bor_expr->xor_expr); - - xor_expr = bor_expr->xor_expr; - if (xor_expr->next) - goto cond; - assert (xor_expr->and_expr); - - band_expr = xor_expr->and_expr; - if (band_expr->next) - goto cond; - assert (band_expr->eq_expr); - - eq_expr = band_expr->eq_expr; - if (eq_expr->next) - goto cond; - assert (eq_expr->type == EE_NONE); - assert (eq_expr->rel_expr); - - rel_expr = eq_expr->rel_expr; - if (rel_expr->next) - goto cond; - assert (rel_expr->type == RE_NONE); - assert (rel_expr->shift_expr); - - shift_expr = rel_expr->shift_expr; - if (shift_expr->next) - goto cond; - assert (shift_expr->type == SE_NONE); - assert (shift_expr->add_expr); - - add_expr = shift_expr->add_expr; - if (add_expr->next) - goto cond; - assert (add_expr->type == AE_NONE); - assert (add_expr->mult_expr); - - mult_expr = add_expr->mult_expr; - if (mult_expr->next) - goto cond; - assert (mult_expr->type == ME_NONE); - assert (mult_expr->unary_expr); - - unary_expr = mult_expr->unary_expr; - if (unary_expr->type != UE_POSTFIX) - goto cond; - assert (unary_expr->data.postfix_expr); - - postfix_expr = unary_expr->data.postfix_expr; - if (postfix_expr->type != PE_NONE) - goto cond; - assert (postfix_expr->expr); - - left_hand_expr = postfix_expr->expr; - - skip_newlines (); - switch (tok.type) - { - case TOK_EQ: res->type = AE_EQ; break; - case TOK_MULT_EQ: res->type = AE_MULT_EQ; break; - case TOK_DIV_EQ: res->type = AE_DIV_EQ; break; - case TOK_MOD_EQ: res->type = AE_MOD_EQ; break; - case TOK_PLUS_EQ: res->type = AE_PLUS_EQ; break; - case TOK_MINUS_EQ: res->type = AE_MINUS_EQ; break; - case TOK_LSHIFT_EQ: res->type = AE_LSHIFT_EQ; break; - case TOK_RSHIFT_EQ: res->type = AE_RSHIFT_EQ; break; - case TOK_RSHIFT_EX_EQ: res->type = AE_RSHIFT_EX_EQ; break; - case TOK_AND_EQ: res->type = AE_AND_EQ; break; - case TOK_OR_EQ: res->type = AE_OR_EQ; break; - case TOK_XOR_EQ: res->type = AE_XOR_EQ; break; - default: - lexer_save_token (tok); - goto cond; - } - res->data.s.left_hand_expr = left_hand_expr; - - skip_newlines (); - res->data.s.assign_expr = parse_assigment_expression (in_allowed); - assert (res->data.s.assign_expr); - return res; - -cond: - res->type = AE_COND; - res->data.cond_expr = cond_expr; + res.data.ops.op2 = parse_operand (); return res; } /* expression : assignment_expression (LT!* ',' LT!* assignment_expression)* ; - - expression_no_in - : assignment_expression_no_in (LT!* ',' LT!* assignment_expression_no_in)* - ; */ -static expression * -parse_expression (bool in_allowed) + */ +static expression +parse_expression () { - expression *res = ALLOCATE (expression); + expression res; + int i; - res->assign_expr = parse_assigment_expression (in_allowed); - RETURN_NULL_IF_NULL (res->assign_expr); - - skip_newlines (); - if (tok.type == TOK_COMMA) + for (i = 0; i < MAX_EXPRS; i++) { + res.exprs[i] = parse_assigment_expression (); skip_newlines (); - res->next = parse_expression (in_allowed); - } - else - { - lexer_save_token (tok); - res->next = NULL; + if (tok.type != TOK_COMMA) + { + lexer_save_token (tok); + if (i != MAX_EXPRS - 1) + res.exprs[i + 1] = empty_expression; + break; + } } return res; @@ -1450,24 +807,24 @@ parse_expression (bool in_allowed) initialiser(_no_in) : '=' LT!* assignment_expression ; */ -static variable_declaration* -parse_variable_declaration (bool in_allowed) +static variable_declaration +parse_variable_declaration () { - variable_declaration *res = ALLOCATE (variable_declaration); + variable_declaration res; current_token_must_be (TOK_NAME); - res->name = tok.data.name; + res.name = tok.data.name; skip_newlines (); if (tok.type == TOK_EQ) { skip_newlines (); - res->ass_expr = parse_assigment_expression (in_allowed); + res.assign_expr = parse_assigment_expression (); } else { lexer_save_token (tok); - res->ass_expr = NULL; + res.assign_expr = empty_expression; } return res; @@ -1477,25 +834,23 @@ parse_variable_declaration (bool in_allowed) : variable_declaration(_no_in) (LT!* ',' LT!* variable_declaration(_no_in))* ; */ -static variable_declaration_list * -parse_variable_declaration_list (bool in_allowed) +static variable_declaration_list +parse_variable_declaration_list () { - variable_declaration_list *res = ALLOCATE (variable_declaration_list);; - variable_declaration *var_decl = parse_variable_declaration (in_allowed); + variable_declaration_list res; + int i; - fatal_if_null (var_decl); - res->var_decl = var_decl; - skip_newlines (); - if (tok.type == TOK_COMMA) + for (i = 0; i < MAX_DECLS; i++) { + res.decls[i] = parse_variable_declaration (); skip_newlines (); - res->next = parse_variable_declaration_list (in_allowed); - assert (res->next); - } - else - { - lexer_save_token (tok); - res->next = NULL; + if (tok.type != TOK_COMMA) + { + lexer_save_token (tok); + if (i != MAX_DECLS - 1) + res.decls[i + 1] = empty_variable_declaration; + break; + } } return res; @@ -1521,12 +876,14 @@ parse_variable_declaration_list (bool in_allowed) | 'var' LT!* variable_declaration_no_in ;*/ -static for_or_for_in_statement * +static for_or_for_in_statement parse_for_or_for_in_statement () { - for_or_for_in_statement *res = ALLOCATE (for_or_for_in_statement); - variable_declaration_list *list = NULL; - expression *expr = NULL; + for_or_for_in_statement res; + variable_declaration_list list; + expression expr; + expr.exprs[0] = empty_expression; + list.decls[0] = empty_variable_declaration; assert_keyword (KW_FOR); token_after_newlines_must_be (TOK_OPEN_PAREN); @@ -1535,13 +892,12 @@ parse_for_or_for_in_statement () if (tok.type == TOK_SEMICOLON) goto plain_for; /* Both for_statement_initialiser_part and for_in_statement_initialiser_part - contains 'var'. Chekc it first. */ + contains 'var'. Check it first. */ if (is_keyword (KW_VAR)) { skip_newlines (); - list = parse_variable_declaration_list (false); - assert (list); - if (list->next) + list = parse_variable_declaration_list (); + if (!is_variable_declaration_empty (list.decls[1])) { token_after_newlines_must_be (TOK_SEMICOLON); goto plain_for; @@ -1557,10 +913,10 @@ parse_for_or_for_in_statement () fatal (ERR_PARSER); } } - assert (list == NULL); + assert (is_variable_declaration_empty(list.decls[0])); /* expression contains left_hand_side_expression. */ - expr = parse_expression (false); + expr = parse_expression (); skip_newlines (); if (tok.type == TOK_SEMICOLON) @@ -1570,149 +926,60 @@ parse_for_or_for_in_statement () else fatal (ERR_PARSER); - unreachable (); + JERRY_UNREACHABLE (); plain_for: - res->is_for_in = false; - res->data.for_stmt = ALLOCATE (for_statement); - if (list) + res.is_for_in = false; + if (!is_variable_declaration_empty(list.decls[0])) { - assert (expr == NULL); - res->data.for_stmt->init = ALLOCATE (for_statement_initialiser_part); - res->data.for_stmt->init->is_decl = true; - res->data.for_stmt->init->data.decl_list = list; + assert (is_expression_empty(expr.exprs[0])); + res.data.for_stmt.init.is_decl = true; + res.data.for_stmt.init.data.decl_list = list; } - if (expr) + if (!is_expression_empty(expr.exprs[0])) { - assert (list == NULL); - res->data.for_stmt->init = ALLOCATE (for_statement_initialiser_part); - res->data.for_stmt->init->is_decl = false; - res->data.for_stmt->init->data.expr = expr; + assert (is_variable_declaration_empty(list.decls[0])); + res.data.for_stmt.init.is_decl = false; + res.data.for_stmt.init.data.expr = expr; } skip_newlines (); if (tok.type == TOK_SEMICOLON) - res->data.for_stmt->limit = NULL; + res.data.for_stmt.limit = empty_expression; else { - res->data.for_stmt->limit = parse_expression (true); - assert (res->data.for_stmt->limit); + res.data.for_stmt.limit = parse_assigment_expression (); next_token_must_be (TOK_SEMICOLON); } skip_newlines (); if (tok.type == TOK_CLOSE_PAREN) - res->data.for_stmt->incr = NULL; + res.data.for_stmt.incr = empty_expression; else { - res->data.for_stmt->incr = parse_expression (true); - assert (res->data.for_stmt->incr); + res.data.for_stmt.incr = parse_assigment_expression (); next_token_must_be (TOK_CLOSE_PAREN); } return res; for_in: - res->is_for_in = true; - res->data.for_in_stmt = ALLOCATE (for_in_statement); - if (list) + res.is_for_in = true; + if (!is_variable_declaration_empty(list.decls[0])) { - assert (expr == NULL); - assert (list->next == NULL); - res->data.for_in_stmt->init = ALLOCATE (for_in_statement_initializer_part); - res->data.for_in_stmt->init->is_decl = true; - res->data.for_in_stmt->init->data.decl = list->var_decl; + assert (is_expression_empty (expr.exprs[0])); + assert (is_variable_declaration_empty (list.decls[1])); + res.data.for_in_stmt.init.is_decl = true; + res.data.for_in_stmt.init.data.decl = list.decls[0]; } - if (expr) + if (!is_expression_empty(expr.exprs[0])) { - assignment_expression *assign_expr = NULL; - conditional_expression *cond_expr = NULL; - logical_or_expression_list *lor_expr = NULL; - logical_and_expression_list *land_expr = NULL; - bitwise_or_expression_list *bor_expr = NULL; - bitwise_xor_expression_list *xor_expr = NULL; - bitwise_and_expression_list *band_expr = NULL; - equality_expression_list *eq_expr = NULL; - relational_expression_list *rel_expr = NULL; - shift_expression_list *shift_expr = NULL; - additive_expression_list *add_expr = NULL; - multiplicative_expression_list *mult_expr = NULL; - unary_expression *unary_expr = NULL; - postfix_expression *postfix_expr = NULL; - - assert (list == NULL); - assert (expr->next == NULL); - - assign_expr = expr->assign_expr; - assert (assign_expr->type == AE_COND); - assert (assign_expr->data.cond_expr); - - cond_expr = assign_expr->data.cond_expr; - assert (cond_expr->then_expr == NULL); - assert (cond_expr->else_expr == NULL); - assert (cond_expr->or_expr); - - lor_expr = cond_expr->or_expr; - assert (lor_expr->next == NULL); - assert (lor_expr->and_expr); - - land_expr = lor_expr->and_expr; - assert (land_expr->next == NULL); - assert (land_expr->or_expr); - - bor_expr = land_expr->or_expr; - assert (bor_expr->next == NULL); - assert (bor_expr->xor_expr); - - xor_expr = bor_expr->xor_expr; - assert (xor_expr->next == NULL); - assert (xor_expr->and_expr); - - band_expr = xor_expr->and_expr; - assert (band_expr->next == NULL); - assert (band_expr->eq_expr); - - eq_expr = band_expr->eq_expr; - assert (eq_expr->next == NULL); - assert (eq_expr->type == EE_NONE); - assert (eq_expr->rel_expr); - - rel_expr = eq_expr->rel_expr; - assert (rel_expr->next == NULL); - assert (rel_expr->type == RE_NONE); - assert (rel_expr->shift_expr); - - shift_expr = rel_expr->shift_expr; - assert (shift_expr->next == NULL); - assert (shift_expr->type == SE_NONE); - assert (shift_expr->add_expr); - - add_expr = shift_expr->add_expr; - assert (add_expr->next == NULL); - assert (add_expr->type == AE_NONE); - assert (add_expr->mult_expr); - - mult_expr = add_expr->mult_expr; - assert (mult_expr->next == NULL); - assert (mult_expr->type == ME_NONE); - assert (mult_expr->unary_expr); - - unary_expr = mult_expr->unary_expr; - assert (unary_expr->type == UE_POSTFIX); - assert (unary_expr->data.postfix_expr); - - postfix_expr = unary_expr->data.postfix_expr; - assert (postfix_expr->type == PE_NONE); - assert (postfix_expr->expr); - - res->data.for_in_stmt->init = ALLOCATE (for_in_statement_initializer_part); - res->data.for_in_stmt->init->is_decl = false; - res->data.for_in_stmt->init->data.left_hand_expr = postfix_expr->expr; + assert (is_expression_empty(expr.exprs[0])); + res.data.for_in_stmt.init.is_decl = false; + res.data.for_in_stmt.init.data.left_hand_expr = expr.exprs[0]; } - assert (res->data.for_in_stmt->init); skip_newlines (); - res->data.for_in_stmt->list_expr = parse_expression (true); - assert (res->data.for_in_stmt->list_expr); + res.data.for_in_stmt.list_expr = parse_expression (); token_after_newlines_must_be (TOK_CLOSE_PAREN); return res; @@ -1723,8 +990,7 @@ parse_expression_inside_parens (statement *res) { token_after_newlines_must_be (TOK_OPEN_PAREN); skip_newlines (); - res->data.expr = parse_expression (true); - assert (res->data.expr); + res->data.expr = parse_expression (); token_after_newlines_must_be (TOK_CLOSE_PAREN); } @@ -1791,63 +1057,62 @@ parse_expression_inside_parens (statement *res) try_statement : 'try' LT!* '{' LT!* statement_list LT!* '}' LT!* (finally_clause | catch_clause (LT!* finally_clause)?) ;*/ -statement * +statement parser_parse_statement () { - statement *res = ALLOCATE (statement); - res->data.none = NULL; + statement res; + res.data.none = NULL; skip_newlines (); if (is_keyword (KW_FINALLY)) { - res->type = STMT_FINALLY; + res.type = STMT_FINALLY; current_scope_must_be (SCOPE_TRY | SCOPE_CATCH); pop_scope (); push_scope (SCOPE_FINALLY); return res; } - if (current_scope->was_stmt - && (current_scope->type & (SCOPE_IF | SCOPE_DO | SCOPE_WITH | SCOPE_SWITCH | SCOPE_ELSE + if (current_scopes[scope_index - 1].was_stmt + && (current_scopes[scope_index - 1].type & (SCOPE_IF | SCOPE_DO | SCOPE_WITH | SCOPE_SWITCH | SCOPE_ELSE | SCOPE_CATCH | SCOPE_FINALLY | SCOPE_FUNCTION | SCOPE_WHILE | SCOPE_FOR))) pop_scope (); - current_scope->was_stmt = true; + current_scopes[scope_index - 1].was_stmt = true; if (tok.type == TOK_EOF) { current_scope_must_be_global (); - res->type = STMT_EOF; + res.type = STMT_EOF; return res; } - if (current_scope->type == SCOPE_SUBEXPRESSION) + if (current_scopes[scope_index - 1].type == SCOPE_SUBEXPRESSION) { if (tok.type == TOK_CLOSE_PAREN) { - res->type = STMT_SUBEXPRESSION_END; + res.type = STMT_SUBEXPRESSION_END; pop_scope (); return res; } - res->type = STMT_EXPRESSION; - res->data.expr = parse_expression (true); - assert (res->data.expr); + res.type = STMT_EXPRESSION; + res.data.expr = parse_expression (); return res; } if (tok.type == TOK_OPEN_BRACE) { - res->type = STMT_BLOCK_START; + res.type = STMT_BLOCK_START; push_scope (SCOPE_BLOCK); return res; } if (tok.type == TOK_CLOSE_BRACE) { current_scope_must_be (SCOPE_BLOCK); - res->type = STMT_BLOCK_END; + res.type = STMT_BLOCK_END; pop_scope (); - current_scope->was_stmt = true; + current_scopes[scope_index - 1].was_stmt = true; return res; } if (is_keyword (KW_ELSE)) @@ -1856,14 +1121,14 @@ parser_parse_statement () skip_newlines (); if (is_keyword (KW_IF)) { - res->type = STMT_ELSE_IF; - parse_expression_inside_parens (res); + res.type = STMT_ELSE_IF; + parse_expression_inside_parens (&res); return res; } else { lexer_save_token (tok); - res->type = STMT_ELSE; + res.type = STMT_ELSE; pop_scope (); push_scope (SCOPE_ELSE); return res; @@ -1871,9 +1136,9 @@ parser_parse_statement () } if (is_keyword (KW_WHILE)) { - res->type = STMT_WHILE; - parse_expression_inside_parens (res); - if (current_scope->type == SCOPE_DO) + res.type = STMT_WHILE; + parse_expression_inside_parens (&res); + if (current_scopes[scope_index - 1].type == SCOPE_DO) { insert_semicolon (); pop_scope (); @@ -1884,61 +1149,60 @@ parser_parse_statement () } if (is_keyword (KW_CATCH)) { - res->type = STMT_CATCH; + res.type = STMT_CATCH; current_scope_must_be (SCOPE_TRY); - parse_expression_inside_parens (res); + parse_expression_inside_parens (&res); pop_scope (); push_scope (SCOPE_CATCH); return res; } if (is_keyword (KW_FUNCTION)) { - res->type = STMT_FUNCTION; - res->data.fun_decl = parse_function_declaration (); + res.type = STMT_FUNCTION; + res.data.fun_decl = parse_function_declaration (); push_scope (SCOPE_FUNCTION); return res; } if (is_keyword (KW_VAR)) { - res->type = STMT_VARIABLE; + res.type = STMT_VARIABLE; skip_newlines (); - res->data.var_stmt = parse_variable_declaration_list (true); + res.data.var_stmt = parse_variable_declaration_list (true); return res; } if (tok.type == TOK_SEMICOLON) { - res->type = STMT_EMPTY; + res.type = STMT_EMPTY; return res; } if (is_keyword (KW_IF)) { - res->type = STMT_IF; - parse_expression_inside_parens (res); + res.type = STMT_IF; + parse_expression_inside_parens (&res); push_scope (SCOPE_IF); return res; } if (is_keyword (KW_DO)) { - res->type = STMT_DO; + res.type = STMT_DO; push_scope (SCOPE_DO); return res; } if (is_keyword (KW_FOR)) { - res->type = STMT_FOR_OR_FOR_IN; - res->data.for_stmt = parse_for_or_for_in_statement (); - assert (res->data.for_stmt); + res.type = STMT_FOR_OR_FOR_IN; + res.data.for_stmt = parse_for_or_for_in_statement (); push_scope (SCOPE_FOR); return res; } if (is_keyword (KW_CONTINUE)) { scope_must_be (SCOPE_LOOP); - res->type = STMT_CONTINUE; + res.type = STMT_CONTINUE; tok = lexer_next_token (); if (tok.type == TOK_NAME) - res->data.name = tok.data.name; + res.data.name = tok.data.name; else lexer_save_token (tok); insert_semicolon (); @@ -1947,13 +1211,13 @@ parser_parse_statement () if (is_keyword (KW_BREAK)) { scope_must_be (SCOPE_LOOP | SCOPE_CASE); - res->type = STMT_BREAK; + res.type = STMT_BREAK; tok = lexer_next_token (); if (tok.type == TOK_NAME) { - if (current_scope->type == SCOPE_CASE) + if (current_scopes[scope_index - 1].type == SCOPE_CASE) fatal (ERR_PARSER); - res->data.name = tok.data.name; + res.data.name = tok.data.name; } else lexer_save_token (tok); @@ -1963,14 +1227,13 @@ parser_parse_statement () if (is_keyword (KW_RETURN)) { scope_must_be (SCOPE_FUNCTION); - res->type = STMT_RETURN; + res.type = STMT_RETURN; tok = lexer_next_token (); if (tok.type != TOK_SEMICOLON && tok.type != TOK_NEWLINE) { - scope *old_scope = current_scope; - res->data.expr = parse_expression (false); - assert (res->data.expr); - if (old_scope == current_scope) + int current_scope_index = scope_index; + res.data.expr = parse_expression (); + if (current_scope_index == scope_index) insert_semicolon (); } // Eat TOK_SEMICOLON @@ -1978,48 +1241,46 @@ parser_parse_statement () } if (is_keyword (KW_WITH)) { - res->type = STMT_WITH; - parse_expression_inside_parens (res); + res.type = STMT_WITH; + parse_expression_inside_parens (&res); push_scope (SCOPE_WITH); return res; } if (is_keyword (KW_SWITCH)) { - res->type = STMT_SWITCH; - parse_expression_inside_parens (res); + res.type = STMT_SWITCH; + parse_expression_inside_parens (&res); push_scope (SCOPE_SWITCH); return res; } if (is_keyword (KW_THROW)) { - res->type = STMT_THROW; + res.type = STMT_THROW; tok = lexer_next_token (); - res->data.expr = parse_expression (true); - assert (res->data.expr); + res.data.expr = parse_expression (); insert_semicolon (); return res; } if (is_keyword (KW_TRY)) { - res->type = STMT_TRY; + res.type = STMT_TRY; push_scope (SCOPE_TRY); return res; } if (is_keyword (KW_CASE)) { - if (current_scope->type == SCOPE_CASE) + if (current_scopes[scope_index - 1].type == SCOPE_CASE) pop_scope (); current_scope_must_be (SCOPE_SWITCH); skip_newlines (); - res->data.expr = parse_expression (true); - assert (res->data.expr); + res.data.expr = parse_expression (); token_after_newlines_must_be (TOK_SEMICOLON); push_scope (SCOPE_CASE); return res; } if (is_keyword (KW_DEFAULT)) { - if (current_scope->type == SCOPE_CASE) + if (current_scopes[scope_index - 1].type == SCOPE_CASE) pop_scope (); current_scope_must_be (SCOPE_SWITCH); token_after_newlines_must_be (TOK_SEMICOLON); @@ -2032,43 +1293,40 @@ parser_parse_statement () skip_newlines (); if (tok.type == TOK_COLON) { - res->type = STMT_LABELLED; - res->data.name = saved.data.name; + res.type = STMT_LABELLED; + res.data.name = saved.data.name; return res; } else { lexer_save_token (tok); tok = saved; - expression *expr = parse_expression (true); - fatal_if_null (expr); - res->type = STMT_EXPRESSION; - res->data.expr = expr; + expression expr = parse_expression (); + res.type = STMT_EXPRESSION; + res.data.expr = expr; return res; } } - expression *expr = parse_expression (true); - if (expr) + expression expr = parse_expression (); + if (!is_expression_empty (expr.exprs[0])) { - res->type = STMT_EXPRESSION; - res->data.expr = expr; + res.type = STMT_EXPRESSION; + res.data.expr = expr; return res; } else { lexer_save_token (tok); - free (res); - return NULL; + return null_statement; } } void parser_init () { - current_scope = ALLOCATE (struct scope); - current_scope->type = SCOPE_GLOBAL; -#ifdef DEBUG + scope_index = 0; +#ifdef JERRY_NDEBUG debug_file = fopen ("parser.log", "w"); #endif } diff --git a/src/libjsparser/parser.h b/src/libjsparser/parser.h index 7f88b1c64..90e60e148 100644 --- a/src/libjsparser/parser.h +++ b/src/libjsparser/parser.h @@ -16,8 +16,7 @@ #ifndef PARSER_H #define PARSER_H -#include -#include +#include "mappings.h" struct source_element_list; struct statement_list; @@ -25,16 +24,32 @@ struct statement; struct assignment_expression; struct member_expression; +#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 { - /** Identifier of a parameter. Cannot be NULL. */ - const char *name; - /** Next parameter: can be NULL. */ - struct formal_parameter_list *next; + /** Identifiers of a parameter. Next after last parameter is NULL. */ + const char *names[MAX_PARAMS]; } formal_parameter_list; +static const formal_parameter_list +empty_formal_parameter_list = +{ + .names = { [0] = NULL} +}; + +static inline bool +is_formal_parameter_list_empty (formal_parameter_list list) +{ + return list.names[0] == NULL; +} + /** @function_declaration represents both declaration and expression of a function. After this parser must return a block of statements. */ typedef struct @@ -42,27 +57,12 @@ typedef struct /** Identifier: name of a function. Can be NULL for anonimous functions. */ const char *name; /** List of parameter of a function. Can be NULL. */ - formal_parameter_list *params; + formal_parameter_list params; } function_declaration; typedef function_declaration function_expression; -/** Represents expression, array literal and list of argument. */ -typedef struct expression_list -{ - /** Single assignment expression. Cannot be NULL for expression and list of arguments. - But can be NULL for array literal. */ - struct assignment_expression *assign_expr; - /** Next expression. Can be NULL. */ - struct expression_list *next; -} -expression_list; - -typedef expression_list expression; -typedef expression_list array_literal; -typedef expression_list argument_list; - /** Types of literals: null, bool, decimal and string. Decimal type is represented by LIT_INT and supports only double-word sized integers. */ typedef enum @@ -84,7 +84,7 @@ typedef struct union { /** Used by null literal, always NULL. */ - void *data; + void *none; /** String literal value. */ const char *str; /** Number value. */ @@ -96,536 +96,257 @@ typedef struct } literal; -/** type of PropertyName. Can be integer, identifier of string literal. */ -typedef enum -{ - PN_NAME, - PN_STRING, - PN_NUM -} -property_name_type; - -/** Represents name of property. */ typedef struct { - /** Type of property name. */ - property_name_type type; + bool is_literal; - /** Value of property name. */ union { - /** Identifier. */ + void *none; + literal lit; const char *name; - /** Value of string literal. */ - const char *str; - /** Numeric value. */ - int num; } data; } -property_name; +operand; + +typedef operand property_name; + +static const operand +empty_operand = +{ + .is_literal = false, + .data.none = NULL +}; + +static inline bool +is_operand_empty (operand op) +{ + return op.is_literal == false && op.data.none == NULL; +} + +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 } } +}; + +static inline bool +is_operand_list_empty (operand_list list) +{ + return is_operand_empty (list.ops[0]); +} + +typedef operand_list array_literal; +typedef operand_list argument_list; + +typedef struct +{ + const char *name; + argument_list args; +} +call_expression; /** Represents a single property. */ typedef struct { /** Name of property. */ - property_name *name; + property_name name; /** Value of property. */ - struct assignment_expression *assign_expr; + operand value; +} +property; + +static const property empty_property = +{ + .name = { .is_literal = false, .data.none = NULL }, + .value = { .is_literal = false, .data.none = NULL } +}; + +static inline bool +is_property_empty (property prop) +{ + return is_operand_empty (prop.name) && is_operand_empty (prop.value); } -property_name_and_value; /** List of properties. Represents ObjectLiteral. */ -typedef struct property_name_and_value_list -{ - /** Current property. */ - property_name_and_value *nav; - - /** Next property. */ - struct property_name_and_value_list *next; -} -property_name_and_value_list; - -typedef property_name_and_value_list object_literal; - -/** Type of PrimaryExpression. Can be ThisLiteral, Identifier, Literal, ArrayLiteral, - ObjectLiteral or expression. */ -typedef enum -{ - PE_THIS, - PE_NAME, - PE_LITERAL, - PE_ARRAY, - PE_OBJECT, - PE_EXPR -} -primary_expression_type; - -/** PrimaryExpression. */ typedef struct { - /** Type of PrimaryExpression. */ - primary_expression_type type; + /** 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 }}} +}; + +static inline bool +is_property_list_empty (property_list list) +{ + return is_property_empty (list.props[0]); +} + +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. */ + const char *var; - /** Value of PrimaryExpression. */ union { - /** Used for ThisLiteral. Always NULL. */ void *none; - /** Identifier. */ - const char *name; - /** Literal. */ - literal *lit; - /** ArrayLiteral. */ - array_literal *array_lit; - /** ObjectLiteral. */ - object_literal *object_lit; - /** Expression. */ - expression *expr; - } - data; -} -primary_expression; - -/** Type of suffix of MemberExpression. Can be either index-like ([]) or property-like (.). */ -typedef enum -{ - MES_INDEX, - MES_PROPERTY -} -member_expression_suffix_type; - -/** Suffix of MemberExpression. */ -typedef struct -{ - /** Type of suffix. */ - member_expression_suffix_type type; - - /** Value of suffix. */ - union - { - /** Used by index-like suffix. */ - expression *index_expr; - /** Used by property-like suffix. */ - const char *name; - } - data; -} -member_expression_suffix; - -/** List of MemberExpression's suffixes. */ -typedef struct member_expression_suffix_list -{ - /** Current suffix. */ - member_expression_suffix *suffix; - - /** Next suffix. */ - struct member_expression_suffix_list *next; -} -member_expression_suffix_list; - -/** Represents MemberExpression Arguments grammar production. */ -typedef struct -{ - /** MemberExpression. */ - struct member_expression *member_expr; - /** Arguments. */ - argument_list *args; -} -member_expression_with_arguments; - -/** Types of MemberExpression. Can be PrimaryExpression, - FunctionExpression or MemberExpression Arguments. */ -typedef enum -{ - ME_PRIMARY, - ME_FUNCTION, - ME_ARGS -} -member_expression_type; - -/** Represents MemberExpression. */ -typedef struct member_expression -{ - /** Type of MemberExpression. */ - member_expression_type type; - - /** Value of MemberExpression. */ - union - { - /** PrimaryExpression. */ - primary_expression *primary_expr; - /** FunctionExpression. */ - function_expression *function_expr; - /** MemberExpression Arguments. */ - member_expression_with_arguments *args; - } - data; - - member_expression_suffix_list *suffix_list; -} -member_expression; - -/** Types of NewExpression. Can be either MemberExpression or NewExpression. */ -typedef enum -{ - NE_MEMBER, - NE_NEW -} -new_expression_type; - -/** Represents NewExpression. */ -typedef struct new_expression -{ - /** Type of NewExpression. */ - new_expression_type type; - - /** Value of NewExpression. */ - union - { - /** MemberExpression. */ - member_expression *member_expr; - /** NewExpression. */ - struct new_expression *new_expr; - } - data; -} -new_expression; - -/** Types of CallExpression' suffix. Can be Arguments, index-like access ([]) or - property-like access (.). */ -typedef enum -{ - CAS_ARGS, - CAS_INDEX, - CAS_PROPERTY -} -call_expression_suffix_type; - -/** Suffix of CallExpression. */ -typedef struct -{ - /** Type of suffix. */ - call_expression_suffix_type type; - - /** Value of suffix. */ - union - { - /** Arguments. */ - argument_list *args; - /** index-like access expression. */ - expression *index_expr; - /** Identifier of property. */ - const char *name; - } - data; -} -call_expression_suffix; - -/** List of CallExpression's suffixes. */ -typedef struct call_expression_suffix_list -{ - /** Current suffix. */ - call_expression_suffix *suffix; - - /** Next suffix. */ - struct call_expression_suffix_list *next; -} -call_expression_suffix_list; - -/** CallExpression. */ -typedef struct -{ - /** Callee. Cannot be NULL. */ - member_expression *member_expr; - /** List of arguments. Can be NULL. */ - argument_list *args; - /** Suffixes of CallExpression. Can be NULL. */ - call_expression_suffix_list *suffix_list; -} -call_expression; - -/** Types of LeftHandSideExpression. Can be either CallExpression or NewExpression. */ -typedef enum -{ - LHSE_CALL, - LHSE_NEW -} -left_hand_side_expression_type; - -/** LeftHandSideExpression. */ -typedef struct -{ - /** Type of LeftHandSideExpression. */ - left_hand_side_expression_type type; - - /** Value of LeftHandSideExpression. */ - union - { - /** Value of CallExpression. */ - call_expression *call_expr; - /** Value of NewExpression. */ - new_expression *new_expr; - } - data; -} -left_hand_side_expression; - -/** Type of PostfixExpression. Unlike ECMA, it can contain no postfix operator in addition to - increment and decrement. */ -typedef enum -{ - PE_NONE, - PE_INCREMENT, - PE_DECREMENT -} -postfix_expression_type; - -/** PostfixExpression. */ -typedef struct -{ - /** Type of PostfixExpression. */ - postfix_expression_type type; - /** LeftHandSideExpression. */ - left_hand_side_expression *expr; -} -postfix_expression; - -/** Types of UnaryExpression. Can be PostfixExpression, delete UnaryExpression, - void UnaryExpression, typeof UnaryExpression, ++ UnaryExpression, -- UnaryExpression, - + UnaryExpression, - UnaryExpression, ~ UnaryExpression, ! UnaryExpression. */ -typedef enum -{ - UE_POSTFIX, - UE_DELETE, - UE_VOID, - UE_TYPEOF, - UE_INCREMENT, - UE_DECREMENT, - UE_PLUS, - UE_MINUS, - UE_COMPL, - UE_NOT -} -unary_expression_type; - -/** UnaryExpression. */ -typedef struct unary_expression -{ - /** Type of UnaryExpression. */ - unary_expression_type type; - - /** Data of UnaryExpression. */ - union - { - /** PostfixExpression. Exists only when type of UE_POSTFIX. */ - postfix_expression *postfix_expr; - /** UnaryExpression after an operator. Exists otherwise. */ - struct unary_expression *unary_expr; - } - data; -} -unary_expression; - -/** Type of MultiplicativeExpression. In addition to ECMA if there is only one operand, - we use ME_NONE. */ -typedef enum -{ - ME_NONE, - ME_MULT, - ME_DIV, - ME_MOD -} -multiplicative_expression_type; - -/** List of MultiplicativeExpressions. It can contain 1..n operands. */ -typedef struct multiplicative_expression_list -{ - /** Type of current MultiplicativeExpression. */ - multiplicative_expression_type type; - /** Current operand. */ - unary_expression *unary_expr; - - /** Next operand. */ - struct multiplicative_expression_list *next; -} -multiplicative_expression_list; - -typedef enum -{ - AE_NONE, - AE_PLUS, - AE_MINUS -} -additive_expression_type; - -typedef struct additive_expression_list -{ - additive_expression_type type; - multiplicative_expression_list *mult_expr; - - struct additive_expression_list *next; -} -additive_expression_list; - -typedef enum -{ - SE_NONE, - SE_LSHIFT, - SE_RSHIFT, - SE_RSHIFT_EX -} -shift_expression_type; - -typedef struct shift_expression_list -{ - shift_expression_type type; - additive_expression_list *add_expr; - - struct shift_expression_list *next; -} -shift_expression_list; - -typedef enum -{ - RE_NONE, - RE_LESS, - RE_GREATER, - RE_LESS_EQ, - RE_GREATER_EQ, - RE_INSTANCEOF, - RE_IN -} -relational_expression_type; - -typedef struct relational_expression_list -{ - relational_expression_type type; - shift_expression_list *shift_expr; - - struct relational_expression_list *next; -} -relational_expression_list; - -typedef enum -{ - EE_NONE, - EE_DOUBLE_EQ, - EE_NOT_EQ, - EE_TRIPLE_EQ, - EE_NOT_DOUBLE_EQ -} -equality_expression_type; - -typedef struct equality_expression_list -{ - equality_expression_type type; - relational_expression_list *rel_expr; - - struct equality_expression_list *next; -} -equality_expression_list; - -typedef struct bitwise_and_expression_list -{ - equality_expression_list *eq_expr; - - struct bitwise_and_expression_list *next; -} -bitwise_and_expression_list; - -typedef struct bitwise_xor_expression_list -{ - bitwise_and_expression_list *and_expr; - - struct bitwise_xor_expression_list *next; -} -bitwise_xor_expression_list; - -typedef struct bitwise_or_expression_list -{ - bitwise_xor_expression_list *xor_expr; - - struct bitwise_or_expression_list *next; -} -bitwise_or_expression_list; - -typedef struct logical_and_expression_list -{ - bitwise_or_expression_list *or_expr; - - struct logical_and_expression_list *next; -} -logical_and_expression_list; - -typedef struct logical_or_expression_list -{ - logical_and_expression_list *and_expr; - - struct logical_or_expression_list *next; -} -logical_or_expression_list; - -typedef struct -{ - logical_or_expression_list *or_expr; - struct assignment_expression *then_expr, *else_expr; -} -conditional_expression; - -typedef enum -{ - AE_COND, - AE_EQ, - AE_MULT_EQ, - AE_DIV_EQ, - AE_MOD_EQ, - AE_PLUS_EQ, - AE_MINUS_EQ, - AE_LSHIFT_EQ, - AE_RSHIFT_EQ, - AE_RSHIFT_EX_EQ, - AE_AND_EQ, - AE_OR_EQ, - AE_XOR_EQ -} -assignment_expression_type; - -typedef struct -{ - left_hand_side_expression *left_hand_expr; - struct assignment_expression *assign_expr; -} -left_hand_and_assignment_expression; - -typedef struct assignment_expression -{ - assignment_expression_type type; - - union - { - conditional_expression *cond_expr; - left_hand_and_assignment_expression s; + 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 +}; + +static inline bool +is_expression_empty (assignment_expression expr) +{ + return expr.oper == AO_NONE && expr.type == ET_NONE && expr.data.none == NULL; +} + +/** 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 { const char *name; - - assignment_expression *ass_expr; + assignment_expression assign_expr; } variable_declaration; -typedef struct variable_declaration_list +static const variable_declaration +empty_variable_declaration = { - variable_declaration *var_decl; + .name = NULL, + .assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL } +}; - struct variable_declaration_list *next; +static inline bool +is_variable_declaration_empty (variable_declaration var_decl) +{ + return var_decl.name == NULL && is_expression_empty (var_decl.assign_expr); +} + +typedef struct +{ + variable_declaration decls[MAX_DECLS]; } variable_declaration_list; @@ -635,8 +356,8 @@ typedef struct union { - expression *expr; - variable_declaration_list *decl_list; + expression expr; + variable_declaration_list decl_list; } data; } @@ -644,8 +365,8 @@ for_statement_initialiser_part; typedef struct { - for_statement_initialiser_part *init; - expression *limit, *incr; + for_statement_initialiser_part init; + assignment_expression limit, incr; } for_statement; @@ -655,8 +376,8 @@ typedef struct union { - left_hand_side_expression *left_hand_expr; - variable_declaration *decl; + assignment_expression left_hand_expr; + variable_declaration decl; } data; } @@ -664,8 +385,8 @@ for_in_statement_initializer_part; typedef struct { - for_in_statement_initializer_part *init; - expression *list_expr; + for_in_statement_initializer_part init; + expression list_expr; } for_in_statement; @@ -675,8 +396,8 @@ typedef struct union { - for_statement *for_stmt; - for_in_statement *for_in_stmt; + for_statement for_stmt; + for_in_statement for_in_stmt; } data; } @@ -684,6 +405,7 @@ for_or_for_in_statement; typedef enum { + STMT_NULL, STMT_BLOCK_START, STMT_BLOCK_END, STMT_VARIABLE, @@ -722,17 +444,30 @@ typedef struct statement union { void *none; - variable_declaration_list *var_stmt; - expression *expr; - for_or_for_in_statement *for_stmt; + variable_declaration_list var_stmt; + expression expr; + for_or_for_in_statement for_stmt; const char *name; - function_declaration *fun_decl; + function_declaration fun_decl; } data; } statement; +static const statement +null_statement = +{ + .type = STMT_NULL, + .data.none = NULL +}; + +static inline bool +is_statement_null (statement stmt) +{ + return stmt.type == STMT_NULL && stmt.data.none == NULL; +} + void parser_init (); -statement *parser_parse_statement (); +statement parser_parse_statement (); #endif diff --git a/src/main.c b/src/main.c index c04fcb64e..092390120 100644 --- a/src/main.c +++ b/src/main.c @@ -13,9 +13,11 @@ * limitations under the License. */ -#include -#include -#include +#ifdef JERRY_NDEBUG +# include +# include +# include +#endif #include "error.h" @@ -40,7 +42,9 @@ main (int argc, char **argv) bool dump_tokens = false; bool dump_ast = true; const char *file_name = NULL; +#ifdef JERRY_NDEBUG FILE *file = NULL; +#endif mem_Init (); ctx_Init (); @@ -64,16 +68,20 @@ main (int argc, char **argv) if (dump_tokens && dump_ast) fatal (ERR_SEVERAL_FILES); +#ifdef JERRY_NDEBUG file = fopen (file_name, "r"); if (file == NULL) { fatal (ERR_IO); } +#endif + + // FIXME: Call parser //gen_bytecode (generated_source); - gen_bytecode (); - run_int (); + //gen_bytecode (); + //run_int (); #ifdef __TARGET_MCU fake_exit (); diff --git a/src/pretty-printer.c b/src/pretty-printer.c index 23062ba71..77ed9dd2b 100644 --- a/src/pretty-printer.c +++ b/src/pretty-printer.c @@ -15,7 +15,6 @@ #include "pretty-printer.h" #include "error.h" -#include "globals.h" static int intendation; static bool was_function_expression; @@ -23,10 +22,6 @@ static bool was_subexpression; static statement_type prev_stmt; -static void pp_expression (expression *); -static void pp_assignment_expression (assignment_expression *); -static void pp_member_expression (member_expression *); - void pp_reset () { @@ -39,244 +34,244 @@ pp_token (token tok) { switch (tok.type) { - case TOK_NAME: - printf ("IDENTIFIER (%s)\n", tok.data.name); - break; + case TOK_NAME: + printf ("IDENTIFIER (%s)\n", tok.data.name); + break; - case TOK_STRING: - printf ("STRING (%s)\n", tok.data.str); - break; + case TOK_STRING: + printf ("STRING (%s)\n", tok.data.str); + break; - case TOK_KEYWORD: - pp_keyword (tok.data.kw); - break; + case TOK_KEYWORD: + pp_keyword (tok.data.kw); + break; - case TOK_INT: - printf ("INTEGER (%d)\n", tok.data.num); - break; + case TOK_INT: + printf ("INTEGER (%d)\n", tok.data.num); + break; - case TOK_FLOAT: - printf ("FLOAT (%f)\n", tok.data.fp_num); - break; + case TOK_FLOAT: + printf ("FLOAT (%f)\n", tok.data.fp_num); + break; - case TOK_NULL: - printf ("NULL (null)\n"); - break; + case TOK_NULL: + printf ("NULL (null)\n"); + break; - case TOK_BOOL: - if (tok.data.is_true) - printf ("BOOL (true)\n"); - else - printf ("BOOL (false)\n"); - break; + case TOK_BOOL: + if (tok.data.is_true) + printf ("BOOL (true)\n"); + else + printf ("BOOL (false)\n"); + break; - case TOK_OPEN_BRACE: - printf ("PUNC ({)\n"); - break; + case TOK_OPEN_BRACE: + printf ("PUNC ({)\n"); + break; - case TOK_CLOSE_BRACE: - printf ("PUNC (})\n"); - break; + case TOK_CLOSE_BRACE: + printf ("PUNC (})\n"); + break; - case TOK_OPEN_PAREN: - printf ("PUNC (()\n"); - break; + case TOK_OPEN_PAREN: + printf ("PUNC (()\n"); + break; - case TOK_CLOSE_PAREN: - printf ("PUNC ())\n"); - break; + case TOK_CLOSE_PAREN: + printf ("PUNC ())\n"); + break; - case TOK_OPEN_SQUARE: - printf ("PUNC ([)\n"); - break; + case TOK_OPEN_SQUARE: + printf ("PUNC ([)\n"); + break; - case TOK_CLOSE_SQUARE: - printf ("PUNC (])\n"); - break; + case TOK_CLOSE_SQUARE: + printf ("PUNC (])\n"); + break; - case TOK_DOT: - printf ("PUNC (.)\n"); - break; + case TOK_DOT: + printf ("PUNC (.)\n"); + break; - case TOK_SEMICOLON: - printf ("PUNC (;)\n"); - break; + case TOK_SEMICOLON: + printf ("PUNC (;)\n"); + break; - case TOK_COMMA: - printf ("PUNC (,)\n"); - break; + case TOK_COMMA: + printf ("PUNC (,)\n"); + break; - case TOK_LESS: - printf ("PUNC (<)\n"); - break; + case TOK_LESS: + printf ("PUNC (<)\n"); + break; - case TOK_GREATER: - printf ("PUNC (>)\n"); - break; + case TOK_GREATER: + printf ("PUNC (>)\n"); + break; - case TOK_LESS_EQ: - printf ("PUNC (<=)\n"); - break; + case TOK_LESS_EQ: + printf ("PUNC (<=)\n"); + break; - case TOK_GREATER_EQ: - printf ("PUNC (>=)\n"); - break; + case TOK_GREATER_EQ: + printf ("PUNC (>=)\n"); + break; - case TOK_DOUBLE_EQ: - printf ("PUNC (==)\n"); - break; + case TOK_DOUBLE_EQ: + printf ("PUNC (==)\n"); + break; - case TOK_NOT_EQ: - printf ("PUNC (!=)\n"); - break; + case TOK_NOT_EQ: + printf ("PUNC (!=)\n"); + break; - case TOK_TRIPLE_EQ: - printf ("PUNC (===)\n"); - break; + case TOK_TRIPLE_EQ: + printf ("PUNC (===)\n"); + break; - case TOK_NOT_DOUBLE_EQ: - printf ("PUNC (!==)\n"); - break; + case TOK_NOT_DOUBLE_EQ: + printf ("PUNC (!==)\n"); + break; - case TOK_PLUS: - printf ("PUNC (+)\n"); - break; + case TOK_PLUS: + printf ("PUNC (+)\n"); + break; - case TOK_MINUS: - printf ("PUNC (-)\n"); - break; + case TOK_MINUS: + printf ("PUNC (-)\n"); + break; - case TOK_MULT: - printf ("PUNC (*)\n"); - break; + case TOK_MULT: + printf ("PUNC (*)\n"); + break; - case TOK_MOD: - printf ("PUNC (%%)\n"); - break; + case TOK_MOD: + printf ("PUNC (%%)\n"); + break; - case TOK_DOUBLE_PLUS: - printf ("PUNC (++)\n"); - break; + case TOK_DOUBLE_PLUS: + printf ("PUNC (++)\n"); + break; - case TOK_DOUBLE_MINUS: - printf ("PUNC (--)\n"); - break; + case TOK_DOUBLE_MINUS: + printf ("PUNC (--)\n"); + break; - case TOK_LSHIFT: - printf ("PUNC (<<)\n"); - break; + case TOK_LSHIFT: + printf ("PUNC (<<)\n"); + break; - case TOK_RSHIFT: - printf ("PUNC (>>)\n"); - break; + case TOK_RSHIFT: + printf ("PUNC (>>)\n"); + break; - case TOK_RSHIFT_EX: - printf ("PUNC (>>>)\n"); - break; + case TOK_RSHIFT_EX: + printf ("PUNC (>>>)\n"); + break; - case TOK_AND: - printf ("PUNC (&)\n"); - break; + case TOK_AND: + printf ("PUNC (&)\n"); + break; - case TOK_OR: - printf ("PUNC (|)\n"); - break; + case TOK_OR: + printf ("PUNC (|)\n"); + break; - case TOK_XOR: - printf ("PUNC (^)\n"); - break; + case TOK_XOR: + printf ("PUNC (^)\n"); + break; - case TOK_NOT: - printf ("PUNC (!)\n"); - break; + case TOK_NOT: + printf ("PUNC (!)\n"); + break; - case TOK_COMPL: - printf ("PUNC (~)\n"); - break; + case TOK_COMPL: + printf ("PUNC (~)\n"); + break; - case TOK_DOUBLE_AND: - printf ("PUNC (&&)\n"); - break; + case TOK_DOUBLE_AND: + printf ("PUNC (&&)\n"); + break; - case TOK_DOUBLE_OR: - printf ("PUNC (||)\n"); - break; + case TOK_DOUBLE_OR: + printf ("PUNC (||)\n"); + break; - case TOK_QUERY: - printf ("PUNC (?)\n"); - break; + case TOK_QUERY: + printf ("PUNC (?)\n"); + break; - case TOK_COLON: - printf ("PUNC (:)\n"); - break; + case TOK_COLON: + printf ("PUNC (:)\n"); + break; - case TOK_EQ: - printf ("PUNC (=)\n"); - break; + case TOK_EQ: + printf ("PUNC (=)\n"); + break; - case TOK_PLUS_EQ: - printf ("PUNC (+=)\n"); - break; + case TOK_PLUS_EQ: + printf ("PUNC (+=)\n"); + break; - case TOK_MINUS_EQ: - printf ("PUNC (-=)\n"); - break; + case TOK_MINUS_EQ: + printf ("PUNC (-=)\n"); + break; - case TOK_MULT_EQ: - printf ("PUNC (*=)\n"); - break; + case TOK_MULT_EQ: + printf ("PUNC (*=)\n"); + break; - case TOK_MOD_EQ: - printf ("PUNC (%%=)\n"); - break; + case TOK_MOD_EQ: + printf ("PUNC (%%=)\n"); + break; - case TOK_LSHIFT_EQ: - printf ("PUNC (<<=)\n"); - break; + case TOK_LSHIFT_EQ: + printf ("PUNC (<<=)\n"); + break; - case TOK_RSHIFT_EQ: - printf ("PUNC (>>=)\n"); - break; + case TOK_RSHIFT_EQ: + printf ("PUNC (>>=)\n"); + break; - case TOK_RSHIFT_EX_EQ: - printf ("PUNC (>>>=)\n"); - break; + case TOK_RSHIFT_EX_EQ: + printf ("PUNC (>>>=)\n"); + break; - case TOK_AND_EQ: - printf ("PUNC (&=)\n"); - break; + case TOK_AND_EQ: + printf ("PUNC (&=)\n"); + break; - case TOK_OR_EQ: - printf ("PUNC (|=)\n"); - break; + case TOK_OR_EQ: + printf ("PUNC (|=)\n"); + break; - case TOK_XOR_EQ: - printf ("PUNC (^=)\n"); - break; + case TOK_XOR_EQ: + printf ("PUNC (^=)\n"); + break; - case TOK_DIV: - printf ("PUNC (/)\n"); - break; + case TOK_DIV: + printf ("PUNC (/)\n"); + break; - case TOK_DIV_EQ: - printf ("PUNC (/=)\n"); - break; + case TOK_DIV_EQ: + printf ("PUNC (/=)\n"); + break; - case TOK_NEWLINE: - printf ("NEWLINE\n"); - break; + case TOK_NEWLINE: + printf ("NEWLINE\n"); + break; - default: - unreachable (); + default: + JERRY_UNREACHABLE (); } } @@ -285,9 +280,9 @@ void pp_keyword (keyword kw) { switch (kw) - { + { case KW_NONE: - unreachable (); + JERRY_UNREACHABLE (); break; case KW_RESERVED: @@ -403,9 +398,9 @@ pp_keyword (keyword kw) break; default: - unreachable (); + JERRY_UNREACHABLE (); - } + } } static void @@ -416,794 +411,426 @@ intend () } static void -pp_formal_parameter_list (formal_parameter_list *param_list) +pp_formal_parameter_list (formal_parameter_list param_list) { - formal_parameter_list *list = param_list; - assert (param_list); - while (list) + int i; + + for (i = 0; i < MAX_PARAMS; i++) { - printf ("%s", list->name); - if (list->next) + if (param_list.names[i] == NULL) + break; + if (i != 0) printf (", "); - list = list->next; + printf ("%s", param_list.names[i]); } } static void -pp_function_declaration (function_declaration *func_decl) +pp_function_declaration (function_declaration func_decl) { - assert (func_decl); printf ("function "); - if (func_decl->name) - printf ("%s ", func_decl->name); + if (func_decl.name) + printf ("%s ", func_decl.name); putchar ('('); - if (func_decl->params) - pp_formal_parameter_list (func_decl->params); + pp_formal_parameter_list (func_decl.params); printf (") "); was_function_expression = true; } static void -pp_literal (literal *lit) +pp_literal (literal lit) { - assert (lit); - switch (lit->type) - { + switch (lit.type) + { case LIT_NULL: printf ("null"); break; case LIT_BOOL: - printf ("%s", lit->data.is_true ? "true" : "false"); + printf ("%s", lit.data.is_true ? "true" : "false"); break; case LIT_INT: - printf ("%d", lit->data.num); + printf ("%d", lit.data.num); break; case LIT_STR: - printf ("\"%s\"", lit->data.str); + printf ("\"%s\"", lit.data.str); break; default: - unreachable (); - } + JERRY_UNREACHABLE (); + } } static void -pp_property_name (property_name *name) +pp_operand (operand op) { - assert (name); - switch (name->type) + JERRY_ASSERT (!is_operand_empty (op)); + if (op.is_literal) + pp_literal (op.data.lit); + else + printf ("%s", op.data.name); +} + +static void +pp_operand_list (operand_list list) +{ + int i; + + for (i = 0; i < MAX_PARAMS; i++) { - case PN_NAME: - printf ("%s", name->data.name); - break; - - case PN_STRING: - printf ("%s", name->data.str); - break; - - case PN_NUM: - printf ("%d", name->data.num); - break; - - default: - unreachable (); + if (is_operand_empty (list.ops[i])) + break; + if (i != 0) + printf (", "); + pp_operand (list.ops[i]); } } static void -pp_property_name_and_value (property_name_and_value *nav) +pp_property (property prop) { - assert (nav); - pp_property_name (nav->name); + JERRY_ASSERT (!is_property_empty (prop)); + pp_operand (prop.name); printf (" : "); - pp_assignment_expression (nav->assign_expr); + pp_operand (prop.value); } static void -pp_property_name_and_value_list (property_name_and_value_list *nav_list) +pp_property_list (property_list prop_list) { - property_name_and_value_list *list = nav_list; - assert (nav_list); - while (list) + int i; + + for (i = 0; i < MAX_PROPERTIES; i++) { - pp_property_name_and_value (list->nav); - if (list->next) + if (is_property_empty (prop_list.props[i])) + break; + if (i != 0) printf (", "); - list = list->next; + pp_property (prop_list.props[i]); } } static void -pp_primary_expression (primary_expression *primary_expr) +pp_call_expression (call_expression expr) { - assert (primary_expr); - switch (primary_expr->type) - { - case PE_THIS: - printf ("this"); - break; - - case PE_NAME: - printf ("%s", primary_expr->data.name); - break; - - case PE_LITERAL: - pp_literal (primary_expr->data.lit); - break; - - case PE_ARRAY: - putchar ('['); - if (primary_expr->data.array_lit) - pp_expression (primary_expr->data.array_lit); - putchar (']'); - break; - - case PE_OBJECT: - putchar ('{'); - if (primary_expr->data.object_lit) - pp_property_name_and_value_list (primary_expr->data.object_lit); - putchar ('}'); - break; - - case PE_EXPR: - putchar ('('); - if (primary_expr->data.expr) - pp_expression (primary_expr->data.expr); - was_subexpression = true; - break; - - default: - unreachable (); - } + JERRY_ASSERT (expr.name); + printf ("%s (", expr.name); + pp_operand_list (expr.args); + printf (")\n"); } static void -pp_member_expression_with_arguments (member_expression_with_arguments *member_expr) +dump_two_operands (operand_pair pair, const char *operation) { - assert (member_expr); - printf ("new "); - pp_member_expression (member_expr->member_expr); - if (member_expr->args) - { - putchar (' '); - pp_expression (member_expr->args); - } + pp_operand (pair.op1); + printf ("%s", operation); + pp_operand (pair.op2); + putchar ('\n'); } static void -pp_member_expression_suffix (member_expression_suffix *suffix) +dump_unary (operand op, const char *operation) { - assert (suffix); - switch (suffix->type) - { - case MES_INDEX: - putchar ('['); - pp_expression (suffix->data.index_expr); - putchar (']'); - break; - - case MES_PROPERTY: - putchar ('.'); - printf ("%s", suffix->data.name); - break; - - default: - unreachable (); - } -} - -static void -pp_member_expression_suffix_list (member_expression_suffix_list *suffix_list) -{ - member_expression_suffix_list *list = suffix_list; - assert (suffix_list); - while (list) - { - pp_member_expression_suffix (list->suffix); - list = list->next; - } + printf ("%s", operation); + pp_operand (op); + putchar ('\n'); } static void -pp_member_expression (member_expression *member_expr) +dump_postfix (operand op, const char *operation) { - assert (member_expr); - switch (member_expr->type) - { - case ME_PRIMARY: - pp_primary_expression (member_expr->data.primary_expr); - break; - - case ME_FUNCTION: - pp_function_declaration (member_expr->data.function_expr); - break; - - case ME_ARGS: - pp_member_expression_with_arguments (member_expr->data.args); - break; - - default: - unreachable (); - } - if (member_expr->suffix_list) - pp_member_expression_suffix_list (member_expr->suffix_list); + pp_operand (op); + printf ("%s\n", operation); } static void -pp_call_expression_suffix (call_expression_suffix *suffix) +pp_assignment_expression (assignment_expression expr) { - assert (suffix); - switch (suffix->type) - { - case CAS_ARGS: - putchar ('('); - pp_expression (suffix->data.args); - putchar (')'); + if (expr.var) + printf ("%s", expr.var); + + switch (expr.oper) + { + case AO_NONE: break; - case CAS_INDEX: - putchar ('['); - pp_expression (suffix->data.index_expr); - putchar (']'); - break; - - case CAS_PROPERTY: - putchar ('.'); - printf ("%s", suffix->data.name); - break; - - default: - unreachable (); - } -} - -static void -pp_call_expression_suffix_list (call_expression_suffix_list *suffix_list) -{ - call_expression_suffix_list *list = suffix_list; - assert (suffix_list); - while (list) - { - pp_call_expression_suffix (list->suffix); - list = list->next; - } -} - -static void -pp_call_expression (call_expression *call_expr) -{ - assert (call_expr); - pp_member_expression (call_expr->member_expr); - printf (" ("); - if (call_expr->args) - pp_expression (call_expr->args); - printf (")"); - if (call_expr->suffix_list) - pp_call_expression_suffix_list (call_expr->suffix_list); -} - -static void -pp_new_expression (new_expression *new_expr) -{ - assert (new_expr); - switch (new_expr->type) - { - case NE_MEMBER: - pp_member_expression (new_expr->data.member_expr); - break; - - case NE_NEW: - printf ("new "); - pp_new_expression (new_expr->data.new_expr); - break; - - unreachable (); - } -} - -static void -pp_left_hand_side_expression (left_hand_side_expression *left_expr) -{ - assert (left_expr); - switch (left_expr->type) - { - case LHSE_CALL: - pp_call_expression (left_expr->data.call_expr); - break; - - case LHSE_NEW: - pp_new_expression (left_expr->data.new_expr); - break; - - default: - unreachable (); - } -} - -static void -pp_postfix_expression (postfix_expression *postfix_expr) -{ - assert (postfix_expr); - pp_left_hand_side_expression (postfix_expr->expr); - switch (postfix_expr->type) - { - case PE_INCREMENT: - printf ("++"); - break; - - case PE_DECREMENT: - printf ("--"); - break; - - default: - break; - } -} - -static void -pp_unary_expression (unary_expression *unary_expr) -{ - assert (unary_expr); - if (unary_expr->type != UE_POSTFIX) - putchar ('('); - switch (unary_expr->type) - { - case UE_POSTFIX: - pp_postfix_expression (unary_expr->data.postfix_expr); - break; - - case UE_DELETE: - printf ("delete "); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_VOID: - printf ("void "); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_TYPEOF: - printf ("typeof "); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_INCREMENT: - printf ("++"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_DECREMENT: - printf ("--"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_PLUS: - printf ("+"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_MINUS: - printf ("-"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_COMPL: - printf ("~"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - case UE_NOT: - printf ("!"); - pp_unary_expression (unary_expr->data.unary_expr); - break; - - default: - unreachable (); - } - if (unary_expr->type != UE_POSTFIX) - putchar (')'); -} - -static void -pp_multiplicative_expression_list (multiplicative_expression_list *expr_list) -{ - multiplicative_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_unary_expression (list->unary_expr); - if (list->next) - { - switch (list->type) - { - case ME_MULT: - printf (" * "); - break; - - case ME_DIV: - printf (" / "); - break; - - case ME_MOD: - printf (" %% "); - break; - - default: - unreachable (); - } - } - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_additive_expression_list (additive_expression_list *expr_list) -{ - additive_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_multiplicative_expression_list (list->mult_expr); - if (list->next) - { - switch (list->type) - { - case AE_PLUS: - printf (" + "); - break; - - case AE_MINUS: - printf (" - "); - break; - - default: - unreachable (); - } - } - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_shift_expression_list (shift_expression_list *expr_list) -{ - shift_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_additive_expression_list (list->add_expr); - if (list->next) - { - switch (list->type) - { - case SE_LSHIFT: - printf (" << "); - break; - - case SE_RSHIFT: - printf (" >> "); - break; - - case SE_RSHIFT_EX: - printf (" >>> "); - break; - - default: - unreachable (); - } - } - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_relational_expression_list (relational_expression_list *expr_list) -{ - relational_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_shift_expression_list (list->shift_expr); - if (list->next) - { - switch (list->type) - { - case RE_LESS: - printf (" < "); - break; - - case RE_GREATER: - printf (" > "); - break; - - case RE_LESS_EQ: - printf (" <= "); - break; - - case RE_GREATER_EQ: - printf (" >= "); - break; - - case RE_INSTANCEOF: - printf (" instanceof "); - break; - - case RE_IN: - printf (" in "); - break; - - default: - unreachable (); - } - } - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_equality_expression_list (equality_expression_list *expr_list) -{ - equality_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_relational_expression_list (list->rel_expr); - if (list->next) - { - switch (list->type) - { - case EE_DOUBLE_EQ: - printf (" == "); - break; - - case EE_NOT_EQ: - printf (" != "); - break; - - case EE_TRIPLE_EQ: - printf (" === "); - break; - - case EE_NOT_DOUBLE_EQ: - printf (" !== "); - break; - - default: - unreachable (); - } - } - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_bitwise_and_expression_list (bitwise_and_expression_list *expr_list) -{ - bitwise_and_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_equality_expression_list (list->eq_expr); - if (list->next) - printf (" & "); - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_bitwise_xor_expression_list (bitwise_xor_expression_list *expr_list) -{ - bitwise_xor_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_bitwise_and_expression_list (list->and_expr); - if (list->next) - printf (" ^ "); - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_bitwise_or_expression_list (bitwise_or_expression_list *expr_list) -{ - bitwise_or_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_bitwise_xor_expression_list (list->xor_expr); - if (list->next) - printf (" | "); - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_logical_and_expression_list (logical_and_expression_list *expr_list) -{ - logical_and_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_bitwise_or_expression_list (list->or_expr); - if (list->next) - printf (" && "); - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_logical_or_expression_list (logical_or_expression_list *expr_list) -{ - logical_or_expression_list *list = expr_list; - assert (expr_list); - if (expr_list->next) - putchar ('('); - while (list) - { - pp_logical_and_expression_list (list->and_expr); - if (list->next) - printf (" || "); - list = list->next; - } - if (expr_list->next) - putchar (')'); -} - -static void -pp_conditional_expression (conditional_expression *cond_expr) -{ - assert (cond_expr); - pp_logical_or_expression_list (cond_expr->or_expr); - if (cond_expr->then_expr) - { - printf (" ? "); - pp_assignment_expression (cond_expr->then_expr); - } - if (cond_expr->else_expr) - { - printf (" : "); - pp_assignment_expression (cond_expr->else_expr); - } -} - -static void -pp_assignment_expression (assignment_expression *assign_expr) -{ - assert (assign_expr); - switch (assign_expr->type) - { - case AE_COND: - pp_conditional_expression (assign_expr->data.cond_expr); - return; - - case AE_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_EQ: printf (" = "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_MULT_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_MULT_EQ: printf (" *= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_DIV_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); - printf (" /= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + case AO_DIV_EQ: + printf (" ?= "); + break; - case AE_MOD_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_MOD_EQ: printf (" %%= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_PLUS_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_PLUS_EQ: printf (" += "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_MINUS_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_MINUS_EQ: printf (" -= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_LSHIFT_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_LSHIFT_EQ: printf (" <<= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_RSHIFT_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_RSHIFT_EQ: printf (" >>= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_RSHIFT_EX_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_RSHIFT_EX_EQ: printf (" >>>= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_AND_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_AND_EQ: printf (" &= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; + break; - case AE_OR_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); - printf (" |= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); - return; - - case AE_XOR_EQ: - pp_left_hand_side_expression (assign_expr->data.s.left_hand_expr); + case AO_XOR_EQ: printf (" ^= "); - pp_assignment_expression (assign_expr->data.s.assign_expr); + break; + + case AO_OR_EQ: + printf (" |= "); + break; + + default: + JERRY_UNREACHABLE (); + } + + switch (expr.type) + { + case ET_NONE: + pp_operand (expr.data.ops.op1); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_LOGICAL_OR: + dump_two_operands (expr.data.ops, " || "); + return; + + case ET_LOGICAL_AND: + dump_two_operands (expr.data.ops, " && "); + return; + + case ET_BITWISE_OR: + dump_two_operands (expr.data.ops, " | "); + return; + + case ET_BITWISE_XOR: + dump_two_operands (expr.data.ops, " ^ "); + return; + + case ET_BITWISE_AND: + dump_two_operands (expr.data.ops, " & "); + return; + + case ET_DOUBLE_EQ: + dump_two_operands (expr.data.ops, " == "); + return; + + case ET_NOT_EQ: + dump_two_operands (expr.data.ops, " != "); + return; + + case ET_TRIPLE_EQ: + dump_two_operands (expr.data.ops, " === "); + return; + + case ET_NOT_DOUBLE_EQ: + dump_two_operands (expr.data.ops, " !== "); + return; + + case ET_LESS: + dump_two_operands (expr.data.ops, " < "); + return; + + case ET_GREATER: + dump_two_operands (expr.data.ops, " > "); + return; + + case ET_LESS_EQ: + dump_two_operands (expr.data.ops, " <= "); + return; + + case ET_GREATER_EQ: + dump_two_operands (expr.data.ops, " <= "); + return; + + case ET_INSTANCEOF: + dump_two_operands (expr.data.ops, " instanceof "); + return; + + case ET_IN: + dump_two_operands (expr.data.ops, " in "); + return; + + case ET_LSHIFT: + dump_two_operands (expr.data.ops, " << "); + return; + + case ET_RSHIFT: + dump_two_operands (expr.data.ops, " >> "); + return; + + case ET_RSHIFT_EX: + dump_two_operands (expr.data.ops, " >>> "); + return; + + case ET_PLUS: + dump_two_operands (expr.data.ops, " + "); + return; + + case ET_MINUS: + dump_two_operands (expr.data.ops, " - "); + return; + + case ET_MULT: + dump_two_operands (expr.data.ops, " * "); + return; + + case ET_DIV: + dump_two_operands (expr.data.ops, " / "); + return; + + case ET_MOD: + dump_two_operands (expr.data.ops, " %% "); + return; + + case ET_UNARY_DELETE: + dump_unary (expr.data.ops.op1, "delete "); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_VOID: + dump_unary (expr.data.ops.op1, "void "); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_TYPEOF: + dump_unary (expr.data.ops.op1, "typeof "); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_INCREMENT: + dump_unary (expr.data.ops.op1, "++"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_DECREMENT: + dump_unary (expr.data.ops.op1, "--"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_PLUS: + dump_unary (expr.data.ops.op1, "+"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_MINUS: + dump_unary (expr.data.ops.op1, "-"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_COMPL: + dump_unary (expr.data.ops.op1, "~"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_UNARY_NOT: + dump_unary (expr.data.ops.op1, "!"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_POSTFIX_INCREMENT: + dump_postfix (expr.data.ops.op1, "++"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_POSTFIX_DECREMENT: + dump_postfix (expr.data.ops.op1, "--"); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + return; + + case ET_CALL: + pp_call_expression (expr.data.call_expr); + return; + + case ET_NEW: + printf ("new "); + pp_operand (expr.data.ops.op1); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + putchar ('\n'); + return; + + case ET_INDEX: + pp_operand (expr.data.ops.op1); + putchar ('.'); + pp_operand (expr.data.ops.op2); + putchar ('\n'); + return; + + case ET_PROP_REF: + pp_operand (expr.data.ops.op1); + putchar ('['); + pp_operand (expr.data.ops.op2); + printf ("]\n"); + return; + + case ET_OBJECT: + putchar ('{'); + pp_property_list (expr.data.obj_lit); + printf ("}\n"); + return; + + case ET_FUNCTION: + pp_function_declaration (expr.data.func_expr); + return; + + case ET_ARRAY: + putchar ('['); + pp_operand_list (expr.data.arr_lit); + printf ("]\n"); + return; + + case ET_SUBEXPRESSION: + putchar ('('); + return; + + case ET_LITERAL: + case ET_IDENTIFIER: + pp_operand (expr.data.ops.op1); + JERRY_ASSERT (is_operand_empty (expr.data.ops.op2)); + putchar ('\n'); return; default: - unreachable (); - } + JERRY_UNREACHABLE (); + } } static void -pp_expression (expression_list *expr_list) +pp_expression (expression_list expr_list) { - expression_list *list = expr_list; - assert (expr_list); - while (list) + int i; + + for (i = 0; i < MAX_EXPRS; i++) { - pp_assignment_expression (list->assign_expr); - if (list->next) + if (is_expression_empty (expr_list.exprs[i])) + break; + if (i != 0) printf (", "); - list = list->next; + pp_assignment_expression (expr_list.exprs[i]); } if (was_subexpression && !was_function_expression) @@ -1214,113 +841,107 @@ pp_expression (expression_list *expr_list) } static void -pp_variable_declaration (variable_declaration *var_decl) +pp_variable_declaration (variable_declaration var_decl) { - assert (var_decl); - printf ("%s", var_decl->name); - if (var_decl->ass_expr) + printf ("%s", var_decl.name); + if (!is_expression_empty (var_decl.assign_expr)) { printf (" = "); - pp_assignment_expression (var_decl->ass_expr); + pp_assignment_expression (var_decl.assign_expr); } } static void -pp_variable_declaration_list (variable_declaration_list *decl_list) +pp_variable_declaration_list (variable_declaration_list decl_list) { - variable_declaration_list *list = decl_list; - assert (decl_list); + int i; + printf ("var "); - while (list) + + for (i = 0; i < MAX_DECLS; i++) { - pp_variable_declaration (list->var_decl); - if (list->next) + if (is_variable_declaration_empty (decl_list.decls[i])) + break; + if (i != 0) printf (", "); - list = list->next; + pp_variable_declaration (decl_list.decls[i]); } } static void -pp_for_in_statement_initializer_part (for_in_statement_initializer_part *init) +pp_for_in_statement_initializer_part (for_in_statement_initializer_part init) { - assert (init); - if (init->is_decl) + if (init.is_decl) { printf ("var "); - pp_variable_declaration (init->data.decl); + pp_variable_declaration (init.data.decl); } - else - pp_left_hand_side_expression (init->data.left_hand_expr); + else if (!is_expression_empty (init.data.left_hand_expr)) + pp_assignment_expression (init.data.left_hand_expr); } static void -pp_for_in_statement (for_in_statement *for_in_stmt) +pp_for_in_statement (for_in_statement for_in_stmt) { - assert (for_in_stmt); printf ("for ("); - pp_for_in_statement_initializer_part (for_in_stmt->init); + pp_for_in_statement_initializer_part (for_in_stmt.init); printf (" in "); - pp_expression (for_in_stmt->list_expr); + pp_expression (for_in_stmt.list_expr); printf (") "); } static void -pp_for_statement_initialiser_part (for_statement_initialiser_part *init) +pp_for_statement_initialiser_part (for_statement_initialiser_part init) { - assert (init); - if (init->is_decl) - pp_variable_declaration_list (init->data.decl_list); + if (init.is_decl) + pp_variable_declaration_list (init.data.decl_list); else - pp_expression (init->data.expr); + pp_expression (init.data.expr); } static void -pp_for_statement (for_statement *for_stmt) +pp_for_statement (for_statement for_stmt) { - assert (for_stmt); printf ("for ("); - if (for_stmt->init) - pp_for_statement_initialiser_part (for_stmt->init); + pp_for_statement_initialiser_part (for_stmt.init); printf ("; "); - if (for_stmt->limit) - pp_expression (for_stmt->limit); + if (is_expression_empty (for_stmt.limit)) + pp_assignment_expression (for_stmt.limit); printf ("; "); - if (for_stmt->incr) - pp_expression (for_stmt->incr); + if (is_expression_empty (for_stmt.incr)) + pp_assignment_expression (for_stmt.incr); printf (") "); } static void -pp_for_or_for_in_statement (for_or_for_in_statement *for_or_for_in_stmt) +pp_for_or_for_in_statement (for_or_for_in_statement for_or_for_in_stmt) { - assert (for_or_for_in_stmt); - if (for_or_for_in_stmt->is_for_in) - pp_for_in_statement (for_or_for_in_stmt->data.for_in_stmt); + if (for_or_for_in_stmt.is_for_in) + pp_for_in_statement (for_or_for_in_stmt.data.for_in_stmt); else - pp_for_statement (for_or_for_in_stmt->data.for_stmt); + pp_for_statement (for_or_for_in_stmt.data.for_stmt); } void -pp_statement (statement *stmt) +pp_statement (statement stmt) { was_function_expression = false; was_subexpression = false; - assert (stmt); if (prev_stmt == STMT_BLOCK_END) { - if (stmt->type == STMT_EMPTY) + if (stmt.type == STMT_EMPTY) { printf (";\n"); - prev_stmt = stmt->type; + prev_stmt = stmt.type; return; } else putchar ('\n'); } - switch (stmt->type) - { + switch (stmt.type) + { case STMT_BLOCK_START: printf ("{\n"); intendation += 2; @@ -1334,7 +955,7 @@ pp_statement (statement *stmt) case STMT_VARIABLE: intend (); - pp_variable_declaration_list (stmt->data.var_stmt); + pp_variable_declaration_list (stmt.data.var_stmt); break; case STMT_EMPTY: @@ -1344,7 +965,7 @@ pp_statement (statement *stmt) case STMT_IF: intend (); printf ("if ("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; @@ -1356,7 +977,7 @@ pp_statement (statement *stmt) case STMT_ELSE_IF: intend (); printf ("else if("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; @@ -1368,13 +989,13 @@ pp_statement (statement *stmt) case STMT_WHILE: intend (); printf ("while ("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; case STMT_FOR_OR_FOR_IN: intend (); - pp_for_or_for_in_statement (stmt->data.for_stmt); + pp_for_or_for_in_statement (stmt.data.for_stmt); break; case STMT_CONTINUE: @@ -1390,8 +1011,7 @@ pp_statement (statement *stmt) case STMT_RETURN: intend (); printf ("return "); - if (stmt->data.expr) - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); if (!was_function_expression) printf (";\n"); break; @@ -1399,33 +1019,33 @@ pp_statement (statement *stmt) case STMT_WITH: intend (); printf ("with ("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; case STMT_LABELLED: intend (); - printf ("%s:\n", stmt->data.name); + printf ("%s:\n", stmt.data.name); break; case STMT_SWITCH: intend (); printf ("switch ("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; case STMT_CASE: intend (); printf ("case "); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (":\n"); break; case STMT_THROW: intend (); printf ("throw "); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (";\n"); break; @@ -1437,7 +1057,7 @@ pp_statement (statement *stmt) case STMT_CATCH: intend (); printf ("catch ("); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); printf (") "); break; @@ -1448,7 +1068,7 @@ pp_statement (statement *stmt) case STMT_EXPRESSION: intend (); - pp_expression (stmt->data.expr); + pp_expression (stmt.data.expr); break; case STMT_SUBEXPRESSION_END: @@ -1457,14 +1077,14 @@ pp_statement (statement *stmt) case STMT_FUNCTION: intend (); - pp_function_declaration (stmt->data.fun_decl); + pp_function_declaration (stmt.data.fun_decl); break; default: - unreachable (); - } + JERRY_UNREACHABLE (); + } - prev_stmt = stmt->type; + prev_stmt = stmt.type; } void pp_finish () diff --git a/src/pretty-printer.h b/src/pretty-printer.h index b3cb5199e..496ccd0da 100644 --- a/src/pretty-printer.h +++ b/src/pretty-printer.h @@ -23,6 +23,6 @@ void pp_reset (); void pp_finish (); void pp_token (token); void pp_keyword (keyword); -void pp_statement (statement *); +void pp_statement (statement); #endif \ No newline at end of file diff --git a/tests/unit/test_poolman.c b/tests/unit/test_poolman.c index a76b13e2f..9144ce072 100644 --- a/tests/unit/test_poolman.c +++ b/tests/unit/test_poolman.c @@ -49,7 +49,7 @@ main( int __unused argc, srand((unsigned int) time(NULL)); unsigned int seed = (unsigned int)rand(); - libc_printf("seed=%u\n", seed); + __printf("seed=%u\n", seed); srand(seed); for ( int i = 0; i < test_iters; i++ ) @@ -70,7 +70,7 @@ main( int __unused argc, if ( ptrs[j] != NULL ) { - libc_memset(ptrs[j], 0, chunkSize); + __memset(ptrs[j], 0, chunkSize); } }