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