Repository: JuliaLang/julia
File: src/ast.c (C)

Code before:
        if (jl_is_number(v) || jl_is_string(v))
            return fl_ctx->T;
    }
    return fl_ctx->F;
}

static value_t fl_julia_push_closure_expr(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
{
    argcount(fl_ctx, "julia-push-closure-expr", nargs, 1);
    // Check if the head of the symbol at `args[0]` is (method <name>) or (method (outerref <name>))
    // and if so, push the name onto the `parsed_method_stack`
    value_t arg = args[0];
    if (iscons(arg)) {
        value_t head = car_(arg);
        if (head == symbol(fl_ctx, "method")) {
            value_t name = car_(cdr_(arg));
            if (issymbol(name)) {
                arraylist_push(&parsed_method_stack, (void*)name);
                return fl_ctx->T;
            }
            if (iscons(name)) {
                value_t head = car_(name);
                if (head == symbol(fl_ctx, "outerref")) {
                    value_t name_inner = car_(cdr_(name));
                    assert(issymbol(name_inner));
                    arraylist_push(&parsed_method_stack, (void*)name_inner);
                    return fl_ctx->T;
                }
            }
        }
    }
    return fl_ctx->F;
}

static value_t fl_julia_pop_closure_expr(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
{
    argcount(fl_ctx, "julia-pop-closure-expr", nargs, 0);
    // Pop the top of the `parsed_method_stack`
    arraylist_pop(&parsed_method_stack);
    return fl_ctx->NIL;
}

static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *mod);

static const builtinspec_t julia_flisp_ast_ext[] = {
    { "defined-julia-global", fl_defined_julia_global }, // TODO: can we kill this safepoint
    { "nothrow-julia-global", fl_nothrow_julia_global },
    { "current-julia-module-counter", fl_current_module_counter },
    { "julia-scalar?", fl_julia_scalar },
    { "julia-push-closure-expr", fl_julia_push_closure_expr },
    { "julia-pop-closure-expr", fl_julia_pop_closure_expr },

Review comment (bug):
I think it'd be preferable to throw an error here - Otherwise, this silently does nothing if the argument is not of the expected form.

The boolean return value help prevents that from breaking the stack discipline, but it's still very easy to get bugs here.


Code after:
        if (jl_is_number(v) || jl_is_string(v))
            return fl_ctx->T;
    }
    return fl_ctx->F;
}

static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *mod);

static const builtinspec_t julia_flisp_ast_ext[] = {
    { "defined-julia-global", fl_defined_julia_global }, // TODO: can we kill this safepoint
    { "nothrow-julia-global", fl_nothrow_julia_global },
    { "current-julia-module-counter", fl_module_unique_name },
    { "julia-scalar?", fl_julia_scalar },
    { NULL, NULL }
};

static void jl_init_ast_ctx(jl_ast_context_t *ctx) JL_NOTSAFEPOINT
{
    fl_context_t *fl_ctx = &ctx->fl;
    fl_init(fl_ctx, 4*1024*1024);

    if (fl_load_system_image_str(fl_ctx, (char*)flisp_system_image,
                                 sizeof(flisp_system_image))) {
        jl_error("fatal error loading system image");
    }

    fl_applyn(fl_ctx, 0, symbol_value(symbol(fl_ctx, "__init_globals")));

    ctx->jvtype = define_opaque_type(fl_ctx->jl_sym, sizeof(void*), NULL, NULL);
    assign_global_builtins(fl_ctx, julia_flisp_ast_ext);
    ctx->true_sym = symbol(fl_ctx, "true");
    ctx->false_sym = symbol(fl_ctx, "false");
    ctx->error_sym = symbol(fl_ctx, "error");
    ctx->null_sym = symbol(fl_ctx, "null");
    ctx->ssavalue_sym = symbol(fl_ctx, "ssavalue");
    ctx->slot_sym = symbol(fl_ctx, "slot");
    ctx->module = NULL;
    set(symbol(fl_ctx, "*scopewarn-opt*"), fixnum(jl_options.warn_scope));
}

// There should be no GC allocation while holding this lock
static uv_mutex_t flisp_lock;
static jl_ast_context_t *jl_ast_ctx_freed = NULL;

static jl_ast_context_t *jl_ast_ctx_enter(jl_module_t *m) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT
{
    JL_SIGATOMIC_BEGIN();
    uv_mutex_lock(&flisp_lock);
    jl_ast_context_t *ctx = jl_ast_ctx_freed;
    if (ctx != NULL) {
        jl_ast_ctx_freed = ctx->next;