diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-07-11 18:03:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-11 18:03:42 +0200 |
commit | e4871c661f0bfb979f1b235d7b6e59b70ed1aca6 (patch) | |
tree | 40542b06a966366e2e8a3a0118e756874a838ce6 | |
parent | dad8f3aed4ca5f2f93e2be6f1243632439dec541 (diff) | |
parent | d5b25f942147b09511d77d5470cd38a1e1643fb9 (diff) |
Merge pull request #15 from jow-/c-api
C API wip
-rw-r--r-- | CMakeLists.txt | 25 | ||||
-rw-r--r-- | chunk.c | 40 | ||||
-rw-r--r-- | compiler.c | 406 | ||||
-rw-r--r-- | examples/CMakeLists.txt | 7 | ||||
-rw-r--r-- | examples/exception-handler.c | 100 | ||||
-rw-r--r-- | examples/execute-file.c | 118 | ||||
-rw-r--r-- | examples/execute-string.c | 128 | ||||
-rw-r--r-- | examples/native-function.c | 104 | ||||
-rw-r--r-- | examples/state-reset.c | 94 | ||||
-rw-r--r-- | examples/state-reuse.c | 98 | ||||
-rw-r--r-- | include/ucode/chunk.h (renamed from chunk.h) | 20 | ||||
-rw-r--r-- | include/ucode/compiler.h (renamed from compiler.h) | 46 | ||||
-rw-r--r-- | include/ucode/lexer.h (renamed from lexer.h) | 18 | ||||
-rw-r--r-- | include/ucode/lib.h | 106 | ||||
-rw-r--r-- | include/ucode/module.h (renamed from module.h) | 28 | ||||
-rw-r--r-- | include/ucode/source.h (renamed from source.h) | 10 | ||||
-rw-r--r-- | include/ucode/types.h (renamed from types.h) | 156 | ||||
-rw-r--r-- | include/ucode/util.h (renamed from util.h) | 105 | ||||
-rw-r--r-- | include/ucode/vallist.h (renamed from value.h) | 19 | ||||
-rw-r--r-- | include/ucode/vm.h (renamed from vm.h) | 31 | ||||
-rw-r--r-- | lexer.c | 100 | ||||
-rw-r--r-- | lib.c | 412 | ||||
-rw-r--r-- | lib.h | 125 | ||||
-rw-r--r-- | lib/fs.c | 170 | ||||
-rw-r--r-- | lib/math.c | 52 | ||||
-rw-r--r-- | lib/ubus.c | 48 | ||||
-rw-r--r-- | lib/uci.c | 164 | ||||
-rw-r--r-- | main.c | 134 | ||||
-rw-r--r-- | source.c | 20 | ||||
-rw-r--r-- | tests/cram/test_basic.t | 17 | ||||
-rw-r--r-- | types.c | 433 | ||||
-rw-r--r-- | vallist.c (renamed from value.c) | 315 | ||||
-rw-r--r-- | vm.c | 514 |
33 files changed, 2377 insertions, 1786 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e9923f1..7f8171d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6) ENDIF() ADD_DEFINITIONS(-Wmissing-declarations -Wno-error=unused-variable -Wno-unused-parameter) +INCLUDE_DIRECTORIES(include) + OPTION(FS_SUPPORT "Filesystem plugin support" ON) OPTION(MATH_SUPPORT "Math plugin support" ON) OPTION(UBUS_SUPPORT "Ubus plugin support" ON) @@ -45,14 +47,19 @@ IF(JSONC_FOUND) INCLUDE_DIRECTORIES(${JSONC_INCLUDE_DIRS}) ENDIF() -SET(UCODE_SOURCES main.c lexer.c lib.c vm.c chunk.c value.c compiler.c source.c types.c) -ADD_EXECUTABLE(ucode ${UCODE_SOURCES}) -SET_PROPERTY(TARGET ucode PROPERTY ENABLE_EXPORTS 1) -TARGET_LINK_LIBRARIES(ucode ${json}) +SET(UCODE_SOURCES lexer.c lib.c vm.c chunk.c vallist.c compiler.c source.c types.c) +ADD_LIBRARY(libucode SHARED ${UCODE_SOURCES}) +SET(SOVERSION 0 CACHE STRING "Override ucode library version") +SET_TARGET_PROPERTIES(libucode PROPERTIES OUTPUT_NAME ucode SOVERSION ${SOVERSION}) +TARGET_LINK_LIBRARIES(libucode ${json}) + +SET(CLI_SOURCES main.c) +ADD_EXECUTABLE(ucode ${CLI_SOURCES}) +TARGET_LINK_LIBRARIES(ucode libucode ${json}) CHECK_FUNCTION_EXISTS(dlopen DLOPEN_FUNCTION_EXISTS) IF (NOT DLOPEN_FUNCTION_EXISTS) - TARGET_LINK_LIBRARIES(ucode dl) + TARGET_LINK_LIBRARIES(libucode dl) ENDIF() SET(CMAKE_REQUIRED_LIBRARIES json-c) @@ -114,7 +121,7 @@ IF(UNIT_TESTING) LIST(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") IF(CMAKE_C_COMPILER_ID STREQUAL "Clang") - ADD_EXECUTABLE(ucode-san ${UCODE_SOURCES}) + ADD_EXECUTABLE(ucode-san ${CLI_SOURCES} ${UCODE_SOURCES}) SET_PROPERTY(TARGET ucode-san PROPERTY ENABLE_EXPORTS 1) TARGET_LINK_LIBRARIES(ucode-san ${json}) TARGET_COMPILE_OPTIONS(ucode-san PRIVATE -g -fno-omit-frame-pointer -fsanitize=undefined,address,leak -fno-sanitize-recover=all) @@ -123,4 +130,10 @@ IF(UNIT_TESTING) ENDIF() INSTALL(TARGETS ucode RUNTIME DESTINATION bin) +INSTALL(TARGETS libucode LIBRARY DESTINATION lib) INSTALL(TARGETS ${LIBRARIES} LIBRARY DESTINATION lib/ucode) + +FILE(GLOB UCODE_HEADERS "include/ucode/*.h") +INSTALL(FILES ${UCODE_HEADERS} DESTINATION include/ucode) + +ADD_SUBDIRECTORY(examples) @@ -16,11 +16,11 @@ #include <assert.h> -#include "chunk.h" -#include "types.h" -#include "util.h" +#include "ucode/chunk.h" +#include "ucode/types.h" +#include "ucode/util.h" -#define OFFSETINFO_BITS (sizeof(((uc_offsetinfo *)NULL)->entries[0]) * 8) +#define OFFSETINFO_BITS (sizeof(((uc_offsetinfo_t *)NULL)->entries[0]) * 8) #define OFFSETINFO_BYTE_BITS 3 #define OFFSETINFO_INSN_BITS (OFFSETINFO_BITS - OFFSETINFO_BYTE_BITS) #define OFFSETINFO_MAX_BYTES ((1 << OFFSETINFO_BYTE_BITS) - 1) @@ -31,7 +31,7 @@ void -uc_chunk_init(uc_chunk *chunk) +uc_chunk_init(uc_chunk_t *chunk) { chunk->count = 0; chunk->entries = NULL; @@ -50,7 +50,7 @@ uc_chunk_init(uc_chunk *chunk) } void -uc_chunk_free(uc_chunk *chunk) +uc_chunk_free(uc_chunk_t *chunk) { uc_vector_clear(chunk); uc_vector_clear(&chunk->ehranges); @@ -64,9 +64,9 @@ uc_chunk_free(uc_chunk *chunk) } size_t -uc_chunk_add(uc_chunk *chunk, uint8_t byte, size_t offset) +uc_chunk_add(uc_chunk_t *chunk, uint8_t byte, size_t offset) { - uc_offsetinfo *offsets = &chunk->debuginfo.offsets; + uc_offsetinfo_t *offsets = &chunk->debuginfo.offsets; size_t i; uc_vector_grow(chunk); @@ -114,9 +114,9 @@ uc_chunk_add(uc_chunk *chunk, uint8_t byte, size_t offset) } void -uc_chunk_pop(uc_chunk *chunk) +uc_chunk_pop(uc_chunk_t *chunk) { - uc_offsetinfo *offsets = &chunk->debuginfo.offsets; + uc_offsetinfo_t *offsets = &chunk->debuginfo.offsets; int n_insns; assert(chunk->count > 0); @@ -137,21 +137,21 @@ uc_chunk_pop(uc_chunk *chunk) } uc_value_t * -uc_chunk_get_constant(uc_chunk *chunk, size_t idx) +uc_chunk_get_constant(uc_chunk_t *chunk, size_t idx) { return uc_vallist_get(&chunk->constants, idx); } ssize_t -uc_chunk_add_constant(uc_chunk *chunk, uc_value_t *val) +uc_chunk_add_constant(uc_chunk_t *chunk, uc_value_t *val) { return uc_vallist_add(&chunk->constants, val); } size_t -uc_chunk_debug_get_srcpos(uc_chunk *chunk, size_t off) +uc_chunk_debug_get_srcpos(uc_chunk_t *chunk, size_t off) { - uc_offsetinfo *offsets = &chunk->debuginfo.offsets; + uc_offsetinfo_t *offsets = &chunk->debuginfo.offsets; size_t i, inum = 0, lnum = 0; if (!offsets->count) @@ -166,10 +166,10 @@ uc_chunk_debug_get_srcpos(uc_chunk *chunk, size_t off) } void -uc_chunk_debug_add_variable(uc_chunk *chunk, size_t from, size_t to, size_t slot, bool upval, uc_value_t *name) +uc_chunk_debug_add_variable(uc_chunk_t *chunk, size_t from, size_t to, size_t slot, bool upval, uc_value_t *name) { - uc_variables *variables = &chunk->debuginfo.variables; - uc_value_list *varnames = &chunk->debuginfo.varnames; + uc_variables_t *variables = &chunk->debuginfo.variables; + uc_value_list_t *varnames = &chunk->debuginfo.varnames; assert(slot <= ((size_t)-1 / 2)); @@ -187,10 +187,10 @@ uc_chunk_debug_add_variable(uc_chunk *chunk, size_t from, size_t to, size_t slot } uc_value_t * -uc_chunk_debug_get_variable(uc_chunk *chunk, size_t off, size_t slot, bool upval) +uc_chunk_debug_get_variable(uc_chunk_t *chunk, size_t off, size_t slot, bool upval) { - uc_variables *variables = &chunk->debuginfo.variables; - uc_value_list *varnames = &chunk->debuginfo.varnames; + uc_variables_t *variables = &chunk->debuginfo.variables; + uc_value_list_t *varnames = &chunk->debuginfo.varnames; uc_value_t *name = NULL; size_t i; @@ -16,35 +16,35 @@ #include <assert.h> -#include "compiler.h" -#include "chunk.h" -#include "vm.h" /* I_* */ -#include "source.h" -#include "lib.h" /* format_error_context() */ - -static void uc_compiler_compile_unary(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_binary(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_delete(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_paren(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_call(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_post_inc(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_constant(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_comma(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_labelexpr(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_function(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_and(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_or(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_dot(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_subscript(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_ternary(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_array(uc_compiler *compiler, bool assignable); -static void uc_compiler_compile_object(uc_compiler *compiler, bool assignable); - -static void uc_compiler_compile_declaration(uc_compiler *compiler); -static void uc_compiler_compile_statement(uc_compiler *compiler); -static void uc_compiler_compile_expstmt(uc_compiler *compiler); - -static uc_parse_rule +#include "ucode/compiler.h" +#include "ucode/chunk.h" +#include "ucode/vm.h" /* I_* */ +#include "ucode/source.h" +#include "ucode/lib.h" /* uc_error_context_format() */ + +static void uc_compiler_compile_unary(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_binary(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_delete(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_paren(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_call(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_post_inc(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_constant(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_comma(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_labelexpr(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_function(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_and(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_or(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_dot(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_subscript(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_ternary(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_array(uc_compiler_t *compiler, bool assignable); +static void uc_compiler_compile_object(uc_compiler_t *compiler, bool assignable); + +static void uc_compiler_compile_declaration(uc_compiler_t *compiler); +static void uc_compiler_compile_statement(uc_compiler_t *compiler); +static void uc_compiler_compile_expstmt(uc_compiler_t *compiler); + +static uc_parse_rule_t uc_compiler_parse_rules[TK_ERROR + 1] = { [TK_LPAREN] = { uc_compiler_compile_paren, uc_compiler_compile_call, P_CALL }, [TK_SUB] = { uc_compiler_compile_unary, uc_compiler_compile_binary, P_ADD }, @@ -91,13 +91,13 @@ uc_compiler_parse_rules[TK_ERROR + 1] = { }; static ssize_t -uc_compiler_declare_local(uc_compiler *compiler, uc_value_t *name, bool constant); +uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant); static ssize_t -uc_compiler_initialize_local(uc_compiler *compiler); +uc_compiler_initialize_local(uc_compiler_t *compiler); static void -uc_compiler_init(uc_compiler *compiler, const char *name, size_t srcpos, uc_source *source, bool strict) +uc_compiler_init(uc_compiler_t *compiler, const char *name, size_t srcpos, uc_source_t *source, bool strict) { uc_value_t *varname = ucv_string_new("(callee)"); uc_function_t *fn; @@ -127,16 +127,16 @@ uc_compiler_init(uc_compiler *compiler, const char *name, size_t srcpos, uc_sour ucv_put(varname); } -static uc_chunk * -uc_compiler_current_chunk(uc_compiler *compiler) +static uc_chunk_t * +uc_compiler_current_chunk(uc_compiler_t *compiler) { uc_function_t *fn = (uc_function_t *)compiler->function; return &fn->chunk; } -static uc_source * -uc_compiler_current_source(uc_compiler *compiler) +static uc_source_t * +uc_compiler_current_source(uc_compiler_t *compiler) { uc_function_t *fn = (uc_function_t *)compiler->function; @@ -144,7 +144,7 @@ uc_compiler_current_source(uc_compiler *compiler) } __attribute__((format(printf, 3, 0))) static void -uc_compiler_syntax_error(uc_compiler *compiler, size_t off, const char *fmt, ...) +uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, ...) { uc_stringbuf_t *buf = compiler->parser->error; size_t line = 0, byte = 0, len = 0; @@ -181,12 +181,12 @@ uc_compiler_syntax_error(uc_compiler *compiler, size_t off, const char *fmt, ... if (line) ucv_stringbuf_printf(buf, "In line %zu, byte %zu:\n", line, byte); - if (format_error_context(buf, uc_compiler_current_source(compiler), NULL, off)) + if (uc_error_context_format(buf, uc_compiler_current_source(compiler), NULL, off)) ucv_stringbuf_append(buf, "\n\n"); } static size_t -uc_compiler_set_srcpos(uc_compiler *compiler, size_t srcpos) +uc_compiler_set_srcpos(uc_compiler_t *compiler, size_t srcpos) { size_t delta; @@ -200,7 +200,7 @@ uc_compiler_set_srcpos(uc_compiler *compiler, size_t srcpos) } static void -uc_compiler_parse_advance(uc_compiler *compiler) +uc_compiler_parse_advance(uc_compiler_t *compiler) { ucv_put(compiler->parser->prev.uv); compiler->parser->prev = compiler->parser->curr; @@ -220,7 +220,7 @@ uc_compiler_parse_advance(uc_compiler *compiler) } static void -uc_compiler_parse_consume(uc_compiler *compiler, uc_tokentype_t type) +uc_compiler_parse_consume(uc_compiler_t *compiler, uc_tokentype_t type) { if (compiler->parser->curr.type == type) { uc_compiler_parse_advance(compiler); @@ -229,17 +229,17 @@ uc_compiler_parse_consume(uc_compiler *compiler, uc_tokentype_t type) } uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, - "Unexpected token\nExpecting %s", uc_get_tokenname(type)); + "Unexpected token\nExpecting %s", uc_tokenname(type)); } static bool -uc_compiler_parse_check(uc_compiler *compiler, uc_tokentype_t type) +uc_compiler_parse_check(uc_compiler_t *compiler, uc_tokentype_t type) { return (compiler->parser->curr.type == type); } static bool -uc_compiler_parse_match(uc_compiler *compiler, uc_tokentype_t type) +uc_compiler_parse_match(uc_compiler_t *compiler, uc_tokentype_t type) { if (!uc_compiler_parse_check(compiler, type)) return false; @@ -250,7 +250,7 @@ uc_compiler_parse_match(uc_compiler *compiler, uc_tokentype_t type) } static void -uc_compiler_parse_synchronize(uc_compiler *compiler) +uc_compiler_parse_synchronize(uc_compiler_t *compiler) { compiler->parser->synchronizing = false; @@ -279,14 +279,14 @@ uc_compiler_parse_synchronize(uc_compiler *compiler) } } -static uc_parse_rule * +static uc_parse_rule_t * uc_compiler_parse_rule(uc_tokentype_t type) { return &uc_compiler_parse_rules[type]; } static bool -uc_compiler_parse_at_assignment_op(uc_compiler *compiler) +uc_compiler_parse_at_assignment_op(uc_compiler_t *compiler) { switch (compiler->parser->curr.type) { case TK_ASBAND: @@ -308,9 +308,9 @@ uc_compiler_parse_at_assignment_op(uc_compiler *compiler) } static void -uc_compiler_parse_precedence(uc_compiler *compiler, uc_precedence_t precedence) +uc_compiler_parse_precedence(uc_compiler_t *compiler, uc_precedence_t precedence) { - uc_parse_rule *rule; + uc_parse_rule_t *rule; bool assignable; rule = uc_compiler_parse_rule(compiler->parser->curr.type); @@ -355,7 +355,7 @@ uc_compiler_parse_precedence(uc_compiler *compiler, uc_precedence_t precedence) } static size_t -uc_compiler_reladdr(uc_compiler *compiler, size_t from, size_t to) +uc_compiler_reladdr(uc_compiler_t *compiler, size_t from, size_t to) { ssize_t delta = to - from; @@ -369,9 +369,9 @@ uc_compiler_reladdr(uc_compiler *compiler, size_t from, size_t to) } static size_t -uc_compiler_emit_insn(uc_compiler *compiler, size_t srcpos, enum insn_type insn) +uc_compiler_emit_insn(uc_compiler_t *compiler, size_t srcpos, uc_vm_insn_t insn) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); compiler->last_insn = uc_chunk_add(chunk, (uint8_t)insn, lineoff); @@ -380,7 +380,7 @@ uc_compiler_emit_insn(uc_compiler *compiler, size_t srcpos, enum insn_type insn) } static size_t -uc_compiler_emit_u8(uc_compiler *compiler, size_t srcpos, uint8_t n) +uc_compiler_emit_u8(uc_compiler_t *compiler, size_t srcpos, uint8_t n) { return uc_chunk_add( uc_compiler_current_chunk(compiler), @@ -389,7 +389,7 @@ uc_compiler_emit_u8(uc_compiler *compiler, size_t srcpos, uint8_t n) } static size_t -uc_compiler_emit_s8(uc_compiler *compiler, size_t srcpos, int8_t n) +uc_compiler_emit_s8(uc_compiler_t *compiler, size_t srcpos, int8_t n) { return uc_chunk_add( uc_compiler_current_chunk(compiler), @@ -398,9 +398,9 @@ uc_compiler_emit_s8(uc_compiler *compiler, size_t srcpos, int8_t n) } static size_t -uc_compiler_emit_u16(uc_compiler *compiler, size_t srcpos, uint16_t n) +uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); uc_chunk_add(chunk, n / 0x100, lineoff); @@ -410,9 +410,9 @@ uc_compiler_emit_u16(uc_compiler *compiler, size_t srcpos, uint16_t n) } static size_t -uc_compiler_emit_s16(uc_compiler *compiler, size_t srcpos, int16_t n) +uc_compiler_emit_s16(uc_compiler_t *compiler, size_t srcpos, int16_t n) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); uint16_t v = n + 0x7fff; @@ -423,9 +423,9 @@ uc_compiler_emit_s16(uc_compiler *compiler, size_t srcpos, int16_t n) } static size_t -uc_compiler_emit_u32(uc_compiler *compiler, size_t srcpos, uint32_t n) +uc_compiler_emit_u32(uc_compiler_t *compiler, size_t srcpos, uint32_t n) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); uc_chunk_add(chunk, n / 0x1000000, lineoff); @@ -437,9 +437,9 @@ uc_compiler_emit_u32(uc_compiler *compiler, size_t srcpos, uint32_t n) } static size_t -uc_compiler_emit_s32(uc_compiler *compiler, size_t srcpos, int32_t n) +uc_compiler_emit_s32(uc_compiler_t *compiler, size_t srcpos, int32_t n) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); uint32_t v; @@ -457,9 +457,9 @@ uc_compiler_emit_s32(uc_compiler *compiler, size_t srcpos, int32_t n) } static uint32_t -uc_compiler_get_u32(uc_compiler *compiler, size_t off) +uc_compiler_get_u32(uc_compiler_t *compiler, size_t off) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); return chunk->entries[off + 0] * 0x1000000 + chunk->entries[off + 1] * 0x10000 + @@ -468,9 +468,9 @@ uc_compiler_get_u32(uc_compiler *compiler, size_t off) } static void -uc_compiler_set_u32(uc_compiler *compiler, size_t off, uint32_t n) +uc_compiler_set_u32(uc_compiler_t *compiler, size_t off, uint32_t n) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); chunk->entries[off + 0] = n / 0x1000000; chunk->entries[off + 1] = (n / 0x10000) % 0x100; @@ -479,9 +479,9 @@ uc_compiler_set_u32(uc_compiler *compiler, size_t off, uint32_t n) } static size_t -uc_compiler_emit_constant(uc_compiler *compiler, size_t srcpos, uc_value_t *val) +uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t cidx = uc_chunk_add_constant(chunk, val); uc_compiler_emit_insn(compiler, srcpos, I_LOAD); @@ -491,9 +491,9 @@ uc_compiler_emit_constant(uc_compiler *compiler, size_t srcpos, uc_value_t *val) } static size_t -uc_compiler_emit_regexp(uc_compiler *compiler, size_t srcpos, uc_value_t *val) +uc_compiler_emit_regexp(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t cidx = uc_chunk_add_constant(chunk, val); uc_compiler_emit_insn(compiler, srcpos, I_LREXP); @@ -503,9 +503,9 @@ uc_compiler_emit_regexp(uc_compiler *compiler, size_t srcpos, uc_value_t *val) } static size_t -uc_compiler_emit_jmp(uc_compiler *compiler, size_t srcpos, uint32_t dest) +uc_compiler_emit_jmp(uc_compiler_t *compiler, size_t srcpos, uint32_t dest) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_compiler_emit_insn(compiler, srcpos, I_JMP); uc_compiler_emit_u32(compiler, 0, dest ? uc_compiler_reladdr(compiler, chunk->count - 1, dest) : 0); @@ -514,9 +514,9 @@ uc_compiler_emit_jmp(uc_compiler *compiler, size_t srcpos, uint32_t dest) } static size_t -uc_compiler_emit_jmpz(uc_compiler *compiler, size_t srcpos, uint32_t dest) +uc_compiler_emit_jmpz(uc_compiler_t *compiler, size_t srcpos, uint32_t dest) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_compiler_emit_insn(compiler, srcpos, I_JMPZ); uc_compiler_emit_u32(compiler, 0, dest ? uc_compiler_reladdr(compiler, chunk->count - 1, dest) : 0); @@ -525,9 +525,9 @@ uc_compiler_emit_jmpz(uc_compiler *compiler, size_t srcpos, uint32_t dest) } static ssize_t -uc_compiler_get_jmpaddr(uc_compiler *compiler, size_t off) +uc_compiler_get_jmpaddr(uc_compiler_t *compiler, size_t off) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ); assert(off + 4 < chunk->count); @@ -541,9 +541,9 @@ uc_compiler_get_jmpaddr(uc_compiler *compiler, size_t off) } static void -uc_compiler_set_jmpaddr(uc_compiler *compiler, size_t off, uint32_t dest) +uc_compiler_set_jmpaddr(uc_compiler_t *compiler, size_t off, uint32_t dest) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t addr = uc_compiler_reladdr(compiler, off, dest); assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ); @@ -556,11 +556,11 @@ uc_compiler_set_jmpaddr(uc_compiler *compiler, size_t off, uint32_t dest) } static uc_function_t * -uc_compiler_finish(uc_compiler *compiler) +uc_compiler_finish(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_locals *locals = &compiler->locals; - uc_upvals *upvals = &compiler->upvals; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_locals_t *locals = &compiler->locals; + uc_upvals_t *upvals = &compiler->upvals; size_t i; uc_compiler_emit_insn(compiler, 0, I_LNULL); @@ -601,16 +601,16 @@ uc_compiler_finish(uc_compiler *compiler) } static void -uc_compiler_enter_scope(uc_compiler *compiler) +uc_compiler_enter_scope(uc_compiler_t *compiler) { compiler->scope_depth++; } static void -uc_compiler_leave_scope(uc_compiler *compiler) +uc_compiler_leave_scope(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_locals *locals = &compiler->locals; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_locals_t *locals = &compiler->locals; compiler->scope_depth--; @@ -633,7 +633,7 @@ uc_compiler_leave_scope(uc_compiler *compiler) } static bool -uc_compiler_is_strict(uc_compiler *compiler) +uc_compiler_is_strict(uc_compiler_t *compiler) { uc_function_t *fn = (uc_function_t *)compiler->function; @@ -641,16 +641,13 @@ uc_compiler_is_strict(uc_compiler *compiler) } static ssize_t -uc_compiler_declare_local(uc_compiler *compiler, uc_value_t *name, bool constant) +uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_locals *locals = &compiler->locals; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_locals_t *locals = &compiler->locals; const char *str1, *str2; size_t i, len1, len2; - //if (compiler->scope_depth == 0) - // return; - if (locals->count >= 0x00FFFFFF) { uc_compiler_syntax_error(compiler, 0, "Too many local variables"); @@ -691,9 +688,9 @@ uc_compiler_declare_local(uc_compiler *compiler, uc_value_t *name, bool constant } static ssize_t -uc_compiler_initialize_local(uc_compiler *compiler) +uc_compiler_initialize_local(uc_compiler_t *compiler) { - uc_locals *locals = &compiler->locals; + uc_locals_t *locals = &compiler->locals; locals->entries[locals->count - 1].depth = compiler->scope_depth; @@ -701,9 +698,9 @@ uc_compiler_initialize_local(uc_compiler *compiler) } static ssize_t -uc_compiler_resolve_local(uc_compiler *compiler, uc_value_t *name, bool *constant) +uc_compiler_resolve_local(uc_compiler_t *compiler, uc_value_t *name, bool *constant) { - uc_locals *locals = &compiler->locals; + uc_locals_t *locals = &compiler->locals; const char *str1, *str2; size_t i, len1, len2; @@ -733,11 +730,11 @@ uc_compiler_resolve_local(uc_compiler *compiler, uc_value_t *name, bool *constan } static ssize_t -uc_compiler_add_upval(uc_compiler *compiler, size_t idx, bool local, uc_value_t *name, bool constant) +uc_compiler_add_upval(uc_compiler_t *compiler, size_t idx, bool local, uc_value_t *name, bool constant) { uc_function_t *function = (uc_function_t *)compiler->function; - uc_upvals *upvals = &compiler->upvals; - uc_upval *uv; + uc_upvals_t *upvals = &compiler->upvals; + uc_upval_t *uv; size_t i; for (i = 0, uv = upvals->entries; i < upvals->count; i++, uv = upvals->entries + i) @@ -764,7 +761,7 @@ uc_compiler_add_upval(uc_compiler *compiler, size_t idx, bool local, uc_value_t } static ssize_t -uc_compiler_resolve_upval(uc_compiler *compiler, uc_value_t *name, bool *constant) +uc_compiler_resolve_upval(uc_compiler_t *compiler, uc_value_t *name, bool *constant) { ssize_t idx; @@ -788,10 +785,10 @@ uc_compiler_resolve_upval(uc_compiler *compiler, uc_value_t *name, bool *constan } static void -uc_compiler_backpatch(uc_compiler *compiler, size_t break_addr, size_t next_addr) +uc_compiler_backpatch(uc_compiler_t *compiler, size_t break_addr, size_t next_addr) { - uc_patchlist *pl = compiler->patchlist; - uc_patchlist *pp = pl->parent; + uc_patchlist_t *pl = compiler->patchlist; + uc_patchlist_t *pp = pl->parent; volatile ssize_t jmpaddr; size_t i; @@ -831,11 +828,11 @@ uc_compiler_backpatch(uc_compiler *compiler, size_t break_addr, size_t next_addr } static void -uc_compiler_emit_inc_dec(uc_compiler *compiler, uc_tokentype_t toktype, bool is_postfix) +uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool is_postfix) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_value_t *varname = NULL; - enum insn_type type; + uc_vm_insn_t type; uint32_t cidx = 0; /* determine kind of emitted load instruction and operand value (if any) */ @@ -913,7 +910,7 @@ uc_compiler_emit_inc_dec(uc_compiler *compiler, uc_tokentype_t toktype, bool is_ static void -uc_compiler_compile_unary(uc_compiler *compiler, bool assignable) +uc_compiler_compile_unary(uc_compiler_t *compiler, bool assignable) { uc_tokentype_t type = compiler->parser->prev.type; @@ -947,7 +944,7 @@ uc_compiler_compile_unary(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_binary(uc_compiler *compiler, bool assignable) +uc_compiler_compile_binary(uc_compiler_t *compiler, bool assignable) { uc_tokentype_t type = compiler->parser->prev.type; @@ -956,10 +953,10 @@ uc_compiler_compile_binary(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_delete(uc_compiler *compiler, bool assignable) +uc_compiler_compile_delete(uc_compiler_t *compiler, bool assignable) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - enum insn_type type; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_vm_insn_t type; #ifndef NO_LEGACY /* If the delete keyword is followed by an opening paren, it might be a @@ -1009,10 +1006,10 @@ uc_compiler_compile_delete(uc_compiler *compiler, bool assignable) } } -static enum insn_type -uc_compiler_emit_variable_rw(uc_compiler *compiler, uc_value_t *varname, uc_tokentype_t type) +static uc_vm_insn_t +uc_compiler_emit_variable_rw(uc_compiler_t *compiler, uc_value_t *varname, uc_tokentype_t type) { - enum insn_type insn; + uc_vm_insn_t insn; uint32_t sub_insn; bool constant; ssize_t idx; @@ -1074,13 +1071,13 @@ uc_compiler_emit_variable_rw(uc_compiler *compiler, uc_value_t *varname, uc_toke } static void -uc_compiler_compile_expression(uc_compiler *compiler) +uc_compiler_compile_expression(uc_compiler_t *compiler) { uc_compiler_parse_precedence(compiler, P_COMMA); } static bool -uc_compiler_compile_assignment(uc_compiler *compiler, uc_value_t *var) +uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var) { uc_tokentype_t type = compiler->parser->curr.type; @@ -1096,10 +1093,10 @@ uc_compiler_compile_assignment(uc_compiler *compiler, uc_value_t *var) } static bool -uc_compiler_compile_arrowfn(uc_compiler *compiler, uc_value_t *args, bool restarg) +uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool restarg) { bool array = (ucv_type(args) == UC_ARRAY); - uc_compiler fncompiler = { 0 }; + uc_compiler_t fncompiler = { 0 }; size_t i, pos, load_off; uc_function_t *fn; ssize_t slot; @@ -1177,7 +1174,7 @@ uc_compiler_compile_arrowfn(uc_compiler *compiler, uc_value_t *args, bool restar } static uc_tokentype_t -uc_compiler_compile_var_or_arrowfn(uc_compiler *compiler, bool assignable, uc_value_t *name) +uc_compiler_compile_var_or_arrowfn(uc_compiler_t *compiler, bool assignable, uc_value_t *name) { uc_tokentype_t rv; @@ -1196,7 +1193,7 @@ uc_compiler_compile_var_or_arrowfn(uc_compiler *compiler, bool assignable, uc_va } static void -uc_compiler_compile_paren(uc_compiler *compiler, bool assignable) +uc_compiler_compile_paren(uc_compiler_t *compiler, bool assignable) { uc_value_t *varnames = NULL, *varname; bool maybe_arrowfn = false; @@ -1335,11 +1332,11 @@ out: } static void -uc_compiler_compile_call(uc_compiler *compiler, bool assignable) +uc_compiler_compile_call(uc_compiler_t *compiler, bool assignable) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_jmplist spreads = { 0 }; - enum insn_type type; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_jmplist_t spreads = { 0 }; + uc_vm_insn_t type; size_t i, nargs = 0; /* determine the kind of the lhs */ @@ -1391,13 +1388,13 @@ uc_compiler_compile_call(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_post_inc(uc_compiler *compiler, bool assignable) +uc_compiler_compile_post_inc(uc_compiler_t *compiler, bool assignable) { uc_compiler_emit_inc_dec(compiler, compiler->parser->prev.type, true); } static bool -uc_compiler_is_use_strict_pragma(uc_compiler *compiler) +uc_compiler_is_use_strict_pragma(uc_compiler_t *compiler) { uc_value_t *v; @@ -1413,7 +1410,7 @@ uc_compiler_is_use_strict_pragma(uc_compiler *compiler) } static void -uc_compiler_compile_constant(uc_compiler *compiler, bool assignable) +uc_compiler_compile_constant(uc_compiler_t *compiler, bool assignable) { uc_function_t *fn; int64_t n; @@ -1478,14 +1475,14 @@ uc_compiler_compile_constant(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_comma(uc_compiler *compiler, bool assignable) +uc_compiler_compile_comma(uc_compiler_t *compiler, bool assignable) { uc_compiler_emit_insn(compiler, 0, I_POP); uc_compiler_parse_precedence(compiler, P_ASSIGN); } static void -uc_compiler_compile_labelexpr(uc_compiler *compiler, bool assignable) +uc_compiler_compile_labelexpr(uc_compiler_t *compiler, bool assignable) { uc_value_t *label = ucv_get(compiler->parser->prev.uv); @@ -1494,7 +1491,7 @@ uc_compiler_compile_labelexpr(uc_compiler *compiler, bool assignable) } static bool -uc_compiler_compile_delimitted_block(uc_compiler *compiler, uc_tokentype_t endtype) +uc_compiler_compile_delimitted_block(uc_compiler_t *compiler, uc_tokentype_t endtype) { while (!uc_compiler_parse_check(compiler, endtype) && !uc_compiler_parse_check(compiler, TK_EOF)) @@ -1504,9 +1501,9 @@ uc_compiler_compile_delimitted_block(uc_compiler *compiler, uc_tokentype_t endty } static void -uc_compiler_compile_function(uc_compiler *compiler, bool assignable) +uc_compiler_compile_function(uc_compiler_t *compiler, bool assignable) { - uc_compiler fncompiler = { 0 }; + uc_compiler_t fncompiler = { 0 }; uc_value_t *name = NULL; ssize_t slot = -1, pos; uc_tokentype_t type; @@ -1612,9 +1609,9 @@ uc_compiler_compile_function(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_and(uc_compiler *compiler, bool assignable) +uc_compiler_compile_and(uc_compiler_t *compiler, bool assignable) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off; uc_compiler_emit_insn(compiler, 0, I_COPY); @@ -1626,9 +1623,9 @@ uc_compiler_compile_and(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_or(uc_compiler *compiler, bool assignable) +uc_compiler_compile_or(uc_compiler_t *compiler, bool assignable) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off, jmp_off; uc_compiler_emit_insn(compiler, 0, I_COPY); @@ -1642,7 +1639,7 @@ uc_compiler_compile_or(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_dot(uc_compiler *compiler, bool assignable) +uc_compiler_compile_dot(uc_compiler_t *compiler, bool assignable) { /* no regexp literal possible after property access */ compiler->parser->lex.no_regexp = true; @@ -1657,7 +1654,7 @@ uc_compiler_compile_dot(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_subscript(uc_compiler *compiler, bool assignable) +uc_compiler_compile_subscript(uc_compiler_t *compiler, bool assignable) { /* compile lhs */ uc_compiler_compile_expression(compiler); @@ -1672,9 +1669,9 @@ uc_compiler_compile_subscript(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_ternary(uc_compiler *compiler, bool assignable) +uc_compiler_compile_ternary(uc_compiler_t *compiler, bool assignable) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off, jmp_off; /* jump to false branch */ @@ -1695,7 +1692,7 @@ uc_compiler_compile_ternary(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_array(uc_compiler *compiler, bool assignable) +uc_compiler_compile_array(uc_compiler_t *compiler, bool assignable) { size_t hint_off, hint_count = 0, len = 0; @@ -1754,7 +1751,7 @@ uc_compiler_compile_array(uc_compiler *compiler, bool assignable) } static void -uc_compiler_compile_object(uc_compiler *compiler, bool assignable) +uc_compiler_compile_object(uc_compiler_t *compiler, bool assignable) { size_t hint_off, hint_count = 0, len = 0; @@ -1860,7 +1857,7 @@ uc_compiler_compile_object(uc_compiler *compiler, bool assignable) static void -uc_compiler_declare_local_null(uc_compiler *compiler, size_t srcpos, uc_value_t *varname) +uc_compiler_declare_local_null(uc_compiler_t *compiler, size_t srcpos, uc_value_t *varname) { ssize_t existing_slot = uc_compiler_declare_local(compiler, varname, false); @@ -1877,40 +1874,10 @@ uc_compiler_declare_local_null(uc_compiler *compiler, size_t srcpos, uc_value_t } static size_t -uc_compiler_declare_internal(uc_compiler *compiler, size_t srcpos, const char *name) +uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char *name) { -#if 0 - ssize_t existing_slot; - json_object *n; - bool strict; - - n = xjs_new_string(name); - strict = compiler->strict_declarations; - compiler->strict_declarations = false; - existing_slot = uc_compiler_declare_local(compiler, n, false); - compiler->strict_declarations = strict; - - uc_compiler_emit_insn(compiler, srcpos, I_LNULL); - - if (existing_slot == -1) { - uc_value_put(n); - - return uc_compiler_initialize_local(compiler); - } - else { - uc_value_put(n); - - uc_compiler_emit_insn(compiler, 0, I_SLOC); - uc_compiler_emit_u32(compiler, 0, existing_slot); - uc_compiler_emit_insn(compiler, 0, I_POP); - - return existing_slot; - } -#else - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_locals *locals = &compiler->locals; - - //uc_compiler_emit_insn(compiler, srcpos, I_LNULL); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_locals_t *locals = &compiler->locals; uc_vector_grow(locals); @@ -1920,11 +1887,10 @@ uc_compiler_declare_internal(uc_compiler *compiler, size_t srcpos, const char *n locals->entries[locals->count].from = chunk->count; return locals->count++; -#endif } static void -uc_compiler_compile_declexpr(uc_compiler *compiler, bool constant) +uc_compiler_compile_declexpr(uc_compiler_t *compiler, bool constant) { ssize_t slot; @@ -1966,21 +1932,21 @@ uc_compiler_compile_declexpr(uc_compiler *compiler, bool constant) } static void -uc_compiler_compile_local(uc_compiler *compiler) +uc_compiler_compile_local(uc_compiler_t *compiler) { uc_compiler_compile_declexpr(compiler, false); uc_compiler_parse_consume(compiler, TK_SCOL); } static void -uc_compiler_compile_const(uc_compiler *compiler) +uc_compiler_compile_const(uc_compiler_t *compiler) { uc_compiler_compile_declexpr(compiler, true); uc_compiler_parse_consume(compiler, TK_SCOL); } static uc_tokentype_t -uc_compiler_compile_altifblock(uc_compiler *compiler) +uc_compiler_compile_altifblock(uc_compiler_t *compiler) { uc_compiler_enter_scope(compiler); @@ -2004,12 +1970,12 @@ uc_compiler_compile_altifblock(uc_compiler *compiler) } static void -uc_compiler_compile_if(uc_compiler *compiler) +uc_compiler_compile_if(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off, jmp_off, i; bool expect_endif = false; - uc_jmplist elifs = { 0 }; + uc_jmplist_t elifs = { 0 }; uc_tokentype_t type; /* parse & compile condition expression */ @@ -2110,10 +2076,10 @@ uc_compiler_compile_if(uc_compiler *compiler) } static void -uc_compiler_compile_while(uc_compiler *compiler) +uc_compiler_compile_while(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_patchlist p = { .depth = compiler->scope_depth }; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_patchlist_t p = { .depth = compiler->scope_depth }; size_t cond_off, jmpz_off, end_off; p.parent = compiler->patchlist; @@ -2158,10 +2124,10 @@ uc_compiler_compile_while(uc_compiler *compiler) } static void -uc_compiler_compile_for_in(uc_compiler *compiler, bool local, uc_token *kvar, uc_token *vvar) +uc_compiler_compile_for_in(uc_compiler_t *compiler, bool local, uc_token_t *kvar, uc_token_t *vvar) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_patchlist p = { .depth = compiler->scope_depth + 1 }; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_patchlist_t p = { .depth = compiler->scope_depth + 1 }; size_t skip_jmp, test_jmp, key_slot, val_slot; p.parent = compiler->patchlist; @@ -2268,11 +2234,11 @@ uc_compiler_compile_for_in(uc_compiler *compiler, bool local, uc_token *kvar, uc } static void -uc_compiler_compile_for_count(uc_compiler *compiler, bool local, uc_token *var) +uc_compiler_compile_for_count(uc_compiler_t *compiler, bool local, uc_token_t *var) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t test_off = 0, incr_off, skip_off, cond_off = 0; - uc_patchlist p = { .depth = compiler->scope_depth + 1 }; + uc_patchlist_t p = { .depth = compiler->scope_depth + 1 }; p.parent = compiler->patchlist; compiler->patchlist = &p; @@ -2377,9 +2343,9 @@ uc_compiler_compile_for_count(uc_compiler *compiler, bool local, uc_token *var) } static void -uc_compiler_compile_for(uc_compiler *compiler) +uc_compiler_compile_for(uc_compiler_t *compiler) { - uc_token keyvar = { 0 }, valvar = { 0 }; + uc_token_t keyvar = { 0 }, valvar = { 0 }; bool local; uc_compiler_parse_consume(compiler, TK_LPAREN); @@ -2429,13 +2395,13 @@ out: } static void -uc_compiler_compile_switch(uc_compiler *compiler) +uc_compiler_compile_switch(uc_compiler_t *compiler) { size_t i, test_jmp, skip_jmp, next_jmp, value_slot, default_off = 0; - uc_chunk *chunk = uc_compiler_current_chunk(compiler); - uc_patchlist p = { .depth = compiler->scope_depth }; - uc_locals *locals = &compiler->locals; - uc_jmplist cases = { 0 }; + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + uc_patchlist_t p = { .depth = compiler->scope_depth }; + uc_locals_t *locals = &compiler->locals; + uc_jmplist_t cases = { 0 }; p.parent = compiler->patchlist; compiler->patchlist = &p; @@ -2600,11 +2566,11 @@ uc_compiler_compile_switch(uc_compiler *compiler) } static void -uc_compiler_compile_try(uc_compiler *compiler) +uc_compiler_compile_try(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t try_from = 0, try_to = 0, jmp_off = 0, ehvar_slot = 0; - uc_ehranges *ranges = &chunk->ehranges; + uc_ehranges_t *ranges = &chunk->ehranges; try_from = chunk->count; ehvar_slot = compiler->locals.count; @@ -2670,12 +2636,12 @@ uc_compiler_compile_try(uc_compiler *compiler) } static void -uc_compiler_compile_control(uc_compiler *compiler) +uc_compiler_compile_control(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_tokentype_t type = compiler->parser->prev.type; - uc_patchlist *p = compiler->patchlist; - uc_locals *locals = &compiler->locals; + uc_patchlist_t *p = compiler->patchlist; + uc_locals_t *locals = &compiler->locals; size_t i, pos = compiler->parser->prev.pos; if (!p) { @@ -2700,9 +2666,9 @@ uc_compiler_compile_control(uc_compiler *compiler) } static void -uc_compiler_compile_return(uc_compiler *compiler) +uc_compiler_compile_return(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t off = chunk->count; uc_compiler_compile_expstmt(compiler); @@ -2718,9 +2684,9 @@ uc_compiler_compile_return(uc_compiler *compiler) } static void -uc_compiler_compile_tplexp(uc_compiler *compiler) +uc_compiler_compile_tplexp(uc_compiler_t *compiler) { - uc_chunk *chunk = uc_compiler_current_chunk(compiler); + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t off = chunk->count; uc_compiler_compile_expression(compiler); @@ -2735,14 +2701,14 @@ uc_compiler_compile_tplexp(uc_compiler *compiler) } static void -uc_compiler_compile_text(uc_compiler *compiler) +uc_compiler_compile_text(uc_compiler_t *compiler) { uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); uc_compiler_emit_insn(compiler, 0, I_PRINT); } static void -uc_compiler_compile_block(uc_compiler *compiler) +uc_compiler_compile_block(uc_compiler_t *compiler) { uc_compiler_enter_scope(compiler); @@ -2756,7 +2722,7 @@ uc_compiler_compile_block(uc_compiler *compiler) } static void -uc_compiler_compile_expstmt(uc_compiler *compiler) +uc_compiler_compile_expstmt(uc_compiler_t *compiler) { /* empty statement */ if (uc_compiler_parse_match(compiler, TK_SCOL)) @@ -2786,7 +2752,7 @@ uc_compiler_compile_expstmt(uc_compiler *compiler) } static void -uc_compiler_compile_statement(uc_compiler *compiler) +uc_compiler_compile_statement(uc_compiler_t *compiler) { if (uc_compiler_parse_match(compiler, TK_IF)) uc_compiler_compile_if(compiler); @@ -2817,7 +2783,7 @@ uc_compiler_compile_statement(uc_compiler *compiler) } static void -uc_compiler_compile_declaration(uc_compiler *compiler) +uc_compiler_compile_declaration(uc_compiler_t *compiler) { if (uc_compiler_parse_match(compiler, TK_LOCAL)) uc_compiler_compile_local(compiler); @@ -2831,10 +2797,10 @@ uc_compiler_compile_declaration(uc_compiler *compiler) } uc_function_t * -uc_compile(uc_parse_config *config, uc_source *source, char **errp) +uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp) { - uc_parser parser = { .config = config }; - uc_compiler compiler = { .parser = &parser }; + uc_parser_t parser = { .config = config }; + uc_compiler_t compiler = { .parser = &parser }; uc_function_t *fn; uc_lexer_init(&parser.lex, config, source); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..12d32ba --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,7 @@ +FILE(GLOB examples "*.c") +FOREACH(example ${examples}) + GET_FILENAME_COMPONENT(example ${example} NAME_WE) + SET(CLI_SOURCES main.c) + ADD_EXECUTABLE(${example} ${example}.c) + TARGET_LINK_LIBRARIES(${example} libucode ${json}) +ENDFOREACH(example) diff --git a/examples/exception-handler.c b/examples/exception-handler.c new file mode 100644 index 0000000..1e722ec --- /dev/null +++ b/examples/exception-handler.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +#define MULTILINE_STRING(...) #__VA_ARGS__ + +static const char *program = MULTILINE_STRING( + {% + function fail() { + /* invoke not existing function to raise runtime error */ + doesnotexist(); + } + + fail(); + %} +); + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +static void +log_exception(uc_vm_t *vm, uc_exception_t *ex) +{ + char *trace = ucv_to_jsonstring_formatted(vm, ex->stacktrace, ' ', 2); + + printf("Program raised an exception:\n"); + printf(" type=%d\n", ex->type); + printf(" message=%s\n", ex->message); + printf(" stacktrace=%s\n", trace); + + free(trace); +} + +int main(int argc, char **argv) +{ + int exit_code = 0; + + /* create a source buffer containing the program code */ + uc_source_t *src = uc_source_new_buffer("my program", strdup(program), strlen(program)); + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* register custom exception handler */ + uc_vm_exception_handler_set(&vm, log_exception); + + /* execute program function */ + int return_code = uc_vm_execute(&vm, progfunc, NULL); + + /* handle return status */ + if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) { + printf("An error occurred while running the program\n"); + exit_code = 1; + } + + /* free VM context */ + uc_vm_free(&vm); + + return exit_code; +} diff --git a/examples/execute-file.c b/examples/execute-file.c new file mode 100644 index 0000000..12910e3 --- /dev/null +++ b/examples/execute-file.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +int main(int argc, char **argv) +{ + int exit_code = 0; + + if (argc != 2) { + fprintf(stderr, "Usage: %s sourcefile.uc\n", argv[0]); + + return 1; + } + + /* create a source buffer from the given input file */ + uc_source_t *src = uc_source_new_file(argv[1]); + + /* check if source file could be opened */ + if (!src) { + fprintf(stderr, "Unable to open source file %s\n", argv[1]); + + return 1; + } + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* add global variables x and y to VM scope */ + ucv_object_add(uc_vm_scope_get(&vm), "x", ucv_int64_new(123)); + ucv_object_add(uc_vm_scope_get(&vm), "y", ucv_int64_new(456)); + + /* execute compiled program function */ + uc_value_t *last_expression_result = NULL; + int return_code = uc_vm_execute(&vm, progfunc, &last_expression_result); + + /* handle return status */ + switch (return_code) { + case STATUS_OK: + exit_code = 0; + + char *s = ucv_to_string(&vm, last_expression_result); + + printf("Program finished successfully.\n"); + printf("Function return value is %s\n", s); + free(s); + break; + + case STATUS_EXIT: + exit_code = (int)ucv_int64_get(last_expression_result); + + printf("The invoked program called exit().\n"); + printf("Exit code is %d\n", exit_code); + break; + + case ERROR_COMPILE: + exit_code = 1; + + printf("A compilation error occurred while running the program\n"); + break; + + case ERROR_RUNTIME: + exit_code = 2; + + printf("A runtime error occurred while running the program\n"); + break; + } + + /* free last expression result */ + ucv_put(last_expression_result); + + /* free VM context */ + uc_vm_free(&vm); + + return exit_code; +} diff --git a/examples/execute-string.c b/examples/execute-string.c new file mode 100644 index 0000000..1fcc966 --- /dev/null +++ b/examples/execute-string.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Example to compile a C string into an ucode program. + * Build with gcc -o execute-string -lucode execute-string.c + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +#define MULTILINE_STRING(...) #__VA_ARGS__ + +static const char *program = MULTILINE_STRING( + {% + function add(a, b) { + c = a + b; + + return c; + } + + result = add(x, y); + + printf('%d + %d is %d\n', x, y, result); + + return result; + %} +); + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +int main(int argc, char **argv) +{ + int exit_code = 0; + + /* create a source buffer containing the program code */ + uc_source_t *src = uc_source_new_buffer("my program", strdup(program), strlen(program)); + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* add global variables x and y to VM scope */ + ucv_object_add(uc_vm_scope_get(&vm), "x", ucv_int64_new(123)); + ucv_object_add(uc_vm_scope_get(&vm), "y", ucv_int64_new(456)); + + /* execute compiled program function */ + uc_value_t *last_expression_result = NULL; + int return_code = uc_vm_execute(&vm, progfunc, &last_expression_result); + + /* handle return status */ + switch (return_code) { + case STATUS_OK: + exit_code = 0; + + char *s = ucv_to_string(&vm, last_expression_result); + + printf("Program finished successfully.\n"); + printf("Function return value is %s\n", s); + free(s); + break; + + case STATUS_EXIT: + exit_code = (int)ucv_int64_get(last_expression_result); + + printf("The invoked program called exit().\n"); + printf("Exit code is %d\n", exit_code); + break; + + case ERROR_COMPILE: + exit_code = 1; + + printf("A compilation error occurred while running the program\n"); + break; + + case ERROR_RUNTIME: + exit_code = 2; + + printf("A runtime error occurred while running the program\n"); + break; + } + + /* free last expression result */ + ucv_put(last_expression_result); + + /* free VM context */ + uc_vm_free(&vm); + + return exit_code; +} diff --git a/examples/native-function.c b/examples/native-function.c new file mode 100644 index 0000000..9c643ec --- /dev/null +++ b/examples/native-function.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +#define MULTILINE_STRING(...) #__VA_ARGS__ + +static const char *program = MULTILINE_STRING( + {% + print("add() = " + add(5, 3.1, 2) + "\n"); + print("multiply() = " + multiply(7.3, 5) + "\n"); + %} +); + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +static uc_value_t * +multiply_two_numbers(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *x = uc_fn_arg(0); + uc_value_t *y = uc_fn_arg(1); + + return ucv_double_new(ucv_to_double(x) * ucv_to_double(y)); +} + +static uc_value_t * +add_all_numbers(uc_vm_t *vm, size_t nargs) +{ + double res = 0.0; + + for (size_t n = 0; n < nargs; n++) + res += ucv_to_double(uc_fn_arg(n)); + + return ucv_double_new(res); +} + +int main(int argc, char **argv) +{ + int exit_code = 0; + + /* create a source buffer containing the program code */ + uc_source_t *src = uc_source_new_buffer("my program", strdup(program), strlen(program)); + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* register our native functions as "add" and "multiply" */ + uc_function_register(uc_vm_scope_get(&vm), "add", add_all_numbers); + uc_function_register(uc_vm_scope_get(&vm), "multiply", multiply_two_numbers); + + /* execute program function */ + int return_code = uc_vm_execute(&vm, progfunc, NULL); + + /* handle return status */ + if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) { + printf("An error occurred while running the program\n"); + exit_code = 1; + } + + /* free VM context */ + uc_vm_free(&vm); + + return exit_code; +} diff --git a/examples/state-reset.c b/examples/state-reset.c new file mode 100644 index 0000000..692aa76 --- /dev/null +++ b/examples/state-reset.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +#define MULTILINE_STRING(...) #__VA_ARGS__ + +static const char *program = MULTILINE_STRING( + {% + /* the global test variable should've been reset since the previous run */ + print("Global variable is null? " + (global.test == null) + "\n"); + + global.test = true; + %} +); + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +int main(int argc, char **argv) +{ + int exit_code = 0; + + /* create a source buffer containing the program code */ + uc_source_t *src = uc_source_new_buffer("my program", strdup(program), strlen(program)); + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* execute compiled program function five times */ + for (int i = 0; i < 5; i++) { + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + printf("Iteration %d: ", i + 1); + + /* take additional reference to progfunc to avoid freeing it after execution */ + ucv_get(&progfunc->header); + + /* execute program function */ + int return_code = uc_vm_execute(&vm, progfunc, NULL); + + /* handle return status */ + if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) { + printf("An error occurred while running the program\n"); + exit_code = 1; + break; + } + + /* free VM context */ + uc_vm_free(&vm); + } + + /* release program function */ + ucv_put(&progfunc->header); + + return exit_code; +} diff --git a/examples/state-reuse.c b/examples/state-reuse.c new file mode 100644 index 0000000..7e2c44f --- /dev/null +++ b/examples/state-reuse.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <ucode/compiler.h> +#include <ucode/lib.h> +#include <ucode/vm.h> + + +#define MULTILINE_STRING(...) #__VA_ARGS__ + +static const char *program = MULTILINE_STRING( + {% + let n = global.value || 1; + + print("Current value is " + n + "\n"); + + global.value = n * 2; + %} +); + +static uc_parse_config_t config = { + .strict_declarations = false, + .lstrip_blocks = true, + .trim_blocks = true +}; + +int main(int argc, char **argv) +{ + int exit_code = 0; + + /* create a source buffer containing the program code */ + uc_source_t *src = uc_source_new_buffer("my program", strdup(program), strlen(program)); + + /* compile source buffer into function */ + char *syntax_error = NULL; + uc_function_t *progfunc = uc_compile(&config, src, &syntax_error); + + /* release source buffer */ + uc_source_put(src); + + /* check if compilation failed */ + if (!progfunc) { + fprintf(stderr, "Failed to compile program: %s\n", syntax_error); + + return 1; + } + + /* initialize VM context */ + uc_vm_t vm = { 0 }; + uc_vm_init(&vm, &config); + + /* load standard library into global VM scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* execute compiled program function five times */ + for (int i = 0; i < 5; i++) { + printf("Iteration %d: ", i + 1); + + /* take additional reference to progfunc to avoid freeing it after execution */ + ucv_get(&progfunc->header); + + /* execute program function */ + int return_code = uc_vm_execute(&vm, progfunc, NULL); + + /* handle return status */ + if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) { + printf("An error occurred while running the program\n"); + exit_code = 1; + break; + } + + /* perform GC step */ + ucv_gc(&vm); + } + + /* release program function */ + ucv_put(&progfunc->header); + + /* free VM context */ + uc_vm_free(&vm); + + return exit_code; +} diff --git a/chunk.h b/include/ucode/chunk.h index 2a8fa3a..0005e3c 100644 --- a/chunk.h +++ b/include/ucode/chunk.h @@ -20,20 +20,20 @@ #include <stdint.h> #include <stddef.h> -#include "value.h" +#include "vallist.h" #include "util.h" #include "types.h" -void uc_chunk_init(uc_chunk *chunk); -void uc_chunk_free(uc_chunk *chunk); -size_t uc_chunk_add(uc_chunk *chunk, uint8_t byte, size_t line); +void uc_chunk_init(uc_chunk_t *chunk); +void uc_chunk_free(uc_chunk_t *chunk); +size_t uc_chunk_add(uc_chunk_t *chunk, uint8_t byte, size_t line); -ssize_t uc_chunk_add_constant(uc_chunk *chunk, uc_value_t *value); -uc_value_t *uc_chunk_get_constant(uc_chunk *chunk, size_t idx); -void uc_chunk_pop(uc_chunk *chunk); +ssize_t uc_chunk_add_constant(uc_chunk_t *chunk, uc_value_t *value); +uc_value_t *uc_chunk_get_constant(uc_chunk_t *chunk, size_t idx); +void uc_chunk_pop(uc_chunk_t *chunk); -size_t uc_chunk_debug_get_srcpos(uc_chunk *chunk, size_t off); -void uc_chunk_debug_add_variable(uc_chunk *chunk, size_t from, size_t to, size_t slot, bool upval, uc_value_t *name); -uc_value_t *uc_chunk_debug_get_variable(uc_chunk *chunk, size_t off, size_t slot, bool upval); +size_t uc_chunk_debug_get_srcpos(uc_chunk_t *chunk, size_t off); +void uc_chunk_debug_add_variable(uc_chunk_t *chunk, size_t from, size_t to, size_t slot, bool upval, uc_value_t *name); +uc_value_t *uc_chunk_debug_get_variable(uc_chunk_t *chunk, size_t off, size_t slot, bool upval); #endif /* __CHUNK_H_ */ diff --git a/compiler.h b/include/ucode/compiler.h index 54f56c2..19fcf37 100644 --- a/compiler.h +++ b/include/ucode/compiler.h @@ -64,12 +64,10 @@ typedef enum { P_PRIMARY /* (…) */ } uc_precedence_t; -struct uc_patchlist { +typedef struct uc_patchlist { struct uc_patchlist *parent; size_t depth, count, *entries; -}; - -typedef struct uc_patchlist uc_patchlist; +} uc_patchlist_t; typedef struct { uc_value_t *name; @@ -77,45 +75,43 @@ typedef struct { size_t from; bool captured; bool constant; -} uc_local; +} uc_local_t; typedef struct { uc_value_t *name; size_t index; bool local; bool constant; -} uc_upval; +} uc_upval_t; -uc_declare_vector(uc_locals, uc_local); -uc_declare_vector(uc_upvals, uc_upval); -uc_declare_vector(uc_jmplist, size_t); +uc_declare_vector(uc_locals_t, uc_local_t); +uc_declare_vector(uc_upvals_t, uc_upval_t); +uc_declare_vector(uc_jmplist_t, size_t); typedef struct { - uc_parse_config *config; - uc_lexer lex; - uc_token prev, curr; + uc_parse_config_t *config; + uc_lexer_t lex; + uc_token_t prev, curr; bool synchronizing; uc_stringbuf_t *error; -} uc_parser; +} uc_parser_t; -struct uc_compiler { +typedef struct uc_compiler { struct uc_compiler *parent; - uc_locals locals; - uc_upvals upvals; - uc_patchlist *patchlist; + uc_locals_t locals; + uc_upvals_t upvals; + uc_patchlist_t *patchlist; uc_value_t *function; - uc_parser *parser; + uc_parser_t *parser; size_t scope_depth, current_srcpos, last_insn; -}; - -typedef struct uc_compiler uc_compiler; +} uc_compiler_t; typedef struct { - void (*prefix)(uc_compiler *, bool); - void (*infix)(uc_compiler *, bool); + void (*prefix)(uc_compiler_t *, bool); + void (*infix)(uc_compiler_t *, bool); uc_precedence_t precedence; -} uc_parse_rule; +} uc_parse_rule_t; -uc_function_t *uc_compile(uc_parse_config *config, uc_source *source, char **errp); +uc_function_t *uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp); #endif /* __COMPILER_H_ */ diff --git a/lexer.h b/include/ucode/lexer.h index 694c056..ee8a0a5 100644 --- a/lexer.h +++ b/include/ucode/lexer.h @@ -127,12 +127,12 @@ typedef struct { uc_tokentype_t type; uc_value_t *uv; size_t pos; -} uc_token; +} uc_token_t; typedef struct { uc_lex_state_t state; - uc_parse_config *config; - uc_source *source; + uc_parse_config_t *config; + uc_source_t *source; uint8_t eof:1; uint8_t is_escape:1; uint8_t no_regexp:1; @@ -142,7 +142,7 @@ typedef struct { size_t lookbehindlen; char *lookbehind; const void *tok; - uc_token curr; + uc_token_t curr; char esc[5]; uint8_t esclen; int lead_surrogate; @@ -159,17 +159,17 @@ typedef struct { STATEMENTS = '%', COMMENT = '#' } block; -} uc_lexer; +} uc_lexer_t; -void uc_lexer_init(uc_lexer *lex, uc_parse_config *config, uc_source *source); -void uc_lexer_free(uc_lexer *lex); +void uc_lexer_init(uc_lexer_t *lex, uc_parse_config_t *config, uc_source_t *source); +void uc_lexer_free(uc_lexer_t *lex); -uc_token *uc_lexer_next_token(uc_lexer *lex); +uc_token_t *uc_lexer_next_token(uc_lexer_t *lex); bool utf8enc(char **out, int *rem, int code); const char * -uc_get_tokenname(unsigned type); +uc_tokenname(unsigned type); #endif /* __LEXER_H_ */ diff --git a/include/ucode/lib.h b/include/ucode/lib.h new file mode 100644 index 0000000..1f30cba --- /dev/null +++ b/include/ucode/lib.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __LIB_H_ +#define __LIB_H_ + +#include "vm.h" +#include "lexer.h" + + +typedef struct { + const char *name; + uc_cfn_ptr_t func; +} uc_function_list_t; + +extern const uc_function_list_t uc_stdlib_functions[]; + +void uc_stdlib_load(uc_value_t *scope); + +bool uc_source_context_format(uc_stringbuf_t *buf, uc_source_t *src, size_t off, bool compact); +bool uc_error_context_format(uc_stringbuf_t *buf, uc_source_t *src, uc_value_t *stacktrace, size_t off); + + +/* vm helper */ + +static inline void * +_uc_fn_this(uc_vm_t *vm, const char *expected_type) +{ + return ucv_ressource_dataptr(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type); +} + +#define uc_fn_this(...) _uc_fn_this(vm, __VA_ARGS__) + +static inline uc_value_t * +_uc_fn_arg(uc_vm_t *vm, size_t nargs, size_t n) +{ + if (n >= nargs) + return NULL; + + return uc_vm_stack_peek(vm, nargs - n - 1); +} + +#define uc_fn_arg(...) _uc_fn_arg(vm, nargs, __VA_ARGS__) + +#define uc_call(nargs) uc_vm_call(vm, false, nargs) +#define uc_value_push(val) uc_vm_stack_push(vm, val) +#define uc_value_pop() uc_vm_stack_pop(vm) + + +/* ressource type helper */ + +static inline uc_value_t * +uc_ressource_new(uc_ressource_type_t *type, void *data) +{ + return ucv_ressource_new(type, data); +} + +static inline uc_ressource_type_t * +_uc_type_declare(uc_vm_t *vm, const char *name, const uc_function_list_t *list, size_t len, void (*freefn)(void *)) +{ + uc_value_t *proto = ucv_object_new(NULL); + + while (len-- > 0) + ucv_object_add(proto, list[len].name, + ucv_cfunction_new(list[len].name, list[len].func)); + + return ucv_ressource_type_add(vm, name, proto, freefn); +} + +#define uc_type_declare(vm, name, functions, freefn) \ + _uc_type_declare(vm, name, functions, ARRAY_SIZE(functions), freefn) + + +/* function helper */ + +#define uc_function_register(object, name, function) \ + ucv_object_add(object, name, ucv_cfunction_new(name, function)) + +static inline bool +_uc_function_list_register(uc_value_t *object, const uc_function_list_t *list, size_t len) +{ + bool rv = true; + + while (len-- > 0) + rv &= uc_function_register(object, list[len].name, list[len].func); + + return rv; +} + +#define uc_function_list_register(object, functions) \ + _uc_function_list_register(object, functions, ARRAY_SIZE(functions)) + +#endif /* __LIB_H_ */ diff --git a/module.h b/include/ucode/module.h index aa72074..1814b3a 100644 --- a/module.h +++ b/include/ucode/module.h @@ -20,34 +20,14 @@ #include "lib.h" #include "vm.h" -#define register_functions(scope, functions) \ - if (scope) \ - for (int i = 0; i < ARRAY_SIZE(functions); i++) \ - json_object_object_add(scope->header.jso, functions[i].name, \ - ops->value.cfunc(functions[i].name, functions[i].func)) -#define alloc_prototype(functions) ({ \ - uc_prototype *__proto = uc_object_as_prototype(ops->value.proto(NULL)); \ - register_functions(__proto, functions); \ - __proto; \ -}) +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) __attribute__((weak)); -#define declare_type(name, proto, freefn) \ - ucv_ressource_type_add(name, proto, freefn) - -#define alloc_ressource(data, type) \ - ucv_ressource_new(ucv_object_new(NULL), type, data) - -#define register_ressource(scope, key, res) \ - json_object_object_add((scope)->header.jso, key, (res)->header.jso) - -void uc_module_init(uc_value_t *scope) __attribute__((weak)); - -void uc_module_entry(uc_value_t *scope); -void uc_module_entry(uc_value_t *scope) +void uc_module_entry(uc_vm_t *vm, uc_value_t *scope); +void uc_module_entry(uc_vm_t *vm, uc_value_t *scope) { if (uc_module_init) - uc_module_init(scope); + uc_module_init(vm, scope); } #endif /* __MODULE_H_ */ diff --git a/source.h b/include/ucode/source.h index 6557a48..3de7c93 100644 --- a/source.h +++ b/include/ucode/source.h @@ -25,12 +25,12 @@ #include "types.h" -uc_source *uc_source_new_file(const char *path); -uc_source *uc_source_new_buffer(const char *name, char *buf, size_t len); +uc_source_t *uc_source_new_file(const char *path); +uc_source_t *uc_source_new_buffer(const char *name, char *buf, size_t len); -size_t uc_source_get_line(uc_source *source, size_t *offset); +size_t uc_source_get_line(uc_source_t *source, size_t *offset); -uc_source *uc_source_get(uc_source *source); -void uc_source_put(uc_source *source); +uc_source_t *uc_source_get(uc_source_t *source); +void uc_source_put(uc_source_t *source); #endif /* __SOURCE_H_ */ diff --git a/types.h b/include/ucode/types.h index a4377ad..7473f22 100644 --- a/types.h +++ b/include/ucode/types.h @@ -27,7 +27,7 @@ /* Value types and generic value header */ -typedef enum uc_type_t { +typedef enum uc_type { UC_NULL, UC_INTEGER, UC_BOOLEAN, @@ -43,7 +43,7 @@ typedef enum uc_type_t { UC_RESSOURCE } uc_type_t; -typedef struct uc_value_t { +typedef struct uc_value { uint32_t type:4; uint32_t mark:1; uint32_t u64:1; @@ -58,53 +58,53 @@ typedef struct { size_t dsize; uint64_t *index; char *data; -} uc_value_list; +} uc_value_list_t; /* Source buffer defintions */ -uc_declare_vector(uc_lineinfo, uint8_t); +uc_declare_vector(uc_lineinfo_t, uint8_t); typedef struct { char *filename, *buffer; FILE *fp; size_t usecount, off; - uc_lineinfo lineinfo; -} uc_source; + uc_lineinfo_t lineinfo; +} uc_source_t; /* Bytecode chunk defintions */ typedef struct { size_t from, to, target, slot; -} uc_ehrange; +} uc_ehrange_t; typedef struct { size_t from, to, slot, nameidx; -} uc_varrange; +} uc_varrange_t; -uc_declare_vector(uc_ehranges, uc_ehrange); -uc_declare_vector(uc_variables, uc_varrange); -uc_declare_vector(uc_offsetinfo, uint8_t); +uc_declare_vector(uc_ehranges_t, uc_ehrange_t); +uc_declare_vector(uc_variables_t, uc_varrange_t); +uc_declare_vector(uc_offsetinfo_t, uint8_t); typedef struct { size_t count; uint8_t *entries; - uc_value_list constants; - uc_ehranges ehranges; + uc_value_list_t constants; + uc_ehranges_t ehranges; struct { - uc_variables variables; - uc_value_list varnames; - uc_offsetinfo offsets; + uc_variables_t variables; + uc_value_list_t varnames; + uc_offsetinfo_t offsets; } debuginfo; -} uc_chunk; +} uc_chunk_t; /* Value type structures */ -typedef struct uc_weakref_t { - struct uc_weakref_t *prev; - struct uc_weakref_t *next; +typedef struct uc_weakref { + struct uc_weakref *prev; + struct uc_weakref *next; } uc_weakref_t; typedef struct { @@ -154,29 +154,29 @@ typedef struct { size_t nargs; size_t nupvals; size_t srcpos; - uc_chunk chunk; - uc_source *source; + uc_chunk_t chunk; + uc_source_t *source; char name[]; } uc_function_t; -typedef struct uc_upvalref_t { +typedef struct uc_upval_tref { uc_value_t header; size_t slot; bool closed; uc_value_t *value; - struct uc_upvalref_t *next; -} uc_upvalref_t; + struct uc_upval_tref *next; +} uc_upval_tref_t; typedef struct { uc_value_t header; uc_weakref_t ref; bool is_arrow; uc_function_t *function; - uc_upvalref_t **upvals; + uc_upval_tref_t **upvals; } uc_closure_t; -typedef struct uc_vm uc_vm; -typedef uc_value_t *(*uc_cfn_ptr_t)(uc_vm *, size_t); +typedef struct uc_vm uc_vm_t; +typedef uc_value_t *(*uc_cfn_ptr_t)(uc_vm_t *, size_t); typedef struct { uc_value_t header; @@ -185,18 +185,18 @@ typedef struct { } uc_cfunction_t; typedef struct { - uc_value_t header; - size_t type; - void *data; -} uc_ressource_t; - -typedef struct { const char *name; uc_value_t *proto; void (*free)(void *); } uc_ressource_type_t; -uc_declare_vector(uc_ressource_types_t, uc_ressource_type_t); +typedef struct { + uc_value_t header; + uc_ressource_type_t *type; + void *data; +} uc_ressource_t; + +uc_declare_vector(uc_ressource_types_t, uc_ressource_type_t *); /* Parser definitions */ @@ -206,7 +206,7 @@ typedef struct { bool trim_blocks; bool strict_declarations; bool raw_mode; -} uc_parse_config; +} uc_parse_config_t; /* VM definitions */ @@ -217,14 +217,15 @@ typedef enum { EXCEPTION_RUNTIME, EXCEPTION_TYPE, EXCEPTION_REFERENCE, - EXCEPTION_USER + EXCEPTION_USER, + EXCEPTION_EXIT } uc_exception_type_t; typedef struct { uc_exception_type_t type; uc_value_t *stacktrace; char *message; -} uc_exception; +} uc_exception_t; typedef struct { uint8_t *ip; @@ -233,22 +234,25 @@ typedef struct { size_t stackframe; uc_value_t *ctx; bool mcall, strict; -} uc_callframe; +} uc_callframe_t; -uc_declare_vector(uc_callframes, uc_callframe); -uc_declare_vector(uc_stack, uc_value_t *); +uc_declare_vector(uc_callframes_t, uc_callframe_t); +uc_declare_vector(uc_stack_t, uc_value_t *); typedef struct printbuf uc_stringbuf_t; +typedef void (uc_exception_handler_t)(uc_vm_t *, uc_exception_t *); + struct uc_vm { - uc_stack stack; - uc_exception exception; - uc_callframes callframes; - uc_upvalref_t *open_upvals; - uc_parse_config *config; + uc_stack_t stack; + uc_exception_t exception; + uc_callframes_t callframes; + uc_upval_tref_t *open_upvals; + uc_parse_config_t *config; uc_value_t *globals; - uc_source *sources; + uc_source_t *sources; uc_weakref_t values; + uc_ressource_types_t restypes; union { uint32_t u32; int32_t s32; @@ -260,6 +264,7 @@ struct uc_vm { size_t spread_values; uint8_t trace; uc_stringbuf_t *strbuf; + uc_exception_handler_t *exhandler; FILE *output; }; @@ -302,8 +307,8 @@ uint64_t ucv_uint64_get(uc_value_t *); uc_value_t *ucv_double_new(double); double ucv_double_get(uc_value_t *); -uc_value_t *ucv_array_new(uc_vm *); -uc_value_t *ucv_array_new_length(uc_vm *, size_t); +uc_value_t *ucv_array_new(uc_vm_t *); +uc_value_t *ucv_array_new_length(uc_vm_t *, size_t); uc_value_t *ucv_array_get(uc_value_t *, size_t); uc_value_t *ucv_array_pop(uc_value_t *); uc_value_t *ucv_array_push(uc_value_t *, uc_value_t *); @@ -314,7 +319,7 @@ bool ucv_array_delete(uc_value_t *, size_t, size_t); bool ucv_array_set(uc_value_t *, size_t, uc_value_t *); size_t ucv_array_length(uc_value_t *); -uc_value_t *ucv_object_new(uc_vm *); +uc_value_t *ucv_object_new(uc_vm_t *); uc_value_t *ucv_object_get(uc_value_t *, const char *, bool *); bool ucv_object_add(uc_value_t *, const char *, uc_value_t *); bool ucv_object_delete(uc_value_t *, const char *); @@ -332,15 +337,15 @@ size_t ucv_object_length(uc_value_t *); : 0); \ entry##key = entry_next##key) -uc_value_t *ucv_function_new(const char *, size_t, uc_source *); +uc_value_t *ucv_function_new(const char *, size_t, uc_source_t *); size_t ucv_function_srcpos(uc_value_t *, size_t); uc_value_t *ucv_cfunction_new(const char *, uc_cfn_ptr_t); -uc_value_t *ucv_closure_new(uc_vm *, uc_function_t *, bool); +uc_value_t *ucv_closure_new(uc_vm_t *, uc_function_t *, bool); -uc_ressource_type_t *ucv_ressource_type_add(const char *, uc_value_t *, void (*)(void *)); -uc_ressource_type_t *ucv_ressource_type_lookup(const char *); +uc_ressource_type_t *ucv_ressource_type_add(uc_vm_t *, const char *, uc_value_t *, void (*)(void *)); +uc_ressource_type_t *ucv_ressource_type_lookup(uc_vm_t *, const char *); uc_value_t *ucv_ressource_new(uc_ressource_type_t *, void *); void **ucv_ressource_dataptr(uc_value_t *, const char *); @@ -354,16 +359,37 @@ bool ucv_prototype_set(uc_value_t *, uc_value_t *); uc_value_t *ucv_property_get(uc_value_t *, const char *); -uc_value_t *ucv_from_json(uc_vm *, json_object *); +uc_value_t *ucv_from_json(uc_vm_t *, json_object *); json_object *ucv_to_json(uc_value_t *); -char *ucv_to_string(uc_vm *, uc_value_t *); -char *ucv_to_jsonstring_formatted(uc_vm *, uc_value_t *, char, size_t); -void ucv_to_stringbuf_formatted(uc_vm *, uc_stringbuf_t *, uc_value_t *, size_t, char, size_t); +char *ucv_to_string(uc_vm_t *, uc_value_t *); +char *ucv_to_jsonstring_formatted(uc_vm_t *, uc_value_t *, char, size_t); +void ucv_to_stringbuf_formatted(uc_vm_t *, uc_stringbuf_t *, uc_value_t *, size_t, char, size_t); #define ucv_to_jsonstring(vm, val) ucv_to_jsonstring_formatted(vm, val, '\1', 0) #define ucv_to_stringbuf(vm, buf, val, json) ucv_to_stringbuf_formatted(vm, buf, val, 0, json ? '\1' : '\0', 0) +uc_type_t ucv_cast_number(uc_value_t *, int64_t *, double *); + +static inline double +ucv_to_double(uc_value_t *v) +{ + int64_t n; + double d; + + return (ucv_cast_number(v, &n, &d) == UC_DOUBLE) ? d : (double)n; +} + +static inline int64_t +ucv_to_integer(uc_value_t *v) +{ + int64_t n; + double d; + + return (ucv_cast_number(v, &n, &d) == UC_DOUBLE) ? (int64_t)d : n; +} + + static inline bool ucv_is_callable(uc_value_t *uv) { @@ -407,6 +433,16 @@ ucv_is_scalar(uc_value_t *uv) } } +bool ucv_is_equal(uc_value_t *, uc_value_t *); +bool ucv_is_truish(uc_value_t *); + +bool ucv_compare(int, uc_value_t *, uc_value_t *); + +uc_value_t *ucv_key_get(uc_vm_t *, uc_value_t *, uc_value_t *); +uc_value_t *ucv_key_set(uc_vm_t *, uc_value_t *, uc_value_t *, uc_value_t *); +bool ucv_key_delete(uc_vm_t *, uc_value_t *, uc_value_t *); + + static inline bool ucv_is_marked(uc_value_t *uv) { @@ -427,8 +463,8 @@ ucv_clear_mark(uc_value_t *uv) uv->mark = false; } -bool ucv_equal(uc_value_t *, uc_value_t *); +void ucv_gc(uc_vm_t *); -void ucv_gc(uc_vm *, bool); +void ucv_freeall(uc_vm_t *); #endif /* __TYPES_H_ */ diff --git a/util.h b/include/ucode/util.h index c4ea087..858a3fd 100644 --- a/util.h +++ b/include/ucode/util.h @@ -36,8 +36,6 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif -#define JSON_C_TO_STRING_STRICT (1<<31) - /* vector macros */ @@ -71,16 +69,7 @@ (&((vec)->entries[(vec)->count - 1])) -/* debug helper */ - -static inline uint32_t getrefcnt(json_object *v) { - struct { - enum json_type o_type; - uint32_t _ref_count; - } *spy = (void *)v; - - return spy ? spy->_ref_count : 0; -} +/* "failsafe" utility functions */ static inline void *xalloc(size_t size) { void *ptr = calloc(1, size); @@ -93,9 +82,6 @@ static inline void *xalloc(size_t size) { return ptr; } - -/* "failsafe" utility functions */ - static inline void *xrealloc(void *ptr, size_t size) { ptr = realloc(ptr, size); @@ -118,95 +104,6 @@ static inline char *xstrdup(const char *s) { return ptr; } -static inline json_object *xjs_new_object(void) { - json_object *ptr = json_object_new_object(); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_array(void) { - json_object *ptr = json_object_new_array(); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_array_size(int size) { - json_object *ptr = json_object_new_array_ext(size); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_int64(int64_t n) { - json_object *ptr = json_object_new_int64(n); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_uint64(uint64_t n) { - json_object *ptr = json_object_new_uint64(n); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_string(const char *s) { - json_object *ptr = json_object_new_string(s); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_string_len(const char *s, size_t len) { - json_object *ptr = json_object_new_string_len(s, len); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - -static inline json_object *xjs_new_boolean(bool v) { - json_object *ptr = json_object_new_boolean(v); - - if (!ptr) { - fprintf(stderr, "Out of memory\n"); - abort(); - } - - return ptr; -} - - static inline struct json_tokener *xjs_new_tokener(void) { struct json_tokener *tok = json_tokener_new(); diff --git a/value.h b/include/ucode/vallist.h index 7d4e2b1..a3d94e8 100644 --- a/value.h +++ b/include/ucode/vallist.h @@ -41,20 +41,11 @@ typedef enum { TAG_PTR = 6 } uc_value_type_t; -bool uc_cmp(int how, uc_value_t *v1, uc_value_t *v2); -bool uc_val_is_truish(uc_value_t *val); +void uc_vallist_init(uc_value_list_t *list); +void uc_vallist_free(uc_value_list_t *list); -uc_type_t uc_cast_number(uc_value_t *v, int64_t *n, double *d); - -uc_value_t *uc_getval(uc_vm *, uc_value_t *scope, uc_value_t *key); -uc_value_t *uc_setval(uc_vm *, uc_value_t *scope, uc_value_t *key, uc_value_t *val); -bool uc_delval(uc_vm *, uc_value_t *scope, uc_value_t *key); - -void uc_vallist_init(uc_value_list *list); -void uc_vallist_free(uc_value_list *list); - -ssize_t uc_vallist_add(uc_value_list *list, uc_value_t *value); -uc_value_type_t uc_vallist_type(uc_value_list *list, size_t idx); -uc_value_t *uc_vallist_get(uc_value_list *list, size_t idx); +ssize_t uc_vallist_add(uc_value_list_t *list, uc_value_t *value); +uc_value_type_t uc_vallist_type(uc_value_list_t *list, size_t idx); +uc_value_t *uc_vallist_get(uc_value_list_t *list, size_t idx); #endif /* __VALUE_H_ */ diff --git a/vm.h b/include/ucode/vm.h index 4e8d428..553cf61 100644 --- a/vm.h +++ b/include/ucode/vm.h @@ -96,31 +96,42 @@ __insn(DELETE) #undef __insn #define __insn(_name) I_##_name, -enum insn_type { +typedef enum { __insns __I_MAX -}; +} uc_vm_insn_t; typedef enum { STATUS_OK, + STATUS_EXIT, ERROR_COMPILE, ERROR_RUNTIME } uc_vm_status_t; extern uint32_t insns[__I_MAX]; -void uc_vm_init(uc_vm *vm, uc_parse_config *config); -void uc_vm_free(uc_vm *vm); +void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config); +void uc_vm_free(uc_vm_t *vm); + +uc_value_t *uc_vm_scope_get(uc_vm_t *vm); +void uc_vm_scope_set(uc_vm_t *vm, uc_value_t *ctx); + +void uc_vm_stack_push(uc_vm_t *vm, uc_value_t *value); +uc_value_t *uc_vm_stack_pop(uc_vm_t *vm); +uc_value_t *uc_vm_stack_peek(uc_vm_t *vm, size_t offset); + +uc_exception_handler_t *uc_vm_exception_handler_get(uc_vm_t *vm); +void uc_vm_exception_handler_set(uc_vm_t *vm, uc_exception_handler_t *exhandler); -void uc_vm_stack_push(uc_vm *vm, uc_value_t *value); -uc_value_t *uc_vm_stack_pop(uc_vm *vm); -uc_value_t *uc_vm_stack_peek(uc_vm *vm, size_t offset); +uint32_t uc_vm_trace_get(uc_vm_t *vm); +void uc_vm_trace_set(uc_vm_t *vm, uint32_t level); -uc_exception_type_t uc_vm_call(uc_vm *vm, bool mcall, size_t nargs); +uc_exception_type_t uc_vm_call(uc_vm_t *vm, bool mcall, size_t nargs); void __attribute__((format(printf, 3, 0))) -uc_vm_raise_exception(uc_vm *vm, uc_exception_type_t type, const char *fmt, ...); +uc_vm_raise_exception(uc_vm_t *vm, uc_exception_type_t type, const char *fmt, ...); -uc_vm_status_t uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *modules); +uc_vm_status_t uc_vm_execute(uc_vm_t *vm, uc_function_t *fn, uc_value_t **retval); +uc_value_t *uc_vm_invoke(uc_vm_t *vm, const char *fname, size_t nargs, ...); #endif /* __VM_H_ */ @@ -25,9 +25,9 @@ #include <errno.h> #include <endian.h> -#include "vm.h" -#include "lib.h" -#include "lexer.h" +#include "ucode/vm.h" +#include "ucode/lib.h" +#include "ucode/lexer.h" #define UC_LEX_CONTINUE_PARSING (void *)1 @@ -44,7 +44,7 @@ struct token { char pat[4]; } u; unsigned plen; - uc_token *(*parse)(uc_lexer *); + uc_token_t *(*parse)(uc_lexer_t *); }; #define dec(o) \ @@ -54,11 +54,11 @@ struct token { (((x) >= 'a') ? (10 + (x) - 'a') : \ (((x) >= 'A') ? (10 + (x) - 'A') : dec(x))) -static uc_token *parse_comment(uc_lexer *); -static uc_token *parse_string(uc_lexer *); -static uc_token *parse_regexp(uc_lexer *); -static uc_token *parse_number(uc_lexer *); -static uc_token *parse_label(uc_lexer *); +static uc_token_t *parse_comment(uc_lexer_t *); +static uc_token_t *parse_string(uc_lexer_t *); +static uc_token_t *parse_regexp(uc_lexer_t *); +static uc_token_t *parse_number(uc_lexer_t *); +static uc_token_t *parse_label(uc_lexer_t *); static const struct token tokens[] = { { TK_ASLEFT, { .pat = "<<=" }, 3, NULL }, @@ -220,8 +220,8 @@ utf8enc(char **out, int *rem, int code) /* length of the longest token in our lookup table */ #define UC_LEX_MAX_TOKEN_LEN 3 -static uc_token * -emit_op(uc_lexer *lex, uint32_t pos, int type, uc_value_t *uv) +static uc_token_t * +emit_op(uc_lexer_t *lex, uint32_t pos, int type, uc_value_t *uv) { lex->curr.type = type; lex->curr.uv = uv; @@ -230,7 +230,7 @@ emit_op(uc_lexer *lex, uint32_t pos, int type, uc_value_t *uv) return &lex->curr; } -static void lookbehind_append(uc_lexer *lex, const char *data, size_t len) +static void lookbehind_append(uc_lexer_t *lex, const char *data, size_t len) { if (len) { lex->lookbehind = xrealloc(lex->lookbehind, lex->lookbehindlen + len); @@ -239,15 +239,15 @@ static void lookbehind_append(uc_lexer *lex, const char *data, size_t len) } } -static void lookbehind_reset(uc_lexer *lex) { +static void lookbehind_reset(uc_lexer_t *lex) { free(lex->lookbehind); lex->lookbehind = NULL; lex->lookbehindlen = 0; } -static uc_token * -lookbehind_to_text(uc_lexer *lex, uint32_t pos, int type, const char *strip_trailing_chars) { - uc_token *rv = NULL; +static uc_token_t * +lookbehind_to_text(uc_lexer_t *lex, uint32_t pos, int type, const char *strip_trailing_chars) { + uc_token_t *rv = NULL; if (lex->lookbehind) { if (strip_trailing_chars) { @@ -264,12 +264,12 @@ lookbehind_to_text(uc_lexer *lex, uint32_t pos, int type, const char *strip_trai } static inline size_t -buf_remaining(uc_lexer *lex) { +buf_remaining(uc_lexer_t *lex) { return (lex->bufend - lex->bufstart); } static inline bool -_buf_startswith(uc_lexer *lex, const char *str, size_t len) { +_buf_startswith(uc_lexer_t *lex, const char *str, size_t len) { return (buf_remaining(lex) >= len && !strncmp(lex->bufstart, str, len)); } @@ -290,18 +290,18 @@ _buf_startswith(uc_lexer *lex, const char *str, size_t len) { */ static void -next_lineinfo(uc_lexer *lex) +next_lineinfo(uc_lexer_t *lex) { - uc_lineinfo *lines = &lex->source->lineinfo; + uc_lineinfo_t *lines = &lex->source->lineinfo; uc_vector_grow(lines); lines->entries[lines->count++] = 0x80; } static void -update_lineinfo(uc_lexer *lex, size_t off) +update_lineinfo(uc_lexer_t *lex, size_t off) { - uc_lineinfo *lines = &lex->source->lineinfo; + uc_lineinfo_t *lines = &lex->source->lineinfo; uint8_t *entry, n; entry = uc_vector_last(lines); @@ -325,7 +325,7 @@ update_lineinfo(uc_lexer *lex, size_t off) } static void -buf_consume(uc_lexer *lex, size_t len) { +buf_consume(uc_lexer_t *lex, size_t len) { size_t i, linelen; if (!lex->source->lineinfo.count) @@ -350,8 +350,8 @@ buf_consume(uc_lexer *lex, size_t len) { lex->source->off += len; } -static uc_token * -parse_comment(uc_lexer *lex) +static uc_token_t * +parse_comment(uc_lexer_t *lex) { const struct token *tok = lex->tok; const char *ptr, *end; @@ -387,7 +387,7 @@ parse_comment(uc_lexer *lex) } static void -append_utf8(uc_lexer *lex, int code) { +append_utf8(uc_lexer_t *lex, int code) { char ustr[8], *up; int rem; @@ -398,13 +398,13 @@ append_utf8(uc_lexer *lex, int code) { lookbehind_append(lex, ustr, up - ustr); } -static uc_token * -parse_string(uc_lexer *lex) +static uc_token_t * +parse_string(uc_lexer_t *lex) { const struct token *tok = lex->tok; char q = tok->u.pat[0]; char *ptr, *c; - uc_token *rv; + uc_token_t *rv; int code; if (!buf_remaining(lex)) @@ -626,11 +626,11 @@ enum { UC_LEX_PARSE_REGEX_FLAGS }; -static uc_token * -parse_regexp(uc_lexer *lex) +static uc_token_t * +parse_regexp(uc_lexer_t *lex) { bool is_reg_global = false, is_reg_icase = false, is_reg_newline = false; - uc_token *rv; + uc_token_t *rv; size_t len; char *s; @@ -663,7 +663,7 @@ parse_regexp(uc_lexer *lex) break; case UC_LEX_PARSE_REGEX_FLAGS: - rv = (uc_token *)lex->lookbehind; + rv = (uc_token_t *)lex->lookbehind; while (lex->bufstart < lex->bufend || lex->eof) { switch (lex->eof ? EOF : lex->bufstart[0]) { @@ -717,8 +717,8 @@ parse_regexp(uc_lexer *lex) * -UC_ERROR_OVERLONG_STRING Label too long */ -static uc_token * -parse_label(uc_lexer *lex) +static uc_token_t * +parse_label(uc_lexer_t *lex) { const struct token *tok = lex->tok; const struct keyword *word; @@ -763,7 +763,7 @@ parse_label(uc_lexer *lex) */ static inline bool -is_numeric_char(uc_lexer *lex, char c) +is_numeric_char(uc_lexer_t *lex, char c) { char prev = lex->lookbehindlen ? lex->lookbehind[lex->lookbehindlen-1] : 0; @@ -773,11 +773,11 @@ is_numeric_char(uc_lexer *lex, char c) return prev ? (isxdigit(c) || c == 'x' || c == 'X' || c == '.') : (isdigit(c) || c == '.'); } -static uc_token * -parse_number(uc_lexer *lex) +static uc_token_t * +parse_number(uc_lexer_t *lex) { const struct token *tok = lex->tok; - uc_token *rv = NULL; + uc_token_t *rv = NULL; long long int n; char *ptr, *e; double d; @@ -826,15 +826,15 @@ parse_number(uc_lexer *lex) return NULL; } -static uc_token * -lex_step(uc_lexer *lex, FILE *fp) +static uc_token_t * +lex_step(uc_lexer_t *lex, FILE *fp) { uint32_t masks[] = { 0, le32toh(0x000000ff), le32toh(0x0000ffff), le32toh(0x00ffffff), le32toh(0xffffffff) }; union { uint32_t n; char str[4]; } search; const struct token *tok; size_t rlen, rem; char *ptr, c; - uc_token *rv; + uc_token_t *rv; size_t i; /* only less than UC_LEX_MAX_TOKEN_LEN unread buffer chars remaining, @@ -1132,9 +1132,9 @@ lex_step(uc_lexer *lex, FILE *fp) } static void -uc_lexer_skip_shebang(uc_lexer *lex) +uc_lexer_skip_shebang(uc_lexer_t *lex) { - uc_source *source = lex->source; + uc_source_t *source = lex->source; FILE *fp = source->fp; int c1, c2; @@ -1164,7 +1164,7 @@ uc_lexer_skip_shebang(uc_lexer *lex) } void -uc_lexer_init(uc_lexer *lex, uc_parse_config *config, uc_source *source) +uc_lexer_init(uc_lexer_t *lex, uc_parse_config_t *config, uc_source_t *source) { lex->state = UC_LEX_IDENTIFY_BLOCK; @@ -1205,7 +1205,7 @@ uc_lexer_init(uc_lexer *lex, uc_parse_config *config, uc_source *source) } void -uc_lexer_free(uc_lexer *lex) +uc_lexer_free(uc_lexer_t *lex) { uc_source_put(lex->source); @@ -1213,10 +1213,10 @@ uc_lexer_free(uc_lexer *lex) free(lex->buf); } -uc_token * -uc_lexer_next_token(uc_lexer *lex) +uc_token_t * +uc_lexer_next_token(uc_lexer_t *lex) { - uc_token *rv = NULL; + uc_token_t *rv = NULL; while (lex->state != UC_LEX_EOF) { rv = lex_step(lex, lex->source->fp); @@ -1236,7 +1236,7 @@ uc_lexer_next_token(uc_lexer *lex) } const char * -uc_get_tokenname(unsigned type) +uc_tokenname(unsigned type) { static char buf[sizeof("'endfunction'")]; size_t i; @@ -32,11 +32,11 @@ #include <sys/wait.h> #include <fnmatch.h> -#include "lexer.h" -#include "compiler.h" -#include "vm.h" -#include "lib.h" -#include "source.h" +#include "ucode/lexer.h" +#include "ucode/compiler.h" +#include "ucode/vm.h" +#include "ucode/lib.h" +#include "ucode/source.h" static void format_context_line(uc_stringbuf_t *buf, const char *line, size_t off, bool compact) @@ -94,7 +94,7 @@ format_context_line(uc_stringbuf_t *buf, const char *line, size_t off, bool comp } static char * -source_filename(uc_source *src, uint32_t line) +source_filename(uc_source_t *src, uint32_t line) { const char *name = src->filename ? basename(src->filename) : "[?]"; static char buf[sizeof("xxxxxxxxx.uc:0000000000")]; @@ -109,7 +109,7 @@ source_filename(uc_source *src, uint32_t line) } bool -format_source_context(uc_stringbuf_t *buf, uc_source *src, size_t off, bool compact) +uc_source_context_format(uc_stringbuf_t *buf, uc_source_t *src, size_t off, bool compact) { size_t len, rlen; bool truncated; @@ -155,7 +155,7 @@ format_source_context(uc_stringbuf_t *buf, uc_source *src, size_t off, bool comp } bool -format_error_context(uc_stringbuf_t *buf, uc_source *src, uc_value_t *stacktrace, size_t off) +uc_error_context_format(uc_stringbuf_t *buf, uc_source_t *src, uc_value_t *stacktrace, size_t off) { uc_value_t *e, *fn, *file, *line, *byte; const char *path; @@ -201,10 +201,10 @@ format_error_context(uc_stringbuf_t *buf, uc_source *src, uc_value_t *stacktrace } } - return format_source_context(buf, src, off, false); + return uc_source_context_format(buf, src, off, false); } -static char *uc_cast_string(uc_vm *vm, uc_value_t **v, bool *freeable) { +static char *uc_cast_string(uc_vm_t *vm, uc_value_t **v, bool *freeable) { if (ucv_type(*v) == UC_STRING) { *freeable = false; @@ -223,7 +223,7 @@ uc_cast_double(uc_value_t *v) int64_t n; double d; - t = uc_cast_number(v, &n, &d); + t = ucv_cast_number(v, &n, &d); errno = 0; if (t == UC_DOUBLE) { @@ -245,7 +245,7 @@ uc_cast_int64(uc_value_t *v) int64_t n; double d; - t = uc_cast_number(v, &n, &d); + t = ucv_cast_number(v, &n, &d); errno = 0; if (t == UC_DOUBLE) { @@ -263,7 +263,7 @@ uc_cast_int64(uc_value_t *v) } static void -uc_vm_ctx_push(uc_vm *vm) +uc_vm_ctx_push(uc_vm_t *vm) { uc_value_t *ctx = NULL; @@ -274,7 +274,7 @@ uc_vm_ctx_push(uc_vm *vm) } static uc_value_t * -uc_print_common(uc_vm *vm, size_t nargs, FILE *fh) +uc_print_common(uc_vm_t *vm, size_t nargs, FILE *fh) { uc_value_t *item; size_t reslen = 0; @@ -283,7 +283,7 @@ uc_print_common(uc_vm *vm, size_t nargs, FILE *fh) char *p; for (arridx = 0; arridx < nargs; arridx++) { - item = uc_get_arg(arridx); + item = uc_fn_arg(arridx); if (ucv_type(item) == UC_STRING) { len = ucv_string_length(item); @@ -302,15 +302,15 @@ uc_print_common(uc_vm *vm, size_t nargs, FILE *fh) static uc_value_t * -uc_print(uc_vm *vm, size_t nargs) +uc_print(uc_vm_t *vm, size_t nargs) { return uc_print_common(vm, nargs, vm->output); } static uc_value_t * -uc_length(uc_vm *vm, size_t nargs) +uc_length(uc_vm_t *vm, size_t nargs) { - uc_value_t *arg = uc_get_arg(0); + uc_value_t *arg = uc_fn_arg(0); switch (ucv_type(arg)) { case UC_OBJECT: @@ -328,10 +328,10 @@ uc_length(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_index(uc_vm *vm, size_t nargs, bool right) +uc_index(uc_vm_t *vm, size_t nargs, bool right) { - uc_value_t *stack = uc_get_arg(0); - uc_value_t *needle = uc_get_arg(1); + uc_value_t *stack = uc_fn_arg(0); + uc_value_t *needle = uc_fn_arg(1); const char *sstr, *nstr, *p; size_t arridx, len; ssize_t ret = -1; @@ -339,7 +339,7 @@ uc_index(uc_vm *vm, size_t nargs, bool right) switch (ucv_type(stack)) { case UC_ARRAY: for (arridx = 0, len = ucv_array_length(stack); arridx < len; arridx++) { - if (uc_cmp(I_EQ, ucv_array_get(stack, arridx), needle)) { + if (ucv_compare(I_EQ, ucv_array_get(stack, arridx), needle)) { ret = (ssize_t)arridx; if (!right) @@ -371,21 +371,21 @@ uc_index(uc_vm *vm, size_t nargs, bool right) } static uc_value_t * -uc_lindex(uc_vm *vm, size_t nargs) +uc_lindex(uc_vm_t *vm, size_t nargs) { return uc_index(vm, nargs, false); } static uc_value_t * -uc_rindex(uc_vm *vm, size_t nargs) +uc_rindex(uc_vm_t *vm, size_t nargs) { return uc_index(vm, nargs, true); } static uc_value_t * -uc_push(uc_vm *vm, size_t nargs) +uc_push(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); + uc_value_t *arr = uc_fn_arg(0); uc_value_t *item = NULL; size_t arridx; @@ -393,7 +393,7 @@ uc_push(uc_vm *vm, size_t nargs) return NULL; for (arridx = 1; arridx < nargs; arridx++) { - item = uc_get_arg(arridx); + item = uc_fn_arg(arridx); ucv_array_push(arr, ucv_get(item)); } @@ -401,25 +401,25 @@ uc_push(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_pop(uc_vm *vm, size_t nargs) +uc_pop(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); + uc_value_t *arr = uc_fn_arg(0); return ucv_array_pop(arr); } static uc_value_t * -uc_shift(uc_vm *vm, size_t nargs) +uc_shift(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); + uc_value_t *arr = uc_fn_arg(0); return ucv_array_shift(arr); } static uc_value_t * -uc_unshift(uc_vm *vm, size_t nargs) +uc_unshift(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); + uc_value_t *arr = uc_fn_arg(0); uc_value_t *item = NULL; size_t i; @@ -427,7 +427,7 @@ uc_unshift(uc_vm *vm, size_t nargs) return NULL; for (i = 1; i < nargs; i++) { - item = uc_get_arg(i); + item = uc_fn_arg(i); ucv_array_unshift(arr, ucv_get(item)); } @@ -435,7 +435,7 @@ uc_unshift(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_chr(uc_vm *vm, size_t nargs) +uc_chr(uc_vm_t *vm, size_t nargs) { uc_value_t *rv = NULL; size_t idx; @@ -448,7 +448,7 @@ uc_chr(uc_vm *vm, size_t nargs) str = xalloc(nargs); for (idx = 0; idx < nargs; idx++) { - n = uc_cast_int64(uc_get_arg(idx)); + n = uc_cast_int64(uc_fn_arg(idx)); if (n < 0) n = 0; @@ -465,9 +465,9 @@ uc_chr(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_die(uc_vm *vm, size_t nargs) +uc_die(uc_vm_t *vm, size_t nargs) { - uc_value_t *msg = uc_get_arg(0); + uc_value_t *msg = uc_fn_arg(0); bool freeable = false; char *s; @@ -482,10 +482,10 @@ uc_die(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_exists(uc_vm *vm, size_t nargs) +uc_exists(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); - uc_value_t *key = uc_get_arg(1); + uc_value_t *obj = uc_fn_arg(0); + uc_value_t *key = uc_fn_arg(1); bool found, freeable; char *k; @@ -502,18 +502,21 @@ uc_exists(uc_vm *vm, size_t nargs) return ucv_boolean_new(found); } -__attribute__((noreturn)) static uc_value_t * -uc_exit(uc_vm *vm, size_t nargs) +static uc_value_t * +uc_exit(uc_vm_t *vm, size_t nargs) { - int64_t n = uc_cast_int64(uc_get_arg(0)); + int64_t n = uc_cast_int64(uc_fn_arg(0)); + + vm->arg.s32 = (int32_t)n; + uc_vm_raise_exception(vm, EXCEPTION_EXIT, "Terminated"); - exit(n); + return NULL; } static uc_value_t * -uc_getenv(uc_vm *vm, size_t nargs) +uc_getenv(uc_vm_t *vm, size_t nargs) { - uc_value_t *key = uc_get_arg(0); + uc_value_t *key = uc_fn_arg(0); char *k = ucv_string_get(key); char *val = k ? getenv(k) : NULL; @@ -521,10 +524,10 @@ uc_getenv(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_filter(uc_vm *vm, size_t nargs) +uc_filter(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); - uc_value_t *func = uc_get_arg(1); + uc_value_t *obj = uc_fn_arg(0); + uc_value_t *func = uc_fn_arg(1); uc_value_t *rv, *arr; size_t arridx, arrlen; @@ -548,7 +551,7 @@ uc_filter(uc_vm *vm, size_t nargs) rv = uc_vm_stack_pop(vm); - if (uc_val_is_truish(rv)) + if (ucv_is_truish(rv)) ucv_array_push(arr, ucv_get(ucv_array_get(obj, arridx))); ucv_put(rv); @@ -558,9 +561,9 @@ uc_filter(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_hex(uc_vm *vm, size_t nargs) +uc_hex(uc_vm_t *vm, size_t nargs) { - uc_value_t *val = uc_get_arg(0); + uc_value_t *val = uc_fn_arg(0); char *e, *v; int64_t n; @@ -578,9 +581,9 @@ uc_hex(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_int(uc_vm *vm, size_t nargs) +uc_int(uc_vm_t *vm, size_t nargs) { - int64_t n = uc_cast_int64(uc_get_arg(0)); + int64_t n = uc_cast_int64(uc_fn_arg(0)); if (errno == EINVAL || errno == EOVERFLOW) return ucv_double_new(NAN); @@ -589,10 +592,10 @@ uc_int(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_join(uc_vm *vm, size_t nargs) +uc_join(uc_vm_t *vm, size_t nargs) { - uc_value_t *sep = uc_get_arg(0); - uc_value_t *arr = uc_get_arg(1); + uc_value_t *sep = uc_fn_arg(0); + uc_value_t *arr = uc_fn_arg(1); size_t arrlen, arridx; uc_stringbuf_t *buf; @@ -612,9 +615,9 @@ uc_join(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_keys(uc_vm *vm, size_t nargs) +uc_keys(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); + uc_value_t *obj = uc_fn_arg(0); uc_value_t *arr = NULL; if (ucv_type(obj) != UC_OBJECT) @@ -631,9 +634,9 @@ uc_keys(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_lc(uc_vm *vm, size_t nargs) +uc_lc(uc_vm_t *vm, size_t nargs) { - char *str = ucv_to_string(vm, uc_get_arg(0)); + char *str = ucv_to_string(vm, uc_fn_arg(0)); uc_value_t *rv = NULL; char *p; @@ -652,10 +655,10 @@ uc_lc(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_map(uc_vm *vm, size_t nargs) +uc_map(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); - uc_value_t *func = uc_get_arg(1); + uc_value_t *obj = uc_fn_arg(0); + uc_value_t *func = uc_fn_arg(1); uc_value_t *arr, *rv; size_t arridx, arrlen; @@ -686,9 +689,9 @@ uc_map(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_ord(uc_vm *vm, size_t nargs) +uc_ord(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); + uc_value_t *obj = uc_fn_arg(0); uc_value_t *rv, *pos; const char *str; size_t i, len; @@ -706,7 +709,7 @@ uc_ord(uc_vm *vm, size_t nargs) rv = ucv_array_new(vm); for (i = 1; i < nargs; i++) { - pos = uc_get_arg(i); + pos = uc_fn_arg(i); if (ucv_type(pos) == UC_INTEGER) { n = ucv_int64_get(pos); @@ -727,9 +730,9 @@ uc_ord(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_type(uc_vm *vm, size_t nargs) +uc_type(uc_vm_t *vm, size_t nargs) { - uc_value_t *v = uc_get_arg(0); + uc_value_t *v = uc_fn_arg(0); uc_type_t t = ucv_type(v); switch (t) { @@ -753,9 +756,9 @@ uc_type(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_reverse(uc_vm *vm, size_t nargs) +uc_reverse(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); + uc_value_t *obj = uc_fn_arg(0); uc_value_t *rv = NULL; size_t len, arridx; const char *str; @@ -785,7 +788,7 @@ uc_reverse(uc_vm *vm, size_t nargs) static struct { - uc_vm *vm; + uc_vm_t *vm; bool ex; uc_value_t *fn; } sort_ctx; @@ -801,8 +804,8 @@ default_cmp(uc_value_t *v1, uc_value_t *v2) if (ucv_type(v1) == UC_INTEGER || ucv_type(v1) == UC_DOUBLE || ucv_type(v2) == UC_INTEGER || ucv_type(v2) == UC_DOUBLE) { - t1 = uc_cast_number(v1, &n1, &d1); - t2 = uc_cast_number(v2, &n2, &d2); + t1 = ucv_cast_number(v1, &n1, &d1); + t2 = ucv_cast_number(v2, &n2, &d2); if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) { d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1; @@ -865,7 +868,7 @@ sort_fn(const void *k1, const void *k2) } rv = uc_vm_stack_pop(sort_ctx.vm); - t = uc_cast_number(rv, &n, &d); + t = ucv_cast_number(rv, &n, &d); if (t == UC_DOUBLE) { if (d < 0) @@ -888,10 +891,10 @@ sort_fn(const void *k1, const void *k2) } static uc_value_t * -uc_sort(uc_vm *vm, size_t nargs) +uc_sort(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); - uc_value_t *fn = uc_get_arg(1); + uc_value_t *arr = uc_fn_arg(0); + uc_value_t *fn = uc_fn_arg(1); if (ucv_type(arr) != UC_ARRAY) return NULL; @@ -905,11 +908,11 @@ uc_sort(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_splice(uc_vm *vm, size_t nargs) +uc_splice(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); - int64_t ofs = uc_cast_int64(uc_get_arg(1)); - int64_t remlen = uc_cast_int64(uc_get_arg(2)); + uc_value_t *arr = uc_fn_arg(0); + int64_t ofs = uc_cast_int64(uc_fn_arg(1)); + int64_t remlen = uc_cast_int64(uc_fn_arg(2)); size_t arrlen, addlen, idx; if (ucv_type(arr) != UC_ARRAY) @@ -972,16 +975,16 @@ uc_splice(uc_vm *vm, size_t nargs) for (idx = 0; idx < addlen; idx++) ucv_array_set(arr, ofs + idx, - ucv_get(uc_get_arg(3 + idx))); + ucv_get(uc_fn_arg(3 + idx))); return ucv_get(arr); } static uc_value_t * -uc_split(uc_vm *vm, size_t nargs) +uc_split(uc_vm_t *vm, size_t nargs) { - uc_value_t *str = uc_get_arg(0); - uc_value_t *sep = uc_get_arg(1); + uc_value_t *str = uc_fn_arg(0); + uc_value_t *sep = uc_fn_arg(1); uc_value_t *arr = NULL; const char *p, *sepstr, *splitstr; int eflags = 0, res; @@ -1037,11 +1040,11 @@ uc_split(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_substr(uc_vm *vm, size_t nargs) +uc_substr(uc_vm_t *vm, size_t nargs) { - uc_value_t *str = uc_get_arg(0); - int64_t ofs = uc_cast_int64(uc_get_arg(1)); - int64_t sublen = uc_cast_int64(uc_get_arg(2)); + uc_value_t *str = uc_fn_arg(0); + int64_t ofs = uc_cast_int64(uc_fn_arg(1)); + int64_t sublen = uc_cast_int64(uc_fn_arg(2)); const char *p; size_t len; @@ -1101,7 +1104,7 @@ uc_substr(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_time(uc_vm *vm, size_t nargs) +uc_time(uc_vm_t *vm, size_t nargs) { time_t t = time(NULL); @@ -1109,9 +1112,9 @@ uc_time(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uc(uc_vm *vm, size_t nargs) +uc_uc(uc_vm_t *vm, size_t nargs) { - char *str = ucv_to_string(vm, uc_get_arg(0)); + char *str = ucv_to_string(vm, uc_fn_arg(0)); uc_value_t *rv = NULL; char *p; @@ -1130,7 +1133,7 @@ uc_uc(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uchr(uc_vm *vm, size_t nargs) +uc_uchr(uc_vm_t *vm, size_t nargs) { uc_value_t *rv = NULL; size_t idx, ulen; @@ -1139,7 +1142,7 @@ uc_uchr(uc_vm *vm, size_t nargs) int rem; for (idx = 0, ulen = 0; idx < nargs; idx++) { - n = uc_cast_int64(uc_get_arg(idx)); + n = uc_cast_int64(uc_fn_arg(idx)); if (errno == EINVAL || errno == EOVERFLOW || n < 0 || n > 0x10FFFF) ulen += 3; @@ -1156,7 +1159,7 @@ uc_uchr(uc_vm *vm, size_t nargs) str = xalloc(ulen); for (idx = 0, p = str, rem = ulen; idx < nargs; idx++) { - n = uc_cast_int64(uc_get_arg(idx)); + n = uc_cast_int64(uc_fn_arg(idx)); if (errno == EINVAL || errno == EOVERFLOW || n < 0 || n > 0x10FFFF) n = 0xFFFD; @@ -1173,9 +1176,9 @@ uc_uchr(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_values(uc_vm *vm, size_t nargs) +uc_values(uc_vm_t *vm, size_t nargs) { - uc_value_t *obj = uc_get_arg(0); + uc_value_t *obj = uc_fn_arg(0); uc_value_t *arr; if (ucv_type(obj) != UC_OBJECT) @@ -1192,10 +1195,10 @@ uc_values(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_trim_common(uc_vm *vm, size_t nargs, bool start, bool end) +uc_trim_common(uc_vm_t *vm, size_t nargs, bool start, bool end) { - uc_value_t *str = uc_get_arg(0); - uc_value_t *chr = uc_get_arg(1); + uc_value_t *str = uc_fn_arg(0); + uc_value_t *chr = uc_fn_arg(1); const char *p, *c; size_t len; @@ -1232,27 +1235,27 @@ uc_trim_common(uc_vm *vm, size_t nargs, bool start, bool end) } static uc_value_t * -uc_trim(uc_vm *vm, size_t nargs) +uc_trim(uc_vm_t *vm, size_t nargs) { return uc_trim_common(vm, nargs, true, true); } static uc_value_t * -uc_ltrim(uc_vm *vm, size_t nargs) +uc_ltrim(uc_vm_t *vm, size_t nargs) { return uc_trim_common(vm, nargs, true, false); } static uc_value_t * -uc_rtrim(uc_vm *vm, size_t nargs) +uc_rtrim(uc_vm_t *vm, size_t nargs) { return uc_trim_common(vm, nargs, false, true); } static void -uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) +uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf) { - uc_value_t *fmt = uc_get_arg(0); + uc_value_t *fmt = uc_fn_arg(0); char *fp, sfmt[sizeof("%0- 123456789.123456789%")]; union { char *s; int64_t n; double d; } arg; const char *fstr, *last, *p; @@ -1342,7 +1345,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) t = UC_INTEGER; if (argidx < nargs) - arg.n = uc_cast_int64(uc_get_arg(argidx++)); + arg.n = uc_cast_int64(uc_fn_arg(argidx++)); else arg.n = 0; @@ -1357,7 +1360,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) t = UC_DOUBLE; if (argidx < nargs) - arg.d = uc_cast_double(uc_get_arg(argidx++)); + arg.d = uc_cast_double(uc_fn_arg(argidx++)); else arg.d = 0; @@ -1367,7 +1370,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) t = UC_INTEGER; if (argidx < nargs) - arg.n = uc_cast_int64(uc_get_arg(argidx++)) & 0xff; + arg.n = uc_cast_int64(uc_fn_arg(argidx++)) & 0xff; else arg.n = 0; @@ -1377,7 +1380,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) t = UC_STRING; if (argidx < nargs) - arg.s = ucv_to_string(vm, uc_get_arg(argidx++)); + arg.s = ucv_to_string(vm, uc_fn_arg(argidx++)); else arg.s = NULL; @@ -1400,7 +1403,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf) if (argidx < nargs) { arg.s = ucv_to_jsonstring_formatted(vm, - uc_get_arg(argidx++), + uc_fn_arg(argidx++), pad_size > 0 ? (pad_size > 1 ? ' ' : '\t') : '\0', pad_size > 0 ? (pad_size > 1 ? pad_size - 1 : 1) : 0); } @@ -1463,7 +1466,7 @@ next: } static uc_value_t * -uc_sprintf(uc_vm *vm, size_t nargs) +uc_sprintf(uc_vm_t *vm, size_t nargs) { uc_stringbuf_t *buf = ucv_stringbuf_new(); @@ -1473,7 +1476,7 @@ uc_sprintf(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_printf(uc_vm *vm, size_t nargs) +uc_printf(uc_vm_t *vm, size_t nargs) { uc_stringbuf_t *buf = xprintbuf_new(); size_t len; @@ -1488,9 +1491,9 @@ uc_printf(uc_vm *vm, size_t nargs) } static bool -uc_require_so(uc_vm *vm, const char *path, uc_value_t **res) +uc_require_so(uc_vm_t *vm, const char *path, uc_value_t **res) { - void (*init)(uc_value_t *); + void (*init)(uc_vm_t *, uc_value_t *); uc_value_t *scope; struct stat st; void *dlh; @@ -1519,7 +1522,7 @@ uc_require_so(uc_vm *vm, const char *path, uc_value_t **res) scope = ucv_object_new(vm); - init(scope); + init(vm, scope); *res = scope; @@ -1527,13 +1530,13 @@ uc_require_so(uc_vm *vm, const char *path, uc_value_t **res) } static bool -uc_require_ucode(uc_vm *vm, const char *path, uc_value_t *scope, uc_value_t **res) +uc_require_ucode(uc_vm_t *vm, const char *path, uc_value_t *scope, uc_value_t **res) { uc_exception_type_t extype; uc_function_t *function; uc_value_t *prev_scope; uc_value_t *closure; - uc_source *source; + uc_source_t *source; struct stat st; char *err; @@ -1565,12 +1568,15 @@ uc_require_ucode(uc_vm *vm, const char *path, uc_value_t *scope, uc_value_t **re uc_vm_stack_push(vm, closure); - prev_scope = vm->globals; - vm->globals = scope ? scope : prev_scope; + if (scope) { + prev_scope = ucv_get(uc_vm_scope_get(vm)); + uc_vm_scope_set(vm, ucv_get(scope)); + } extype = uc_vm_call(vm, false, 0); - vm->globals = prev_scope; + if (scope) + uc_vm_scope_set(vm, prev_scope); if (extype == EXCEPTION_NONE) *res = uc_vm_stack_pop(vm); @@ -1581,14 +1587,14 @@ uc_require_ucode(uc_vm *vm, const char *path, uc_value_t *scope, uc_value_t **re } static bool -uc_require_path(uc_vm *vm, const char *path_template, const char *name, uc_value_t **res) +uc_require_path(uc_vm_t *vm, const char *path_template, const char *name, uc_value_t **res) { uc_stringbuf_t *buf = xprintbuf_new(); const char *p, *q, *last; uc_value_t *modtable; bool rv; - modtable = ucv_property_get(vm->globals, "modules"); + modtable = ucv_property_get(uc_vm_scope_get(vm), "modules"); *res = ucv_object_get(modtable, name, &rv); if (rv) @@ -1635,9 +1641,9 @@ out: } static uc_value_t * -uc_require(uc_vm *vm, size_t nargs) +uc_require(uc_vm_t *vm, size_t nargs) { - uc_value_t *val = uc_get_arg(0); + uc_value_t *val = uc_fn_arg(0); uc_value_t *search, *se, *res; size_t arridx, arrlen; const char *name; @@ -1646,7 +1652,7 @@ uc_require(uc_vm *vm, size_t nargs) return NULL; name = ucv_string_get(val); - search = ucv_property_get(vm->globals, "REQUIRE_SEARCH_PATH"); + search = ucv_property_get(uc_vm_scope_get(vm), "REQUIRE_SEARCH_PATH"); if (ucv_type(search) != UC_ARRAY) { uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, @@ -1672,9 +1678,9 @@ uc_require(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_iptoarr(uc_vm *vm, size_t nargs) +uc_iptoarr(uc_vm_t *vm, size_t nargs) { - uc_value_t *ip = uc_get_arg(0); + uc_value_t *ip = uc_fn_arg(0); uc_value_t *res; union { uint8_t u8[4]; @@ -1725,9 +1731,9 @@ check_byte(uc_value_t *v) } static uc_value_t * -uc_arrtoip(uc_vm *vm, size_t nargs) +uc_arrtoip(uc_vm_t *vm, size_t nargs) { - uc_value_t *arr = uc_get_arg(0); + uc_value_t *arr = uc_fn_arg(0); union { uint8_t u8[4]; struct in6_addr in6; @@ -1773,10 +1779,10 @@ uc_arrtoip(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_match(uc_vm *vm, size_t nargs) +uc_match(uc_vm_t *vm, size_t nargs) { - uc_value_t *subject = uc_get_arg(0); - uc_value_t *pattern = uc_get_arg(1); + uc_value_t *subject = uc_fn_arg(0); + uc_value_t *pattern = uc_fn_arg(1); uc_value_t *rv = NULL, *m; regmatch_t pmatch[10]; int eflags = 0, res; @@ -1827,7 +1833,7 @@ uc_match(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_replace_cb(uc_vm *vm, uc_value_t *func, +uc_replace_cb(uc_vm_t *vm, uc_value_t *func, const char *subject, regmatch_t *pmatch, size_t plen, uc_stringbuf_t *resbuf) { @@ -1856,7 +1862,7 @@ uc_replace_cb(uc_vm *vm, uc_value_t *func, } static void -uc_replace_str(uc_vm *vm, uc_value_t *str, +uc_replace_str(uc_vm_t *vm, uc_value_t *str, const char *subject, regmatch_t *pmatch, size_t plen, uc_stringbuf_t *resbuf) { @@ -1930,12 +1936,12 @@ uc_replace_str(uc_vm *vm, uc_value_t *str, } static uc_value_t * -uc_replace(uc_vm *vm, size_t nargs) +uc_replace(uc_vm_t *vm, size_t nargs) { char *sb = NULL, *pt = NULL, *p, *l; - uc_value_t *subject = uc_get_arg(0); - uc_value_t *pattern = uc_get_arg(1); - uc_value_t *replace = uc_get_arg(2); + uc_value_t *subject = uc_fn_arg(0); + uc_value_t *pattern = uc_fn_arg(1); + uc_value_t *replace = uc_fn_arg(2); bool sb_freeable, pt_freeable; uc_value_t *rv = NULL; uc_stringbuf_t *resbuf; @@ -2032,9 +2038,9 @@ uc_replace(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_json(uc_vm *vm, size_t nargs) +uc_json(uc_vm_t *vm, size_t nargs) { - uc_value_t *rv, *src = uc_get_arg(0); + uc_value_t *rv, *src = uc_fn_arg(0); struct json_tokener *tok = NULL; enum json_tokener_error err; json_object *jso; @@ -2124,10 +2130,10 @@ include_path(const char *curpath, const char *incpath) } static uc_value_t * -uc_include(uc_vm *vm, size_t nargs) +uc_include(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); - uc_value_t *scope = uc_get_arg(1); + uc_value_t *path = uc_fn_arg(0); + uc_value_t *scope = uc_fn_arg(1); uc_value_t *rv = NULL, *sc = NULL; uc_closure_t *closure = NULL; size_t i; @@ -2176,10 +2182,10 @@ uc_include(uc_vm *vm, size_t nargs) ucv_object_foreach(scope, key, val) ucv_object_add(sc, key, ucv_get(val)); - ucv_prototype_set(sc, ucv_get(vm->globals)); + ucv_prototype_set(sc, ucv_get(uc_vm_scope_get(vm))); } else { - sc = ucv_get(vm->globals); + sc = ucv_get(uc_vm_scope_get(vm)); } if (uc_require_ucode(vm, p, sc, &rv)) @@ -2192,7 +2198,7 @@ uc_include(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_render(uc_vm *vm, size_t nargs) +uc_render(uc_vm_t *vm, size_t nargs) { uc_string_t *ustr = NULL; FILE *mem, *prev; @@ -2239,16 +2245,16 @@ out: } static uc_value_t * -uc_warn(uc_vm *vm, size_t nargs) +uc_warn(uc_vm_t *vm, size_t nargs) { return uc_print_common(vm, nargs, stderr); } static uc_value_t * -uc_system(uc_vm *vm, size_t nargs) +uc_system(uc_vm_t *vm, size_t nargs) { - uc_value_t *cmdline = uc_get_arg(0); - uc_value_t *timeout = uc_get_arg(1); + uc_value_t *cmdline = uc_fn_arg(0); + uc_value_t *timeout = uc_fn_arg(1); const char **arglist, *fn; sigset_t sigmask, sigomask; struct timespec ts; @@ -2385,9 +2391,9 @@ fail: } static uc_value_t * -uc_trace(uc_vm *vm, size_t nargs) +uc_trace(uc_vm_t *vm, size_t nargs) { - uc_value_t *level = uc_get_arg(0); + uc_value_t *level = uc_fn_arg(0); uint8_t prev_level; if (ucv_type(level) != UC_INTEGER) { @@ -2403,15 +2409,15 @@ uc_trace(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_proto(uc_vm *vm, size_t nargs) +uc_proto(uc_vm_t *vm, size_t nargs) { - uc_value_t *val = uc_get_arg(0); + uc_value_t *val = uc_fn_arg(0); uc_value_t *proto = NULL; if (nargs < 2) return ucv_get(ucv_prototype_get(val)); - proto = uc_get_arg(1); + proto = uc_fn_arg(1); if (!ucv_prototype_set(val, proto)) uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Passed value is neither a prototype, ressource or object"); @@ -2422,9 +2428,9 @@ uc_proto(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_sleep(uc_vm *vm, size_t nargs) +uc_sleep(uc_vm_t *vm, size_t nargs) { - uc_value_t *duration = uc_get_arg(0); + uc_value_t *duration = uc_fn_arg(0); struct timeval tv; int64_t ms; @@ -2442,14 +2448,14 @@ uc_sleep(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_assert(uc_vm *vm, size_t nargs) +uc_assert(uc_vm_t *vm, size_t nargs) { - uc_value_t *cond = uc_get_arg(0); - uc_value_t *msg = uc_get_arg(1); + uc_value_t *cond = uc_fn_arg(0); + uc_value_t *msg = uc_fn_arg(1); bool freeable = false; char *s; - if (!uc_val_is_truish(cond)) { + if (!ucv_is_truish(cond)) { s = msg ? uc_cast_string(vm, &msg, &freeable) : "Assertion failed"; uc_vm_raise_exception(vm, EXCEPTION_USER, "%s", s); @@ -2464,11 +2470,11 @@ uc_assert(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_regexp(uc_vm *vm, size_t nargs) +uc_regexp(uc_vm_t *vm, size_t nargs) { bool icase = false, newline = false, global = false, freeable; - uc_value_t *source = uc_get_arg(0); - uc_value_t *flags = uc_get_arg(1); + uc_value_t *source = uc_fn_arg(0); + uc_value_t *flags = uc_fn_arg(1); uc_value_t *regex = NULL; char *p, *err = NULL; @@ -2519,11 +2525,11 @@ uc_regexp(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_wildcard(uc_vm *vm, size_t nargs) +uc_wildcard(uc_vm_t *vm, size_t nargs) { - uc_value_t *subject = uc_get_arg(0); - uc_value_t *pattern = uc_get_arg(1); - uc_value_t *icase = uc_get_arg(2); + uc_value_t *subject = uc_fn_arg(0); + uc_value_t *pattern = uc_fn_arg(1); + uc_value_t *icase = uc_fn_arg(2); int flags = 0, rv; bool freeable; char *s; @@ -2531,7 +2537,7 @@ uc_wildcard(uc_vm *vm, size_t nargs) if (!subject || ucv_type(pattern) != UC_STRING) return NULL; - if (uc_val_is_truish(icase)) + if (ucv_is_truish(icase)) flags |= FNM_CASEFOLD; s = uc_cast_string(vm, &subject, &freeable); @@ -2544,12 +2550,12 @@ uc_wildcard(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_sourcepath(uc_vm *vm, size_t nargs) +uc_sourcepath(uc_vm_t *vm, size_t nargs) { - uc_value_t *calldepth = uc_get_arg(0); - uc_value_t *dironly = uc_get_arg(1); + uc_value_t *calldepth = uc_fn_arg(0); + uc_value_t *dironly = uc_fn_arg(1); uc_value_t *rv = NULL; - uc_callframe *frame; + uc_callframe_t *frame; char *path = NULL; int64_t depth; size_t i; @@ -2575,7 +2581,7 @@ uc_sourcepath(uc_vm *vm, size_t nargs) } if (path) { - if (uc_val_is_truish(dironly)) + if (ucv_is_truish(dironly)) rv = ucv_string_new(dirname(path)); else rv = ucv_string_new(path); @@ -2587,16 +2593,16 @@ uc_sourcepath(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_min_max(uc_vm *vm, size_t nargs, int cmp) +uc_min_max(uc_vm_t *vm, size_t nargs, int cmp) { uc_value_t *rv = NULL, *val; bool set = false; size_t i; for (i = 0; i < nargs; i++) { - val = uc_get_arg(i); + val = uc_fn_arg(i); - if (!set || uc_cmp(cmp, val, rv)) { + if (!set || ucv_compare(cmp, val, rv)) { set = true; rv = val; } @@ -2606,13 +2612,13 @@ uc_min_max(uc_vm *vm, size_t nargs, int cmp) } static uc_value_t * -uc_min(uc_vm *vm, size_t nargs) +uc_min(uc_vm_t *vm, size_t nargs) { return uc_min_max(vm, nargs, I_LT); } static uc_value_t * -uc_max(uc_vm *vm, size_t nargs) +uc_max(uc_vm_t *vm, size_t nargs) { return uc_min_max(vm, nargs, I_GT); } @@ -2695,10 +2701,10 @@ uc_max(uc_vm *vm, size_t nargs) */ static uc_value_t * -uc_b64dec(uc_vm *vm, size_t nargs) +uc_b64dec(uc_vm_t *vm, size_t nargs) { enum { BYTE1, BYTE2, BYTE3, BYTE4 } state; - uc_value_t *str = uc_get_arg(0); + uc_value_t *str = uc_fn_arg(0); uc_stringbuf_t *buf; const char *src; unsigned int ch; @@ -2828,9 +2834,9 @@ static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static uc_value_t * -uc_b64enc(uc_vm *vm, size_t nargs) +uc_b64enc(uc_vm_t *vm, size_t nargs) { - uc_value_t *str = uc_get_arg(0); + uc_value_t *str = uc_fn_arg(0); unsigned char input[3] = {0}; uc_stringbuf_t *buf; const char *src; @@ -2881,7 +2887,7 @@ uc_b64enc(uc_vm *vm, size_t nargs) */ -static const uc_cfunction_list functions[] = { +const uc_function_list_t uc_stdlib_functions[] = { { "chr", uc_chr }, { "die", uc_die }, { "exists", uc_exists }, @@ -2943,37 +2949,7 @@ static const uc_cfunction_list functions[] = { void -uc_load_stdlib(uc_value_t *scope) +uc_stdlib_load(uc_value_t *scope) { - uc_add_proto_functions(scope, functions); -} - -uc_value_t * -uc_alloc_global(uc_vm *vm) -{ - const char *path[] = { LIB_SEARCH_PATH }; - uc_value_t *global, *arr; - size_t i; - - global = ucv_object_new(vm); - - /* build default require() search path */ - arr = ucv_array_new(vm); - - for (i = 0; i < ARRAY_SIZE(path); i++) - ucv_array_push(arr, ucv_string_new(path[i])); - - /* register module related constants */ - ucv_object_add(global, "REQUIRE_SEARCH_PATH", arr); - ucv_object_add(global, "modules", ucv_object_new(vm)); - - /* register global math constants */ - ucv_object_add(global, "NaN", ucv_double_new(NAN)); - ucv_object_add(global, "Infinity", ucv_double_new(INFINITY)); - - /* register global property */ - ucv_object_add(global, "global", ucv_get(global)); - - - return global; + uc_function_list_register(scope, uc_stdlib_functions); } @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __LIB_H_ -#define __LIB_H_ - -#include "vm.h" -#include "lexer.h" - -typedef struct { - const char *name; - uc_cfn_ptr_t func; -} uc_cfunction_list; - -void uc_load_stdlib(uc_value_t *scope); -uc_value_t *uc_alloc_global(uc_vm *vm); - -bool format_source_context(uc_stringbuf_t *buf, uc_source *src, size_t off, bool compact); -bool format_error_context(uc_stringbuf_t *buf, uc_source *src, uc_value_t *stacktrace, size_t off); - - -/* vm helper */ - -static inline void * -_uc_get_self(uc_vm *vm, const char *expected_type) -{ - return ucv_ressource_dataptr(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type); -} - -#define uc_get_self(...) _uc_get_self(vm, __VA_ARGS__) - -static inline uc_value_t * -_uc_get_arg(uc_vm *vm, size_t nargs, size_t n) -{ - if (n >= nargs) - return NULL; - - return uc_vm_stack_peek(vm, nargs - n - 1); -} - -#define uc_get_arg(...) _uc_get_arg(vm, nargs, __VA_ARGS__) - -#define uc_call(nargs) uc_vm_call(vm, false, nargs) -#define uc_push_val(val) uc_vm_stack_push(vm, val) -#define uc_pop_val() uc_vm_stack_pop(vm) - - -/* value helper */ - -static inline uc_value_t * -uc_alloc_ressource(uc_ressource_type_t *type, void *data) -{ - return ucv_ressource_new(type, data); -} - -static inline uc_type_t -uc_to_number(uc_value_t *v, int64_t *n, double *d) -{ - return uc_cast_number(v, n, d); -} - -static inline double -uc_to_double(uc_value_t *v) -{ - int64_t n; - double d; - - return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? d : (double)n; -} - -static inline int64_t -uc_to_int64(uc_value_t *v) -{ - int64_t n; - double d; - - return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? (int64_t)d : n; -} - - -/* ressource type helper */ - -static inline uc_ressource_type_t * -_uc_declare_type(const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *)) -{ - uc_value_t *proto = ucv_object_new(NULL); - - while (len-- > 0) - ucv_object_add(proto, list[len].name, - ucv_cfunction_new(list[len].name, list[len].func)); - - return ucv_ressource_type_add(name, proto, freefn); -} - -#define uc_declare_type(name, functions, freefn) \ - _uc_declare_type(name, functions, ARRAY_SIZE(functions), freefn) - - -/* prototype helper */ - -static inline void -_uc_add_proto_functions(uc_value_t *proto, const uc_cfunction_list *list, size_t len) -{ - while (len-- > 0) - ucv_object_add(proto, list[len].name, - ucv_cfunction_new(list[len].name, list[len].func)); -} - -#define uc_add_proto_functions(proto, functions) \ - _uc_add_proto_functions(proto, functions, ARRAY_SIZE(functions)) - -#endif /* __LIB_H_ */ @@ -26,7 +26,7 @@ #include <pwd.h> #include <glob.h> -#include "../module.h" +#include "ucode/module.h" #define err_return(err) do { last_error = err; return NULL; } while(0) @@ -36,7 +36,7 @@ static uc_ressource_type_t *file_type, *proc_type, *dir_type; static int last_error = 0; static uc_value_t * -uc_fs_error(uc_vm *vm, size_t nargs) +uc_fs_error(uc_vm_t *vm, size_t nargs) { uc_value_t *errmsg; @@ -50,16 +50,16 @@ uc_fs_error(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type) +uc_fs_read_common(uc_vm_t *vm, size_t nargs, const char *type) { - uc_value_t *limit = uc_get_arg(0); + uc_value_t *limit = uc_fn_arg(0); uc_value_t *rv = NULL; char buf[128], *p = NULL, *tmp; size_t rlen, len = 0; const char *lstr; int64_t lsize; - FILE **fp = uc_get_self(type); + FILE **fp = uc_fn_this(type); if (!fp || !*fp) err_return(EBADF); @@ -142,13 +142,13 @@ uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type) } static uc_value_t * -uc_fs_write_common(uc_vm *vm, size_t nargs, const char *type) +uc_fs_write_common(uc_vm_t *vm, size_t nargs, const char *type) { - uc_value_t *data = uc_get_arg(0); + uc_value_t *data = uc_fn_arg(0); size_t len, wsize; char *str; - FILE **fp = uc_get_self(type); + FILE **fp = uc_fn_this(type); if (!fp || !*fp) err_return(EBADF); @@ -172,9 +172,9 @@ uc_fs_write_common(uc_vm *vm, size_t nargs, const char *type) static uc_value_t * -uc_fs_pclose(uc_vm *vm, size_t nargs) +uc_fs_pclose(uc_vm_t *vm, size_t nargs) { - FILE **fp = uc_get_self("fs.proc"); + FILE **fp = uc_fn_this("fs.proc"); int rc; if (!fp || !*fp) @@ -196,22 +196,22 @@ uc_fs_pclose(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_pread(uc_vm *vm, size_t nargs) +uc_fs_pread(uc_vm_t *vm, size_t nargs) { return uc_fs_read_common(vm, nargs, "fs.proc"); } static uc_value_t * -uc_fs_pwrite(uc_vm *vm, size_t nargs) +uc_fs_pwrite(uc_vm_t *vm, size_t nargs) { return uc_fs_write_common(vm, nargs, "fs.proc"); } static uc_value_t * -uc_fs_popen(uc_vm *vm, size_t nargs) +uc_fs_popen(uc_vm_t *vm, size_t nargs) { - uc_value_t *comm = uc_get_arg(0); - uc_value_t *mode = uc_get_arg(1); + uc_value_t *comm = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); FILE *fp; if (ucv_type(comm) != UC_STRING) @@ -223,14 +223,14 @@ uc_fs_popen(uc_vm *vm, size_t nargs) if (!fp) err_return(errno); - return uc_alloc_ressource(proc_type, fp); + return uc_ressource_new(proc_type, fp); } static uc_value_t * -uc_fs_close(uc_vm *vm, size_t nargs) +uc_fs_close(uc_vm_t *vm, size_t nargs) { - FILE **fp = uc_get_self("fs.file"); + FILE **fp = uc_fn_this("fs.file"); if (!fp || !*fp) err_return(EBADF); @@ -242,26 +242,26 @@ uc_fs_close(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_read(uc_vm *vm, size_t nargs) +uc_fs_read(uc_vm_t *vm, size_t nargs) { return uc_fs_read_common(vm, nargs, "fs.file"); } static uc_value_t * -uc_fs_write(uc_vm *vm, size_t nargs) +uc_fs_write(uc_vm_t *vm, size_t nargs) { return uc_fs_write_common(vm, nargs, "fs.file"); } static uc_value_t * -uc_fs_seek(uc_vm *vm, size_t nargs) +uc_fs_seek(uc_vm_t *vm, size_t nargs) { - uc_value_t *ofs = uc_get_arg(0); - uc_value_t *how = uc_get_arg(1); + uc_value_t *ofs = uc_fn_arg(0); + uc_value_t *how = uc_fn_arg(1); int whence, res; long offset; - FILE **fp = uc_get_self("fs.file"); + FILE **fp = uc_fn_this("fs.file"); if (!fp || !*fp) err_return(EBADF); @@ -289,11 +289,11 @@ uc_fs_seek(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_tell(uc_vm *vm, size_t nargs) +uc_fs_tell(uc_vm_t *vm, size_t nargs) { long offset; - FILE **fp = uc_get_self("fs.file"); + FILE **fp = uc_fn_this("fs.file"); if (!fp || !*fp) err_return(EBADF); @@ -307,10 +307,10 @@ uc_fs_tell(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_open(uc_vm *vm, size_t nargs) +uc_fs_open(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); - uc_value_t *mode = uc_get_arg(1); + uc_value_t *path = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); FILE *fp; if (ucv_type(path) != UC_STRING) @@ -322,14 +322,14 @@ uc_fs_open(uc_vm *vm, size_t nargs) if (!fp) err_return(errno); - return uc_alloc_ressource(file_type, fp); + return uc_ressource_new(file_type, fp); } static uc_value_t * -uc_fs_readdir(uc_vm *vm, size_t nargs) +uc_fs_readdir(uc_vm_t *vm, size_t nargs) { - DIR **dp = uc_get_self("fs.dir"); + DIR **dp = uc_fn_this("fs.dir"); struct dirent *e; if (!dp || !*dp) @@ -345,9 +345,9 @@ uc_fs_readdir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_telldir(uc_vm *vm, size_t nargs) +uc_fs_telldir(uc_vm_t *vm, size_t nargs) { - DIR **dp = uc_get_self("fs.dir"); + DIR **dp = uc_fn_this("fs.dir"); long position; if (!dp || !*dp) @@ -362,10 +362,10 @@ uc_fs_telldir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_seekdir(uc_vm *vm, size_t nargs) +uc_fs_seekdir(uc_vm_t *vm, size_t nargs) { - uc_value_t *ofs = uc_get_arg(0); - DIR **dp = uc_get_self("fs.dir"); + uc_value_t *ofs = uc_fn_arg(0); + DIR **dp = uc_fn_this("fs.dir"); long position; if (ucv_type(ofs) != UC_INTEGER) @@ -382,9 +382,9 @@ uc_fs_seekdir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_closedir(uc_vm *vm, size_t nargs) +uc_fs_closedir(uc_vm_t *vm, size_t nargs) { - DIR **dp = uc_get_self("fs.dir"); + DIR **dp = uc_fn_this("fs.dir"); if (!dp || !*dp) err_return(EBADF); @@ -396,9 +396,9 @@ uc_fs_closedir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_opendir(uc_vm *vm, size_t nargs) +uc_fs_opendir(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); DIR *dp; if (ucv_type(path) != UC_STRING) @@ -409,13 +409,13 @@ uc_fs_opendir(uc_vm *vm, size_t nargs) if (!dp) err_return(errno); - return uc_alloc_ressource(dir_type, dp); + return uc_ressource_new(dir_type, dp); } static uc_value_t * -uc_fs_readlink(uc_vm *vm, size_t nargs) +uc_fs_readlink(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); uc_value_t *res; ssize_t buflen = 0, rv; char *buf = NULL, *tmp; @@ -453,9 +453,9 @@ uc_fs_readlink(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_stat_common(uc_vm *vm, size_t nargs, bool use_lstat) +uc_fs_stat_common(uc_vm_t *vm, size_t nargs, bool use_lstat) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); uc_value_t *res, *o; struct stat st; int rv; @@ -537,22 +537,22 @@ uc_fs_stat_common(uc_vm *vm, size_t nargs, bool use_lstat) } static uc_value_t * -uc_fs_stat(uc_vm *vm, size_t nargs) +uc_fs_stat(uc_vm_t *vm, size_t nargs) { return uc_fs_stat_common(vm, nargs, false); } static uc_value_t * -uc_fs_lstat(uc_vm *vm, size_t nargs) +uc_fs_lstat(uc_vm_t *vm, size_t nargs) { return uc_fs_stat_common(vm, nargs, true); } static uc_value_t * -uc_fs_mkdir(uc_vm *vm, size_t nargs) +uc_fs_mkdir(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); - uc_value_t *mode = uc_get_arg(1); + uc_value_t *path = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); if (ucv_type(path) != UC_STRING || (mode && ucv_type(mode) != UC_INTEGER)) @@ -565,9 +565,9 @@ uc_fs_mkdir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_rmdir(uc_vm *vm, size_t nargs) +uc_fs_rmdir(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); if (ucv_type(path) != UC_STRING) err_return(EINVAL); @@ -579,10 +579,10 @@ uc_fs_rmdir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_symlink(uc_vm *vm, size_t nargs) +uc_fs_symlink(uc_vm_t *vm, size_t nargs) { - uc_value_t *dest = uc_get_arg(0); - uc_value_t *path = uc_get_arg(1); + uc_value_t *dest = uc_fn_arg(0); + uc_value_t *path = uc_fn_arg(1); if (ucv_type(dest) != UC_STRING || ucv_type(path) != UC_STRING) @@ -595,9 +595,9 @@ uc_fs_symlink(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_unlink(uc_vm *vm, size_t nargs) +uc_fs_unlink(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); if (ucv_type(path) != UC_STRING) err_return(EINVAL); @@ -609,7 +609,7 @@ uc_fs_unlink(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_getcwd(uc_vm *vm, size_t nargs) +uc_fs_getcwd(uc_vm_t *vm, size_t nargs) { uc_value_t *res; char *buf = NULL, *tmp; @@ -645,9 +645,9 @@ uc_fs_getcwd(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_chdir(uc_vm *vm, size_t nargs) +uc_fs_chdir(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); + uc_value_t *path = uc_fn_arg(0); if (ucv_type(path) != UC_STRING) err_return(EINVAL); @@ -659,10 +659,10 @@ uc_fs_chdir(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_chmod(uc_vm *vm, size_t nargs) +uc_fs_chmod(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); - uc_value_t *mode = uc_get_arg(1); + uc_value_t *path = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); if (ucv_type(path) != UC_STRING || ucv_type(mode) != UC_INTEGER) @@ -769,11 +769,11 @@ uc_fs_resolve_group(uc_value_t *v, gid_t *gid) } static uc_value_t * -uc_fs_chown(uc_vm *vm, size_t nargs) +uc_fs_chown(uc_vm_t *vm, size_t nargs) { - uc_value_t *path = uc_get_arg(0); - uc_value_t *user = uc_get_arg(1); - uc_value_t *group = uc_get_arg(2); + uc_value_t *path = uc_fn_arg(0); + uc_value_t *user = uc_fn_arg(1); + uc_value_t *group = uc_fn_arg(2); uid_t uid; gid_t gid; @@ -791,10 +791,10 @@ uc_fs_chown(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_rename(uc_vm *vm, size_t nargs) +uc_fs_rename(uc_vm_t *vm, size_t nargs) { - uc_value_t *oldpath = uc_get_arg(0); - uc_value_t *newpath = uc_get_arg(1); + uc_value_t *oldpath = uc_fn_arg(0); + uc_value_t *newpath = uc_fn_arg(1); if (ucv_type(oldpath) != UC_STRING || ucv_type(newpath) != UC_STRING) @@ -807,14 +807,14 @@ uc_fs_rename(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_fs_glob(uc_vm *vm, size_t nargs) +uc_fs_glob(uc_vm_t *vm, size_t nargs) { uc_value_t *pat, *arr; glob_t gl = { 0 }; size_t i; for (i = 0; i < nargs; i++) { - pat = uc_get_arg(i); + pat = uc_fn_arg(i); if (ucv_type(pat) != UC_STRING) { globfree(&gl); @@ -835,14 +835,14 @@ uc_fs_glob(uc_vm *vm, size_t nargs) } -static const uc_cfunction_list proc_fns[] = { +static const uc_function_list_t proc_fns[] = { { "read", uc_fs_pread }, { "write", uc_fs_pwrite }, { "close", uc_fs_pclose }, { "error", uc_fs_error }, }; -static const uc_cfunction_list file_fns[] = { +static const uc_function_list_t file_fns[] = { { "read", uc_fs_read }, { "write", uc_fs_write }, { "seek", uc_fs_seek }, @@ -851,7 +851,7 @@ static const uc_cfunction_list file_fns[] = { { "error", uc_fs_error }, }; -static const uc_cfunction_list dir_fns[] = { +static const uc_function_list_t dir_fns[] = { { "read", uc_fs_readdir }, { "seek", uc_fs_seekdir }, { "tell", uc_fs_telldir }, @@ -859,7 +859,7 @@ static const uc_cfunction_list dir_fns[] = { { "error", uc_fs_error }, }; -static const uc_cfunction_list global_fns[] = { +static const uc_function_list_t global_fns[] = { { "error", uc_fs_error }, { "open", uc_fs_open }, { "opendir", uc_fs_opendir }, @@ -904,15 +904,15 @@ static void close_dir(void *ud) closedir(dp); } -void uc_module_init(uc_value_t *scope) +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) { - uc_add_proto_functions(scope, global_fns); + uc_function_list_register(scope, global_fns); - proc_type = uc_declare_type("fs.proc", proc_fns, close_proc); - file_type = uc_declare_type("fs.file", file_fns, close_file); - dir_type = uc_declare_type("fs.dir", dir_fns, close_dir); + proc_type = uc_type_declare(vm, "fs.proc", proc_fns, close_proc); + file_type = uc_type_declare(vm, "fs.file", file_fns, close_file); + dir_type = uc_type_declare(vm, "fs.dir", dir_fns, close_dir); - ucv_object_add(scope, "stdin", uc_alloc_ressource(file_type, stdin)); - ucv_object_add(scope, "stdout", uc_alloc_ressource(file_type, stdout)); - ucv_object_add(scope, "stderr", uc_alloc_ressource(file_type, stderr)); + ucv_object_add(scope, "stdin", uc_ressource_new(file_type, stdin)); + ucv_object_add(scope, "stdout", uc_ressource_new(file_type, stdout)); + ucv_object_add(scope, "stderr", uc_ressource_new(file_type, stderr)); } @@ -17,14 +17,14 @@ #include <math.h> #include <sys/time.h> -#include "../module.h" +#include "ucode/module.h" static bool srand_called = false; static uc_value_t * -uc_abs(uc_vm *vm, size_t nargs) +uc_abs(uc_vm_t *vm, size_t nargs) { - uc_value_t *v = uc_get_arg(0); + uc_value_t *v = uc_fn_arg(0); uc_type_t t; int64_t n; double d; @@ -32,7 +32,7 @@ uc_abs(uc_vm *vm, size_t nargs) if (ucv_type(v) == UC_NULL) return ucv_double_new(NAN); - t = uc_to_number(v, &n, &d); + t = ucv_cast_number(v, &n, &d); if (t == UC_DOUBLE) return (isnan(d) || d < 0) ? ucv_double_new(-d) : ucv_get(v); @@ -41,10 +41,10 @@ uc_abs(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_atan2(uc_vm *vm, size_t nargs) +uc_atan2(uc_vm_t *vm, size_t nargs) { - double d1 = uc_to_double(uc_get_arg(0)); - double d2 = uc_to_double(uc_get_arg(1)); + double d1 = ucv_to_double(uc_fn_arg(0)); + double d2 = ucv_to_double(uc_fn_arg(1)); if (isnan(d1) || isnan(d2)) return ucv_double_new(NAN); @@ -53,9 +53,9 @@ uc_atan2(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_cos(uc_vm *vm, size_t nargs) +uc_cos(uc_vm_t *vm, size_t nargs) { - double d = uc_to_double(uc_get_arg(0)); + double d = ucv_to_double(uc_fn_arg(0)); if (isnan(d)) return ucv_double_new(NAN); @@ -64,9 +64,9 @@ uc_cos(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_exp(uc_vm *vm, size_t nargs) +uc_exp(uc_vm_t *vm, size_t nargs) { - double d = uc_to_double(uc_get_arg(0)); + double d = ucv_to_double(uc_fn_arg(0)); if (isnan(d)) return ucv_double_new(NAN); @@ -75,9 +75,9 @@ uc_exp(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_log(uc_vm *vm, size_t nargs) +uc_log(uc_vm_t *vm, size_t nargs) { - double d = uc_to_double(uc_get_arg(0)); + double d = ucv_to_double(uc_fn_arg(0)); if (isnan(d)) return ucv_double_new(NAN); @@ -86,9 +86,9 @@ uc_log(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_sin(uc_vm *vm, size_t nargs) +uc_sin(uc_vm_t *vm, size_t nargs) { - double d = uc_to_double(uc_get_arg(0)); + double d = ucv_to_double(uc_fn_arg(0)); if (isnan(d)) return ucv_double_new(NAN); @@ -97,9 +97,9 @@ uc_sin(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_sqrt(uc_vm *vm, size_t nargs) +uc_sqrt(uc_vm_t *vm, size_t nargs) { - double d = uc_to_double(uc_get_arg(0)); + double d = ucv_to_double(uc_fn_arg(0)); if (isnan(d)) return ucv_double_new(NAN); @@ -108,10 +108,10 @@ uc_sqrt(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_pow(uc_vm *vm, size_t nargs) +uc_pow(uc_vm_t *vm, size_t nargs) { - double x = uc_to_double(uc_get_arg(0)); - double y = uc_to_double(uc_get_arg(1)); + double x = ucv_to_double(uc_fn_arg(0)); + double y = ucv_to_double(uc_fn_arg(1)); if (isnan(x) || isnan(y)) return ucv_double_new(NAN); @@ -120,7 +120,7 @@ uc_pow(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_rand(uc_vm *vm, size_t nargs) +uc_rand(uc_vm_t *vm, size_t nargs) { struct timeval tv; @@ -135,9 +135,9 @@ uc_rand(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_srand(uc_vm *vm, size_t nargs) +uc_srand(uc_vm_t *vm, size_t nargs) { - int64_t n = uc_to_int64(uc_get_arg(0)); + int64_t n = ucv_to_integer(uc_fn_arg(0)); srand((unsigned int)n); srand_called = true; @@ -145,7 +145,7 @@ uc_srand(uc_vm *vm, size_t nargs) return NULL; } -static const uc_cfunction_list math_fns[] = { +static const uc_function_list_t math_fns[] = { { "abs", uc_abs }, { "atan2", uc_atan2 }, { "cos", uc_cos }, @@ -158,7 +158,7 @@ static const uc_cfunction_list math_fns[] = { { "srand", uc_srand }, }; -void uc_module_init(uc_value_t *scope) +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) { - uc_add_proto_functions(scope, math_fns); + uc_function_list_register(scope, math_fns); } @@ -19,7 +19,7 @@ #include <libubox/blobmsg.h> #include <libubox/blobmsg_json.h> -#include "../module.h" +#include "ucode/module.h" #define err_return(err) do { last_error = err; return NULL; } while(0) @@ -33,7 +33,7 @@ typedef struct { } ubus_connection; static uc_value_t * -uc_ubus_error(uc_vm *vm, size_t nargs) +uc_ubus_error(uc_vm_t *vm, size_t nargs) { uc_value_t *errmsg; @@ -47,10 +47,10 @@ uc_ubus_error(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_blob_to_json(uc_vm *vm, struct blob_attr *attr, bool table, const char **name); +uc_blob_to_json(uc_vm_t *vm, struct blob_attr *attr, bool table, const char **name); static uc_value_t * -uc_blob_array_to_json(uc_vm *vm, struct blob_attr *attr, size_t len, bool table) +uc_blob_array_to_json(uc_vm_t *vm, struct blob_attr *attr, size_t len, bool table) { uc_value_t *o = table ? ucv_object_new(vm) : ucv_array_new(vm); uc_value_t *v; @@ -77,7 +77,7 @@ uc_blob_array_to_json(uc_vm *vm, struct blob_attr *attr, size_t len, bool table) } static uc_value_t * -uc_blob_to_json(uc_vm *vm, struct blob_attr *attr, bool table, const char **name) +uc_blob_to_json(uc_vm_t *vm, struct blob_attr *attr, bool table, const char **name) { void *data; int len; @@ -131,10 +131,10 @@ uc_blob_to_json(uc_vm *vm, struct blob_attr *attr, bool table, const char **name static uc_value_t * -uc_ubus_connect(uc_vm *vm, size_t nargs) +uc_ubus_connect(uc_vm_t *vm, size_t nargs) { - uc_value_t *socket = uc_get_arg(0); - uc_value_t *timeout = uc_get_arg(1); + uc_value_t *socket = uc_fn_arg(0); + uc_value_t *timeout = uc_fn_arg(1); uc_value_t *co; ubus_connection *c; @@ -168,7 +168,7 @@ uc_ubus_connect(uc_vm *vm, size_t nargs) ubus_add_uloop(c->ctx); - return uc_alloc_ressource(conn_type, c); + return uc_ressource_new(conn_type, c); } static void @@ -199,10 +199,10 @@ uc_ubus_objects_cb(struct ubus_context *c, struct ubus_object_data *o, void *p) } static uc_value_t * -uc_ubus_list(uc_vm *vm, size_t nargs) +uc_ubus_list(uc_vm_t *vm, size_t nargs) { - ubus_connection **c = uc_get_self("ubus.connection"); - uc_value_t *objname = uc_get_arg(0); + ubus_connection **c = uc_fn_this("ubus.connection"); + uc_value_t *objname = uc_fn_arg(0); uc_value_t *res = NULL; enum ubus_msg_status rv; @@ -237,12 +237,12 @@ uc_ubus_call_cb(struct ubus_request *req, int type, struct blob_attr *msg) } static uc_value_t * -uc_ubus_call(uc_vm *vm, size_t nargs) +uc_ubus_call(uc_vm_t *vm, size_t nargs) { - ubus_connection **c = uc_get_self("ubus.connection"); - uc_value_t *objname = uc_get_arg(0); - uc_value_t *funname = uc_get_arg(1); - uc_value_t *funargs = uc_get_arg(2); + ubus_connection **c = uc_fn_this("ubus.connection"); + uc_value_t *objname = uc_fn_arg(0); + uc_value_t *funname = uc_fn_arg(1); + uc_value_t *funargs = uc_fn_arg(2); uc_value_t *res = NULL; json_object *o; enum ubus_msg_status rv; @@ -282,9 +282,9 @@ uc_ubus_call(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_ubus_disconnect(uc_vm *vm, size_t nargs) +uc_ubus_disconnect(uc_vm_t *vm, size_t nargs) { - ubus_connection **c = uc_get_self("ubus.connection"); + ubus_connection **c = uc_fn_this("ubus.connection"); if (!c || !*c || !(*c)->ctx) err_return(UBUS_STATUS_CONNECTION_FAILED); @@ -296,12 +296,12 @@ uc_ubus_disconnect(uc_vm *vm, size_t nargs) } -static const uc_cfunction_list global_fns[] = { +static const uc_function_list_t global_fns[] = { { "error", uc_ubus_error }, { "connect", uc_ubus_connect }, }; -static const uc_cfunction_list conn_fns[] = { +static const uc_function_list_t conn_fns[] = { { "list", uc_ubus_list }, { "call", uc_ubus_call }, { "error", uc_ubus_error }, @@ -320,9 +320,9 @@ static void close_connection(void *ud) { free(conn); } -void uc_module_init(uc_value_t *scope) +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) { - uc_add_proto_functions(scope, global_fns); + uc_function_list_register(scope, global_fns); - conn_type = uc_declare_type("ubus.connection", conn_fns, close_connection); + conn_type = uc_type_declare(vm, "ubus.connection", conn_fns, close_connection); } @@ -17,7 +17,7 @@ #include <string.h> #include <uci.h> -#include "../module.h" +#include "ucode/module.h" #define err_return(err) do { last_error = err; return NULL; } while(0) @@ -31,7 +31,7 @@ enum pkg_cmd { }; static uc_value_t * -uc_uci_error(uc_vm *vm, size_t nargs) +uc_uci_error(uc_vm_t *vm, size_t nargs) { char buf[sizeof("Unknown error: -9223372036854775808")]; uc_value_t *errmsg; @@ -64,10 +64,10 @@ uc_uci_error(uc_vm *vm, size_t nargs) static uc_value_t * -uc_uci_cursor(uc_vm *vm, size_t nargs) +uc_uci_cursor(uc_vm_t *vm, size_t nargs) { - uc_value_t *cdir = uc_get_arg(0); - uc_value_t *sdir = uc_get_arg(1); + uc_value_t *cdir = uc_fn_arg(0); + uc_value_t *sdir = uc_fn_arg(1); struct uci_context *c; int rv; @@ -94,15 +94,15 @@ uc_uci_cursor(uc_vm *vm, size_t nargs) err_return(rv); } - return uc_alloc_ressource(cursor_type, c); + return uc_ressource_new(cursor_type, c); } static uc_value_t * -uc_uci_load(uc_vm *vm, size_t nargs) +uc_uci_load(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); struct uci_element *e; char *s; @@ -128,10 +128,10 @@ uc_uci_load(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_unload(uc_vm *vm, size_t nargs) +uc_uci_unload(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); struct uci_element *e; if (!c || !*c) @@ -181,7 +181,7 @@ lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, bool extended) } static uc_value_t * -option_to_uval(uc_vm *vm, struct uci_option *o) +option_to_uval(uc_vm_t *vm, struct uci_option *o) { struct uci_element *e; uc_value_t *arr; @@ -205,7 +205,7 @@ option_to_uval(uc_vm *vm, struct uci_option *o) } static uc_value_t * -section_to_uval(uc_vm *vm, struct uci_section *s, int index) +section_to_uval(uc_vm_t *vm, struct uci_section *s, int index) { uc_value_t *so = ucv_object_new(vm); struct uci_element *e; @@ -230,7 +230,7 @@ section_to_uval(uc_vm *vm, struct uci_section *s, int index) } static uc_value_t * -package_to_uval(uc_vm *vm, struct uci_package *p) +package_to_uval(uc_vm_t *vm, struct uci_package *p) { uc_value_t *po = ucv_object_new(vm); uc_value_t *so; @@ -249,12 +249,12 @@ package_to_uval(uc_vm *vm, struct uci_package *p) } static uc_value_t * -uc_uci_get_any(uc_vm *vm, size_t nargs, bool all) +uc_uci_get_any(uc_vm_t *vm, size_t nargs, bool all) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *sect = uc_get_arg(1); - uc_value_t *opt = uc_get_arg(2); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *sect = uc_fn_arg(1); + uc_value_t *opt = uc_fn_arg(2); struct uci_ptr ptr = { 0 }; int rv; @@ -309,24 +309,24 @@ uc_uci_get_any(uc_vm *vm, size_t nargs, bool all) } static uc_value_t * -uc_uci_get(uc_vm *vm, size_t nargs) +uc_uci_get(uc_vm_t *vm, size_t nargs) { return uc_uci_get_any(vm, nargs, false); } static uc_value_t * -uc_uci_get_all(uc_vm *vm, size_t nargs) +uc_uci_get_all(uc_vm_t *vm, size_t nargs) { return uc_uci_get_any(vm, nargs, true); } static uc_value_t * -uc_uci_get_first(uc_vm *vm, size_t nargs) +uc_uci_get_first(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *type = uc_get_arg(1); - uc_value_t *opt = uc_get_arg(2); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *type = uc_fn_arg(1); + uc_value_t *opt = uc_fn_arg(2); struct uci_package *p = NULL; struct uci_section *sc; struct uci_element *e; @@ -379,11 +379,11 @@ uc_uci_get_first(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_add(uc_vm *vm, size_t nargs) +uc_uci_add(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *type = uc_get_arg(1); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *type = uc_fn_arg(1); struct uci_element *e = NULL; struct uci_package *p = NULL; struct uci_section *sc = NULL; @@ -414,7 +414,7 @@ uc_uci_add(uc_vm *vm, size_t nargs) } static bool -uval_to_uci(uc_vm *vm, uc_value_t *val, const char **p, bool *is_list) +uval_to_uci(uc_vm_t *vm, uc_value_t *val, const char **p, bool *is_list) { uc_value_t *item; @@ -459,11 +459,11 @@ uval_to_uci(uc_vm *vm, uc_value_t *val, const char **p, bool *is_list) } static uc_value_t * -uc_uci_set(uc_vm *vm, size_t nargs) +uc_uci_set(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *sect = uc_get_arg(1); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *sect = uc_fn_arg(1); uc_value_t *opt = NULL, *val = NULL; struct uci_ptr ptr = { 0 }; bool is_list = false; @@ -477,8 +477,8 @@ uc_uci_set(uc_vm *vm, size_t nargs) switch (nargs) { /* conf, sect, opt, val */ case 4: - opt = uc_get_arg(2); - val = uc_get_arg(3); + opt = uc_fn_arg(2); + val = uc_fn_arg(3); if (ucv_type(opt) != UC_STRING) err_return(UCI_ERR_INVAL); @@ -487,7 +487,7 @@ uc_uci_set(uc_vm *vm, size_t nargs) /* conf, sect, type */ case 3: - val = uc_get_arg(2); + val = uc_fn_arg(2); if (ucv_type(val) != UC_STRING) err_return(UCI_ERR_INVAL); @@ -564,12 +564,12 @@ uc_uci_set(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_delete(uc_vm *vm, size_t nargs) +uc_uci_delete(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *sect = uc_get_arg(1); - uc_value_t *opt = uc_get_arg(2); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *sect = uc_fn_arg(1); + uc_value_t *opt = uc_fn_arg(2); struct uci_ptr ptr = { 0 }; int rv; @@ -599,11 +599,11 @@ uc_uci_delete(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_rename(uc_vm *vm, size_t nargs) +uc_uci_rename(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *sect = uc_get_arg(1); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *sect = uc_fn_arg(1); uc_value_t *opt = NULL, *val = NULL; struct uci_ptr ptr = { 0 }; int rv; @@ -615,8 +615,8 @@ uc_uci_rename(uc_vm *vm, size_t nargs) switch (nargs) { /* conf, sect, opt, val */ case 4: - opt = uc_get_arg(2); - val = uc_get_arg(3); + opt = uc_fn_arg(2); + val = uc_fn_arg(3); if (ucv_type(opt) != UC_STRING || ucv_type(val) != UC_STRING) @@ -626,7 +626,7 @@ uc_uci_rename(uc_vm *vm, size_t nargs) /* conf, sect, type */ case 3: - val = uc_get_arg(2); + val = uc_fn_arg(2); if (ucv_type(val) != UC_STRING) err_return(UCI_ERR_INVAL); @@ -659,12 +659,12 @@ uc_uci_rename(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_reorder(uc_vm *vm, size_t nargs) +uc_uci_reorder(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *sect = uc_get_arg(1); - uc_value_t *val = uc_get_arg(2); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *sect = uc_fn_arg(1); + uc_value_t *val = uc_fn_arg(2); struct uci_ptr ptr = { 0 }; int64_t n; int rv; @@ -699,10 +699,10 @@ uc_uci_reorder(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_pkg_command(uc_vm *vm, size_t nargs, enum pkg_cmd cmd) +uc_uci_pkg_command(uc_vm_t *vm, size_t nargs, enum pkg_cmd cmd) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); struct uci_element *e, *tmp; struct uci_package *p; struct uci_ptr ptr = { 0 }; @@ -749,25 +749,25 @@ uc_uci_pkg_command(uc_vm *vm, size_t nargs, enum pkg_cmd cmd) } static uc_value_t * -uc_uci_save(uc_vm *vm, size_t nargs) +uc_uci_save(uc_vm_t *vm, size_t nargs) { return uc_uci_pkg_command(vm, nargs, CMD_SAVE); } static uc_value_t * -uc_uci_commit(uc_vm *vm, size_t nargs) +uc_uci_commit(uc_vm_t *vm, size_t nargs) { return uc_uci_pkg_command(vm, nargs, CMD_COMMIT); } static uc_value_t * -uc_uci_revert(uc_vm *vm, size_t nargs) +uc_uci_revert(uc_vm_t *vm, size_t nargs) { return uc_uci_pkg_command(vm, nargs, CMD_REVERT); } static uc_value_t * -change_to_uval(uc_vm *vm, struct uci_delta *d) +change_to_uval(uc_vm_t *vm, struct uci_delta *d) { const char *types[] = { [UCI_CMD_REORDER] = "order", @@ -806,7 +806,7 @@ change_to_uval(uc_vm *vm, struct uci_delta *d) } static uc_value_t * -changes_to_uval(uc_vm *vm, struct uci_context *ctx, const char *package) +changes_to_uval(uc_vm_t *vm, struct uci_context *ctx, const char *package) { uc_value_t *a = NULL, *c; struct uci_package *p = NULL; @@ -856,10 +856,10 @@ changes_to_uval(uc_vm *vm, struct uci_context *ctx, const char *package) } static uc_value_t * -uc_uci_changes(uc_vm *vm, size_t nargs) +uc_uci_changes(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); uc_value_t *res, *chg; char **configs; int rv, i; @@ -890,12 +890,12 @@ uc_uci_changes(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_foreach(uc_vm *vm, size_t nargs) +uc_uci_foreach(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); - uc_value_t *conf = uc_get_arg(0); - uc_value_t *type = uc_get_arg(1); - uc_value_t *func = uc_get_arg(2); + struct uci_context **c = uc_fn_this("uci.cursor"); + uc_value_t *conf = uc_fn_arg(0); + uc_value_t *type = uc_fn_arg(1); + uc_value_t *func = uc_fn_arg(2); uc_value_t *rv = NULL; struct uci_package *p = NULL; struct uci_element *e, *tmp; @@ -927,8 +927,8 @@ uc_uci_foreach(uc_vm *vm, size_t nargs) if (type && strcmp(sc->type, ucv_string_get(type))) continue; - uc_push_val(ucv_get(func)); - uc_push_val(section_to_uval(vm, sc, i - 1)); + uc_value_push(ucv_get(func)); + uc_value_push(section_to_uval(vm, sc, i - 1)); ex = uc_call(1); @@ -937,7 +937,7 @@ uc_uci_foreach(uc_vm *vm, size_t nargs) break; ret = true; - rv = uc_pop_val(); + rv = uc_value_pop(); stop = (ucv_type(rv) == UC_BOOLEAN && !ucv_boolean_get(rv)); ucv_put(rv); @@ -952,9 +952,9 @@ uc_uci_foreach(uc_vm *vm, size_t nargs) } static uc_value_t * -uc_uci_configs(uc_vm *vm, size_t nargs) +uc_uci_configs(uc_vm_t *vm, size_t nargs) { - struct uci_context **c = uc_get_self("uci.cursor"); + struct uci_context **c = uc_fn_this("uci.cursor"); uc_value_t *a; char **configs; int i, rv; @@ -975,7 +975,7 @@ uc_uci_configs(uc_vm *vm, size_t nargs) } -static const uc_cfunction_list cursor_fns[] = { +static const uc_function_list_t cursor_fns[] = { { "load", uc_uci_load }, { "unload", uc_uci_unload }, { "get", uc_uci_get }, @@ -995,7 +995,7 @@ static const uc_cfunction_list cursor_fns[] = { { "error", uc_uci_error }, }; -static const uc_cfunction_list global_fns[] = { +static const uc_function_list_t global_fns[] = { { "error", uc_uci_error }, { "cursor", uc_uci_cursor }, }; @@ -1005,9 +1005,9 @@ static void close_uci(void *ud) { uci_free_context((struct uci_context *)ud); } -void uc_module_init(uc_value_t *scope) +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) { - uc_add_proto_functions(scope, global_fns); + uc_function_list_register(scope, global_fns); - cursor_type = uc_declare_type("uci.cursor", cursor_fns, close_uci); + cursor_type = uc_type_declare(vm, "uci.cursor", cursor_fns, close_uci); } @@ -28,29 +28,30 @@ #include <json-c/json.h> #endif -#include "compiler.h" -#include "lexer.h" -#include "lib.h" -#include "vm.h" -#include "source.h" +#include "ucode/compiler.h" +#include "ucode/lexer.h" +#include "ucode/lib.h" +#include "ucode/vm.h" +#include "ucode/source.h" static void print_usage(const char *app) { printf( - "== Usage ==\n\n" - " # %s [-d] [-l] [-r] [-S] [-R] [-e '[prefix=]{\"var\": ...}'] [-E [prefix=]env.json] {-i <file> | -s \"ucode script...\"}\n" + "Usage\n\n" + " # %s [-t] [-l] [-r] [-S] [-R] [-x function [-x ...]] [-e '[prefix=]{\"var\": ...}'] [-E [prefix=]env.json] {-i <file> | -s \"ucode script...\"}\n" " -h, --help Print this help\n" - " -i file Specify an ucode script to parse\n" - " -s \"ucode script...\" Specify an ucode fragment to parse\n" - " -d Instead of executing the script, dump the resulting AST as dot\n" + " -i file Execute the given ucode script file\n" + " -s \"ucode script...\" Execute the given string as ucode script\n" + " -t Enable VM execution tracing\n" " -l Do not strip leading block whitespace\n" " -r Do not trim trailing block newlines\n" " -S Enable strict mode\n" " -R Enable raw code mode\n" " -e Set global variables from given JSON object\n" " -E Set global variables from given JSON file\n" + " -x Disable given function\n" " -m Preload given module\n", basename(app)); } @@ -74,61 +75,49 @@ register_variable(uc_value_t *scope, const char *key, uc_value_t *val) static int -parse(uc_parse_config *config, uc_source *src, - uc_value_t *env, uc_value_t *modules, - int argc, char **argv) +compile(uc_vm_t *vm, uc_source_t *src) { - uc_value_t *globals = NULL, *arr; + uc_value_t *res = NULL; uc_function_t *entry; - uc_vm vm = { 0 }; - int i, rc = 0; + int rc = 0; char *err; - uc_vm_init(&vm, config); - - entry = uc_compile(config, src, &err); + entry = uc_compile(vm->config, src, &err); if (!entry) { fprintf(stderr, "%s", err); free(err); - rc = 2; + rc = -1; goto out; } - /* allocate global scope */ - globals = uc_alloc_global(&vm); - - /* register ARGV array */ - arr = ucv_array_new_length(&vm, argc); - - for (i = 0; i < argc; i++) - ucv_array_push(arr, ucv_string_new(argv[i])); + rc = uc_vm_execute(vm, entry, &res); - ucv_object_add(globals, "ARGV", arr); + switch (rc) { + case STATUS_OK: + rc = 0; + break; - /* load env variables */ - if (env) { - ucv_object_foreach(env, key, val) - register_variable(globals, key, ucv_get(val)); - } - - /* load std functions into global scope */ - uc_load_stdlib(globals); + case STATUS_EXIT: + rc = (int)ucv_int64_get(res); + break; - rc = uc_vm_execute(&vm, entry, globals, modules); + case ERROR_COMPILE: + rc = -1; + break; - if (rc) { - rc = 1; - goto out; + case ERROR_RUNTIME: + rc = -2; + break; } out: - uc_vm_free(&vm); + ucv_put(res); return rc; } -static uc_source * +static uc_source_t * read_stdin(char **ptr) { size_t rlen = 0, tlen = 0; @@ -198,12 +187,13 @@ parse_envfile(FILE *fp) int main(int argc, char **argv) { - uc_value_t *env = NULL, *modules = NULL, *o, *p; - uc_source *source = NULL, *envfile = NULL; + uc_source_t *source = NULL, *envfile = NULL; char *stdin = NULL, *c; + uc_vm_t vm = { 0 }; + uc_value_t *o, *p; int opt, rv = 0; - uc_parse_config config = { + uc_parse_config_t config = { .strict_declarations = false, .lstrip_blocks = true, .trim_blocks = true @@ -215,7 +205,21 @@ main(int argc, char **argv) goto out; } - while ((opt = getopt(argc, argv, "hlrSRe:E:i:s:m:")) != -1) + uc_vm_init(&vm, &config); + + /* load std functions into global scope */ + uc_stdlib_load(uc_vm_scope_get(&vm)); + + /* register ARGV array */ + o = ucv_array_new_length(&vm, argc); + + for (opt = 0; opt < argc; opt++) + ucv_array_push(o, ucv_string_new(argv[opt])); + + ucv_object_add(uc_vm_scope_get(&vm), "ARGV", o); + + /* parse options */ + while ((opt = getopt(argc, argv, "hlrtSRe:E:i:s:m:x:")) != -1) { switch (opt) { case 'h': @@ -311,27 +315,40 @@ main(int argc, char **argv) goto out; } - env = env ? env : ucv_object_new(NULL); - if (c > optarg && optarg[0]) { - p = ucv_object_new(NULL); - ucv_object_add(env, optarg, p); + p = ucv_object_new(&vm); + ucv_object_add(uc_vm_scope_get(&vm), optarg, p); } else { - p = env; + p = uc_vm_scope_get(&vm); } ucv_object_foreach(o, key, val) - ucv_object_add(p, key, ucv_get(val)); + register_variable(p, key, ucv_get(val)); ucv_put(o); break; case 'm': - modules = modules ? modules : ucv_array_new(NULL); + o = uc_vm_invoke(&vm, "require", 1, ucv_string_new(optarg)); - ucv_array_push(modules, ucv_string_new(optarg)); + if (o) + register_variable(uc_vm_scope_get(&vm), optarg, o); + + break; + + case 't': + uc_vm_trace_set(&vm, 1); + break; + + case 'x': + o = ucv_object_get(uc_vm_scope_get(&vm), optarg, NULL); + + if (ucv_is_callable(o)) + ucv_object_delete(uc_vm_scope_get(&vm), optarg); + else + fprintf(stderr, "Unknown function %s specified\n", optarg); break; } @@ -353,13 +370,12 @@ main(int argc, char **argv) goto out; } - rv = parse(&config, source, env, modules, argc, argv); + rv = compile(&vm, source); out: - ucv_put(modules); - ucv_put(env); - uc_source_put(source); + uc_vm_free(&vm); + return rv; } @@ -16,14 +16,14 @@ #include <string.h> -#include "source.h" +#include "ucode/source.h" -uc_source * +uc_source_t * uc_source_new_file(const char *path) { FILE *fp = fopen(path, "rb"); - uc_source *src; + uc_source_t *src; if (!fp) return NULL; @@ -41,11 +41,11 @@ uc_source_new_file(const char *path) return src; } -uc_source * +uc_source_t * uc_source_new_buffer(const char *name, char *buf, size_t len) { FILE *fp = fmemopen(buf, len, "rb"); - uc_source *src; + uc_source_t *src; if (!fp) return NULL; @@ -64,9 +64,9 @@ uc_source_new_buffer(const char *name, char *buf, size_t len) } size_t -uc_source_get_line(uc_source *source, size_t *offset) +uc_source_get_line(uc_source_t *source, size_t *offset) { - uc_lineinfo *lines = &source->lineinfo; + uc_lineinfo_t *lines = &source->lineinfo; size_t i, pos = 0, line = 0, lastoff = 0; for (i = 0; i < lines->count; i++) { @@ -88,8 +88,8 @@ uc_source_get_line(uc_source *source, size_t *offset) return 0; } -uc_source * -uc_source_get(uc_source *source) +uc_source_t * +uc_source_get(uc_source_t *source) { if (!source) return NULL; @@ -100,7 +100,7 @@ uc_source_get(uc_source *source) } void -uc_source_put(uc_source *source) +uc_source_put(uc_source_t *source) { if (!source) return; diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t index aab5b16..2c22131 100644 --- a/tests/cram/test_basic.t +++ b/tests/cram/test_basic.t @@ -10,19 +10,20 @@ setup common environment: check that ucode provides exepected help: $ ucode | sed 's/ucode-san/ucode/' - == Usage == + Usage - # ucode [-d] [-l] [-r] [-S] [-R] [-e '[prefix=]{"var": ...}'] [-E [prefix=]env.json] {-i <file> | -s "ucode script..."} + # ucode [-t] [-l] [-r] [-S] [-R] [-x function [-x ...]] [-e '[prefix=]{"var": ...}'] [-E [prefix=]env.json] {-i <file> | -s "ucode script..."} -h, --help\tPrint this help (esc) - -i file\tSpecify an ucode script to parse (esc) - -s "ucode script..."\tSpecify an ucode fragment to parse (esc) - -d Instead of executing the script, dump the resulting AST as dot + -i file\tExecute the given ucode script file (esc) + -s "ucode script..."\tExecute the given string as ucode script (esc) + -t Enable VM execution tracing -l Do not strip leading block whitespace -r Do not trim trailing block newlines -S Enable strict mode -R Enable raw code mode -e Set global variables from given JSON object -E Set global variables from given JSON file + -x Disable given function -m Preload given module check that ucode prints greetings: @@ -38,15 +39,13 @@ check that ucode provides proper error messages: $ ucode -m foo -s ' ' Runtime error: No module named 'foo' could be found - At start of program - [1] + [254] $ touch moo; ucode -m foo -i moo Runtime error: No module named 'foo' could be found - At start of program - [1] + [254] check that ucode can load fs module: @@ -20,10 +20,11 @@ #include <endian.h> #include <errno.h> #include <math.h> +#include <ctype.h> -#include "types.h" -#include "util.h" -#include "vm.h" +#include "ucode/types.h" +#include "ucode/util.h" +#include "ucode/vm.h" uc_type_t ucv_type(uc_value_t *uv) @@ -58,9 +59,6 @@ ucv_typename(uc_value_t *uv) return "unknown"; } -static uc_ressource_type_t * -ucv_ressource_type_get(size_t type); - static void ucv_unref(uc_weakref_t *ref) { @@ -120,7 +118,7 @@ ucv_gc_mark(uc_value_t *uv) { uc_function_t *function; uc_closure_t *closure; - uc_upvalref_t *upval; + uc_upval_tref_t *upval; uc_object_t *object; uc_array_t *array; struct lh_entry *entry; @@ -165,14 +163,14 @@ ucv_gc_mark(uc_value_t *uv) ucv_set_mark(uv); for (i = 0; i < function->nupvals; i++) - ucv_gc_mark((uc_value_t *)closure->upvals[i]); + ucv_gc_mark(&closure->upvals[i]->header); - ucv_gc_mark((uc_value_t *)function); + ucv_gc_mark(&function->header); break; case UC_UPVALUE: - upval = (uc_upvalref_t *)uv; + upval = (uc_upval_tref_t *)uv; ucv_gc_mark(upval->value); break; @@ -188,7 +186,7 @@ ucv_free(uc_value_t *uv, bool retain) uc_ressource_t *ressource; uc_function_t *function; uc_closure_t *closure; - uc_upvalref_t *upval; + uc_upval_tref_t *upval; uc_regexp_t *regexp; uc_object_t *object; uc_array_t *array; @@ -241,14 +239,14 @@ ucv_free(uc_value_t *uv, bool retain) ref = &closure->ref; for (i = 0; i < function->nupvals; i++) - ucv_put_value((uc_value_t *)closure->upvals[i], retain); + ucv_put_value(&closure->upvals[i]->header, retain); - ucv_put_value((uc_value_t *)function, retain); + ucv_put_value(&function->header, retain); break; case UC_RESSOURCE: ressource = (uc_ressource_t *)uv; - restype = ucv_ressource_type_get(ressource->type); + restype = ressource->type; if (restype && restype->free) restype->free(ressource->data); @@ -256,7 +254,7 @@ ucv_free(uc_value_t *uv, bool retain) break; case UC_UPVALUE: - upval = (uc_upvalref_t *)uv; + upval = (uc_upval_tref_t *)uv; ucv_put_value(upval->value, retain); break; } @@ -563,13 +561,13 @@ ucv_double_get(uc_value_t *uv) uc_value_t * -ucv_array_new(uc_vm *vm) +ucv_array_new(uc_vm_t *vm) { return ucv_array_new_length(vm, 0); } uc_value_t * -ucv_array_new_length(uc_vm *vm, size_t length) +ucv_array_new_length(uc_vm_t *vm, size_t length) { uc_array_t *array; @@ -758,7 +756,7 @@ ucv_free_object_entry(struct lh_entry *entry) } uc_value_t * -ucv_object_new(uc_vm *vm) +ucv_object_new(uc_vm_t *vm) { struct lh_table *table; uc_object_t *object; @@ -863,7 +861,7 @@ ucv_object_length(uc_value_t *uv) uc_value_t * -ucv_function_new(const char *name, size_t srcpos, uc_source *source) +ucv_function_new(const char *name, size_t srcpos, uc_source_t *source) { size_t namelen = 0; uc_function_t *fn; @@ -927,16 +925,16 @@ ucv_cfunction_new(const char *name, uc_cfn_ptr_t fptr) uc_value_t * -ucv_closure_new(uc_vm *vm, uc_function_t *function, bool arrow_fn) +ucv_closure_new(uc_vm_t *vm, uc_function_t *function, bool arrow_fn) { uc_closure_t *closure; - closure = xalloc(sizeof(*closure) + (sizeof(uc_upvalref_t *) * function->nupvals)); + closure = xalloc(sizeof(*closure) + (sizeof(uc_upval_tref_t *) * function->nupvals)); closure->header.type = UC_CLOSURE; closure->header.refcount = 1; closure->function = function; closure->is_arrow = arrow_fn; - closure->upvals = function->nupvals ? (uc_upvalref_t **)((uintptr_t)closure + ALIGN(sizeof(*closure))) : NULL; + closure->upvals = function->nupvals ? (uc_upval_tref_t **)((uintptr_t)closure + ALIGN(sizeof(*closure))) : NULL; if (vm) ucv_ref(&vm->values, &closure->ref); @@ -945,44 +943,38 @@ ucv_closure_new(uc_vm *vm, uc_function_t *function, bool arrow_fn) } -static uc_ressource_types_t res_types; - uc_ressource_type_t * -ucv_ressource_type_add(const char *name, uc_value_t *proto, void (*freefn)(void *)) +ucv_ressource_type_add(uc_vm_t *vm, const char *name, uc_value_t *proto, void (*freefn)(void *)) { - uc_ressource_type_t *existing; + uc_ressource_type_t *type; - existing = ucv_ressource_type_lookup(name); + type = ucv_ressource_type_lookup(vm, name); - if (existing) { + if (type) { ucv_put(proto); - return existing; + return type; } - uc_vector_grow(&res_types); + type = xalloc(sizeof(*type)); + type->name = name; + type->proto = proto; + type->free = freefn; - res_types.entries[res_types.count].name = name; - res_types.entries[res_types.count].proto = proto; - res_types.entries[res_types.count].free = freefn; + uc_vector_grow(&vm->restypes); + vm->restypes.entries[vm->restypes.count++] = type; - return &res_types.entries[res_types.count++]; -} - -static uc_ressource_type_t * -ucv_ressource_type_get(size_t type) -{ - return (type > 0 && type <= res_types.count) ? &res_types.entries[type - 1] : NULL; + return type; } uc_ressource_type_t * -ucv_ressource_type_lookup(const char *name) +ucv_ressource_type_lookup(uc_vm_t *vm, const char *name) { size_t i; - for (i = 0; i < res_types.count; i++) - if (!strcmp(res_types.entries[i].name, name)) - return &res_types.entries[i]; + for (i = 0; i < vm->restypes.count; i++) + if (!strcmp(vm->restypes.entries[i]->name, name)) + return vm->restypes.entries[i]; return NULL; } @@ -996,7 +988,7 @@ ucv_ressource_new(uc_ressource_type_t *type, void *data) res = xalloc(sizeof(*res)); res->header.type = UC_RESSOURCE; res->header.refcount = 1; - res->type = type ? (type - res_types.entries) + 1 : 0; + res->type = type; res->data = data; return &res->header; @@ -1006,15 +998,12 @@ void ** ucv_ressource_dataptr(uc_value_t *uv, const char *name) { uc_ressource_t *res = (uc_ressource_t *)uv; - uc_ressource_type_t *type; if (ucv_type(uv) != UC_RESSOURCE) return NULL; if (name) { - type = ucv_ressource_type_lookup(name); - - if (!type || type != ucv_ressource_type_get(res->type)) + if (!res->type || strcmp(res->type->name, name)) return NULL; } @@ -1058,13 +1047,6 @@ ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char return NULL; } - /* - json_object_object_add(re->header.jso, "source", xjs_new_string(pattern)); - json_object_object_add(re->header.jso, "i", xjs_new_boolean(icase)); - json_object_object_add(re->header.jso, "g", xjs_new_boolean(global)); - json_object_object_add(re->header.jso, "s", xjs_new_boolean(newline)); - */ - return &re->header; } @@ -1072,7 +1054,7 @@ ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char uc_value_t * ucv_upvalref_new(size_t slot) { - uc_upvalref_t *up; + uc_upval_tref_t *up; up = xalloc(sizeof(*up)); up->header.type = UC_UPVALUE; @@ -1104,7 +1086,7 @@ ucv_prototype_get(uc_value_t *uv) case UC_RESSOURCE: ressource = (uc_ressource_t *)uv; - restype = ucv_ressource_type_get(ressource->type); + restype = ressource->type; return restype ? restype->proto : NULL; @@ -1158,7 +1140,7 @@ ucv_property_get(uc_value_t *uv, const char *key) uc_value_t * -ucv_from_json(uc_vm *vm, json_object *jso) +ucv_from_json(uc_vm_t *vm, json_object *jso) { //uc_array_t *arr; uc_value_t *uv, *item; @@ -1366,7 +1348,7 @@ ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool r } static bool -ucv_call_tostring(uc_vm *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) +ucv_call_tostring(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) { uc_value_t *proto = ucv_prototype_get(uv); uc_value_t *tostr = ucv_object_get(proto, "tostring", NULL); @@ -1422,7 +1404,7 @@ ucv_to_stringbuf_add_padding(uc_stringbuf_t *pb, char pad_char, size_t pad_size) } void -ucv_to_stringbuf_formatted(uc_vm *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t depth, char pad_char, size_t pad_size) +ucv_to_stringbuf_formatted(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t depth, char pad_char, size_t pad_size) { bool json = (pad_char != '\0'); uc_ressource_type_t *restype; @@ -1628,7 +1610,7 @@ ucv_to_stringbuf_formatted(uc_vm *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t case UC_RESSOURCE: ressource = (uc_ressource_t *)uv; - restype = ucv_ressource_type_get(ressource->type); + restype = ressource->type; ucv_stringbuf_printf(pb, "%s<%s %p>%s", json ? "\"" : "", @@ -1651,7 +1633,7 @@ ucv_to_stringbuf_formatted(uc_vm *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t } static char * -ucv_to_string_any(uc_vm *vm, uc_value_t *uv, char pad_char, size_t pad_size) +ucv_to_string_any(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) { uc_stringbuf_t *pb = xprintbuf_new(); char *rv; @@ -1666,19 +1648,91 @@ ucv_to_string_any(uc_vm *vm, uc_value_t *uv, char pad_char, size_t pad_size) } char * -ucv_to_string(uc_vm *vm, uc_value_t *uv) +ucv_to_string(uc_vm_t *vm, uc_value_t *uv) { return ucv_to_string_any(vm, uv, '\0', 0); } char * -ucv_to_jsonstring_formatted(uc_vm *vm, uc_value_t *uv, char pad_char, size_t pad_size) +ucv_to_jsonstring_formatted(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) { return ucv_to_string_any(vm, uv, pad_char ? pad_char : '\1', pad_size); } +uc_type_t +ucv_cast_number(uc_value_t *v, int64_t *n, double *d) +{ + bool is_double = false; + const char *s; + char *e; + + *d = 0.0; + *n = 0; + + switch (ucv_type(v)) { + case UC_INTEGER: + *n = ucv_int64_get(v); + + return UC_INTEGER; + + case UC_DOUBLE: + *d = ucv_double_get(v); + + return UC_DOUBLE; + + case UC_NULL: + return UC_INTEGER; + + case UC_BOOLEAN: + *n = ucv_boolean_get(v); + + return UC_INTEGER; + + case UC_STRING: + s = ucv_string_get(v); + + while (isspace(*s)) + s++; + + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && isxdigit(s[2])) { + *n = strtoll(s, &e, 16); + } + else if (s[0] == '0' && isdigit(s[2])) { + *n = strtoll(s, &e, 8); + } + else { + *n = strtoll(s, &e, 10); + + if (*e == '.') { + *d = strtod(s, &e); + is_double = (e > s); + } + } + + while (isspace(*e)) + e++; + + if (*e) { + *d = NAN; + + return UC_DOUBLE; + } + + if (is_double) + return UC_DOUBLE; + + return UC_INTEGER; + + default: + *d = NAN; + + return UC_DOUBLE; + } +} + + bool -ucv_equal(uc_value_t *uv1, uc_value_t *uv2) +ucv_is_equal(uc_value_t *uv1, uc_value_t *uv2) { uc_type_t t1 = ucv_type(uv1); uc_type_t t2 = ucv_type(uv2); @@ -1743,7 +1797,7 @@ ucv_equal(uc_value_t *uv1, uc_value_t *uv2) return false; for (u1 = 0; u1 < u2; u1++) - if (!ucv_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) + if (!ucv_is_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) return false; return true; @@ -1756,7 +1810,7 @@ ucv_equal(uc_value_t *uv1, uc_value_t *uv2) return false; ucv_object_foreach(uv1, key, val) { - if (!ucv_equal(val, ucv_object_get(uv2, key, NULL))) + if (!ucv_is_equal(val, ucv_object_get(uv2, key, NULL))) return false; } @@ -1775,13 +1829,232 @@ ucv_equal(uc_value_t *uv1, uc_value_t *uv2) } } -void -ucv_gc(uc_vm *vm, bool final) +bool +ucv_is_truish(uc_value_t *val) +{ + double d; + + switch (ucv_type(val)) { + case UC_INTEGER: + if (ucv_is_u64(val)) + return (ucv_uint64_get(val) != 0); + + return (ucv_int64_get(val) != 0); + + case UC_DOUBLE: + d = ucv_double_get(val); + + return (d != 0 && !isnan(d)); + + case UC_BOOLEAN: + return ucv_boolean_get(val); + + case UC_STRING: + return (ucv_string_length(val) > 0); + + case UC_NULL: + return false; + + default: + return true; + } +} + + +bool +ucv_compare(int how, uc_value_t *v1, uc_value_t *v2) +{ + uc_type_t t1 = ucv_type(v1); + uc_type_t t2 = ucv_type(v2); + int64_t n1, n2, delta; + double d1, d2; + + if (t1 == UC_STRING && t2 == UC_STRING) { + delta = strcmp(ucv_string_get(v1), ucv_string_get(v2)); + } + else { + if (t1 == t2 && !ucv_is_scalar(v1)) { + delta = (intptr_t)v1 - (intptr_t)v2; + } + else { + t1 = ucv_cast_number(v1, &n1, &d1); + t2 = ucv_cast_number(v2, &n2, &d2); + + if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) { + d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1; + d2 = (t2 == UC_DOUBLE) ? d2 : (double)n2; + + /* all comparison results except `!=` involving NaN are false */ + if (isnan(d1) || isnan(d2)) + return (how == I_NE); + + if (d1 == d2) + delta = 0; + else if (d1 < d2) + delta = -1; + else + delta = 1; + } + else { + delta = n1 - n2; + } + } + } + + switch (how) { + case I_LT: + return (delta < 0); + + case I_LE: + return (delta <= 0); + + case I_GT: + return (delta > 0); + + case I_GE: + return (delta >= 0); + + case I_EQ: + return (delta == 0); + + case I_NE: + return (delta != 0); + + default: + return false; + } +} + + +static char * +ucv_key_to_string(uc_vm_t *vm, uc_value_t *val) +{ + if (ucv_type(val) != UC_STRING) + return ucv_to_string(vm, val); + + return NULL; +} + +static int64_t +ucv_key_to_index(uc_value_t *val) +{ + const char *k; + int64_t idx; + double d; + char *e; + + /* only consider doubles with integer values as array keys */ + if (ucv_type(val) == UC_DOUBLE) { + d = ucv_double_get(val); + + if ((double)(int64_t)(d) != d) + return -1; + + return (int64_t)d; + } + else if (ucv_type(val) == UC_INTEGER) { + return ucv_int64_get(val); + } + else if (ucv_type(val) == UC_STRING) { + errno = 0; + k = ucv_string_get(val); + idx = strtoll(k, &e, 0); + + if (errno != 0 || e == k || *e != 0) + return -1; + + return idx; + } + + return -1; +} + +uc_value_t * +ucv_key_get(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) +{ + uc_value_t *o, *v = NULL; + int64_t idx; + bool found; + char *k; + + if (ucv_type(scope) == UC_ARRAY) { + idx = ucv_key_to_index(key); + + if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) + return ucv_get(ucv_array_get(scope, idx)); + } + + k = ucv_key_to_string(vm, key); + + for (o = scope; o; o = ucv_prototype_get(o)) { + if (ucv_type(o) != UC_OBJECT) + continue; + + v = ucv_object_get(o, k ? k : ucv_string_get(key), &found); + + if (found) + break; + } + + free(k); + + return ucv_get(v); +} + +uc_value_t * +ucv_key_set(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) +{ + int64_t idx; + char *s; + bool rv; + + if (!key) + return NULL; + + if (ucv_type(scope) == UC_ARRAY) { + idx = ucv_key_to_index(key); + + if (idx < 0 || !ucv_array_set(scope, idx, val)) + return NULL; + + return ucv_get(val); + } + + s = ucv_key_to_string(vm, key); + rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val); + free(s); + + return rv ? ucv_get(val) : NULL; +} + +bool +ucv_key_delete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) +{ + char *s; + bool rv; + + if (!key) + return NULL; + + s = ucv_key_to_string(vm, key); + rv = ucv_object_delete(scope, s ? s : ucv_string_get(key)); + free(s); + + return rv; +} + + +static void +ucv_gc_common(uc_vm_t *vm, bool final) { uc_weakref_t *ref, *tmp; uc_value_t *val; size_t i; + /* back out early if value list is uninitialized */ + if (!vm->values.prev || !vm->values.next) + return; + if (!final) { /* mark reachable objects */ ucv_gc_mark(vm->globals); @@ -1814,18 +2087,14 @@ ucv_gc(uc_vm *vm, bool final) } } - -#ifdef __GNUC__ - -__attribute__((destructor)) -static void ucv_ressource_types_free(void) +void +ucv_gc(uc_vm_t *vm) { - size_t i; - - for (i = 0; i < res_types.count; i++) - ucv_put(res_types.entries[i].proto); - - uc_vector_clear(&res_types); + ucv_gc_common(vm, false); } -#endif +void +ucv_freeall(uc_vm_t *vm) +{ + ucv_gc_common(vm, true); +} @@ -20,10 +20,10 @@ #include <ctype.h> /* isspace(), isdigit(), isxdigit() */ #include <errno.h> -#include "util.h" -#include "chunk.h" -#include "value.h" -#include "vm.h" +#include "ucode/util.h" +#include "ucode/chunk.h" +#include "ucode/vallist.h" +#include "ucode/vm.h" #define TAG_TYPE uint64_t #define TAG_BITS 3 @@ -43,291 +43,8 @@ #define UC_VALLIST_CHUNK_SIZE 8 -bool -uc_val_is_truish(uc_value_t *val) -{ - double d; - - switch (ucv_type(val)) { - case UC_INTEGER: - if (ucv_is_u64(val)) - return (ucv_uint64_get(val) != 0); - - return (ucv_int64_get(val) != 0); - - case UC_DOUBLE: - d = ucv_double_get(val); - - return (d != 0 && !isnan(d)); - - case UC_BOOLEAN: - return ucv_boolean_get(val); - - case UC_STRING: - return (ucv_string_length(val) > 0); - - case UC_NULL: - return false; - - default: - return true; - } -} - -uc_type_t -uc_cast_number(uc_value_t *v, int64_t *n, double *d) -{ - bool is_double = false; - const char *s; - char *e; - - *d = 0.0; - *n = 0; - - switch (ucv_type(v)) { - case UC_INTEGER: - *n = ucv_int64_get(v); - - return UC_INTEGER; - - case UC_DOUBLE: - *d = ucv_double_get(v); - - return UC_DOUBLE; - - case UC_NULL: - return UC_INTEGER; - - case UC_BOOLEAN: - *n = ucv_boolean_get(v); - - return UC_INTEGER; - - case UC_STRING: - s = ucv_string_get(v); - - while (isspace(*s)) - s++; - - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && isxdigit(s[2])) { - *n = strtoll(s, &e, 16); - } - else if (s[0] == '0' && isdigit(s[2])) { - *n = strtoll(s, &e, 8); - } - else { - *n = strtoll(s, &e, 10); - - if (*e == '.') { - *d = strtod(s, &e); - is_double = (e > s); - } - } - - while (isspace(*e)) - e++; - - if (*e) { - *d = NAN; - - return UC_DOUBLE; - } - - if (is_double) - return UC_DOUBLE; - - return UC_INTEGER; - - default: - *d = NAN; - - return UC_DOUBLE; - } -} - -static char * -uc_tostring(uc_vm *vm, uc_value_t *val) -{ - if (ucv_type(val) != UC_STRING) - return ucv_to_string(vm, val); - - return NULL; -} - -static int64_t -uc_toidx(uc_value_t *val) -{ - const char *k; - int64_t idx; - double d; - char *e; - - /* only consider doubles with integer values as array keys */ - if (ucv_type(val) == UC_DOUBLE) { - d = ucv_double_get(val); - - if ((double)(int64_t)(d) != d) - return -1; - - return (int64_t)d; - } - else if (ucv_type(val) == UC_INTEGER) { - return ucv_int64_get(val); - } - else if (ucv_type(val) == UC_STRING) { - errno = 0; - k = ucv_string_get(val); - idx = strtoll(k, &e, 0); - - if (errno != 0 || e == k || *e != 0) - return -1; - - return idx; - } - - return -1; -} - -uc_value_t * -uc_getval(uc_vm *vm, uc_value_t *scope, uc_value_t *key) -{ - uc_value_t *o, *v = NULL; - int64_t idx; - bool found; - char *k; - - if (ucv_type(scope) == UC_ARRAY) { - idx = uc_toidx(key); - - if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) - return ucv_get(ucv_array_get(scope, idx)); - } - - k = uc_tostring(vm, key); - - for (o = scope; o; o = ucv_prototype_get(o)) { - if (ucv_type(o) != UC_OBJECT) - continue; - - v = ucv_object_get(o, k ? k : ucv_string_get(key), &found); - - if (found) - break; - } - - free(k); - - return ucv_get(v); -} - -uc_value_t * -uc_setval(uc_vm *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) -{ - int64_t idx; - char *s; - bool rv; - - if (!key) - return NULL; - - if (ucv_type(scope) == UC_ARRAY) { - idx = uc_toidx(key); - - if (idx < 0 || !ucv_array_set(scope, idx, val)) - return NULL; - - return ucv_get(val); - } - - s = uc_tostring(vm, key); - rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val); - free(s); - - return rv ? ucv_get(val) : NULL; -} - -bool -uc_delval(uc_vm *vm, uc_value_t *scope, uc_value_t *key) -{ - char *s; - bool rv; - - if (!key) - return NULL; - - s = uc_tostring(vm, key); - rv = ucv_object_delete(scope, s ? s : ucv_string_get(key)); - free(s); - - return rv; -} - -bool -uc_cmp(int how, uc_value_t *v1, uc_value_t *v2) -{ - uc_type_t t1 = ucv_type(v1); - uc_type_t t2 = ucv_type(v2); - int64_t n1, n2, delta; - double d1, d2; - - if (t1 == UC_STRING && t2 == UC_STRING) { - delta = strcmp(ucv_string_get(v1), ucv_string_get(v2)); - } - else { - if (t1 == t2 && !ucv_is_scalar(v1)) { - delta = (intptr_t)v1 - (intptr_t)v2; - } - else { - t1 = uc_cast_number(v1, &n1, &d1); - t2 = uc_cast_number(v2, &n2, &d2); - - if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) { - d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1; - d2 = (t2 == UC_DOUBLE) ? d2 : (double)n2; - - /* all comparison results except `!=` involving NaN are false */ - if (isnan(d1) || isnan(d2)) - return (how == I_NE); - - if (d1 == d2) - delta = 0; - else if (d1 < d2) - delta = -1; - else - delta = 1; - } - else { - delta = n1 - n2; - } - } - } - - switch (how) { - case I_LT: - return (delta < 0); - - case I_LE: - return (delta <= 0); - - case I_GT: - return (delta > 0); - - case I_GE: - return (delta >= 0); - - case I_EQ: - return (delta == 0); - - case I_NE: - return (delta != 0); - - default: - return false; - } -} - void -uc_vallist_init(uc_value_list *list) +uc_vallist_init(uc_value_list_t *list) { list->isize = 0; list->dsize = 0; @@ -336,7 +53,7 @@ uc_vallist_init(uc_value_list *list) } void -uc_vallist_free(uc_value_list *list) +uc_vallist_free(uc_value_list_t *list) { uc_value_t *o; size_t i; @@ -355,7 +72,7 @@ uc_vallist_free(uc_value_list *list) } static void -add_num(uc_value_list *list, int64_t n) +add_num(uc_value_list_t *list, int64_t n) { size_t sz = TAG_ALIGN(sizeof(n)); @@ -380,7 +97,7 @@ add_num(uc_value_list *list, int64_t n) } static ssize_t -find_num(uc_value_list *list, int64_t n) +find_num(uc_value_list_t *list, int64_t n) { TAG_TYPE search; size_t i; @@ -411,7 +128,7 @@ find_num(uc_value_list *list, int64_t n) } static void -add_dbl(uc_value_list *list, double d) +add_dbl(uc_value_list_t *list, double d) { size_t sz = TAG_ALIGN(sizeof(d)); @@ -430,7 +147,7 @@ add_dbl(uc_value_list *list, double d) } static ssize_t -find_dbl(uc_value_list *list, double d) +find_dbl(uc_value_list_t *list, double d) { size_t i; @@ -451,7 +168,7 @@ find_dbl(uc_value_list *list, double d) } static void -add_str(uc_value_list *list, const char *s, size_t slen) +add_str(uc_value_list_t *list, const char *s, size_t slen) { uint32_t sl; size_t sz; @@ -497,7 +214,7 @@ add_str(uc_value_list *list, const char *s, size_t slen) } static ssize_t -find_str(uc_value_list *list, const char *s, size_t slen) +find_str(uc_value_list_t *list, const char *s, size_t slen) { TAG_TYPE search; size_t i, len; @@ -539,7 +256,7 @@ find_str(uc_value_list *list, const char *s, size_t slen) } static void -add_ptr(uc_value_list *list, void *ptr) +add_ptr(uc_value_list_t *list, void *ptr) { size_t sz = TAG_ALIGN(sizeof(ptr)); @@ -558,7 +275,7 @@ add_ptr(uc_value_list *list, void *ptr) } ssize_t -uc_vallist_add(uc_value_list *list, uc_value_t *value) +uc_vallist_add(uc_value_list_t *list, uc_value_t *value) { ssize_t existing; @@ -615,7 +332,7 @@ uc_vallist_add(uc_value_list *list, uc_value_t *value) } uc_value_type_t -uc_vallist_type(uc_value_list *list, size_t idx) +uc_vallist_type(uc_value_list_t *list, size_t idx) { if (idx >= list->isize) return TAG_INVAL; @@ -624,7 +341,7 @@ uc_vallist_type(uc_value_list *list, size_t idx) } uc_value_t * -uc_vallist_get(uc_value_list *list, size_t idx) +uc_vallist_get(uc_value_list_t *list, size_t idx) { char str[sizeof(TAG_TYPE)]; size_t n, len; @@ -14,16 +14,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdlib.h> #include <stdarg.h> #include <string.h> #include <assert.h> #include <ctype.h> #include <math.h> -#include "vm.h" -#include "compiler.h" -#include "lib.h" /* format_error_context() */ +#include "ucode/vm.h" +#include "ucode/compiler.h" +#include "ucode/lib.h" /* uc_error_context_format() */ #undef __insn #define __insn(_name) #_name, @@ -77,11 +76,12 @@ static const char *exception_type_strings[] = { [EXCEPTION_TYPE] = "Type error", [EXCEPTION_REFERENCE] = "Reference error", [EXCEPTION_USER] = "Error", + [EXCEPTION_EXIT] = "Exit" }; static void -uc_vm_reset_stack(uc_vm *vm) +uc_vm_reset_stack(uc_vm_t *vm) { while (vm->stack.count > 0) { vm->stack.count--; @@ -91,24 +91,54 @@ uc_vm_reset_stack(uc_vm *vm) } static uc_value_t * -uc_vm_callframe_pop(uc_vm *vm); +uc_vm_callframe_pop(uc_vm_t *vm); static void -uc_vm_reset_callframes(uc_vm *vm) +uc_vm_reset_callframes(uc_vm_t *vm) { while (vm->callframes.count > 0) ucv_put(uc_vm_callframe_pop(vm)); } -void uc_vm_init(uc_vm *vm, uc_parse_config *config) +static uc_value_t * +uc_vm_alloc_global_scope(uc_vm_t *vm) { - char *s = getenv("TRACE"); + const char *path[] = { LIB_SEARCH_PATH }; + uc_value_t *scope, *arr; + size_t i; + + scope = ucv_object_new(vm); + + /* build default require() search path */ + arr = ucv_array_new(vm); + + for (i = 0; i < ARRAY_SIZE(path); i++) + ucv_array_push(arr, ucv_string_new(path[i])); + + /* register module related constants */ + ucv_object_add(scope, "REQUIRE_SEARCH_PATH", arr); + ucv_object_add(scope, "modules", ucv_object_new(vm)); + + /* register scope math constants */ + ucv_object_add(scope, "NaN", ucv_double_new(NAN)); + ucv_object_add(scope, "Infinity", ucv_double_new(INFINITY)); + + /* register global property */ + ucv_object_add(scope, "global", ucv_get(scope)); + + uc_vm_scope_set(vm, scope); + + return scope; +} + +static void +uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex); +void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config) +{ vm->exception.type = EXCEPTION_NONE; vm->exception.message = NULL; - vm->trace = s ? strtoul(s, NULL, 0) : 0; - vm->config = config; vm->open_upvals = NULL; @@ -121,11 +151,18 @@ void uc_vm_init(uc_vm *vm, uc_parse_config *config) vm->output = stdout; uc_vm_reset_stack(vm); + + uc_vm_alloc_global_scope(vm); + + uc_vm_exception_handler_set(vm, uc_vm_output_exception); + + uc_vm_trace_set(vm, 0); } -void uc_vm_free(uc_vm *vm) +void uc_vm_free(uc_vm_t *vm) { - uc_upvalref_t *ref; + uc_upval_tref_t *ref; + size_t i; ucv_put(vm->exception.stacktrace); free(vm->exception.message); @@ -136,6 +173,9 @@ void uc_vm_free(uc_vm *vm) vm->open_upvals = ref; } + for (i = 0; i < vm->restypes.count; i++) + ucv_put(vm->restypes.entries[i]->proto); + uc_vm_reset_callframes(vm); uc_vm_reset_stack(vm); uc_vector_clear(&vm->stack); @@ -143,37 +183,42 @@ void uc_vm_free(uc_vm *vm) printbuf_free(vm->strbuf); - ucv_gc(vm, true); + ucv_freeall(vm); + + for (i = 0; i < vm->restypes.count; i++) + free(vm->restypes.entries[i]); + + uc_vector_clear(&vm->restypes); } -static uc_chunk * -uc_vm_frame_chunk(uc_callframe *frame) +static uc_chunk_t * +uc_vm_frame_chunk(uc_callframe_t *frame) { return frame->closure ? &frame->closure->function->chunk : NULL; } -static uc_callframe * -uc_vm_current_frame(uc_vm *vm) +static uc_callframe_t * +uc_vm_current_frame(uc_vm_t *vm) { return uc_vector_last(&vm->callframes); } -static uc_chunk * -uc_vm_current_chunk(uc_vm *vm) +static uc_chunk_t * +uc_vm_current_chunk(uc_vm_t *vm) { return uc_vm_frame_chunk(uc_vm_current_frame(vm)); } static bool -uc_vm_is_strict(uc_vm *vm) +uc_vm_is_strict(uc_vm_t *vm) { return uc_vm_current_frame(vm)->strict; } -static enum insn_type -uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk) +static uc_vm_insn_t +uc_vm_decode_insn(uc_vm_t *vm, uc_callframe_t *frame, uc_chunk_t *chunk) { - enum insn_type insn; + uc_vm_insn_t insn; #ifndef NDEBUG uint8_t *end = chunk->entries + chunk->count; @@ -238,7 +283,7 @@ uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk) static char * -uc_vm_format_val(uc_vm *vm, uc_value_t *val) +uc_vm_format_val(uc_vm_t *vm, uc_value_t *val) { if (!vm->strbuf) vm->strbuf = xprintbuf_new(); @@ -256,12 +301,12 @@ uc_vm_format_val(uc_vm *vm, uc_value_t *val) } static void -uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) +uc_vm_frame_dump(uc_vm_t *vm, uc_callframe_t *frame) { - uc_chunk *chunk = uc_vm_frame_chunk(frame); + uc_chunk_t *chunk = uc_vm_frame_chunk(frame); uc_function_t *function; uc_closure_t *closure; - uc_upvalref_t *ref; + uc_upval_tref_t *ref; uc_value_t *v; size_t i; @@ -316,7 +361,7 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) } void -uc_vm_stack_push(uc_vm *vm, uc_value_t *value) +uc_vm_stack_push(uc_vm_t *vm, uc_value_t *value) { uc_vector_grow(&vm->stack); @@ -333,7 +378,7 @@ uc_vm_stack_push(uc_vm *vm, uc_value_t *value) } uc_value_t * -uc_vm_stack_pop(uc_vm *vm) +uc_vm_stack_pop(uc_vm_t *vm) { uc_value_t *rv; @@ -351,13 +396,13 @@ uc_vm_stack_pop(uc_vm *vm) } uc_value_t * -uc_vm_stack_peek(uc_vm *vm, size_t offset) +uc_vm_stack_peek(uc_vm_t *vm, size_t offset) { return vm->stack.entries[vm->stack.count + (-1 - offset)]; } static void -uc_vm_stack_set(uc_vm *vm, size_t offset, uc_value_t *value) +uc_vm_stack_set(uc_vm_t *vm, size_t offset, uc_value_t *value) { if (vm->trace) { fprintf(stderr, " [!%zu] %s\n", @@ -370,10 +415,10 @@ uc_vm_stack_set(uc_vm *vm, size_t offset, uc_value_t *value) } static void -uc_vm_call_native(uc_vm *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs) +uc_vm_call_native(uc_vm_t *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs) { uc_value_t *res = NULL; - uc_callframe *frame; + uc_callframe_t *frame; /* add new callframe */ uc_vector_grow(&vm->callframes); @@ -401,10 +446,10 @@ uc_vm_call_native(uc_vm *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, } static bool -uc_vm_call_function(uc_vm *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, size_t argspec) +uc_vm_call_function(uc_vm_t *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, size_t argspec) { size_t i, j, stackoff, nargs = argspec & 0xffff, nspreads = argspec >> 16; - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = NULL; uc_value_t *ellip, *arg; uc_function_t *function; uc_closure_t *closure; @@ -422,6 +467,8 @@ uc_vm_call_function(uc_vm *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, siz /* argument list contains spread operations, we need to reshuffle the stack */ if (nspreads > 0) { + frame = uc_vm_current_frame(vm); + /* create temporary array */ ellip = ucv_array_new_length(vm, nargs); @@ -535,24 +582,24 @@ uc_vm_call_function(uc_vm *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, siz return true; } -static uc_source *last_source = NULL; +static uc_source_t *last_source = NULL; static size_t last_srcpos = 0; static void -uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) +uc_dump_insn(uc_vm_t *vm, uint8_t *pos, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_chunk *chunk = uc_vm_frame_chunk(frame); + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_chunk_t *chunk = uc_vm_frame_chunk(frame); uc_stringbuf_t *buf = NULL; uc_value_t *cnst = NULL; size_t srcpos; - srcpos = ucv_function_srcpos((uc_value_t *)frame->closure->function, pos - chunk->entries); + srcpos = ucv_function_srcpos(&frame->closure->function->header, pos - chunk->entries); if (last_srcpos == 0 || last_source != frame->closure->function->source || srcpos != last_srcpos) { buf = xprintbuf_new(); - format_source_context(buf, frame->closure->function->source, srcpos, true); + uc_source_context_format(buf, frame->closure->function->source, srcpos, true); fwrite(buf->buf, 1, printbuf_length(buf), stderr); printbuf_free(buf); @@ -651,9 +698,9 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) } static uc_value_t * -uc_vm_exception_tostring(uc_vm *vm, size_t nargs) +uc_vm_exception_tostring(uc_vm_t *vm, size_t nargs) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); uc_value_t *message = ucv_object_get(frame->ctx, "message", NULL); return message ? ucv_get(message) : ucv_string_new("Exception"); @@ -662,7 +709,7 @@ uc_vm_exception_tostring(uc_vm *vm, size_t nargs) static uc_value_t *exception_prototype = NULL; static uc_value_t * -uc_vm_exception_new(uc_vm *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace) +uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace) { uc_value_t *exo; @@ -685,14 +732,17 @@ uc_vm_exception_new(uc_vm *vm, uc_exception_type_t type, const char *message, uc } static bool -uc_vm_handle_exception(uc_vm *vm) +uc_vm_handle_exception(uc_vm_t *vm) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_chunk *chunk = NULL; + uc_callframe_t *frame = NULL; + uc_chunk_t *chunk = NULL; uc_value_t *exo; size_t i, pos; - if (!frame->closure) + if (vm->callframes.count) + frame = uc_vm_current_frame(vm); + + if (!frame || !frame->closure) return false; chunk = uc_vm_frame_chunk(frame); @@ -744,11 +794,11 @@ uc_vm_handle_exception(uc_vm *vm) } static uc_value_t * -uc_vm_capture_stacktrace(uc_vm *vm, size_t i) +uc_vm_capture_stacktrace(uc_vm_t *vm, size_t i) { uc_value_t *stacktrace, *entry, *last = NULL; uc_function_t *function; - uc_callframe *frame; + uc_callframe_t *frame; size_t off, srcpos; char *name; @@ -762,7 +812,7 @@ uc_vm_capture_stacktrace(uc_vm *vm, size_t i) function = frame->closure->function; off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1; - srcpos = ucv_function_srcpos((uc_value_t *)function, off); + srcpos = ucv_function_srcpos(&function->header, off); ucv_object_add(entry, "filename", ucv_string_new(function->source->filename)); ucv_object_add(entry, "line", ucv_int64_new(uc_source_get_line(function->source, &srcpos))); @@ -785,7 +835,7 @@ uc_vm_capture_stacktrace(uc_vm *vm, size_t i) ucv_object_add(entry, "function", ucv_string_new(name)); } - if (!ucv_equal(last, entry)) { + if (!ucv_is_equal(last, entry)) { ucv_array_push(stacktrace, entry); last = entry; } @@ -798,12 +848,12 @@ uc_vm_capture_stacktrace(uc_vm *vm, size_t i) } static uc_value_t * -uc_vm_get_error_context(uc_vm *vm) +uc_vm_get_error_context(uc_vm_t *vm) { uc_value_t *stacktrace; - uc_callframe *frame; + uc_callframe_t *frame; uc_stringbuf_t *buf; - uc_chunk *chunk; + uc_chunk_t *chunk; size_t offset, i; /* skip to first non-native function call frame */ @@ -817,13 +867,13 @@ uc_vm_get_error_context(uc_vm *vm) return NULL; chunk = uc_vm_frame_chunk(frame); - offset = ucv_function_srcpos((uc_value_t *)frame->closure->function, (frame->ip - chunk->entries) - 1); + offset = ucv_function_srcpos(&frame->closure->function->header, (frame->ip - chunk->entries) - 1); stacktrace = uc_vm_capture_stacktrace(vm, i); buf = ucv_stringbuf_new(); if (offset) - format_error_context(buf, frame->closure->function->source, stacktrace, offset); + uc_error_context_format(buf, frame->closure->function->source, stacktrace, offset); else if (frame->ip != chunk->entries) ucv_stringbuf_printf(buf, "At instruction %zu", (frame->ip - chunk->entries) - 1); else @@ -835,7 +885,7 @@ uc_vm_get_error_context(uc_vm *vm) } void __attribute__((format(printf, 3, 0))) -uc_vm_raise_exception(uc_vm *vm, uc_exception_type_t type, const char *fmt, ...) +uc_vm_raise_exception(uc_vm_t *vm, uc_exception_type_t type, const char *fmt, ...) { va_list ap; @@ -853,7 +903,7 @@ uc_vm_raise_exception(uc_vm *vm, uc_exception_type_t type, const char *fmt, ...) static void -uc_vm_insn_load(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load(uc_vm_t *vm, uc_vm_insn_t insn) { switch (insn) { case I_LOAD: @@ -878,7 +928,7 @@ uc_vm_insn_load(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_load_regexp(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_regexp(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *re, *jstr = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); bool icase = false, newline = false, global = false; @@ -910,19 +960,19 @@ uc_vm_insn_load_regexp(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_load_null(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_null(uc_vm_t *vm, uc_vm_insn_t insn) { uc_vm_stack_push(vm, NULL); } static void -uc_vm_insn_load_bool(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_bool(uc_vm_t *vm, uc_vm_insn_t insn) { uc_vm_stack_push(vm, ucv_boolean_new(insn == I_LTRUE)); } static void -uc_vm_insn_load_var(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_var(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *name, *val = NULL; uc_value_t *scope, *next; @@ -958,7 +1008,7 @@ uc_vm_insn_load_var(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_val(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *k = uc_vm_stack_pop(vm); uc_value_t *v = uc_vm_stack_pop(vm); @@ -966,7 +1016,7 @@ uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn) switch (ucv_type(v)) { case UC_OBJECT: case UC_ARRAY: - uc_vm_stack_push(vm, uc_getval(vm, v, k)); + uc_vm_stack_push(vm, ucv_key_get(vm, v, k)); break; default: @@ -982,10 +1032,10 @@ uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_load_upval(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_upval(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_upval_tref_t *ref = frame->closure->upvals[vm->arg.u32]; if (ref->closed) uc_vm_stack_push(vm, ucv_get(ref->value)); @@ -994,19 +1044,19 @@ uc_vm_insn_load_upval(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_load_local(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_local(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); uc_vm_stack_push(vm, ucv_get(vm->stack.entries[frame->stackframe + vm->arg.u32])); } -static uc_upvalref_t * -uc_vm_capture_upval(uc_vm *vm, size_t slot) +static uc_upval_tref_t * +uc_vm_capture_upval(uc_vm_t *vm, size_t slot) { - uc_upvalref_t *curr = vm->open_upvals; - uc_upvalref_t *prev = NULL; - uc_upvalref_t *created; + uc_upval_tref_t *curr = vm->open_upvals; + uc_upval_tref_t *prev = NULL; + uc_upval_tref_t *created; char *s; while (curr && curr->slot > slot) { @@ -1024,7 +1074,7 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot) return curr; } - created = (uc_upvalref_t *)ucv_upvalref_new(slot); + created = (uc_upval_tref_t *)ucv_upvalref_new(slot); created->next = curr; if (vm->trace) { @@ -1042,9 +1092,9 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot) } static void -uc_vm_close_upvals(uc_vm *vm, size_t slot) +uc_vm_close_upvals(uc_vm_t *vm, size_t slot) { - uc_upvalref_t *ref; + uc_upval_tref_t *ref; while (vm->open_upvals && vm->open_upvals->slot >= slot) { ref = vm->open_upvals; @@ -1063,9 +1113,9 @@ uc_vm_close_upvals(uc_vm *vm, size_t slot) } static void -uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn) +uc_vm_insn_load_closure(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); uc_value_t *fno = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); uc_function_t *function = (uc_function_t *)fno; uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, function, insn == I_ARFN); @@ -1094,7 +1144,7 @@ uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_store_var(uc_vm *vm, enum insn_type insn) +uc_vm_insn_store_var(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *name, *v = uc_vm_stack_pop(vm); uc_value_t *scope, *next; @@ -1132,7 +1182,7 @@ uc_vm_insn_store_var(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_store_val(uc_vm *vm, enum insn_type insn) +uc_vm_insn_store_val(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *v = uc_vm_stack_pop(vm); uc_value_t *k = uc_vm_stack_pop(vm); @@ -1141,7 +1191,7 @@ uc_vm_insn_store_val(uc_vm *vm, enum insn_type insn) switch (ucv_type(o)) { case UC_OBJECT: case UC_ARRAY: - uc_vm_stack_push(vm, uc_setval(vm, o, k, v)); + uc_vm_stack_push(vm, ucv_key_set(vm, o, k, v)); break; default: @@ -1155,10 +1205,10 @@ uc_vm_insn_store_val(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_store_upval(uc_vm *vm, enum insn_type insn) +uc_vm_insn_store_upval(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_upval_tref_t *ref = frame->closure->upvals[vm->arg.u32]; uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); if (ref->closed) { @@ -1171,25 +1221,25 @@ uc_vm_insn_store_upval(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_store_local(uc_vm *vm, enum insn_type insn) +uc_vm_insn_store_local(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); uc_vm_stack_set(vm, frame->stackframe + vm->arg.u32, val); } static uc_value_t * -uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand) +uc_vm_value_bitop(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) { uc_value_t *rv = NULL; int64_t n1, n2; double d; - if (uc_cast_number(value, &n1, &d) == UC_DOUBLE) + if (ucv_cast_number(value, &n1, &d) == UC_DOUBLE) n1 = isnan(d) ? 0 : (int64_t)d; - if (uc_cast_number(operand, &n2, &d) == UC_DOUBLE) + if (ucv_cast_number(operand, &n2, &d) == UC_DOUBLE) n2 = isnan(d) ? 0 : (int64_t)d; switch (operation) { @@ -1221,7 +1271,7 @@ uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_val } static uc_value_t * -uc_vm_value_arith(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand) +uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) { uc_value_t *rv = NULL; uc_type_t t1, t2; @@ -1253,8 +1303,8 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_val return rv; } - t1 = uc_cast_number(value, &n1, &d1); - t2 = uc_cast_number(operand, &n2, &d2); + t1 = ucv_cast_number(value, &n1, &d1); + t2 = ucv_cast_number(operand, &n2, &d2); if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) { d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1; @@ -1336,7 +1386,7 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_val } static void -uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn) +uc_vm_insn_update_var(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *name, *val, *inc = uc_vm_stack_pop(vm); uc_value_t *scope, *next; @@ -1378,7 +1428,7 @@ uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn) +uc_vm_insn_update_val(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *inc = uc_vm_stack_pop(vm); uc_value_t *k = uc_vm_stack_pop(vm); @@ -1388,8 +1438,8 @@ uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn) switch (ucv_type(v)) { case UC_OBJECT: case UC_ARRAY: - val = uc_getval(vm, v, k); - uc_vm_stack_push(vm, uc_setval(vm, v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); + val = ucv_key_get(vm, v, k); + uc_vm_stack_push(vm, ucv_key_set(vm, v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); break; default: @@ -1407,11 +1457,11 @@ uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn) +uc_vm_insn_update_upval(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); size_t slot = vm->arg.u32 & 0x00FFFFFF; - uc_upvalref_t *ref = frame->closure->upvals[slot]; + uc_upval_tref_t *ref = frame->closure->upvals[slot]; uc_value_t *inc = uc_vm_stack_pop(vm); uc_value_t *val; @@ -1436,9 +1486,9 @@ uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_update_local(uc_vm *vm, enum insn_type insn) +uc_vm_insn_update_local(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); size_t slot = vm->arg.u32 & 0x00FFFFFF; uc_value_t *inc = uc_vm_stack_pop(vm); uc_value_t *val; @@ -1453,7 +1503,7 @@ uc_vm_insn_update_local(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_narr(uc_vm *vm, enum insn_type insn) +uc_vm_insn_narr(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *arr = ucv_array_new_length(vm, vm->arg.u32); @@ -1461,7 +1511,7 @@ uc_vm_insn_narr(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_parr(uc_vm *vm, enum insn_type insn) +uc_vm_insn_parr(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *arr = uc_vm_stack_peek(vm, vm->arg.u32); size_t idx; @@ -1476,7 +1526,7 @@ uc_vm_insn_parr(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_marr(uc_vm *vm, enum insn_type insn) +uc_vm_insn_marr(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *src = uc_vm_stack_pop(vm); uc_value_t *dst = uc_vm_stack_peek(vm, 0); @@ -1499,7 +1549,7 @@ uc_vm_insn_marr(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_nobj(uc_vm *vm, enum insn_type insn) +uc_vm_insn_nobj(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *obj = ucv_object_new(vm); @@ -1507,7 +1557,7 @@ uc_vm_insn_nobj(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_sobj(uc_vm *vm, enum insn_type insn) +uc_vm_insn_sobj(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *obj = uc_vm_stack_peek(vm, vm->arg.u32); uc_value_t *val; @@ -1525,7 +1575,7 @@ uc_vm_insn_sobj(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn) +uc_vm_insn_mobj(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *src = uc_vm_stack_pop(vm); uc_value_t *dst = uc_vm_stack_peek(vm, 0); @@ -1561,7 +1611,7 @@ uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_arith(uc_vm *vm, enum insn_type insn) +uc_vm_insn_arith(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r2 = uc_vm_stack_pop(vm); uc_value_t *r1 = uc_vm_stack_pop(vm); @@ -1576,7 +1626,7 @@ uc_vm_insn_arith(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_plus_minus(uc_vm *vm, enum insn_type insn) +uc_vm_insn_plus_minus(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *v = uc_vm_stack_pop(vm); bool is_sub = (insn == I_MINUS); @@ -1584,7 +1634,7 @@ uc_vm_insn_plus_minus(uc_vm *vm, enum insn_type insn) int64_t n; double d; - t = uc_cast_number(v, &n, &d); + t = ucv_cast_number(v, &n, &d); ucv_put(v); @@ -1600,7 +1650,7 @@ uc_vm_insn_plus_minus(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_bitop(uc_vm *vm, enum insn_type insn) +uc_vm_insn_bitop(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r2 = uc_vm_stack_pop(vm); uc_value_t *r1 = uc_vm_stack_pop(vm); @@ -1615,13 +1665,13 @@ uc_vm_insn_bitop(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_complement(uc_vm *vm, enum insn_type insn) +uc_vm_insn_complement(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *v = uc_vm_stack_pop(vm); int64_t n; double d; - if (uc_cast_number(v, &n, &d) == UC_DOUBLE) + if (ucv_cast_number(v, &n, &d) == UC_DOUBLE) n = isnan(d) ? 0 : (int64_t)d; ucv_put(v); @@ -1630,12 +1680,12 @@ uc_vm_insn_complement(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_rel(uc_vm *vm, enum insn_type insn) +uc_vm_insn_rel(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r2 = uc_vm_stack_pop(vm); uc_value_t *r1 = uc_vm_stack_pop(vm); - bool res = uc_cmp(insn, r1, r2); + bool res = ucv_compare(insn, r1, r2); ucv_put(r1); ucv_put(r2); @@ -1644,7 +1694,7 @@ uc_vm_insn_rel(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_in(uc_vm *vm, enum insn_type insn) +uc_vm_insn_in(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r2 = uc_vm_stack_pop(vm); uc_value_t *r1 = uc_vm_stack_pop(vm); @@ -1659,7 +1709,7 @@ uc_vm_insn_in(uc_vm *vm, enum insn_type insn) arridx < arrlen; arridx++) { item = ucv_array_get(r2, arridx); - if (uc_cmp(I_EQ, r1, item)) { + if (ucv_compare(I_EQ, r1, item)) { found = true; break; } @@ -1690,14 +1740,14 @@ uc_vm_insn_in(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_equality(uc_vm *vm, enum insn_type insn) +uc_vm_insn_equality(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r2 = uc_vm_stack_pop(vm); uc_value_t *r1 = uc_vm_stack_pop(vm); bool equal; if (ucv_is_scalar(r1) && ucv_is_scalar(r2)) - equal = ucv_equal(r1, r2); + equal = ucv_is_equal(r1, r2); else equal = (r1 == r2); @@ -1708,19 +1758,19 @@ uc_vm_insn_equality(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_not(uc_vm *vm, enum insn_type insn) +uc_vm_insn_not(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *r1 = uc_vm_stack_pop(vm); - uc_vm_stack_push(vm, ucv_boolean_new(!uc_val_is_truish(r1))); + uc_vm_stack_push(vm, ucv_boolean_new(!ucv_is_truish(r1))); ucv_put(r1); } static void -uc_vm_insn_jmp(uc_vm *vm, enum insn_type insn) +uc_vm_insn_jmp(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_chunk *chunk = uc_vm_frame_chunk(frame); + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_chunk_t *chunk = uc_vm_frame_chunk(frame); int32_t addr = vm->arg.s32; /* ip already has been incremented */ @@ -1736,10 +1786,10 @@ uc_vm_insn_jmp(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn) +uc_vm_insn_jmpz(uc_vm_t *vm, uc_vm_insn_t insn) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_chunk *chunk = uc_vm_frame_chunk(frame); + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_chunk_t *chunk = uc_vm_frame_chunk(frame); uc_value_t *v = uc_vm_stack_pop(vm); int32_t addr = vm->arg.s32; @@ -1752,14 +1802,14 @@ uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn) return; } - if (!uc_val_is_truish(v)) + if (!ucv_is_truish(v)) frame->ip += addr; ucv_put(v); } static void -uc_vm_insn_next(uc_vm *vm, enum insn_type insn) +uc_vm_insn_next(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *k = uc_vm_stack_pop(vm); uc_value_t *v = uc_vm_stack_pop(vm); @@ -1832,14 +1882,14 @@ uc_vm_insn_next(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_close_upval(uc_vm *vm, enum insn_type insn) +uc_vm_insn_close_upval(uc_vm_t *vm, uc_vm_insn_t insn) { uc_vm_close_upvals(vm, vm->stack.count - 1); ucv_put(uc_vm_stack_pop(vm)); } static void -uc_vm_insn_call(uc_vm *vm, enum insn_type insn) +uc_vm_insn_call(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff)); uc_value_t *ctx = NULL; @@ -1853,12 +1903,12 @@ uc_vm_insn_call(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_mcall(uc_vm *vm, enum insn_type insn) +uc_vm_insn_mcall(uc_vm_t *vm, uc_vm_insn_t insn) { size_t key_slot = vm->stack.count - (vm->arg.u32 & 0xffff) - 1; uc_value_t *ctx = vm->stack.entries[key_slot - 1]; uc_value_t *key = vm->stack.entries[key_slot]; - uc_value_t *fno = uc_getval(vm, ctx, key); + uc_value_t *fno = ucv_key_get(vm, ctx, key); uc_vm_stack_set(vm, key_slot, fno); @@ -1870,7 +1920,7 @@ uc_vm_insn_mcall(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_print(uc_vm *vm, enum insn_type insn) +uc_vm_insn_print(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *v = uc_vm_stack_pop(vm); char *p; @@ -1900,7 +1950,7 @@ uc_vm_insn_print(uc_vm *vm, enum insn_type insn) } static void -uc_vm_insn_delete(uc_vm *vm, enum insn_type insn) +uc_vm_insn_delete(uc_vm_t *vm, uc_vm_insn_t insn) { uc_value_t *k = uc_vm_stack_pop(vm); uc_value_t *v = uc_vm_stack_pop(vm); @@ -1908,7 +1958,7 @@ uc_vm_insn_delete(uc_vm *vm, enum insn_type insn) switch (ucv_type(v)) { case UC_OBJECT: - rv = uc_delval(vm, v, k); + rv = ucv_key_delete(vm, v, k); uc_vm_stack_push(vm, ucv_boolean_new(rv)); break; @@ -1925,9 +1975,9 @@ uc_vm_insn_delete(uc_vm *vm, enum insn_type insn) } static uc_value_t * -uc_vm_callframe_pop(uc_vm *vm) +uc_vm_callframe_pop(uc_vm_t *vm) { - uc_callframe *frame = uc_vm_current_frame(vm); + uc_callframe_t *frame = uc_vm_current_frame(vm); uc_value_t *retval; /* close upvalues */ @@ -1947,8 +1997,11 @@ uc_vm_callframe_pop(uc_vm *vm) ucv_put(uc_vm_stack_pop(vm)); /* release function */ - ucv_put((uc_value_t *)frame->closure); - ucv_put((uc_value_t *)frame->cfunction); + if (frame->closure) + ucv_put(&frame->closure->header); + + if (frame->cfunction) + ucv_put(&frame->cfunction->header); /* release context */ ucv_put(frame->ctx); @@ -1959,29 +2012,32 @@ uc_vm_callframe_pop(uc_vm *vm) } static void -uc_vm_output_exception(uc_vm *vm) +uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex) { uc_value_t *ctx; - if (vm->exception.type == EXCEPTION_USER) - fprintf(stderr, "%s\n", vm->exception.message); + if (ex->type == EXCEPTION_USER) + fprintf(stderr, "%s\n", ex->message); else fprintf(stderr, "%s: %s\n", - exception_type_strings[vm->exception.type] ? exception_type_strings[vm->exception.type] : "Error", - vm->exception.message); + exception_type_strings[ex->type] ? exception_type_strings[ex->type] : "Error", + ex->message); + + ctx = ucv_object_get(ucv_array_get(ex->stacktrace, 0), "context", NULL); - ctx = ucv_object_get(ucv_array_get(vm->exception.stacktrace, 0), "context", NULL); + if (ctx) + fprintf(stderr, "%s\n", ucv_string_get(ctx)); - fprintf(stderr, "%s\n\n", ucv_string_get(ctx)); + fprintf(stderr, "\n"); } static uc_vm_status_t -uc_vm_execute_chunk(uc_vm *vm) +uc_vm_execute_chunk(uc_vm_t *vm, uc_value_t **retvalp) { - uc_callframe *frame = uc_vm_current_frame(vm); - uc_chunk *chunk = uc_vm_frame_chunk(frame); + uc_callframe_t *frame = uc_vm_current_frame(vm); + uc_chunk_t *chunk = uc_vm_frame_chunk(frame); uc_value_t *retval; - enum insn_type insn; + uc_vm_insn_t insn; while (chunk) { if (vm->trace) @@ -2179,7 +2235,10 @@ uc_vm_execute_chunk(uc_vm *vm) retval = uc_vm_callframe_pop(vm); if (vm->callframes.count == 0) { - ucv_put(retval); + if (retvalp) + *retvalp = retval; + else + ucv_put(retval); return STATUS_OK; } @@ -2205,11 +2264,22 @@ uc_vm_execute_chunk(uc_vm *vm) /* previous instruction raised exception */ if (vm->exception.type != EXCEPTION_NONE) { + /* VM termination was requested */ + if (vm->exception.type == EXCEPTION_EXIT) { + uc_vm_reset_callframes(vm); + + if (retvalp) + *retvalp = ucv_int64_new(vm->arg.s32); + + return STATUS_EXIT; + } + /* walk up callframes until something handles the exception or the root is reached */ while (!uc_vm_handle_exception(vm)) { /* no further callframe to pop, report unhandled exception and terminate */ - if (vm->callframes.count == 1) { - uc_vm_output_exception(vm); + if (vm->callframes.count <= 1) { + if (vm->exhandler) + vm->exhandler(vm, &vm->exception); return ERROR_RUNTIME; } @@ -2231,50 +2301,12 @@ uc_vm_execute_chunk(uc_vm *vm) return STATUS_OK; } -static uc_vm_status_t -uc_vm_preload(uc_vm *vm, uc_value_t *modules) -{ - uc_value_t *requirefn, *module, *name; - uc_exception_type_t ex; - size_t i; - - if (ucv_type(modules) != UC_ARRAY) - return STATUS_OK; - - requirefn = ucv_property_get(vm->globals, "require"); - - if (ucv_type(requirefn) != UC_CFUNCTION) - return STATUS_OK; - - for (i = 0; i < ucv_array_length(modules); i++) { - name = ucv_array_get(modules, i); - - uc_vm_stack_push(vm, ucv_get(requirefn)); - uc_vm_stack_push(vm, ucv_get(name)); - - ex = uc_vm_call(vm, false, 1); - - if (ex) - return ERROR_RUNTIME; - - module = uc_vm_stack_pop(vm); - - ucv_put(uc_setval(vm, vm->globals, name, module)); - } - - return STATUS_OK; -} - uc_vm_status_t -uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *modules) +uc_vm_execute(uc_vm_t *vm, uc_function_t *fn, uc_value_t **retval) { uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, fn, false); - uc_callframe *frame; + uc_callframe_t *frame; uc_stringbuf_t *buf; - uc_vm_status_t rv; - - vm->globals = globals; - ucv_get(globals); uc_vector_grow(&vm->callframes); @@ -2287,7 +2319,7 @@ uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *mod if (vm->trace) { buf = xprintbuf_new(); - format_source_context(buf, fn->source, 0, true); + uc_source_context_format(buf, fn->source, 0, true); fwrite(buf->buf, 1, printbuf_length(buf), stderr); printbuf_free(buf); @@ -2298,29 +2330,91 @@ uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *mod //uc_vm_stack_push(vm, closure->header.jso); uc_vm_stack_push(vm, NULL); - rv = uc_vm_preload(vm, modules); - - if (rv != STATUS_OK) - uc_vm_output_exception(vm); - else - rv = uc_vm_execute_chunk(vm); + if (retval) + *retval = NULL; - ucv_put(vm->globals); - vm->globals = NULL; - - return rv; + return uc_vm_execute_chunk(vm, retval); } uc_exception_type_t -uc_vm_call(uc_vm *vm, bool mcall, size_t nargs) +uc_vm_call(uc_vm_t *vm, bool mcall, size_t nargs) { uc_value_t *ctx = mcall ? ucv_get(uc_vm_stack_peek(vm, nargs + 1)) : NULL; uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, nargs)); if (uc_vm_call_function(vm, ctx, fno, mcall, nargs & 0xffff)) { if (ucv_type(fno) != UC_CFUNCTION) - uc_vm_execute_chunk(vm); + uc_vm_execute_chunk(vm, NULL); } return vm->exception.type; } + +uc_value_t * +uc_vm_scope_get(uc_vm_t *vm) +{ + return vm->globals; +} + +void +uc_vm_scope_set(uc_vm_t *vm, uc_value_t *ctx) +{ + ucv_put(vm->globals); + vm->globals = ctx; +} + +uc_value_t * +uc_vm_invoke(uc_vm_t *vm, const char *fname, size_t nargs, ...) +{ + uc_exception_type_t ex; + uc_value_t *fno, *arg; + va_list ap; + size_t i; + + fno = ucv_property_get(vm->globals, fname); + + if (!ucv_is_callable(fno)) + return NULL; + + uc_vm_stack_push(vm, ucv_get(fno)); + + va_start(ap, nargs); + + for (i = 0; i < nargs; i++) { + arg = va_arg(ap, uc_value_t *); + uc_vm_stack_push(vm, ucv_get(arg)); + } + + va_end(ap); + + ex = uc_vm_call(vm, false, nargs); + + if (ex) + return NULL; + + return uc_vm_stack_pop(vm); +} + +uc_exception_handler_t * +uc_vm_exception_handler_get(uc_vm_t *vm) +{ + return vm->exhandler; +} + +void +uc_vm_exception_handler_set(uc_vm_t *vm, uc_exception_handler_t *exhandler) +{ + vm->exhandler = exhandler; +} + +uint32_t +uc_vm_trace_get(uc_vm_t *vm) +{ + return vm->trace; +} + +void +uc_vm_trace_set(uc_vm_t *vm, uint32_t level) +{ + vm->trace = level; +} |