summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-04-27 12:43:38 +0200
committerGitHub <noreply@github.com>2021-04-27 12:43:38 +0200
commit8469c4b1be228f42c46f08852f028f7801b93cc9 (patch)
treef61121e8f89e39787a960e621fc8492e57fc4bc0
parentf360350bd874aeec0806c8df02c7a20a54c44406 (diff)
parent64eec7f90e945696572ee076b75d1f35e8f2248a (diff)
Merge pull request #5 from jow-/new-type-system
New type system
-rw-r--r--.github/workflows/openwrt-ci.yml48
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml7
-rw-r--r--CMakeLists.txt51
-rw-r--r--chunk.c11
-rw-r--r--chunk.h34
-rw-r--r--compiler.c316
-rw-r--r--compiler.h12
-rw-r--r--lexer.c250
-rw-r--r--lexer.h11
-rw-r--r--lib.c1488
-rw-r--r--lib.h151
-rw-r--r--lib/fs.c313
-rw-r--r--lib/math.c66
-rw-r--r--lib/ubus.c127
-rw-r--r--lib/uci.c445
-rw-r--r--main.c96
-rw-r--r--module.h15
-rw-r--r--object.c493
-rw-r--r--object.h201
-rw-r--r--source.h10
-rw-r--r--tests/CMakeLists.txt6
-rw-r--r--tests/cram/CMakeLists.txt27
-rw-r--r--tests/cram/test_basic.t59
-rw-r--r--tests/custom/00_syntax/00_single_line_comments (renamed from tests/00_syntax/00_single_line_comments)0
-rw-r--r--tests/custom/00_syntax/01_unterminated_comment (renamed from tests/00_syntax/01_unterminated_comment)0
-rw-r--r--tests/custom/00_syntax/02_multi_line_comments (renamed from tests/00_syntax/02_multi_line_comments)0
-rw-r--r--tests/custom/00_syntax/03_expression_blocks (renamed from tests/00_syntax/03_expression_blocks)0
-rw-r--r--tests/custom/00_syntax/04_statement_blocks (renamed from tests/00_syntax/04_statement_blocks)0
-rw-r--r--tests/custom/00_syntax/05_block_nesting (renamed from tests/00_syntax/05_block_nesting)0
-rw-r--r--tests/custom/00_syntax/06_open_statement_block (renamed from tests/00_syntax/06_open_statement_block)0
-rw-r--r--tests/custom/00_syntax/07_embedded_single_line_comments (renamed from tests/00_syntax/07_embedded_single_line_comments)0
-rw-r--r--tests/custom/00_syntax/08_embedded_multi_line_comments (renamed from tests/00_syntax/08_embedded_multi_line_comments)0
-rw-r--r--tests/custom/00_syntax/09_string_literals (renamed from tests/00_syntax/09_string_literals)0
-rw-r--r--tests/custom/00_syntax/10_numeric_literals (renamed from tests/00_syntax/10_numeric_literals)0
-rw-r--r--tests/custom/00_syntax/11_misc_literals (renamed from tests/00_syntax/11_misc_literals)0
-rw-r--r--tests/custom/00_syntax/12_block_whitespace_control (renamed from tests/00_syntax/12_block_whitespace_control)0
-rw-r--r--tests/custom/00_syntax/13_object_literals (renamed from tests/00_syntax/13_object_literals)0
-rw-r--r--tests/custom/00_syntax/14_array_literals (renamed from tests/00_syntax/14_array_literals)0
-rw-r--r--tests/custom/00_syntax/15_function_declarations (renamed from tests/00_syntax/15_function_declarations)0
-rw-r--r--tests/custom/00_syntax/16_for_loop (renamed from tests/00_syntax/16_for_loop)0
-rw-r--r--tests/custom/00_syntax/17_while_loop (renamed from tests/00_syntax/17_while_loop)0
-rw-r--r--tests/custom/00_syntax/18_if_condition (renamed from tests/00_syntax/18_if_condition)0
-rw-r--r--tests/custom/00_syntax/19_arrow_functions (renamed from tests/00_syntax/19_arrow_functions)0
-rw-r--r--tests/custom/00_syntax/20_list_expressions (renamed from tests/00_syntax/20_list_expressions)0
-rw-r--r--tests/custom/00_syntax/21_regex_literals (renamed from tests/00_syntax/21_regex_literals)2
-rw-r--r--tests/custom/01_arithmetic/00_value_conversion (renamed from tests/01_arithmetic/00_value_conversion)0
-rw-r--r--tests/custom/01_arithmetic/01_division (renamed from tests/01_arithmetic/01_division)0
-rw-r--r--tests/custom/01_arithmetic/02_modulo (renamed from tests/01_arithmetic/02_modulo)0
-rw-r--r--tests/custom/01_arithmetic/03_bitwise (renamed from tests/01_arithmetic/03_bitwise)0
-rw-r--r--tests/custom/01_arithmetic/04_inc_dec (renamed from tests/01_arithmetic/04_inc_dec)0
-rw-r--r--tests/custom/02_runtime/00_scoping (renamed from tests/02_runtime/00_scoping)0
-rw-r--r--tests/custom/02_runtime/01_break_continue (renamed from tests/02_runtime/01_break_continue)0
-rw-r--r--tests/custom/02_runtime/02_this (renamed from tests/02_runtime/02_this)0
-rw-r--r--tests/custom/02_runtime/03_try_catch (renamed from tests/02_runtime/03_try_catch)0
-rw-r--r--tests/custom/02_runtime/04_switch_case (renamed from tests/02_runtime/04_switch_case)0
-rw-r--r--tests/custom/02_runtime/05_closure_scope (renamed from tests/02_runtime/05_closure_scope)0
-rw-r--r--tests/custom/02_runtime/06_recursion (renamed from tests/02_runtime/06_recursion)0
-rw-r--r--tests/custom/03_bugs/01_try_catch_stack_mismatch (renamed from tests/03_bugs/01_try_catch_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/02_array_pop_use_after_free (renamed from tests/03_bugs/02_array_pop_use_after_free)0
-rw-r--r--tests/custom/03_bugs/03_switch_fallthrough_miscompilation (renamed from tests/03_bugs/03_switch_fallthrough_miscompilation)0
-rw-r--r--tests/custom/03_bugs/04_property_set_abort (renamed from tests/03_bugs/04_property_set_abort)0
-rw-r--r--tests/custom/03_bugs/05_duplicate_ressource_type (renamed from tests/03_bugs/05_duplicate_ressource_type)0
-rw-r--r--tests/custom/03_bugs/06_lexer_escape_at_boundary (renamed from tests/03_bugs/06_lexer_escape_at_boundary)0
-rw-r--r--tests/custom/03_bugs/07_lexer_overlong_lines (renamed from tests/03_bugs/07_lexer_overlong_lines)0
-rw-r--r--tests/custom/03_bugs/08_compiler_arrow_fn_expressions (renamed from tests/03_bugs/08_compiler_arrow_fn_expressions)0
-rw-r--r--tests/custom/03_bugs/09_reject_invalid_array_indexes (renamed from tests/03_bugs/09_reject_invalid_array_indexes)0
-rw-r--r--tests/custom/03_bugs/10_break_stack_mismatch (renamed from tests/03_bugs/10_break_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/11_switch_stack_mismatch (renamed from tests/03_bugs/11_switch_stack_mismatch)0
-rw-r--r--tests/custom/03_bugs/12_altblock_stack_mismatch (renamed from tests/03_bugs/12_altblock_stack_mismatch)0
-rw-r--r--tests/custom/CMakeLists.txt22
-rwxr-xr-xtests/custom/run_tests.sh (renamed from run_tests.sh)13
-rw-r--r--tests/fuzz/CMakeLists.txt16
-rw-r--r--tests/fuzz/corpus/.keep0
-rw-r--r--tests/fuzz/test-fuzz.c9
-rw-r--r--types.c1809
-rw-r--r--types.h428
-rw-r--r--util.h13
-rw-r--r--value.c355
-rw-r--r--value.h40
-rw-r--r--vm.c1056
-rw-r--r--vm.h58
82 files changed, 4794 insertions, 3265 deletions
diff --git a/.github/workflows/openwrt-ci.yml b/.github/workflows/openwrt-ci.yml
new file mode 100644
index 0000000..08a9ccb
--- /dev/null
+++ b/.github/workflows/openwrt-ci.yml
@@ -0,0 +1,48 @@
+name: OpenWrt CI testing
+
+on: [ push, pull_request ]
+env:
+ CI_ENABLE_UNIT_TESTING: 1
+ CI_TARGET_BUILD_DEPENDS: ubus uci
+
+jobs:
+ native_testing:
+ name: Various native checks
+ runs-on: ubuntu-20.04
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: ynezz/gh-actions-openwrt-ci-native@v0.0.1
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v2
+ if: failure()
+ with:
+ name: native-build-artifacts
+ if-no-files-found: ignore
+ path: |
+ build/scan
+ tests/cram/**/*.t.err
+
+ sdk_build:
+ name: Build with OpenWrt ${{ matrix.sdk_platform }} SDK (out of tree)
+ runs-on: ubuntu-20.04
+
+ strategy:
+ fail-fast: false
+ matrix:
+ sdk_platform:
+ - ath79-generic
+ - imx6-generic
+ - malta-be
+ - mvebu-cortexa53
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Out of tree build with OpenWrt ${{ matrix.sdk_platform }} SDK
+ uses: ynezz/gh-actions-openwrt-ci-sdk@v0.0.1
+ env:
+ CI_TARGET_SDK_RELEASE: master
+ CI_TARGET_SDK_IMAGE: ${{ matrix.sdk_platform }}
diff --git a/.gitignore b/.gitignore
index cb1f574..e111836 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ parser.out
contrib/lemon
utpl
lib/*.so
+tests/cram/*.t.err
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..5ec04e4
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,7 @@
+variables:
+ CI_ENABLE_UNIT_TESTING: 1
+ CI_TARGET_BUILD_DEPENDS: ubus uci
+
+include:
+ - remote: https://gitlab.com/ynezz/openwrt-ci/raw/master/openwrt-ci/gitlab/main.yml
+ - remote: https://gitlab.com/ynezz/openwrt-ci/raw/master/openwrt-ci/gitlab/pipeline.yml
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2046392..0d5fe54 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,15 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 3.17)
include(CheckFunctionExists)
include(CheckSymbolExists)
PROJECT(ucode C)
-ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations -Wno-error=unused-variable -ffunction-sections -D_GNU_SOURCE)
+ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -ffunction-sections -D_GNU_SOURCE)
+
+IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
+ ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
+ ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral)
+ENDIF()
+ADD_DEFINITIONS(-Wmissing-declarations -Wno-error=unused-variable -Wno-unused-parameter)
OPTION(FS_SUPPORT "Filesystem plugin support" ON)
OPTION(MATH_SUPPORT "Math plugin support" ON)
@@ -17,7 +23,7 @@ IF(NOT APPLE)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,--gc-sections")
ENDIF()
-find_library(json NAMES json-c json)
+FIND_LIBRARY(json NAMES json-c json)
IF(DEBUG)
ADD_DEFINITIONS(-DDEBUG -g3 -O0)
@@ -32,7 +38,9 @@ IF(JSONC_FOUND)
INCLUDE_DIRECTORIES(${JSONC_INCLUDE_DIRS})
ENDIF()
-ADD_EXECUTABLE(ucode main.c lexer.c lib.c vm.c chunk.c value.c object.c compiler.c source.c)
+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})
CHECK_FUNCTION_EXISTS(dlopen DLOPEN_FUNCTION_EXISTS)
@@ -57,13 +65,13 @@ SET(LIBRARIES "")
IF(FS_SUPPORT)
SET(LIBRARIES ${LIBRARIES} fs_lib)
ADD_LIBRARY(fs_lib MODULE lib/fs.c)
- SET_TARGET_PROPERTIES(fs_lib PROPERTIES OUTPUT_NAME lib/fs PREFIX "")
+ SET_TARGET_PROPERTIES(fs_lib PROPERTIES OUTPUT_NAME fs PREFIX "")
ENDIF()
IF(MATH_SUPPORT)
SET(LIBRARIES ${LIBRARIES} math_lib)
ADD_LIBRARY(math_lib MODULE lib/math.c)
- SET_TARGET_PROPERTIES(math_lib PROPERTIES OUTPUT_NAME lib/math PREFIX "")
+ SET_TARGET_PROPERTIES(math_lib PROPERTIES OUTPUT_NAME math PREFIX "")
CHECK_FUNCTION_EXISTS(ceil CEIL_FUNCTION_EXISTS)
IF (NOT CEIL_FUNCTION_EXISTS)
TARGET_LINK_LIBRARIES(math_lib m)
@@ -71,17 +79,40 @@ IF(MATH_SUPPORT)
ENDIF()
IF(UBUS_SUPPORT)
+ FIND_LIBRARY(ubus NAMES ubus)
+ FIND_LIBRARY(blobmsg_json NAMES blobmsg_json)
+ FIND_PATH(ubus_include_dir NAMES libubus.h)
+ INCLUDE_DIRECTORIES(${ubus_include_dir})
SET(LIBRARIES ${LIBRARIES} ubus_lib)
ADD_LIBRARY(ubus_lib MODULE lib/ubus.c)
- SET_TARGET_PROPERTIES(ubus_lib PROPERTIES OUTPUT_NAME lib/ubus PREFIX "")
- TARGET_LINK_LIBRARIES(ubus_lib ubus blobmsg_json)
+ SET_TARGET_PROPERTIES(ubus_lib PROPERTIES OUTPUT_NAME ubus PREFIX "")
+ TARGET_LINK_LIBRARIES(ubus_lib ${ubus} ${blobmsg_json})
ENDIF()
IF(UCI_SUPPORT)
+ FIND_LIBRARY(uci NAMES uci)
+ FIND_LIBRARY(ubox NAMES ubox)
+ FIND_PATH(uci_include_dir uci.h)
+ INCLUDE_DIRECTORIES(${uci_include_dir})
SET(LIBRARIES ${LIBRARIES} uci_lib)
ADD_LIBRARY(uci_lib MODULE lib/uci.c)
- SET_TARGET_PROPERTIES(uci_lib PROPERTIES OUTPUT_NAME lib/uci PREFIX "")
- TARGET_LINK_LIBRARIES(uci_lib uci)
+ SET_TARGET_PROPERTIES(uci_lib PROPERTIES OUTPUT_NAME uci PREFIX "")
+ TARGET_LINK_LIBRARIES(uci_lib ${uci} ${ubox})
+ENDIF()
+
+IF(UNIT_TESTING)
+ ENABLE_TESTING()
+ ADD_DEFINITIONS(-DUNIT_TESTING)
+ ADD_SUBDIRECTORY(tests)
+ LIST(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
+
+ IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_EXECUTABLE(ucode-san ${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)
+ TARGET_LINK_OPTIONS(ucode-san PRIVATE -fsanitize=undefined,address,leak)
+ ENDIF()
ENDIF()
INSTALL(TARGETS ucode RUNTIME DESTINATION bin)
diff --git a/chunk.c b/chunk.c
index 66c24af..7d3e498 100644
--- a/chunk.c
+++ b/chunk.c
@@ -17,6 +17,7 @@
#include <assert.h>
#include "chunk.h"
+#include "types.h"
#include "util.h"
#define OFFSETINFO_BITS (sizeof(((uc_offsetinfo *)NULL)->entries[0]) * 8)
@@ -135,14 +136,14 @@ uc_chunk_pop(uc_chunk *chunk)
}
}
-struct json_object *
+uc_value_t *
uc_chunk_get_constant(uc_chunk *chunk, size_t idx)
{
return uc_vallist_get(&chunk->constants, idx);
}
ssize_t
-uc_chunk_add_constant(uc_chunk *chunk, struct json_object *val)
+uc_chunk_add_constant(uc_chunk *chunk, uc_value_t *val)
{
return uc_vallist_add(&chunk->constants, val);
}
@@ -165,7 +166,7 @@ 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, json_object *name)
+uc_chunk_debug_add_variable(uc_chunk *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;
@@ -185,12 +186,12 @@ uc_chunk_debug_add_variable(uc_chunk *chunk, size_t from, size_t to, size_t slot
variables->count++;
}
-json_object *
+uc_value_t *
uc_chunk_debug_get_variable(uc_chunk *chunk, size_t off, size_t slot, bool upval)
{
uc_variables *variables = &chunk->debuginfo.variables;
uc_value_list *varnames = &chunk->debuginfo.varnames;
- json_object *name = NULL;
+ uc_value_t *name = NULL;
size_t i;
assert(slot <= ((size_t)-1 / 2));
diff --git a/chunk.h b/chunk.h
index a3eed0e..2a8fa3a 100644
--- a/chunk.h
+++ b/chunk.h
@@ -22,42 +22,18 @@
#include "value.h"
#include "util.h"
-
-
-typedef struct {
- size_t from, to, target, slot;
-} uc_ehrange;
-
-typedef struct {
- size_t from, to, slot, nameidx;
-} uc_varrange;
-
-uc_declare_vector(uc_ehranges, uc_ehrange);
-uc_declare_vector(uc_variables, uc_varrange);
-uc_declare_vector(uc_offsetinfo, uint8_t);
-
-typedef struct {
- size_t count;
- uint8_t *entries;
- uc_value_list constants;
- uc_ehranges ehranges;
- struct {
- uc_variables variables;
- uc_value_list varnames;
- uc_offsetinfo offsets;
- } debuginfo;
-} uc_chunk;
+#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);
-ssize_t uc_chunk_add_constant(uc_chunk *chunk, struct json_object *value);
-struct json_object *uc_chunk_get_constant(uc_chunk *chunk, size_t idx);
+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);
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, json_object *name);
-json_object *uc_chunk_debug_get_variable(uc_chunk *chunk, size_t off, size_t slot, bool upval);
+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);
#endif /* __CHUNK_H_ */
diff --git a/compiler.c b/compiler.c
index 7c0a2a1..fd5b3af 100644
--- a/compiler.c
+++ b/compiler.c
@@ -88,7 +88,7 @@ uc_compiler_parse_rules[TK_ERROR + 1] = {
};
static ssize_t
-uc_compiler_declare_local(uc_compiler *compiler, json_object *name);
+uc_compiler_declare_local(uc_compiler *compiler, uc_value_t *name);
static ssize_t
uc_compiler_initialize_local(uc_compiler *compiler);
@@ -96,11 +96,11 @@ uc_compiler_initialize_local(uc_compiler *compiler);
static void
uc_compiler_init(uc_compiler *compiler, const char *name, size_t srcpos, uc_source *source)
{
- json_object *varname = xjs_new_string("(callee)");
+ uc_value_t *varname = ucv_string_new("(callee)");
compiler->scope_depth = 0;
- compiler->function = uc_function_new(name, srcpos, source);
+ compiler->function = ucv_function_new(name, srcpos, source);
compiler->locals.count = 0;
compiler->locals.entries = NULL;
@@ -117,69 +117,65 @@ uc_compiler_init(uc_compiler *compiler, const char *name, size_t srcpos, uc_sour
/* reserve stack slot 0 */
uc_compiler_declare_local(compiler, varname);
uc_compiler_initialize_local(compiler);
- uc_value_put(varname);
+ ucv_put(varname);
}
static uc_chunk *
uc_compiler_current_chunk(uc_compiler *compiler)
{
- return &compiler->function->chunk;
+ uc_function_t *fn = (uc_function_t *)compiler->function;
+
+ return &fn->chunk;
+}
+
+static uc_source *
+uc_compiler_current_source(uc_compiler *compiler)
+{
+ uc_function_t *fn = (uc_function_t *)compiler->function;
+
+ return fn->source;
}
__attribute__((format(printf, 3, 0))) static void
uc_compiler_syntax_error(uc_compiler *compiler, size_t off, const char *fmt, ...)
{
+ uc_stringbuf_t *buf = compiler->parser->error;
size_t line = 0, byte = 0, len = 0;
- char *context = NULL;
- char *s, *tmp;
va_list ap;
+ char *s;
if (compiler->parser->synchronizing)
return;
compiler->parser->synchronizing = true;
+ if (!buf)
+ buf = compiler->parser->error = xprintbuf_new();
+
if (!off)
- off = uc_function_get_srcpos(compiler->function,
+ off = ucv_function_srcpos(compiler->function,
uc_compiler_current_chunk(compiler)->count);
if (off) {
byte = off;
- line = uc_source_get_line(compiler->function->source, &byte);
-
- format_error_context(&context, &len, compiler->function->source, NULL, off);
+ line = uc_source_get_line(uc_compiler_current_source(compiler), &byte);
}
va_start(ap, fmt);
- xvasprintf(&s, fmt, ap);
+ len = xvasprintf(&s, fmt, ap);
va_end(ap);
- xasprintf(&tmp, "Syntax error: %s\n", s);
- free(s);
- s = tmp;
+ ucv_stringbuf_append(buf, "Syntax error: ");
+ ucv_stringbuf_addstr(buf, s, len);
+ ucv_stringbuf_append(buf, "\n");
- if (line) {
- xasprintf(&tmp, "%sIn line %zu, byte %zu:\n", s, line, byte);
- free(s);
- s = tmp;
- }
+ free(s);
- if (context) {
- xasprintf(&tmp, "%s%s\n\n", s, context);
- free(context);
- free(s);
- s = tmp;
- }
+ if (line)
+ ucv_stringbuf_printf(buf, "In line %zu, byte %zu:\n", line, byte);
- if (compiler->parser->error) {
- xasprintf(&tmp, "%s%s", compiler->parser->error, s);
- free(compiler->parser->error);
- free(s);
- compiler->parser->error = tmp;
- }
- else {
- compiler->parser->error = s;
- }
+ if (format_error_context(buf, uc_compiler_current_source(compiler), NULL, off))
+ ucv_stringbuf_append(buf, "\n\n");
}
static size_t
@@ -201,7 +197,7 @@ uc_compiler_parse_advance(uc_compiler *compiler)
{
bool no_regexp;
- uc_value_put(compiler->parser->prev.val);
+ ucv_put(compiler->parser->prev.uv);
compiler->parser->prev = compiler->parser->curr;
while (true) {
@@ -262,10 +258,10 @@ uc_compiler_parse_advance(uc_compiler *compiler)
break;
uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "%s",
- json_object_get_string(compiler->parser->curr.val));
+ ucv_string_get(compiler->parser->curr.uv));
- uc_value_put(compiler->parser->curr.val);
- compiler->parser->curr.val = NULL;
+ ucv_put(compiler->parser->curr.uv);
+ compiler->parser->curr.uv = NULL;
}
}
@@ -472,7 +468,12 @@ uc_compiler_emit_s32(uc_compiler *compiler, size_t srcpos, int32_t n)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
- uint32_t v = n + 0x7fffffff;
+ uint32_t v;
+
+ if (n <= 0)
+ v = n + 0x7fffffff;
+ else
+ v = (uint32_t)n + 0x7fffffff;
uc_chunk_add(chunk, v / 0x1000000, lineoff);
uc_chunk_add(chunk, (v / 0x10000) % 0x100, 0);
@@ -505,7 +506,7 @@ 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, json_object *val)
+uc_compiler_emit_constant(uc_compiler *compiler, size_t srcpos, uc_value_t *val)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t cidx = uc_chunk_add_constant(chunk, val);
@@ -517,7 +518,7 @@ uc_compiler_emit_constant(uc_compiler *compiler, size_t srcpos, json_object *val
}
static size_t
-uc_compiler_emit_regexp(uc_compiler *compiler, size_t srcpos, json_object *val)
+uc_compiler_emit_regexp(uc_compiler *compiler, size_t srcpos, uc_value_t *val)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t cidx = uc_chunk_add_constant(chunk, val);
@@ -559,9 +560,9 @@ uc_compiler_get_jmpaddr(uc_compiler *compiler, size_t off)
assert(off + 4 < chunk->count);
return (
- chunk->entries[off + 1] * 0x1000000 +
- chunk->entries[off + 2] * 0x10000 +
- chunk->entries[off + 3] * 0x100 +
+ chunk->entries[off + 1] * 0x1000000UL +
+ chunk->entries[off + 2] * 0x10000UL +
+ chunk->entries[off + 3] * 0x100UL +
chunk->entries[off + 4]
) - 0x7fffffff;
}
@@ -581,7 +582,7 @@ uc_compiler_set_jmpaddr(uc_compiler *compiler, size_t off, uint32_t dest)
chunk->entries[off + 4] = addr % 0x100;
}
-static uc_function *
+static uc_function_t *
uc_compiler_finish(uc_compiler *compiler)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
@@ -600,7 +601,7 @@ uc_compiler_finish(uc_compiler *compiler)
false,
locals->entries[i].name);
- uc_value_put(locals->entries[i].name);
+ ucv_put(locals->entries[i].name);
}
for (i = 0; i < upvals->count; i++) {
@@ -611,19 +612,19 @@ uc_compiler_finish(uc_compiler *compiler)
true,
upvals->entries[i].name);
- uc_value_put(upvals->entries[i].name);
+ ucv_put(upvals->entries[i].name);
}
uc_vector_clear(locals);
uc_vector_clear(upvals);
if (compiler->parser->error) {
- uc_value_put(compiler->function->header.jso);
+ ucv_put(compiler->function);
return NULL;
}
- return compiler->function;
+ return (uc_function_t *)compiler->function;
}
static void
@@ -640,7 +641,7 @@ uc_compiler_leave_scope(uc_compiler *compiler)
compiler->scope_depth--;
- while (locals->count > 0 && locals->entries[locals->count - 1].depth > compiler->scope_depth) {
+ while (locals->count > 0 && locals->entries[locals->count - 1].depth > (ssize_t)compiler->scope_depth) {
locals->count--;
uc_chunk_debug_add_variable(chunk,
@@ -650,7 +651,7 @@ uc_compiler_leave_scope(uc_compiler *compiler)
false,
locals->entries[locals->count].name);
- uc_value_put(locals->entries[locals->count].name);
+ ucv_put(locals->entries[locals->count].name);
locals->entries[locals->count].name = NULL;
uc_compiler_emit_insn(compiler, 0,
@@ -659,7 +660,7 @@ uc_compiler_leave_scope(uc_compiler *compiler)
}
static ssize_t
-uc_compiler_declare_local(uc_compiler *compiler, json_object *name)
+uc_compiler_declare_local(uc_compiler *compiler, uc_value_t *name)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
uc_locals *locals = &compiler->locals;
@@ -675,15 +676,15 @@ uc_compiler_declare_local(uc_compiler *compiler, json_object *name)
return -1;
}
- str1 = json_object_get_string(name);
- len1 = json_object_get_string_len(name);
+ str1 = ucv_string_get(name);
+ len1 = ucv_string_length(name);
for (i = locals->count; i > 0; i--) {
- if (locals->entries[i - 1].depth != -1 && locals->entries[i - 1].depth < compiler->scope_depth)
+ if (locals->entries[i - 1].depth != -1 && locals->entries[i - 1].depth < (ssize_t)compiler->scope_depth)
break;
- str2 = json_object_get_string(locals->entries[i - 1].name);
- len2 = json_object_get_string_len(locals->entries[i - 1].name);
+ str2 = ucv_string_get(locals->entries[i - 1].name);
+ len2 = ucv_string_length(locals->entries[i - 1].name);
if (len1 == len2 && !strcmp(str1, str2)) {
if (compiler->parser->config &&
@@ -699,7 +700,7 @@ uc_compiler_declare_local(uc_compiler *compiler, json_object *name)
uc_vector_grow(locals);
- locals->entries[locals->count].name = uc_value_get(name);
+ locals->entries[locals->count].name = ucv_get(name);
locals->entries[locals->count].depth = -1;
locals->entries[locals->count].captured = false;
locals->entries[locals->count].from = chunk->count;
@@ -719,18 +720,18 @@ uc_compiler_initialize_local(uc_compiler *compiler)
}
static ssize_t
-uc_compiler_resolve_local(uc_compiler *compiler, json_object *name)
+uc_compiler_resolve_local(uc_compiler *compiler, uc_value_t *name)
{
uc_locals *locals = &compiler->locals;
const char *str1, *str2;
size_t i, len1, len2;
- str1 = json_object_get_string(name);
- len1 = json_object_get_string_len(name);
+ str1 = ucv_string_get(name);
+ len1 = ucv_string_length(name);
for (i = locals->count; i > 0; i--) {
- str2 = json_object_get_string(locals->entries[i - 1].name);
- len2 = json_object_get_string_len(locals->entries[i - 1].name);
+ str2 = ucv_string_get(locals->entries[i - 1].name);
+ len2 = ucv_string_length(locals->entries[i - 1].name);
if (len1 != len2 || strcmp(str1, str2))
continue;
@@ -749,9 +750,9 @@ uc_compiler_resolve_local(uc_compiler *compiler, json_object *name)
}
static ssize_t
-uc_compiler_add_upval(uc_compiler *compiler, ssize_t idx, bool local, json_object *name)
+uc_compiler_add_upval(uc_compiler *compiler, size_t idx, bool local, uc_value_t *name)
{
- uc_function *function = compiler->function;
+ uc_function_t *function = (uc_function_t *)compiler->function;
uc_upvals *upvals = &compiler->upvals;
uc_upval *uv;
size_t i;
@@ -771,7 +772,7 @@ uc_compiler_add_upval(uc_compiler *compiler, ssize_t idx, bool local, json_objec
upvals->entries[upvals->count].local = local;
upvals->entries[upvals->count].index = idx;
- upvals->entries[upvals->count].name = uc_value_get(name);
+ upvals->entries[upvals->count].name = ucv_get(name);
function->nupvals++;
@@ -779,7 +780,7 @@ uc_compiler_add_upval(uc_compiler *compiler, ssize_t idx, bool local, json_objec
}
static ssize_t
-uc_compiler_resolve_upval(uc_compiler *compiler, json_object *name)
+uc_compiler_resolve_upval(uc_compiler *compiler, uc_value_t *name)
{
ssize_t idx;
@@ -989,7 +990,7 @@ uc_compiler_compile_binary(uc_compiler *compiler, bool assignable)
}
static enum insn_type
-uc_compiler_emit_variable_rw(uc_compiler *compiler, json_object *varname, uc_tokentype_t type)
+uc_compiler_emit_variable_rw(uc_compiler *compiler, uc_value_t *varname, uc_tokentype_t type)
{
enum insn_type insn;
uint32_t sub_insn;
@@ -1050,7 +1051,7 @@ uc_compiler_compile_expression(uc_compiler *compiler)
}
static bool
-uc_compiler_compile_assignment(uc_compiler *compiler, json_object *var)
+uc_compiler_compile_assignment(uc_compiler *compiler, uc_value_t *var)
{
uc_tokentype_t type = compiler->parser->curr.type;
@@ -1066,12 +1067,12 @@ uc_compiler_compile_assignment(uc_compiler *compiler, json_object *var)
}
static bool
-uc_compiler_compile_arrowfn(uc_compiler *compiler, json_object *args, bool restarg)
+uc_compiler_compile_arrowfn(uc_compiler *compiler, uc_value_t *args, bool restarg)
{
- bool array = json_object_is_type(args, json_type_array);
- uc_compiler fncompiler = {};
+ bool array = (ucv_type(args) == UC_ARRAY);
+ uc_compiler fncompiler = { 0 };
size_t i, pos, load_off;
- uc_function *fn;
+ uc_function_t *fn;
ssize_t slot;
if (!uc_compiler_parse_match(compiler, TK_ARROW))
@@ -1080,21 +1081,22 @@ uc_compiler_compile_arrowfn(uc_compiler *compiler, json_object *args, bool resta
pos = compiler->parser->prev.pos;
uc_compiler_init(&fncompiler, NULL, compiler->parser->prev.pos,
- compiler->function->source);
+ uc_compiler_current_source(compiler));
fncompiler.parent = compiler;
fncompiler.parser = compiler->parser;
- fncompiler.function->arrow = true;
- fncompiler.function->vararg = args ? restarg : false;
- fncompiler.function->nargs = array ? json_object_array_length(args) : !!args;
+ fn = (uc_function_t *)fncompiler.function;
+ fn->arrow = true;
+ fn->vararg = args ? restarg : false;
+ fn->nargs = array ? ucv_array_length(args) : !!args;
uc_compiler_enter_scope(&fncompiler);
/* declare local variables for arguments */
- for (i = 0; i < fncompiler.function->nargs; i++) {
+ for (i = 0; i < fn->nargs; i++) {
slot = uc_compiler_declare_local(&fncompiler,
- array ? json_object_array_get_idx(args, i) : args);
+ array ? ucv_array_get(args, i) : args);
if (slot != -1)
uc_compiler_syntax_error(&fncompiler, pos,
@@ -1112,8 +1114,8 @@ uc_compiler_compile_arrowfn(uc_compiler *compiler, json_object *args, bool resta
uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
/* overwrite last pop result with return */
- if (fncompiler.function->chunk.count) {
- uc_chunk_pop(&fncompiler.function->chunk);
+ if (fn->chunk.count) {
+ uc_chunk_pop(&fn->chunk);
uc_compiler_emit_insn(&fncompiler, 0, I_RETURN);
}
}
@@ -1127,7 +1129,7 @@ uc_compiler_compile_arrowfn(uc_compiler *compiler, json_object *args, bool resta
load_off = uc_compiler_emit_u32(compiler, 0, 0);
/* encode upvalue information */
- for (i = 0; i < fncompiler.function->nupvals; i++)
+ for (i = 0; i < fn->nupvals; i++)
uc_compiler_emit_s32(compiler, 0,
fncompiler.upvals.entries[i].local
? -(fncompiler.upvals.entries[i].index + 1)
@@ -1139,13 +1141,13 @@ uc_compiler_compile_arrowfn(uc_compiler *compiler, json_object *args, bool resta
if (fn)
uc_compiler_set_u32(compiler, load_off,
uc_chunk_add_constant(uc_compiler_current_chunk(compiler),
- fn->header.jso));
+ &fn->header));
return true;
}
static uc_tokentype_t
-uc_compiler_compile_var_or_arrowfn(uc_compiler *compiler, bool assignable, json_object *name)
+uc_compiler_compile_var_or_arrowfn(uc_compiler *compiler, bool assignable, uc_value_t *name)
{
uc_tokentype_t rv;
@@ -1166,7 +1168,7 @@ uc_compiler_compile_var_or_arrowfn(uc_compiler *compiler, bool assignable, json_
static void
uc_compiler_compile_paren(uc_compiler *compiler, bool assignable)
{
- json_object *varnames = NULL, *varname;
+ uc_value_t *varnames = NULL, *varname;
bool maybe_arrowfn = false;
bool restarg = false;
@@ -1175,17 +1177,17 @@ uc_compiler_compile_paren(uc_compiler *compiler, bool assignable)
while (true) {
if (uc_compiler_parse_match(compiler, TK_LABEL)) {
if (!varnames)
- varnames = xjs_new_array();
+ varnames = ucv_array_new(NULL);
- json_object_array_add(varnames, uc_value_get(compiler->parser->prev.val));
+ ucv_array_push(varnames, ucv_get(compiler->parser->prev.uv));
}
else if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
uc_compiler_parse_consume(compiler, TK_LABEL);
if (!varnames)
- varnames = xjs_new_array();
+ varnames = ucv_array_new(NULL);
- json_object_array_add(varnames, uc_value_get(compiler->parser->prev.val));
+ ucv_array_push(varnames, ucv_get(compiler->parser->prev.uv));
uc_compiler_parse_consume(compiler, TK_RPAREN);
@@ -1232,8 +1234,8 @@ uc_compiler_compile_paren(uc_compiler *compiler, bool assignable)
* consecutive labels. */
if (varnames) {
/* Get last variable name */
- varname = json_object_array_get_idx(varnames,
- json_object_array_length(varnames) - 1);
+ varname = ucv_array_get(varnames,
+ ucv_array_length(varnames) - 1);
/* If we consumed the right paren, the expression is complete and we
* only need to emit a variable read operation for the last parsed
@@ -1279,14 +1281,14 @@ uc_compiler_compile_paren(uc_compiler *compiler, bool assignable)
uc_compiler_parse_consume(compiler, TK_RPAREN);
out:
- uc_value_put(varnames);
+ ucv_put(varnames);
}
static void
uc_compiler_compile_call(uc_compiler *compiler, bool assignable)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
- uc_jmplist spreads = {};
+ uc_jmplist spreads = { 0 };
enum insn_type type;
size_t i, nargs = 0;
@@ -1358,20 +1360,20 @@ uc_compiler_compile_constant(uc_compiler *compiler, bool assignable)
case TK_BOOL:
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos,
- json_object_get_boolean(compiler->parser->prev.val) ? I_LTRUE : I_LFALSE);
+ ucv_boolean_get(compiler->parser->prev.uv) ? I_LTRUE : I_LFALSE);
break;
case TK_DOUBLE:
case TK_STRING:
- uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.val);
+ uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
break;
case TK_REGEXP:
- uc_compiler_emit_regexp(compiler, compiler->parser->prev.pos, compiler->parser->prev.val);
+ uc_compiler_emit_regexp(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
break;
case TK_NUMBER:
- n = json_object_get_int64(compiler->parser->prev.val);
+ n = ucv_int64_get(compiler->parser->prev.uv);
if (n >= -0x7f && n <= 0x7f) {
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD8);
@@ -1386,7 +1388,7 @@ uc_compiler_compile_constant(uc_compiler *compiler, bool assignable)
uc_compiler_emit_s32(compiler, compiler->parser->prev.pos, n);
}
else {
- uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.val);
+ uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
}
break;
@@ -1406,10 +1408,10 @@ uc_compiler_compile_comma(uc_compiler *compiler, bool assignable)
static void
uc_compiler_compile_labelexpr(uc_compiler *compiler, bool assignable)
{
- json_object *label = uc_value_get(compiler->parser->prev.val);
+ uc_value_t *label = ucv_get(compiler->parser->prev.uv);
uc_compiler_compile_var_or_arrowfn(compiler, assignable, label);
- uc_value_put(label);
+ ucv_put(label);
}
static bool
@@ -1425,18 +1427,18 @@ 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 fncompiler = {};
- json_object *name = NULL;
+ uc_compiler fncompiler = { 0 };
+ uc_value_t *name = NULL;
ssize_t slot = -1, pos;
uc_tokentype_t type;
size_t i, load_off;
- uc_function *fn;
+ uc_function_t *fn;
pos = compiler->parser->prev.pos;
type = compiler->parser->prev.type;
if (uc_compiler_parse_match(compiler, TK_LABEL)) {
- name = compiler->parser->prev.val;
+ name = compiler->parser->prev.uv;
/* Named functions are syntactic sugar for local variable declaration
* with function value assignment. If a name token was encountered,
@@ -1448,11 +1450,12 @@ uc_compiler_compile_function(uc_compiler *compiler, bool assignable)
}
uc_compiler_init(&fncompiler,
- name ? json_object_get_string(name) : NULL, compiler->parser->prev.pos,
- compiler->function->source);
+ name ? ucv_string_get(name) : NULL, compiler->parser->prev.pos,
+ uc_compiler_current_source(compiler));
fncompiler.parent = compiler;
fncompiler.parser = compiler->parser;
+ fn = (uc_function_t *)fncompiler.function;
uc_compiler_parse_consume(&fncompiler, TK_LPAREN);
@@ -1464,15 +1467,15 @@ uc_compiler_compile_function(uc_compiler *compiler, bool assignable)
break;
if (uc_compiler_parse_match(&fncompiler, TK_ELLIP))
- fncompiler.function->vararg = true;
+ fn->vararg = true;
if (uc_compiler_parse_match(&fncompiler, TK_LABEL)) {
- fncompiler.function->nargs++;
+ fn->nargs++;
- uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.val);
+ uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.uv);
uc_compiler_initialize_local(&fncompiler);
- if (fncompiler.function->vararg ||
+ if (fn->vararg ||
!uc_compiler_parse_match(&fncompiler, TK_COMMA))
break;
}
@@ -1505,7 +1508,7 @@ uc_compiler_compile_function(uc_compiler *compiler, bool assignable)
load_off = uc_compiler_emit_u32(compiler, 0, 0);
/* encode upvalue information */
- for (i = 0; i < fncompiler.function->nupvals; i++)
+ for (i = 0; i < fn->nupvals; i++)
uc_compiler_emit_s32(compiler, 0,
fncompiler.upvals.entries[i].local
? -(fncompiler.upvals.entries[i].index + 1)
@@ -1517,7 +1520,7 @@ uc_compiler_compile_function(uc_compiler *compiler, bool assignable)
if (fn)
uc_compiler_set_u32(compiler, load_off,
uc_chunk_add_constant(uc_compiler_current_chunk(compiler),
- fn->header.jso));
+ &fn->header));
/* if a local variable of the same name already existed, overwrite its value
* with the compiled function here */
@@ -1563,7 +1566,7 @@ uc_compiler_compile_dot(uc_compiler *compiler, bool assignable)
{
/* parse label lhs */
uc_compiler_parse_consume(compiler, TK_LABEL);
- uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.val);
+ uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
/* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */
if (!assignable || !uc_compiler_compile_assignment(compiler, NULL))
@@ -1718,7 +1721,7 @@ uc_compiler_compile_object(uc_compiler *compiler, bool assignable)
/* load label */
uc_compiler_emit_constant(compiler, compiler->parser->prev.pos,
- compiler->parser->prev.val);
+ compiler->parser->prev.uv);
/* If the property name is a plain label followed by a comma or
* closing curly brace, treat it as ES2015 property shorthand
@@ -1727,7 +1730,7 @@ uc_compiler_compile_object(uc_compiler *compiler, bool assignable)
(uc_compiler_parse_check(compiler, TK_COMMA) ||
uc_compiler_parse_check(compiler, TK_RBRACE))) {
uc_compiler_emit_variable_rw(compiler,
- compiler->parser->prev.val, 0);
+ compiler->parser->prev.uv, 0);
}
/* ... otherwise treat it as ordinary `key: value` tuple */
@@ -1757,7 +1760,6 @@ uc_compiler_compile_object(uc_compiler *compiler, bool assignable)
if (len > 0) {
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
uc_compiler_emit_u32(compiler, 0, len);
- len = 0;
}
/* set initial size hint */
@@ -1766,7 +1768,7 @@ uc_compiler_compile_object(uc_compiler *compiler, bool assignable)
static void
-uc_compiler_declare_local_null(uc_compiler *compiler, size_t srcpos, json_object *varname)
+uc_compiler_declare_local_null(uc_compiler *compiler, size_t srcpos, uc_value_t *varname)
{
ssize_t existing_slot = uc_compiler_declare_local(compiler, varname);
@@ -1820,7 +1822,7 @@ uc_compiler_declare_internal(uc_compiler *compiler, size_t srcpos, const char *n
uc_vector_grow(locals);
- locals->entries[locals->count].name = xjs_new_string(name);
+ locals->entries[locals->count].name = ucv_string_new(name);
locals->entries[locals->count].depth = compiler->scope_depth;
locals->entries[locals->count].captured = false;
locals->entries[locals->count].from = chunk->count;
@@ -1839,7 +1841,7 @@ uc_compiler_compile_local(uc_compiler *compiler)
uc_compiler_parse_consume(compiler, TK_LABEL);
/* declare local variable */
- slot = uc_compiler_declare_local(compiler, compiler->parser->prev.val);
+ slot = uc_compiler_declare_local(compiler, compiler->parser->prev.uv);
/* if followed by '=', parse initializer expression */
if (uc_compiler_parse_match(compiler, TK_ASSIGN))
@@ -1894,7 +1896,7 @@ uc_compiler_compile_if(uc_compiler *compiler)
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t jmpz_off, jmp_off, i;
bool expect_endif = false;
- uc_jmplist elifs = {};
+ uc_jmplist elifs = { 0 };
uc_tokentype_t type;
/* parse & compile condition expression */
@@ -1999,7 +2001,7 @@ uc_compiler_compile_while(uc_compiler *compiler)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t cond_off, jmpz_off, end_off;
- uc_patchlist p = {};
+ uc_patchlist p = { 0 };
p.parent = compiler->patchlist;
compiler->patchlist = &p;
@@ -2047,7 +2049,7 @@ uc_compiler_compile_for_in(uc_compiler *compiler, bool local, uc_token *kvar, uc
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t skip_jmp, test_jmp, key_slot, val_slot;
- uc_patchlist p = {};
+ uc_patchlist p = { 0 };
p.parent = compiler->patchlist;
compiler->patchlist = &p;
@@ -2063,10 +2065,10 @@ uc_compiler_compile_for_in(uc_compiler *compiler, bool local, uc_token *kvar, uc
/* declare loop variables */
if (local) {
- uc_compiler_declare_local_null(compiler, kvar->pos, kvar->val);
+ uc_compiler_declare_local_null(compiler, kvar->pos, kvar->uv);
if (vvar)
- uc_compiler_declare_local_null(compiler, vvar->pos, vvar->val);
+ uc_compiler_declare_local_null(compiler, vvar->pos, vvar->uv);
}
/* value to iterate */
@@ -2110,12 +2112,12 @@ uc_compiler_compile_for_in(uc_compiler *compiler, bool local, uc_token *kvar, uc
/* set key and value variables */
if (vvar) {
- uc_compiler_emit_variable_rw(compiler, vvar->val, TK_ASSIGN);
+ uc_compiler_emit_variable_rw(compiler, vvar->uv, TK_ASSIGN);
uc_compiler_emit_insn(compiler, 0, I_POP);
}
/* set key variable */
- uc_compiler_emit_variable_rw(compiler, kvar->val, TK_ASSIGN);
+ uc_compiler_emit_variable_rw(compiler, kvar->uv, TK_ASSIGN);
uc_compiler_emit_insn(compiler, 0, I_POP);
/* compile loop body */
@@ -2157,7 +2159,7 @@ uc_compiler_compile_for_count(uc_compiler *compiler, bool local, uc_token *var)
{
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
size_t test_off = 0, incr_off, skip_off, cond_off = 0;
- uc_patchlist p = {};
+ uc_patchlist p = { 0 };
p.parent = compiler->patchlist;
compiler->patchlist = &p;
@@ -2166,14 +2168,14 @@ uc_compiler_compile_for_count(uc_compiler *compiler, bool local, uc_token *var)
/* Initializer ---------------------------------------------------------- */
- /* We parsed a `local x` or `local x, y` expression, so (re)declare
- * last label as local initializer variable */
- if (local)
- uc_compiler_declare_local_null(compiler, var->pos, var->val);
-
- /* If we parsed at least on label, try continue parsing as variable
+ /* If we parsed at least one label, try continue parsing as variable
* expression... */
if (var) {
+ /* We parsed a `local x` or `local x, y` expression, so (re)declare
+ * last label as local initializer variable */
+ if (local)
+ uc_compiler_declare_local_null(compiler, var->pos, var->uv);
+
uc_compiler_compile_labelexpr(compiler, true);
uc_compiler_emit_insn(compiler, 0, I_POP);
@@ -2257,7 +2259,7 @@ uc_compiler_compile_for_count(uc_compiler *compiler, bool local, uc_token *var)
static void
uc_compiler_compile_for(uc_compiler *compiler)
{
- uc_token keyvar = {}, valvar = {};
+ uc_token keyvar = { 0 }, valvar = { 0 };
bool local;
uc_compiler_parse_consume(compiler, TK_LPAREN);
@@ -2268,19 +2270,15 @@ uc_compiler_compile_for(uc_compiler *compiler)
local = uc_compiler_parse_match(compiler, TK_LOCAL);
- if (local && !uc_compiler_parse_check(compiler, TK_LABEL))
- uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
- "Expecting label after 'local'");
-
if (uc_compiler_parse_match(compiler, TK_LABEL)) {
keyvar = compiler->parser->prev;
- uc_value_get(keyvar.val);
+ ucv_get(keyvar.uv);
if (uc_compiler_parse_match(compiler, TK_COMMA)) {
uc_compiler_parse_consume(compiler, TK_LABEL);
valvar = compiler->parser->prev;
- uc_value_get(valvar.val);
+ ucv_get(valvar.uv);
}
/* is a for-in loop */
@@ -2291,17 +2289,23 @@ uc_compiler_compile_for(uc_compiler *compiler)
goto out;
}
}
+ else if (local) {
+ uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
+ "Expecting label after 'local'");
+
+ goto out;
+ }
/*
* The previous expression ruled out a for-in loop, so continue parsing
* as counting for loop...
*/
uc_compiler_compile_for_count(compiler, local,
- valvar.val ? &valvar : (keyvar.val ? &keyvar : NULL));
+ valvar.uv ? &valvar : (keyvar.uv ? &keyvar : NULL));
out:
- uc_value_put(keyvar.val);
- uc_value_put(valvar.val);
+ ucv_put(keyvar.uv);
+ ucv_put(valvar.uv);
}
static void
@@ -2310,8 +2314,8 @@ uc_compiler_compile_switch(uc_compiler *compiler)
size_t i, test_jmp, skip_jmp, next_jmp, value_slot, default_off = 0;
uc_chunk *chunk = uc_compiler_current_chunk(compiler);
uc_locals *locals = &compiler->locals;
- uc_jmplist cases = {};
- uc_patchlist p = {};
+ uc_jmplist cases = { 0 };
+ uc_patchlist p = { 0 };
p.parent = compiler->patchlist;
compiler->patchlist = &p;
@@ -2335,6 +2339,7 @@ uc_compiler_compile_switch(uc_compiler *compiler)
/* handle `default:` */
if (uc_compiler_parse_match(compiler, TK_DEFAULT)) {
if (default_off) {
+ uc_vector_clear(&cases);
uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
"more than one switch default case");
@@ -2521,7 +2526,7 @@ uc_compiler_compile_try(uc_compiler *compiler)
if (uc_compiler_parse_match(compiler, TK_LPAREN)) {
uc_compiler_parse_consume(compiler, TK_LABEL);
- uc_compiler_declare_local(compiler, compiler->parser->prev.val);
+ uc_compiler_declare_local(compiler, compiler->parser->prev.uv);
uc_compiler_initialize_local(compiler);
uc_compiler_parse_consume(compiler, TK_RPAREN);
@@ -2563,7 +2568,7 @@ uc_compiler_compile_control(uc_compiler *compiler)
}
/* pop locals in scope up to this point */
- for (i = locals->count; i > 0 && locals->entries[i - 1].depth == compiler->scope_depth; i--)
+ for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth == compiler->scope_depth; i--)
uc_compiler_emit_insn(compiler, 0, I_POP);
uc_vector_grow(p);
@@ -2612,7 +2617,7 @@ uc_compiler_compile_tplexp(uc_compiler *compiler)
static void
uc_compiler_compile_text(uc_compiler *compiler)
{
- uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.val);
+ uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
uc_compiler_emit_insn(compiler, 0, I_PRINT);
}
@@ -2703,12 +2708,12 @@ uc_compiler_compile_declaration(uc_compiler *compiler)
uc_compiler_parse_synchronize(compiler);
}
-uc_function *
+uc_function_t *
uc_compile(uc_parse_config *config, uc_source *source, char **errp)
{
uc_parser parser = { .config = config };
uc_compiler compiler = { .parser = &parser };
- uc_function *fn;
+ uc_function_t *fn;
uc_lexer_init(&parser.lex, config, source);
uc_compiler_init(&compiler, "main", 0, source);
@@ -2720,8 +2725,13 @@ uc_compile(uc_parse_config *config, uc_source *source, char **errp)
fn = uc_compiler_finish(&compiler);
- if (errp)
- *errp = parser.error;
+ if (errp) {
+ *errp = parser.error ? parser.error->buf : NULL;
+ free(parser.error);
+ }
+ else {
+ printbuf_free(parser.error);
+ }
uc_lexer_free(&parser.lex);
diff --git a/compiler.h b/compiler.h
index 53ff987..7b241ff 100644
--- a/compiler.h
+++ b/compiler.h
@@ -28,8 +28,8 @@
#endif
#include "source.h"
-#include "object.h"
#include "lexer.h"
+#include "types.h"
#include "util.h"
typedef enum {
@@ -72,14 +72,14 @@ struct uc_patchlist {
typedef struct uc_patchlist uc_patchlist;
typedef struct {
- json_object *name;
+ uc_value_t *name;
ssize_t depth;
size_t from;
bool captured;
} uc_local;
typedef struct {
- json_object *name;
+ uc_value_t *name;
size_t index;
bool local;
} uc_upval;
@@ -93,7 +93,7 @@ typedef struct {
uc_lexer lex;
uc_token prev, curr;
bool synchronizing;
- char *error;
+ uc_stringbuf_t *error;
} uc_parser;
struct uc_compiler {
@@ -101,7 +101,7 @@ struct uc_compiler {
uc_locals locals;
uc_upvals upvals;
uc_patchlist *patchlist;
- uc_function *function;
+ uc_value_t *function;
uc_parser *parser;
size_t scope_depth, current_srcpos, last_insn;
bool statement_emitted;
@@ -115,6 +115,6 @@ typedef struct {
uc_precedence_t precedence;
} uc_parse_rule;
-uc_function *uc_compile(uc_parse_config *config, uc_source *source, char **errp);
+uc_function_t *uc_compile(uc_parse_config *config, uc_source *source, char **errp);
#endif /* __COMPILER_H_ */
diff --git a/lexer.c b/lexer.c
index bf099f5..aaba314 100644
--- a/lexer.c
+++ b/lexer.c
@@ -32,22 +32,22 @@
#define UC_LEX_CONTINUE_PARSING (void *)1
struct keyword {
- int type;
+ unsigned type;
const char *pat;
- int plen;
+ unsigned plen;
union {
double d;
bool b;
- };
+ } u;
};
struct token {
- int type;
+ unsigned type;
union {
uint32_t patn;
char pat[4];
- };
- int plen;
+ } u;
+ unsigned plen;
uc_token *(*parse)(uc_lexer *, bool);
};
@@ -65,103 +65,103 @@ static uc_token *parse_number(uc_lexer *, bool);
static uc_token *parse_label(uc_lexer *, bool);
static const struct token tokens[] = {
- { TK_ASLEFT, { .pat = "<<=" }, 3 },
- { TK_ASRIGHT, { .pat = ">>=" }, 3 },
- { TK_LEXP, { .pat = "{{-" }, 3 },
- { TK_REXP, { .pat = "-}}" }, 3 },
- { TK_LSTM, { .pat = "{%+" }, 3 },
- { TK_LSTM, { .pat = "{%-" }, 3 },
- { TK_RSTM, { .pat = "-%}" }, 3 },
- { TK_EQS, { .pat = "===" }, 3 },
- { TK_NES, { .pat = "!==" }, 3 },
- { TK_ELLIP, { .pat = "..." }, 3 },
- { TK_AND, { .pat = "&&" }, 2 },
- { TK_ASADD, { .pat = "+=" }, 2 },
- { TK_ASBAND, { .pat = "&=" }, 2 },
- { TK_ASBOR, { .pat = "|=" }, 2 },
- { TK_ASBXOR, { .pat = "^=" }, 2 },
- //{ TK_ASDIV, { .pat = "/=" }, 2 },
- { TK_ASMOD, { .pat = "%=" }, 2 },
- { TK_ASMUL, { .pat = "*=" }, 2 },
- { TK_ASSUB, { .pat = "-=" }, 2 },
- { TK_DEC, { .pat = "--" }, 2 },
- { TK_INC, { .pat = "++" }, 2 },
- { TK_EQ, { .pat = "==" }, 2 },
- { TK_NE, { .pat = "!=" }, 2 },
- { TK_LE, { .pat = "<=" }, 2 },
- { TK_GE, { .pat = ">=" }, 2 },
- { TK_LSHIFT, { .pat = "<<" }, 2 },
- { TK_RSHIFT, { .pat = ">>" }, 2 },
+ { TK_ASLEFT, { .pat = "<<=" }, 3, NULL },
+ { TK_ASRIGHT, { .pat = ">>=" }, 3, NULL },
+ { TK_LEXP, { .pat = "{{-" }, 3, NULL },
+ { TK_REXP, { .pat = "-}}" }, 3, NULL },
+ { TK_LSTM, { .pat = "{%+" }, 3, NULL },
+ { TK_LSTM, { .pat = "{%-" }, 3, NULL },
+ { TK_RSTM, { .pat = "-%}" }, 3, NULL },
+ { TK_EQS, { .pat = "===" }, 3, NULL },
+ { TK_NES, { .pat = "!==" }, 3, NULL },
+ { TK_ELLIP, { .pat = "..." }, 3, NULL },
+ { TK_AND, { .pat = "&&" }, 2, NULL },
+ { TK_ASADD, { .pat = "+=" }, 2, NULL },
+ { TK_ASBAND, { .pat = "&=" }, 2, NULL },
+ { TK_ASBOR, { .pat = "|=" }, 2, NULL },
+ { TK_ASBXOR, { .pat = "^=" }, 2, NULL },
+ //{ TK_ASDIV, { .pat = "/=" }, 2, NULL },
+ { TK_ASMOD, { .pat = "%=" }, 2, NULL },
+ { TK_ASMUL, { .pat = "*=" }, 2, NULL },
+ { TK_ASSUB, { .pat = "-=" }, 2, NULL },
+ { TK_DEC, { .pat = "--" }, 2, NULL },
+ { TK_INC, { .pat = "++" }, 2, NULL },
+ { TK_EQ, { .pat = "==" }, 2, NULL },
+ { TK_NE, { .pat = "!=" }, 2, NULL },
+ { TK_LE, { .pat = "<=" }, 2, NULL },
+ { TK_GE, { .pat = ">=" }, 2, NULL },
+ { TK_LSHIFT, { .pat = "<<" }, 2, NULL },
+ { TK_RSHIFT, { .pat = ">>" }, 2, NULL },
{ 0, { .pat = "//" }, 2, parse_comment },
{ 0, { .pat = "/*" }, 2, parse_comment },
- { TK_OR, { .pat = "||" }, 2 },
- { TK_LEXP, { .pat = "{{" }, 2 },
- { TK_REXP, { .pat = "}}" }, 2 },
- { TK_LSTM, { .pat = "{%" }, 2 },
- { TK_RSTM, { .pat = "%}" }, 2 },
- { TK_ARROW, { .pat = "=>" }, 2 },
- { TK_ADD, { .pat = "+" }, 1 },
- { TK_ASSIGN, { .pat = "=" }, 1 },
- { TK_BAND, { .pat = "&" }, 1 },
- { TK_BOR, { .pat = "|" }, 1 },
- { TK_LBRACK, { .pat = "[" }, 1 },
- { TK_RBRACK, { .pat = "]" }, 1 },
- { TK_BXOR, { .pat = "^" }, 1 },
- { TK_LBRACE, { .pat = "{" }, 1 },
- { TK_RBRACE, { .pat = "}" }, 1 },
- { TK_COLON, { .pat = ":" }, 1 },
- { TK_COMMA, { .pat = "," }, 1 },
- { TK_COMPL, { .pat = "~" }, 1 },
- //{ TK_DIV, { .pat = "/" }, 1 },
- { TK_GT, { .pat = ">" }, 1 },
- { TK_NOT, { .pat = "!" }, 1 },
- { TK_LT, { .pat = "<" }, 1 },
- { TK_MOD, { .pat = "%" }, 1 },
- { TK_MUL, { .pat = "*" }, 1 },
- { TK_LPAREN, { .pat = "(" }, 1 },
- { TK_RPAREN, { .pat = ")" }, 1 },
- { TK_QMARK, { .pat = "?" }, 1 },
- { TK_SCOL, { .pat = ";" }, 1 },
- //{ TK_SUB, { .pat = "-" }, 1 },
- { TK_DOT, { .pat = "." }, 1 },
+ { TK_OR, { .pat = "||" }, 2, NULL },
+ { TK_LEXP, { .pat = "{{" }, 2, NULL },
+ { TK_REXP, { .pat = "}}" }, 2, NULL },
+ { TK_LSTM, { .pat = "{%" }, 2, NULL },
+ { TK_RSTM, { .pat = "%}" }, 2, NULL },
+ { TK_ARROW, { .pat = "=>" }, 2, NULL },
+ { TK_ADD, { .pat = "+" }, 1, NULL },
+ { TK_ASSIGN, { .pat = "=" }, 1, NULL },
+ { TK_BAND, { .pat = "&" }, 1, NULL },
+ { TK_BOR, { .pat = "|" }, 1, NULL },
+ { TK_LBRACK, { .pat = "[" }, 1, NULL },
+ { TK_RBRACK, { .pat = "]" }, 1, NULL },
+ { TK_BXOR, { .pat = "^" }, 1, NULL },
+ { TK_LBRACE, { .pat = "{" }, 1, NULL },
+ { TK_RBRACE, { .pat = "}" }, 1, NULL },
+ { TK_COLON, { .pat = ":" }, 1, NULL },
+ { TK_COMMA, { .pat = "," }, 1, NULL },
+ { TK_COMPL, { .pat = "~" }, 1, NULL },
+ //{ TK_DIV, { .pat = "/" }, 1, NULL },
+ { TK_GT, { .pat = ">" }, 1, NULL },
+ { TK_NOT, { .pat = "!" }, 1, NULL },
+ { TK_LT, { .pat = "<" }, 1, NULL },
+ { TK_MOD, { .pat = "%" }, 1, NULL },
+ { TK_MUL, { .pat = "*" }, 1, NULL },
+ { TK_LPAREN, { .pat = "(" }, 1, NULL },
+ { TK_RPAREN, { .pat = ")" }, 1, NULL },
+ { TK_QMARK, { .pat = "?" }, 1, NULL },
+ { TK_SCOL, { .pat = ";" }, 1, NULL },
+ //{ TK_SUB, { .pat = "-" }, 1, NULL },
+ { TK_DOT, { .pat = "." }, 1, NULL },
{ TK_STRING, { .pat = "'" }, 1, parse_string },
{ TK_STRING, { .pat = "\"" }, 1, parse_string },
{ TK_REGEXP, { .pat = "/" }, 1, parse_regexp },
- { TK_LABEL, { .pat = "_" }, 1, parse_label },
- { TK_LABEL, { .pat = "az" }, 0, parse_label },
- { TK_LABEL, { .pat = "AZ" }, 0, parse_label },
+ { TK_LABEL, { .pat = "_" }, 1, parse_label },
+ { TK_LABEL, { .pat = "az" }, 0, parse_label },
+ { TK_LABEL, { .pat = "AZ" }, 0, parse_label },
{ TK_NUMBER, { .pat = "-" }, 1, parse_number },
{ TK_NUMBER, { .pat = "09" }, 0, parse_number },
};
static const struct keyword reserved_words[] = {
- { TK_ENDFUNC, "endfunction", 11 },
+ { TK_ENDFUNC, "endfunction", 11, { 0 } },
{ TK_DOUBLE, "Infinity", 8, { .d = INFINITY } },
- { TK_CONTINUE, "continue", 8 },
- { TK_ENDWHILE, "endwhile", 8 },
- { TK_FUNC, "function", 8 },
- { TK_DEFAULT, "default", 7 },
- { TK_RETURN, "return", 6 },
- { TK_ENDFOR, "endfor", 6 },
- { TK_SWITCH, "switch", 6 },
- { TK_LOCAL, "local", 5 },
- { TK_ENDIF, "endif", 5 },
- { TK_WHILE, "while", 5 },
- { TK_BREAK, "break", 5 },
- { TK_CATCH, "catch", 5 },
+ { TK_CONTINUE, "continue", 8, { 0 } },
+ { TK_ENDWHILE, "endwhile", 8, { 0 } },
+ { TK_FUNC, "function", 8, { 0 } },
+ { TK_DEFAULT, "default", 7, { 0 } },
+ { TK_RETURN, "return", 6, { 0 } },
+ { TK_ENDFOR, "endfor", 6, { 0 } },
+ { TK_SWITCH, "switch", 6, { 0 } },
+ { TK_LOCAL, "local", 5, { 0 } },
+ { TK_ENDIF, "endif", 5, { 0 } },
+ { TK_WHILE, "while", 5, { 0 } },
+ { TK_BREAK, "break", 5, { 0 } },
+ { TK_CATCH, "catch", 5, { 0 } },
{ TK_BOOL, "false", 5, { .b = false } },
{ TK_BOOL, "true", 4, { .b = true } },
- { TK_ELIF, "elif", 4 },
- { TK_ELSE, "else", 4 },
- { TK_THIS, "this", 4 },
- { TK_NULL, "null", 4 },
- { TK_CASE, "case", 4 },
+ { TK_ELIF, "elif", 4, { 0 } },
+ { TK_ELSE, "else", 4, { 0 } },
+ { TK_THIS, "this", 4, { 0 } },
+ { TK_NULL, "null", 4, { 0 } },
+ { TK_CASE, "case", 4, { 0 } },
{ TK_DOUBLE, "NaN", 3, { .d = NAN } },
- { TK_TRY, "try", 3 },
- { TK_FOR, "for", 3 },
- { TK_LOCAL, "let", 3 },
- { TK_IF, "if", 2 },
- { TK_IN, "in", 2 },
+ { TK_TRY, "try", 3, { 0 } },
+ { TK_FOR, "for", 3, { 0 } },
+ { TK_LOCAL, "let", 3, { 0 } },
+ { TK_IF, "if", 2, { 0 } },
+ { TK_IN, "in", 2, { 0 } },
};
@@ -223,10 +223,10 @@ utf8enc(char **out, int *rem, int code)
#define UT_LEX_MAX_TOKEN_LEN 3
static uc_token *
-emit_op(uc_lexer *lex, uint32_t pos, int type, struct json_object *val)
+emit_op(uc_lexer *lex, uint32_t pos, int type, uc_value_t *uv)
{
lex->curr.type = type;
- lex->curr.val = val;
+ lex->curr.uv = uv;
lex->curr.pos = pos;
return &lex->curr;
@@ -257,7 +257,7 @@ lookbehind_to_text(uc_lexer *lex, uint32_t pos, int type, const char *strip_trai
lex->lookbehindlen--;
}
- rv = emit_op(lex, pos, type, xjs_new_string_len(lex->lookbehind, lex->lookbehindlen));
+ rv = emit_op(lex, pos, type, ucv_string_new_length(lex->lookbehind, lex->lookbehindlen));
lookbehind_reset(lex);
}
@@ -360,9 +360,9 @@ parse_comment(uc_lexer *lex, bool no_regexp)
size_t elen;
if (!buf_remaining(lex))
- return emit_op(lex, lex->lastoff, TK_ERROR, xjs_new_string("Unterminated comment"));
+ return emit_op(lex, lex->lastoff, TK_ERROR, ucv_string_new("Unterminated comment"));
- if (!strcmp(tok->pat, "//")) {
+ if (!strcmp(tok->u.pat, "//")) {
end = "\n";
elen = 1;
}
@@ -400,13 +400,13 @@ static uc_token *
parse_string(uc_lexer *lex, bool no_regexp)
{
const struct token *tok = lex->tok;
- char q = tok->pat[0];
+ char q = tok->u.pat[0];
char *ptr, *c;
uc_token *rv;
int code;
if (!buf_remaining(lex))
- return emit_op(lex, lex->lastoff, TK_ERROR, xjs_new_string("Unterminated string"));
+ return emit_op(lex, lex->lastoff, TK_ERROR, ucv_string_new("Unterminated string"));
for (ptr = lex->bufstart; ptr < lex->bufend; ptr++) {
/* continuation of escape sequence */
@@ -438,7 +438,7 @@ parse_string(uc_lexer *lex, bool no_regexp)
default:
lex->is_escape = false;
- c = strchr("a\ab\be\ef\fn\nr\rt\tv\v", *ptr);
+ c = strchr("a\ab\be\033f\fn\nr\rt\tv\v", *ptr);
if (c && *c >= 'a') {
lookbehind_append(lex, c + 1, 1);
@@ -461,7 +461,7 @@ parse_string(uc_lexer *lex, bool no_regexp)
case 'u':
if (lex->esclen < 5) {
if (!isxdigit(*ptr))
- return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, xjs_new_string("Invalid escape sequence"));
+ return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, ucv_string_new("Invalid escape sequence"));
lex->esc[lex->esclen++] = *ptr;
}
@@ -513,7 +513,7 @@ parse_string(uc_lexer *lex, bool no_regexp)
case 'x':
if (lex->esclen < 3) {
if (!isxdigit(*ptr))
- return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, xjs_new_string("Invalid escape sequence"));
+ return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, ucv_string_new("Invalid escape sequence"));
lex->esc[lex->esclen++] = *ptr;
}
@@ -564,7 +564,7 @@ parse_string(uc_lexer *lex, bool no_regexp)
dec(lex->esc[3]);
if (code > 255)
- return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, xjs_new_string("Invalid escape sequence"));
+ return emit_op(lex, lex->source->off + lex->esclen + 1, TK_ERROR, ucv_string_new("Invalid escape sequence"));
append_utf8(lex, code);
@@ -585,7 +585,7 @@ parse_string(uc_lexer *lex, bool no_regexp)
rv = lookbehind_to_text(lex, lex->lastoff, TK_STRING, NULL);
if (!rv)
- rv = emit_op(lex, lex->lastoff, TK_STRING, xjs_new_string_len("", 0));
+ rv = emit_op(lex, lex->lastoff, TK_STRING, ucv_string_new_length("", 0));
return rv;
}
@@ -685,10 +685,11 @@ parse_regexp(uc_lexer *lex, bool no_regexp)
len = xasprintf(&s, "%c%*s",
(is_reg_global << 0) | (is_reg_icase << 1) | (is_reg_newline << 2),
- json_object_get_string_len(rv->val),
- json_object_get_string(rv->val));
+ ucv_string_length(rv->uv),
+ ucv_string_get(rv->uv));
- json_object_set_string_len(rv->val, s, len);
+ ucv_free(rv->uv, false);
+ rv->uv = ucv_string_new_length(s, len);
free(s);
rv->type = TK_REGEXP;
@@ -724,20 +725,20 @@ parse_label(uc_lexer *lex, bool no_regexp)
size_t i;
if (!lex->lookbehind && tok->plen)
- lookbehind_append(lex, tok->pat, tok->plen);
+ lookbehind_append(lex, tok->u.pat, tok->plen);
if (!buf_remaining(lex) || (lex->bufstart[0] != '_' && !isalnum(lex->bufstart[0]))) {
for (i = 0, word = &reserved_words[0]; i < ARRAY_SIZE(reserved_words); i++, word = &reserved_words[i]) {
- if (lex->lookbehindlen == word->plen && !strncmp(lex->lookbehind, word->pat, word->plen)) {
+ if (lex->lookbehind && lex->lookbehindlen == word->plen && !strncmp(lex->lookbehind, word->pat, word->plen)) {
lookbehind_reset(lex);
switch (word->type) {
case TK_DOUBLE:
- rv = emit_op(lex, lex->source->off - word->plen, word->type, uc_double_new(word->d));
+ rv = emit_op(lex, lex->source->off - word->plen, word->type, ucv_double_new(word->u.d));
break;
case TK_BOOL:
- rv = emit_op(lex, lex->source->off - word->plen, word->type, xjs_new_boolean(word->b));
+ rv = emit_op(lex, lex->source->off - word->plen, word->type, ucv_boolean_new(word->u.b));
break;
default:
@@ -802,23 +803,23 @@ parse_number(uc_lexer *lex, bool no_regexp)
if (*e == '.' || *e == 'e' || *e == 'E') {
d = strtod(lex->lookbehind, &e);
- if (tok->pat[0] == '-')
+ if (tok->u.pat[0] == '-')
d = -d;
if (e > lex->lookbehind && *e == 0)
- rv = emit_op(lex, lex->source->off - (e - lex->lookbehind), TK_DOUBLE, uc_double_new(d));
+ rv = emit_op(lex, lex->source->off - (e - lex->lookbehind), TK_DOUBLE, ucv_double_new(d));
else
- rv = emit_op(lex, lex->source->off - (lex->lookbehindlen - (e - lex->lookbehind) - 1), TK_ERROR, xjs_new_string("Invalid number literal"));
+ rv = emit_op(lex, lex->source->off - (lex->lookbehindlen - (e - lex->lookbehind) - 1), TK_ERROR, ucv_string_new("Invalid number literal"));
}
else if (*e == 0) {
- if (tok->pat[0] == '-')
+ if (tok->u.pat[0] == '-')
n = (errno == ERANGE) ? INT64_MIN : -n;
- rv = emit_op(lex, lex->source->off - (e - lex->lookbehind), TK_NUMBER, xjs_new_int64(n));
+ rv = emit_op(lex, lex->source->off - (e - lex->lookbehind), TK_NUMBER, ucv_int64_new(n));
//OP(rv)->is_overflow = (errno == ERANGE);
}
else {
- rv = emit_op(lex, lex->source->off - (lex->lookbehindlen - (e - lex->lookbehind) - 1), TK_ERROR, xjs_new_string("Invalid number literal"));
+ rv = emit_op(lex, lex->source->off - (lex->lookbehindlen - (e - lex->lookbehind) - 1), TK_ERROR, ucv_string_new("Invalid number literal"));
}
lookbehind_reset(lex);
@@ -856,7 +857,8 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
rem = lex->bufend - lex->bufstart;
- memcpy(lex->buf, lex->bufstart, rem);
+ if (rem)
+ memcpy(lex->buf, lex->bufstart, rem);
rlen = fread(lex->buf + rem, 1, lex->buflen - rem, fp);
@@ -1008,7 +1010,7 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
buf_consume(lex, lex->bufend - lex->bufstart);
- return emit_op(lex, lex->lastoff, TK_ERROR, xjs_new_string("Unterminated template block"));
+ return emit_op(lex, lex->lastoff, TK_ERROR, ucv_string_new("Unterminated template block"));
}
break;
@@ -1041,8 +1043,8 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
c = buf_remaining(lex) ? lex->bufstart[0] : 0;
- if (tok->plen ? ((search.n & masks[tok->plen]) == tok->patn)
- : (c >= tok->pat[0] && c <= tok->pat[1])) {
+ if (tok->plen ? ((search.n & masks[tok->plen]) == tok->u.patn)
+ : (c >= tok->u.pat[0] && c <= tok->u.pat[1])) {
lex->lastoff = lex->source->off;
/* token has a parse method, switch state */
@@ -1059,14 +1061,14 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
if (tok->type == TK_LSTM || tok->type == TK_LEXP) {
buf_consume(lex, tok->plen);
- return emit_op(lex, lex->source->off - tok->plen, TK_ERROR, xjs_new_string("Template blocks may not be nested"));
+ return emit_op(lex, lex->source->off - tok->plen, TK_ERROR, ucv_string_new("Template blocks may not be nested"));
}
/* found end of block */
else if ((lex->block == STATEMENTS && tok->type == TK_RSTM) ||
(lex->block == EXPRESSION && tok->type == TK_REXP)) {
/* strip whitespace after block */
- if (tok->pat[0] == '-')
+ if (tok->u.pat[0] == '-')
lex->modifier = MINUS;
/* strip newline after statement block */
@@ -1093,7 +1095,7 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
/* no token matched and we do have remaining data, junk */
if (buf_remaining(lex))
- return emit_op(lex, lex->source->off, TK_ERROR, xjs_new_string("Unexpected character"));
+ return emit_op(lex, lex->source->off, TK_ERROR, ucv_string_new("Unexpected character"));
/* we're at eof, allow unclosed statement blocks */
if (lex->block == STATEMENTS) {
@@ -1103,7 +1105,7 @@ lex_step(uc_lexer *lex, FILE *fp, bool no_regexp)
}
/* premature EOF */
- return emit_op(lex, lex->source->off, TK_ERROR, xjs_new_string("Unterminated template block"));
+ return emit_op(lex, lex->source->off, TK_ERROR, ucv_string_new("Unterminated template block"));
case UT_LEX_PARSE_TOKEN:
@@ -1188,7 +1190,7 @@ uc_lexer_next_token(uc_lexer *lex, bool no_regexp)
}
const char *
-uc_get_tokenname(int type)
+uc_get_tokenname(unsigned type)
{
static char buf[sizeof("'endfunction'")];
size_t i;
@@ -1206,7 +1208,7 @@ uc_get_tokenname(int type)
if (tokens[i].type != type)
continue;
- snprintf(buf, sizeof(buf), "'%s'", tokens[i].pat);
+ snprintf(buf, sizeof(buf), "'%s'", tokens[i].u.pat);
return buf;
}
diff --git a/lexer.h b/lexer.h
index 820a986..069e9e0 100644
--- a/lexer.h
+++ b/lexer.h
@@ -18,6 +18,7 @@
#define __LEXER_H_
#include "source.h"
+#include "types.h"
typedef enum {
@@ -121,17 +122,11 @@ typedef enum {
typedef struct {
uc_tokentype_t type;
- json_object *val;
+ uc_value_t *uv;
size_t pos;
} uc_token;
typedef struct {
- bool lstrip_blocks;
- bool trim_blocks;
- bool strict_declarations;
-} uc_parse_config;
-
-typedef struct {
uc_lex_state_t state;
uc_parse_config *config;
uc_source *source;
@@ -170,6 +165,6 @@ uc_token *uc_lexer_next_token(uc_lexer *lex, bool no_regexp);
bool utf8enc(char **out, int *rem, int code);
const char *
-uc_get_tokenname(int type);
+uc_get_tokenname(unsigned type);
#endif /* __LEXER_H_ */
diff --git a/lib.c b/lib.c
index a4cfdea..5d6235d 100644
--- a/lib.c
+++ b/lib.c
@@ -35,116 +35,60 @@
#include "compiler.h"
#include "vm.h"
#include "lib.h"
-#include "object.h"
-
-
-const uc_ops uc = {
- .value = {
- .proto = uc_prototype_new,
- .cfunc = uc_cfunction_new,
- .dbl = uc_double_new,
- .regexp = uc_regexp_new,
- .tonumber = uc_cast_number,
- .ressource = uc_ressource_new
- },
-
- .ressource = {
- .define = uc_ressource_type_add,
- .create = uc_ressource_new,
- .data = uc_ressource_dataptr,
- .proto = uc_ressource_prototype
- },
-
- .vm = {
- .call = uc_vm_call,
- .peek = uc_vm_stack_peek,
- .pop = uc_vm_stack_pop,
- .push = uc_vm_stack_push,
- .raise = uc_vm_raise_exception
- }
-};
-
-const uc_ops *ops = &uc;
-
-__attribute__((format(printf, 3, 5))) static void
-snprintf_append(char **dptr, size_t *dlen, const char *fmt, ssize_t sz, ...)
-{
- va_list ap;
- char *tmp;
- int n;
-
- va_start(ap, sz);
- n = vsnprintf(NULL, 0, fmt, ap);
- va_end(ap);
-
- if (sz >= 0 && n > sz)
- n = sz;
-
- tmp = xrealloc(*dptr, *dlen + n + 1);
-
- va_start(ap, sz);
- vsnprintf(tmp + *dlen, n + 1, fmt, ap);
- va_end(ap);
-
- *dptr = tmp;
- *dlen += n;
-}
-
-#define sprintf_append(dptr, dlen, fmt, ...) \
- snprintf_append(dptr, dlen, fmt, -1, ##__VA_ARGS__)
+#include "source.h"
static void
-format_context_line(char **msg, size_t *msglen, const char *line, size_t off, bool compact)
+format_context_line(uc_stringbuf_t *buf, const char *line, size_t off, bool compact)
{
+ unsigned padlen, i;
const char *p;
- int padlen, i;
for (p = line, padlen = 0; *p != '\n' && *p != '\0'; p++) {
- if (compact && (p - line) == off)
- sprintf_append(msg, msglen, "\033[22m");
+ if (compact && (p - line) == (ptrdiff_t)off)
+ ucv_stringbuf_append(buf, "\033[22m");
switch (*p) {
case '\t':
- sprintf_append(msg, msglen, " ");
+ ucv_stringbuf_append(buf, " ");
if (p < line + off)
padlen += 4;
break;
case '\r':
case '\v':
- sprintf_append(msg, msglen, " ");
+ ucv_stringbuf_append(buf, " ");
if (p < line + off)
padlen++;
break;
default:
- sprintf_append(msg, msglen, "%c", *p);
+ ucv_stringbuf_addstr(buf, p, 1);
if (p < line + off)
padlen++;
}
}
if (compact) {
- sprintf_append(msg, msglen, "\033[m\n");
+ ucv_stringbuf_append(buf, "\033[m\n");
return;
}
- sprintf_append(msg, msglen, "`\n ");
+ ucv_stringbuf_append(buf, "`\n ");
if (padlen < strlen("Near here ^")) {
for (i = 0; i < padlen; i++)
- sprintf_append(msg, msglen, " ");
+ ucv_stringbuf_append(buf, " ");
- sprintf_append(msg, msglen, "^-- Near here\n");
+ ucv_stringbuf_append(buf, "^-- Near here\n");
}
else {
- sprintf_append(msg, msglen, "Near here ");
+ ucv_stringbuf_append(buf, "Near here ");
for (i = strlen("Near here "); i < padlen; i++)
- sprintf_append(msg, msglen, "-");
+ ucv_stringbuf_append(buf, "-");
- sprintf_append(msg, msglen, "^\n");
+ ucv_stringbuf_append(buf, "^\n");
}
}
@@ -163,19 +107,19 @@ source_filename(uc_source *src, uint32_t line)
return buf;
}
-void
-format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bool compact)
+bool
+format_source_context(uc_stringbuf_t *buf, uc_source *src, size_t off, bool compact)
{
size_t len, rlen;
bool truncated;
- char buf[256];
+ char line[256];
long srcpos;
int eline;
srcpos = ftell(src->fp);
if (srcpos == -1)
- return;
+ return false;
fseek(src->fp, 0, SEEK_SET);
@@ -183,93 +127,105 @@ format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bo
eline = 1;
rlen = 0;
- while (fgets(buf, sizeof(buf), src->fp)) {
- len = strlen(buf);
+ while (fgets(line, sizeof(line), src->fp)) {
+ len = strlen(line);
rlen += len;
if (rlen > off) {
if (compact)
- sprintf_append(msg, msglen, "\033[2;40;97m%17s %s",
+ ucv_stringbuf_printf(buf, "\033[2;40;97m%17s %s",
source_filename(src, eline),
truncated ? "..." : "");
else
- sprintf_append(msg, msglen, "\n `%s",
+ ucv_stringbuf_printf(buf, "\n `%s",
truncated ? "..." : "");
- format_context_line(msg, msglen, buf, len - (rlen - off) + (truncated ? 3 : 0), compact);
+ format_context_line(buf, line, len - (rlen - off) + (truncated ? 3 : 0), compact);
break;
}
- truncated = (len > 0 && buf[len-1] != '\n');
+ truncated = (len > 0 && line[len-1] != '\n');
eline += !truncated;
}
fseek(src->fp, srcpos, SEEK_SET);
+
+ return true;
}
-void
-format_error_context(char **msg, size_t *msglen, uc_source *src, json_object *stacktrace, size_t off)
+bool
+format_error_context(uc_stringbuf_t *buf, uc_source *src, uc_value_t *stacktrace, size_t off)
{
- json_object *e, *fn, *file, *line, *byte;
+ uc_value_t *e, *fn, *file, *line, *byte;
const char *path;
size_t idx;
- for (idx = 0; idx < (stacktrace ? json_object_array_length(stacktrace) : 0); idx++) {
- e = json_object_array_get_idx(stacktrace, idx);
- fn = json_object_object_get(e, "function");
- file = json_object_object_get(e, "filename");
+ for (idx = 0; idx < (stacktrace ? ucv_array_length(stacktrace) : 0); idx++) {
+ e = ucv_array_get(stacktrace, idx);
+ fn = ucv_object_get(e, "function", NULL);
+ file = ucv_object_get(e, "filename", NULL);
if (idx == 0) {
- path = (file && strcmp(json_object_get_string(file), "[stdin]"))
- ? json_object_get_string(file) : NULL;
+ path = (file && strcmp(ucv_string_get(file), "[stdin]"))
+ ? ucv_string_get(file) : NULL;
if (path && fn)
- sprintf_append(msg, msglen, "In %s(), file %s, ",
- json_object_get_string(fn), path);
+ ucv_stringbuf_printf(buf, "In %s(), file %s, ", ucv_string_get(fn), path);
else if (fn)
- sprintf_append(msg, msglen, "In %s(), ",
- json_object_get_string(fn));
+ ucv_stringbuf_printf(buf, "In %s(), ", ucv_string_get(fn));
else if (path)
- sprintf_append(msg, msglen, "In %s, ", path);
+ ucv_stringbuf_printf(buf, "In %s, ", path);
else
- sprintf_append(msg, msglen, "In ");
+ ucv_stringbuf_append(buf, "In ");
- sprintf_append(msg, msglen, "line %" PRId64 ", byte %" PRId64 ":\n",
- json_object_get_int64(json_object_object_get(e, "line")),
- json_object_get_int64(json_object_object_get(e, "byte")));
+ ucv_stringbuf_printf(buf, "line %" PRId64 ", byte %" PRId64 ":\n",
+ ucv_int64_get(ucv_object_get(e, "line", NULL)),
+ ucv_int64_get(ucv_object_get(e, "byte", NULL)));
}
else {
- line = json_object_object_get(e, "line");
- byte = json_object_object_get(e, "byte");
+ line = ucv_object_get(e, "line", NULL);
+ byte = ucv_object_get(e, "byte", NULL);
- sprintf_append(msg, msglen, " called from %s%s (%s",
- fn ? "function " : "anonymous function",
- fn ? json_object_get_string(fn) : "",
- file ? json_object_get_string(file) : "");
+ ucv_stringbuf_printf(buf, " called from %s%s (%s",
+ fn ? "function " : "anonymous function",
+ fn ? ucv_string_get(fn) : "",
+ file ? ucv_string_get(file) : "");
if (line && byte)
- sprintf_append(msg, msglen, ":%" PRId64 ":%" PRId64 ")\n",
- json_object_get_int64(line),
- json_object_get_int64(byte));
+ ucv_stringbuf_printf(buf, ":%" PRId64 ":%" PRId64 ")\n",
+ ucv_int64_get(line),
+ ucv_int64_get(byte));
else
- sprintf_append(msg, msglen, "[C])\n");
+ ucv_stringbuf_append(buf, "[C])\n");
}
}
- format_source_context(msg, msglen, src, off, false);
+ return format_source_context(buf, src, off, false);
+}
+
+static char *uc_cast_string(uc_vm *vm, uc_value_t **v, bool *freeable) {
+ if (ucv_type(*v) == UC_STRING) {
+ *freeable = false;
+
+ return _ucv_string_get(v);
+ }
+
+ *freeable = true;
+
+ return ucv_to_string(vm, *v);
}
static double
-uc_cast_double(json_object *v)
+uc_cast_double(uc_value_t *v)
{
- enum json_type t;
+ uc_type_t t;
int64_t n;
double d;
t = uc_cast_number(v, &n, &d);
errno = 0;
- if (t == json_type_double) {
+ if (t == UC_DOUBLE) {
if (isnan(d))
errno = EINVAL;
else if (!isfinite(d))
@@ -282,16 +238,16 @@ uc_cast_double(json_object *v)
}
static int64_t
-uc_cast_int64(json_object *v)
+uc_cast_int64(uc_value_t *v)
{
- enum json_type t;
+ uc_type_t t;
int64_t n;
double d;
t = uc_cast_number(v, &n, &d);
errno = 0;
- if (t == json_type_double) {
+ if (t == UC_DOUBLE) {
if (isnan(d))
errno = EINVAL;
else if (!isfinite(d))
@@ -305,73 +261,72 @@ uc_cast_int64(json_object *v)
return n;
}
-static json_object *
+static uc_value_t *
uc_print_common(uc_vm *vm, size_t nargs, FILE *fh)
{
- json_object *item;
+ uc_value_t *item;
size_t reslen = 0;
size_t len = 0;
size_t arridx;
- const char *p;
+ char *p;
for (arridx = 0; arridx < nargs; arridx++) {
item = uc_get_arg(arridx);
- if (json_object_is_type(item, json_type_string)) {
- p = json_object_get_string(item);
- len = json_object_get_string_len(item);
+ if (ucv_type(item) == UC_STRING) {
+ len = ucv_string_length(item);
+ reslen += fwrite(ucv_string_get(item), 1, len, fh);
}
- else {
- p = item ? json_object_get_string(item) : NULL;
- p = p ? p : "";
+ else if (item != NULL) {
+ p = ucv_to_string(vm, item);
len = strlen(p);
+ reslen += fwrite(p, 1, len, fh);
+ free(p);
}
-
- reslen += fwrite(p, 1, len, fh);
}
- return xjs_new_int64(reslen);
+ return ucv_int64_new(reslen);
}
-static json_object *
+static uc_value_t *
uc_print(uc_vm *vm, size_t nargs)
{
return uc_print_common(vm, nargs, stdout);
}
-static json_object *
+static uc_value_t *
uc_length(uc_vm *vm, size_t nargs)
{
- json_object *arg = uc_get_arg(0);
+ uc_value_t *arg = uc_get_arg(0);
- switch (json_object_get_type(arg)) {
- case json_type_object:
- return xjs_new_int64(json_object_object_length(arg));
+ switch (ucv_type(arg)) {
+ case UC_OBJECT:
+ return ucv_int64_new(ucv_object_length(arg));
- case json_type_array:
- return xjs_new_int64(json_object_array_length(arg));
+ case UC_ARRAY:
+ return ucv_int64_new(ucv_array_length(arg));
- case json_type_string:
- return xjs_new_int64(json_object_get_string_len(arg));
+ case UC_STRING:
+ return ucv_int64_new(ucv_string_length(arg));
default:
return NULL;
}
}
-static json_object *
+static uc_value_t *
uc_index(uc_vm *vm, size_t nargs, bool right)
{
- json_object *stack = uc_get_arg(0);
- json_object *needle = uc_get_arg(1);
+ uc_value_t *stack = uc_get_arg(0);
+ uc_value_t *needle = uc_get_arg(1);
size_t arridx, len, ret = -1;
const char *sstr, *nstr, *p;
- switch (json_object_get_type(stack)) {
- case json_type_array:
- for (arridx = 0, len = json_object_array_length(stack); arridx < len; arridx++) {
- if (uc_cmp(TK_EQ, json_object_array_get_idx(stack, arridx), needle)) {
+ switch (ucv_type(stack)) {
+ case UC_ARRAY:
+ for (arridx = 0, len = ucv_array_length(stack); arridx < len; arridx++) {
+ if (uc_cmp(TK_EQ, ucv_array_get(stack, arridx), needle)) {
ret = arridx;
if (!right)
@@ -379,11 +334,11 @@ uc_index(uc_vm *vm, size_t nargs, bool right)
}
}
- return xjs_new_int64(ret);
+ return ucv_int64_new(ret);
- case json_type_string:
- sstr = json_object_get_string(stack);
- nstr = needle ? json_object_get_string(needle) : NULL;
+ case UC_STRING:
+ sstr = ucv_string_get(stack);
+ nstr = needle ? ucv_string_get(needle) : NULL;
len = needle ? strlen(nstr) : 0;
for (p = sstr; *p && len; p++) {
@@ -395,125 +350,87 @@ uc_index(uc_vm *vm, size_t nargs, bool right)
}
}
- return xjs_new_int64(ret);
+ return ucv_int64_new(ret);
default:
return NULL;
}
}
-static json_object *
+static uc_value_t *
uc_lindex(uc_vm *vm, size_t nargs)
{
return uc_index(vm, nargs, false);
}
-static json_object *
+static uc_value_t *
uc_rindex(uc_vm *vm, size_t nargs)
{
return uc_index(vm, nargs, true);
}
-static json_object *
+static uc_value_t *
uc_push(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
- json_object *item = NULL;
+ uc_value_t *arr = uc_get_arg(0);
+ uc_value_t *item = NULL;
size_t arridx;
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
for (arridx = 1; arridx < nargs; arridx++) {
item = uc_get_arg(arridx);
- json_object_array_add(arr, uc_value_get(item));
+ ucv_array_push(arr, ucv_get(item));
}
- return uc_value_get(item);
+ return ucv_get(item);
}
-static json_object *
+static uc_value_t *
uc_pop(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
- json_object *item = NULL;
- size_t arrlen;
+ uc_value_t *arr = uc_get_arg(0);
- if (!json_object_is_type(arr, json_type_array))
- return NULL;
-
- arrlen = json_object_array_length(arr);
-
- if (arrlen > 0) {
- item = uc_value_get(json_object_array_get_idx(arr, arrlen - 1));
- json_object_array_del_idx(arr, arrlen - 1, 1);
-#ifdef HAVE_ARRAY_SHRINK
- json_object_array_shrink(arr, 0);
-#endif
- }
-
- return item;
+ return ucv_array_pop(arr);
}
-static json_object *
+static uc_value_t *
uc_shift(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
- json_object *item = NULL;
- size_t arridx, arrlen;
+ uc_value_t *arr = uc_get_arg(0);
- if (!json_object_is_type(arr, json_type_array))
- return NULL;
-
- item = uc_value_get(json_object_array_get_idx(arr, 0));
- arrlen = json_object_array_length(arr);
-
- for (arridx = 0; arridx < arrlen - 1; arridx++)
- json_object_array_put_idx(arr, arridx,
- uc_value_get(json_object_array_get_idx(arr, arridx + 1)));
-
- json_object_array_del_idx(arr, arrlen - 1, 1);
-#ifdef HAVE_ARRAY_SHRINK
- json_object_array_shrink(arr, 0);
-#endif
-
- return item;
+ return ucv_array_shift(arr);
}
-static json_object *
+static uc_value_t *
uc_unshift(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
- json_object *item = NULL;
- size_t arridx, arrlen, addlen;
+ uc_value_t *arr = uc_get_arg(0);
+ uc_value_t *item = NULL;
+ size_t i;
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
- arrlen = json_object_array_length(arr);
- addlen = nargs - 1;
-
- for (arridx = arrlen; arridx > 0; arridx--)
- json_object_array_put_idx(arr, arridx + addlen - 1,
- uc_value_get(json_object_array_get_idx(arr, arridx - 1)));
-
- for (arridx = 0; arridx < addlen; arridx++) {
- item = uc_get_arg(arridx + 1);
- json_object_array_put_idx(arr, arridx, uc_value_get(item));
+ for (i = 1; i < nargs; i++) {
+ item = uc_get_arg(i);
+ ucv_array_unshift(arr, ucv_get(item));
}
- return uc_value_get(item);
+ return ucv_get(item);
}
-static json_object *
+static uc_value_t *
uc_chr(uc_vm *vm, size_t nargs)
{
+ uc_value_t *rv = NULL;
size_t idx;
int64_t n;
char *str;
if (!nargs)
- return xjs_new_string_len("", 0);
+ return ucv_string_new_length("", 0);
str = xalloc(nargs);
@@ -528,55 +445,80 @@ uc_chr(uc_vm *vm, size_t nargs)
str[idx] = (char)n;
}
- return xjs_new_string_len(str, nargs);
+ rv = ucv_string_new_length(str, nargs);
+ free(str);
+
+ return rv;
}
-static json_object *
+static uc_value_t *
uc_delete(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *rv = NULL;
- const char *key;
- size_t arridx;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *key = NULL;
+ uc_value_t *rv = NULL;
+ bool freeable;
+ size_t i;
+ char *k;
- if (!json_object_is_type(obj, json_type_object))
+ if (ucv_type(obj) != UC_OBJECT)
return NULL;
- for (arridx = 1; arridx < nargs; arridx++) {
- uc_value_put(rv);
+ for (i = 1; i < nargs; i++) {
+ ucv_put(rv);
+
+ key = uc_get_arg(i);
+ k = uc_cast_string(vm, &key, &freeable);
+ rv = ucv_get(ucv_object_get(obj, k, NULL));
- key = json_object_get_string(uc_get_arg(arridx));
- rv = uc_value_get(json_object_object_get(obj, key ? key : "null"));
+ ucv_object_delete(obj, k);
- json_object_object_del(obj, key ? key : "null");
+ if (freeable)
+ free(k);
}
return rv;
}
-static json_object *
+static uc_value_t *
uc_die(uc_vm *vm, size_t nargs)
{
- const char *msg = json_object_get_string(uc_get_arg(0));
+ uc_value_t *msg = uc_get_arg(0);
+ bool freeable = false;
+ char *s;
- uc_vm_raise_exception(vm, EXCEPTION_USER, msg ? msg : "Died");
+ s = msg ? uc_cast_string(vm, &msg, &freeable) : "Died";
+
+ uc_vm_raise_exception(vm, EXCEPTION_USER, "%s", s);
+
+ if (freeable)
+ free(s);
return NULL;
}
-static json_object *
+static uc_value_t *
uc_exists(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- const char *key = json_object_get_string(uc_get_arg(1));
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *key = uc_get_arg(1);
+ bool found, freeable;
+ char *k;
- if (!json_object_is_type(obj, json_type_object))
+ if (ucv_type(obj) != UC_OBJECT)
return false;
- return xjs_new_boolean(json_object_object_get_ex(obj, key ? key : "null", NULL));
+ k = uc_cast_string(vm, &key, &freeable);
+
+ ucv_object_get(obj, k, &found);
+
+ if (freeable)
+ free(k);
+
+ return ucv_boolean_new(found);
}
-__attribute__((noreturn)) static json_object *
+__attribute__((noreturn)) static uc_value_t *
uc_exit(uc_vm *vm, size_t nargs)
{
int64_t n = uc_cast_int64(uc_get_arg(0));
@@ -584,37 +526,38 @@ uc_exit(uc_vm *vm, size_t nargs)
exit(n);
}
-static json_object *
+static uc_value_t *
uc_getenv(uc_vm *vm, size_t nargs)
{
- const char *key = json_object_get_string(uc_get_arg(0));
- char *val = key ? getenv(key) : NULL;
+ uc_value_t *key = uc_get_arg(0);
+ char *k = ucv_string_get(key);
+ char *val = k ? getenv(k) : NULL;
- return val ? xjs_new_string(val) : NULL;
+ return val ? ucv_string_new(val) : NULL;
}
-static json_object *
+static uc_value_t *
uc_filter(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *func = uc_get_arg(1);
- json_object *rv, *arr;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *func = uc_get_arg(1);
+ uc_value_t *rv, *arr;
size_t arridx, arrlen;
- if (!json_object_is_type(obj, json_type_array))
+ if (ucv_type(obj) != UC_ARRAY)
return NULL;
- arr = xjs_new_array();
+ arr = ucv_array_new(vm);
- for (arrlen = json_object_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
+ for (arrlen = ucv_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
/* XXX: revisit leaks */
- uc_vm_stack_push(vm, uc_value_get(func));
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(obj, arridx)));
- uc_vm_stack_push(vm, xjs_new_int64(arridx));
- uc_vm_stack_push(vm, uc_value_get(obj));
+ uc_vm_stack_push(vm, ucv_get(func));
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(obj, arridx)));
+ uc_vm_stack_push(vm, ucv_int64_new(arridx));
+ uc_vm_stack_push(vm, ucv_get(obj));
if (uc_vm_call(vm, false, 3)) {
- uc_value_put(arr);
+ ucv_put(arr);
return NULL;
}
@@ -622,281 +565,233 @@ uc_filter(uc_vm *vm, size_t nargs)
rv = uc_vm_stack_pop(vm);
if (uc_val_is_truish(rv))
- json_object_array_add(arr, uc_value_get(json_object_array_get_idx(obj, arridx)));
+ ucv_array_push(arr, ucv_get(ucv_array_get(obj, arridx)));
- uc_value_put(rv);
+ ucv_put(rv);
}
return arr;
}
-static json_object *
+static uc_value_t *
uc_hex(uc_vm *vm, size_t nargs)
{
- const char *val = json_object_get_string(uc_get_arg(0));
+ uc_value_t *val = uc_get_arg(0);
+ char *e, *v;
int64_t n;
- char *e;
- if (!val || !isxdigit(*val))
- return uc_double_new(NAN);
+ v = ucv_string_get(val);
+
+ if (!v || !isxdigit(*v))
+ return ucv_double_new(NAN);
- n = strtoll(val, &e, 16);
+ n = strtoll(v, &e, 16);
- if (e == val || *e)
- return uc_double_new(NAN);
+ if (e == v || *e)
+ return ucv_double_new(NAN);
- return xjs_new_int64(n);
+ return ucv_int64_new(n);
}
-static json_object *
+static uc_value_t *
uc_int(uc_vm *vm, size_t nargs)
{
int64_t n = uc_cast_int64(uc_get_arg(0));
if (errno == EINVAL || errno == EOVERFLOW)
- return uc_double_new(NAN);
+ return ucv_double_new(NAN);
- return xjs_new_int64(n);
+ return ucv_int64_new(n);
}
-static json_object *
+static uc_value_t *
uc_join(uc_vm *vm, size_t nargs)
{
- const char *sep = json_object_get_string(uc_get_arg(0));
- json_object *arr = uc_get_arg(1);
- json_object *rv = NULL;
- size_t arrlen, arridx, len = 1;
- const char *item;
- char *res, *p;
- int ret;
+ uc_value_t *sep = uc_get_arg(0);
+ uc_value_t *arr = uc_get_arg(1);
+ size_t arrlen, arridx;
+ uc_stringbuf_t *buf;
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
- for (arrlen = json_object_array_length(arr), arridx = 0; arridx < arrlen; arridx++) {
- if (arridx > 0)
- len += strlen(sep);
-
- item = json_object_get_string(json_object_array_get_idx(arr, arridx));
- len += item ? strlen(item) : 0;
- }
-
- p = res = xalloc(len);
-
- for (arrlen = json_object_array_length(arr), arridx = 0; arridx < arrlen; arridx++) {
- if (arridx > 0) {
- ret = snprintf(p, len, "%s", sep);
-
- if (ret < 0 || ret >= len)
- goto out;
-
- len -= ret;
- p += ret;
- }
-
- item = json_object_get_string(json_object_array_get_idx(arr, arridx));
-
- if (item) {
- ret = snprintf(p, len, "%s", item);
+ buf = ucv_stringbuf_new();
- if (ret < 0 || ret >= len)
- goto out;
+ for (arrlen = ucv_array_length(arr), arridx = 0; arridx < arrlen; arridx++) {
+ if (arridx > 0)
+ ucv_to_stringbuf(vm, buf, sep, false);
- len -= ret;
- p += ret;
- }
+ ucv_to_stringbuf(vm, buf, ucv_array_get(arr, arridx), false);
}
- rv = xjs_new_string(res);
-
-out:
- free(res);
-
- return rv;
+ return ucv_stringbuf_finish(buf);
}
-static json_object *
+static uc_value_t *
uc_keys(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *arr = NULL;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *arr = NULL;
- if (!json_object_is_type(obj, json_type_object))
+ if (ucv_type(obj) != UC_OBJECT)
return NULL;
- arr = xjs_new_array();
+ arr = ucv_array_new(vm);
- json_object_object_foreach(obj, key, val)
- json_object_array_add(arr, xjs_new_string(key));
+ ucv_object_foreach(obj, key, val) {
+ (void)val;
+ ucv_array_push(arr, ucv_string_new(key));
+ }
return arr;
}
-static json_object *
+static uc_value_t *
uc_lc(uc_vm *vm, size_t nargs)
{
- const char *str = json_object_get_string(uc_get_arg(0));
- size_t len = str ? strlen(str) : 0;
- json_object *rv = NULL;
- char *res, *p;
+ char *str = ucv_to_string(vm, uc_get_arg(0));
+ uc_value_t *rv = NULL;
+ char *p;
if (!str)
return NULL;
- res = p = xalloc(len);
+ for (p = str; *p; p++)
+ if (*p >= 'A' && *p <= 'Z')
+ *p |= 32;
- while (*str)
- if (*str >= 'A' && *str <= 'Z')
- *p++ = 32 + *str++;
- else
- *p++ = *str++;
+ rv = ucv_string_new(str);
- rv = xjs_new_string_len(res, len);
- free(res);
+ free(str);
return rv;
}
-static json_object *
+static uc_value_t *
uc_map(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *func = uc_get_arg(1);
- json_object *arr, *rv;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *func = uc_get_arg(1);
+ uc_value_t *arr, *rv;
size_t arridx, arrlen;
- if (!json_object_is_type(obj, json_type_array))
+ if (ucv_type(obj) != UC_ARRAY)
return NULL;
- arr = xjs_new_array();
+ arr = ucv_array_new(vm);
- for (arrlen = json_object_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
+ for (arrlen = ucv_array_length(obj), arridx = 0; arridx < arrlen; arridx++) {
/* XXX: revisit leaks */
- uc_vm_stack_push(vm, uc_value_get(func));
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(obj, arridx)));
- uc_vm_stack_push(vm, xjs_new_int64(arridx));
- uc_vm_stack_push(vm, uc_value_get(obj));
+ uc_vm_stack_push(vm, ucv_get(func));
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(obj, arridx)));
+ uc_vm_stack_push(vm, ucv_int64_new(arridx));
+ uc_vm_stack_push(vm, ucv_get(obj));
if (uc_vm_call(vm, false, 3)) {
- uc_value_put(arr);
+ ucv_put(arr);
return NULL;
}
rv = uc_vm_stack_pop(vm);
- json_object_array_add(arr, rv);
+ ucv_array_push(arr, rv);
}
return arr;
}
-static json_object *
+static uc_value_t *
uc_ord(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *rv, *pos;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *rv, *pos;
const char *str;
size_t i, len;
int64_t n;
- if (!json_object_is_type(obj, json_type_string))
+ if (ucv_type(obj) != UC_STRING)
return NULL;
- str = json_object_get_string(obj);
- len = json_object_get_string_len(obj);
+ str = ucv_string_get(obj);
+ len = ucv_string_length(obj);
if (nargs == 1)
- return str[0] ? xjs_new_int64((int64_t)str[0]) : NULL;
+ return str[0] ? ucv_int64_new((int64_t)str[0]) : NULL;
- rv = xjs_new_array();
+ rv = ucv_array_new(vm);
for (i = 1; i < nargs; i++) {
pos = uc_get_arg(i);
- if (json_object_is_type(pos, json_type_int)) {
- n = json_object_get_int64(pos);
+ if (ucv_type(pos) == UC_INTEGER) {
+ n = ucv_int64_get(pos);
if (n < 0)
n += len;
- if (n >= 0 && n < len) {
- json_object_array_add(rv, xjs_new_int64((int64_t)str[n]));
+ if (n >= 0 && (uint64_t)n < len) {
+ ucv_array_push(rv, ucv_int64_new((int64_t)str[n]));
continue;
}
}
- json_object_array_add(rv, NULL);
+ ucv_array_push(rv, NULL);
}
return rv;
}
-static json_object *
+static uc_value_t *
uc_type(uc_vm *vm, size_t nargs)
{
- json_object *v = uc_get_arg(0);
- uc_objtype_t o = uc_object_type(v);
+ uc_value_t *v = uc_get_arg(0);
+ uc_type_t t = ucv_type(v);
- switch (o) {
- case UC_OBJ_CFUNCTION:
- case UC_OBJ_FUNCTION:
- case UC_OBJ_CLOSURE:
- return xjs_new_string("function");
+ switch (t) {
+ case UC_CFUNCTION:
+ case UC_FUNCTION:
+ case UC_CLOSURE:
+ return ucv_string_new("function");
- case UC_OBJ_RESSOURCE:
- return xjs_new_string("ressource");
+ case UC_INTEGER:
+ return ucv_string_new("int");
- default:
- switch (json_object_get_type(v)) {
- case json_type_object:
- return xjs_new_string("object");
+ case UC_BOOLEAN:
+ return ucv_string_new("bool");
- case json_type_array:
- return xjs_new_string("array");
-
- case json_type_double:
- return xjs_new_string("double");
-
- case json_type_int:
- return xjs_new_string("int");
-
- case json_type_boolean:
- return xjs_new_string("bool");
-
- case json_type_string:
- return xjs_new_string("string");
+ case UC_NULL:
+ return NULL;
- default:
- return NULL;
- }
+ default:
+ return ucv_string_new(ucv_typename(v));
}
}
-static json_object *
+static uc_value_t *
uc_reverse(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *rv = NULL;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *rv = NULL;
size_t len, arridx;
const char *str;
char *dup, *p;
- if (json_object_is_type(obj, json_type_array)) {
- rv = xjs_new_array();
+ if (ucv_type(obj) == UC_ARRAY) {
+ rv = ucv_array_new(vm);
- for (arridx = json_object_array_length(obj); arridx > 0; arridx--)
- json_object_array_add(rv, uc_value_get(json_object_array_get_idx(obj, arridx - 1)));
+ for (arridx = ucv_array_length(obj); arridx > 0; arridx--)
+ ucv_array_push(rv, ucv_get(ucv_array_get(obj, arridx - 1)));
}
- else if (json_object_is_type(obj, json_type_string)) {
- len = json_object_get_string_len(obj);
- str = json_object_get_string(obj);
+ else if (ucv_type(obj) == UC_STRING) {
+ len = ucv_string_length(obj);
+ str = ucv_string_get(obj);
p = dup = xalloc(len + 1);
while (len > 0)
*p++ = str[--len];
- rv = xjs_new_string(dup);
+ rv = ucv_string_new(dup);
free(dup);
}
@@ -908,15 +803,15 @@ uc_reverse(uc_vm *vm, size_t nargs)
static struct {
uc_vm *vm;
bool ex;
- json_object *fn;
+ uc_value_t *fn;
} sort_ctx;
static int
sort_fn(const void *k1, const void *k2)
{
- json_object * const *v1 = k1;
- json_object * const *v2 = k2;
- json_object *rv;
+ uc_value_t * const *v1 = k1;
+ uc_value_t * const *v2 = k2;
+ uc_value_t *rv;
int ret;
if (!sort_ctx.fn)
@@ -925,9 +820,9 @@ sort_fn(const void *k1, const void *k2)
if (sort_ctx.ex)
return 0;
- uc_vm_stack_push(sort_ctx.vm, uc_value_get(sort_ctx.fn));
- uc_vm_stack_push(sort_ctx.vm, uc_value_get(*v1));
- uc_vm_stack_push(sort_ctx.vm, uc_value_get(*v2));
+ uc_vm_stack_push(sort_ctx.vm, ucv_get(sort_ctx.fn));
+ uc_vm_stack_push(sort_ctx.vm, ucv_get(*v1));
+ uc_vm_stack_push(sort_ctx.vm, ucv_get(*v2));
if (uc_vm_call(sort_ctx.vm, false, 2)) {
sort_ctx.ex = true;
@@ -939,40 +834,40 @@ sort_fn(const void *k1, const void *k2)
ret = !uc_val_is_truish(rv);
- uc_value_put(rv);
+ ucv_put(rv);
return ret;
}
-static json_object *
+static uc_value_t *
uc_sort(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
- json_object *fn = uc_get_arg(1);
+ uc_value_t *arr = uc_get_arg(0);
+ uc_value_t *fn = uc_get_arg(1);
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
sort_ctx.vm = vm;
sort_ctx.fn = fn;
- json_object_array_sort(arr, sort_fn);
+ ucv_array_sort(arr, sort_fn);
- return sort_ctx.ex ? NULL : uc_value_get(arr);
+ return sort_ctx.ex ? NULL : ucv_get(arr);
}
-static json_object *
+static uc_value_t *
uc_splice(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
+ 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));
size_t arrlen, addlen, idx;
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
- arrlen = json_object_array_length(arr);
+ arrlen = ucv_array_length(arr);
addlen = nargs;
if (addlen == 1) {
@@ -987,7 +882,7 @@ uc_splice(uc_vm *vm, size_t nargs)
if (ofs < 0)
ofs = 0;
}
- else if (ofs > arrlen) {
+ else if ((uint64_t)ofs > arrlen) {
ofs = arrlen;
}
@@ -1001,7 +896,7 @@ uc_splice(uc_vm *vm, size_t nargs)
if (ofs < 0)
ofs = 0;
}
- else if (ofs > arrlen) {
+ else if ((uint64_t)ofs > arrlen) {
ofs = arrlen;
}
@@ -1011,71 +906,71 @@ uc_splice(uc_vm *vm, size_t nargs)
if (remlen < 0)
remlen = 0;
}
- else if (remlen > arrlen - ofs) {
+ else if ((uint64_t)remlen > arrlen - (uint64_t)ofs) {
remlen = arrlen - ofs;
}
addlen -= 3;
}
- if (addlen < remlen) {
- json_object_array_del_idx(arr, ofs, remlen - addlen);
+ if (addlen < (uint64_t)remlen) {
+ ucv_array_delete(arr, ofs, remlen - addlen);
}
- else if (addlen > remlen) {
- for (idx = arrlen; idx > ofs; idx--)
- json_object_array_put_idx(arr, idx + addlen - remlen - 1,
- uc_value_get(json_object_array_get_idx(arr, idx - 1)));
+ else if (addlen > (uint64_t)remlen) {
+ for (idx = arrlen; idx > (uint64_t)ofs; idx--)
+ ucv_array_set(arr, idx + addlen - remlen - 1,
+ ucv_get(ucv_array_get(arr, idx - 1)));
}
for (idx = 0; idx < addlen; idx++)
- json_object_array_put_idx(arr, ofs + idx,
- uc_value_get(uc_get_arg(3 + idx)));
+ ucv_array_set(arr, ofs + idx,
+ ucv_get(uc_get_arg(3 + idx)));
- return uc_value_get(arr);
+ return ucv_get(arr);
}
-static json_object *
+static uc_value_t *
uc_split(uc_vm *vm, size_t nargs)
{
- json_object *str = uc_get_arg(0);
- json_object *sep = uc_get_arg(1);
- json_object *arr = NULL;
+ uc_value_t *str = uc_get_arg(0);
+ uc_value_t *sep = uc_get_arg(1);
+ uc_value_t *arr = NULL;
const char *p, *sepstr, *splitstr;
int eflags = 0, res;
regmatch_t pmatch;
- uc_regexp *re;
+ uc_regexp_t *re;
size_t seplen;
- if (!sep || !json_object_is_type(str, json_type_string))
+ if (!sep || ucv_type(str) != UC_STRING)
return NULL;
- arr = xjs_new_array();
- splitstr = json_object_get_string(str);
+ arr = ucv_array_new(vm);
+ splitstr = ucv_string_get(str);
- if (uc_object_is_type(sep, UC_OBJ_REGEXP)) {
- re = uc_object_as_regexp(sep);
+ if (ucv_type(sep) == UC_REGEXP) {
+ re = (uc_regexp_t *)sep;
while (true) {
- res = regexec(&re->re, splitstr, 1, &pmatch, eflags);
+ res = regexec(&re->regexp, splitstr, 1, &pmatch, eflags);
if (res == REG_NOMATCH)
break;
- json_object_array_add(arr, xjs_new_string_len(splitstr, pmatch.rm_so));
+ ucv_array_push(arr, ucv_string_new_length(splitstr, pmatch.rm_so));
splitstr += pmatch.rm_eo;
eflags |= REG_NOTBOL;
}
- json_object_array_add(arr, xjs_new_string(splitstr));
+ ucv_array_push(arr, ucv_string_new(splitstr));
}
- else if (json_object_is_type(sep, json_type_string)) {
- sepstr = json_object_get_string(sep);
+ else if (ucv_type(sep) == UC_STRING) {
+ sepstr = ucv_string_get(sep);
for (p = splitstr + (*sepstr ? 1 : 0), seplen = strlen(sepstr); *p; p++) {
if (!strncmp(p, sepstr, seplen)) {
if (*sepstr || p > splitstr)
- json_object_array_add(arr, xjs_new_string_len(splitstr, p - splitstr));
+ ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr));
splitstr = p + seplen;
p = splitstr - (*sepstr ? 1 : 0);
@@ -1083,10 +978,10 @@ uc_split(uc_vm *vm, size_t nargs)
}
if (*splitstr)
- json_object_array_add(arr, xjs_new_string_len(splitstr, p - splitstr));
+ ucv_array_push(arr, ucv_string_new_length(splitstr, p - splitstr));
}
else {
- uc_value_put(arr);
+ ucv_put(arr);
return NULL;
}
@@ -1094,20 +989,20 @@ uc_split(uc_vm *vm, size_t nargs)
return arr;
}
-static json_object *
+static uc_value_t *
uc_substr(uc_vm *vm, size_t nargs)
{
- json_object *str = uc_get_arg(0);
+ 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));
const char *p;
size_t len;
- if (!json_object_is_type(str, json_type_string))
+ if (ucv_type(str) != UC_STRING)
return NULL;
- p = json_object_get_string(str);
- len = json_object_get_string_len(str);
+ p = ucv_string_get(str);
+ len = ucv_string_length(str);
switch (nargs) {
case 1:
@@ -1123,7 +1018,7 @@ uc_substr(uc_vm *vm, size_t nargs)
if (ofs < 0)
ofs = 0;
}
- else if (ofs > len) {
+ else if ((uint64_t)ofs > len) {
ofs = len;
}
@@ -1138,7 +1033,7 @@ uc_substr(uc_vm *vm, size_t nargs)
if (ofs < 0)
ofs = 0;
}
- else if (ofs > len) {
+ else if ((uint64_t)ofs > len) {
ofs = len;
}
@@ -1148,52 +1043,49 @@ uc_substr(uc_vm *vm, size_t nargs)
if (sublen < 0)
sublen = 0;
}
- else if (sublen > len - ofs) {
+ else if ((uint64_t)sublen > len - (uint64_t)ofs) {
sublen = len - ofs;
}
break;
}
- return xjs_new_string_len(p + ofs, sublen);
+ return ucv_string_new_length(p + ofs, sublen);
}
-static json_object *
+static uc_value_t *
uc_time(uc_vm *vm, size_t nargs)
{
time_t t = time(NULL);
- return xjs_new_int64((int64_t)t);
+ return ucv_int64_new((int64_t)t);
}
-static json_object *
+static uc_value_t *
uc_uc(uc_vm *vm, size_t nargs)
{
- const char *str = json_object_get_string(uc_get_arg(0));
- size_t len = str ? strlen(str) : 0;
- json_object *rv = NULL;
- char *res, *p;
+ char *str = ucv_to_string(vm, uc_get_arg(0));
+ uc_value_t *rv = NULL;
+ char *p;
if (!str)
return NULL;
- res = p = xalloc(len);
+ for (p = str; *p; p++)
+ if (*p >= 'a' && *p <= 'z')
+ *p &= ~32;
- while (*str)
- if (*str >= 'a' && *str <= 'z')
- *p++ = *str++ - 32;
- else
- *p++ = *str++;
+ rv = ucv_string_new(str);
- rv = xjs_new_string_len(res, len);
- free(res);
+ free(str);
return rv;
}
-static json_object *
+static uc_value_t *
uc_uchr(uc_vm *vm, size_t nargs)
{
+ uc_value_t *rv = NULL;
size_t idx, ulen;
char *p, *str;
int64_t n;
@@ -1226,45 +1118,49 @@ uc_uchr(uc_vm *vm, size_t nargs)
break;
}
- return xjs_new_string_len(str, ulen);
+ rv = ucv_string_new_length(str, ulen);
+
+ free(str);
+
+ return rv;
}
-static json_object *
+static uc_value_t *
uc_values(uc_vm *vm, size_t nargs)
{
- json_object *obj = uc_get_arg(0);
- json_object *arr;
+ uc_value_t *obj = uc_get_arg(0);
+ uc_value_t *arr;
- if (!json_object_is_type(obj, json_type_object))
+ if (ucv_type(obj) != UC_OBJECT)
return NULL;
- arr = xjs_new_array();
+ arr = ucv_array_new(vm);
- json_object_object_foreach(obj, key, val) {
+ ucv_object_foreach(obj, key, val) {
(void)key;
- json_object_array_add(arr, uc_value_get(val));
+ ucv_array_push(arr, ucv_get(val));
}
return arr;
}
-static json_object *
+static uc_value_t *
uc_trim_common(uc_vm *vm, size_t nargs, bool start, bool end)
{
- json_object *str = uc_get_arg(0);
- json_object *chr = uc_get_arg(1);
+ uc_value_t *str = uc_get_arg(0);
+ uc_value_t *chr = uc_get_arg(1);
const char *p, *c;
size_t len;
- if (!json_object_is_type(str, json_type_string) ||
- (chr != NULL && !json_object_is_type(chr, json_type_string)))
+ if (ucv_type(str) != UC_STRING ||
+ (chr != NULL && ucv_type(chr) != UC_STRING))
return NULL;
- c = json_object_get_string(chr);
+ c = ucv_string_get(chr);
c = c ? c : " \t\r\n";
- p = json_object_get_string(str);
- len = json_object_get_string_len(str);
+ p = ucv_string_get(str);
+ len = ucv_string_length(str);
if (start) {
while (*p) {
@@ -1285,47 +1181,45 @@ uc_trim_common(uc_vm *vm, size_t nargs, bool start, bool end)
}
}
- return xjs_new_string_len(p, len);
+ return ucv_string_new_length(p, len);
}
-static json_object *
+static uc_value_t *
uc_trim(uc_vm *vm, size_t nargs)
{
return uc_trim_common(vm, nargs, true, true);
}
-static json_object *
+static uc_value_t *
uc_ltrim(uc_vm *vm, size_t nargs)
{
return uc_trim_common(vm, nargs, true, false);
}
-static json_object *
+static uc_value_t *
uc_rtrim(uc_vm *vm, size_t nargs)
{
return uc_trim_common(vm, nargs, false, true);
}
-static size_t
-uc_printf_common(uc_vm *vm, size_t nargs, char **res)
+static void
+uc_printf_common(uc_vm *vm, size_t nargs, uc_stringbuf_t *buf)
{
- json_object *fmt = uc_get_arg(0);
+ uc_value_t *fmt = uc_get_arg(0);
char *fp, sfmt[sizeof("%0- 123456789.123456789%")];
- union { const char *s; int64_t n; double d; } arg;
+ union { char *s; int64_t n; double d; } arg;
const char *fstr, *last, *p;
- size_t len = 0, argidx = 1;
- enum json_type t;
-
- *res = NULL;
+ uc_type_t t = UC_NULL;
+ size_t argidx = 1;
- if (json_object_is_type(fmt, json_type_string))
- fstr = json_object_get_string(fmt);
+ if (ucv_type(fmt) == UC_STRING)
+ fstr = ucv_string_get(fmt);
else
fstr = "";
for (last = p = fstr; *p; p++) {
if (*p == '%') {
- snprintf_append(res, &len, "%s", p - last, last);
+ ucv_stringbuf_addstr(buf, last, p - last);
last = p++;
@@ -1397,7 +1291,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, char **res)
case 'u':
case 'x':
case 'X':
- t = json_type_int;
+ t = UC_INTEGER;
if (argidx < nargs)
arg.n = uc_cast_int64(uc_get_arg(argidx++));
@@ -1412,7 +1306,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, char **res)
case 'F':
case 'g':
case 'G':
- t = json_type_double;
+ t = UC_DOUBLE;
if (argidx < nargs)
arg.d = uc_cast_double(uc_get_arg(argidx++));
@@ -1422,7 +1316,7 @@ uc_printf_common(uc_vm *vm, size_t nargs, char **res)
break;
case 'c':
- t = json_type_int;
+ t = UC_INTEGER;
if (argidx < nargs)
arg.n = uc_cast_int64(uc_get_arg(argidx++)) & 0xff;
@@ -1432,33 +1326,31 @@ uc_printf_common(uc_vm *vm, size_t nargs, char **res)
break;
case 's':
- t = json_type_string;
+ t = UC_STRING;
if (argidx < nargs)
- arg.s = json_object_get_string(uc_get_arg(argidx++));
+ arg.s = ucv_to_string(vm, uc_get_arg(argidx++));
else
arg.s = NULL;
- arg.s = arg.s ? arg.s : "(null)";
+ arg.s = arg.s ? arg.s : xstrdup("(null)");
break;
case 'J':
- t = json_type_string;
+ t = UC_STRING;
if (argidx < nargs)
- arg.s = json_object_to_json_string_ext(
- uc_get_arg(argidx++),
- JSON_C_TO_STRING_SPACED|JSON_C_TO_STRING_NOSLASHESCAPE|JSON_C_TO_STRING_STRICT);
+ arg.s = ucv_to_jsonstring(vm, uc_get_arg(argidx++));
else
arg.s = NULL;
- arg.s = arg.s ? arg.s : "null";
+ arg.s = arg.s ? arg.s : xstrdup("null");
break;
case '%':
- t = json_type_null;
+ t = UC_NULL;
break;
@@ -1469,66 +1361,70 @@ uc_printf_common(uc_vm *vm, size_t nargs, char **res)
if (fp + 2 >= sfmt + sizeof(sfmt))
goto next;
- *fp++ = (t == json_type_string) ? 's' : *p;
+ *fp++ = (t == UC_STRING) ? 's' : *p;
*fp = 0;
-#pragma GCC diagnostic ignored "-Wformat-security"
-
switch (t) {
- case json_type_int: sprintf_append(res, &len, sfmt, arg.n); break;
- case json_type_double: sprintf_append(res, &len, sfmt, arg.d); break;
- case json_type_string: sprintf_append(res, &len, sfmt, arg.s); break;
- default: sprintf_append(res, &len, sfmt); break;
- }
+ case UC_INTEGER:
+ ucv_stringbuf_printf(buf, sfmt, arg.n);
+ break;
-#pragma GCC diagnostic pop
+ case UC_DOUBLE:
+ ucv_stringbuf_printf(buf, sfmt, arg.d);
+ break;
+
+ case UC_STRING:
+ ucv_stringbuf_printf(buf, sfmt, arg.s);
+ break;
+
+ default:
+ ucv_stringbuf_addstr(buf, sfmt, strlen(sfmt));
+ break;
+ }
last = p + 1;
next:
+ if (t == UC_STRING)
+ free(arg.s);
+
continue;
}
}
- snprintf_append(res, &len, "%s", p - last, last);
-
- return len;
+ ucv_stringbuf_addstr(buf, last, p - last);
}
-static json_object *
+static uc_value_t *
uc_sprintf(uc_vm *vm, size_t nargs)
{
- json_object *rv;
- char *str = NULL;
- size_t len;
-
- len = uc_printf_common(vm, nargs, &str);
- rv = xjs_new_string_len(str, len);
+ uc_stringbuf_t *buf = ucv_stringbuf_new();
- free(str);
+ uc_printf_common(vm, nargs, buf);
- return rv;
+ return ucv_stringbuf_finish(buf);
}
-static json_object *
+static uc_value_t *
uc_printf(uc_vm *vm, size_t nargs)
{
- char *str = NULL;
+ uc_stringbuf_t *buf = xprintbuf_new();
size_t len;
- len = uc_printf_common(vm, nargs, &str);
- len = fwrite(str, 1, len, stdout);
+ uc_printf_common(vm, nargs, buf);
- free(str);
+ len = fwrite(buf->buf, 1, printbuf_length(buf), stdout);
- return xjs_new_int64(len);
+ printbuf_free(buf);
+
+ return ucv_int64_new(len);
}
static bool
-uc_require_so(uc_vm *vm, const char *path, json_object **res)
+uc_require_so(uc_vm *vm, const char *path, uc_value_t **res)
{
- void (*init)(const uc_ops *, uc_prototype *);
- uc_prototype *scope;
+ void (*init)(uc_value_t *);
+ uc_value_t *scope;
struct stat st;
void *dlh;
@@ -1545,7 +1441,7 @@ uc_require_so(uc_vm *vm, const char *path, json_object **res)
return true;
}
- init = dlsym(dlh, "uc_module_entry");
+ *(void **)(&init) = dlsym(dlh, "uc_module_entry");
if (!init) {
uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
@@ -1554,22 +1450,22 @@ uc_require_so(uc_vm *vm, const char *path, json_object **res)
return true;
}
- scope = uc_prototype_new(NULL);
+ scope = ucv_object_new(vm);
- init(&uc, scope);
+ init(scope);
- *res = scope->header.jso;
+ *res = scope;
return true;
}
static bool
-uc_require_ucode(uc_vm *vm, const char *path, uc_prototype *scope, json_object **res)
+uc_require_ucode(uc_vm *vm, const char *path, uc_value_t *scope, uc_value_t **res)
{
uc_exception_type_t extype;
- uc_prototype *prev_scope;
- uc_function *function;
- uc_closure *closure;
+ uc_function_t *function;
+ uc_value_t *prev_scope;
+ uc_value_t *closure;
uc_source *source;
struct stat st;
char *err;
@@ -1598,9 +1494,9 @@ uc_require_ucode(uc_vm *vm, const char *path, uc_prototype *scope, json_object *
return true;
}
- closure = uc_closure_new(function, false);
+ closure = ucv_closure_new(vm, function, false);
- uc_vm_stack_push(vm, closure->header.jso);
+ uc_vm_stack_push(vm, closure);
prev_scope = vm->globals;
vm->globals = scope ? scope : prev_scope;
@@ -1618,11 +1514,10 @@ uc_require_ucode(uc_vm *vm, const char *path, uc_prototype *scope, json_object *
}
static bool
-uc_require_path(uc_vm *vm, const char *path_template, const char *name, json_object **res)
+uc_require_path(uc_vm *vm, const char *path_template, const char *name, uc_value_t **res)
{
+ uc_stringbuf_t *buf = xprintbuf_new();
const char *p, *q, *last;
- char *path = NULL;
- size_t plen = 0;
bool rv = false;
*res = NULL;
@@ -1632,12 +1527,16 @@ uc_require_path(uc_vm *vm, const char *path_template, const char *name, json_obj
if (!p)
goto invalid;
- snprintf_append(&path, &plen, "%s", p - path_template, path_template);
+ ucv_stringbuf_addstr(buf, path_template, p - path_template);
for (q = last = name;; q++) {
if (*q == '.' || *q == '\0') {
- snprintf_append(&path, &plen, "%s", q - last, last);
- sprintf_append(&path, &plen, "%s", *q ? "/" : ++p);
+ ucv_stringbuf_addstr(buf, last, q - last);
+
+ if (*q)
+ ucv_stringbuf_append(buf, "/");
+ else
+ ucv_stringbuf_addstr(buf, p + 1, strlen(p + 1));
if (*q == '\0')
break;
@@ -1649,46 +1548,45 @@ uc_require_path(uc_vm *vm, const char *path_template, const char *name, json_obj
}
}
- if (!strcmp(p, ".so"))
- rv = uc_require_so(vm, path, res);
- else if (!strcmp(p, ".uc"))
- rv = uc_require_ucode(vm, path, NULL, res);
+ if (!strcmp(p + 1, ".so"))
+ rv = uc_require_so(vm, buf->buf, res);
+ else if (!strcmp(p + 1, ".uc"))
+ rv = uc_require_ucode(vm, buf->buf, NULL, res);
invalid:
- free(path);
+ printbuf_free(buf);
return rv;
}
-static json_object *
+static uc_value_t *
uc_require(uc_vm *vm, size_t nargs)
{
- const char *name = json_object_get_string(uc_get_arg(0));
-
- json_object *val = uc_get_arg(0);
- json_object *search, *se, *res;
+ uc_value_t *val = uc_get_arg(0);
+ uc_value_t *search, *se, *res;
size_t arridx, arrlen;
+ const char *name;
- if (!json_object_is_type(val, json_type_string))
+ if (ucv_type(val) != UC_STRING)
return NULL;
- name = json_object_get_string(val);
- search = uc_prototype_lookup(vm->globals, "REQUIRE_SEARCH_PATH");
+ name = ucv_string_get(val);
+ search = ucv_property_get(vm->globals, "REQUIRE_SEARCH_PATH");
- if (!json_object_is_type(search, json_type_array)) {
+ if (ucv_type(search) != UC_ARRAY) {
uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
"Global require search path not set");
return NULL;
}
- for (arridx = 0, arrlen = json_object_array_length(search); arridx < arrlen; arridx++) {
- se = json_object_array_get_idx(search, arridx);
+ for (arridx = 0, arrlen = ucv_array_length(search); arridx < arrlen; arridx++) {
+ se = ucv_array_get(search, arridx);
- if (!json_object_is_type(se, json_type_string))
+ if (ucv_type(se) != UC_STRING)
continue;
- if (uc_require_path(vm, json_object_get_string(se), name, &res))
+ if (uc_require_path(vm, ucv_string_get(se), name, &res))
return res;
}
@@ -1698,11 +1596,11 @@ uc_require(uc_vm *vm, size_t nargs)
return NULL;
}
-static json_object *
+static uc_value_t *
uc_iptoarr(uc_vm *vm, size_t nargs)
{
- json_object *ip = uc_get_arg(0);
- json_object *res;
+ uc_value_t *ip = uc_get_arg(0);
+ uc_value_t *res;
union {
uint8_t u8[4];
struct in_addr in;
@@ -1710,24 +1608,24 @@ uc_iptoarr(uc_vm *vm, size_t nargs)
} a;
int i;
- if (!json_object_is_type(ip, json_type_string))
+ if (ucv_type(ip) != UC_STRING)
return NULL;
- if (inet_pton(AF_INET6, json_object_get_string(ip), &a)) {
- res = xjs_new_array();
+ if (inet_pton(AF_INET6, ucv_string_get(ip), &a)) {
+ res = ucv_array_new(vm);
for (i = 0; i < 16; i++)
- json_object_array_add(res, xjs_new_int64(a.in6.s6_addr[i]));
+ ucv_array_push(res, ucv_int64_new(a.in6.s6_addr[i]));
return res;
}
- else if (inet_pton(AF_INET, json_object_get_string(ip), &a)) {
- res = xjs_new_array();
+ else if (inet_pton(AF_INET, ucv_string_get(ip), &a)) {
+ res = ucv_array_new(vm);
- json_object_array_add(res, xjs_new_int64(a.u8[0]));
- json_object_array_add(res, xjs_new_int64(a.u8[1]));
- json_object_array_add(res, xjs_new_int64(a.u8[2]));
- json_object_array_add(res, xjs_new_int64(a.u8[3]));
+ ucv_array_push(res, ucv_int64_new(a.u8[0]));
+ ucv_array_push(res, ucv_int64_new(a.u8[1]));
+ ucv_array_push(res, ucv_int64_new(a.u8[2]));
+ ucv_array_push(res, ucv_int64_new(a.u8[3]));
return res;
}
@@ -1736,14 +1634,14 @@ uc_iptoarr(uc_vm *vm, size_t nargs)
}
static int
-check_byte(json_object *v)
+check_byte(uc_value_t *v)
{
int n;
- if (!json_object_is_type(v, json_type_int))
+ if (ucv_type(v) != UC_INTEGER)
return -1;
- n = json_object_get_int(v);
+ n = ucv_int64_get(v);
if (n < 0 || n > 255)
return -1;
@@ -1751,10 +1649,10 @@ check_byte(json_object *v)
return n;
}
-static json_object *
+static uc_value_t *
uc_arrtoip(uc_vm *vm, size_t nargs)
{
- json_object *arr = uc_get_arg(0);
+ uc_value_t *arr = uc_get_arg(0);
union {
uint8_t u8[4];
struct in6_addr in6;
@@ -1762,13 +1660,13 @@ uc_arrtoip(uc_vm *vm, size_t nargs)
char buf[INET6_ADDRSTRLEN];
int i, n;
- if (!json_object_is_type(arr, json_type_array))
+ if (ucv_type(arr) != UC_ARRAY)
return NULL;
- switch (json_object_array_length(arr)) {
+ switch (ucv_array_length(arr)) {
case 4:
for (i = 0; i < 4; i++) {
- n = check_byte(json_object_array_get_idx(arr, i));
+ n = check_byte(ucv_array_get(arr, i));
if (n < 0)
return NULL;
@@ -1778,11 +1676,11 @@ uc_arrtoip(uc_vm *vm, size_t nargs)
inet_ntop(AF_INET, &a, buf, sizeof(buf));
- return xjs_new_string(buf);
+ return ucv_string_new(buf);
case 16:
for (i = 0; i < 16; i++) {
- n = check_byte(json_object_array_get_idx(arr, i));
+ n = check_byte(ucv_array_get(arr, i));
if (n < 0)
return NULL;
@@ -1792,49 +1690,51 @@ uc_arrtoip(uc_vm *vm, size_t nargs)
inet_ntop(AF_INET6, &a, buf, sizeof(buf));
- return xjs_new_string(buf);
+ return ucv_string_new(buf);
default:
return NULL;
}
}
-static json_object *
+static uc_value_t *
uc_match(uc_vm *vm, size_t nargs)
{
- json_object *subject = uc_get_arg(0);
- json_object *pattern = uc_get_arg(1);
- json_object *rv = NULL, *m;
- int eflags = 0, res, i;
+ uc_value_t *subject = uc_get_arg(0);
+ uc_value_t *pattern = uc_get_arg(1);
+ uc_value_t *rv = NULL, *m;
regmatch_t pmatch[10];
- uc_regexp *re;
- const char *p;
+ int eflags = 0, res;
+ uc_regexp_t *re;
+ bool freeable;
+ char *p;
+ size_t i;
- if (!uc_object_is_type(pattern, UC_OBJ_REGEXP) || !subject)
+ if (ucv_type(pattern) != UC_REGEXP || !subject)
return NULL;
- p = json_object_get_string(subject);
- re = uc_object_as_regexp(pattern);
+ p = uc_cast_string(vm, &subject, &freeable);
+ re = (uc_regexp_t *)pattern;
while (true) {
- res = regexec(&re->re, p, ARRAY_SIZE(pmatch), pmatch, eflags);
+ res = regexec(&re->regexp, p, ARRAY_SIZE(pmatch), pmatch, eflags);
if (res == REG_NOMATCH)
break;
- m = xjs_new_array();
+ m = ucv_array_new(vm);
for (i = 0; i < ARRAY_SIZE(pmatch) && pmatch[i].rm_so != -1; i++) {
- json_object_array_add(m,
- xjs_new_string_len(p + pmatch[i].rm_so,
- pmatch[i].rm_eo - pmatch[i].rm_so));
+ ucv_array_push(m,
+ ucv_string_new_length(p + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
}
if (re->global) {
if (!rv)
- rv = xjs_new_array();
+ rv = ucv_array_new(vm);
- json_object_array_add(rv, m);
+ ucv_array_push(rv, m);
p += pmatch[0].rm_eo;
eflags |= REG_NOTBOL;
@@ -1845,24 +1745,27 @@ uc_match(uc_vm *vm, size_t nargs)
}
}
+ if (freeable)
+ free(p);
+
return rv;
}
-static json_object *
-uc_replace_cb(uc_vm *vm, json_object *func,
+static uc_value_t *
+uc_replace_cb(uc_vm *vm, uc_value_t *func,
const char *subject, regmatch_t *pmatch, size_t plen,
- char **sp, size_t *sl)
+ uc_stringbuf_t *resbuf)
{
- json_object *rv;
+ uc_value_t *rv;
size_t i;
/* XXX: revisit leaks */
- uc_vm_stack_push(vm, uc_value_get(func));
+ uc_vm_stack_push(vm, ucv_get(func));
for (i = 0; i < plen && pmatch[i].rm_so != -1; i++) {
uc_vm_stack_push(vm,
- xjs_new_string_len(subject + pmatch[i].rm_so,
- pmatch[i].rm_eo - pmatch[i].rm_so));
+ ucv_string_new_length(subject + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
}
if (uc_vm_call(vm, false, i))
@@ -1870,40 +1773,42 @@ uc_replace_cb(uc_vm *vm, json_object *func,
rv = uc_vm_stack_pop(vm);
- sprintf_append(sp, sl, "%s", rv ? json_object_get_string(rv) : "null");
+ ucv_to_stringbuf(vm, resbuf, rv, false);
- uc_value_put(rv);
+ ucv_put(rv);
return NULL;
}
static void
-uc_replace_str(uc_vm *vm, json_object *str,
+uc_replace_str(uc_vm *vm, uc_value_t *str,
const char *subject, regmatch_t *pmatch, size_t plen,
- char **sp, size_t *sl)
+ uc_stringbuf_t *resbuf)
{
- const char *r = str ? json_object_get_string(str) : "null";
- const char *p = r;
bool esc = false;
- int i;
+ char *p, *r;
+ uint8_t i;
- for (p = r; *p; p++) {
+ for (p = r = ucv_to_string(vm, str); *p; p++) {
if (esc) {
switch (*p) {
case '&':
if (pmatch[0].rm_so != -1)
- snprintf_append(sp, sl, "%s", pmatch[0].rm_eo - pmatch[0].rm_so,
- subject + pmatch[0].rm_so);
+ ucv_stringbuf_addstr(resbuf,
+ subject + pmatch[0].rm_so,
+ pmatch[0].rm_eo - pmatch[0].rm_so);
break;
case '`':
if (pmatch[0].rm_so != -1)
- snprintf_append(sp, sl, "%s", pmatch[0].rm_so, subject);
+ ucv_stringbuf_addstr(resbuf, subject, pmatch[0].rm_so);
break;
case '\'':
if (pmatch[0].rm_so != -1)
- sprintf_append(sp, sl, "%s", subject + pmatch[0].rm_eo);
+ ucv_stringbuf_addstr(resbuf,
+ subject + pmatch[0].rm_eo,
+ strlen(subject + pmatch[0].rm_eo));
break;
case '1':
@@ -1916,19 +1821,24 @@ uc_replace_str(uc_vm *vm, json_object *str,
case '8':
case '9':
i = *p - '0';
- if (i < plen && pmatch[i].rm_so != -1)
- snprintf_append(sp, sl, "%s", pmatch[i].rm_eo - pmatch[i].rm_so,
- subject + pmatch[i].rm_so);
- else
- sprintf_append(sp, sl, "$%c", *p);
+ if (i < plen && pmatch[i].rm_so != -1) {
+ ucv_stringbuf_addstr(resbuf,
+ subject + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so);
+ }
+ else {
+ ucv_stringbuf_append(resbuf, "$");
+ ucv_stringbuf_addstr(resbuf, p, 1);
+ }
break;
case '$':
- sprintf_append(sp, sl, "$");
+ ucv_stringbuf_append(resbuf, "$");
break;
default:
- sprintf_append(sp, sl, "$%c", *p);
+ ucv_stringbuf_append(resbuf, "$");
+ ucv_stringbuf_addstr(resbuf, p, 1);
}
esc = false;
@@ -1937,51 +1847,58 @@ uc_replace_str(uc_vm *vm, json_object *str,
esc = true;
}
else {
- sprintf_append(sp, sl, "%c", *p);
+ ucv_stringbuf_addstr(resbuf, p, 1);
}
}
+
+ free(r);
}
-static json_object *
+static uc_value_t *
uc_replace(uc_vm *vm, size_t nargs)
{
- json_object *subject = uc_get_arg(0);
- json_object *pattern = uc_get_arg(1);
- json_object *replace = uc_get_arg(2);
- json_object *rv = NULL;
- const char *sb, *p, *l;
+ 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);
+ bool sb_freeable, pt_freeable;
+ uc_value_t *rv = NULL;
+ uc_stringbuf_t *resbuf;
regmatch_t pmatch[10];
int eflags = 0, res;
- size_t sl = 0, pl;
- char *sp = NULL;
- uc_regexp *re;
+ uc_regexp_t *re;
+ size_t pl;
if (!pattern || !subject || !replace)
return NULL;
- if (uc_object_is_type(pattern, UC_OBJ_REGEXP)) {
- p = json_object_get_string(subject);
- re = uc_object_as_regexp(pattern);
+ sb = uc_cast_string(vm, &subject, &sb_freeable);
+ resbuf = ucv_stringbuf_new();
+
+ if (ucv_type(pattern) == UC_REGEXP) {
+ re = (uc_regexp_t *)pattern;
+ p = sb;
while (true) {
- res = regexec(&re->re, p, ARRAY_SIZE(pmatch), pmatch, eflags);
+ res = regexec(&re->regexp, p, ARRAY_SIZE(pmatch), pmatch, eflags);
if (res == REG_NOMATCH)
break;
- snprintf_append(&sp, &sl, "%s", pmatch[0].rm_so, p);
+ ucv_stringbuf_addstr(resbuf, p, pmatch[0].rm_so);
- if (uc_object_is_callable(replace)) {
- rv = uc_replace_cb(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
+ if (ucv_is_callable(replace)) {
+ rv = uc_replace_cb(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), resbuf);
if (rv) {
- free(sp);
+ if (sb_freeable)
+ free(sb);
return rv;
}
}
else {
- uc_replace_str(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), &sp, &sl);
+ uc_replace_str(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), resbuf);
}
p += pmatch[0].rm_eo;
@@ -1992,57 +1909,64 @@ uc_replace(uc_vm *vm, size_t nargs)
break;
}
- sprintf_append(&sp, &sl, "%s", p);
+ ucv_stringbuf_addstr(resbuf, p, strlen(p));
}
else {
- sb = json_object_get_string(subject);
- p = json_object_get_string(pattern);
- pl = strlen(p);
+ pt = uc_cast_string(vm, &pattern, &pt_freeable);
+ pl = strlen(pt);
- for (l = sb; *sb; sb++) {
- if (!strncmp(sb, p, pl)) {
- snprintf_append(&sp, &sl, "%s", sb - l, l);
+ for (l = p = sb; *p; p++) {
+ if (!strncmp(p, pt, pl)) {
+ ucv_stringbuf_addstr(resbuf, l, p - l);
- pmatch[0].rm_so = sb - l;
+ pmatch[0].rm_so = p - l;
pmatch[0].rm_eo = pmatch[0].rm_so + pl;
- if (uc_object_is_callable(replace)) {
- rv = uc_replace_cb(vm, replace, l, pmatch, 1, &sp, &sl);
+ if (ucv_is_callable(replace)) {
+ rv = uc_replace_cb(vm, replace, l, pmatch, 1, resbuf);
if (rv) {
- free(sp);
+ if (sb_freeable)
+ free(sb);
+
+ if (pt_freeable)
+ free(pt);
return rv;
}
}
else {
- uc_replace_str(vm, replace, l, pmatch, 1, &sp, &sl);
+ uc_replace_str(vm, replace, l, pmatch, 1, resbuf);
}
- l = sb + pl;
- sb += pl - 1;
+ l = p + pl;
+ p += pl - 1;
}
}
- sprintf_append(&sp, &sl, "%s", l);
+ ucv_stringbuf_addstr(resbuf, l, strlen(l));
+
+ if (pt_freeable)
+ free(pt);
}
- rv = xjs_new_string_len(sp, sl);
- free(sp);
+ if (sb_freeable)
+ free(sb);
- return rv;
+ return ucv_stringbuf_finish(resbuf);
}
-static json_object *
+static uc_value_t *
uc_json(uc_vm *vm, size_t nargs)
{
- json_object *rv, *src = uc_get_arg(0);
+ uc_value_t *rv, *src = uc_get_arg(0);
struct json_tokener *tok = NULL;
enum json_tokener_error err;
+ json_object *jso;
const char *str;
size_t len;
- if (!json_object_is_type(src, json_type_string)) {
+ if (ucv_type(src) != UC_STRING) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE,
"Passed value is not a string");
@@ -2050,24 +1974,24 @@ uc_json(uc_vm *vm, size_t nargs)
}
tok = xjs_new_tokener();
- str = json_object_get_string(src);
- len = json_object_get_string_len(src);
+ str = ucv_string_get(src);
+ len = ucv_string_length(src);
/* NB: the len + 1 here is intentional to pass the terminating \0 byte
* to the json-c parser. This is required to work-around upstream
* issue #681 <https://github.com/json-c/json-c/issues/681> */
- rv = json_tokener_parse_ex(tok, str, len + 1);
+ jso = json_tokener_parse_ex(tok, str, len + 1);
err = json_tokener_get_error(tok);
if (err == json_tokener_continue) {
- uc_value_put(rv);
+ json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Unexpected end of string in JSON data");
return NULL;
}
else if (err != json_tokener_success) {
- uc_value_put(rv);
+ json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Failed to parse JSON string: %s",
json_tokener_error_desc(err));
@@ -2075,7 +1999,7 @@ uc_json(uc_vm *vm, size_t nargs)
return NULL;
}
else if (json_tokener_get_parse_end(tok) < len) {
- uc_value_put(rv);
+ json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Trailing garbage after JSON data");
@@ -2084,6 +2008,10 @@ uc_json(uc_vm *vm, size_t nargs)
json_tokener_free(tok);
+ rv = ucv_from_json(vm, jso);
+
+ json_object_put(jso);
+
return rv;
}
@@ -2120,26 +2048,24 @@ include_path(const char *curpath, const char *incpath)
return dup;
}
-static json_object *
+static uc_value_t *
uc_include(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
- json_object *scope = uc_get_arg(1);
- json_object *rv = NULL;
- uc_closure *closure = NULL;
- uc_prototype *sc;
- bool put = false;
+ uc_value_t *path = uc_get_arg(0);
+ uc_value_t *scope = uc_get_arg(1);
+ uc_value_t *rv = NULL, *sc = NULL;
+ uc_closure_t *closure = NULL;
size_t i;
char *p;
- if (!json_object_is_type(path, json_type_string)) {
+ if (ucv_type(path) != UC_STRING) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE,
"Passed filename is not a string");
return NULL;
}
- if (scope && !json_object_is_type(scope, json_type_object)) {
+ if (scope && ucv_type(scope) != UC_OBJECT) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE,
"Passed scope value is not an object");
@@ -2157,7 +2083,7 @@ uc_include(uc_vm *vm, size_t nargs)
if (!closure)
return NULL;
- p = include_path(closure->function->source->filename, json_object_get_string(path));
+ p = include_path(closure->function->source->filename, ucv_string_get(path));
if (!p) {
uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
@@ -2166,64 +2092,79 @@ uc_include(uc_vm *vm, size_t nargs)
return NULL;
}
- if (uc_object_is_type(scope, UC_OBJ_PROTOTYPE)) {
- sc = uc_object_as_prototype(scope);
+ if (ucv_prototype_get(scope)) {
+ sc = ucv_get(scope);
}
else if (scope) {
- sc = uc_prototype_new(vm->globals);
- put = true;
+ sc = ucv_object_new(vm);
+
+ ucv_object_foreach(scope, key, val)
+ ucv_object_add(sc, key, ucv_get(val));
- json_object_object_foreach(scope, key, val)
- json_object_object_add(sc->header.jso, key, uc_value_get(val));
+ ucv_prototype_set(sc, ucv_get(vm->globals));
}
else {
- sc = vm->globals;
+ sc = ucv_get(vm->globals);
}
if (uc_require_ucode(vm, p, sc, &rv))
- uc_value_put(rv);
+ ucv_put(rv);
+ ucv_put(sc);
free(p);
- if (put)
- uc_value_put(sc->header.jso);
-
return NULL;
}
-static json_object *
+static uc_value_t *
uc_warn(uc_vm *vm, size_t nargs)
{
return uc_print_common(vm, nargs, stderr);
}
-static json_object *
+static uc_value_t *
uc_system(uc_vm *vm, size_t nargs)
{
- json_object *cmdline = uc_get_arg(0);
- json_object *timeout = uc_get_arg(1);
- sigset_t sigmask, sigomask;
+ uc_value_t *cmdline = uc_get_arg(0);
+ uc_value_t *timeout = uc_get_arg(1);
const char **arglist, *fn;
+ sigset_t sigmask, sigomask;
struct timespec ts;
+ size_t i, len;
int64_t tms;
pid_t cld;
- size_t i;
int rc;
- switch (json_object_get_type(cmdline)) {
- case json_type_string:
+ if (timeout && (ucv_type(timeout) != UC_INTEGER || ucv_int64_get(timeout) < 0)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Invalid timeout specified");
+
+ return NULL;
+ }
+
+ switch (ucv_type(cmdline)) {
+ case UC_STRING:
arglist = xalloc(sizeof(*arglist) * 4);
- arglist[0] = "/bin/sh";
- arglist[1] = "-c";
- arglist[2] = json_object_get_string(cmdline);
+ arglist[0] = xstrdup("/bin/sh");
+ arglist[1] = xstrdup("-c");
+ arglist[2] = ucv_to_string(vm, cmdline);
arglist[3] = NULL;
break;
- case json_type_array:
- arglist = xalloc(sizeof(*arglist) * (json_object_array_length(cmdline) + 1));
+ case UC_ARRAY:
+ len = ucv_array_length(cmdline);
+
+ if (len == 0) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE,
+ "Passed command array is empty");
+
+ return NULL;
+ }
+
+ arglist = xalloc(sizeof(*arglist) * (len + 1));
- for (i = 0; i < json_object_array_length(cmdline); i++)
- arglist[i] = json_object_get_string(json_object_array_get_idx(cmdline, i));
+ for (i = 0; i < len; i++)
+ arglist[i] = ucv_to_string(vm, ucv_array_get(cmdline, i));
arglist[i] = NULL;
@@ -2236,14 +2177,7 @@ uc_system(uc_vm *vm, size_t nargs)
return NULL;
}
- if (timeout && (!json_object_is_type(timeout, json_type_int) || json_object_get_int64(timeout) < 0)) {
- uc_vm_raise_exception(vm, EXCEPTION_TYPE,
- "Invalid timeout specified");
-
- return NULL;
- }
-
- tms = timeout ? json_object_get_int64(timeout) : 0;
+ tms = timeout ? ucv_int64_get(timeout) : 0;
if (tms > 0) {
sigemptyset(&sigmask);
@@ -2298,14 +2232,17 @@ uc_system(uc_vm *vm, size_t nargs)
if (tms > 0)
sigprocmask(SIG_SETMASK, &sigomask, NULL);
+ for (i = 0; arglist[i]; i++)
+ free((char *)arglist[i]);
+
free(arglist);
if (WIFEXITED(rc))
- return xjs_new_int64(WEXITSTATUS(rc));
+ return ucv_int64_new(WEXITSTATUS(rc));
else if (WIFSIGNALED(rc))
- return xjs_new_int64(-WTERMSIG(rc));
+ return ucv_int64_new(-WTERMSIG(rc));
else if (WIFSTOPPED(rc))
- return xjs_new_int64(-WSTOPSIG(rc));
+ return ucv_int64_new(-WSTOPSIG(rc));
return NULL;
}
@@ -2314,6 +2251,9 @@ fail:
if (tms > 0)
sigprocmask(SIG_SETMASK, &sigomask, NULL);
+ for (i = 0; arglist[i]; i++)
+ free((char *)arglist[i]);
+
free(arglist);
uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
@@ -2322,95 +2262,61 @@ fail:
return NULL;
}
-static json_object *
+static uc_value_t *
uc_trace(uc_vm *vm, size_t nargs)
{
- json_object *level = uc_get_arg(0);
+ uc_value_t *level = uc_get_arg(0);
uint8_t prev_level;
- if (!json_object_is_type(level, json_type_int)) {
+ if (ucv_type(level) != UC_INTEGER) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid level specified");
return NULL;
}
prev_level = vm->trace;
- vm->trace = json_object_get_int64(level);
+ vm->trace = ucv_int64_get(level);
- return xjs_new_int64(prev_level);
+ return ucv_int64_new(prev_level);
}
-static json_object *
+static uc_value_t *
uc_proto(uc_vm *vm, size_t nargs)
{
- json_object *val = uc_get_arg(0);
- json_object *proto = NULL;
- uc_prototype *p, *ref;
-
- if (nargs < 2) {
- switch (uc_object_type(val)) {
- case UC_OBJ_PROTOTYPE:
- p = uc_object_as_prototype(val)->parent;
-
- return p ? uc_value_get(p->header.jso) : NULL;
-
- case UC_OBJ_RESSOURCE:
- p = uc_ressource_prototype(val);
+ uc_value_t *val = uc_get_arg(0);
+ uc_value_t *proto = NULL;
- return p ? uc_value_get(p->header.jso) : NULL;
-
- default:
- return NULL;
- }
- }
+ if (nargs < 2)
+ return ucv_get(ucv_prototype_get(val));
proto = uc_get_arg(1);
- switch (uc_object_type(proto)) {
- case UC_OBJ_PROTOTYPE:
- p = uc_object_as_prototype(proto);
- break;
-
- case UC_OBJ_RESSOURCE:
- p = uc_ressource_prototype(proto);
- break;
-
- default:
- switch (json_object_get_type(proto)) {
- case json_type_object:
- p = uc_protoref_new(proto, NULL);
- break;
-
- default:
- uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Passed value is neither a prototype, ressource or object");
-
- return NULL;
- }
- }
+ if (!ucv_prototype_set(val, proto))
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Passed value is neither a prototype, ressource or object");
- ref = uc_protoref_new(val, p);
+ ucv_get(proto);
- return ref ? uc_value_get(ref->header.jso) : NULL;
+ return ucv_get(val);
}
-static json_object *
+static uc_value_t *
uc_sleep(uc_vm *vm, size_t nargs)
{
- json_object *duration = uc_get_arg(0);
+ uc_value_t *duration = uc_get_arg(0);
struct timeval tv;
int64_t ms;
ms = uc_cast_int64(duration);
if (errno != 0 || ms <= 0)
- return xjs_new_boolean(false);
+ return ucv_boolean_new(false);
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
select(0, NULL, NULL, NULL, &tv);
- return xjs_new_boolean(true);
+ return ucv_boolean_new(true);
}
static const uc_cfunction_list functions[] = {
@@ -2467,7 +2373,7 @@ static const uc_cfunction_list functions[] = {
void
-uc_lib_init(uc_prototype *scope)
+uc_lib_init(uc_value_t *scope)
{
uc_add_proto_functions(scope, functions);
}
diff --git a/lib.h b/lib.h
index c14d11d..aad9a9d 100644
--- a/lib.h
+++ b/lib.h
@@ -19,185 +19,106 @@
#include "vm.h"
#include "lexer.h"
-#include "object.h"
typedef struct {
const char *name;
- uc_cfn_ptr func;
+ uc_cfn_ptr_t func;
} uc_cfunction_list;
-typedef struct {
- /* value operations */
- struct {
- uc_prototype *(*proto)(uc_prototype *);
- uc_cfunction *(*cfunc)(const char *, uc_cfn_ptr);
- json_object *(*dbl)(double);
- uc_regexp *(*regexp)(const char *, bool, bool, bool, char **);
- uc_ressource *(*ressource)(json_object *, uc_ressource_type *, void *);
- enum json_type (*tonumber)(json_object *, int64_t *, double *);
- } value;
-
- /* ressource operations */
- struct {
- uc_ressource_type *(*define)(const char *, uc_prototype *, void (*)(void *));
- uc_ressource *(*create)(json_object *, uc_ressource_type *, void *);
- void **(*data)(json_object *, const char *);
- uc_prototype *(*proto)(json_object *);
- } ressource;
-
- /* VM operations */
- struct {
- uc_exception_type_t (*call)(uc_vm *, bool, size_t);
- json_object *(*peek)(uc_vm *, size_t);
- json_object *(*pop)(uc_vm *);
- void (*push)(uc_vm *, json_object *);
- void (*raise)(uc_vm *, uc_exception_type_t, const char *, ...);
- } vm;
-} uc_ops;
-
-extern const uc_ops uc;
-
-void uc_lib_init(uc_prototype *scope);
-
-void format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bool compact);
-void format_error_context(char **msg, size_t *msglen, uc_source *src, json_object *stacktrace, size_t off);
+void uc_lib_init(uc_value_t *scope);
+
+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(const uc_ops *ops, uc_vm *vm, const char *expected_type)
+_uc_get_self(uc_vm *vm, const char *expected_type)
{
- return ops->ressource.data(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type);
+ return ucv_ressource_dataptr(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type);
}
-#define uc_get_self(...) _uc_get_self(ops, vm, __VA_ARGS__)
+#define uc_get_self(...) _uc_get_self(vm, __VA_ARGS__)
-static inline json_object *
-_uc_get_arg(const uc_ops *ops, uc_vm *vm, size_t nargs, size_t n)
+static inline uc_value_t *
+_uc_get_arg(uc_vm *vm, size_t nargs, size_t n)
{
if (n >= nargs)
return NULL;
- return ops->vm.peek(vm, nargs - n - 1);
+ return uc_vm_stack_peek(vm, nargs - n - 1);
}
-#define uc_get_arg(...) _uc_get_arg(ops, vm, nargs, __VA_ARGS__)
+#define uc_get_arg(...) _uc_get_arg(vm, nargs, __VA_ARGS__)
-#define uc_call(nargs) ops->vm.call(vm, false, nargs)
-#define uc_push_val(val) ops->vm.push(vm, val)
-#define uc_pop_val() ops->vm.pop(vm)
+#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 json_object *
-_uc_alloc_proto(const uc_ops *ops, uc_prototype *parent)
-{
- return ops->value.proto(parent)->header.jso;
-}
-
-static inline json_object *
-_uc_alloc_cfunc(const uc_ops *ops, const char *name, uc_cfn_ptr fptr)
-{
- return ops->value.cfunc(name, fptr)->header.jso;
-}
-
-static inline json_object *
-_uc_alloc_double(const uc_ops *ops, double dbl)
-{
- return ops->value.dbl(dbl);
-}
-
-static inline json_object *
-_uc_alloc_regexp(const uc_ops *ops, const char *pattern, bool global, bool icase, bool newline, char **errp)
+static inline uc_value_t *
+uc_alloc_ressource(uc_ressource_type_t *type, void *data)
{
- uc_regexp *re = ops->value.regexp(pattern, global, icase, newline, errp);
-
- return re ? re->header.jso : NULL;
-}
-
-static inline json_object *
-_uc_alloc_ressource(const uc_ops *ops, uc_ressource_type *type, void *data)
-{
- uc_ressource *res = ops->value.ressource(xjs_new_object(), type, data);
-
- return res ? res->header.jso : NULL;
+ return ucv_ressource_new(type, data);
}
-#define uc_alloc_proto(...) _uc_alloc_proto(ops, __VA_ARGS__)
-#define uc_alloc_cfunc(...) _uc_alloc_cfunc(ops, __VA_ARGS__)
-#define uc_alloc_double(...) _uc_alloc_double(ops, __VA_ARGS__)
-#define uc_alloc_regexp(...) _uc_alloc_regexp(ops, __VA_ARGS__)
-#define uc_alloc_ressource(...) _uc_alloc_ressource(ops, __VA_ARGS__)
-
-static inline json_type
-_uc_to_number(const uc_ops *ops, json_object *v, int64_t *n, double *d)
+static inline uc_type_t
+uc_to_number(uc_value_t *v, int64_t *n, double *d)
{
- return ops->value.tonumber(v, n, d);
+ return uc_cast_number(v, n, d);
}
static inline double
-_uc_to_double(const uc_ops *ops, json_object *v)
+uc_to_double(uc_value_t *v)
{
int64_t n;
double d;
- return (ops->value.tonumber(v, &n, &d) == json_type_double) ? d : (double)n;
+ return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? d : (double)n;
}
static inline int64_t
-_uc_to_int64(const uc_ops *ops, json_object *v)
+uc_to_int64(uc_value_t *v)
{
int64_t n;
double d;
- return (ops->value.tonumber(v, &n, &d) == json_type_double) ? (int64_t)d : n;
+ return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? (int64_t)d : n;
}
-#define uc_to_number(...) _uc_to_number(ops, __VA_ARGS__)
-#define uc_to_double(...) _uc_to_double(ops, __VA_ARGS__)
-#define uc_to_int64(...) _uc_to_int64(ops, __VA_ARGS__)
-
/* ressource type helper */
-static inline uc_ressource_type *
-_uc_declare_type(const uc_ops *ops, const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *))
+static inline uc_ressource_type_t *
+_uc_declare_type(const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *))
{
- uc_prototype *proto = ops->value.proto(NULL);
+ uc_value_t *proto = ucv_object_new(NULL);
while (len-- > 0)
- json_object_object_add(proto->header.jso, list[len].name,
- _uc_alloc_cfunc(ops, list[len].name, list[len].func));
+ ucv_object_add(proto, list[len].name,
+ ucv_cfunction_new(list[len].name, list[len].func));
- return ops->ressource.define(name, proto, freefn);
+ return ucv_ressource_type_add(name, proto, freefn);
}
#define uc_declare_type(name, functions, freefn) \
- _uc_declare_type(ops, name, functions, ARRAY_SIZE(functions), freefn)
+ _uc_declare_type(name, functions, ARRAY_SIZE(functions), freefn)
/* prototype helper */
-static inline bool
-uc_add_proto_val(uc_prototype *proto, const char *key, json_object *value)
-{
- if (!proto)
- return false;
-
- return json_object_object_add(proto->header.jso, key, value);
-}
-
static inline void
-_uc_add_proto_functions(const uc_ops *ops, uc_prototype *proto, const uc_cfunction_list *list, size_t len)
+_uc_add_proto_functions(uc_value_t *proto, const uc_cfunction_list *list, size_t len)
{
while (len-- > 0)
- json_object_object_add(proto->header.jso, list[len].name,
- _uc_alloc_cfunc(ops, list[len].name, list[len].func));
+ 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(ops, proto, functions, ARRAY_SIZE(functions))
+ _uc_add_proto_functions(proto, functions, ARRAY_SIZE(functions))
#endif /* __LIB_H_ */
diff --git a/lib/fs.c b/lib/fs.c
index 6ea4ec1..707e6db 100644
--- a/lib/fs.c
+++ b/lib/fs.c
@@ -28,29 +28,29 @@
#define err_return(err) do { last_error = err; return NULL; } while(0)
//static const uc_ops *ops;
-static uc_ressource_type *file_type, *proc_type, *dir_type;
+static uc_ressource_type_t *file_type, *proc_type, *dir_type;
static int last_error = 0;
-static json_object *
+static uc_value_t *
uc_fs_error(uc_vm *vm, size_t nargs)
{
- json_object *errmsg;
+ uc_value_t *errmsg;
if (last_error == 0)
return NULL;
- errmsg = json_object_new_string(strerror(last_error));
+ errmsg = ucv_string_new(strerror(last_error));
last_error = 0;
return errmsg;
}
-static json_object *
+static uc_value_t *
uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type)
{
- json_object *limit = uc_get_arg(0);
- json_object *rv = NULL;
+ uc_value_t *limit = uc_get_arg(0);
+ uc_value_t *rv = NULL;
char buf[128], *p = NULL, *tmp;
size_t rlen, len = 0;
const char *lstr;
@@ -61,8 +61,8 @@ uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type)
if (!fp || !*fp)
err_return(EBADF);
- if (json_object_is_type(limit, json_type_string)) {
- lstr = json_object_get_string(limit);
+ if (ucv_type(limit) == UC_STRING) {
+ lstr = ucv_string_get(limit);
if (!strcmp(lstr, "line")) {
while (true) {
@@ -110,8 +110,8 @@ uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type)
return NULL;
}
}
- else if (json_object_is_type(limit, json_type_int)) {
- lsize = json_object_get_int64(limit);
+ else if (ucv_type(limit) == UC_INTEGER) {
+ lsize = ucv_int64_get(limit);
if (lsize <= 0)
return NULL;
@@ -132,43 +132,43 @@ uc_fs_read_common(uc_vm *vm, size_t nargs, const char *type)
err_return(EINVAL);
}
- rv = json_object_new_string_len(p, len);
+ rv = ucv_string_new_length(p, len);
free(p);
return rv;
}
-static json_object *
+static uc_value_t *
uc_fs_write_common(uc_vm *vm, size_t nargs, const char *type)
{
- json_object *data = uc_get_arg(0);
+ uc_value_t *data = uc_get_arg(0);
size_t len, wsize;
- const char *str;
+ char *str;
FILE **fp = uc_get_self(type);
if (!fp || !*fp)
err_return(EBADF);
- if (json_object_is_type(data, json_type_string)) {
- str = json_object_get_string(data);
- len = json_object_get_string_len(data);
+ if (ucv_type(data) == UC_STRING) {
+ len = ucv_string_length(data);
+ wsize = fwrite(ucv_string_get(data), 1, len, *fp);
}
else {
- str = json_object_to_json_string(data);
+ str = ucv_to_jsonstring(vm, data);
len = str ? strlen(str) : 0;
+ wsize = fwrite(str, 1, len, *fp);
+ free(str);
}
- wsize = fwrite(str, 1, len, *fp);
-
if (wsize < len && ferror(*fp))
err_return(errno);
- return json_object_new_int64(wsize);
+ return ucv_int64_new(wsize);
}
-static json_object *
+static uc_value_t *
uc_fs_pclose(uc_vm *vm, size_t nargs)
{
FILE **fp = uc_get_self("fs.proc");
@@ -184,38 +184,38 @@ uc_fs_pclose(uc_vm *vm, size_t nargs)
err_return(errno);
if (WIFEXITED(rc))
- return xjs_new_int64(WEXITSTATUS(rc));
+ return ucv_int64_new(WEXITSTATUS(rc));
if (WIFSIGNALED(rc))
- return xjs_new_int64(-WTERMSIG(rc));
+ return ucv_int64_new(-WTERMSIG(rc));
- return xjs_new_int64(0);
+ return ucv_int64_new(0);
}
-static json_object *
+static uc_value_t *
uc_fs_pread(uc_vm *vm, size_t nargs)
{
return uc_fs_read_common(vm, nargs, "fs.proc");
}
-static json_object *
+static uc_value_t *
uc_fs_pwrite(uc_vm *vm, size_t nargs)
{
return uc_fs_write_common(vm, nargs, "fs.proc");
}
-static json_object *
+static uc_value_t *
uc_fs_popen(uc_vm *vm, size_t nargs)
{
- json_object *comm = uc_get_arg(0);
- json_object *mode = uc_get_arg(1);
+ uc_value_t *comm = uc_get_arg(0);
+ uc_value_t *mode = uc_get_arg(1);
FILE *fp;
- if (!json_object_is_type(comm, json_type_string))
+ if (ucv_type(comm) != UC_STRING)
err_return(EINVAL);
- fp = popen(json_object_get_string(comm),
- json_object_is_type(mode, json_type_string) ? json_object_get_string(mode) : "r");
+ fp = popen(ucv_string_get(comm),
+ ucv_type(mode) == UC_STRING ? ucv_string_get(mode) : "r");
if (!fp)
err_return(errno);
@@ -224,7 +224,7 @@ uc_fs_popen(uc_vm *vm, size_t nargs)
}
-static json_object *
+static uc_value_t *
uc_fs_close(uc_vm *vm, size_t nargs)
{
FILE **fp = uc_get_self("fs.file");
@@ -235,26 +235,26 @@ uc_fs_close(uc_vm *vm, size_t nargs)
fclose(*fp);
*fp = NULL;
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_read(uc_vm *vm, size_t nargs)
{
return uc_fs_read_common(vm, nargs, "fs.file");
}
-static json_object *
+static uc_value_t *
uc_fs_write(uc_vm *vm, size_t nargs)
{
return uc_fs_write_common(vm, nargs, "fs.file");
}
-static json_object *
+static uc_value_t *
uc_fs_seek(uc_vm *vm, size_t nargs)
{
- json_object *ofs = uc_get_arg(0);
- json_object *how = uc_get_arg(1);
+ uc_value_t *ofs = uc_get_arg(0);
+ uc_value_t *how = uc_get_arg(1);
int whence, res;
long offset;
@@ -265,27 +265,27 @@ uc_fs_seek(uc_vm *vm, size_t nargs)
if (!ofs)
offset = 0;
- else if (!json_object_is_type(ofs, json_type_int))
+ else if (ucv_type(ofs) != UC_INTEGER)
err_return(EINVAL);
else
- offset = (long)json_object_get_int64(ofs);
+ offset = (long)ucv_int64_get(ofs);
if (!how)
whence = 0;
- else if (!json_object_is_type(how, json_type_int))
+ else if (ucv_type(how) != UC_INTEGER)
err_return(EINVAL);
else
- whence = (int)json_object_get_int64(how);
+ whence = (int)ucv_int64_get(how);
res = fseek(*fp, offset, whence);
if (res < 0)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_tell(uc_vm *vm, size_t nargs)
{
long offset;
@@ -300,21 +300,21 @@ uc_fs_tell(uc_vm *vm, size_t nargs)
if (offset < 0)
err_return(errno);
- return json_object_new_int64(offset);
+ return ucv_int64_new(offset);
}
-static json_object *
+static uc_value_t *
uc_fs_open(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
- json_object *mode = uc_get_arg(1);
+ uc_value_t *path = uc_get_arg(0);
+ uc_value_t *mode = uc_get_arg(1);
FILE *fp;
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- fp = fopen(json_object_get_string(path),
- json_object_is_type(mode, json_type_string) ? json_object_get_string(mode) : "r");
+ fp = fopen(ucv_string_get(path),
+ ucv_type(mode) == UC_STRING ? ucv_string_get(mode) : "r");
if (!fp)
err_return(errno);
@@ -323,7 +323,7 @@ uc_fs_open(uc_vm *vm, size_t nargs)
}
-static json_object *
+static uc_value_t *
uc_fs_readdir(uc_vm *vm, size_t nargs)
{
DIR **dp = uc_get_self("fs.dir");
@@ -338,10 +338,10 @@ uc_fs_readdir(uc_vm *vm, size_t nargs)
if (!e)
err_return(errno);
- return json_object_new_string(e->d_name);
+ return ucv_string_new(e->d_name);
}
-static json_object *
+static uc_value_t *
uc_fs_telldir(uc_vm *vm, size_t nargs)
{
DIR **dp = uc_get_self("fs.dir");
@@ -355,30 +355,30 @@ uc_fs_telldir(uc_vm *vm, size_t nargs)
if (position == -1)
err_return(errno);
- return json_object_new_int64((int64_t)position);
+ return ucv_int64_new((int64_t)position);
}
-static json_object *
+static uc_value_t *
uc_fs_seekdir(uc_vm *vm, size_t nargs)
{
- json_object *ofs = uc_get_arg(0);
+ uc_value_t *ofs = uc_get_arg(0);
DIR **dp = uc_get_self("fs.dir");
long position;
- if (!json_object_is_type(ofs, json_type_int))
+ if (ucv_type(ofs) != UC_INTEGER)
err_return(EINVAL);
if (!dp || !*dp)
err_return(EBADF);
- position = (long)json_object_get_int64(ofs);
+ position = (long)ucv_int64_get(ofs);
seekdir(*dp, position);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_closedir(uc_vm *vm, size_t nargs)
{
DIR **dp = uc_get_self("fs.dir");
@@ -389,19 +389,19 @@ uc_fs_closedir(uc_vm *vm, size_t nargs)
closedir(*dp);
*dp = NULL;
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_opendir(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
+ uc_value_t *path = uc_get_arg(0);
DIR *dp;
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- dp = opendir(json_object_get_string(path));
+ dp = opendir(ucv_string_get(path));
if (!dp)
err_return(errno);
@@ -409,15 +409,15 @@ uc_fs_opendir(uc_vm *vm, size_t nargs)
return uc_alloc_ressource(dir_type, dp);
}
-static json_object *
+static uc_value_t *
uc_fs_readlink(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
- json_object *res;
+ uc_value_t *path = uc_get_arg(0);
+ uc_value_t *res;
ssize_t buflen = 0, rv;
char *buf = NULL, *tmp;
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
do {
@@ -430,7 +430,7 @@ uc_fs_readlink(uc_vm *vm, size_t nargs)
}
buf = tmp;
- rv = readlink(json_object_get_string(path), buf, buflen);
+ rv = readlink(ucv_string_get(path), buf, buflen);
if (rv == -1) {
free(buf);
@@ -442,173 +442,173 @@ uc_fs_readlink(uc_vm *vm, size_t nargs)
}
while (true);
- res = json_object_new_string_len(buf, rv);
+ res = ucv_string_new_length(buf, rv);
free(buf);
return res;
}
-static json_object *
+static uc_value_t *
uc_fs_stat_common(uc_vm *vm, size_t nargs, bool use_lstat)
{
- json_object *path = uc_get_arg(0);
- json_object *res, *o;
+ uc_value_t *path = uc_get_arg(0);
+ uc_value_t *res, *o;
struct stat st;
int rv;
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- rv = (use_lstat ? lstat : stat)(json_object_get_string(path), &st);
+ rv = (use_lstat ? lstat : stat)(ucv_string_get(path), &st);
if (rv == -1)
err_return(errno);
- res = json_object_new_object();
+ res = ucv_object_new(vm);
if (!res)
err_return(ENOMEM);
- o = json_object_new_object();
+ o = ucv_object_new(vm);
if (o) {
- json_object_object_add(o, "major", json_object_new_int64(major(st.st_dev)));
- json_object_object_add(o, "minor", json_object_new_int64(minor(st.st_dev)));
+ ucv_object_add(o, "major", ucv_int64_new(major(st.st_dev)));
+ ucv_object_add(o, "minor", ucv_int64_new(minor(st.st_dev)));
- json_object_object_add(res, "dev", o);
+ ucv_object_add(res, "dev", o);
}
- o = json_object_new_object();
+ o = ucv_object_new(vm);
if (o) {
- json_object_object_add(o, "setuid", json_object_new_boolean(st.st_mode & S_ISUID));
- json_object_object_add(o, "setgid", json_object_new_boolean(st.st_mode & S_ISGID));
- json_object_object_add(o, "sticky", json_object_new_boolean(st.st_mode & S_ISVTX));
+ ucv_object_add(o, "setuid", ucv_boolean_new(st.st_mode & S_ISUID));
+ ucv_object_add(o, "setgid", ucv_boolean_new(st.st_mode & S_ISGID));
+ ucv_object_add(o, "sticky", ucv_boolean_new(st.st_mode & S_ISVTX));
- json_object_object_add(o, "user_read", json_object_new_boolean(st.st_mode & S_IRUSR));
- json_object_object_add(o, "user_write", json_object_new_boolean(st.st_mode & S_IWUSR));
- json_object_object_add(o, "user_exec", json_object_new_boolean(st.st_mode & S_IXUSR));
+ ucv_object_add(o, "user_read", ucv_boolean_new(st.st_mode & S_IRUSR));
+ ucv_object_add(o, "user_write", ucv_boolean_new(st.st_mode & S_IWUSR));
+ ucv_object_add(o, "user_exec", ucv_boolean_new(st.st_mode & S_IXUSR));
- json_object_object_add(o, "group_read", json_object_new_boolean(st.st_mode & S_IRGRP));
- json_object_object_add(o, "group_write", json_object_new_boolean(st.st_mode & S_IWGRP));
- json_object_object_add(o, "group_exec", json_object_new_boolean(st.st_mode & S_IXGRP));
+ ucv_object_add(o, "group_read", ucv_boolean_new(st.st_mode & S_IRGRP));
+ ucv_object_add(o, "group_write", ucv_boolean_new(st.st_mode & S_IWGRP));
+ ucv_object_add(o, "group_exec", ucv_boolean_new(st.st_mode & S_IXGRP));
- json_object_object_add(o, "other_read", json_object_new_boolean(st.st_mode & S_IROTH));
- json_object_object_add(o, "other_write", json_object_new_boolean(st.st_mode & S_IWOTH));
- json_object_object_add(o, "other_exec", json_object_new_boolean(st.st_mode & S_IXOTH));
+ ucv_object_add(o, "other_read", ucv_boolean_new(st.st_mode & S_IROTH));
+ ucv_object_add(o, "other_write", ucv_boolean_new(st.st_mode & S_IWOTH));
+ ucv_object_add(o, "other_exec", ucv_boolean_new(st.st_mode & S_IXOTH));
- json_object_object_add(res, "perm", o);
+ ucv_object_add(res, "perm", o);
}
- json_object_object_add(res, "inode", json_object_new_int64((int64_t)st.st_ino));
- json_object_object_add(res, "mode", json_object_new_int64((int64_t)st.st_mode & ~S_IFMT));
- json_object_object_add(res, "nlink", json_object_new_int64((int64_t)st.st_nlink));
- json_object_object_add(res, "uid", json_object_new_int64((int64_t)st.st_uid));
- json_object_object_add(res, "gid", json_object_new_int64((int64_t)st.st_gid));
- json_object_object_add(res, "size", json_object_new_int64((int64_t)st.st_size));
- json_object_object_add(res, "blksize", json_object_new_int64((int64_t)st.st_blksize));
- json_object_object_add(res, "blocks", json_object_new_int64((int64_t)st.st_blocks));
- json_object_object_add(res, "atime", json_object_new_int64((int64_t)st.st_atime));
- json_object_object_add(res, "mtime", json_object_new_int64((int64_t)st.st_mtime));
- json_object_object_add(res, "ctime", json_object_new_int64((int64_t)st.st_ctime));
+ ucv_object_add(res, "inode", ucv_int64_new((int64_t)st.st_ino));
+ ucv_object_add(res, "mode", ucv_int64_new((int64_t)st.st_mode & ~S_IFMT));
+ ucv_object_add(res, "nlink", ucv_int64_new((int64_t)st.st_nlink));
+ ucv_object_add(res, "uid", ucv_int64_new((int64_t)st.st_uid));
+ ucv_object_add(res, "gid", ucv_int64_new((int64_t)st.st_gid));
+ ucv_object_add(res, "size", ucv_int64_new((int64_t)st.st_size));
+ ucv_object_add(res, "blksize", ucv_int64_new((int64_t)st.st_blksize));
+ ucv_object_add(res, "blocks", ucv_int64_new((int64_t)st.st_blocks));
+ ucv_object_add(res, "atime", ucv_int64_new((int64_t)st.st_atime));
+ ucv_object_add(res, "mtime", ucv_int64_new((int64_t)st.st_mtime));
+ ucv_object_add(res, "ctime", ucv_int64_new((int64_t)st.st_ctime));
if (S_ISREG(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("file"));
+ ucv_object_add(res, "type", ucv_string_new("file"));
else if (S_ISDIR(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("directory"));
+ ucv_object_add(res, "type", ucv_string_new("directory"));
else if (S_ISCHR(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("char"));
+ ucv_object_add(res, "type", ucv_string_new("char"));
else if (S_ISBLK(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("block"));
+ ucv_object_add(res, "type", ucv_string_new("block"));
else if (S_ISFIFO(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("fifo"));
+ ucv_object_add(res, "type", ucv_string_new("fifo"));
else if (S_ISLNK(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("link"));
+ ucv_object_add(res, "type", ucv_string_new("link"));
else if (S_ISSOCK(st.st_mode))
- json_object_object_add(res, "type", json_object_new_string("socket"));
+ ucv_object_add(res, "type", ucv_string_new("socket"));
else
- json_object_object_add(res, "type", json_object_new_string("unknown"));
+ ucv_object_add(res, "type", ucv_string_new("unknown"));
return res;
}
-static json_object *
+static uc_value_t *
uc_fs_stat(uc_vm *vm, size_t nargs)
{
return uc_fs_stat_common(vm, nargs, false);
}
-static json_object *
+static uc_value_t *
uc_fs_lstat(uc_vm *vm, size_t nargs)
{
return uc_fs_stat_common(vm, nargs, true);
}
-static json_object *
+static uc_value_t *
uc_fs_mkdir(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
- json_object *mode = uc_get_arg(1);
+ uc_value_t *path = uc_get_arg(0);
+ uc_value_t *mode = uc_get_arg(1);
- if (!json_object_is_type(path, json_type_string) ||
- (mode && !json_object_is_type(mode, json_type_int)))
+ if (ucv_type(path) != UC_STRING ||
+ (mode && ucv_type(mode) != UC_INTEGER))
err_return(EINVAL);
- if (mkdir(json_object_get_string(path), (mode_t)(mode ? json_object_get_int64(mode) : 0777)) == -1)
+ if (mkdir(ucv_string_get(path), (mode_t)(mode ? ucv_int64_get(mode) : 0777)) == -1)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_rmdir(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
+ uc_value_t *path = uc_get_arg(0);
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- if (rmdir(json_object_get_string(path)) == -1)
+ if (rmdir(ucv_string_get(path)) == -1)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_symlink(uc_vm *vm, size_t nargs)
{
- json_object *dest = uc_get_arg(0);
- json_object *path = uc_get_arg(1);
+ uc_value_t *dest = uc_get_arg(0);
+ uc_value_t *path = uc_get_arg(1);
- if (!json_object_is_type(dest, json_type_string) ||
- !json_object_is_type(path, json_type_string))
+ if (ucv_type(dest) != UC_STRING ||
+ ucv_type(path) != UC_STRING)
err_return(EINVAL);
- if (symlink(json_object_get_string(dest), json_object_get_string(path)) == -1)
+ if (symlink(ucv_string_get(dest), ucv_string_get(path)) == -1)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_unlink(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
+ uc_value_t *path = uc_get_arg(0);
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- if (unlink(json_object_get_string(path)) == -1)
+ if (unlink(ucv_string_get(path)) == -1)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_fs_getcwd(uc_vm *vm, size_t nargs)
{
- json_object *res;
+ uc_value_t *res;
char *buf = NULL, *tmp;
size_t buflen = 0;
@@ -629,29 +629,30 @@ uc_fs_getcwd(uc_vm *vm, size_t nargs)
if (errno == ERANGE)
continue;
+ free(buf);
err_return(errno);
}
while (true);
- res = json_object_new_string(buf);
+ res = ucv_string_new(buf);
free(buf);
return res;
}
-static json_object *
+static uc_value_t *
uc_fs_chdir(uc_vm *vm, size_t nargs)
{
- json_object *path = uc_get_arg(0);
+ uc_value_t *path = uc_get_arg(0);
- if (!json_object_is_type(path, json_type_string))
+ if (ucv_type(path) != UC_STRING)
err_return(EINVAL);
- if (chdir(json_object_get_string(path)) == -1)
+ if (chdir(ucv_string_get(path)) == -1)
err_return(errno);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
static const uc_cfunction_list proc_fns[] = {
@@ -719,7 +720,7 @@ static void close_dir(void *ud)
closedir(dp);
}
-void uc_module_init(uc_prototype *scope)
+void uc_module_init(uc_value_t *scope)
{
uc_add_proto_functions(scope, global_fns);
@@ -727,7 +728,7 @@ void uc_module_init(uc_prototype *scope)
file_type = uc_declare_type("fs.file", file_fns, close_file);
dir_type = uc_declare_type("fs.dir", dir_fns, close_dir);
- uc_add_proto_val(scope, "stdin", uc_alloc_ressource(file_type, stdin));
- uc_add_proto_val(scope, "stdout", uc_alloc_ressource(file_type, stdout));
- uc_add_proto_val(scope, "stderr", uc_alloc_ressource(file_type, stderr));
+ 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));
}
diff --git a/lib/math.c b/lib/math.c
index 99f3fbc..8f8466e 100644
--- a/lib/math.c
+++ b/lib/math.c
@@ -21,105 +21,105 @@
static bool srand_called = false;
-static json_object *
+static uc_value_t *
uc_abs(uc_vm *vm, size_t nargs)
{
- json_object *v = uc_get_arg(0);
- enum json_type t;
+ uc_value_t *v = uc_get_arg(0);
+ uc_type_t t;
int64_t n;
double d;
- if (json_object_is_type(v, json_type_null))
- return uc_alloc_double(NAN);
+ if (ucv_type(v) == UC_NULL)
+ return ucv_double_new(NAN);
t = uc_to_number(v, &n, &d);
- if (t == json_type_double)
- return (isnan(d) || d < 0) ? uc_alloc_double(-d) : json_object_get(v);
+ if (t == UC_DOUBLE)
+ return (isnan(d) || d < 0) ? ucv_double_new(-d) : ucv_get(v);
- return (n < 0) ? json_object_new_int64(-n) : json_object_get(v);
+ return (n < 0) ? ucv_int64_new(-n) : ucv_get(v);
}
-static json_object *
+static uc_value_t *
uc_atan2(uc_vm *vm, size_t nargs)
{
double d1 = uc_to_double(uc_get_arg(0));
double d2 = uc_to_double(uc_get_arg(1));
if (isnan(d1) || isnan(d2))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(atan2(d1, d2));
+ return ucv_double_new(atan2(d1, d2));
}
-static json_object *
+static uc_value_t *
uc_cos(uc_vm *vm, size_t nargs)
{
double d = uc_to_double(uc_get_arg(0));
if (isnan(d))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(cos(d));
+ return ucv_double_new(cos(d));
}
-static json_object *
+static uc_value_t *
uc_exp(uc_vm *vm, size_t nargs)
{
double d = uc_to_double(uc_get_arg(0));
if (isnan(d))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(exp(d));
+ return ucv_double_new(exp(d));
}
-static json_object *
+static uc_value_t *
uc_log(uc_vm *vm, size_t nargs)
{
double d = uc_to_double(uc_get_arg(0));
if (isnan(d))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(log(d));
+ return ucv_double_new(log(d));
}
-static json_object *
+static uc_value_t *
uc_sin(uc_vm *vm, size_t nargs)
{
double d = uc_to_double(uc_get_arg(0));
if (isnan(d))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(sin(d));
+ return ucv_double_new(sin(d));
}
-static json_object *
+static uc_value_t *
uc_sqrt(uc_vm *vm, size_t nargs)
{
double d = uc_to_double(uc_get_arg(0));
if (isnan(d))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(sqrt(d));
+ return ucv_double_new(sqrt(d));
}
-static json_object *
+static uc_value_t *
uc_pow(uc_vm *vm, size_t nargs)
{
double x = uc_to_double(uc_get_arg(0));
double y = uc_to_double(uc_get_arg(1));
if (isnan(x) || isnan(y))
- return uc_alloc_double(NAN);
+ return ucv_double_new(NAN);
- return uc_alloc_double(pow(x, y));
+ return ucv_double_new(pow(x, y));
}
-static json_object *
+static uc_value_t *
uc_rand(uc_vm *vm, size_t nargs)
{
struct timeval tv;
@@ -131,10 +131,10 @@ uc_rand(uc_vm *vm, size_t nargs)
srand_called = true;
}
- return json_object_new_int64(rand());
+ return ucv_int64_new(rand());
}
-static json_object *
+static uc_value_t *
uc_srand(uc_vm *vm, size_t nargs)
{
int64_t n = uc_to_int64(uc_get_arg(0));
@@ -158,7 +158,7 @@ static const uc_cfunction_list math_fns[] = {
{ "srand", uc_srand },
};
-void uc_module_init(uc_prototype *scope)
+void uc_module_init(uc_value_t *scope)
{
uc_add_proto_functions(scope, math_fns);
}
diff --git a/lib/ubus.c b/lib/ubus.c
index 47f22d3..4d74710 100644
--- a/lib/ubus.c
+++ b/lib/ubus.c
@@ -24,7 +24,7 @@
#define err_return(err) do { last_error = err; return NULL; } while(0)
static enum ubus_msg_status last_error = 0;
-static uc_ressource_type *conn_type;
+static uc_ressource_type_t *conn_type;
typedef struct {
int timeout;
@@ -32,28 +32,28 @@ typedef struct {
struct ubus_context *ctx;
} ubus_connection;
-static json_object *
+static uc_value_t *
uc_ubus_error(uc_vm *vm, size_t nargs)
{
- json_object *errmsg;
+ uc_value_t *errmsg;
if (last_error == 0)
return NULL;
- errmsg = json_object_new_string(ubus_strerror(last_error));
+ errmsg = ucv_string_new(ubus_strerror(last_error));
last_error = 0;
return errmsg;
}
-static json_object *
-uc_blob_to_json(struct blob_attr *attr, bool table, const char **name);
+static uc_value_t *
+uc_blob_to_json(uc_vm *vm, struct blob_attr *attr, bool table, const char **name);
-static json_object *
-uc_blob_array_to_json(struct blob_attr *attr, size_t len, bool table)
+static uc_value_t *
+uc_blob_array_to_json(uc_vm *vm, struct blob_attr *attr, size_t len, bool table)
{
- json_object *o = table ? json_object_new_object() : json_object_new_array();
- json_object *v;
+ uc_value_t *o = table ? ucv_object_new(vm) : ucv_array_new(vm);
+ uc_value_t *v;
struct blob_attr *pos;
size_t rem = len;
const char *name;
@@ -63,21 +63,21 @@ uc_blob_array_to_json(struct blob_attr *attr, size_t len, bool table)
__blob_for_each_attr(pos, attr, rem) {
name = NULL;
- v = uc_blob_to_json(pos, table, &name);
+ v = uc_blob_to_json(vm, pos, table, &name);
if (table && name)
- json_object_object_add(o, name, v);
+ ucv_object_add(o, name, v);
else if (!table)
- json_object_array_add(o, v);
+ ucv_array_push(o, v);
else
- json_object_put(v);
+ ucv_put(v);
}
return o;
}
-static json_object *
-uc_blob_to_json(struct blob_attr *attr, bool table, const char **name)
+static uc_value_t *
+uc_blob_to_json(uc_vm *vm, struct blob_attr *attr, bool table, const char **name)
{
void *data;
int len;
@@ -93,16 +93,16 @@ uc_blob_to_json(struct blob_attr *attr, bool table, const char **name)
switch (blob_id(attr)) {
case BLOBMSG_TYPE_BOOL:
- return json_object_new_boolean(*(uint8_t *)data);
+ return ucv_boolean_new(*(uint8_t *)data);
case BLOBMSG_TYPE_INT16:
- return json_object_new_int64((int64_t)be16_to_cpu(*(uint16_t *)data));
+ return ucv_int64_new((int64_t)be16_to_cpu(*(uint16_t *)data));
case BLOBMSG_TYPE_INT32:
- return json_object_new_int64((int64_t)be32_to_cpu(*(uint32_t *)data));
+ return ucv_int64_new((int64_t)be32_to_cpu(*(uint32_t *)data));
case BLOBMSG_TYPE_INT64:
- return json_object_new_uint64(be64_to_cpu(*(uint64_t *)data));
+ return ucv_uint64_new(be64_to_cpu(*(uint64_t *)data));
case BLOBMSG_TYPE_DOUBLE:
;
@@ -113,16 +113,16 @@ uc_blob_to_json(struct blob_attr *attr, bool table, const char **name)
v.u64 = be64_to_cpu(*(uint64_t *)data);
- return json_object_new_double(v.d);
+ return ucv_double_new(v.d);
case BLOBMSG_TYPE_STRING:
- return json_object_new_string(data);
+ return ucv_string_new(data);
case BLOBMSG_TYPE_ARRAY:
- return uc_blob_array_to_json(data, len, false);
+ return uc_blob_array_to_json(vm, data, len, false);
case BLOBMSG_TYPE_TABLE:
- return uc_blob_array_to_json(data, len, true);
+ return uc_blob_array_to_json(vm, data, len, true);
default:
return NULL;
@@ -130,16 +130,16 @@ uc_blob_to_json(struct blob_attr *attr, bool table, const char **name)
}
-static json_object *
+static uc_value_t *
uc_ubus_connect(uc_vm *vm, size_t nargs)
{
- json_object *socket = uc_get_arg(0);
- json_object *timeout = uc_get_arg(1);
- json_object *co;
+ uc_value_t *socket = uc_get_arg(0);
+ uc_value_t *timeout = uc_get_arg(1);
+ uc_value_t *co;
ubus_connection *c;
- if ((socket && !json_object_is_type(socket, json_type_string)) ||
- (timeout && !json_object_is_type(timeout, json_type_int)))
+ if ((socket && ucv_type(socket) != UC_STRING) ||
+ (timeout && ucv_type(timeout) != UC_INTEGER))
err_return(UBUS_STATUS_INVALID_ARGUMENT);
c = calloc(1, sizeof(*c));
@@ -147,8 +147,8 @@ uc_ubus_connect(uc_vm *vm, size_t nargs)
if (!c)
err_return(UBUS_STATUS_UNKNOWN_ERROR);
- c->ctx = ubus_connect(socket ? json_object_get_string(socket) : NULL);
- c->timeout = timeout ? json_object_get_int(timeout) : 30;
+ c->ctx = ubus_connect(socket ? ucv_string_get(socket) : NULL);
+ c->timeout = timeout ? ucv_int64_get(timeout) : 30;
if (!c->ctx) {
free(c);
@@ -158,7 +158,7 @@ uc_ubus_connect(uc_vm *vm, size_t nargs)
if (c->timeout < 0)
c->timeout = 30;
- co = json_object_new_object();
+ co = ucv_object_new(vm);
if (!co) {
ubus_free(c->ctx);
@@ -174,16 +174,16 @@ uc_ubus_connect(uc_vm *vm, size_t nargs)
static void
uc_ubus_signatures_cb(struct ubus_context *c, struct ubus_object_data *o, void *p)
{
- json_object *arr = p;
- json_object *sig;
+ uc_value_t *arr = p;
+ uc_value_t *sig;
if (!o->signature)
return;
- sig = uc_blob_array_to_json(blob_data(o->signature), blob_len(o->signature), true);
+ sig = uc_blob_array_to_json(NULL, blob_data(o->signature), blob_len(o->signature), true);
if (sig)
- json_object_array_add(arr, sig);
+ ucv_array_push(arr, sig);
}
static void
@@ -198,27 +198,27 @@ uc_ubus_objects_cb(struct ubus_context *c, struct ubus_object_data *o, void *p)
json_object_array_add(arr, obj);
}
-static json_object *
+static uc_value_t *
uc_ubus_list(uc_vm *vm, size_t nargs)
{
ubus_connection **c = uc_get_self("ubus.connection");
- json_object *objname = uc_get_arg(0);
- json_object *res = NULL;
+ uc_value_t *objname = uc_get_arg(0);
+ uc_value_t *res = NULL;
enum ubus_msg_status rv;
if (!c || !*c || !(*c)->ctx)
err_return(UBUS_STATUS_CONNECTION_FAILED);
- if (objname && !json_object_is_type(objname, json_type_string))
+ if (objname && ucv_type(objname) != UC_STRING)
err_return(UBUS_STATUS_INVALID_ARGUMENT);
- res = json_object_new_array();
+ res = ucv_array_new(vm);
if (!res)
err_return(UBUS_STATUS_UNKNOWN_ERROR);
rv = ubus_lookup((*c)->ctx,
- objname ? json_object_get_string(objname) : NULL,
+ objname ? ucv_string_get(objname) : NULL,
objname ? uc_ubus_signatures_cb : uc_ubus_objects_cb,
res);
@@ -231,41 +231,48 @@ uc_ubus_list(uc_vm *vm, size_t nargs)
static void
uc_ubus_call_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
- json_object **res = (json_object **)req->priv;
+ uc_value_t **res = (uc_value_t **)req->priv;
- *res = msg ? uc_blob_array_to_json(blob_data(msg), blob_len(msg), true) : NULL;
+ *res = msg ? uc_blob_array_to_json(NULL, blob_data(msg), blob_len(msg), true) : NULL;
}
-static json_object *
+static uc_value_t *
uc_ubus_call(uc_vm *vm, size_t nargs)
{
ubus_connection **c = uc_get_self("ubus.connection");
- json_object *objname = uc_get_arg(0);
- json_object *funname = uc_get_arg(1);
- json_object *funargs = uc_get_arg(2);
- json_object *res = NULL;
+ uc_value_t *objname = uc_get_arg(0);
+ uc_value_t *funname = uc_get_arg(1);
+ uc_value_t *funargs = uc_get_arg(2);
+ uc_value_t *res = NULL;
+ json_object *o;
enum ubus_msg_status rv;
uint32_t id;
if (!c || !*c || !(*c)->ctx)
err_return(UBUS_STATUS_CONNECTION_FAILED);
- if (!json_object_is_type(objname, json_type_string) ||
- !json_object_is_type(funname, json_type_string) ||
- (funargs && !json_object_is_type(funargs, json_type_object)))
+ if (ucv_type(objname) != UC_STRING ||
+ ucv_type(funname) != UC_STRING ||
+ (funargs && ucv_type(funargs) != UC_OBJECT))
err_return(UBUS_STATUS_INVALID_ARGUMENT);
blob_buf_init(&(*c)->buf, 0);
- if (funargs && !blobmsg_add_object(&(*c)->buf, funargs))
- err_return(UBUS_STATUS_UNKNOWN_ERROR);
+ if (funargs) {
+ o = ucv_to_json(funargs);
+ rv = blobmsg_add_object(&(*c)->buf, o);
+ json_object_put(o);
+
+ if (!rv)
+ err_return(UBUS_STATUS_UNKNOWN_ERROR);
+ }
- rv = ubus_lookup_id((*c)->ctx, json_object_get_string(objname), &id);
+ rv = ubus_lookup_id((*c)->ctx, ucv_string_get(objname), &id);
if (rv != UBUS_STATUS_OK)
err_return(rv);
- rv = ubus_invoke((*c)->ctx, id, json_object_get_string(funname), (*c)->buf.head,
+ rv = ubus_invoke((*c)->ctx, id, ucv_string_get(funname), (*c)->buf.head,
uc_ubus_call_cb, &res, (*c)->timeout * 1000);
if (rv != UBUS_STATUS_OK)
@@ -274,7 +281,7 @@ uc_ubus_call(uc_vm *vm, size_t nargs)
return res;
}
-static json_object *
+static uc_value_t *
uc_ubus_disconnect(uc_vm *vm, size_t nargs)
{
ubus_connection **c = uc_get_self("ubus.connection");
@@ -285,7 +292,7 @@ uc_ubus_disconnect(uc_vm *vm, size_t nargs)
ubus_free((*c)->ctx);
(*c)->ctx = NULL;
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
@@ -313,7 +320,7 @@ static void close_connection(void *ud) {
free(conn);
}
-void uc_module_init(uc_prototype *scope)
+void uc_module_init(uc_value_t *scope)
{
uc_add_proto_functions(scope, global_fns);
diff --git a/lib/uci.c b/lib/uci.c
index be98214..00a451c 100644
--- a/lib/uci.c
+++ b/lib/uci.c
@@ -22,7 +22,7 @@
#define err_return(err) do { last_error = err; return NULL; } while(0)
static int last_error = 0;
-static uc_ressource_type *cursor_type;
+static uc_ressource_type_t *cursor_type;
enum pkg_cmd {
CMD_SAVE,
@@ -30,11 +30,11 @@ enum pkg_cmd {
CMD_REVERT
};
-static json_object *
+static uc_value_t *
uc_uci_error(uc_vm *vm, size_t nargs)
{
char buf[sizeof("Unknown error: -9223372036854775808")];
- json_object *errmsg;
+ uc_value_t *errmsg;
const char *errstr[] = {
[UCI_ERR_MEM] = "Out of memory",
@@ -49,12 +49,12 @@ uc_uci_error(uc_vm *vm, size_t nargs)
if (last_error == 0)
return NULL;
- if (last_error >= 0 && last_error < ARRAY_SIZE(errstr)) {
- errmsg = json_object_new_string(errstr[last_error]);
+ if (last_error >= 0 && (unsigned)last_error < ARRAY_SIZE(errstr)) {
+ errmsg = ucv_string_new(errstr[last_error]);
}
else {
snprintf(buf, sizeof(buf), "Unknown error: %d", last_error);
- errmsg = json_object_new_string(buf);
+ errmsg = ucv_string_new(buf);
}
last_error = 0;
@@ -63,16 +63,16 @@ uc_uci_error(uc_vm *vm, size_t nargs)
}
-static json_object *
+static uc_value_t *
uc_uci_cursor(uc_vm *vm, size_t nargs)
{
- json_object *cdir = uc_get_arg(0);
- json_object *sdir = uc_get_arg(1);
+ uc_value_t *cdir = uc_get_arg(0);
+ uc_value_t *sdir = uc_get_arg(1);
struct uci_context *c;
int rv;
- if ((cdir && !json_object_is_type(cdir, json_type_string)) ||
- (sdir && !json_object_is_type(sdir, json_type_string)))
+ if ((cdir && ucv_type(cdir) != UC_STRING) ||
+ (sdir && ucv_type(sdir) != UC_STRING))
err_return(UCI_ERR_INVAL);
c = uci_alloc_context();
@@ -81,14 +81,14 @@ uc_uci_cursor(uc_vm *vm, size_t nargs)
err_return(UCI_ERR_MEM);
if (cdir) {
- rv = uci_set_confdir(c, json_object_get_string(cdir));
+ rv = uci_set_confdir(c, ucv_string_get(cdir));
if (rv)
err_return(rv);
}
if (sdir) {
- rv = uci_set_savedir(c, json_object_get_string(sdir));
+ rv = uci_set_savedir(c, ucv_string_get(sdir));
if (rv)
err_return(rv);
@@ -98,54 +98,57 @@ uc_uci_cursor(uc_vm *vm, size_t nargs)
}
-static json_object *
+static uc_value_t *
uc_uci_load(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
+ uc_value_t *conf = uc_get_arg(0);
struct uci_element *e;
+ char *s;
if (!c || !*c)
err_return(UCI_ERR_INVAL);
- if (!json_object_is_type(conf, json_type_string))
+ if (ucv_type(conf) != UC_STRING)
err_return(UCI_ERR_INVAL);
+ s = ucv_string_get(conf);
+
uci_foreach_element(&(*c)->root, e) {
- if (!strcmp(e->name, json_object_get_string(conf))) {
+ if (!strcmp(e->name, s)) {
uci_unload(*c, uci_to_package(e));
break;
}
}
- if (uci_load(*c, json_object_get_string(conf), NULL))
+ if (uci_load(*c, s, NULL))
err_return((*c)->err);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_unload(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
+ uc_value_t *conf = uc_get_arg(0);
struct uci_element *e;
if (!c || !*c)
err_return(UCI_ERR_INVAL);
- if (!json_object_is_type(conf, json_type_string))
+ if (ucv_type(conf) != UC_STRING)
err_return(UCI_ERR_INVAL);
uci_foreach_element(&(*c)->root, e) {
- if (!strcmp(e->name, json_object_get_string(conf))) {
+ if (!strcmp(e->name, ucv_string_get(conf))) {
uci_unload(*c, uci_to_package(e));
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
}
- return json_object_new_boolean(false);
+ return ucv_boolean_new(false);
}
static int
@@ -177,22 +180,22 @@ lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, bool extended)
return uci_lookup_ptr(ctx, ptr, NULL, extended);
}
-static json_object *
-option_to_json(struct uci_option *o)
+static uc_value_t *
+option_to_uval(uc_vm *vm, struct uci_option *o)
{
- json_object *arr;
struct uci_element *e;
+ uc_value_t *arr;
switch (o->type) {
case UCI_TYPE_STRING:
- return json_object_new_string(o->v.string);
+ return ucv_string_new(o->v.string);
case UCI_TYPE_LIST:
- arr = json_object_new_array();
+ arr = ucv_array_new(vm);
if (arr)
uci_foreach_element(&o->v.list, e)
- json_object_array_add(arr, json_object_new_string(e->name));
+ ucv_array_push(arr, ucv_string_new(e->name));
return arr;
@@ -201,36 +204,36 @@ option_to_json(struct uci_option *o)
}
}
-static json_object *
-section_to_json(struct uci_section *s, int index)
+static uc_value_t *
+section_to_uval(uc_vm *vm, struct uci_section *s, int index)
{
- json_object *so = json_object_new_object();
+ uc_value_t *so = ucv_object_new(vm);
struct uci_element *e;
struct uci_option *o;
if (!so)
return NULL;
- json_object_object_add(so, ".anonymous", json_object_new_boolean(s->anonymous));
- json_object_object_add(so, ".type", json_object_new_string(s->type));
- json_object_object_add(so, ".name", json_object_new_string(s->e.name));
+ ucv_object_add(so, ".anonymous", ucv_boolean_new(s->anonymous));
+ ucv_object_add(so, ".type", ucv_string_new(s->type));
+ ucv_object_add(so, ".name", ucv_string_new(s->e.name));
if (index >= 0)
- json_object_object_add(so, ".index", json_object_new_int64(index));
+ ucv_object_add(so, ".index", ucv_int64_new(index));
uci_foreach_element(&s->options, e) {
o = uci_to_option(e);
- json_object_object_add(so, o->e.name, option_to_json(o));
+ ucv_object_add(so, o->e.name, option_to_uval(vm, o));
}
return so;
}
-static json_object *
-package_to_json(struct uci_package *p)
+static uc_value_t *
+package_to_uval(uc_vm *vm, struct uci_package *p)
{
- json_object *po = json_object_new_object();
- json_object *so;
+ uc_value_t *po = ucv_object_new(vm);
+ uc_value_t *so;
struct uci_element *e;
int i = 0;
@@ -238,37 +241,37 @@ package_to_json(struct uci_package *p)
return NULL;
uci_foreach_element(&p->sections, e) {
- so = section_to_json(uci_to_section(e), i++);
- json_object_object_add(po, e->name, so);
+ so = section_to_uval(vm, uci_to_section(e), i++);
+ ucv_object_add(po, e->name, so);
}
return po;
}
-static json_object *
+static uc_value_t *
uc_uci_get_any(uc_vm *vm, size_t nargs, bool all)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *sect = uc_get_arg(1);
- json_object *opt = uc_get_arg(2);
- struct uci_ptr ptr = {};
+ 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_ptr ptr = { 0 };
int rv;
if (!c || !*c)
err_return(UCI_ERR_INVAL);
- if (!json_object_is_type(conf, json_type_string) ||
- (sect && !json_object_is_type(sect, json_type_string)) ||
- (opt && !json_object_is_type(opt, json_type_string)))
+ if ((ucv_type(conf) != UC_STRING) ||
+ (sect && ucv_type(sect) != UC_STRING) ||
+ (opt && ucv_type(opt) != UC_STRING))
err_return(UCI_ERR_INVAL);
if ((!sect && !all) || (opt && all))
err_return(UCI_ERR_INVAL);
- ptr.package = json_object_get_string(conf);
- ptr.section = sect ? json_object_get_string(sect) : NULL;
- ptr.option = opt ? json_object_get_string(opt) : NULL;
+ ptr.package = ucv_string_get(conf);
+ ptr.section = sect ? ucv_string_get(sect) : NULL;
+ ptr.option = opt ? ucv_string_get(opt) : NULL;
rv = lookup_ptr(*c, &ptr, true);
@@ -283,60 +286,60 @@ uc_uci_get_any(uc_vm *vm, size_t nargs, bool all)
if (!ptr.s)
err_return(UCI_ERR_NOTFOUND);
- return section_to_json(ptr.s, -1);
+ return section_to_uval(vm, ptr.s, -1);
}
if (!ptr.p)
err_return(UCI_ERR_NOTFOUND);
- return package_to_json(ptr.p);
+ return package_to_uval(vm, ptr.p);
}
if (ptr.option) {
if (!ptr.o)
err_return(UCI_ERR_NOTFOUND);
- return option_to_json(ptr.o);
+ return option_to_uval(vm, ptr.o);
}
if (!ptr.s)
err_return(UCI_ERR_NOTFOUND);
- return json_object_new_string(ptr.s->type);
+ return ucv_string_new(ptr.s->type);
}
-static json_object *
+static uc_value_t *
uc_uci_get(uc_vm *vm, size_t nargs)
{
return uc_uci_get_any(vm, nargs, false);
}
-static json_object *
+static uc_value_t *
uc_uci_get_all(uc_vm *vm, size_t nargs)
{
return uc_uci_get_any(vm, nargs, true);
}
-static json_object *
+static uc_value_t *
uc_uci_get_first(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *type = uc_get_arg(1);
- json_object *opt = uc_get_arg(2);
+ 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_package *p = NULL;
struct uci_section *sc;
struct uci_element *e;
- struct uci_ptr ptr = {};
+ struct uci_ptr ptr = { 0 };
int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(type, json_type_string) ||
- (opt && !json_object_is_type(opt, json_type_string)))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(type) != UC_STRING ||
+ (opt && ucv_type(opt) != UC_STRING))
err_return(UCI_ERR_INVAL);
uci_foreach_element(&(*c)->root, e) {
- if (strcmp(e->name, json_object_get_string(conf)))
+ if (strcmp(e->name, ucv_string_get(conf)))
continue;
p = uci_to_package(e);
@@ -349,15 +352,15 @@ uc_uci_get_first(uc_vm *vm, size_t nargs)
uci_foreach_element(&p->sections, e) {
sc = uci_to_section(e);
- if (strcmp(sc->type, json_object_get_string(type)))
+ if (strcmp(sc->type, ucv_string_get(type)))
continue;
if (!opt)
- return json_object_new_string(sc->e.name);
+ return ucv_string_new(sc->e.name);
- ptr.package = json_object_get_string(conf);
+ ptr.package = ucv_string_get(conf);
ptr.section = sc->e.name;
- ptr.option = json_object_get_string(opt);
+ ptr.option = ucv_string_get(opt);
ptr.p = p;
ptr.s = sc;
@@ -369,29 +372,29 @@ uc_uci_get_first(uc_vm *vm, size_t nargs)
if (!(ptr.flags & UCI_LOOKUP_COMPLETE))
err_return(UCI_ERR_NOTFOUND);
- return option_to_json(ptr.o);
+ return option_to_uval(vm, ptr.o);
}
err_return(UCI_ERR_NOTFOUND);
}
-static json_object *
+static uc_value_t *
uc_uci_add(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *type = uc_get_arg(1);
+ uc_value_t *conf = uc_get_arg(0);
+ uc_value_t *type = uc_get_arg(1);
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *sc = NULL;
int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(type, json_type_string))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(type) != UC_STRING)
err_return(UCI_ERR_INVAL);
uci_foreach_element(&(*c)->root, e) {
- if (!strcmp(e->name, json_object_get_string(conf))) {
+ if (!strcmp(e->name, ucv_string_get(conf))) {
p = uci_to_package(e);
break;
}
@@ -400,73 +403,75 @@ uc_uci_add(uc_vm *vm, size_t nargs)
if (!p)
err_return(UCI_ERR_NOTFOUND);
- rv = uci_add_section(*c, p, json_object_get_string(type), &sc);
+ rv = uci_add_section(*c, p, ucv_string_get(type), &sc);
if (rv != UCI_OK)
err_return(rv);
else if (!sc)
err_return(UCI_ERR_NOTFOUND);
- return json_object_new_string(sc->e.name);
+ return ucv_string_new(sc->e.name);
}
static bool
-json_to_value(json_object *val, const char **p, bool *is_list)
+uval_to_uci(uc_vm *vm, uc_value_t *val, const char **p, bool *is_list)
{
- json_object *item;
+ uc_value_t *item;
*p = NULL;
if (is_list)
*is_list = false;
- switch (json_object_get_type(val)) {
- case json_type_object:
- return false;
-
- case json_type_array:
- if (json_object_array_length(val) == 0)
+ switch (ucv_type(val)) {
+ case UC_ARRAY:
+ if (ucv_array_length(val) == 0)
return false;
- item = json_object_array_get_idx(val, 0);
+ item = ucv_array_get(val, 0);
/* don't recurse */
- if (json_object_is_type(item, json_type_array))
+ if (ucv_type(item) == UC_ARRAY)
return false;
if (is_list)
*is_list = true;
- return json_to_value(item, p, NULL);
+ return uval_to_uci(vm, item, p, NULL);
- case json_type_boolean:
- *p = json_object_get_boolean(val) ? "1" : "0";
+ case UC_BOOLEAN:
+ *p = xstrdup(ucv_boolean_get(val) ? "1" : "0");
return true;
- case json_type_null:
+ case UC_DOUBLE:
+ case UC_INTEGER:
+ case UC_STRING:
+ *p = ucv_to_string(vm, val);
+ /* fall through */
+
+ case UC_NULL:
return true;
default:
- *p = json_object_get_string(val);
-
- return true;
+ return false;
}
}
-static json_object *
+static uc_value_t *
uc_uci_set(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *sect = uc_get_arg(1);
- json_object *opt = NULL, *val = NULL;
- struct uci_ptr ptr = {};
+ uc_value_t *conf = uc_get_arg(0);
+ uc_value_t *sect = uc_get_arg(1);
+ uc_value_t *opt = NULL, *val = NULL;
+ struct uci_ptr ptr = { 0 };
bool is_list = false;
- int rv, i;
+ size_t i;
+ int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(sect, json_type_string))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(sect) != UC_STRING)
err_return(UCI_ERR_INVAL);
switch (nargs) {
@@ -475,7 +480,7 @@ uc_uci_set(uc_vm *vm, size_t nargs)
opt = uc_get_arg(2);
val = uc_get_arg(3);
- if (!json_object_is_type(opt, json_type_string))
+ if (ucv_type(opt) != UC_STRING)
err_return(UCI_ERR_INVAL);
break;
@@ -484,7 +489,7 @@ uc_uci_set(uc_vm *vm, size_t nargs)
case 3:
val = uc_get_arg(2);
- if (!json_object_is_type(val, json_type_string))
+ if (ucv_type(val) != UC_STRING)
err_return(UCI_ERR_INVAL);
break;
@@ -493,9 +498,9 @@ uc_uci_set(uc_vm *vm, size_t nargs)
err_return(UCI_ERR_INVAL);
}
- ptr.package = json_object_get_string(conf);
- ptr.section = json_object_get_string(sect);
- ptr.option = opt ? json_object_get_string(opt) : NULL;
+ ptr.package = ucv_string_get(conf);
+ ptr.section = ucv_string_get(sect);
+ ptr.option = opt ? ucv_string_get(opt) : NULL;
rv = lookup_ptr(*c, &ptr, true);
@@ -505,18 +510,19 @@ uc_uci_set(uc_vm *vm, size_t nargs)
if (!ptr.s && ptr.option)
err_return(UCI_ERR_NOTFOUND);
- if (!json_to_value(val, &ptr.value, &is_list))
+ if (!uval_to_uci(vm, val, &ptr.value, &is_list))
err_return(UCI_ERR_INVAL);
if (is_list) {
/* if we got a one-element array, delete existing option (if any)
* and iterate array at offset 0 */
- if (json_object_array_length(val) == 1) {
+ if (ucv_array_length(val) == 1) {
i = 0;
- if (ptr.o) {
- ptr.value = NULL;
+ free((char *)ptr.value);
+ ptr.value = NULL;
+ if (ptr.o) {
rv = uci_delete(*c, &ptr);
if (rv != UCI_OK)
@@ -529,16 +535,18 @@ uc_uci_set(uc_vm *vm, size_t nargs)
i = 1;
rv = uci_set(*c, &ptr);
+ free((char *)ptr.value);
if (rv != UCI_OK)
err_return(rv);
}
- for (; i < json_object_array_length(val); i++) {
- if (!json_to_value(json_object_array_get_idx(val, i), &ptr.value, NULL))
+ for (; i < ucv_array_length(val); i++) {
+ if (!uval_to_uci(vm, ucv_array_get(val, i), &ptr.value, NULL))
continue;
rv = uci_add_list(*c, &ptr);
+ free((char *)ptr.value);
if (rv != UCI_OK)
err_return(rv);
@@ -546,32 +554,33 @@ uc_uci_set(uc_vm *vm, size_t nargs)
}
else {
rv = uci_set(*c, &ptr);
+ free((char *)ptr.value);
if (rv != UCI_OK)
err_return(rv);
}
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_delete(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *sect = uc_get_arg(1);
- json_object *opt = uc_get_arg(2);
- struct uci_ptr ptr = {};
+ 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_ptr ptr = { 0 };
int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(sect, json_type_string) ||
- (opt && !json_object_is_type(opt, json_type_string)))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(sect) != UC_STRING ||
+ (opt && ucv_type(opt) != UC_STRING))
err_return(UCI_ERR_INVAL);
- ptr.package = json_object_get_string(conf);
- ptr.section = json_object_get_string(sect);
- ptr.option = opt ? json_object_get_string(opt) : NULL;
+ ptr.package = ucv_string_get(conf);
+ ptr.section = ucv_string_get(sect);
+ ptr.option = opt ? ucv_string_get(opt) : NULL;
rv = lookup_ptr(*c, &ptr, true);
@@ -586,21 +595,21 @@ uc_uci_delete(uc_vm *vm, size_t nargs)
if (rv != UCI_OK)
err_return(rv);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_rename(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *sect = uc_get_arg(1);
- json_object *opt = NULL, *val = NULL;
- struct uci_ptr ptr = {};
+ uc_value_t *conf = uc_get_arg(0);
+ uc_value_t *sect = uc_get_arg(1);
+ uc_value_t *opt = NULL, *val = NULL;
+ struct uci_ptr ptr = { 0 };
int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(sect, json_type_string))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(sect) != UC_STRING)
err_return(UCI_ERR_INVAL);
switch (nargs) {
@@ -609,8 +618,8 @@ uc_uci_rename(uc_vm *vm, size_t nargs)
opt = uc_get_arg(2);
val = uc_get_arg(3);
- if (!json_object_is_type(opt, json_type_string) ||
- !json_object_is_type(val, json_type_string))
+ if (ucv_type(opt) != UC_STRING ||
+ ucv_type(val) != UC_STRING)
err_return(UCI_ERR_INVAL);
break;
@@ -619,7 +628,7 @@ uc_uci_rename(uc_vm *vm, size_t nargs)
case 3:
val = uc_get_arg(2);
- if (!json_object_is_type(val, json_type_string))
+ if (ucv_type(val) != UC_STRING)
err_return(UCI_ERR_INVAL);
break;
@@ -628,10 +637,10 @@ uc_uci_rename(uc_vm *vm, size_t nargs)
err_return(UCI_ERR_INVAL);
}
- ptr.package = json_object_get_string(conf);
- ptr.section = json_object_get_string(sect);
- ptr.option = opt ? json_object_get_string(opt) : NULL;
- ptr.value = json_object_get_string(val);
+ ptr.package = ucv_string_get(conf);
+ ptr.section = ucv_string_get(sect);
+ ptr.option = opt ? ucv_string_get(opt) : NULL;
+ ptr.value = ucv_string_get(val);
rv = lookup_ptr(*c, &ptr, true);
@@ -646,32 +655,32 @@ uc_uci_rename(uc_vm *vm, size_t nargs)
if (rv != UCI_OK)
err_return(rv);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_reorder(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *sect = uc_get_arg(1);
- json_object *val = uc_get_arg(2);
- struct uci_ptr ptr = {};
+ 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_ptr ptr = { 0 };
int64_t n;
int rv;
- if (!json_object_is_type(conf, json_type_string) ||
- !json_object_is_type(sect, json_type_string) ||
- !json_object_is_type(val, json_type_int))
+ if (ucv_type(conf) != UC_STRING ||
+ ucv_type(sect) != UC_STRING ||
+ ucv_type(val) != UC_INTEGER)
err_return(UCI_ERR_INVAL);
- n = json_object_get_int64(val);
+ n = ucv_int64_get(val);
if (n < 0)
err_return(UCI_ERR_INVAL);
- ptr.package = json_object_get_string(conf);
- ptr.section = json_object_get_string(sect);
+ ptr.package = ucv_string_get(conf);
+ ptr.section = ucv_string_get(sect);
rv = lookup_ptr(*c, &ptr, true);
@@ -686,29 +695,29 @@ uc_uci_reorder(uc_vm *vm, size_t nargs)
if (rv != UCI_OK)
err_return(rv);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_pkg_command(uc_vm *vm, size_t nargs, enum pkg_cmd cmd)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
+ uc_value_t *conf = uc_get_arg(0);
struct uci_element *e, *tmp;
struct uci_package *p;
- struct uci_ptr ptr = {};
+ struct uci_ptr ptr = { 0 };
int rv, res = UCI_OK;
if (cmd != CMD_REVERT && conf)
err_return(UCI_ERR_INVAL);
- if (conf && !json_object_is_type(conf, json_type_string))
+ if (conf && ucv_type(conf) != UC_STRING)
err_return(UCI_ERR_INVAL);
uci_foreach_element_safe(&(*c)->root, tmp, e) {
p = uci_to_package(e);
- if (conf && strcmp(e->name, json_object_get_string(conf)))
+ if (conf && strcmp(e->name, ucv_string_get(conf)))
continue;
switch (cmd) {
@@ -736,29 +745,29 @@ uc_uci_pkg_command(uc_vm *vm, size_t nargs, enum pkg_cmd cmd)
if (res != UCI_OK)
err_return(res);
- return json_object_new_boolean(true);
+ return ucv_boolean_new(true);
}
-static json_object *
+static uc_value_t *
uc_uci_save(uc_vm *vm, size_t nargs)
{
return uc_uci_pkg_command(vm, nargs, CMD_SAVE);
}
-static json_object *
+static uc_value_t *
uc_uci_commit(uc_vm *vm, size_t nargs)
{
return uc_uci_pkg_command(vm, nargs, CMD_COMMIT);
}
-static json_object *
+static uc_value_t *
uc_uci_revert(uc_vm *vm, size_t nargs)
{
return uc_uci_pkg_command(vm, nargs, CMD_REVERT);
}
-static json_object *
-change_to_json(struct uci_delta *d)
+static uc_value_t *
+change_to_uval(uc_vm *vm, struct uci_delta *d)
{
const char *types[] = {
[UCI_CMD_REORDER] = "order",
@@ -770,36 +779,36 @@ change_to_json(struct uci_delta *d)
[UCI_CMD_CHANGE] = "set",
};
- json_object *a;
+ uc_value_t *a;
if (!d->section)
return NULL;
- a = json_object_new_array();
+ a = ucv_array_new(vm);
if (!a)
return NULL;
- json_object_array_add(a, json_object_new_string(types[d->cmd]));
- json_object_array_add(a, json_object_new_string(d->section));
+ ucv_array_push(a, ucv_string_new(types[d->cmd]));
+ ucv_array_push(a, ucv_string_new(d->section));
if (d->e.name)
- json_object_array_add(a, json_object_new_string(d->e.name));
+ ucv_array_push(a, ucv_string_new(d->e.name));
if (d->value) {
if (d->cmd == UCI_CMD_REORDER)
- json_object_array_add(a, json_object_new_int64(strtoul(d->value, NULL, 10)));
+ ucv_array_push(a, ucv_int64_new(strtoul(d->value, NULL, 10)));
else
- json_object_array_add(a, json_object_new_string(d->value));
+ ucv_array_push(a, ucv_string_new(d->value));
}
return a;
}
-static json_object *
-changes_to_json(struct uci_context *ctx, const char *package)
+static uc_value_t *
+changes_to_uval(uc_vm *vm, struct uci_context *ctx, const char *package)
{
- json_object *a = NULL, *c;
+ uc_value_t *a = NULL, *c;
struct uci_package *p = NULL;
struct uci_element *e;
bool unload = false;
@@ -820,23 +829,23 @@ changes_to_json(struct uci_context *ctx, const char *package)
return NULL;
if (!uci_list_empty(&p->delta) || !uci_list_empty(&p->saved_delta)) {
- a = json_object_new_array();
+ a = ucv_array_new(vm);
if (!a)
err_return(UCI_ERR_MEM);
uci_foreach_element(&p->saved_delta, e) {
- c = change_to_json(uci_to_delta(e));
+ c = change_to_uval(vm, uci_to_delta(e));
if (c)
- json_object_array_add(a, c);
+ ucv_array_push(a, c);
}
uci_foreach_element(&p->delta, e) {
- c = change_to_json(uci_to_delta(e));
+ c = change_to_uval(vm, uci_to_delta(e));
if (c)
- json_object_array_add(a, c);
+ ucv_array_push(a, c);
}
}
@@ -846,16 +855,16 @@ changes_to_json(struct uci_context *ctx, const char *package)
return a;
}
-static json_object *
+static uc_value_t *
uc_uci_changes(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *res, *chg;
+ uc_value_t *conf = uc_get_arg(0);
+ uc_value_t *res, *chg;
char **configs;
int rv, i;
- if (conf && !json_object_is_type(conf, json_type_string))
+ if (conf && ucv_type(conf) != UC_STRING)
err_return(UCI_ERR_INVAL);
rv = uci_list_configs(*c, &configs);
@@ -863,21 +872,16 @@ uc_uci_changes(uc_vm *vm, size_t nargs)
if (rv != UCI_OK)
err_return(rv);
- res = json_object_new_object();
-
- if (!res) {
- free(configs);
- err_return(UCI_ERR_MEM);
- }
+ res = ucv_object_new(vm);
for (i = 0; configs[i]; i++) {
- if (conf && strcmp(configs[i], json_object_get_string(conf)))
+ if (conf && strcmp(configs[i], ucv_string_get(conf)))
continue;
- chg = changes_to_json(*c, configs[i]);
+ chg = changes_to_uval(vm, *c, configs[i]);
if (chg)
- json_object_object_add(res, configs[i], chg);
+ ucv_object_add(res, configs[i], chg);
}
free(configs);
@@ -885,14 +889,14 @@ uc_uci_changes(uc_vm *vm, size_t nargs)
return res;
}
-static json_object *
+static uc_value_t *
uc_uci_foreach(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *conf = uc_get_arg(0);
- json_object *type = uc_get_arg(1);
- json_object *func = uc_get_arg(2);
- json_object *rv = NULL;
+ uc_value_t *conf = uc_get_arg(0);
+ uc_value_t *type = uc_get_arg(1);
+ uc_value_t *func = uc_get_arg(2);
+ uc_value_t *rv = NULL;
struct uci_package *p = NULL;
struct uci_element *e, *tmp;
struct uci_section *sc;
@@ -901,12 +905,12 @@ uc_uci_foreach(uc_vm *vm, size_t nargs)
bool ret = false;
int i = 0;
- if (!json_object_is_type(conf, json_type_string) ||
- (type && !json_object_is_type(type, json_type_string)))
+ if (ucv_type(conf) != UC_STRING ||
+ (type && ucv_type(type) != UC_STRING))
err_return(UCI_ERR_INVAL);
uci_foreach_element(&(*c)->root, e) {
- if (strcmp(e->name, json_object_get_string(conf)))
+ if (strcmp(e->name, ucv_string_get(conf)))
continue;
p = uci_to_package(e);
@@ -920,11 +924,11 @@ uc_uci_foreach(uc_vm *vm, size_t nargs)
sc = uci_to_section(e);
i++;
- if (type && strcmp(sc->type, json_object_get_string(type)))
+ if (type && strcmp(sc->type, ucv_string_get(type)))
continue;
- uc_push_val(uc_value_get(func));
- uc_push_val(section_to_json(sc, i - 1));
+ uc_push_val(ucv_get(func));
+ uc_push_val(section_to_uval(vm, sc, i - 1));
ex = uc_call(1);
@@ -934,9 +938,9 @@ uc_uci_foreach(uc_vm *vm, size_t nargs)
ret = true;
rv = uc_pop_val();
- stop = (json_object_is_type(rv, json_type_boolean) && !json_object_get_boolean(rv));
+ stop = (ucv_type(rv) == UC_BOOLEAN && !ucv_boolean_get(rv));
- json_object_put(rv);
+ ucv_put(rv);
if (stop)
break;
@@ -944,14 +948,14 @@ uc_uci_foreach(uc_vm *vm, size_t nargs)
/* XXX: rethrow */
- return json_object_new_boolean(ret);
+ return ucv_boolean_new(ret);
}
-static json_object *
+static uc_value_t *
uc_uci_configs(uc_vm *vm, size_t nargs)
{
struct uci_context **c = uc_get_self("uci.cursor");
- json_object *a;
+ uc_value_t *a;
char **configs;
int i, rv;
@@ -960,15 +964,10 @@ uc_uci_configs(uc_vm *vm, size_t nargs)
if (rv != UCI_OK)
err_return(rv);
- a = json_object_new_array();
-
- if (!a) {
- free(configs);
- err_return(UCI_ERR_MEM);
- }
+ a = ucv_array_new(vm);
for (i = 0; configs[i]; i++)
- json_object_array_add(a, json_object_new_string(configs[i]));
+ ucv_array_push(a, ucv_string_new(configs[i]));
free(configs);
@@ -1006,7 +1005,7 @@ static void close_uci(void *ud) {
uci_free_context((struct uci_context *)ud);
}
-void uc_module_init(uc_prototype *scope)
+void uc_module_init(uc_value_t *scope)
{
uc_add_proto_functions(scope, global_fns);
diff --git a/main.c b/main.c
index 36d42a8..d291447 100644
--- a/main.c
+++ b/main.c
@@ -36,7 +36,7 @@
static void
-print_usage(char *app)
+print_usage(const char *app)
{
printf(
"== Usage ==\n\n"
@@ -51,18 +51,18 @@ print_usage(char *app)
" -e Set global variables from given JSON object\n"
" -E Set global variables from given JSON file\n"
" -m Preload given module\n",
- app);
+ basename(app));
}
static void
-globals_init(uc_prototype *scope)
+globals_init(uc_vm *vm, uc_value_t *scope)
{
- json_object *arr = xjs_new_array();
+ uc_value_t *arr = ucv_array_new(vm);
const char *p, *last;
for (p = last = LIB_SEARCH_PATH;; p++) {
if (*p == ':' || *p == '\0') {
- json_object_array_add(arr, xjs_new_string_len(last, p - last));
+ ucv_array_push(arr, ucv_string_new_length(last, p - last));
if (!*p)
break;
@@ -71,11 +71,11 @@ globals_init(uc_prototype *scope)
}
}
- json_object_object_add(scope->header.jso, "REQUIRE_SEARCH_PATH", arr);
+ ucv_object_add(scope, "REQUIRE_SEARCH_PATH", arr);
}
static void
-register_variable(uc_prototype *scope, const char *key, json_object *val)
+register_variable(uc_value_t *scope, const char *key, uc_value_t *val)
{
char *name = strdup(key);
char *p;
@@ -87,20 +87,20 @@ register_variable(uc_prototype *scope, const char *key, json_object *val)
if (!isalnum(*p) && *p != '_')
*p = '_';
- json_object_object_add(scope->header.jso, name, val);
+ ucv_object_add(scope, name, val);
free(name);
}
static int
parse(uc_parse_config *config, uc_source *src,
- bool skip_shebang, json_object *env, json_object *modules)
+ bool skip_shebang, uc_value_t *env, uc_value_t *modules)
{
- uc_prototype *globals = uc_prototype_new(NULL), *rootscope = NULL;
- uc_function *entry;
- uc_vm vm = {};
- char c, c2, *err;
- int rc = 0;
+ uc_value_t *globals = NULL;
+ uc_function_t *entry;
+ uc_vm vm = { 0 };
+ int c, c2, rc = 0;
+ char *err;
uc_vm_init(&vm, config);
@@ -131,25 +131,24 @@ parse(uc_parse_config *config, uc_source *src,
goto out;
}
+ globals = ucv_object_new(&vm);
+
/* load global variables */
- globals_init(globals);
+ globals_init(&vm, globals);
/* load env variables */
if (env) {
- json_object_object_foreach(env, key, val)
- register_variable(globals, key, uc_value_get(val));
+ ucv_object_foreach(env, key, val)
+ register_variable(globals, key, ucv_get(val));
}
/* load std functions into global scope */
uc_lib_init(globals);
/* create instance of global scope, set "global" property on it */
- rootscope = uc_protoref_new(xjs_new_object(), globals);
-
- json_object_object_add(rootscope->header.jso, "global",
- uc_value_get(globals->header.jso));
+ ucv_object_add(globals, "global", ucv_get(globals));
- rc = uc_vm_execute(&vm, entry, rootscope, modules);
+ rc = uc_vm_execute(&vm, entry, globals, modules);
if (rc) {
rc = 1;
@@ -158,10 +157,6 @@ parse(uc_parse_config *config, uc_source *src,
out:
uc_vm_free(&vm);
- uc_value_put(globals->header.jso);
-
- if (rootscope)
- uc_value_put(rootscope->header.jso);
return rc;
}
@@ -193,12 +188,13 @@ read_stdin(char **ptr)
return uc_source_new_buffer("[stdin]", *ptr, tlen);
}
-static json_object *
+static uc_value_t *
parse_envfile(FILE *fp)
{
- json_object *rv = NULL;
- enum json_tokener_error err;
+ enum json_tokener_error err = json_tokener_continue;
struct json_tokener *tok;
+ json_object *jso = NULL;
+ uc_value_t *rv;
char buf[128];
size_t rlen;
@@ -210,27 +206,32 @@ parse_envfile(FILE *fp)
if (rlen == 0)
break;
- rv = json_tokener_parse_ex(tok, buf, rlen);
+ jso = json_tokener_parse_ex(tok, buf, rlen);
err = json_tokener_get_error(tok);
if (err != json_tokener_continue)
break;
}
- if (err != json_tokener_success || !json_object_is_type(rv, json_type_object)) {
- json_object_put(rv);
- rv = NULL;
+ if (err != json_tokener_success || !json_object_is_type(jso, json_type_object)) {
+ json_object_put(jso);
+
+ return NULL;
}
json_tokener_free(tok);
+ rv = ucv_from_json(NULL, jso);
+
+ json_object_put(jso);
+
return rv;
}
int
main(int argc, char **argv)
{
- json_object *env = NULL, *modules = NULL, *o, *p;
+ uc_value_t *env = NULL, *modules = NULL, *o, *p;
uc_source *source = NULL, *envfile = NULL;
char *stdin = NULL, *c;
bool shebang = false;
@@ -284,7 +285,12 @@ main(int argc, char **argv)
if (source)
fprintf(stderr, "Options -i and -s are exclusive\n");
- source = uc_source_new_buffer("[-s argument]", xstrdup(optarg), strlen(optarg));
+ c = xstrdup(optarg);
+ source = uc_source_new_buffer("[-s argument]", c, strlen(c));
+
+ if (!source)
+ free(c);
+
break;
case 'S':
@@ -335,27 +341,27 @@ main(int argc, char **argv)
goto out;
}
- env = env ? env : xjs_new_object();
+ env = env ? env : ucv_object_new(NULL);
if (c > optarg && optarg[0]) {
- p = xjs_new_object();
- json_object_object_add(env, optarg, p);
+ p = ucv_object_new(NULL);
+ ucv_object_add(env, optarg, p);
}
else {
p = env;
}
- json_object_object_foreach(o, key, val)
- json_object_object_add(p, key, json_object_get(val));
+ ucv_object_foreach(o, key, val)
+ ucv_object_add(p, key, ucv_get(val));
- json_object_put(o);
+ ucv_put(o);
break;
case 'm':
- modules = modules ? modules : xjs_new_array();
+ modules = modules ? modules : ucv_array_new(NULL);
- json_object_array_add(modules, xjs_new_string(optarg));
+ ucv_array_push(modules, ucv_string_new(optarg));
break;
}
@@ -382,8 +388,8 @@ main(int argc, char **argv)
rv = parse(&config, source, shebang, env, modules);
out:
- json_object_put(modules);
- json_object_put(env);
+ ucv_put(modules);
+ ucv_put(env);
uc_source_put(source);
diff --git a/module.h b/module.h
index 9885270..aa72074 100644
--- a/module.h
+++ b/module.h
@@ -18,7 +18,6 @@
#define __MODULE_H_
#include "lib.h"
-#include "object.h"
#include "vm.h"
#define register_functions(scope, functions) \
@@ -34,23 +33,19 @@
})
#define declare_type(name, proto, freefn) \
- ops->ressource.define(name, proto, freefn)
+ ucv_ressource_type_add(name, proto, freefn)
#define alloc_ressource(data, type) \
- ops->ressource.create(xjs_new_object(), type, data)
+ 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)
-static const uc_ops *ops;
+void uc_module_init(uc_value_t *scope) __attribute__((weak));
-void uc_module_init(uc_prototype *scope) __attribute__((weak));
-
-void uc_module_entry(const uc_ops *_ops, uc_prototype *scope);
-void uc_module_entry(const uc_ops *_ops, uc_prototype *scope)
+void uc_module_entry(uc_value_t *scope);
+void uc_module_entry(uc_value_t *scope)
{
- ops = _ops;
-
if (uc_module_init)
uc_module_init(scope);
}
diff --git a/object.c b/object.c
deleted file mode 100644
index 7748744..0000000
--- a/object.c
+++ /dev/null
@@ -1,493 +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.
- */
-
-#include <string.h>
-#include <assert.h>
-
-#include "object.h"
-
-static void *
-uc_object_new(uc_objtype_t type, size_t size, json_object_to_json_string_fn *tostring, json_object_delete_fn *gc)
-{
- uc_objhdr *hdr = xalloc(size);
-
- hdr->type = type;
- hdr->jso = xjs_new_object();
-
- json_object_set_serializer(hdr->jso, tostring, hdr, gc);
-
- return hdr;
-}
-
-static int
-uc_upvalref_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- return sprintbuf(pb, "<upvalref %p>", jso);
-}
-
-static void
-uc_upvalref_gc(json_object *jso, void *userdata)
-{
- uc_upvalref *up = userdata;
-
- uc_value_put(up->value);
- free(up);
-}
-
-uc_upvalref *
-uc_upvalref_new(size_t slot)
-{
- uc_upvalref *up;
-
- up = uc_object_new(UC_OBJ_UPVAL, sizeof(*up), uc_upvalref_tostring, uc_upvalref_gc);
- up->slot = slot;
-
- return up;
-}
-
-static int
-uc_function_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- return sprintbuf(pb, "<function %p>", jso);
-}
-
-static void
-uc_function_gc(json_object *jso, void *userdata)
-{
- uc_function *fn = userdata;
-
- uc_chunk_free(&fn->chunk);
- uc_source_put(fn->source);
-
- free(fn);
-}
-
-uc_function *
-uc_function_new(const char *name, size_t srcpos, uc_source *source)
-{
- size_t namelen = 0;
- uc_function *fn;
-
- if (name)
- namelen = strlen(name) + 1;
-
- fn = uc_object_new(UC_OBJ_FUNCTION, ALIGN(sizeof(*fn)) + namelen, uc_function_tostring, uc_function_gc);
- fn->name = name ? strcpy((char *)fn + ALIGN(sizeof(*fn)), name) : NULL;
- fn->nargs = 0;
- fn->nupvals = 0;
- fn->srcpos = srcpos;
- fn->source = uc_source_get(source);
- fn->vararg = false;
-
- uc_chunk_init(&fn->chunk);
-
- return fn;
-}
-
-size_t
-uc_function_get_srcpos(uc_function *fn, size_t off)
-{
- size_t pos = uc_chunk_debug_get_srcpos(&fn->chunk, off);
-
- return pos ? fn->srcpos + pos : 0;
-}
-
-static int
-uc_closure_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- uc_closure *closure = json_object_get_userdata(jso);
- uc_function *function = closure->function;
- json_object *argname;
- size_t i;
-
- sprintbuf(pb, "%s%s",
- strict ? "\"" : "",
- closure->is_arrow ? "" : "function");
-
- if (function->name)
- sprintbuf(pb, " %s", function->name);
-
- sprintbuf(pb, "(");
-
- for (i = 1; i <= function->nargs; i++) {
- argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false);
-
- if (i > 1)
- sprintbuf(pb, ", ");
-
- if (i == function->nargs && function->vararg)
- sprintbuf(pb, "...");
-
- if (argname)
- sprintbuf(pb, "%s", json_object_get_string(argname));
- else
- sprintbuf(pb, "[arg%zu]", i);
-
- uc_value_put(argname);
- }
-
- return sprintbuf(pb, ")%s { ... }%s",
- closure->is_arrow ? " =>" : "",
- strict ? "\"" : "");
-}
-
-static void
-uc_closure_gc(json_object *jso, void *userdata)
-{
- uc_closure *closure = userdata;
- uc_function *function = closure->function;
- size_t i;
-
- for (i = 0; i < function->nupvals; i++)
- uc_value_put(closure->upvals[i]->header.jso);
-
- uc_value_put(function->header.jso);
-
- free(closure);
-}
-
-uc_closure *
-uc_closure_new(uc_function *function, bool arrow_fn)
-{
- uc_closure *closure;
-
- closure = uc_object_new(UC_OBJ_CLOSURE,
- ALIGN(sizeof(*closure)) + (sizeof(uc_upvalref *) * function->nupvals),
- uc_closure_tostring, uc_closure_gc);
-
- closure->function = function;
- closure->is_arrow = arrow_fn;
- closure->upvals = function->nupvals ? ((void *)closure + ALIGN(sizeof(*closure))) : NULL;
-
- return closure;
-}
-
-static int
-uc_cfunction_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- uc_cfunction *cfn = json_object_get_userdata(jso);
-
- return sprintbuf(pb, "%sfunction%s%s(...) { [native code] }%s",
- strict ? "\"" : "",
- cfn->name ? " " : "",
- cfn->name ? cfn->name : "",
- strict ? "\"" : "");
-}
-
-static void
-uc_cfunction_gc(json_object *jso, void *userdata)
-{
- free(userdata);
-}
-
-uc_cfunction *
-uc_cfunction_new(const char *name, uc_cfn_ptr fptr)
-{
- size_t namelen = 0;
- uc_cfunction *cfn;
-
- if (name)
- namelen = strlen(name) + 1;
-
- cfn = uc_object_new(UC_OBJ_CFUNCTION, ALIGN(sizeof(*cfn)) + namelen, uc_cfunction_tostring, uc_cfunction_gc);
- cfn->name = name ? strcpy((char *)cfn + ALIGN(sizeof(*cfn)), name) : NULL;
- cfn->cfn = fptr;
-
- return cfn;
-}
-
-static int
-uc_regexp_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- uc_regexp *re = json_object_get_userdata(jso);
- json_object *s;
- const char *p;
- size_t len;
-
- sprintbuf(pb, "%s/", strict ? "\"" : "");
-
- s = xjs_new_string(re->pattern);
-
- if (strict)
- for (p = json_object_to_json_string(s) + 1, len = strlen(p) - 1; len > 0; len--, p++)
- sprintbuf(pb, "%c", *p);
- else
- sprintbuf(pb, "%s", json_object_get_string(s));
-
- uc_value_put(s);
-
- return sprintbuf(pb, "/%s%s%s%s",
- re->global ? "g" : "",
- re->icase ? "i" : "",
- re->newline ? "s" : "",
- strict ? "\"" : "");
-}
-
-static void
-uc_regexp_gc(json_object *jso, void *userdata)
-{
- uc_regexp *re = userdata;
-
- regfree(&re->re);
- free(re);
-}
-
-uc_regexp *
-uc_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **err)
-{
- int cflags = REG_EXTENDED, res;
- uc_regexp *re;
- size_t len;
-
- re = uc_object_new(UC_OBJ_REGEXP, ALIGN(sizeof(*re)) + strlen(pattern) + 1, uc_regexp_tostring, uc_regexp_gc);
- re->icase = icase;
- re->global = global;
- re->newline = newline;
- re->pattern = strcpy((char *)re + ALIGN(sizeof(*re)), pattern);
-
- if (icase)
- cflags |= REG_ICASE;
-
- if (newline)
- cflags |= REG_NEWLINE;
-
- res = regcomp(&re->re, pattern, cflags);
-
- if (res != 0) {
- if (err) {
- len = regerror(res, &re->re, NULL, 0);
- *err = xalloc(len);
-
- regerror(res, &re->re, *err, len);
- }
-
- uc_value_put(re->header.jso);
-
- 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;
-}
-
-static void
-uc_prototype_gc(json_object *jso, void *userdata)
-{
- uc_prototype *proto = userdata;
-
- if (proto->parent)
- uc_value_put(proto->parent->header.jso);
-
- free(proto);
-}
-
-uc_prototype *
-uc_prototype_new(uc_prototype *parent)
-{
- uc_prototype *proto;
-
- proto = uc_object_new(UC_OBJ_PROTOTYPE, sizeof(*proto), NULL, uc_prototype_gc);
-
- if (parent) {
- proto->parent = parent;
- uc_value_get(parent->header.jso);
- }
-
- return proto;
-}
-
-json_object *
-uc_prototype_lookup(uc_prototype *proto, const char *key)
-{
- json_object *val;
-
- for (; proto; proto = proto->parent)
- if (json_object_object_get_ex(proto->header.jso, key, &val))
- return val;
-
- return NULL;
-}
-
-uc_prototype *
-uc_protoref_new(json_object *value, uc_prototype *proto)
-{
- uc_prototype *ref;
-
- if (!json_object_is_type(value, json_type_object) &&
- !json_object_is_type(value, json_type_array))
- return NULL;
-
- ref = xalloc(sizeof(*ref));
- ref->header.type = UC_OBJ_PROTOTYPE;
- ref->header.jso = value;
-
- if (proto) {
- ref->parent = proto;
- uc_value_get(proto->header.jso);
- }
-
- json_object_set_serializer(ref->header.jso, NULL, ref, uc_prototype_gc);
-
- return ref;
-}
-
-
-static uc_ressource_types res_types;
-
-uc_ressource_type *
-uc_ressource_type_add(const char *name, uc_prototype *proto, void (*freefn)(void *))
-{
- uc_ressource_type *existing;
-
- existing = uc_ressource_type_lookup(name);
-
- if (existing) {
- uc_value_put(proto->header.jso);
-
- return existing;
- }
-
- uc_vector_grow(&res_types);
-
- res_types.entries[res_types.count].name = name;
- res_types.entries[res_types.count].proto = proto;
- res_types.entries[res_types.count].free = freefn;
-
- return &res_types.entries[res_types.count++];
-}
-
-static uc_ressource_type *
-uc_ressource_type_get(size_t type)
-{
- return (type < res_types.count) ? &res_types.entries[type] : NULL;
-}
-
-uc_ressource_type *
-uc_ressource_type_lookup(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];
-
- return NULL;
-}
-
-static int
-uc_ressource_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- uc_ressource *res = json_object_get_userdata(jso);
- uc_ressource_type *type = uc_ressource_type_get(res->type);
-
- return sprintbuf(pb, "%s<%s %p>%s",
- strict ? "\"" : "",
- type ? type->name : "ressource",
- res->data,
- strict ? "\"" : "");
-}
-
-static void
-uc_ressource_gc(json_object *jso, void *userdata)
-{
- uc_ressource *res = userdata;
- uc_ressource_type *type = uc_ressource_type_get(res->type);
-
- if (type && type->free)
- type->free(res->data);
-
- free(res);
-}
-
-uc_ressource *
-uc_ressource_new(json_object *jso, uc_ressource_type *type, void *data)
-{
- uc_ressource *res;
-
- if (!jso)
- return NULL;
-
- res = xalloc(sizeof(*res));
- res->header.type = UC_OBJ_RESSOURCE;
- res->header.jso = jso;
-
- res->type = type - res_types.entries;
- res->data = data;
-
- json_object_set_serializer(res->header.jso, uc_ressource_tostring, res, uc_ressource_gc);
-
- return res;
-}
-
-void **
-uc_ressource_dataptr(json_object *jso, const char *name)
-{
- uc_ressource_type *type;
- uc_ressource *res;
-
- if (!uc_object_is_type(jso, UC_OBJ_RESSOURCE))
- return NULL;
-
- res = uc_object_as_ressource(jso);
-
- if (name) {
- type = uc_ressource_type_lookup(name);
-
- if (!type || type != uc_ressource_type_get(res->type))
- return NULL;
- }
-
- return &res->data;
-}
-
-uc_prototype *
-uc_ressource_prototype(json_object *jso)
-{
- uc_ressource_type *type;
- uc_ressource *res;
-
- if (!uc_object_is_type(jso, UC_OBJ_RESSOURCE))
- return NULL;
-
- res = uc_object_as_ressource(jso);
- type = uc_ressource_type_get(res->type);
-
- return type ? type->proto : NULL;
-}
-
-
-#ifdef __GNUC__
-
-__attribute__((destructor))
-static void uc_ressource_types_free(void)
-{
- size_t i;
-
- for (i = 0; i < res_types.count; i++)
- uc_value_put(res_types.entries[i].proto->header.jso);
-
- uc_vector_clear(&res_types);
-}
-
-#endif
diff --git a/object.h b/object.h
deleted file mode 100644
index 74cc835..0000000
--- a/object.h
+++ /dev/null
@@ -1,201 +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 __OBJECT_H_
-#define __OBJECT_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <regex.h>
-
-#ifdef JSONC
- #include <json.h>
-#else
- #include <json-c/json.h>
-#endif
-
-#include "source.h"
-#include "chunk.h"
-#include "util.h"
-
-typedef enum {
- UC_OBJ_INVAL,
- UC_OBJ_UPVAL,
- UC_OBJ_FUNCTION,
- UC_OBJ_CLOSURE,
- UC_OBJ_CFUNCTION,
- UC_OBJ_REGEXP,
- UC_OBJ_PROTOTYPE,
- UC_OBJ_RESSOURCE
-} uc_objtype_t;
-
-typedef struct {
- uc_objtype_t type;
- json_object *jso;
-} uc_objhdr;
-
-typedef struct uc_upvalref {
- uc_objhdr header;
- size_t slot;
- bool closed;
- json_object *value;
- struct uc_upvalref *next;
-} uc_upvalref;
-
-typedef struct {
- uc_objhdr header;
- char *name;
- bool arrow, vararg;
- size_t nargs;
- size_t nupvals;
- size_t srcpos;
- uc_chunk chunk;
- uc_source *source;
-} uc_function;
-
-typedef struct {
- uc_objhdr header;
- uc_function *function;
- uc_upvalref **upvals;
- bool is_arrow;
-} uc_closure;
-
-struct uc_vm;
-typedef json_object *(*uc_cfn_ptr)(struct uc_vm *, size_t);
-
-typedef struct {
- uc_objhdr header;
- char *name;
- uc_cfn_ptr cfn;
-} uc_cfunction;
-
-typedef struct {
- uc_objhdr header;
- regex_t re;
- char *pattern;
- bool icase, newline, global;
-} uc_regexp;
-
-struct uc_prototype {
- uc_objhdr header;
- struct uc_prototype *parent;
-};
-
-typedef struct uc_prototype uc_prototype;
-
-typedef struct {
- uc_objhdr header;
- size_t type;
- void *data;
-} uc_ressource;
-
-typedef struct {
- const char *name;
- uc_prototype *proto;
- void (*free)(void *);
-} uc_ressource_type;
-
-uc_declare_vector(uc_ressource_types, uc_ressource_type);
-
-uc_upvalref *uc_upvalref_new(size_t slot);
-uc_function *uc_function_new(const char *name, size_t line, uc_source *source);
-uc_closure *uc_closure_new(uc_function *function, bool arrow_fn);
-uc_cfunction *uc_cfunction_new(const char *name, uc_cfn_ptr cfn);
-uc_regexp *uc_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **err);
-uc_prototype *uc_prototype_new(uc_prototype *parent);
-uc_prototype *uc_protoref_new(json_object *value, uc_prototype *proto);
-json_object *uc_prototype_lookup(uc_prototype *proto, const char *key);
-
-uc_ressource_type *uc_ressource_type_add(const char *name, uc_prototype *proto, void (*freefn)(void *));
-uc_ressource_type *uc_ressource_type_lookup(const char *name);
-
-uc_ressource *uc_ressource_new(json_object *jso, uc_ressource_type *type, void *data);
-uc_prototype *uc_ressource_prototype(json_object *jso);
-void **uc_ressource_dataptr(json_object *jso, const char *name);
-
-size_t uc_function_get_srcpos(uc_function *function, size_t off);
-
-static inline uc_objtype_t
-uc_object_type(json_object *jso)
-{
- uc_objhdr *hdr = json_object_get_userdata(jso);
-
- return hdr ? hdr->type : UC_OBJ_INVAL;
-}
-
-static inline bool
-uc_object_is_type(json_object *jso, uc_objtype_t type)
-{
- return uc_object_type(jso) == type;
-}
-
-static inline uc_upvalref *
-uc_object_as_upvalref(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_function *
-uc_object_as_function(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_closure *
-uc_object_as_closure(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_cfunction *
-uc_object_as_cfunction(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_regexp *
-uc_object_as_regexp(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_prototype *
-uc_object_as_prototype(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline uc_ressource *
-uc_object_as_ressource(json_object *jso)
-{
- return json_object_get_userdata(jso);
-}
-
-static inline bool
-uc_object_is_callable(json_object *jso)
-{
- switch (uc_object_type(jso)) {
- case UC_OBJ_CLOSURE:
- case UC_OBJ_CFUNCTION:
- return true;
-
- default:
- return false;
- }
-}
-
-#endif /* __OBJECT_H_ */
diff --git a/source.h b/source.h
index 4ca01b3..6557a48 100644
--- a/source.h
+++ b/source.h
@@ -22,17 +22,9 @@
#include <stdio.h>
#include "util.h"
+#include "types.h"
-uc_declare_vector(uc_lineinfo, uint8_t);
-
-typedef struct {
- char *filename, *buffer;
- FILE *fp;
- size_t usecount, off;
- uc_lineinfo lineinfo;
-} uc_source;
-
uc_source *uc_source_new_file(const char *path);
uc_source *uc_source_new_buffer(const char *name, char *buf, size_t len);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..aed0100
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,6 @@
+ADD_SUBDIRECTORY(cram)
+ADD_SUBDIRECTORY(custom)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_SUBDIRECTORY(fuzz)
+ENDIF()
diff --git a/tests/cram/CMakeLists.txt b/tests/cram/CMakeLists.txt
new file mode 100644
index 0000000..a93add5
--- /dev/null
+++ b/tests/cram/CMakeLists.txt
@@ -0,0 +1,27 @@
+FIND_PACKAGE(PythonInterp 3 REQUIRED)
+FILE(GLOB test_cases "test_*.t")
+
+SET(PYTHON_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv")
+SET(PYTHON_VENV_PIP "${PYTHON_VENV_DIR}/bin/pip")
+SET(PYTHON_VENV_CRAM "${PYTHON_VENV_DIR}/bin/cram")
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${PYTHON_VENV_CRAM}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${PYTHON_VENV_DIR}
+ COMMAND ${PYTHON_VENV_PIP} install cram
+)
+ADD_CUSTOM_TARGET(prepare-cram-venv ALL DEPENDS ${PYTHON_VENV_CRAM})
+
+ADD_TEST(
+ NAME cram
+ COMMAND ${PYTHON_VENV_CRAM} ${test_cases} ${test_cases_san}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "BUILD_BIN_DIR=$<TARGET_FILE_DIR:ucode>")
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "UCODE_BIN=$<TARGET_FILE:ucode-san>")
+ELSE()
+ SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "UCODE_BIN=valgrind --quiet --leak-check=full $<TARGET_FILE:ucode>")
+ENDIF()
diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t
new file mode 100644
index 0000000..3d4cd9e
--- /dev/null
+++ b/tests/cram/test_basic.t
@@ -0,0 +1,59 @@
+setup common environment:
+
+ $ [ -n "$BUILD_BIN_DIR" ] && export PATH="$BUILD_BIN_DIR:$PATH"
+ $ alias ucode="$UCODE_BIN"
+
+ $ for m in $BUILD_BIN_DIR/*.so; do
+ > ln -s "$m" "$(pwd)/$(basename $m)"; \
+ > done
+
+check that ucode provides exepected help:
+
+ $ ucode | sed 's/ucode-san/ucode/'
+ == Usage ==
+
+ # ucode [-d] [-l] [-r] [-S] [-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
+ -l Do not strip leading block whitespace
+ -r Do not trim trailing block newlines
+ -S Enable strict mode
+ -e Set global variables from given JSON object
+ -E Set global variables from given JSON file
+ -m Preload given module
+
+check that ucode prints greetings:
+
+ $ ucode -s "{% print('hello world') %}"
+ hello world (no-eol)
+
+check that ucode provides proper error messages:
+
+ $ ucode -m foo
+ One of -i or -s is required
+ [1]
+
+ $ ucode -m foo -s ' '
+ Runtime error: No module named 'foo' could be found
+ At start of program
+
+ [1]
+
+ $ touch moo; ucode -m foo -i moo
+ Runtime error: No module named 'foo' could be found
+ At start of program
+
+ [1]
+
+check that ucode can load fs module:
+
+ $ ucode -m fs
+ One of -i or -s is required
+ [1]
+
+ $ ucode -m fs -s ' '
+ (no-eol)
+
+ $ touch moo; ucode -m fs -i moo
diff --git a/tests/00_syntax/00_single_line_comments b/tests/custom/00_syntax/00_single_line_comments
index 24a32a2..24a32a2 100644
--- a/tests/00_syntax/00_single_line_comments
+++ b/tests/custom/00_syntax/00_single_line_comments
diff --git a/tests/00_syntax/01_unterminated_comment b/tests/custom/00_syntax/01_unterminated_comment
index 1d3669c..1d3669c 100644
--- a/tests/00_syntax/01_unterminated_comment
+++ b/tests/custom/00_syntax/01_unterminated_comment
diff --git a/tests/00_syntax/02_multi_line_comments b/tests/custom/00_syntax/02_multi_line_comments
index 99fc37e..99fc37e 100644
--- a/tests/00_syntax/02_multi_line_comments
+++ b/tests/custom/00_syntax/02_multi_line_comments
diff --git a/tests/00_syntax/03_expression_blocks b/tests/custom/00_syntax/03_expression_blocks
index 3568016..3568016 100644
--- a/tests/00_syntax/03_expression_blocks
+++ b/tests/custom/00_syntax/03_expression_blocks
diff --git a/tests/00_syntax/04_statement_blocks b/tests/custom/00_syntax/04_statement_blocks
index 920ed71..920ed71 100644
--- a/tests/00_syntax/04_statement_blocks
+++ b/tests/custom/00_syntax/04_statement_blocks
diff --git a/tests/00_syntax/05_block_nesting b/tests/custom/00_syntax/05_block_nesting
index fcfd7da..fcfd7da 100644
--- a/tests/00_syntax/05_block_nesting
+++ b/tests/custom/00_syntax/05_block_nesting
diff --git a/tests/00_syntax/06_open_statement_block b/tests/custom/00_syntax/06_open_statement_block
index 9c2d142..9c2d142 100644
--- a/tests/00_syntax/06_open_statement_block
+++ b/tests/custom/00_syntax/06_open_statement_block
diff --git a/tests/00_syntax/07_embedded_single_line_comments b/tests/custom/00_syntax/07_embedded_single_line_comments
index 43f188c..43f188c 100644
--- a/tests/00_syntax/07_embedded_single_line_comments
+++ b/tests/custom/00_syntax/07_embedded_single_line_comments
diff --git a/tests/00_syntax/08_embedded_multi_line_comments b/tests/custom/00_syntax/08_embedded_multi_line_comments
index 75aba5f..75aba5f 100644
--- a/tests/00_syntax/08_embedded_multi_line_comments
+++ b/tests/custom/00_syntax/08_embedded_multi_line_comments
diff --git a/tests/00_syntax/09_string_literals b/tests/custom/00_syntax/09_string_literals
index 0967850..0967850 100644
--- a/tests/00_syntax/09_string_literals
+++ b/tests/custom/00_syntax/09_string_literals
diff --git a/tests/00_syntax/10_numeric_literals b/tests/custom/00_syntax/10_numeric_literals
index 3e367d0..3e367d0 100644
--- a/tests/00_syntax/10_numeric_literals
+++ b/tests/custom/00_syntax/10_numeric_literals
diff --git a/tests/00_syntax/11_misc_literals b/tests/custom/00_syntax/11_misc_literals
index 372741c..372741c 100644
--- a/tests/00_syntax/11_misc_literals
+++ b/tests/custom/00_syntax/11_misc_literals
diff --git a/tests/00_syntax/12_block_whitespace_control b/tests/custom/00_syntax/12_block_whitespace_control
index 911171c..911171c 100644
--- a/tests/00_syntax/12_block_whitespace_control
+++ b/tests/custom/00_syntax/12_block_whitespace_control
diff --git a/tests/00_syntax/13_object_literals b/tests/custom/00_syntax/13_object_literals
index 18fbbed..18fbbed 100644
--- a/tests/00_syntax/13_object_literals
+++ b/tests/custom/00_syntax/13_object_literals
diff --git a/tests/00_syntax/14_array_literals b/tests/custom/00_syntax/14_array_literals
index 941ee4a..941ee4a 100644
--- a/tests/00_syntax/14_array_literals
+++ b/tests/custom/00_syntax/14_array_literals
diff --git a/tests/00_syntax/15_function_declarations b/tests/custom/00_syntax/15_function_declarations
index 4257dd6..4257dd6 100644
--- a/tests/00_syntax/15_function_declarations
+++ b/tests/custom/00_syntax/15_function_declarations
diff --git a/tests/00_syntax/16_for_loop b/tests/custom/00_syntax/16_for_loop
index 67edc21..67edc21 100644
--- a/tests/00_syntax/16_for_loop
+++ b/tests/custom/00_syntax/16_for_loop
diff --git a/tests/00_syntax/17_while_loop b/tests/custom/00_syntax/17_while_loop
index 1e68d6b..1e68d6b 100644
--- a/tests/00_syntax/17_while_loop
+++ b/tests/custom/00_syntax/17_while_loop
diff --git a/tests/00_syntax/18_if_condition b/tests/custom/00_syntax/18_if_condition
index 9e02767..9e02767 100644
--- a/tests/00_syntax/18_if_condition
+++ b/tests/custom/00_syntax/18_if_condition
diff --git a/tests/00_syntax/19_arrow_functions b/tests/custom/00_syntax/19_arrow_functions
index 102c527..102c527 100644
--- a/tests/00_syntax/19_arrow_functions
+++ b/tests/custom/00_syntax/19_arrow_functions
diff --git a/tests/00_syntax/20_list_expressions b/tests/custom/00_syntax/20_list_expressions
index d5ba459..d5ba459 100644
--- a/tests/00_syntax/20_list_expressions
+++ b/tests/custom/00_syntax/20_list_expressions
diff --git a/tests/00_syntax/21_regex_literals b/tests/custom/00_syntax/21_regex_literals
index 3af53bb..6d85e97 100644
--- a/tests/00_syntax/21_regex_literals
+++ b/tests/custom/00_syntax/21_regex_literals
@@ -23,7 +23,7 @@ regular expression engine.
Testing regular expression type.
-- Expect stdout --
-object
+regexp
-- End --
-- Testcase --
diff --git a/tests/01_arithmetic/00_value_conversion b/tests/custom/01_arithmetic/00_value_conversion
index c44ad00..c44ad00 100644
--- a/tests/01_arithmetic/00_value_conversion
+++ b/tests/custom/01_arithmetic/00_value_conversion
diff --git a/tests/01_arithmetic/01_division b/tests/custom/01_arithmetic/01_division
index d4a2adb..d4a2adb 100644
--- a/tests/01_arithmetic/01_division
+++ b/tests/custom/01_arithmetic/01_division
diff --git a/tests/01_arithmetic/02_modulo b/tests/custom/01_arithmetic/02_modulo
index 244d624..244d624 100644
--- a/tests/01_arithmetic/02_modulo
+++ b/tests/custom/01_arithmetic/02_modulo
diff --git a/tests/01_arithmetic/03_bitwise b/tests/custom/01_arithmetic/03_bitwise
index faf4ffd..faf4ffd 100644
--- a/tests/01_arithmetic/03_bitwise
+++ b/tests/custom/01_arithmetic/03_bitwise
diff --git a/tests/01_arithmetic/04_inc_dec b/tests/custom/01_arithmetic/04_inc_dec
index ae50ceb..ae50ceb 100644
--- a/tests/01_arithmetic/04_inc_dec
+++ b/tests/custom/01_arithmetic/04_inc_dec
diff --git a/tests/02_runtime/00_scoping b/tests/custom/02_runtime/00_scoping
index 5fadf43..5fadf43 100644
--- a/tests/02_runtime/00_scoping
+++ b/tests/custom/02_runtime/00_scoping
diff --git a/tests/02_runtime/01_break_continue b/tests/custom/02_runtime/01_break_continue
index a27d072..a27d072 100644
--- a/tests/02_runtime/01_break_continue
+++ b/tests/custom/02_runtime/01_break_continue
diff --git a/tests/02_runtime/02_this b/tests/custom/02_runtime/02_this
index d8e85d2..d8e85d2 100644
--- a/tests/02_runtime/02_this
+++ b/tests/custom/02_runtime/02_this
diff --git a/tests/02_runtime/03_try_catch b/tests/custom/02_runtime/03_try_catch
index 751ca1d..751ca1d 100644
--- a/tests/02_runtime/03_try_catch
+++ b/tests/custom/02_runtime/03_try_catch
diff --git a/tests/02_runtime/04_switch_case b/tests/custom/02_runtime/04_switch_case
index 4c1fc57..4c1fc57 100644
--- a/tests/02_runtime/04_switch_case
+++ b/tests/custom/02_runtime/04_switch_case
diff --git a/tests/02_runtime/05_closure_scope b/tests/custom/02_runtime/05_closure_scope
index c59a433..c59a433 100644
--- a/tests/02_runtime/05_closure_scope
+++ b/tests/custom/02_runtime/05_closure_scope
diff --git a/tests/02_runtime/06_recursion b/tests/custom/02_runtime/06_recursion
index 470fc3a..470fc3a 100644
--- a/tests/02_runtime/06_recursion
+++ b/tests/custom/02_runtime/06_recursion
diff --git a/tests/03_bugs/01_try_catch_stack_mismatch b/tests/custom/03_bugs/01_try_catch_stack_mismatch
index f6e5a0a..f6e5a0a 100644
--- a/tests/03_bugs/01_try_catch_stack_mismatch
+++ b/tests/custom/03_bugs/01_try_catch_stack_mismatch
diff --git a/tests/03_bugs/02_array_pop_use_after_free b/tests/custom/03_bugs/02_array_pop_use_after_free
index 22f63ff..22f63ff 100644
--- a/tests/03_bugs/02_array_pop_use_after_free
+++ b/tests/custom/03_bugs/02_array_pop_use_after_free
diff --git a/tests/03_bugs/03_switch_fallthrough_miscompilation b/tests/custom/03_bugs/03_switch_fallthrough_miscompilation
index 3e6410e..3e6410e 100644
--- a/tests/03_bugs/03_switch_fallthrough_miscompilation
+++ b/tests/custom/03_bugs/03_switch_fallthrough_miscompilation
diff --git a/tests/03_bugs/04_property_set_abort b/tests/custom/03_bugs/04_property_set_abort
index 8af477f..8af477f 100644
--- a/tests/03_bugs/04_property_set_abort
+++ b/tests/custom/03_bugs/04_property_set_abort
diff --git a/tests/03_bugs/05_duplicate_ressource_type b/tests/custom/03_bugs/05_duplicate_ressource_type
index 21166b2..21166b2 100644
--- a/tests/03_bugs/05_duplicate_ressource_type
+++ b/tests/custom/03_bugs/05_duplicate_ressource_type
diff --git a/tests/03_bugs/06_lexer_escape_at_boundary b/tests/custom/03_bugs/06_lexer_escape_at_boundary
index e80b0a1..e80b0a1 100644
--- a/tests/03_bugs/06_lexer_escape_at_boundary
+++ b/tests/custom/03_bugs/06_lexer_escape_at_boundary
diff --git a/tests/03_bugs/07_lexer_overlong_lines b/tests/custom/03_bugs/07_lexer_overlong_lines
index d2dd3be..d2dd3be 100644
--- a/tests/03_bugs/07_lexer_overlong_lines
+++ b/tests/custom/03_bugs/07_lexer_overlong_lines
diff --git a/tests/03_bugs/08_compiler_arrow_fn_expressions b/tests/custom/03_bugs/08_compiler_arrow_fn_expressions
index 5cd8960..5cd8960 100644
--- a/tests/03_bugs/08_compiler_arrow_fn_expressions
+++ b/tests/custom/03_bugs/08_compiler_arrow_fn_expressions
diff --git a/tests/03_bugs/09_reject_invalid_array_indexes b/tests/custom/03_bugs/09_reject_invalid_array_indexes
index a7e5272..a7e5272 100644
--- a/tests/03_bugs/09_reject_invalid_array_indexes
+++ b/tests/custom/03_bugs/09_reject_invalid_array_indexes
diff --git a/tests/03_bugs/10_break_stack_mismatch b/tests/custom/03_bugs/10_break_stack_mismatch
index ae16dac..ae16dac 100644
--- a/tests/03_bugs/10_break_stack_mismatch
+++ b/tests/custom/03_bugs/10_break_stack_mismatch
diff --git a/tests/03_bugs/11_switch_stack_mismatch b/tests/custom/03_bugs/11_switch_stack_mismatch
index cc3b41a..cc3b41a 100644
--- a/tests/03_bugs/11_switch_stack_mismatch
+++ b/tests/custom/03_bugs/11_switch_stack_mismatch
diff --git a/tests/03_bugs/12_altblock_stack_mismatch b/tests/custom/03_bugs/12_altblock_stack_mismatch
index e350660..e350660 100644
--- a/tests/03_bugs/12_altblock_stack_mismatch
+++ b/tests/custom/03_bugs/12_altblock_stack_mismatch
diff --git a/tests/custom/CMakeLists.txt b/tests/custom/CMakeLists.txt
new file mode 100644
index 0000000..c8007a0
--- /dev/null
+++ b/tests/custom/CMakeLists.txt
@@ -0,0 +1,22 @@
+ADD_TEST(
+ NAME custom
+ COMMAND run_tests.sh
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+SET_PROPERTY(TEST custom APPEND PROPERTY ENVIRONMENT
+ "UCODE_BIN=valgrind --quiet --leak-check=full $<TARGET_FILE:ucode>"
+ "UCODE_LIB=${CMAKE_BINARY_DIR}"
+)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_TEST(
+ NAME custom-san
+ COMMAND run_tests.sh
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+ SET_PROPERTY(TEST custom-san APPEND PROPERTY ENVIRONMENT
+ "UCODE_BIN=$<TARGET_FILE:ucode-san>"
+ "UCODE_LIB=${CMAKE_BINARY_DIR}"
+ )
+ENDIF()
diff --git a/run_tests.sh b/tests/custom/run_tests.sh
index 69010c5..61b116f 100755
--- a/run_tests.sh
+++ b/tests/custom/run_tests.sh
@@ -1,6 +1,11 @@
#!/usr/bin/env bash
+testdir=$(dirname "$0")
+topdir=$(readlink -f "$testdir/../..")
+
line='........................................'
+ucode_bin=${UCODE_BIN:-"$topdir/ucode"}
+ucode_lib=${UCODE_LIB:-"$topdir"}
extract_sections() {
local file=$1
@@ -47,7 +52,10 @@ run_testcase() {
local code=$6
local fail=0
- ./ucode -e '{ "REQUIRE_SEARCH_PATH": [ "./lib/*.so" ] }' -i - <"$in" >"$dir/res.out" 2>"$dir/res.err"
+ (
+ cd "$topdir"
+ $ucode_bin -e '{ "REQUIRE_SEARCH_PATH": [ "'"$ucode_lib"'/*.so" ] }' -i - <"$in" >"$dir/res.out" 2>"$dir/res.err"
+ )
touch "$dir/empty"
printf "%d\n" $? > "$dir/res.code"
@@ -162,7 +170,7 @@ use_test() {
return 1
}
-for catdir in tests/[0-9][0-9]_*; do
+for catdir in "$testdir/"[0-9][0-9]_*; do
[ -d "$catdir" ] || continue
printf "\n##\n## Running %s tests\n##\n\n" "${catdir##*/[0-9][0-9]_}"
@@ -176,3 +184,4 @@ for catdir in tests/[0-9][0-9]_*; do
done
printf "\nRan %d tests, %d okay, %d failures\n" $n_tests $((n_tests - n_fails)) $n_fails
+exit $n_fails
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..384e7e0
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,16 @@
+MACRO(ADD_FUZZER_TEST name)
+ ADD_EXECUTABLE(${name} ${name}.c)
+ TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+ TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+ ADD_TEST(
+ NAME ${name}
+ COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+ )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FILE(GLOB test_cases "test-*.c")
+FOREACH(test_case ${test_cases})
+ GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+ ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
diff --git a/tests/fuzz/corpus/.keep b/tests/fuzz/corpus/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/fuzz/corpus/.keep
diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 0000000..40649e2
--- /dev/null
+++ b/tests/fuzz/test-fuzz.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *input, size_t size)
+{
+ return 0;
+}
diff --git a/types.c b/types.c
new file mode 100644
index 0000000..3ed8aaa
--- /dev/null
+++ b/types.c
@@ -0,0 +1,1809 @@
+/*
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+#include <math.h>
+
+#include "types.h"
+#include "util.h"
+#include "vm.h"
+
+uc_type_t
+ucv_type(uc_value_t *uv)
+{
+ uc_type_t type = ((uintptr_t)uv & 3);
+
+ if (type == UC_NULL && uv != NULL)
+ type = uv->type;
+
+ return type;
+}
+
+const char *
+ucv_typename(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_NULL: return "null";
+ case UC_INTEGER: return "integer";
+ case UC_BOOLEAN: return "boolean";
+ case UC_STRING: return "string";
+ case UC_DOUBLE: return "double";
+ case UC_ARRAY: return "array";
+ case UC_OBJECT: return "object";
+ case UC_REGEXP: return "regexp";
+ case UC_FUNCTION: return "function";
+ case UC_CFUNCTION: return "cfunction";
+ case UC_CLOSURE: return "closure";
+ case UC_UPVALUE: return "upvalue";
+ case UC_RESSOURCE: return "ressource";
+ }
+
+ return "unknown";
+}
+
+static uc_ressource_type_t *
+ucv_ressource_type_get(size_t type);
+
+static void
+ucv_unref(uc_weakref_t *ref)
+{
+ ref->prev->next = ref->next;
+ ref->next->prev = ref->prev;
+}
+
+static void
+ucv_ref(uc_weakref_t *head, uc_weakref_t *item)
+{
+ item->next = head->next;
+ item->prev = head;
+ head->next->prev = item;
+ head->next = item;
+}
+
+#if 0
+static uc_weakref_t *
+ucv_get_weakref(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_ARRAY:
+ return &((uc_array_t *)uv)->ref;
+
+ case UC_OBJECT:
+ return &((uc_object_t *)uv)->ref;
+
+ case UC_CLOSURE:
+ return &((uc_closure_t *)uv)->ref;
+
+ default:
+ return NULL;
+ }
+}
+#endif
+
+static void
+ucv_put_value(uc_value_t *uv, bool retain)
+{
+ if (uv == NULL || (uintptr_t)uv & 3)
+ return;
+
+ assert(uv->refcount > 0);
+
+ if (uv->refcount > 0)
+ uv->refcount--;
+
+ if (uv->refcount == 0)
+ ucv_free(uv, retain);
+}
+
+static void
+ucv_gc_mark(uc_value_t *uv);
+
+static void
+ucv_gc_mark(uc_value_t *uv)
+{
+ uc_function_t *function;
+ uc_closure_t *closure;
+ uc_upvalref_t *upval;
+ uc_object_t *object;
+ uc_array_t *array;
+ struct lh_entry *entry;
+ size_t i;
+
+ switch (ucv_type(uv)) {
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+
+ ucv_gc_mark(array->proto);
+
+ for (i = 0; i < array->count; i++)
+ ucv_gc_mark(array->entries[i]);
+
+ if (array->ref.next)
+ ucv_set_mark(uv);
+
+ break;
+
+ case UC_OBJECT:
+ object = (uc_object_t *)uv;
+
+ ucv_gc_mark(object->proto);
+
+ lh_foreach(object->table, entry)
+ ucv_gc_mark((uc_value_t *)lh_entry_v(entry));
+
+ if (object->ref.next)
+ ucv_set_mark(uv);
+
+ break;
+
+ case UC_CLOSURE:
+ closure = (uc_closure_t *)uv;
+ function = closure->function;
+
+ for (i = 0; i < function->nupvals; i++)
+ ucv_gc_mark((uc_value_t *)closure->upvals[i]);
+
+ ucv_gc_mark((uc_value_t *)function);
+
+ if (closure->ref.next)
+ ucv_set_mark(uv);
+
+ break;
+
+ case UC_UPVALUE:
+ upval = (uc_upvalref_t *)uv;
+ ucv_gc_mark(upval->value);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+ucv_free(uc_value_t *uv, bool retain)
+{
+ uc_ressource_type_t *restype;
+ uc_ressource_t *ressource;
+ uc_function_t *function;
+ uc_closure_t *closure;
+ uc_upvalref_t *upval;
+ uc_regexp_t *regexp;
+ uc_object_t *object;
+ uc_array_t *array;
+ uc_weakref_t *ref;
+ size_t i;
+
+ if (uv == NULL || (uintptr_t)uv & 3)
+ return;
+
+ if (uv->mark)
+ return;
+
+ uv->mark = true;
+
+ ref = NULL;
+
+ switch (uv->type) {
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+ ref = &array->ref;
+ ucv_put_value(array->proto, retain);
+
+ for (i = 0; i < array->count; i++)
+ ucv_put_value(array->entries[i], retain);
+
+ uc_vector_clear(array);
+ break;
+
+ case UC_OBJECT:
+ object = (uc_object_t *)uv;
+ ref = &object->ref;
+ ucv_put_value(object->proto, retain);
+ lh_table_free(object->table);
+ break;
+
+ case UC_REGEXP:
+ regexp = (uc_regexp_t *)uv;
+ regfree(&regexp->regexp);
+ break;
+
+ case UC_FUNCTION:
+ function = (uc_function_t *)uv;
+ uc_chunk_free(&function->chunk);
+ uc_source_put(function->source);
+ break;
+
+ case UC_CLOSURE:
+ closure = (uc_closure_t *)uv;
+ function = closure->function;
+ ref = &closure->ref;
+
+ for (i = 0; i < function->nupvals; i++)
+ ucv_put_value((uc_value_t *)closure->upvals[i], retain);
+
+ ucv_put_value((uc_value_t *)function, retain);
+ break;
+
+ case UC_RESSOURCE:
+ ressource = (uc_ressource_t *)uv;
+ restype = ucv_ressource_type_get(ressource->type);
+
+ if (restype && restype->free)
+ restype->free(ressource->data);
+
+ break;
+
+ case UC_UPVALUE:
+ upval = (uc_upvalref_t *)uv;
+ ucv_put_value(upval->value, retain);
+ break;
+ }
+
+ if (!ref || !retain) {
+ if (ref && ref->prev && ref->next)
+ ucv_unref(ref);
+
+ free(uv);
+ }
+ else {
+ uv->type = UC_NULL;
+ }
+}
+
+void
+ucv_put(uc_value_t *uv)
+{
+ ucv_put_value(uv, false);
+}
+
+uc_value_t *
+ucv_get(uc_value_t *uv)
+{
+ if (uv == NULL || (uintptr_t)uv & 3)
+ return uv;
+
+ assert(uv->refcount < 0x03ffffff);
+
+ uv->refcount++;
+
+ return uv;
+}
+
+uc_value_t *
+ucv_boolean_new(bool val)
+{
+ uintptr_t pv = UC_BOOLEAN | (val << 2);
+
+ return (uc_value_t *)pv;
+}
+
+bool
+ucv_boolean_get(uc_value_t *uv)
+{
+ uintptr_t pv = (uintptr_t)uv;
+
+ if ((pv & 3) == UC_BOOLEAN)
+ return (pv >> 2) & 1;
+
+ return false;
+}
+
+
+uc_value_t *
+ucv_string_new(const char *str)
+{
+ return ucv_string_new_length(str, strlen(str));
+}
+
+uc_value_t *
+ucv_string_new_length(const char *str, size_t length)
+{
+ uc_string_t *ustr;
+ uintptr_t pv;
+ size_t i;
+ char *s;
+
+ if ((length + 1) < sizeof(void *)) {
+ pv = UC_STRING | (length << 2);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ s = (char *)&pv + 1;
+#else
+ s = (char *)&pv;
+#endif
+
+ for (i = 0; i < length; i++)
+ s[i] = str[i];
+
+ return (uc_value_t *)pv;
+ }
+
+ ustr = xalloc(sizeof(*ustr) + length + 1);
+ ustr->header.type = UC_STRING;
+ ustr->header.refcount = 1;
+ ustr->length = length;
+ memcpy(ustr->str, str, length);
+
+ return &ustr->header;
+}
+
+uc_stringbuf_t *
+ucv_stringbuf_new(void)
+{
+ uc_stringbuf_t *sb = xprintbuf_new();
+ uc_string_t ustr = {
+ .header = {
+ .type = UC_STRING,
+ .refcount = 1
+ }
+ };
+
+ printbuf_memappend_fast(sb, (char *)&ustr, (int)sizeof(ustr));
+
+ return sb;
+}
+
+uc_value_t *
+ucv_stringbuf_finish(uc_stringbuf_t *sb)
+{
+ uc_string_t *ustr = (uc_string_t *)sb->buf;
+
+ ustr->length = printbuf_length(sb) - offsetof(uc_string_t, str);
+
+ free(sb);
+
+ return &ustr->header;
+}
+
+char *
+_ucv_string_get(uc_value_t **uv)
+{
+ uc_string_t *str;
+
+ switch ((uintptr_t)*uv & 3) {
+ case UC_STRING:
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return (char *)uv + 1;
+#else
+ return (char *)uv;
+#endif
+
+ case UC_NULL:
+ if (*uv != NULL && (*uv)->type == UC_STRING) {
+ str = (uc_string_t *)*uv;
+
+ return str->str;
+ }
+ }
+
+ return NULL;
+}
+
+size_t
+ucv_string_length(uc_value_t *uv)
+{
+ uc_string_t *str = (uc_string_t *)uv;
+ uintptr_t pv = (uintptr_t)uv;
+
+ if ((pv & 3) == UC_STRING)
+ return (pv & 0xff) >> 2;
+ else if (uv != NULL && uv->type == UC_STRING)
+ return str->length;
+
+ return 0;
+}
+
+
+uc_value_t *
+ucv_int64_new(int64_t n)
+{
+ uint64_t uval = (n < 0) ? ((n > INT64_MIN) ? (~n + 1) : INT64_MAX) : n;
+ uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1;
+ uc_integer_t *integer;
+ uintptr_t pv;
+
+ if (uval <= max) {
+ pv = UC_INTEGER | ((n < 0) << 2) | (uval << 3);
+
+ return (uc_value_t *)pv;
+ }
+
+ integer = xalloc(sizeof(*integer));
+ integer->header.type = UC_INTEGER;
+ integer->header.refcount = 1;
+ integer->header.u64 = 0;
+ integer->i.s64 = n;
+
+ return &integer->header;
+}
+
+uc_value_t *
+ucv_uint64_new(uint64_t n)
+{
+ uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1;
+ uc_integer_t *integer;
+ uintptr_t pv;
+
+ if (n <= max) {
+ pv = UC_INTEGER | (n << 3);
+
+ return (uc_value_t *)pv;
+ }
+
+ integer = xalloc(sizeof(*integer));
+ integer->header.type = UC_INTEGER;
+ integer->header.refcount = 1;
+ integer->header.u64 = 1;
+ integer->i.u64 = n;
+
+ return &integer->header;
+}
+
+uint64_t
+ucv_uint64_get(uc_value_t *uv)
+{
+ uintptr_t pv = (uintptr_t)uv;
+ uc_integer_t *integer;
+
+ errno = 0;
+
+ if ((pv & 3) == UC_INTEGER) {
+ if (((pv >> 2) & 1) == 0)
+ return (uint64_t)(pv >> 3);
+
+ errno = ERANGE;
+
+ return 0;
+ }
+ else if (uv != NULL && uv->type == UC_INTEGER) {
+ integer = (uc_integer_t *)uv;
+
+ if (integer->header.u64)
+ return integer->i.u64;
+
+ if (integer->i.s64 >= 0)
+ return (uint64_t)integer->i.s64;
+
+ errno = ERANGE;
+
+ return 0;
+ }
+
+ errno = EINVAL;
+
+ return 0;
+}
+
+int64_t
+ucv_int64_get(uc_value_t *uv)
+{
+ uintptr_t pv = (uintptr_t)uv;
+ uc_integer_t *integer;
+
+ errno = 0;
+
+ if ((pv & 3) == UC_INTEGER) {
+ if (((pv >> 2) & 1) == 0)
+ return (int64_t)(pv >> 3);
+
+ return -(int64_t)(pv >> 3);
+ }
+ else if (uv != NULL && uv->type == UC_INTEGER) {
+ integer = (uc_integer_t *)uv;
+
+ if (integer->header.u64 && integer->i.u64 <= INT64_MAX)
+ return (int64_t)integer->i.u64;
+
+ if (!integer->header.u64)
+ return integer->i.s64;
+
+ errno = ERANGE;
+
+ return 0;
+ }
+
+ errno = EINVAL;
+
+ return 0;
+}
+
+
+uc_value_t *
+ucv_double_new(double d)
+{
+ uc_double_t *dbl;
+
+ dbl = xalloc(sizeof(*dbl));
+ dbl->header.type = UC_DOUBLE;
+ dbl->header.refcount = 1;
+ dbl->dbl = d;
+
+ return &dbl->header;
+}
+
+double
+ucv_double_get(uc_value_t *uv)
+{
+ uc_double_t *dbl;
+
+ errno = 0;
+
+ if (ucv_type(uv) != UC_DOUBLE) {
+ errno = EINVAL;
+
+ return NAN;
+ }
+
+ dbl = (uc_double_t *)uv;
+
+ return dbl->dbl;
+}
+
+
+uc_value_t *
+ucv_array_new(uc_vm *vm)
+{
+ return ucv_array_new_length(vm, 0);
+}
+
+uc_value_t *
+ucv_array_new_length(uc_vm *vm, size_t length)
+{
+ uc_array_t *array;
+
+ /* XXX */
+ length = 0;
+
+ array = xalloc(sizeof(*array) + length * sizeof(array->entries[0]));
+ array->header.type = UC_ARRAY;
+ array->header.refcount = 1;
+
+ if (length > 0)
+ array->count = length;
+
+ uc_vector_grow(array);
+
+ if (vm)
+ ucv_ref(&vm->values, &array->ref);
+
+ return &array->header;
+}
+
+uc_value_t *
+ucv_array_pop(uc_value_t *uv)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+ uc_value_t *item;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count == 0)
+ return NULL;
+
+ item = ucv_get(array->entries[array->count - 1]);
+
+ ucv_array_delete(uv, array->count - 1, 1);
+
+ return item;
+}
+
+uc_value_t *
+ucv_array_push(uc_value_t *uv, uc_value_t *item)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY)
+ return NULL;
+
+ ucv_array_set(uv, array->count, item);
+
+ return item;
+}
+
+uc_value_t *
+ucv_array_shift(uc_value_t *uv)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+ uc_value_t *item;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count == 0)
+ return NULL;
+
+ item = ucv_get(array->entries[0]);
+
+ ucv_array_delete(uv, 0, 1);
+
+ return item;
+}
+
+uc_value_t *
+ucv_array_unshift(uc_value_t *uv, uc_value_t *item)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+ size_t i;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count == 0)
+ return NULL;
+
+ array->count++;
+ uc_vector_grow(array);
+
+ for (i = array->count; i > 1; i--)
+ array->entries[i - 1] = array->entries[i - 2];
+
+ array->entries[0] = item;
+
+ return item;
+}
+
+void
+ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
+{
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count <= 1)
+ return;
+
+ qsort(array->entries, array->count, sizeof(array->entries[0]), cmp);
+}
+
+bool
+ucv_array_delete(uc_value_t *uv, size_t offset, size_t count)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+ size_t i;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count == 0)
+ return false;
+
+ if (offset >= array->count)
+ return false;
+
+ if ((offset + count) < offset)
+ return false;
+
+ if ((offset + count) > array->count)
+ count = array->count - offset;
+
+ for (i = 0; i < count; i++)
+ ucv_put(array->entries[offset + i]);
+
+ memmove(&array->entries[offset],
+ &array->entries[offset + count],
+ (array->count - (offset + count)) * sizeof(array->entries[0]));
+
+ array->count -= count;
+
+ uc_vector_grow(array);
+
+ return true;
+}
+
+bool
+ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY)
+ return false;
+
+ if (index >= array->count) {
+ array->count = index + 1;
+ uc_vector_grow(array);
+ }
+ else {
+ ucv_put(array->entries[index]);
+ }
+
+ array->entries[index] = item;
+
+ return true;
+}
+
+uc_value_t *
+ucv_array_get(uc_value_t *uv, size_t index)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY)
+ return NULL;
+
+ if (index >= array->count)
+ return NULL;
+
+ return array->entries[index];
+}
+size_t
+ucv_array_length(uc_value_t *uv)
+{
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY)
+ return 0;
+
+ return array->count;
+}
+
+
+static void
+ucv_free_object_entry(struct lh_entry *entry)
+{
+ free(lh_entry_k(entry));
+ ucv_put(lh_entry_v(entry));
+}
+
+uc_value_t *
+ucv_object_new(uc_vm *vm)
+{
+ struct lh_table *table;
+ uc_object_t *object;
+
+ table = lh_kchar_table_new(16, ucv_free_object_entry);
+
+ if (!table) {
+ fprintf(stderr, "Out of memory\n");
+ abort();
+ }
+
+ object = xalloc(sizeof(*object));
+ object->header.type = UC_OBJECT;
+ object->header.refcount = 1;
+ object->table = table;
+
+ if (vm)
+ ucv_ref(&vm->values, &object->ref);
+
+ return &object->header;
+}
+
+bool
+ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)
+{
+ uc_object_t *object = (uc_object_t *)uv;
+ struct lh_entry *existing_entry;
+ uc_value_t *existing_value;
+ unsigned long hash;
+ void *k;
+
+ if (ucv_type(uv) != UC_OBJECT)
+ return false;
+
+ hash = lh_get_hash(object->table, (const void *)key);
+ existing_entry = lh_table_lookup_entry_w_hash(object->table, (const void *)key, hash);
+
+ if (existing_entry == NULL) {
+ k = xstrdup(key);
+
+ if (lh_table_insert_w_hash(object->table, k, val, hash, 0) != 0) {
+ free(k);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ existing_value = (uc_value_t *)lh_entry_v(existing_entry);
+
+ if (existing_value)
+ ucv_put(existing_value);
+
+ existing_entry->v = val;
+
+ return true;
+}
+
+bool
+ucv_object_delete(uc_value_t *uv, const char *key)
+{
+ uc_object_t *object = (uc_object_t *)uv;
+
+ if (ucv_type(uv) != UC_OBJECT)
+ return false;
+
+ return (lh_table_delete(object->table, key) == 0);
+}
+
+uc_value_t *
+ucv_object_get(uc_value_t *uv, const char *key, bool *found)
+{
+ uc_object_t *object = (uc_object_t *)uv;
+ uc_value_t *val = NULL;
+ bool rv;
+
+ if (found != NULL)
+ *found = false;
+
+ if (ucv_type(uv) != UC_OBJECT)
+ return NULL;
+
+ rv = lh_table_lookup_ex(object->table, (const void *)key, (void **)&val);
+
+ if (found != NULL)
+ *found = rv;
+
+ return val;
+}
+
+size_t
+ucv_object_length(uc_value_t *uv)
+{
+ uc_object_t *object = (uc_object_t *)uv;
+
+ if (ucv_type(uv) != UC_OBJECT)
+ return 0;
+
+ return lh_table_length(object->table);
+}
+
+
+uc_value_t *
+ucv_function_new(const char *name, size_t srcpos, uc_source *source)
+{
+ size_t namelen = 0;
+ uc_function_t *fn;
+
+ if (name)
+ namelen = strlen(name);
+
+ fn = xalloc(sizeof(*fn) + namelen + 1);
+ fn->header.type = UC_FUNCTION;
+ fn->header.refcount = 1;
+
+ if (name)
+ strcpy(fn->name, name);
+
+ fn->nargs = 0;
+ fn->nupvals = 0;
+ fn->srcpos = srcpos;
+ fn->source = uc_source_get(source);
+ fn->vararg = false;
+
+ uc_chunk_init(&fn->chunk);
+
+ return &fn->header;
+}
+
+size_t
+ucv_function_srcpos(uc_value_t *uv, size_t off)
+{
+ uc_function_t *fn = (uc_function_t *)uv;
+ size_t pos;
+
+ if (ucv_type(uv) != UC_FUNCTION)
+ return 0;
+
+ pos = uc_chunk_debug_get_srcpos(&fn->chunk, off);
+
+ return pos ? fn->srcpos + pos : 0;
+}
+
+
+uc_value_t *
+ucv_cfunction_new(const char *name, uc_cfn_ptr_t fptr)
+{
+ uc_cfunction_t *cfn;
+ size_t namelen = 0;
+
+ if (name)
+ namelen = strlen(name);
+
+ cfn = xalloc(sizeof(*cfn) + namelen + 1);
+ cfn->header.type = UC_CFUNCTION;
+ cfn->header.refcount = 1;
+
+ if (name)
+ strcpy(cfn->name, name);
+
+ cfn->cfn = fptr;
+
+ return &cfn->header;
+}
+
+
+uc_value_t *
+ucv_closure_new(uc_vm *vm, uc_function_t *function, bool arrow_fn)
+{
+ uc_closure_t *closure;
+
+ closure = xalloc(sizeof(*closure) + (sizeof(uc_upvalref_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;
+
+ if (vm)
+ ucv_ref(&vm->values, &closure->ref);
+
+ return &closure->header;
+}
+
+
+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 *))
+{
+ uc_ressource_type_t *existing;
+
+ existing = ucv_ressource_type_lookup(name);
+
+ if (existing) {
+ ucv_put(proto);
+
+ return existing;
+ }
+
+ uc_vector_grow(&res_types);
+
+ res_types.entries[res_types.count].name = name;
+ res_types.entries[res_types.count].proto = proto;
+ res_types.entries[res_types.count].free = freefn;
+
+ 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;
+}
+
+uc_ressource_type_t *
+ucv_ressource_type_lookup(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];
+
+ return NULL;
+}
+
+
+uc_value_t *
+ucv_ressource_new(uc_ressource_type_t *type, void *data)
+{
+ uc_ressource_t *res;
+
+ res = xalloc(sizeof(*res));
+ res->header.type = UC_RESSOURCE;
+ res->header.refcount = 1;
+ res->type = type ? (type - res_types.entries) + 1 : 0;
+ res->data = data;
+
+ return &res->header;
+}
+
+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))
+ return NULL;
+ }
+
+ return &res->data;
+}
+
+
+uc_value_t *
+ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **error)
+{
+ int cflags = REG_EXTENDED, res;
+ uc_regexp_t *re;
+ size_t len;
+
+ re = xalloc(sizeof(*re) + strlen(pattern) + 1);
+ re->header.type = UC_REGEXP;
+ re->header.refcount = 1;
+ re->icase = icase;
+ re->global = global;
+ re->newline = newline;
+ strcpy(re->source, pattern);
+
+ if (icase)
+ cflags |= REG_ICASE;
+
+ if (newline)
+ cflags |= REG_NEWLINE;
+
+ res = regcomp(&re->regexp, pattern, cflags);
+
+ if (res != 0) {
+ if (error) {
+ len = regerror(res, &re->regexp, NULL, 0);
+ *error = xalloc(len);
+
+ regerror(res, &re->regexp, *error, len);
+ }
+
+ free(re);
+
+ 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;
+}
+
+
+uc_value_t *
+ucv_upvalref_new(size_t slot)
+{
+ uc_upvalref_t *up;
+
+ up = xalloc(sizeof(*up));
+ up->header.type = UC_UPVALUE;
+ up->header.refcount = 1;
+ up->slot = slot;
+
+ return &up->header;
+}
+
+
+uc_value_t *
+ucv_prototype_get(uc_value_t *uv)
+{
+ uc_ressource_type_t *restype;
+ uc_ressource_t *ressource;
+ uc_object_t *object;
+ uc_array_t *array;
+
+ switch (ucv_type(uv)) {
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+
+ return array->proto;
+
+ case UC_OBJECT:
+ object = (uc_object_t *)uv;
+
+ return object->proto;
+
+ case UC_RESSOURCE:
+ ressource = (uc_ressource_t *)uv;
+ restype = ucv_ressource_type_get(ressource->type);
+
+ return restype ? restype->proto : NULL;
+
+ default:
+ return NULL;
+ }
+}
+
+bool
+ucv_prototype_set(uc_value_t *uv, uc_value_t *proto)
+{
+ uc_object_t *object;
+ uc_array_t *array;
+
+ if (ucv_type(proto) != UC_OBJECT)
+ return false;
+
+ switch (ucv_type(uv)) {
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+ array->proto = proto;
+
+ return true;
+
+ case UC_OBJECT:
+ object = (uc_object_t *)uv;
+ object->proto = proto;
+
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+uc_value_t *
+ucv_property_get(uc_value_t *uv, const char *key)
+{
+ uc_value_t *val;
+ bool found;
+
+ for (; uv; uv = ucv_prototype_get(uv)) {
+ val = ucv_object_get(uv, key, &found);
+
+ if (found)
+ return val;
+ }
+
+ return NULL;
+}
+
+
+uc_value_t *
+ucv_from_json(uc_vm *vm, json_object *jso)
+{
+ //uc_array_t *arr;
+ uc_value_t *uv, *item;
+ int64_t n;
+ size_t i;
+
+ switch (json_object_get_type(jso)) {
+ case json_type_null:
+ return NULL;
+
+ case json_type_boolean:
+ return ucv_boolean_new(json_object_get_boolean(jso));
+
+ case json_type_double:
+ return ucv_double_new(json_object_get_double(jso));
+
+ case json_type_int:
+ n = json_object_get_int64(jso);
+
+ if (n == INT64_MAX)
+ return ucv_uint64_new(json_object_get_uint64(jso));
+
+ return ucv_int64_new(n);
+
+ case json_type_object:
+ uv = ucv_object_new(vm);
+
+ json_object_object_foreach(jso, key, val) {
+ item = ucv_from_json(vm, val);
+
+ if (!ucv_object_add(uv, key, item))
+ ucv_put(item);
+
+#ifdef __clang_analyzer__
+ /* Clang static analyzer does not understand that the object retains
+ * our item so pretend to free it here to suppress the false positive
+ * memory leak warning. */
+ ucv_put(item);
+#endif
+ }
+
+ return uv;
+
+ case json_type_array:
+ /* XXX
+ arr = (uc_array_t *)ucv_array_new_length(vm, json_object_array_length(jso));
+
+ for (i = 0; i < arr->count; i++)
+ arr->entries[i] = ucv_from_json(vm, json_object_array_get_idx(jso, i));
+
+ return &arr->header;
+ */
+ uv = ucv_array_new(vm);
+
+ for (i = 0; i < json_object_array_length(jso); i++) {
+ item = ucv_from_json(vm, json_object_array_get_idx(jso, i));
+
+ if (!ucv_array_push(uv, item))
+ ucv_put(item);
+
+#ifdef __clang_analyzer__
+ /* Clang static analyzer does not understand that the array retains
+ * our item so pretend to free it here to suppress the false positive
+ * memory leak warning. */
+ ucv_put(item);
+#endif
+ }
+
+ return uv;
+
+ case json_type_string:
+ return ucv_string_new_length(json_object_get_string(jso), json_object_get_string_len(jso));
+ }
+
+ return NULL;
+}
+
+json_object *
+ucv_to_json(uc_value_t *uv)
+{
+ uc_regexp_t *regexp;
+ uc_array_t *array;
+ json_object *jso;
+ size_t i;
+ char *s;
+
+ switch (ucv_type(uv)) {
+ case UC_BOOLEAN:
+ return json_object_new_boolean(ucv_boolean_get(uv));
+
+ case UC_INTEGER:
+ if (ucv_is_u64(uv))
+ return json_object_new_uint64(ucv_uint64_get(uv));
+
+ return json_object_new_int64(ucv_int64_get(uv));
+
+ case UC_DOUBLE:
+ return json_object_new_double(ucv_double_get(uv));
+
+ case UC_STRING:
+ return json_object_new_string_len(ucv_string_get(uv), ucv_string_length(uv));
+
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+ jso = json_object_new_array_ext(array->count);
+
+ for (i = 0; i < array->count; i++)
+ json_object_array_put_idx(jso, i, ucv_to_json(array->entries[i]));
+
+ return jso;
+
+ case UC_OBJECT:
+ jso = json_object_new_object();
+
+ ucv_object_foreach(uv, key, val)
+ json_object_object_add(jso, key, ucv_to_json(val));
+
+ return jso;
+
+ case UC_REGEXP:
+ regexp = (uc_regexp_t *)uv;
+ i = asprintf(&s, "/%s/%s%s%s",
+ regexp->source,
+ regexp->global ? "g" : "",
+ regexp->icase ? "i" : "",
+ regexp->newline ? "s" : "");
+
+ if (i <= 0)
+ return NULL;
+
+ jso = json_object_new_string_len(s, i);
+
+ free(s);
+
+ return jso;
+
+ case UC_CLOSURE:
+ case UC_CFUNCTION:
+ case UC_FUNCTION:
+ case UC_RESSOURCE:
+ case UC_UPVALUE:
+ case UC_NULL:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static void
+ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool regexp)
+{
+ size_t i;
+
+ if (!regexp)
+ ucv_stringbuf_append(pb, "\"");
+
+ for (i = 0; s != NULL && i < len; i++, s++) {
+ switch (*s) {
+ case '"':
+ ucv_stringbuf_append(pb, "\\\"");
+ break;
+
+ case '\\':
+ ucv_stringbuf_append(pb, "\\\\");
+ break;
+
+ case '\b':
+ ucv_stringbuf_append(pb, "\\b");
+ break;
+
+ case '\f':
+ ucv_stringbuf_append(pb, "\\f");
+ break;
+
+ case '\n':
+ ucv_stringbuf_append(pb, "\\n");
+ break;
+
+ case '\r':
+ ucv_stringbuf_append(pb, "\\r");
+ break;
+
+ case '\t':
+ ucv_stringbuf_append(pb, "\\t");
+ break;
+
+ case '/':
+ if (regexp)
+ ucv_stringbuf_append(pb, "\\");
+
+ ucv_stringbuf_append(pb, "/");
+ break;
+
+ default:
+ if (*s < 0x20)
+ ucv_stringbuf_printf(pb, "\\u%04x", *s);
+ else
+ ucv_stringbuf_addstr(pb, s, 1);
+ break;
+ }
+ }
+
+ if (!regexp)
+ ucv_stringbuf_append(pb, "\"");
+}
+
+static bool
+ucv_call_tostring(uc_vm *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);
+ uc_value_t *str;
+ size_t l;
+ char *s;
+
+ if (!ucv_is_callable(tostr))
+ return false;
+
+ uc_vm_stack_push(vm, ucv_get(uv));
+ uc_vm_stack_push(vm, ucv_get(tostr));
+
+ if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE)
+ return false;
+
+ str = uc_vm_stack_pop(vm);
+
+ if (ucv_type(str) == UC_STRING) {
+ s = ucv_string_get(str);
+ l = ucv_string_length(str);
+
+ if (json)
+ ucv_to_string_json_encoded(pb, s, l, false);
+ else if (s)
+ ucv_stringbuf_addstr(pb, s, l);
+ }
+ else if (json) {
+ ucv_stringbuf_append(pb, "\"\"");
+ }
+
+ ucv_put(str);
+
+ return true;
+}
+
+void
+_ucv_stringbuf_append(uc_stringbuf_t *pb, const char *str, size_t len)
+{
+ printbuf_memappend_fast(pb, str, (int)len);
+}
+
+void
+ucv_to_stringbuf(uc_vm *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json)
+{
+ uc_ressource_type_t *restype;
+ uc_ressource_t *ressource;
+ uc_cfunction_t *cfunction;
+ uc_function_t *function;
+ uc_closure_t *closure;
+ uc_regexp_t *regexp;
+ uc_value_t *argname;
+ uc_array_t *array;
+ size_t i, l;
+ double d;
+ char *s;
+
+ if (ucv_is_marked(uv)) {
+ ucv_stringbuf_append(pb, "null");
+
+ return;
+ }
+
+ if (vm != NULL && ucv_call_tostring(vm, pb, uv, json))
+ return;
+
+ ucv_set_mark(uv);
+
+ switch (ucv_type(uv)) {
+ case UC_NULL:
+ ucv_stringbuf_append(pb, "null");
+ break;
+
+ case UC_BOOLEAN:
+ if (ucv_boolean_get(uv))
+ ucv_stringbuf_append(pb, "true");
+ else
+ ucv_stringbuf_append(pb, "false");
+ break;
+
+ case UC_INTEGER:
+ if (ucv_is_u64(uv))
+ ucv_stringbuf_printf(pb, "%" PRIu64, ucv_uint64_get(uv));
+ else
+ ucv_stringbuf_printf(pb, "%" PRId64, ucv_int64_get(uv));
+ break;
+
+ case UC_DOUBLE:
+ d = ucv_double_get(uv);
+
+ if (json && isnan(d))
+ ucv_stringbuf_append(pb, "\"NaN\"");
+ else if (json && d == INFINITY)
+ ucv_stringbuf_append(pb, "1e309");
+ else if (json && d == -INFINITY)
+ ucv_stringbuf_append(pb, "-1e309");
+ else if (isnan(d))
+ ucv_stringbuf_append(pb, "NaN");
+ else if (d == INFINITY)
+ ucv_stringbuf_append(pb, "Infinity");
+ else if (d == -INFINITY)
+ ucv_stringbuf_append(pb, "-Infinity");
+ else
+ ucv_stringbuf_printf(pb, "%g", d);
+
+ break;
+
+ case UC_STRING:
+ s = ucv_string_get(uv);
+ l = ucv_string_length(uv);
+
+ if (s) {
+ if (json)
+ ucv_to_string_json_encoded(pb, s, l, false);
+ else
+ ucv_stringbuf_addstr(pb, s, l);
+ }
+
+ break;
+
+ case UC_ARRAY:
+ array = (uc_array_t *)uv;
+
+ ucv_stringbuf_append(pb, "[");
+
+ for (i = 0; i < array->count; i++) {
+ if (i)
+ ucv_stringbuf_append(pb, ", ");
+ else
+ ucv_stringbuf_append(pb, " ");
+
+ ucv_to_stringbuf(vm, pb, array->entries[i], true);
+ }
+
+ ucv_stringbuf_append(pb, " ]");
+ break;
+
+ case UC_OBJECT:
+ ucv_stringbuf_append(pb, "{");
+
+ i = 0;
+ ucv_object_foreach(uv, key, val) {
+ if (i++)
+ ucv_stringbuf_append(pb, ", ");
+ else
+ ucv_stringbuf_append(pb, " ");
+
+ ucv_to_string_json_encoded(pb, key, strlen(key), false);
+ ucv_stringbuf_append(pb, ": ");
+ ucv_to_stringbuf(vm, pb, val, true);
+ }
+
+ ucv_stringbuf_append(pb, " }");
+ break;
+
+ case UC_REGEXP:
+ regexp = (uc_regexp_t *)uv;
+
+ if (json)
+ ucv_stringbuf_append(pb, "\"");
+
+ ucv_stringbuf_append(pb, "/");
+ ucv_to_string_json_encoded(pb, regexp->source, strlen(regexp->source), true);
+ ucv_stringbuf_append(pb, "/");
+
+ if (regexp->global)
+ ucv_stringbuf_append(pb, "g");
+
+ if (regexp->icase)
+ ucv_stringbuf_append(pb, "i");
+
+ if (regexp->newline)
+ ucv_stringbuf_append(pb, "s");
+
+ if (json)
+ ucv_stringbuf_append(pb, "\"");
+
+ break;
+
+ case UC_CLOSURE:
+ closure = (uc_closure_t *)uv;
+ function = closure->function;
+
+ if (json)
+ ucv_stringbuf_append(pb, "\"");
+
+ if (!closure->is_arrow) {
+ ucv_stringbuf_append(pb, "function");
+
+ if (function->name[0]) {
+ ucv_stringbuf_append(pb, " ");
+ ucv_stringbuf_addstr(pb, function->name, strlen(function->name));
+ }
+ }
+
+ ucv_stringbuf_append(pb, "(");
+
+ for (i = 1; i <= function->nargs; i++) {
+ argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false);
+
+ if (i > 1)
+ ucv_stringbuf_append(pb, ", ");
+
+ if (i == function->nargs && function->vararg)
+ ucv_stringbuf_append(pb, "...");
+
+ if (argname) {
+ s = ucv_string_get(argname);
+ l = ucv_string_length(argname);
+
+ if (s)
+ ucv_stringbuf_addstr(pb, s, l);
+
+ ucv_put(argname);
+
+ continue;
+ }
+
+ ucv_stringbuf_printf(pb, "[arg%zu]", i);
+ }
+
+ ucv_stringbuf_printf(pb, ")%s { ... }%s",
+ closure->is_arrow ? " =>" : "",
+ json ? "\"" : "");
+
+ break;
+
+ case UC_CFUNCTION:
+ cfunction = (uc_cfunction_t *)uv;
+
+ ucv_stringbuf_printf(pb, "%sfunction%s%s(...) { [native code] }%s",
+ json ? "\"" : "",
+ cfunction->name[0] ? " " : "",
+ cfunction->name[0] ? cfunction->name : "",
+ json ? "\"" : "");
+
+ break;
+
+ case UC_FUNCTION:
+ ucv_stringbuf_printf(pb, "%s<function %p>%s",
+ json ? "\"" : "",
+ uv,
+ json ? "\"" : "");
+
+ break;
+
+ case UC_RESSOURCE:
+ ressource = (uc_ressource_t *)uv;
+ restype = ucv_ressource_type_get(ressource->type);
+
+ ucv_stringbuf_printf(pb, "%s<%s %p>%s",
+ json ? "\"" : "",
+ restype ? restype->name : "ressource",
+ ressource->data,
+ json ? "\"" : "");
+
+ break;
+
+ case UC_UPVALUE:
+ ucv_stringbuf_printf(pb, "%s<upvalref %p>%s",
+ json ? "\"" : "",
+ uv,
+ json ? "\"" : "");
+
+ break;
+ }
+
+ ucv_clear_mark(uv);
+}
+
+static char *
+ucv_to_string_any(uc_vm *vm, uc_value_t *uv, bool json)
+{
+ uc_stringbuf_t *pb = xprintbuf_new();
+ char *rv;
+
+ ucv_to_stringbuf(vm, pb, uv, json);
+
+ rv = pb->buf;
+
+ free(pb);
+
+ return rv;
+}
+
+char *
+ucv_to_string(uc_vm *vm, uc_value_t *uv)
+{
+ return ucv_to_string_any(vm, uv, false);
+}
+
+char *
+ucv_to_jsonstring(uc_vm *vm, uc_value_t *uv)
+{
+ return ucv_to_string_any(vm, uv, true);
+}
+
+bool
+ucv_equal(uc_value_t *uv1, uc_value_t *uv2)
+{
+ uc_type_t t1 = ucv_type(uv1);
+ uc_type_t t2 = ucv_type(uv2);
+ const char *s1, *s2;
+ uint64_t u1, u2;
+ int64_t n1, n2;
+ bool b1, b2;
+
+ if (t1 != t2)
+ return false;
+
+ if (uv1 == uv2)
+ return true;
+
+ switch (t1) {
+ case UC_NULL:
+ return true;
+
+ case UC_BOOLEAN:
+ return ucv_boolean_get(uv1) == ucv_boolean_get(uv2);
+
+ case UC_DOUBLE:
+ return ucv_double_get(uv1) == ucv_double_get(uv2);
+
+ case UC_INTEGER:
+ n1 = ucv_int64_get(uv1);
+ b1 = (errno == 0);
+
+ n2 = ucv_int64_get(uv2);
+ b2 = (errno == 0);
+
+ if (b1 && b2)
+ return (n1 == n2);
+
+ u1 = ucv_uint64_get(uv1);
+ b1 = (errno == 0);
+
+ u2 = ucv_uint64_get(uv2);
+ b2 = (errno == 0);
+
+ if (b1 && b2)
+ return (u1 == u2);
+
+ return false;
+
+ case UC_STRING:
+ s1 = ucv_string_get(uv1);
+ s2 = ucv_string_get(uv2);
+ u1 = ucv_string_length(uv1);
+ u2 = ucv_string_length(uv2);
+
+ if (s1 == NULL || s2 == NULL || u1 != u2)
+ return false;
+
+ return (memcmp(s1, s2, u1) == 0);
+
+ case UC_ARRAY:
+ u1 = ucv_array_length(uv1);
+ u2 = ucv_array_length(uv2);
+
+ if (u1 != u2)
+ return false;
+
+ for (u1 = 0; u1 < u2; u1++)
+ if (!ucv_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1)))
+ return false;
+
+ return true;
+
+ case UC_OBJECT:
+ u1 = ucv_object_length(uv1);
+ u2 = ucv_object_length(uv2);
+
+ if (u1 != u2)
+ return false;
+
+ ucv_object_foreach(uv1, key, val) {
+ if (!ucv_equal(val, ucv_object_get(uv2, key, NULL)))
+ return false;
+ }
+
+ ucv_object_foreach(uv2, key2, val2) {
+ (void)val2;
+ ucv_object_get(uv1, key2, &b1);
+
+ if (!b1)
+ return false;
+ }
+
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void
+ucv_gc(uc_vm *vm, bool final)
+{
+ uc_weakref_t *ref, *tmp;
+ uc_value_t *val;
+ size_t i;
+
+ if (!final) {
+ /* mark reachable objects */
+ ucv_gc_mark(vm->globals);
+
+ for (i = 0; i < vm->callframes.count; i++)
+ ucv_gc_mark(vm->callframes.entries[i].ctx);
+
+ for (i = 0; i < vm->stack.count; i++)
+ ucv_gc_mark(vm->stack.entries[i]);
+ }
+
+ /* unref unreachable objects */
+ for (ref = vm->values.next; ref != &vm->values; ref = ref->next) {
+ val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref));
+
+ if (ucv_is_marked(val))
+ ucv_clear_mark(val);
+ else
+ ucv_free(val, true);
+ }
+
+ /* free destroyed objects */
+ for (ref = vm->values.next, tmp = ref->next; ref != &vm->values; ref = tmp, tmp = tmp->next) {
+ val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref));
+
+ if (val->type == UC_NULL) {
+ ucv_unref(ref);
+ free(val);
+ }
+ }
+}
+
+
+#ifdef __GNUC__
+
+__attribute__((destructor))
+static void ucv_ressource_types_free(void)
+{
+ size_t i;
+
+ for (i = 0; i < res_types.count; i++)
+ ucv_put(res_types.entries[i].proto);
+
+ uc_vector_clear(&res_types);
+}
+
+#endif
diff --git a/types.h b/types.h
new file mode 100644
index 0000000..9dab246
--- /dev/null
+++ b/types.h
@@ -0,0 +1,428 @@
+/*
+ * 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.
+ */
+
+#ifndef __TYPES_H_
+#define __TYPES_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <regex.h>
+#include <json-c/json.h>
+
+#include "util.h"
+
+
+/* Value types and generic value header */
+
+typedef enum uc_type_t {
+ UC_NULL,
+ UC_INTEGER,
+ UC_BOOLEAN,
+ UC_STRING,
+ UC_DOUBLE,
+ UC_ARRAY,
+ UC_OBJECT,
+ UC_REGEXP,
+ UC_FUNCTION,
+ UC_CFUNCTION,
+ UC_CLOSURE,
+ UC_UPVALUE,
+ UC_RESSOURCE
+} uc_type_t;
+
+typedef struct uc_value_t {
+ uint32_t type:4;
+ uint32_t mark:1;
+ uint32_t u64:1;
+ uint32_t refcount:26;
+} uc_value_t;
+
+
+/* Constant list defintions */
+
+typedef struct {
+ size_t isize;
+ size_t dsize;
+ uint64_t *index;
+ char *data;
+} uc_value_list;
+
+
+/* Source buffer defintions */
+
+uc_declare_vector(uc_lineinfo, uint8_t);
+
+typedef struct {
+ char *filename, *buffer;
+ FILE *fp;
+ size_t usecount, off;
+ uc_lineinfo lineinfo;
+} uc_source;
+
+
+/* Bytecode chunk defintions */
+
+typedef struct {
+ size_t from, to, target, slot;
+} uc_ehrange;
+
+typedef struct {
+ size_t from, to, slot, nameidx;
+} uc_varrange;
+
+uc_declare_vector(uc_ehranges, uc_ehrange);
+uc_declare_vector(uc_variables, uc_varrange);
+uc_declare_vector(uc_offsetinfo, uint8_t);
+
+typedef struct {
+ size_t count;
+ uint8_t *entries;
+ uc_value_list constants;
+ uc_ehranges ehranges;
+ struct {
+ uc_variables variables;
+ uc_value_list varnames;
+ uc_offsetinfo offsets;
+ } debuginfo;
+} uc_chunk;
+
+
+/* Value type structures */
+
+typedef struct uc_weakref_t {
+ struct uc_weakref_t *prev;
+ struct uc_weakref_t *next;
+} uc_weakref_t;
+
+typedef struct {
+ uc_value_t header;
+ double dbl;
+} uc_double_t;
+
+typedef struct {
+ uc_value_t header;
+ union {
+ int64_t s64;
+ uint64_t u64;
+ } i;
+} uc_integer_t;
+
+typedef struct {
+ uc_value_t header;
+ size_t length;
+ char str[];
+} uc_string_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ size_t count;
+ uc_value_t *proto;
+ uc_value_t **entries;
+} uc_array_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ uc_value_t *proto;
+ struct lh_table *table;
+} uc_object_t;
+
+typedef struct {
+ uc_value_t header;
+ regex_t regexp;
+ bool icase, newline, global;
+ char source[];
+} uc_regexp_t;
+
+typedef struct {
+ uc_value_t header;
+ bool arrow, vararg;
+ size_t nargs;
+ size_t nupvals;
+ size_t srcpos;
+ uc_chunk chunk;
+ uc_source *source;
+ char name[];
+} uc_function_t;
+
+typedef struct uc_upvalref_t {
+ uc_value_t header;
+ size_t slot;
+ bool closed;
+ uc_value_t *value;
+ struct uc_upvalref_t *next;
+} uc_upvalref_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ bool is_arrow;
+ uc_function_t *function;
+ uc_upvalref_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_value_t header;
+ uc_cfn_ptr_t cfn;
+ char name[];
+} 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);
+
+
+/* Parser definitions */
+
+typedef struct {
+ bool lstrip_blocks;
+ bool trim_blocks;
+ bool strict_declarations;
+} uc_parse_config;
+
+
+/* VM definitions */
+
+typedef enum {
+ EXCEPTION_NONE,
+ EXCEPTION_SYNTAX,
+ EXCEPTION_RUNTIME,
+ EXCEPTION_TYPE,
+ EXCEPTION_REFERENCE,
+ EXCEPTION_USER
+} uc_exception_type_t;
+
+typedef struct {
+ uc_exception_type_t type;
+ uc_value_t *stacktrace;
+ char *message;
+} uc_exception;
+
+typedef struct {
+ uint8_t *ip;
+ uc_closure_t *closure;
+ uc_cfunction_t *cfunction;
+ size_t stackframe;
+ uc_value_t *ctx;
+ bool mcall;
+} uc_callframe;
+
+uc_declare_vector(uc_callframes, uc_callframe);
+uc_declare_vector(uc_stack, uc_value_t *);
+
+struct uc_vm {
+ uc_stack stack;
+ uc_exception exception;
+ uc_callframes callframes;
+ uc_upvalref_t *open_upvals;
+ uc_parse_config *config;
+ uc_value_t *globals;
+ uc_source *sources;
+ uc_weakref_t values;
+ union {
+ uint32_t u32;
+ int32_t s32;
+ uint16_t u16;
+ int16_t s16;
+ uint8_t u8;
+ int8_t s8;
+ } arg;
+ size_t spread_values;
+ uint8_t trace;
+};
+
+
+/* Value API */
+
+typedef struct printbuf uc_stringbuf_t;
+
+void ucv_free(uc_value_t *, bool);
+void ucv_put(uc_value_t *);
+
+uc_value_t *ucv_get(uc_value_t *uv);
+
+uc_type_t ucv_type(uc_value_t *);
+const char *ucv_typename(uc_value_t *);
+
+uc_value_t *ucv_boolean_new(bool);
+bool ucv_boolean_get(uc_value_t *);
+
+uc_value_t *ucv_string_new(const char *);
+uc_value_t *ucv_string_new_length(const char *, size_t);
+size_t ucv_string_length(uc_value_t *);
+
+char *_ucv_string_get(uc_value_t **);
+#define ucv_string_get(uv) _ucv_string_get((uc_value_t **)&uv)
+
+uc_stringbuf_t *ucv_stringbuf_new(void);
+uc_value_t *ucv_stringbuf_finish(uc_stringbuf_t *);
+
+void _ucv_stringbuf_append(uc_stringbuf_t *, const char *, size_t);
+
+#define _ucv_is_literal(str) ("" str)
+#define ucv_stringbuf_append(buf, str) _ucv_stringbuf_append(buf, _ucv_is_literal(str), sizeof(str) - 1)
+#define ucv_stringbuf_addstr(buf, str, len) _ucv_stringbuf_append(buf, str, len)
+#define ucv_stringbuf_printf(buf, fmt, ...) sprintbuf(buf, fmt, __VA_ARGS__)
+
+uc_value_t *ucv_int64_new(int64_t);
+uc_value_t *ucv_uint64_new(uint64_t);
+int64_t ucv_int64_get(uc_value_t *);
+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_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 *);
+uc_value_t *ucv_array_shift(uc_value_t *);
+uc_value_t *ucv_array_unshift(uc_value_t *, uc_value_t *);
+void ucv_array_sort(uc_value_t *, int (*)(const void *, const void *));
+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_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 *);
+size_t ucv_object_length(uc_value_t *);
+
+#define ucv_object_foreach(obj, key, val) \
+ char *key = NULL; \
+ uc_value_t *val = NULL; \
+ struct lh_entry *entry##key; \
+ struct lh_entry *entry_next##key = NULL; \
+ for (entry##key = (ucv_type(obj) == UC_OBJECT) ? ((uc_object_t *)obj)->table->head : NULL; \
+ (entry##key ? (key = (char *)lh_entry_k(entry##key), \
+ val = (uc_value_t *)lh_entry_v(entry##key), \
+ entry_next##key = entry##key->next, entry##key) \
+ : 0); \
+ entry##key = entry_next##key)
+
+uc_value_t *ucv_function_new(const char *, size_t, uc_source *);
+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_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_value_t *ucv_ressource_new(uc_ressource_type_t *, void *);
+void **ucv_ressource_dataptr(uc_value_t *, const char *);
+
+uc_value_t *ucv_regexp_new(const char *, bool, bool, bool, char **);
+
+uc_value_t *ucv_upvalref_new(size_t);
+
+uc_value_t *ucv_prototype_get(uc_value_t *);
+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 *);
+json_object *ucv_to_json(uc_value_t *);
+
+char *ucv_to_string(uc_vm *, uc_value_t *);
+char *ucv_to_jsonstring(uc_vm *, uc_value_t *);
+void ucv_to_stringbuf(uc_vm *, uc_stringbuf_t *, uc_value_t *, bool);
+
+static inline bool
+ucv_is_callable(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_CLOSURE:
+ case UC_CFUNCTION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static inline bool
+ucv_is_arrowfn(uc_value_t *uv)
+{
+ uc_closure_t *closure = (uc_closure_t *)uv;
+
+ return (ucv_type(uv) == UC_CLOSURE && closure->is_arrow);
+}
+
+static inline bool
+ucv_is_u64(uc_value_t *uv)
+{
+ return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64 == true);
+}
+
+static inline bool
+ucv_is_scalar(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_NULL:
+ case UC_BOOLEAN:
+ case UC_DOUBLE:
+ case UC_INTEGER:
+ case UC_STRING:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static inline bool
+ucv_is_marked(uc_value_t *uv)
+{
+ return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->mark == true);
+}
+
+static inline void
+ucv_set_mark(uc_value_t *uv)
+{
+ if (((uintptr_t)uv & 3) == 0 && uv != NULL)
+ uv->mark = true;
+}
+
+static inline void
+ucv_clear_mark(uc_value_t *uv)
+{
+ if (((uintptr_t)uv & 3) == 0 && uv != NULL)
+ uv->mark = false;
+}
+
+bool ucv_equal(uc_value_t *, uc_value_t *);
+
+void ucv_gc(uc_vm *, bool);
+
+#endif /* __TYPES_H_ */
diff --git a/util.h b/util.h
index b7029cc..c4ea087 100644
--- a/util.h
+++ b/util.h
@@ -218,6 +218,7 @@ static inline struct json_tokener *xjs_new_tokener(void) {
return tok;
}
+__attribute__((format(printf, 2, 0)))
static inline int xasprintf(char **strp, const char *fmt, ...) {
va_list ap;
int len;
@@ -234,6 +235,7 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
return len;
}
+__attribute__((format(printf, 2, 0)))
static inline int xvasprintf(char **strp, const char *fmt, va_list ap) {
int len = vasprintf(strp, fmt, ap);
@@ -245,4 +247,15 @@ static inline int xvasprintf(char **strp, const char *fmt, va_list ap) {
return len;
}
+static inline struct printbuf *xprintbuf_new(void) {
+ struct printbuf *pb = printbuf_new();
+
+ if (!pb) {
+ fprintf(stderr, "Out of memory\n");
+ abort();
+ }
+
+ return pb;
+}
+
#endif /* __UTIL_H_ */
diff --git a/value.c b/value.c
index 4312135..0827038 100644
--- a/value.c
+++ b/value.c
@@ -23,8 +23,8 @@
#include "util.h"
#include "chunk.h"
#include "value.h"
-#include "object.h"
#include "lexer.h" /* TK_* */
+#include "vm.h"
#define TAG_TYPE uint64_t
#define TAG_BITS 3
@@ -44,70 +44,39 @@
#define UC_VALLIST_CHUNK_SIZE 8
-static int
-uc_double_tostring(json_object *v, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- double d = json_object_get_double(v);
-
- if (isnan(d))
- return sprintbuf(pb, strict ? "\"NaN\"" : "NaN");
-
- if (d == INFINITY)
- return sprintbuf(pb, strict ? "1e309" : "Infinity");
-
- if (d == -INFINITY)
- return sprintbuf(pb, strict ? "-1e309" : "-Infinity");
-
- return sprintbuf(pb, "%g", d);
-}
-
-json_object *
-uc_double_new(double v)
-{
- json_object *d = json_object_new_double(v);
-
- if (!d) {
- fprintf(stderr, "Out of memory\n");
- abort();
- }
-
- json_object_set_serializer(d, uc_double_tostring, NULL, NULL);
-
- return d;
-}
-
bool
-uc_val_is_truish(json_object *val)
+uc_val_is_truish(uc_value_t *val)
{
double d;
- switch (json_object_get_type(val)) {
- case json_type_int:
- return (json_object_get_int64(val) != 0);
+ 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 json_type_double:
- d = json_object_get_double(val);
+ case UC_DOUBLE:
+ d = ucv_double_get(val);
return (d != 0 && !isnan(d));
- case json_type_boolean:
- return (json_object_get_boolean(val) != false);
+ case UC_BOOLEAN:
+ return ucv_boolean_get(val);
- case json_type_string:
- return (json_object_get_string_len(val) > 0);
+ case UC_STRING:
+ return (ucv_string_length(val) > 0);
- case json_type_array:
- case json_type_object:
- return true;
+ case UC_NULL:
+ return false;
default:
- return false;
+ return true;
}
}
-enum json_type
-uc_cast_number(json_object *v, int64_t *n, double *d)
+uc_type_t
+uc_cast_number(uc_value_t *v, int64_t *n, double *d)
{
bool is_double = false;
const char *s;
@@ -116,27 +85,27 @@ uc_cast_number(json_object *v, int64_t *n, double *d)
*d = 0.0;
*n = 0;
- switch (json_object_get_type(v)) {
- case json_type_int:
- *n = json_object_get_int64(v);
+ switch (ucv_type(v)) {
+ case UC_INTEGER:
+ *n = ucv_int64_get(v);
- return json_type_int;
+ return UC_INTEGER;
- case json_type_double:
- *d = json_object_get_double(v);
+ case UC_DOUBLE:
+ *d = ucv_double_get(v);
- return json_type_double;
+ return UC_DOUBLE;
- case json_type_null:
- return json_type_int;
+ case UC_NULL:
+ return UC_INTEGER;
- case json_type_boolean:
- *n = json_object_get_boolean(v) ? 1 : 0;
+ case UC_BOOLEAN:
+ *n = ucv_boolean_get(v);
- return json_type_int;
+ return UC_INTEGER;
- case json_type_string:
- s = json_object_get_string(v);
+ case UC_STRING:
+ s = ucv_string_get(v);
while (isspace(*s))
s++;
@@ -162,141 +131,144 @@ uc_cast_number(json_object *v, int64_t *n, double *d)
if (*e) {
*d = NAN;
- return json_type_double;
+ return UC_DOUBLE;
}
if (is_double)
- return json_type_double;
+ return UC_DOUBLE;
- return json_type_int;
+ return UC_INTEGER;
default:
*d = NAN;
- return json_type_double;
+ return UC_DOUBLE;
}
}
-static json_object *
-uc_getproto(json_object *obj)
+static char *
+uc_tostring(uc_vm *vm, uc_value_t *val)
{
- uc_prototype *proto;
-
- switch (uc_object_type(obj)) {
- case UC_OBJ_RESSOURCE:
- proto = uc_ressource_prototype(obj);
- break;
-
- case UC_OBJ_PROTOTYPE:
- proto = uc_object_as_prototype(obj)->parent;
- break;
-
- default:
- proto = NULL;
- }
+ if (ucv_type(val) != UC_STRING)
+ return ucv_to_string(vm, val);
- return proto ? proto->header.jso : NULL;
+ return NULL;
}
-json_object *
-uc_getval(json_object *scope, json_object *key)
+static int64_t
+uc_toidx(uc_value_t *val)
{
- json_object *o, *v;
const char *k;
int64_t idx;
double d;
char *e;
- if (json_object_is_type(scope, json_type_array)) {
- /* only consider doubles with integer values as array keys */
- if (json_object_is_type(key, json_type_double)) {
- d = json_object_get_double(key);
+ /* 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)
- idx = (int64_t)d;
- else
- idx = -1;
- }
- else if (json_object_is_type(key, json_type_int)) {
- idx = json_object_get_int64(key);
- }
- else if (json_object_is_type(key, json_type_string)) {
- errno = 0;
- k = json_object_get_string(key);
- idx = strtoll(k, &e, 0);
+ if ((double)(int64_t)(d) != d)
+ return -1;
- if (errno != 0 || e == k || *e != 0)
- idx = -1;
- }
- else {
- idx = -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 (idx >= 0 && idx < json_object_array_length(scope))
- return json_object_get(json_object_array_get_idx(scope, idx));
+ 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));
}
- for (o = scope, k = key ? json_object_get_string(key) : "null"; o; o = uc_getproto(o)) {
- if (!json_object_is_type(o, json_type_object))
+ k = uc_tostring(vm, key);
+
+ for (o = scope; o; o = ucv_prototype_get(o)) {
+ if (ucv_type(o) != UC_OBJECT)
continue;
- if (json_object_object_get_ex(o, k, &v))
- return json_object_get(v);
+ v = ucv_object_get(o, k ? k : ucv_string_get(key), &found);
+
+ if (found)
+ break;
}
- return NULL;
+ free(k);
+
+ return ucv_get(v);
}
-json_object *
-uc_setval(json_object *scope, json_object *key, json_object *val)
+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 (json_object_is_type(scope, json_type_array)) {
- errno = 0;
- idx = json_object_get_int64(key);
-
- if (errno != 0)
- return NULL;
+ if (ucv_type(scope) == UC_ARRAY) {
+ idx = uc_toidx(key);
- if (json_object_array_put_idx(scope, idx, val))
+ if (idx < 0 || !ucv_array_set(scope, idx, val))
return NULL;
- return json_object_get(val);
+ return ucv_get(val);
}
- if (json_object_object_add(scope, key ? json_object_get_string(key) : "null", val))
- return NULL;
+ s = uc_tostring(vm, key);
+ rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val);
+ free(s);
- return json_object_get(val);
+ return rv ? ucv_get(val) : NULL;
}
bool
-uc_cmp(int how, json_object *v1, json_object *v2)
+uc_cmp(int how, uc_value_t *v1, uc_value_t *v2)
{
- enum json_type t1 = json_object_get_type(v1);
- enum json_type t2 = json_object_get_type(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 == json_type_string && t2 == json_type_string) {
- delta = strcmp(json_object_get_string(v1), json_object_get_string(v2));
+ if (t1 == UC_STRING && t2 == UC_STRING) {
+ delta = strcmp(ucv_string_get(v1), ucv_string_get(v2));
}
else {
- if ((t1 == json_type_array && t2 == json_type_array) ||
- (t1 == json_type_object && t2 == json_type_object)) {
- delta = (void *)v1 - (void *)v2;
+ 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 == json_type_double || t2 == json_type_double) {
- d1 = (t1 == json_type_double) ? d1 : (double)n1;
- d2 = (t2 == json_type_double) ? d2 : (double)n2;
+ 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))
@@ -339,44 +311,6 @@ uc_cmp(int how, json_object *v1, json_object *v2)
}
}
-bool
-uc_eq(json_object *v1, json_object *v2)
-{
- uc_objtype_t o1 = uc_object_type(v1);
- uc_objtype_t o2 = uc_object_type(v2);
- enum json_type t1 = json_object_get_type(v1);
- enum json_type t2 = json_object_get_type(v2);
-
- if (o1 != o2 || t1 != t2)
- return false;
-
- switch (t1) {
- case json_type_array:
- case json_type_object:
- return (v1 == v2);
-
- case json_type_boolean:
- return (json_object_get_boolean(v1) == json_object_get_boolean(v2));
-
- case json_type_double:
- if (isnan(json_object_get_double(v1)) || isnan(json_object_get_double(v2)))
- return false;
-
- return (json_object_get_double(v1) == json_object_get_double(v2));
-
- case json_type_int:
- return (json_object_get_int64(v1) == json_object_get_int64(v2));
-
- case json_type_string:
- return !strcmp(json_object_get_string(v1), json_object_get_string(v2));
-
- case json_type_null:
- return true;
- }
-
- return false;
-}
-
void
uc_vallist_init(uc_value_list *list)
{
@@ -389,14 +323,14 @@ uc_vallist_init(uc_value_list *list)
void
uc_vallist_free(uc_value_list *list)
{
- json_object *o;
+ uc_value_t *o;
size_t i;
for (i = 0; i < list->isize; i++) {
if (TAG_GET_TYPE(list->index[i]) == TAG_PTR) {
o = uc_vallist_get(list, i);
- uc_value_put(o);
- uc_value_put(o);
+ ucv_put(o);
+ ucv_put(o);
}
}
@@ -414,7 +348,7 @@ add_num(uc_value_list *list, int64_t n)
list->index[list->isize++] = (TAG_TYPE)(TAG_NUM | TAG_SET_NV(n));
}
else {
- if (list->dsize + sz > TAG_MASK) {
+ if ((TAG_TYPE)list->dsize + sz > TAG_MASK) {
fprintf(stderr, "Constant data too large\n");
abort();
}
@@ -466,7 +400,7 @@ add_dbl(uc_value_list *list, double d)
{
size_t sz = TAG_ALIGN(sizeof(d));
- if (list->dsize + sz > TAG_MASK) {
+ if ((TAG_TYPE)list->dsize + sz > TAG_MASK) {
fprintf(stderr, "Constant data too large\n");
abort();
}
@@ -507,7 +441,7 @@ add_str(uc_value_list *list, const char *s, size_t slen)
uint32_t sl;
size_t sz;
char *dst;
- int i;
+ size_t i;
if (slen > UINT32_MAX) {
fprintf(stderr, "String constant too long\n");
@@ -516,7 +450,7 @@ add_str(uc_value_list *list, const char *s, size_t slen)
sz = TAG_ALIGN(sizeof(uint32_t) + slen);
- if (list->dsize + sz > TAG_MASK) {
+ if ((TAG_TYPE)list->dsize + sz > TAG_MASK) {
fprintf(stderr, "Constant data too large\n");
abort();
}
@@ -594,7 +528,7 @@ add_ptr(uc_value_list *list, void *ptr)
{
size_t sz = TAG_ALIGN(sizeof(ptr));
- if (list->dsize + sz > TAG_MASK) {
+ if ((TAG_TYPE)list->dsize + sz > TAG_MASK) {
fprintf(stderr, "Constant data too large\n");
abort();
}
@@ -609,7 +543,7 @@ add_ptr(uc_value_list *list, void *ptr)
}
ssize_t
-uc_vallist_add(uc_value_list *list, json_object *value)
+uc_vallist_add(uc_value_list *list, uc_value_t *value)
{
ssize_t existing;
@@ -618,42 +552,43 @@ uc_vallist_add(uc_value_list *list, json_object *value)
memset(&list->index[list->isize], 0, UC_VALLIST_CHUNK_SIZE);
}
- switch (json_object_get_type(value)) {
- case json_type_int:
- existing = find_num(list, json_object_get_int64(value));
+ switch (ucv_type(value)) {
+ case UC_INTEGER:
+ /* XXX: u64 */
+ existing = find_num(list, ucv_int64_get(value));
if (existing > -1)
return existing;
- add_num(list, json_object_get_int64(value));
+ add_num(list, ucv_int64_get(value));
break;
- case json_type_double:
- existing = find_dbl(list, json_object_get_double(value));
+ case UC_DOUBLE:
+ existing = find_dbl(list, ucv_double_get(value));
if (existing > -1)
return existing;
- add_dbl(list, json_object_get_double(value));
+ add_dbl(list, ucv_double_get(value));
break;
- case json_type_string:
+ case UC_STRING:
existing = find_str(list,
- json_object_get_string(value),
- json_object_get_string_len(value));
+ ucv_string_get(value),
+ ucv_string_length(value));
if (existing > -1)
return existing;
add_str(list,
- json_object_get_string(value),
- json_object_get_string_len(value));
+ ucv_string_get(value),
+ ucv_string_length(value));
break;
- case json_type_object:
+ case UC_FUNCTION:
add_ptr(list, value);
break;
@@ -673,28 +608,28 @@ uc_vallist_type(uc_value_list *list, size_t idx)
return TAG_GET_TYPE(list->index[idx]);
}
-json_object *
+uc_value_t *
uc_vallist_get(uc_value_list *list, size_t idx)
{
char str[sizeof(TAG_TYPE)];
- size_t len;
- int n;
+ size_t n, len;
switch (uc_vallist_type(list, idx)) {
case TAG_NUM:
- return xjs_new_int64(TAG_GET_NV(list->index[idx]));
+ return ucv_int64_new(TAG_GET_NV(list->index[idx]));
case TAG_LNUM:
if (TAG_GET_OFFSET(list->index[idx]) + sizeof(int64_t) > list->dsize)
return NULL;
- return xjs_new_int64(be64toh(*(int64_t *)(list->data + TAG_GET_OFFSET(list->index[idx]))));
+ /* XXX: u64 */
+ return ucv_int64_new(be64toh(*(int64_t *)(list->data + TAG_GET_OFFSET(list->index[idx]))));
case TAG_DBL:
if (TAG_GET_OFFSET(list->index[idx]) + sizeof(double) > list->dsize)
return NULL;
- return uc_double_new(*(double *)(list->data + TAG_GET_OFFSET(list->index[idx])));
+ return ucv_double_new(*(double *)(list->data + TAG_GET_OFFSET(list->index[idx])));
case TAG_STR:
len = TAG_GET_STR_L(list->index[idx]);
@@ -702,7 +637,7 @@ uc_vallist_get(uc_value_list *list, size_t idx)
for (n = 0; n < len; n++)
str[n] = (list->index[idx] >> ((n + 1) << 3));
- return xjs_new_string_len(str, len);
+ return ucv_string_new_length(str, len);
case TAG_LSTR:
if (TAG_GET_OFFSET(list->index[idx]) + sizeof(uint32_t) > list->dsize)
@@ -713,13 +648,13 @@ uc_vallist_get(uc_value_list *list, size_t idx)
if (TAG_GET_OFFSET(list->index[idx]) + sizeof(uint32_t) + len > list->dsize)
return NULL;
- return xjs_new_string_len(list->data + TAG_GET_OFFSET(list->index[idx]) + sizeof(uint32_t), len);
+ return ucv_string_new_length(list->data + TAG_GET_OFFSET(list->index[idx]) + sizeof(uint32_t), len);
case TAG_PTR:
if (TAG_GET_OFFSET(list->index[idx]) + sizeof(void *) > list->dsize)
return NULL;
- return uc_value_get(*(json_object **)(list->data + TAG_GET_OFFSET(list->index[idx])));
+ return ucv_get(*(uc_value_t **)(list->data + TAG_GET_OFFSET(list->index[idx])));
default:
return NULL;
diff --git a/value.h b/value.h
index e9d5ce6..a3abfc6 100644
--- a/value.h
+++ b/value.h
@@ -29,6 +29,8 @@
#include <stdio.h>
+#include "types.h"
+
typedef enum {
TAG_INVAL = 0,
TAG_NUM = 1,
@@ -39,43 +41,19 @@ typedef enum {
TAG_PTR = 6
} uc_value_type_t;
-typedef struct {
- size_t isize;
- size_t dsize;
- uint64_t *index;
- char *data;
-} uc_value_list;
-
-json_object *uc_double_new(double v);
-
-bool uc_eq(json_object *v1, json_object *v2);
-bool uc_cmp(int how, json_object *v1, json_object *v2);
-bool uc_val_is_truish(json_object *val);
+bool uc_cmp(int how, uc_value_t *v1, uc_value_t *v2);
+bool uc_val_is_truish(uc_value_t *val);
-enum json_type uc_cast_number(json_object *v, int64_t *n, double *d);
+uc_type_t uc_cast_number(uc_value_t *v, int64_t *n, double *d);
-json_object *uc_getval(json_object *scope, json_object *key);
-json_object *uc_setval(json_object *scope, json_object *key, json_object *val);
+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);
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, json_object *value);
+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);
-struct json_object *uc_vallist_get(uc_value_list *list, size_t idx);
-
-#define uc_value_get(val) \
- ({ \
- struct json_object *__o = val; \
- /*fprintf(stderr, "get(%p // %s) [%d + 1] @ %s:%d\n", __o, json_object_to_json_string(__o), getrefcnt(__o), __FILE__, __LINE__);*/ \
- json_object_get(__o); \
- })
-
-#define uc_value_put(val) \
- ({ \
- struct json_object *__o = val; \
- /*fprintf(stderr, "put(%p // %s) [%d - 1] @ %s:%d\n", __o, json_object_to_json_string(__o), getrefcnt(__o), __FILE__, __LINE__);*/ \
- json_object_put(__o); \
- })
+uc_value_t *uc_vallist_get(uc_value_list *list, size_t idx);
#endif /* __VALUE_H_ */
diff --git a/vm.c b/vm.c
index ce1aa0c..ee73265 100644
--- a/vm.c
+++ b/vm.c
@@ -51,8 +51,8 @@ static const uc_insn_definition insn_defs[__I_MAX] = {
[I_LUPV] = { 0, 1, 4 },
[I_LVAL] = { 2, 1, 0 },
- [I_CLFN] = { 0, 1, 4, true },
- [I_ARFN] = { 0, 1, 4, true },
+ [I_CLFN] = { 0, 1, 4 },
+ [I_ARFN] = { 0, 1, 4 },
[I_SLOC] = { 0, 0, 4 },
[I_SUPV] = { 0, 0, 4 },
@@ -90,8 +90,8 @@ static const uc_insn_definition insn_defs[__I_MAX] = {
[I_GT] = { 2, 1, 0 },
[I_IN] = { 2, 1, 0 },
- [I_JMP] = { 0, 0, -4, true },
- [I_JMPZ] = { 1, 0, -4, true },
+ [I_JMP] = { 0, 0, -4 },
+ [I_JMPZ] = { 1, 0, -4 },
[I_COPY] = { 0, 1, 1 },
[I_POP] = { 1, 0, 0 },
@@ -124,19 +124,19 @@ uc_vm_reset_stack(uc_vm *vm)
{
while (vm->stack.count > 0) {
vm->stack.count--;
- uc_value_put(vm->stack.entries[vm->stack.count]);
+ ucv_put(vm->stack.entries[vm->stack.count]);
vm->stack.entries[vm->stack.count] = NULL;
}
}
-static json_object *
+static uc_value_t *
uc_vm_callframe_pop(uc_vm *vm);
static void
uc_vm_reset_callframes(uc_vm *vm)
{
while (vm->callframes.count > 0)
- uc_value_put(uc_vm_callframe_pop(vm));
+ ucv_put(uc_vm_callframe_pop(vm));
}
void uc_vm_init(uc_vm *vm, uc_parse_config *config)
@@ -152,19 +152,22 @@ void uc_vm_init(uc_vm *vm, uc_parse_config *config)
vm->open_upvals = NULL;
+ vm->values.prev = &vm->values;
+ vm->values.next = &vm->values;
+
uc_vm_reset_stack(vm);
}
void uc_vm_free(uc_vm *vm)
{
- uc_upvalref *ref;
+ uc_upvalref_t *ref;
- uc_value_put(vm->exception.stacktrace);
+ ucv_put(vm->exception.stacktrace);
free(vm->exception.message);
while (vm->open_upvals) {
ref = vm->open_upvals->next;
- uc_value_put(vm->open_upvals->header.jso);
+ ucv_put(&vm->open_upvals->header);
vm->open_upvals = ref;
}
@@ -172,6 +175,8 @@ void uc_vm_free(uc_vm *vm)
uc_vm_reset_stack(vm);
uc_vector_clear(&vm->stack);
uc_vector_clear(&vm->callframes);
+
+ ucv_gc(vm, true);
}
static uc_chunk *
@@ -227,9 +232,9 @@ uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk)
case -4:
vm->arg.s32 = (
- frame->ip[0] * 0x1000000 +
- frame->ip[1] * 0x10000 +
- frame->ip[2] * 0x100 +
+ frame->ip[0] * 0x1000000UL +
+ frame->ip[1] * 0x10000UL +
+ frame->ip[2] * 0x100UL +
frame->ip[3]
) - 0x7fffffff;
frame->ip += 4;
@@ -242,9 +247,9 @@ uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk)
case 4:
vm->arg.u32 = (
- frame->ip[0] * 0x1000000 +
- frame->ip[1] * 0x10000 +
- frame->ip[2] * 0x100 +
+ frame->ip[0] * 0x1000000UL +
+ frame->ip[1] * 0x10000UL +
+ frame->ip[2] * 0x100UL +
frame->ip[3]
);
frame->ip += 4;
@@ -263,11 +268,12 @@ static void
uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame)
{
uc_chunk *chunk = uc_vm_frame_chunk(frame);
- uc_function *function;
- uc_closure *closure;
- uc_upvalref *ref;
- json_object *v;
+ uc_function_t *function;
+ uc_closure_t *closure;
+ uc_upvalref_t *ref;
+ uc_value_t *v;
size_t i;
+ char *s;
fprintf(stderr, " [*] CALLFRAME[%zx]\n",
frame - vm->callframes.entries);
@@ -275,8 +281,9 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame)
fprintf(stderr, " |- stackframe %zu/%zu\n",
frame->stackframe, vm->stack.count);
- fprintf(stderr, " |- ctx %s\n",
- json_object_to_json_string(frame->ctx));
+ s = ucv_to_string(NULL, frame->ctx);
+ fprintf(stderr, " |- ctx %s\n", s);
+ free(s);
if (chunk) {
fprintf(stderr, " |- %zu constants\n",
@@ -284,12 +291,10 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame)
for (i = 0; i < chunk->constants.isize; i++) {
v = uc_chunk_get_constant(chunk, i);
-
- fprintf(stderr, " | [%zu] %s\n",
- i,
- json_object_to_json_string(v));
-
- uc_value_put(v);
+ s = ucv_to_jsonstring(NULL, v);
+ fprintf(stderr, " | [%zu] %s\n", i, s);
+ free(s);
+ ucv_put(v);
}
closure = frame->closure;
@@ -301,80 +306,88 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame)
for (i = 0; i < function->nupvals; i++) {
ref = closure->upvals[i];
v = uc_chunk_debug_get_variable(chunk, 0, i, true);
+ s = ucv_to_string(NULL, v);
+ fprintf(stderr, " [%zu] <%p> %s ", i, (void *)ref, s);
+ free(s);
- if (ref->closed)
- fprintf(stderr, " [%zu] <%p> %s {closed} %s\n",
- i,
- ref,
- json_object_to_json_string(v),
- json_object_to_json_string(ref->value));
- else
- fprintf(stderr, " [%zu] <%p> %s {open[%zu]} %s\n",
- i,
- ref,
- json_object_to_json_string(v),
- ref->slot,
- json_object_to_json_string(vm->stack.entries[ref->slot]));
-
- uc_value_put(v);
+ if (ref->closed) {
+ s = ucv_to_jsonstring(NULL, ref->value);
+ fprintf(stderr, "{closed} %s\n", s);
+ }
+ else {
+ s = ucv_to_jsonstring(NULL, vm->stack.entries[ref->slot]);
+ fprintf(stderr, "{open[%zu]} %s\n", ref->slot, s);
+ }
+
+ ucv_put(v);
+ free(s);
}
}
}
void
-uc_vm_stack_push(uc_vm *vm, json_object *value)
+uc_vm_stack_push(uc_vm *vm, uc_value_t *value)
{
+ char *s;
+
uc_vector_grow(&vm->stack);
- uc_value_put(vm->stack.entries[vm->stack.count]);
+ ucv_put(vm->stack.entries[vm->stack.count]);
vm->stack.entries[vm->stack.count] = value;
vm->stack.count++;
- if (vm->trace)
- fprintf(stderr, " [+%zd] %s\n",
- vm->stack.count - 1,
- json_object_to_json_string(value));
+ if (vm->trace) {
+ s = ucv_to_jsonstring(NULL, value);
+ fprintf(stderr, " [+%zd] %s\n", vm->stack.count - 1, s);
+ free(s);
+ }
}
-json_object *
+uc_value_t *
uc_vm_stack_pop(uc_vm *vm)
{
- json_object *rv;
+ uc_value_t *rv;
+ char *s;
vm->stack.count--;
rv = vm->stack.entries[vm->stack.count];
vm->stack.entries[vm->stack.count] = NULL;
- if (vm->trace)
- fprintf(stderr, " [-%zd] %s\n",
- vm->stack.count,
- json_object_to_json_string(rv));
+ if (vm->trace) {
+ s = ucv_to_jsonstring(NULL, rv);
+ fprintf(stderr, " [-%zd] %s\n", vm->stack.count, s);
+ free(s);
+ }
return rv;
}
-json_object *
+uc_value_t *
uc_vm_stack_peek(uc_vm *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, json_object *value)
+uc_vm_stack_set(uc_vm *vm, size_t offset, uc_value_t *value)
{
- if (vm->trace)
- fprintf(stderr, " [!%zu] %s\n",
- offset, json_object_to_json_string(value));
+ char *s;
- uc_value_put(vm->stack.entries[offset]);
+ if (vm->trace) {
+ s = ucv_to_jsonstring(NULL, value);
+ fprintf(stderr, " [!%zu] %s\n", offset, s);
+ free(s);
+ }
+
+ ucv_put(vm->stack.entries[offset]);
vm->stack.entries[offset] = value;
}
static void
-uc_vm_call_native(uc_vm *vm, json_object *ctx, uc_cfunction *fptr, bool mcall, size_t nargs)
+uc_vm_call_native(uc_vm *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs)
{
- json_object *res = NULL;
+ uc_value_t *res = NULL;
uc_callframe *frame;
/* add new callframe */
@@ -393,24 +406,25 @@ uc_vm_call_native(uc_vm *vm, json_object *ctx, uc_cfunction *fptr, bool mcall, s
res = fptr->cfn(vm, nargs);
/* reset stack */
- uc_value_put(uc_vm_callframe_pop(vm));
+ ucv_put(uc_vm_callframe_pop(vm));
/* push return value */
if (!vm->exception.type)
uc_vm_stack_push(vm, res);
else
- uc_value_put(res);
+ ucv_put(res);
}
static bool
-uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, size_t argspec)
+uc_vm_call_function(uc_vm *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);
- json_object *ellip, *arg;
- uc_function *function;
- uc_closure *closure;
+ uc_value_t *ellip, *arg;
+ uc_function_t *function;
+ uc_closure_t *closure;
uint16_t slot, tmp;
+ char *s;
/* XXX: make dependent on stack size */
if (vm->callframes.count >= 1000) {
@@ -424,11 +438,11 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s
/* argument list contains spread operations, we need to reshuffle the stack */
if (nspreads > 0) {
/* create temporary array */
- ellip = xjs_new_array_size(nargs);
+ ellip = ucv_array_new_length(vm, nargs);
/* pop original stack values and push to temp array in reverse order */
for (i = 0; i < nargs; i++)
- json_object_array_add(ellip, uc_vm_stack_pop(vm));
+ ucv_array_push(ellip, uc_vm_stack_pop(vm));
/* for each spread value index ... */
for (i = 0, slot = nargs; i < nspreads; i++) {
@@ -437,61 +451,61 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s
frame->ip += 2;
/* push each preceeding non-spread value to the stack */
- for (j = slot; j > tmp + 1; j--)
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(ellip, j - 1)));
+ for (j = slot; j > tmp + 1UL; j--)
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, j - 1)));
/* read spread value at index... */
slot = tmp;
- arg = uc_value_get(json_object_array_get_idx(ellip, slot));
+ arg = ucv_get(ucv_array_get(ellip, slot));
/* ... ensure that it is an array type ... */
- if (!json_object_is_type(arg, json_type_array)) {
- uc_vm_raise_exception(vm, EXCEPTION_TYPE,
- "(%s) is not iterable",
- json_object_to_json_string(arg));
+ if (ucv_type(arg) != UC_ARRAY) {
+ s = ucv_to_string(vm, arg);
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s);
+ free(s);
return false;
}
/* ... and push each spread array value as argument to the stack */
- for (j = 0; j < json_object_array_length(arg); j++)
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(arg, j)));
+ for (j = 0; j < ucv_array_length(arg); j++)
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(arg, j)));
- uc_value_put(arg);
+ ucv_put(arg);
}
/* push remaining non-spread arguments to the stack */
for (i = slot; i > 0; i--)
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(ellip, i - 1)));
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, i - 1)));
/* free temp array */
- uc_value_put(ellip);
+ ucv_put(ellip);
/* update arg count */
nargs = vm->stack.count - stackoff - 1;
}
/* is a native function */
- if (uc_object_is_type(fno, UC_OBJ_CFUNCTION)) {
- uc_vm_call_native(vm, ctx, uc_object_as_cfunction(fno), mcall, nargs);
+ if (ucv_type(fno) == UC_CFUNCTION) {
+ uc_vm_call_native(vm, ctx, (uc_cfunction_t *)fno, mcall, nargs);
return true;
}
- if (!uc_object_is_type(fno, UC_OBJ_CLOSURE)) {
+ if (ucv_type(fno) != UC_CLOSURE) {
uc_vm_raise_exception(vm, EXCEPTION_TYPE, "left-hand side is not a function");
return false;
}
- closure = uc_object_as_closure(fno);
+ closure = (uc_closure_t *)fno;
function = closure->function;
/* fewer arguments on stack than function expects => pad */
if (nargs < function->nargs) {
for (i = nargs; i < function->nargs; i++) {
if (function->vararg && (i + 1) == function->nargs)
- uc_vm_stack_push(vm, xjs_new_array_size(0));
+ uc_vm_stack_push(vm, ucv_array_new_length(vm, 0));
else
uc_vm_stack_push(vm, NULL);
}
@@ -501,10 +515,10 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s
else if (nargs > function->nargs - function->vararg) {
/* is a vararg function => pass excess args as array */
if (function->vararg) {
- ellip = xjs_new_array_size(nargs - (function->nargs - 1));
+ ellip = ucv_array_new_length(vm, nargs - (function->nargs - 1));
for (i = function->nargs; i <= nargs; i++)
- json_object_array_add(ellip, uc_vm_stack_peek(vm, nargs - i));
+ ucv_array_push(ellip, uc_vm_stack_peek(vm, nargs - i));
for (i = function->nargs; i <= nargs; i++)
uc_vm_stack_pop(vm);
@@ -515,7 +529,7 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s
/* static amount of args => drop excess values */
else {
for (i = function->nargs; i < nargs; i++)
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
}
}
@@ -543,19 +557,19 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
uc_chunk *chunk = uc_vm_frame_chunk(frame);
- size_t msglen = 0, srcpos;
- json_object *cnst = NULL;
- char *msg = NULL;
+ uc_stringbuf_t *buf = NULL;
+ uc_value_t *cnst = NULL;
+ size_t srcpos;
+ char *s;
- srcpos = uc_function_get_srcpos(frame->closure->function, pos - chunk->entries);
+ srcpos = ucv_function_srcpos((uc_value_t *)frame->closure->function, pos - chunk->entries);
if (last_srcpos == 0 || last_source != frame->closure->function->source || srcpos != last_srcpos) {
- format_source_context(&msg, &msglen,
- frame->closure->function->source,
- srcpos, true);
+ buf = xprintbuf_new();
- fprintf(stderr, "%s", msg);
- free(msg);
+ format_source_context(buf, frame->closure->function->source, srcpos, true);
+ fwrite(buf->buf, 1, printbuf_length(buf), stderr);
+ printbuf_free(buf);
last_source = frame->closure->function->source;
last_srcpos = srcpos;
@@ -574,13 +588,13 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
case -2:
fprintf(stderr, " {%c0x%hx}",
vm->arg.s16 < 0 ? '-' : '+',
- vm->arg.s16 < 0 ? -(unsigned)vm->arg.s16 : vm->arg.s16);
+ (uint16_t)(vm->arg.s16 < 0 ? -vm->arg.s16 : vm->arg.s16));
break;
case -4:
fprintf(stderr, " {%c0x%x}",
vm->arg.s32 < 0 ? '-' : '+',
- vm->arg.s32 < 0 ? -(unsigned)vm->arg.s32 : vm->arg.s32);
+ (uint32_t)(vm->arg.s32 < 0 ? -vm->arg.s32 : vm->arg.s32));
break;
case 1:
@@ -605,9 +619,11 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
case I_LVAR:
case I_SVAR:
cnst = uc_chunk_get_constant(uc_vm_frame_chunk(uc_vector_last(&vm->callframes)), vm->arg.u32);
+ s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL;
- fprintf(stderr, "\t; %s", cnst ? json_object_to_json_string(cnst) : "null");
- uc_value_put(cnst);
+ fprintf(stderr, "\t; %s", s ? s : "(?)");
+ ucv_put(cnst);
+ free(s);
break;
case I_LLOC:
@@ -615,9 +631,11 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
case I_SLOC:
case I_SUPV:
cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32, (insn == I_LUPV || insn == I_SUPV));
+ s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL;
- fprintf(stderr, "\t; %s", cnst ? json_object_to_json_string(cnst) : "(?)");
- uc_value_put(cnst);
+ fprintf(stderr, "\t; %s", s ? s : "(?)");
+ ucv_put(cnst);
+ free(s);
break;
case I_ULOC:
@@ -629,11 +647,14 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
if (!cnst)
cnst = uc_chunk_get_constant(uc_vm_frame_chunk(uc_vector_last(&vm->callframes)), vm->arg.u32 & 0x00ffffff);
+ s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL;
+
fprintf(stderr, "\t; %s (%s)",
- cnst ? json_object_to_json_string(cnst) : "(?)",
+ s ? s : "(?)",
insn_names[vm->arg.u32 >> 24]);
- uc_value_put(cnst);
+ ucv_put(cnst);
+ free(s);
break;
case I_UVAL:
@@ -647,14 +668,38 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn)
fprintf(stderr, "\n");
}
-static int
-uc_vm_exception_tostring(json_object *jso, struct printbuf *pb, int level, int flags)
+static uc_value_t *
+uc_vm_exception_tostring(uc_vm *vm, size_t nargs)
+{
+ uc_callframe *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");
+}
+
+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)
{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- json_object *message = json_object_object_get(jso, "message");
+ uc_value_t *exo;
+
+ if (exception_prototype == NULL) {
+ exception_prototype = ucv_object_new(vm);
+
+ ucv_object_add(exception_prototype, "tostring",
+ ucv_cfunction_new("tostring", uc_vm_exception_tostring));
+ }
+
+ exo = ucv_object_new(vm);
+
+ ucv_object_add(exo, "type", ucv_string_new(exception_type_strings[type]));
+ ucv_object_add(exo, "message", ucv_string_new(message));
+ ucv_object_add(exo, "stacktrace", ucv_get(stacktrace));
- return sprintbuf(pb, "%s",
- strict ? json_object_to_json_string(message) : json_object_get_string(message));
+ ucv_prototype_set(exo, ucv_get(exception_prototype));
+
+ return exo;
}
static bool
@@ -662,7 +707,7 @@ uc_vm_handle_exception(uc_vm *vm)
{
uc_callframe *frame = uc_vm_current_frame(vm);
uc_chunk *chunk = NULL;
- json_object *exo;
+ uc_value_t *exo;
size_t i, pos;
if (!frame->closure)
@@ -680,16 +725,11 @@ uc_vm_handle_exception(uc_vm *vm)
/* we found a matching range... first unwind stack */
while (vm->stack.count > frame->stackframe + chunk->ehranges.entries[i].slot)
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
/* prepare exception object and expose it to user handler code */
- exo = xjs_new_object();
-
- json_object_object_add(exo, "type", xjs_new_string(exception_type_strings[vm->exception.type]));
- json_object_object_add(exo, "message", xjs_new_string(vm->exception.message));
- json_object_object_add(exo, "stacktrace", uc_value_get(vm->exception.stacktrace));
+ exo = uc_vm_exception_new(vm, vm->exception.type, vm->exception.message, vm->exception.stacktrace);
- json_object_set_serializer(exo, uc_vm_exception_tostring, NULL, NULL);
uc_vm_stack_push(vm, exo);
/* reset exception information */
@@ -721,35 +761,35 @@ uc_vm_handle_exception(uc_vm *vm)
return false;
}
-static json_object *
+static uc_value_t *
uc_vm_capture_stacktrace(uc_vm *vm, size_t i)
{
- json_object *stacktrace, *entry, *last = NULL;
- uc_function *function;
+ uc_value_t *stacktrace, *entry, *last = NULL;
+ uc_function_t *function;
uc_callframe *frame;
size_t off, srcpos;
char *name;
- stacktrace = xjs_new_array();
+ stacktrace = ucv_array_new(vm);
for (; i > 0; i--) {
frame = &vm->callframes.entries[i - 1];
- entry = xjs_new_object();
+ entry = ucv_object_new(vm);
if (frame->closure) {
function = frame->closure->function;
off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1;
- srcpos = uc_function_get_srcpos(function, off);
+ srcpos = ucv_function_srcpos((uc_value_t *)function, off);
- json_object_object_add(entry, "filename", xjs_new_string(function->source->filename));
- json_object_object_add(entry, "line", xjs_new_int64(uc_source_get_line(function->source, &srcpos)));
- json_object_object_add(entry, "byte", xjs_new_int64(srcpos));
+ 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)));
+ ucv_object_add(entry, "byte", ucv_int64_new(srcpos));
}
if (i > 1) {
if (frame->closure) {
- if (frame->closure->function->name)
+ if (frame->closure->function->name[0])
name = frame->closure->function->name;
else if (frame->closure->is_arrow)
name = "[arrow function]";
@@ -760,29 +800,29 @@ uc_vm_capture_stacktrace(uc_vm *vm, size_t i)
name = frame->cfunction->name;
}
- json_object_object_add(entry, "function", xjs_new_string(name));
+ ucv_object_add(entry, "function", ucv_string_new(name));
}
- if (!json_object_equal(last, entry)) {
- json_object_array_add(stacktrace, entry);
+ if (!ucv_equal(last, entry)) {
+ ucv_array_push(stacktrace, entry);
last = entry;
}
else {
- uc_value_put(entry);
+ ucv_put(entry);
}
}
return stacktrace;
}
-static json_object *
+static uc_value_t *
uc_vm_get_error_context(uc_vm *vm)
{
- json_object *stacktrace;
+ uc_value_t *stacktrace;
uc_callframe *frame;
+ uc_stringbuf_t *buf;
uc_chunk *chunk;
- size_t offset, len = 0, i;
- char *msg = NULL;
+ size_t offset, i;
/* skip to first non-native function call frame */
for (i = vm->callframes.count; i > 0; i--)
@@ -795,17 +835,19 @@ uc_vm_get_error_context(uc_vm *vm)
return NULL;
chunk = uc_vm_frame_chunk(frame);
- offset = uc_function_get_srcpos(frame->closure->function, (frame->ip - chunk->entries) - 1);
+ offset = ucv_function_srcpos((uc_value_t *)frame->closure->function, (frame->ip - chunk->entries) - 1);
stacktrace = uc_vm_capture_stacktrace(vm, i);
+ buf = ucv_stringbuf_new();
+
if (offset)
- format_error_context(&msg, &len, frame->closure->function->source, stacktrace, offset);
+ format_error_context(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
- xasprintf(&msg, "At offset %zu", (frame->ip - chunk->entries) - 1);
-
- json_object_object_add(json_object_array_get_idx(stacktrace, 0), "context", xjs_new_string(msg));
+ ucv_stringbuf_append(buf, "At start of program");
- free(msg);
+ ucv_object_add(ucv_array_get(stacktrace, 0), "context", ucv_stringbuf_finish(buf));
return stacktrace;
}
@@ -823,7 +865,7 @@ uc_vm_raise_exception(uc_vm *vm, uc_exception_type_t type, const char *fmt, ...)
xvasprintf(&vm->exception.message, fmt, ap);
va_end(ap);
- uc_value_put(vm->exception.stacktrace);
+ ucv_put(vm->exception.stacktrace);
vm->exception.stacktrace = uc_vm_get_error_context(vm);
}
@@ -837,15 +879,15 @@ uc_vm_insn_load(uc_vm *vm, enum insn_type insn)
break;
case I_LOAD8:
- uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s8));
+ uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s8));
break;
case I_LOAD16:
- uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s16));
+ uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s16));
break;
case I_LOAD32:
- uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s32));
+ uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s32));
break;
default:
@@ -856,33 +898,33 @@ 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_value_t *re, *jstr = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32);
bool icase = false, newline = false, global = false;
- json_object *jstr = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32);
- const char *str;
- uc_regexp *re;
- char *err;
+ char *str, *err = NULL;
- if (!json_object_is_type(jstr, json_type_string) || json_object_get_string_len(jstr) < 2) {
+ if (ucv_type(jstr) != UC_STRING || ucv_string_length(jstr) < 2) {
uc_vm_stack_push(vm, NULL);
- uc_value_put(jstr);
+ ucv_put(jstr);
return;
}
- str = json_object_get_string(jstr);
+ str = ucv_string_get(jstr);
global = (*str & (1 << 0));
icase = (*str & (1 << 1));
newline = (*str & (1 << 2));
- re = uc_regexp_new(++str, icase, newline, global, &err);
+ re = ucv_regexp_new(++str, icase, newline, global, &err);
- uc_value_put(jstr);
+ ucv_put(jstr);
if (re)
- uc_vm_stack_push(vm, re->header.jso);
+ uc_vm_stack_push(vm, re);
else
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err);
+
+ free(err);
}
static void
@@ -894,29 +936,32 @@ uc_vm_insn_load_null(uc_vm *vm, enum insn_type insn)
static void
uc_vm_insn_load_bool(uc_vm *vm, enum insn_type insn)
{
- uc_vm_stack_push(vm, xjs_new_boolean(insn == I_LTRUE));
+ 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)
{
- json_object *name, *val = NULL;
- uc_prototype *scope, *next;
+ uc_value_t *name, *val = NULL;
+ uc_value_t *scope, *next;
+ bool found;
scope = vm->globals;
name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32);
- while (json_object_get_type(name) == json_type_string) {
- if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), &val))
+ while (ucv_type(name) == UC_STRING) {
+ val = ucv_object_get(scope, ucv_string_get(name), &found);
+
+ if (found)
break;
- next = scope->parent;
+ next = ucv_prototype_get(scope);
if (!next) {
if (vm->config->strict_declarations) {
uc_vm_raise_exception(vm, EXCEPTION_REFERENCE,
"access to undeclared variable %s",
- json_object_get_string(name));
+ ucv_string_get(name));
}
break;
@@ -925,21 +970,21 @@ uc_vm_insn_load_var(uc_vm *vm, enum insn_type insn)
scope = next;
}
- uc_value_put(name);
+ ucv_put(name);
- uc_vm_stack_push(vm, uc_value_get(val));
+ uc_vm_stack_push(vm, ucv_get(val));
}
static void
uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn)
{
- json_object *k = uc_vm_stack_pop(vm);
- json_object *v = uc_vm_stack_pop(vm);
+ uc_value_t *k = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
- switch (json_object_get_type(v)) {
- case json_type_object:
- case json_type_array:
- uc_vm_stack_push(vm, uc_getval(v, k));
+ switch (ucv_type(v)) {
+ case UC_OBJECT:
+ case UC_ARRAY:
+ uc_vm_stack_push(vm, uc_getval(vm, v, k));
break;
default:
@@ -950,21 +995,20 @@ uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn)
break;
}
-
- uc_value_put(k);
- uc_value_put(v);
+ ucv_put(k);
+ ucv_put(v);
}
static void
uc_vm_insn_load_upval(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- uc_upvalref *ref = frame->closure->upvals[vm->arg.u32];
+ uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32];
if (ref->closed)
- uc_vm_stack_push(vm, uc_value_get(ref->value));
+ uc_vm_stack_push(vm, ucv_get(ref->value));
else
- uc_vm_stack_push(vm, uc_value_get(vm->stack.entries[ref->slot]));
+ uc_vm_stack_push(vm, ucv_get(vm->stack.entries[ref->slot]));
}
static void
@@ -972,15 +1016,16 @@ uc_vm_insn_load_local(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- uc_vm_stack_push(vm, uc_value_get(vm->stack.entries[frame->stackframe + vm->arg.u32]));
+ uc_vm_stack_push(vm, ucv_get(vm->stack.entries[frame->stackframe + vm->arg.u32]));
}
-static uc_upvalref *
+static uc_upvalref_t *
uc_vm_capture_upval(uc_vm *vm, size_t slot)
{
- uc_upvalref *curr = vm->open_upvals;
- uc_upvalref *prev = NULL;
- uc_upvalref *created;
+ uc_upvalref_t *curr = vm->open_upvals;
+ uc_upvalref_t *prev = NULL;
+ uc_upvalref_t *created;
+ char *s;
while (curr && curr->slot > slot) {
prev = curr;
@@ -988,23 +1033,23 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot)
}
if (curr && curr->slot == slot) {
- if (vm->trace)
- fprintf(stderr, " {+%zu} <%p> %s\n",
- slot,
- curr,
- json_object_to_json_string(vm->stack.entries[slot]));
+ if (vm->trace) {
+ s = ucv_to_string(NULL, vm->stack.entries[slot]);
+ fprintf(stderr, " {+%zu} <%p> %s\n", slot, (void *)curr, s);
+ free(s);
+ }
return curr;
}
- created = uc_upvalref_new(slot);
+ created = (uc_upvalref_t *)ucv_upvalref_new(slot);
created->next = curr;
- if (vm->trace)
- fprintf(stderr, " {*%zu} <%p> %s\n",
- slot,
- created,
- json_object_to_json_string(vm->stack.entries[slot]));
+ if (vm->trace) {
+ s = ucv_to_string(NULL, vm->stack.entries[slot]);
+ fprintf(stderr, " {*%zu} <%p> %s\n", slot, (void *)created, s);
+ free(s);
+ }
if (prev)
prev->next = created;
@@ -1017,21 +1062,22 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot)
static void
uc_vm_close_upvals(uc_vm *vm, size_t slot)
{
- uc_upvalref *ref;
+ uc_upvalref_t *ref;
+ char *s;
while (vm->open_upvals && vm->open_upvals->slot >= slot) {
ref = vm->open_upvals;
- ref->value = uc_value_get(vm->stack.entries[ref->slot]);
+ ref->value = ucv_get(vm->stack.entries[ref->slot]);
ref->closed = true;
- if (vm->trace)
- fprintf(stderr, " {!%zu} <%p> %s\n",
- ref->slot,
- ref,
- json_object_to_json_string(ref->value));
+ if (vm->trace) {
+ s = ucv_to_string(NULL, ref->value);
+ fprintf(stderr, " {!%zu} <%p> %s\n", ref->slot, (void *)ref, s);
+ free(s);
+ }
vm->open_upvals = ref->next;
- json_object_put(ref->header.jso);
+ ucv_put(&ref->header);
}
}
@@ -1039,13 +1085,13 @@ static void
uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- json_object *fno = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32);
- uc_function *function = uc_object_as_function(fno);
- uc_closure *closure = uc_closure_new(function, insn == I_ARFN);
+ 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);
volatile int32_t uv;
size_t i;
- uc_vm_stack_push(vm, closure->header.jso);
+ uc_vm_stack_push(vm, &closure->header);
for (i = 0; i < function->nupvals; i++) {
uv = (
@@ -1060,7 +1106,7 @@ uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn)
else
closure->upvals[i] = frame->closure->upvals[uv];
- uc_value_get(closure->upvals[i]->header.jso);
+ ucv_get(&closure->upvals[i]->header);
frame->ip += 4;
}
@@ -1069,23 +1115,26 @@ 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)
{
- json_object *name, *v = uc_vm_stack_pop(vm);
- uc_prototype *scope, *next;
+ uc_value_t *name, *v = uc_vm_stack_pop(vm);
+ uc_value_t *scope, *next;
+ bool found;
scope = vm->globals;
name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32);
- while (json_object_get_type(name) == json_type_string) {
- if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), NULL))
+ while (ucv_type(name) == UC_STRING) {
+ ucv_object_get(scope, ucv_string_get(name), &found);
+
+ if (found)
break;
- next = scope->parent;
+ next = ucv_prototype_get(scope);
if (!next) {
if (vm->config->strict_declarations) {
uc_vm_raise_exception(vm, EXCEPTION_REFERENCE,
"access to undeclared variable %s",
- json_object_get_string(name));
+ ucv_string_get(name));
}
break;
@@ -1094,53 +1143,45 @@ uc_vm_insn_store_var(uc_vm *vm, enum insn_type insn)
scope = next;
}
- if (scope && json_object_get_type(name) == json_type_string)
- json_object_object_add(scope->header.jso, json_object_get_string(name), uc_value_get(v));
+ if (scope && ucv_type(name) == UC_STRING)
+ ucv_object_add(scope, ucv_string_get(name), ucv_get(v));
- uc_value_put(name);
+ ucv_put(name);
uc_vm_stack_push(vm, v);
}
static void
uc_vm_insn_store_val(uc_vm *vm, enum insn_type insn)
{
- json_object *v = uc_vm_stack_pop(vm);
- json_object *k = uc_vm_stack_pop(vm);
- json_object *o = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
+ uc_value_t *k = uc_vm_stack_pop(vm);
+ uc_value_t *o = uc_vm_stack_pop(vm);
- const char *typenames[] = {
- [json_type_string] = "string",
- [json_type_int] = "integer",
- [json_type_double] = "double",
- [json_type_boolean] = "boolean",
- [json_type_null] = "null"
- };
-
- switch (json_object_get_type(o)) {
- case json_type_object:
- case json_type_array:
- uc_vm_stack_push(vm, uc_setval(o, k, v));
+ switch (ucv_type(o)) {
+ case UC_OBJECT:
+ case UC_ARRAY:
+ uc_vm_stack_push(vm, uc_setval(vm, o, k, v));
break;
default:
uc_vm_raise_exception(vm, EXCEPTION_TYPE,
"attempt to set property on %s value",
- typenames[json_object_get_type(o)]);
+ ucv_typename(o));
}
- uc_value_put(o);
- uc_value_put(k);
+ ucv_put(o);
+ ucv_put(k);
}
static void
uc_vm_insn_store_upval(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- uc_upvalref *ref = frame->closure->upvals[vm->arg.u32];
- json_object *val = uc_value_get(uc_vm_stack_peek(vm, 0));
+ uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32];
+ uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0));
if (ref->closed) {
- uc_value_put(ref->value);
+ ucv_put(ref->value);
ref->value = val;
}
else {
@@ -1152,43 +1193,43 @@ static void
uc_vm_insn_store_local(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- json_object *val = uc_value_get(uc_vm_stack_peek(vm, 0));
+ uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0));
uc_vm_stack_set(vm, frame->stackframe + vm->arg.u32, val);
}
-static json_object *
-uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, json_object *value, json_object *operand)
+static uc_value_t *
+uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand)
{
- json_object *rv = NULL;
+ uc_value_t *rv = NULL;
int64_t n1, n2;
double d;
- if (uc_cast_number(value, &n1, &d) == json_type_double)
+ if (uc_cast_number(value, &n1, &d) == UC_DOUBLE)
n1 = isnan(d) ? 0 : (int64_t)d;
- if (uc_cast_number(operand, &n2, &d) == json_type_double)
+ if (uc_cast_number(operand, &n2, &d) == UC_DOUBLE)
n2 = isnan(d) ? 0 : (int64_t)d;
switch (operation) {
case I_LSHIFT:
- rv = xjs_new_int64(n1 << n2);
+ rv = ucv_int64_new(n1 << n2);
break;
case I_RSHIFT:
- rv = xjs_new_int64(n1 >> n2);
+ rv = ucv_int64_new(n1 >> n2);
break;
case I_BAND:
- rv = xjs_new_int64(n1 & n2);
+ rv = ucv_int64_new(n1 & n2);
break;
case I_BXOR:
- rv = xjs_new_int64(n1 ^ n2);
+ rv = ucv_int64_new(n1 ^ n2);
break;
case I_BOR:
- rv = xjs_new_int64(n1 | n2);
+ rv = ucv_int64_new(n1 | n2);
break;
default:
@@ -1198,32 +1239,32 @@ uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, json_object *value, json_
return rv;
}
-static json_object *
-uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_object *operand)
+static uc_value_t *
+uc_vm_value_arith(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand)
{
- json_object *rv = NULL;
- enum json_type t1, t2;
- const char *s1, *s2;
+ uc_value_t *rv = NULL;
+ uc_type_t t1, t2;
+ char *s, *s1, *s2;
size_t len1, len2;
int64_t n1, n2;
double d1, d2;
- char *s;
if (operation > I_MOD)
return uc_vm_value_bitop(vm, operation, value, operand);
- if (operation == I_ADD &&
- (json_object_is_type(value, json_type_string) ||
- json_object_is_type(operand, json_type_string))) {
- s1 = value ? json_object_get_string(value) : "null";
- s2 = operand ? json_object_get_string(operand) : "null";
- len1 = strlen(s1);
- len2 = strlen(s2);
+ if (operation == I_ADD && (ucv_type(value) == UC_STRING || ucv_type(operand) == UC_STRING)) {
+ s1 = (ucv_type(value) != UC_STRING) ? ucv_to_string(vm, value) : NULL;
+ s2 = (ucv_type(operand) != UC_STRING) ? ucv_to_string(vm, operand) : NULL;
+ len1 = s1 ? strlen(s1) : ucv_string_length(value);
+ len2 = s2 ? strlen(s2) : ucv_string_length(operand);
s = xalloc(len1 + len2 + 1);
- snprintf(s, len1 + len2 + 1, "%s%s", s1, s2);
+ memcpy(s, s1 ? s1 : ucv_string_get(value), len1);
+ memcpy(s + len1, s2 ? s2 : ucv_string_get(operand), len2);
+ free(s1);
+ free(s2);
- rv = xjs_new_string(s);
+ rv = ucv_string_new_length(s, len1 + len2);
free(s);
@@ -1233,38 +1274,38 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_
t1 = uc_cast_number(value, &n1, &d1);
t2 = uc_cast_number(operand, &n2, &d2);
- if (t1 == json_type_double || t2 == json_type_double) {
- d1 = (t1 == json_type_double) ? d1 : (double)n1;
- d2 = (t2 == json_type_double) ? d2 : (double)n2;
+ if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) {
+ d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1;
+ d2 = (t2 == UC_DOUBLE) ? d2 : (double)n2;
switch (operation) {
case I_ADD:
case I_PLUS:
- rv = uc_double_new(d1 + d2);
+ rv = ucv_double_new(d1 + d2);
break;
case I_SUB:
- rv = uc_double_new(d1 - d2);
+ rv = ucv_double_new(d1 - d2);
break;
case I_MUL:
- rv = uc_double_new(d1 * d2);
+ rv = ucv_double_new(d1 * d2);
break;
case I_DIV:
if (d2 == 0.0)
- rv = uc_double_new(INFINITY);
+ rv = ucv_double_new(INFINITY);
else if (isnan(d2))
- rv = uc_double_new(NAN);
+ rv = ucv_double_new(NAN);
else if (!isfinite(d2))
- rv = uc_double_new(isfinite(d1) ? 0.0 : NAN);
+ rv = ucv_double_new(isfinite(d1) ? 0.0 : NAN);
else
- rv = uc_double_new(d1 / d2);
+ rv = ucv_double_new(d1 / d2);
break;
case I_MOD:
- rv = uc_double_new(NAN);
+ rv = ucv_double_new(NAN);
break;
default:
@@ -1278,27 +1319,27 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_
switch (operation) {
case I_ADD:
case I_PLUS:
- rv = xjs_new_int64(n1 + n2);
+ rv = ucv_int64_new(n1 + n2);
break;
case I_SUB:
- rv = xjs_new_int64(n1 - n2);
+ rv = ucv_int64_new(n1 - n2);
break;
case I_MUL:
- rv = xjs_new_int64(n1 * n2);
+ rv = ucv_int64_new(n1 * n2);
break;
case I_DIV:
if (n2 == 0)
- rv = uc_double_new(INFINITY);
+ rv = ucv_double_new(INFINITY);
else
- rv = xjs_new_int64(n1 / n2);
+ rv = ucv_int64_new(n1 / n2);
break;
case I_MOD:
- rv = xjs_new_int64(n1 % n2);
+ rv = ucv_int64_new(n1 % n2);
break;
default:
@@ -1315,25 +1356,28 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_
static void
uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn)
{
- json_object *name, *val, *inc = uc_vm_stack_pop(vm);
- uc_prototype *scope, *next;
+ uc_value_t *name, *val, *inc = uc_vm_stack_pop(vm);
+ uc_value_t *scope, *next;
+ bool found;
scope = vm->globals;
name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32 & 0x00FFFFFF);
- assert(json_object_is_type(name, json_type_string));
+ assert(ucv_type(name) == UC_STRING);
- while (true) {
- if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), &val))
+ while (true) {
+ val = ucv_object_get(scope, ucv_string_get(name), &found);
+
+ if (found)
break;
- next = scope->parent;
+ next = ucv_prototype_get(scope);
if (!next) {
if (vm->config->strict_declarations) {
uc_vm_raise_exception(vm, EXCEPTION_REFERENCE,
"access to undeclared variable %s",
- json_object_get_string(name));
+ ucv_string_get(name));
}
break;
@@ -1344,26 +1388,26 @@ uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn)
val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc);
- json_object_object_add(scope->header.jso, json_object_get_string(name), uc_value_get(val));
+ ucv_object_add(scope, ucv_string_get(name), ucv_get(val));
uc_vm_stack_push(vm, val);
- uc_value_put(name);
- uc_value_put(inc);
+ ucv_put(name);
+ ucv_put(inc);
}
static void
uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn)
{
- json_object *inc = uc_vm_stack_pop(vm);
- json_object *k = uc_vm_stack_pop(vm);
- json_object *v = uc_vm_stack_pop(vm);
- json_object *val = NULL;
+ uc_value_t *inc = uc_vm_stack_pop(vm);
+ uc_value_t *k = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
+ uc_value_t *val = NULL;
- switch (json_object_get_type(v)) {
- case json_type_object:
- case json_type_array:
- val = uc_getval(v, k);
- uc_vm_stack_push(vm, uc_setval(v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc)));
+ 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)));
break;
default:
@@ -1374,10 +1418,10 @@ uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn)
break;
}
- uc_value_put(val);
- uc_value_put(inc);
- uc_value_put(v);
- uc_value_put(k);
+ ucv_put(val);
+ ucv_put(inc);
+ ucv_put(v);
+ ucv_put(k);
}
static void
@@ -1385,9 +1429,9 @@ uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
size_t slot = vm->arg.u32 & 0x00FFFFFF;
- uc_upvalref *ref = frame->closure->upvals[slot];
- json_object *inc = uc_vm_stack_pop(vm);
- json_object *val;
+ uc_upvalref_t *ref = frame->closure->upvals[slot];
+ uc_value_t *inc = uc_vm_stack_pop(vm);
+ uc_value_t *val;
if (ref->closed)
val = ref->value;
@@ -1398,14 +1442,14 @@ uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn)
uc_vm_stack_push(vm, val);
- uc_value_put(inc);
+ ucv_put(inc);
if (ref->closed) {
- uc_value_put(ref->value);
- ref->value = uc_value_get(uc_vm_stack_peek(vm, 0));
+ ucv_put(ref->value);
+ ref->value = ucv_get(uc_vm_stack_peek(vm, 0));
}
else {
- uc_vm_stack_set(vm, ref->slot, uc_value_get(uc_vm_stack_peek(vm, 0)));
+ uc_vm_stack_set(vm, ref->slot, ucv_get(uc_vm_stack_peek(vm, 0)));
}
}
@@ -1414,22 +1458,22 @@ uc_vm_insn_update_local(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
size_t slot = vm->arg.u32 & 0x00FFFFFF;
- json_object *inc = uc_vm_stack_pop(vm);
- json_object *val;
+ uc_value_t *inc = uc_vm_stack_pop(vm);
+ uc_value_t *val;
val = uc_vm_value_arith(vm, vm->arg.u32 >> 24,
vm->stack.entries[frame->stackframe + slot], inc);
uc_vm_stack_push(vm, val);
- uc_value_put(inc);
- uc_vm_stack_set(vm, frame->stackframe + slot, uc_value_get(uc_vm_stack_peek(vm, 0)));
+ ucv_put(inc);
+ uc_vm_stack_set(vm, frame->stackframe + slot, ucv_get(uc_vm_stack_peek(vm, 0)));
}
static void
uc_vm_insn_narr(uc_vm *vm, enum insn_type insn)
{
- json_object *arr = xjs_new_array_size(vm->arg.u32);
+ uc_value_t *arr = ucv_array_new_length(vm, vm->arg.u32);
uc_vm_stack_push(vm, arr);
}
@@ -1437,11 +1481,11 @@ uc_vm_insn_narr(uc_vm *vm, enum insn_type insn)
static void
uc_vm_insn_parr(uc_vm *vm, enum insn_type insn)
{
- json_object *arr = uc_vm_stack_peek(vm, vm->arg.u32);
+ uc_value_t *arr = uc_vm_stack_peek(vm, vm->arg.u32);
size_t idx;
for (idx = 0; idx < vm->arg.u32; idx++)
- json_object_array_add(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1));
+ ucv_array_push(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1));
for (idx = 0; idx < vm->arg.u32; idx++)
uc_vm_stack_pop(vm);
@@ -1452,79 +1496,83 @@ uc_vm_insn_parr(uc_vm *vm, enum insn_type insn)
static void
uc_vm_insn_marr(uc_vm *vm, enum insn_type insn)
{
- json_object *src = uc_vm_stack_pop(vm);
- json_object *dst = uc_vm_stack_peek(vm, 0);
+ uc_value_t *src = uc_vm_stack_pop(vm);
+ uc_value_t *dst = uc_vm_stack_peek(vm, 0);
size_t i;
+ char *s;
- if (!json_object_is_type(src, json_type_array)) {
- uc_vm_raise_exception(vm, EXCEPTION_TYPE,
- "(%s) is not iterable",
- json_object_to_json_string(src));
+ if (ucv_type(src) != UC_ARRAY) {
+ s = ucv_to_string(vm, src);
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s);
+ ucv_put(src);
+ free(s);
return;
}
- for (i = 0; i < json_object_array_length(src); i++)
- json_object_array_add(dst, uc_value_get(json_object_array_get_idx(src, i)));
+ for (i = 0; i < ucv_array_length(src); i++)
+ ucv_array_push(dst, ucv_get(ucv_array_get(src, i)));
- uc_value_put(src);
+ ucv_put(src);
}
static void
uc_vm_insn_nobj(uc_vm *vm, enum insn_type insn)
{
- json_object *arr = xjs_new_object();
+ uc_value_t *obj = ucv_object_new(vm);
- uc_vm_stack_push(vm, arr);
+ uc_vm_stack_push(vm, obj);
}
static void
uc_vm_insn_sobj(uc_vm *vm, enum insn_type insn)
{
- json_object *obj = uc_vm_stack_peek(vm, vm->arg.u32);
+ uc_value_t *obj = uc_vm_stack_peek(vm, vm->arg.u32);
+ uc_value_t *val;
size_t idx;
for (idx = 0; idx < vm->arg.u32; idx += 2) {
- json_object_object_add(obj,
- json_object_get_string(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)),
- uc_value_get(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2)));
+ val = uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1);
+ ucv_object_add(obj,
+ ucv_string_get(val),
+ ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2)));
}
for (idx = 0; idx < vm->arg.u32; idx++)
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
}
static void
uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn)
{
- json_object *src = uc_vm_stack_pop(vm);
- json_object *dst = uc_vm_stack_peek(vm, 0);
- char *istr;
+ uc_value_t *src = uc_vm_stack_pop(vm);
+ uc_value_t *dst = uc_vm_stack_peek(vm, 0);
size_t i;
+ char *s;
- switch (json_object_get_type(src)) {
- case json_type_object:
+ switch (ucv_type(src)) {
+ case UC_OBJECT:
; /* a label can only be part of a statement and a declaration is not a statement */
- json_object_object_foreach(src, k, v)
- json_object_object_add(dst, k, uc_value_get(v));
+ ucv_object_foreach(src, k, v)
+ ucv_object_add(dst, k, ucv_get(v));
- uc_value_put(src);
+ ucv_put(src);
break;
case json_type_array:
- for (i = 0; i < json_object_array_length(src); i++) {
- xasprintf(&istr, "%zu", i);
- json_object_object_add(dst, istr, uc_value_get(json_object_array_get_idx(src, i)));
- free(istr);
+ for (i = 0; i < ucv_array_length(src); i++) {
+ xasprintf(&s, "%zu", i);
+ ucv_object_add(dst, s, ucv_get(ucv_array_get(src, i)));
+ free(s);
}
- uc_value_put(src);
+ ucv_put(src);
break;
default:
- uc_vm_raise_exception(vm, EXCEPTION_TYPE,
- "Value (%s) is not iterable",
- json_object_to_json_string(src));
+ s = ucv_to_string(vm, src);
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Value (%s) is not iterable", s);
+ free(s);
break;
}
@@ -1533,14 +1581,14 @@ uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn)
static void
uc_vm_insn_arith(uc_vm *vm, enum insn_type insn)
{
- json_object *r2 = uc_vm_stack_pop(vm);
- json_object *r1 = uc_vm_stack_pop(vm);
- json_object *rv;
+ uc_value_t *r2 = uc_vm_stack_pop(vm);
+ uc_value_t *r1 = uc_vm_stack_pop(vm);
+ uc_value_t *rv;
rv = uc_vm_value_arith(vm, insn, r1, r2);
- uc_value_put(r1);
- uc_value_put(r2);
+ ucv_put(r1);
+ ucv_put(r2);
uc_vm_stack_push(vm, rv);
}
@@ -1548,23 +1596,23 @@ 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)
{
- struct json_object *v = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
bool is_sub = (insn == I_MINUS);
- enum json_type t;
+ uc_type_t t;
int64_t n;
double d;
t = uc_cast_number(v, &n, &d);
- json_object_put(v);
+ ucv_put(v);
switch (t) {
- case json_type_int:
- uc_vm_stack_push(vm, xjs_new_int64(is_sub ? -n : n));
+ case UC_INTEGER:
+ uc_vm_stack_push(vm, ucv_int64_new(is_sub ? -n : n));
break;
default:
- uc_vm_stack_push(vm, uc_double_new(is_sub ? -d : d));
+ uc_vm_stack_push(vm, ucv_double_new(is_sub ? -d : d));
break;
}
}
@@ -1572,14 +1620,14 @@ 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)
{
- json_object *r2 = uc_vm_stack_pop(vm);
- json_object *r1 = uc_vm_stack_pop(vm);
- json_object *rv;
+ uc_value_t *r2 = uc_vm_stack_pop(vm);
+ uc_value_t *r1 = uc_vm_stack_pop(vm);
+ uc_value_t *rv;
rv = uc_vm_value_bitop(vm, insn, r1, r2);
- uc_value_put(r1);
- uc_value_put(r2);
+ ucv_put(r1);
+ ucv_put(r2);
uc_vm_stack_push(vm, rv);
}
@@ -1587,23 +1635,23 @@ uc_vm_insn_bitop(uc_vm *vm, enum insn_type insn)
static void
uc_vm_insn_complement(uc_vm *vm, enum insn_type insn)
{
- struct json_object *v = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
int64_t n;
double d;
- if (uc_cast_number(v, &n, &d) == json_type_double)
+ if (uc_cast_number(v, &n, &d) == UC_DOUBLE)
n = isnan(d) ? 0 : (int64_t)d;
- json_object_put(v);
+ ucv_put(v);
- uc_vm_stack_push(vm, xjs_new_int64(~n));
+ uc_vm_stack_push(vm, ucv_int64_new(~n));
}
static void
uc_vm_insn_rel(uc_vm *vm, enum insn_type insn)
{
- json_object *r2 = uc_vm_stack_pop(vm);
- json_object *r1 = uc_vm_stack_pop(vm);
+ uc_value_t *r2 = uc_vm_stack_pop(vm);
+ uc_value_t *r1 = uc_vm_stack_pop(vm);
bool res = false;
switch (insn) {
@@ -1627,27 +1675,27 @@ uc_vm_insn_rel(uc_vm *vm, enum insn_type insn)
break;
}
- uc_value_put(r1);
- uc_value_put(r2);
+ ucv_put(r1);
+ ucv_put(r2);
- uc_vm_stack_push(vm, xjs_new_boolean(res));
+ uc_vm_stack_push(vm, ucv_boolean_new(res));
}
static void
uc_vm_insn_in(uc_vm *vm, enum insn_type insn)
{
- json_object *r2 = uc_vm_stack_pop(vm);
- json_object *r1 = uc_vm_stack_pop(vm);
- json_object *item;
+ uc_value_t *r2 = uc_vm_stack_pop(vm);
+ uc_value_t *r1 = uc_vm_stack_pop(vm);
+ uc_value_t *item;
size_t arrlen, arridx;
bool found = false;
- const char *key;
+ char *key;
- switch (json_object_get_type(r2)) {
- case json_type_array:
- for (arridx = 0, arrlen = json_object_array_length(r2);
+ switch (ucv_type(r2)) {
+ case UC_ARRAY:
+ for (arridx = 0, arrlen = ucv_array_length(r2);
arridx < arrlen; arridx++) {
- item = json_object_array_get_idx(r2, arridx);
+ item = ucv_array_get(r2, arridx);
if (uc_cmp(TK_EQ, r1, item)) {
found = true;
@@ -1657,41 +1705,53 @@ uc_vm_insn_in(uc_vm *vm, enum insn_type insn)
break;
- case json_type_object:
- key = r1 ? json_object_get_string(r1) : "null";
- found = json_object_object_get_ex(r2, key, NULL);
+ case UC_OBJECT:
+ if (ucv_type(r1) == UC_STRING) {
+ ucv_object_get(r2, ucv_string_get(r1), &found);
+ }
+ else {
+ key = ucv_to_string(vm, r1);
+ ucv_object_get(r2, key, &found);
+ free(key);
+ }
+
break;
default:
found = false;
}
- uc_value_put(r1);
- uc_value_put(r2);
+ ucv_put(r1);
+ ucv_put(r2);
- uc_vm_stack_push(vm, xjs_new_boolean(found));
+ uc_vm_stack_push(vm, ucv_boolean_new(found));
}
static void
uc_vm_insn_equality(uc_vm *vm, enum insn_type insn)
{
- json_object *r2 = uc_vm_stack_pop(vm);
- json_object *r1 = uc_vm_stack_pop(vm);
- bool equal = uc_eq(r1, r2);
+ 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);
+ else
+ equal = (r1 == r2);
- uc_value_put(r1);
- uc_value_put(r2);
+ ucv_put(r1);
+ ucv_put(r2);
- uc_vm_stack_push(vm, xjs_new_boolean((insn == I_EQS) ? equal : !equal));
+ uc_vm_stack_push(vm, ucv_boolean_new((insn == I_EQS) ? equal : !equal));
}
static void
uc_vm_insn_not(uc_vm *vm, enum insn_type insn)
{
- json_object *r1 = uc_vm_stack_pop(vm);
+ uc_value_t *r1 = uc_vm_stack_pop(vm);
- uc_vm_stack_push(vm, xjs_new_boolean(!uc_val_is_truish(r1)));
- uc_value_put(r1);
+ uc_vm_stack_push(vm, ucv_boolean_new(!uc_val_is_truish(r1)));
+ ucv_put(r1);
}
static void
@@ -1718,7 +1778,7 @@ uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn)
{
uc_callframe *frame = uc_vm_current_frame(vm);
uc_chunk *chunk = uc_vm_frame_chunk(frame);
- json_object *v = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
int32_t addr = vm->arg.s32;
/* ip already has been incremented */
@@ -1733,56 +1793,62 @@ uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn)
if (!uc_val_is_truish(v))
frame->ip += addr;
- uc_value_put(v);
+ ucv_put(v);
}
static void
uc_vm_insn_next(uc_vm *vm, enum insn_type insn)
{
- json_object *k = uc_vm_stack_pop(vm);
- json_object *v = uc_vm_stack_pop(vm);
+ uc_value_t *k = uc_vm_stack_pop(vm);
+ uc_value_t *v = uc_vm_stack_pop(vm);
+ void *end = (void *)~(uintptr_t)0;
+ uc_ressource_t *iterk;
struct lh_entry *curr;
- int64_t n;
+ uint64_t n;
+
+ if (k != NULL && ucv_type(k) != UC_RESSOURCE) {
+ fprintf(stderr, "Invalid iterator value\n");
+ abort();
+ }
+
+ if (k == NULL)
+ k = ucv_ressource_new(NULL, NULL);
- switch (json_object_get_type(v)) {
- case json_type_object:
- curr = k ? json_object_get_userdata(k) : json_object_get_object(v)->head;
+ iterk = (uc_ressource_t *)k;
- if (curr) {
- if (!k)
- k = xjs_new_string("[key]");
+ switch (ucv_type(v)) {
+ case UC_OBJECT:
+ curr = iterk->data ? iterk->data : ((uc_object_t *)v)->table->head;
- json_object_set_userdata(k, curr->next, NULL);
+ if (curr != NULL && curr != end) {
+ iterk->data = curr->next ? curr->next : end;
- uc_vm_stack_push(vm, xjs_new_string(curr->k));
+ uc_vm_stack_push(vm, ucv_string_new(curr->k));
if (insn == I_NEXTKV)
- uc_vm_stack_push(vm, uc_value_get((json_object *)curr->v));
+ uc_vm_stack_push(vm, ucv_get((uc_value_t *)curr->v));
uc_vm_stack_push(vm, k);
- uc_value_put(v);
+ ucv_put(v);
return;
}
break;
- case json_type_array:
- if (!k)
- k = xjs_new_int64(0);
-
- n = json_object_get_int64(k);
+ case UC_ARRAY:
+ n = (uintptr_t)iterk->data;
- if (json_object_is_type(k, json_type_int) && n < json_object_array_length(v)) {
- json_object_int_inc(k, 1);
+ if (n < ucv_array_length(v)) {
+ iterk->data = (void *)(uintptr_t)(n + 1);
if (insn == I_NEXTKV)
- uc_vm_stack_push(vm, xjs_new_int64(n));
+ uc_vm_stack_push(vm, ucv_uint64_new(n));
- uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(v, n)));
+ uc_vm_stack_push(vm, ucv_get(ucv_array_get(v, n)));
uc_vm_stack_push(vm, k);
- uc_value_put(v);
+ ucv_put(v);
return;
}
@@ -1799,87 +1865,83 @@ uc_vm_insn_next(uc_vm *vm, enum insn_type insn)
if (insn == I_NEXTKV)
uc_vm_stack_push(vm, NULL);
- uc_value_put(k);
- uc_value_put(v);
+ ucv_put(k);
+ ucv_put(v);
}
static void
uc_vm_insn_close_upval(uc_vm *vm, enum insn_type insn)
{
uc_vm_close_upvals(vm, vm->stack.count - 1);
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
}
static void
uc_vm_insn_call(uc_vm *vm, enum insn_type insn)
{
- json_object *fno = uc_value_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff));
- json_object *ctx = NULL;
+ uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff));
+ uc_value_t *ctx = NULL;
- if (!uc_object_is_type(fno, UC_OBJ_CLOSURE) || !uc_object_as_closure(fno)->is_arrow)
+ if (!ucv_is_arrowfn(fno))
ctx = NULL;
else if (vm->callframes.count > 0)
- ctx = uc_value_get(uc_vm_current_frame(vm)->ctx);
+ ctx = uc_vm_current_frame(vm)->ctx;
- uc_vm_call_function(vm, ctx, fno, false, vm->arg.u32);
+ uc_vm_call_function(vm, ucv_get(ctx), fno, false, vm->arg.u32);
}
static void
uc_vm_insn_mcall(uc_vm *vm, enum insn_type insn)
{
size_t key_slot = vm->stack.count - (vm->arg.u32 & 0xffff) - 1;
- json_object *ctx = vm->stack.entries[key_slot - 1];
- json_object *key = vm->stack.entries[key_slot];
- json_object *fno = uc_getval(ctx, key);
+ 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_vm_stack_set(vm, key_slot, fno);
/* arrow functions as method calls inherit the parent ctx */
- if (uc_object_is_type(fno, UC_OBJ_CLOSURE) && uc_object_as_closure(fno)->is_arrow)
+ if (ucv_is_arrowfn(fno))
ctx = uc_vm_current_frame(vm)->ctx;
- uc_vm_call_function(vm, uc_value_get(ctx), uc_value_get(fno), true, vm->arg.u32);
+ uc_vm_call_function(vm, ucv_get(ctx), ucv_get(fno), true, vm->arg.u32);
}
static void
uc_vm_insn_print(uc_vm *vm, enum insn_type insn)
{
- json_object *v = uc_vm_stack_pop(vm);
- const char *p;
- size_t len;
+ uc_value_t *v = uc_vm_stack_pop(vm);
+ char *p;
- switch (json_object_get_type(v)) {
- case json_type_object:
- case json_type_array:
- p = json_object_to_json_string_ext(v, JSON_C_TO_STRING_NOSLASHESCAPE|JSON_C_TO_STRING_SPACED);
- len = strlen(p);
+ switch (ucv_type(v)) {
+ case UC_OBJECT:
+ case UC_ARRAY:
+ p = ucv_to_jsonstring(vm, v);
+ fwrite(p, 1, strlen(p), stdout);
+ free(p);
break;
- case json_type_string:
- p = json_object_get_string(v);
- len = json_object_get_string_len(v);
+ case UC_STRING:
+ fwrite(ucv_string_get(v), 1, ucv_string_length(v), stdout);
break;
- case json_type_null:
- p = "";
- len = 0;
+ case UC_NULL:
break;
default:
- p = json_object_get_string(v);
- len = strlen(p);
+ p = ucv_to_string(vm, v);
+ fwrite(p, 1, strlen(p), stdout);
+ free(p);
}
- fwrite(p, 1, len, stdout);
-
- uc_value_put(v);
+ ucv_put(v);
}
-static json_object *
+static uc_value_t *
uc_vm_callframe_pop(uc_vm *vm)
{
uc_callframe *frame = uc_vm_current_frame(vm);
- json_object *retval;
+ uc_value_t *retval;
/* close upvalues */
uc_vm_close_upvals(vm, frame->stackframe);
@@ -1891,18 +1953,18 @@ uc_vm_callframe_pop(uc_vm *vm)
/* reset function stack frame */
while (vm->stack.count > frame->stackframe)
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
/* for method calls, release context as well */
if (frame->mcall)
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
/* release function */
- uc_value_put(frame->closure ? frame->closure->header.jso : NULL);
- uc_value_put(frame->cfunction ? frame->cfunction->header.jso : NULL);
+ ucv_put((uc_value_t *)frame->closure);
+ ucv_put((uc_value_t *)frame->cfunction);
/* release context */
- uc_value_put(frame->ctx);
+ ucv_put(frame->ctx);
vm->callframes.count--;
@@ -1912,6 +1974,8 @@ uc_vm_callframe_pop(uc_vm *vm)
static void
uc_vm_output_exception(uc_vm *vm)
{
+ uc_value_t *ctx;
+
if (vm->exception.type == EXCEPTION_USER)
fprintf(stderr, "%s\n", vm->exception.message);
else
@@ -1919,10 +1983,9 @@ uc_vm_output_exception(uc_vm *vm)
exception_type_strings[vm->exception.type] ? exception_type_strings[vm->exception.type] : "Error",
vm->exception.message);
- fprintf(stderr, "%s\n\n",
- json_object_get_string(
- json_object_object_get(
- json_object_array_get_idx(vm->exception.stacktrace, 0), "context")));
+ ctx = ucv_object_get(ucv_array_get(vm->exception.stacktrace, 0), "context", NULL);
+
+ fprintf(stderr, "%s\n\n", ucv_string_get(ctx));
}
static uc_vm_status_t
@@ -1930,7 +1993,7 @@ uc_vm_execute_chunk(uc_vm *vm)
{
uc_callframe *frame = uc_vm_current_frame(vm);
uc_chunk *chunk = uc_vm_frame_chunk(frame);
- json_object *retval;
+ uc_value_t *retval;
enum insn_type insn;
while (chunk) {
@@ -1961,7 +2024,7 @@ uc_vm_execute_chunk(uc_vm *vm)
break;
case I_LTHIS:
- uc_vm_stack_push(vm, uc_value_get(frame->ctx));
+ uc_vm_stack_push(vm, ucv_get(frame->ctx));
break;
case I_LVAR:
@@ -2100,11 +2163,11 @@ uc_vm_execute_chunk(uc_vm *vm)
break;
case I_COPY:
- uc_vm_stack_push(vm, uc_value_get(uc_vm_stack_peek(vm, vm->arg.u8)));
+ uc_vm_stack_push(vm, ucv_get(uc_vm_stack_peek(vm, vm->arg.u8)));
break;
case I_POP:
- uc_value_put(uc_vm_stack_pop(vm));
+ ucv_put(uc_vm_stack_pop(vm));
break;
case I_CUPV:
@@ -2127,7 +2190,7 @@ uc_vm_execute_chunk(uc_vm *vm)
retval = uc_vm_callframe_pop(vm);
if (vm->callframes.count == 0) {
- uc_value_put(retval);
+ ucv_put(retval);
return STATUS_OK;
}
@@ -2163,7 +2226,7 @@ uc_vm_execute_chunk(uc_vm *vm)
return ERROR_RUNTIME;
/* no exception handler in current function, pop callframe */
- uc_value_put(uc_vm_callframe_pop(vm));
+ ucv_put(uc_vm_callframe_pop(vm));
/* resume execution at topmost remaining callframe */
frame = uc_vector_last(&vm->callframes);
@@ -2176,25 +2239,25 @@ uc_vm_execute_chunk(uc_vm *vm)
}
static uc_vm_status_t
-uc_vm_preload(uc_vm *vm, json_object *modules)
+uc_vm_preload(uc_vm *vm, uc_value_t *modules)
{
- json_object *requirefn, *module, *name;
+ uc_value_t *requirefn, *module, *name;
uc_exception_type_t ex;
size_t i;
- if (!json_object_is_type(modules, json_type_array))
+ if (ucv_type(modules) != UC_ARRAY)
return STATUS_OK;
- requirefn = uc_prototype_lookup(vm->globals, "require");
+ requirefn = ucv_property_get(vm->globals, "require");
- if (!uc_object_is_type(requirefn, UC_OBJ_CFUNCTION))
+ if (ucv_type(requirefn) != UC_CFUNCTION)
return STATUS_OK;
- for (i = 0; i < json_object_array_length(modules); i++) {
- name = json_object_array_get_idx(modules, i);
+ for (i = 0; i < ucv_array_length(modules); i++) {
+ name = ucv_array_get(modules, i);
- uc_vm_stack_push(vm, uc_value_get(requirefn));
- uc_vm_stack_push(vm, uc_value_get(name));
+ uc_vm_stack_push(vm, ucv_get(requirefn));
+ uc_vm_stack_push(vm, ucv_get(name));
ex = uc_vm_call(vm, false, 1);
@@ -2203,21 +2266,22 @@ uc_vm_preload(uc_vm *vm, json_object *modules)
module = uc_vm_stack_pop(vm);
- uc_value_put(uc_setval(vm->globals->header.jso, name, module));
+ ucv_put(uc_setval(vm, vm->globals, name, module));
}
return STATUS_OK;
}
uc_vm_status_t
-uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *modules)
+uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *modules)
{
- uc_closure *closure = uc_closure_new(fn, false);
+ uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, fn, false);
uc_callframe *frame;
+ uc_stringbuf_t *buf;
uc_vm_status_t rv;
vm->globals = globals;
- uc_value_get(globals ? globals->header.jso : NULL);
+ ucv_get(globals);
uc_vector_grow(&vm->callframes);
@@ -2227,14 +2291,12 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo
frame->ip = uc_vm_frame_chunk(frame)->entries;
if (vm->trace) {
- size_t msglen = 0;
- char *msg = NULL;
+ buf = xprintbuf_new();
- format_source_context(&msg, &msglen,
- fn->source, 0, true);
+ format_source_context(buf, fn->source, 0, true);
- fprintf(stderr, "%s", msg);
- free(msg);
+ fwrite(buf->buf, 1, printbuf_length(buf), stderr);
+ printbuf_free(buf);
uc_vm_frame_dump(vm, frame);
}
@@ -2249,7 +2311,7 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo
else
rv = uc_vm_execute_chunk(vm);
- uc_value_put(vm->globals->header.jso);
+ ucv_put(vm->globals);
vm->globals = NULL;
return rv;
@@ -2258,11 +2320,11 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo
uc_exception_type_t
uc_vm_call(uc_vm *vm, bool mcall, size_t nargs)
{
- json_object *ctx = mcall ? uc_value_get(uc_vm_stack_peek(vm, nargs - 1)) : NULL;
- json_object *fno = uc_value_get(uc_vm_stack_peek(vm, 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 (!uc_object_is_type(fno, UC_OBJ_CFUNCTION))
+ if (ucv_type(fno) != UC_CFUNCTION)
uc_vm_execute_chunk(vm);
}
diff --git a/vm.h b/vm.h
index 5672cbb..0f7b805 100644
--- a/vm.h
+++ b/vm.h
@@ -21,9 +21,9 @@
#include <stdarg.h>
#include "chunk.h"
-#include "object.h"
#include "util.h"
#include "lexer.h"
+#include "types.h"
#define __insns \
__insn(NOOP) \
@@ -102,57 +102,9 @@ typedef struct {
int8_t stack_pop;
int8_t stack_push;
int8_t operand_bytes;
- bool operand_is_skip;
} uc_insn_definition;
typedef enum {
- EXCEPTION_NONE,
- EXCEPTION_SYNTAX,
- EXCEPTION_RUNTIME,
- EXCEPTION_TYPE,
- EXCEPTION_REFERENCE,
- EXCEPTION_USER
-} uc_exception_type_t;
-
-typedef struct {
- uc_exception_type_t type;
- json_object *stacktrace;
- char *message;
-} uc_exception;
-
-typedef struct {
- uint8_t *ip;
- uc_closure *closure;
- uc_cfunction *cfunction;
- size_t stackframe;
- json_object *ctx;
- bool mcall;
-} uc_callframe;
-
-uc_declare_vector(uc_callframes, uc_callframe);
-uc_declare_vector(uc_stack, json_object *);
-
-typedef struct uc_vm {
- uc_stack stack;
- uc_exception exception;
- uc_callframes callframes;
- uc_upvalref *open_upvals;
- uc_parse_config *config;
- uc_prototype *globals;
- uc_source *sources;
- union {
- uint32_t u32;
- int32_t s32;
- uint16_t u16;
- int16_t s16;
- uint8_t u8;
- int8_t s8;
- } arg;
- size_t spread_values;
- uint8_t trace;
-} uc_vm;
-
-typedef enum {
STATUS_OK,
ERROR_COMPILE,
ERROR_RUNTIME
@@ -163,15 +115,15 @@ 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_stack_push(uc_vm *vm, json_object *value);
-json_object *uc_vm_stack_pop(uc_vm *vm);
-json_object *uc_vm_stack_peek(uc_vm *vm, size_t offset);
+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);
uc_exception_type_t uc_vm_call(uc_vm *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_status_t uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *modules);
+uc_vm_status_t uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *modules);
#endif /* __VM_H_ */