Skip to content

Commit

Permalink
treewide: rework function memory model
Browse files Browse the repository at this point in the history
 - Instead of treating individual program functions as managed ucode types,
   demote uc_function_t values to pointers into a uc_program_t entity

 - Promote uc_program_t to a managed type

 - Let uc_closure_t claim references to the owning program of the enclosed
   uc_function_t

 - Redefine public APIs uc_compile() and uc_vm_execute() APIs to return and
   expect an uc_program_t object respectively

 - Remove vallist indirection for function loading and let the compiler
   emit the function id directly when producing function construction code

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
  • Loading branch information
jow- committed Feb 6, 2022
1 parent 5bd764a commit 3a49192
Show file tree
Hide file tree
Showing 18 changed files with 214 additions and 256 deletions.
49 changes: 25 additions & 24 deletions compiler.c
Expand Up @@ -178,7 +178,7 @@ uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, .
buf = compiler->parser->error = xprintbuf_new();

if (!off)
off = ucv_function_srcpos(compiler->function,
off = uc_program_function_srcpos(compiler->function,
uc_compiler_current_chunk(compiler)->count);

if (off) {
Expand Down Expand Up @@ -603,12 +603,12 @@ uc_compiler_finish(uc_compiler_t *compiler)
uc_vector_clear(upvals);

if (compiler->parser->error) {
ucv_put(compiler->function);
uc_program_function_free(compiler->function);

return NULL;
}

return (uc_function_t *)compiler->function;
return compiler->function;
}

static void
Expand Down Expand Up @@ -1156,7 +1156,7 @@ uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool rest

if (fn)
uc_compiler_set_u32(compiler, load_off,
uc_program_add_constant(compiler->program, &fn->header));
uc_program_function_id(compiler->program, fn));

return true;
}
Expand Down Expand Up @@ -1595,7 +1595,7 @@ uc_compiler_compile_function(uc_compiler_t *compiler)

if (fn)
uc_compiler_set_u32(compiler, load_off,
uc_program_add_constant(compiler->program, &fn->header));
uc_program_function_id(compiler->program, fn));

/* if a local variable of the same name already existed, overwrite its value
* with the compiled function here */
Expand Down Expand Up @@ -2833,7 +2833,7 @@ uc_compiler_compile_declaration(uc_compiler_t *compiler)
#endif /* NO_COMPILE */


static uc_function_t *
static uc_program_t *
uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **errp)
{
#ifdef NO_COMPILE
Expand All @@ -2842,11 +2842,11 @@ uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **er

return NULL;
#else
uc_function_t *fn = NULL;
uc_exprstack_t expr = { .token = TK_EOF };
uc_parser_t parser = { .config = config };
uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr };
uc_program_t *prog;
uc_function_t *fn;

prog = uc_program_new(source);

Expand All @@ -2871,44 +2871,45 @@ uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **er

uc_lexer_free(&parser.lex);

return fn;
if (!fn) {
ucv_put(&prog->header);

return NULL;
}

return prog;
#endif
}

