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

Code before:
// of a codebase. see #53719
static value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) JL_NOTSAFEPOINT
{
    argcount(fl_ctx, "current-julia-module-counter", nargs, 1);
    jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx);
    jl_module_t *m = ctx->module;
    assert(m != NULL);
    // Get the outermost function name from the `parsed_method_stack` top
    char *funcname = NULL;
    value_t parsed_method_stack = args[0];
    if (parsed_method_stack != fl_ctx->NIL) {
        value_t bottom_stack_symbol = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "last")), parsed_method_stack);
        funcname = symbol_name(fl_ctx, bottom_stack_symbol);
    }
    char buf[(funcname != NULL ? strlen(funcname) : 0) + 20];
    if (funcname != NULL && funcname[0] != '#') {
        jl_mutex_lock_nogc(&m->lock);
        htable_t *mod_table = m->counter_table;
        if (mod_table == NULL) {
            mod_table = m->counter_table = htable_new((htable_t *)malloc_s(sizeof(htable_t)), 0);
        }
        // try to find the function name in the module's counter table, if it's not found, add it
        if (ptrhash_get(mod_table, funcname) == HT_NOTFOUND) {
            ptrhash_put(mod_table, funcname, (void*)((uintptr_t)HT_NOTFOUND + 1));
        }
        int should_check_binding_table = 0;
        do {
            uint32_t nxt = ((uint32_t)(uintptr_t)ptrhash_get(mod_table, funcname) - (uintptr_t)HT_NOTFOUND - 1);
            snprintf(buf, sizeof(buf), "%s##%d", funcname, nxt);
            ptrhash_put(mod_table, funcname, (void*)(nxt + (uintptr_t)HT_NOTFOUND + 1 + 1));
            // Check if the counter is already in use
            should_check_binding_table = 0;
            jl_svec_t *t = jl_atomic_load_relaxed(&m->bindings);
            for (size_t i = 0; i < jl_svec_len(t); i++) {
                jl_binding_t *b = (jl_binding_t*)jl_svecref(t, i);
                if ((void*)b == jl_nothing) {
                    continue;
                }
                if (strstr(jl_symbol_name(b->globalref->name), buf)) {
                    should_check_binding_table = 1;
                    break;
                }
            }
        } while (should_check_binding_table);
        jl_mutex_unlock_nogc(&m->lock);
    }
    else {
        snprintf(buf, sizeof(buf), "%d", jl_module_next_counter(ctx->module));
    }
    return symbol(fl_ctx, buf);
}

Review comment (suggestion):
```suggestion
        int collision_found = 0;
```

Probably a good idea to add a comment explaining that the `counter_table` is dropped during serialization, so we always have to check for conflicts here.

Code after:
}

// Used to generate a unique suffix for a given symbol (e.g. variable or type name)
// first argument contains a stack of method definitions seen so far by `closure-convert` in flisp.
// if the top of the stack is non-NIL, we use it to augment the suffix so that it becomes
// of the form $top_level_method_name##$counter, where `counter` is the smallest integer
// such that the resulting name is not already defined in the current module's bindings.
// If the top of the stack is NIL, we simply return the current module's counter.
// This ensures that precompile statements are a bit more stable across different versions
// of a codebase. see #53719
static value_t fl_module_unique_name(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
{
    argcount(fl_ctx, "julia-module-unique-name", nargs, 1);
    jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx);
    jl_module_t *m = ctx->module;
    assert(m != NULL);
    // Get the outermost function name from the `parsed_method_stack` top
    char *funcname = NULL;
    value_t parsed_method_stack = args[0];
    if (parsed_method_stack != fl_ctx->NIL) {
        value_t bottom_stack_symbol = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "last")), parsed_method_stack);
        funcname = tosymbol(fl_ctx, bottom_stack_symbol, "julia-module-unique-name")->name;
    }
    size_t sz = funcname != NULL ? strlen(funcname) + 32 : 32; // 32 is enough for the suffix
    char *buf = (char*)alloca(sz);
    if (funcname != NULL && strchr(funcname, '#') == NULL) {
        for (int i = 0; ; i++) {
            snprintf(buf, sz, "%s##%d", funcname, i);
            jl_sym_t *sym = jl_symbol(buf);
            JL_LOCK(&m->lock);
            if (jl_get_module_binding(m, sym, 0) == NULL) { // make sure this name is not already taken
                jl_get_module_binding(m, sym, 1); // create the binding
                JL_UNLOCK(&m->lock);
                return symbol(fl_ctx, buf);
            }
            JL_UNLOCK(&m->lock);
        }
    }
    else {
        snprintf(buf, sz, "%d", jl_module_next_counter(m));
    }
    return symbol(fl_ctx, buf);
}

static int jl_is_number(jl_value_t *v)
{
    jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
    for (; t->super != t; t = t->super)
        if (t == jl_number_type)
            return 1;
    return 0;