static uc_function_t *
static uc_program_t *
uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp)
{
uc_function_t *fn = NULL;
uc_program_t *prog;

prog = uc_program_load(source, errp);

if (prog) {
fn = uc_program_entry(prog);

if (!fn) {
if (errp)
xasprintf(errp, "Program file contains no entry function\n");
if (prog && !uc_program_entry(prog)) {
if (errp)
xasprintf(errp, "Program file contains no entry function\n");

uc_program_free(prog);
}
ucv_put(&prog->header);
}

return fn;
return prog;
}

uc_function_t *
uc_program_t *
uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
{
uc_function_t *fn = NULL;
uc_program_t *prog = NULL;

switch (uc_source_type_test(source)) {
case UC_SOURCE_TYPE_PLAIN:
fn = uc_compile_from_source(config, source, errp);
prog = uc_compile_from_source(config, source, errp);
break;

case UC_SOURCE_TYPE_PRECOMPILED:
fn = uc_compile_from_bytecode(config, source, errp);
prog = uc_compile_from_bytecode(config, source, errp);
break;

default:
Expand All @@ -2918,5 +2919,5 @@ uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
break;
}

return fn;
return prog;
}
10 changes: 5 additions & 5 deletions examples/exception-handler.c
Expand Up @@ -23,7 +23,7 @@

#define MULTILINE_STRING(...) #__VA_ARGS__

static const char *program = MULTILINE_STRING(
static const char *program_code = MULTILINE_STRING(
{%
function fail() {
/* invoke not existing function to raise runtime error */
Expand Down Expand Up @@ -58,17 +58,17 @@ 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));
uc_source_t *src = uc_source_new_buffer("my program", strdup(program_code), strlen(program_code));

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -85,7 +85,7 @@ int main(int argc, char **argv)
uc_vm_exception_handler_set(&vm, log_exception);

/* execute program function */
int return_code = uc_vm_execute(&vm, progfunc, NULL);
int return_code = uc_vm_execute(&vm, program, NULL);

/* handle return status */
if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) {
Expand Down
6 changes: 3 additions & 3 deletions examples/execute-file.c
Expand Up @@ -49,13 +49,13 @@ int main(int argc, char **argv)

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -74,7 +74,7 @@ int main(int argc, char **argv)

/* execute compiled program function */
uc_value_t *last_expression_result = NULL;
int return_code = uc_vm_execute(&vm, progfunc, &last_expression_result);
int return_code = uc_vm_execute(&vm, program, &last_expression_result);

/* handle return status */
switch (return_code) {
Expand Down
13 changes: 8 additions & 5 deletions examples/execute-string.c
Expand Up @@ -28,7 +28,7 @@

#define MULTILINE_STRING(...) #__VA_ARGS__

static const char *program = MULTILINE_STRING(
static const char *program_code = MULTILINE_STRING(
{%
function add(a, b) {
c = a + b;
Expand All @@ -55,17 +55,17 @@ 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));
uc_source_t *src = uc_source_new_buffer("my program", strdup(program_code), strlen(program_code));

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -84,7 +84,10 @@ int main(int argc, char **argv)

/* execute compiled program function */
uc_value_t *last_expression_result = NULL;
int return_code = uc_vm_execute(&vm, progfunc, &last_expression_result);
int return_code = uc_vm_execute(&vm, program, &last_expression_result);

/* release program */
uc_program_put(program);

/* handle return status */
switch (return_code) {
Expand Down
13 changes: 8 additions & 5 deletions examples/native-function.c
Expand Up @@ -23,7 +23,7 @@

#define MULTILINE_STRING(...) #__VA_ARGS__

static const char *program = MULTILINE_STRING(
static const char *program_code = MULTILINE_STRING(
{%
print("add() = " + add(5, 3.1, 2) + "\n");
print("multiply() = " + multiply(7.3, 5) + "\n");
Expand Down Expand Up @@ -61,17 +61,17 @@ 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));
uc_source_t *src = uc_source_new_buffer("my program", strdup(program_code), strlen(program_code));

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -89,7 +89,10 @@ int main(int argc, char **argv)
uc_function_register(uc_vm_scope_get(&vm), "multiply", multiply_two_numbers);

/* execute program function */
int return_code = uc_vm_execute(&vm, progfunc, NULL);
int return_code = uc_vm_execute(&vm, program, NULL);

/* release program */
uc_program_put(program);

/* handle return status */
if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) {
Expand Down
15 changes: 6 additions & 9 deletions examples/state-reset.c
Expand Up @@ -23,7 +23,7 @@

#define MULTILINE_STRING(...) #__VA_ARGS__

static const char *program = MULTILINE_STRING(
static const char *program_code = MULTILINE_STRING(
{%
/* the global test variable should've been reset since the previous run */
print("Global variable is null? " + (global.test == null) + "\n");
Expand All @@ -43,17 +43,17 @@ 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));
uc_source_t *src = uc_source_new_buffer("my program", strdup(program_code), strlen(program_code));

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -70,11 +70,8 @@ int main(int argc, char **argv)

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);
int return_code = uc_vm_execute(&vm, program, NULL);

/* handle return status */
if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) {
Expand All @@ -88,7 +85,7 @@ int main(int argc, char **argv)
}

/* release program function */
ucv_put(&progfunc->header);
uc_program_put(program);

return exit_code;
}
15 changes: 6 additions & 9 deletions examples/state-reuse.c
Expand Up @@ -23,7 +23,7 @@

#define MULTILINE_STRING(...) #__VA_ARGS__

static const char *program = MULTILINE_STRING(
static const char *program_code = MULTILINE_STRING(
{%
let n = global.value || 1;

Expand All @@ -44,17 +44,17 @@ 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));
uc_source_t *src = uc_source_new_buffer("my program", strdup(program_code), strlen(program_code));

/* compile source buffer into function */
char *syntax_error = NULL;
uc_function_t *progfunc = uc_compile(&config, src, &syntax_error);
uc_program_t *program = uc_compile(&config, src, &syntax_error);

/* release source buffer */
uc_source_put(src);

/* check if compilation failed */
if (!progfunc) {
if (!program) {
fprintf(stderr, "Failed to compile program: %s\n", syntax_error);

return 1;
Expand All @@ -71,11 +71,8 @@ int main(int argc, char **argv)
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);
int return_code = uc_vm_execute(&vm, program, NULL);

/* handle return status */
if (return_code == ERROR_COMPILE || return_code == ERROR_RUNTIME) {
Expand All @@ -89,7 +86,7 @@ int main(int argc, char **argv)
}

/* release program function */
ucv_put(&progfunc->header);
uc_program_put(program);

/* free VM context */
uc_vm_free(&vm);
Expand Down

0 comments on commit 3a49192

Please sign in to comment.