Пример #1
0
Term* if_block_append_output(Term* ifBlock)
{
    Branch* contents = nested_contents(ifBlock);

    Term* placeholder = append_output_placeholder(contents, NULL);

    // Add a corresponding output placeholder to each case
    for (CaseIterator it(contents); it.unfinished(); it.advance()) {
        Branch* caseContents = nested_contents(it.current());
        /*Term* casePlaceholder =*/ append_output_placeholder(caseContents, NULL);
    }

    return placeholder;
}
Пример #2
0
void load_script(Block* block, const char* filename)
{
    // Store the filename
    set_string(block_insert_property(block, s_filename), filename);

    // Read the text file
    circa::Value contents;
    circa_read_file(block->world, filename, &contents);

    if (is_null(&contents)) {
        Value msg;
        set_string(&msg, "File not found: ");
        string_append(&msg, filename);
        Term* term = create_string(block, as_cstring(&msg));
        apply(block, FUNCS.error, TermList(term));
        return;
    }

    parse(block, parse_statement_list, &contents);

    // Make sure the block has a primary output.
    if (get_output_placeholder(block, 0) == NULL)
        append_output_placeholder(block, NULL);

    update_static_error_list(block);

    return;
}
Пример #3
0
void insert_looped_placeholders(Block* contents)
{
    Value names;
    list_names_that_must_be_looped(contents, &names);

    for (ListIterator it(&names); it; ++it) {
        Term* inputPlaceholder = append_input_placeholder(contents);
        Value* name = it.value();
        rename(inputPlaceholder, name);
        Value owningTermVal;
        owningTermVal.set_term(contents->owningTerm);
        Term* outsideTerm = find_name_at(&owningTermVal, name);
        Term* innerResult = find_local_name(contents, name);
        Term* outputPlaceholder = append_output_placeholder(contents, innerResult);
        rename(outputPlaceholder, name);

        set_inputs(inputPlaceholder, TermList(outsideTerm, outputPlaceholder));

        for (BlockInputIterator it(contents); it; ++it) {
            Term* term = it.currentTerm();
            if (it.currentInput() == outsideTerm && term != inputPlaceholder)
                set_input(term, it.currentInputIndex(), inputPlaceholder);
        }
    }
}
Пример #4
0
void for_loop_remake_zero_branch(Branch* forContents)
{
    Branch* zero = for_loop_get_zero_branch(forContents);
    clear_branch(zero);

    // Clone inputs
    for (int i=0;; i++) {
        Term* placeholder = get_input_placeholder(forContents, i);
        if (placeholder == NULL)
            break;
        Term* clone = append_input_placeholder(zero);
        rename(clone, placeholder->nameSymbol);
    }

    Term* loopOutput = create_list(zero);

    // Clone outputs
    for (int i=0;; i++) {
        Term* placeholder = get_output_placeholder(forContents, i);
        if (placeholder == NULL)
            break;

        // Find the appropriate connection
        Term* result = find_local_name(zero, placeholder->name.c_str());

        if (i == 0)
            result = loopOutput;

        Term* clone = append_output_placeholder(zero, result);
        rename(clone, placeholder->nameSymbol);
    }

    branch_finish_changes(zero);
}
Пример #5
0
void load_script_from_text(Block* block, const char* text)
{
    parse(block, parse_statement_list, text);

    // Make sure the block has a primary output.
    if (get_output_placeholder(block, 0) == NULL)
        append_output_placeholder(block, NULL);

    update_static_error_list(block);
}
Пример #6
0
void bootstrap_kernel()
{
    // First, instanciate the types that are used by Type.
    TYPES.dict = create_type_uninitialized();
    TYPES.null = create_type_uninitialized();
    TYPES.string = create_type_uninitialized();
    TYPES.type = create_type_uninitialized();

    initialize_type(TYPES.dict);
    initialize_type(TYPES.null);
    initialize_type(TYPES.string);
    initialize_type(TYPES.type);
    string_setup_type(TYPES.string);

    // Initialize remaining global types.
    TYPES.any = create_type();
    TYPES.block = create_type();
    TYPES.bool_type = create_type();
    TYPES.error = create_type();
    TYPES.eval_context = create_type();
    TYPES.float_type = create_type();
    TYPES.function = create_type();
    TYPES.int_type = create_type();
    TYPES.list = create_type();
    TYPES.map = create_type();
    TYPES.opaque_pointer = create_type();
    TYPES.symbol = create_type();
    TYPES.term = create_type();
    TYPES.void_type = create_type();

    any_t::setup_type(TYPES.any);
    block_setup_type(TYPES.block);
    bool_t::setup_type(TYPES.bool_type);
    dict_t::setup_type(TYPES.dict);
    eval_context_t::setup_type(TYPES.eval_context);
    function_t::setup_type(TYPES.function);
    hashtable_setup_type(TYPES.map);
    int_t::setup_type(TYPES.int_type);
    list_t::setup_type(TYPES.list);
    symbol_setup_type(TYPES.symbol);
    null_t::setup_type(TYPES.null);
    number_t::setup_type(TYPES.float_type);
    opaque_pointer_t::setup_type(TYPES.opaque_pointer);
    term_setup_type(TYPES.term);
    string_setup_type(TYPES.error); // errors are just stored as strings for now
    type_t::setup_type(TYPES.type);
    void_t::setup_type(TYPES.void_type);

    // Start building World
    g_world = alloc_world();
    g_world->bootstrapStatus = sym_Bootstrapping;

    // Create root Block.
    g_world->root = new Block();
    Block* kernel = g_world->root;

    // Create value function
    Term* valueFunc = kernel->appendNew();
    rename(valueFunc, "value");
    FUNCS.value = valueFunc;

    // Create Type type
    Term* typeType = kernel->appendNew();
    typeType->function = FUNCS.value;
    typeType->type = TYPES.type;
    term_value(typeType)->value_type = TYPES.type;
    term_value(typeType)->value_data.ptr = TYPES.type;
    TYPES.type->declaringTerm = typeType;
    rename(typeType, "Type");

    // Create Any type
    Term* anyType = kernel->appendNew();
    anyType->function = valueFunc;
    anyType->type = TYPES.type;
    term_value(anyType)->value_type = TYPES.type;
    term_value(anyType)->value_data.ptr = TYPES.any;
    TYPES.any->declaringTerm = anyType;
    rename(anyType, "any");

    // Create Function type
    Term* functionType = kernel->appendNew();
    functionType->function = valueFunc;
    functionType->type = TYPES.type;
    TYPES.function->declaringTerm = functionType;
    term_value(functionType)->value_type = TYPES.type;
    term_value(functionType)->value_data.ptr = TYPES.function;
    rename(functionType, "Function");

    // Initialize value() func
    valueFunc->type = TYPES.function;
    valueFunc->function = valueFunc;
    make(TYPES.function, term_value(valueFunc));

    function_t::initialize(TYPES.function, term_value(valueFunc));
    initialize_function(valueFunc);
    as_function(valueFunc)->name = "value";
    block_set_evaluation_empty(function_contents(valueFunc), true);

    // Initialize primitive types (this requires value() function)
    create_type_value(kernel, TYPES.bool_type, "bool");
    create_type_value(kernel, TYPES.block, "Block");
    create_type_value(kernel, TYPES.dict, "Dict");
    create_type_value(kernel, TYPES.float_type, "number");
    create_type_value(kernel, TYPES.int_type, "int");
    create_type_value(kernel, TYPES.list, "List");
    create_type_value(kernel, TYPES.opaque_pointer, "opaque_pointer");
    create_type_value(kernel, TYPES.string, "String");
    create_type_value(kernel, TYPES.symbol, "Symbol");
    create_type_value(kernel, TYPES.term, "Term");
    create_type_value(kernel, TYPES.void_type, "void");
    create_type_value(kernel, TYPES.map, "Map");

    // Finish initializing World (this requires List and Hashtable types)
    world_initialize(g_world);

    // Create global symbol table (requires Hashtable type)
    symbol_initialize_global_table();

    // Setup output_placeholder() function, needed to declare functions properly.
    FUNCS.output = create_value(kernel, TYPES.function, "output_placeholder");
    function_t::initialize(TYPES.function, term_value(FUNCS.output));
    initialize_function(FUNCS.output);
    as_function(FUNCS.output)->name = "output_placeholder";
    as_function(FUNCS.output)->evaluate = NULL;
    as_function(FUNCS.output)->specializeType = output_placeholder_specializeType;
    ca_assert(function_get_output_type(FUNCS.output, 0) == TYPES.any);

    // Fix some holes in value() function
    {
        Function* attrs = as_function(valueFunc);
        Term* output = append_output_placeholder(function_contents(attrs), NULL);
        change_declared_type(output, TYPES.any);
        finish_building_function(function_contents(attrs));
    }

    ca_assert(function_get_output_type(valueFunc, 0) == TYPES.any);

    // input_placeholder() is needed before we can declare a function with inputs
    FUNCS.input = import_function(kernel, NULL, "input_placeholder() -> any");
    block_set_evaluation_empty(function_contents(FUNCS.input), true);

    // Now that we have input_placeholder() let's declare one input on output_placeholder()
    apply(function_contents(as_function(FUNCS.output)),
        FUNCS.input, TermList())->setBoolProp("optional", true);

    namespace_function::early_setup(kernel);

    // Setup declare_field() function, needed to represent compound types.
    FUNCS.declare_field = import_function(kernel, NULL, "declare_field() -> any");

    // Initialize a few more types
    Term* set_type = create_value(kernel, TYPES.type, "Set");
    set_t::setup_type(unbox_type(set_type));

    Term* indexableType = create_value(kernel, TYPES.type, "Indexable");
    indexable_t::setup_type(unbox_type(indexableType));

    TYPES.selector = unbox_type(create_value(kernel, TYPES.type, "Selector"));
    list_t::setup_type(TYPES.selector);

    control_flow_setup_funcs(kernel);
    selector_setup_funcs(kernel);
    loop_setup_functions(kernel);

    // Setup all the builtin functions defined in src/functions
    setup_builtin_functions(kernel);

    FUNCS.section_block = import_function(kernel, NULL, "def section_block() -> any");
    as_function(FUNCS.section_block)->formatSource = section_block_formatSource;

    // Create IMPLICIT_TYPES (deprecated)
    type_initialize_kernel(kernel);

    // Now we can build derived functions

    // Create overloaded functions
    FUNCS.add = create_overloaded_function(kernel, "add(any a,any b) -> any");
    append_to_overloaded_function(FUNCS.add, FUNCS.add_i);
    append_to_overloaded_function(FUNCS.add, FUNCS.add_f);

    Term* less_than = create_overloaded_function(kernel, "less_than(any a,any b) -> bool");
    append_to_overloaded_function(less_than, kernel->get("less_than_i"));
    append_to_overloaded_function(less_than, kernel->get("less_than_f"));

    Term* less_than_eq = create_overloaded_function(kernel, "less_than_eq(any a,any b) -> bool");
    append_to_overloaded_function(less_than_eq, kernel->get("less_than_eq_i"));
    append_to_overloaded_function(less_than_eq, kernel->get("less_than_eq_f"));

    Term* greater_than = create_overloaded_function(kernel, "greater_than(any a,any b) -> bool");
    append_to_overloaded_function(greater_than, kernel->get("greater_than_i"));
    append_to_overloaded_function(greater_than, kernel->get("greater_than_f"));

    Term* greater_than_eq = create_overloaded_function(kernel, "greater_than_eq(any a,any b) -> bool");
    append_to_overloaded_function(greater_than_eq, kernel->get("greater_than_eq_i"));
    append_to_overloaded_function(greater_than_eq, kernel->get("greater_than_eq_f"));

    Term* max_func = create_overloaded_function(kernel, "max(any a,any b) -> any");
    append_to_overloaded_function(max_func, kernel->get("max_i"));
    append_to_overloaded_function(max_func, kernel->get("max_f"));

    Term* min_func = create_overloaded_function(kernel, "min(any a,any b) -> any");
    append_to_overloaded_function(min_func, kernel->get("min_i"));
    append_to_overloaded_function(min_func, kernel->get("min_f"));

    Term* remainder_func = create_overloaded_function(kernel, "remainder(any a,any b) -> any");
    append_to_overloaded_function(remainder_func, kernel->get("remainder_i"));
    append_to_overloaded_function(remainder_func, kernel->get("remainder_f"));

    Term* mod_func = create_overloaded_function(kernel, "mod(any a,any b) -> any");
    append_to_overloaded_function(mod_func, kernel->get("mod_i"));
    append_to_overloaded_function(mod_func, kernel->get("mod_f"));

    FUNCS.mult = create_overloaded_function(kernel, "mult(any a,any b) -> any");
    append_to_overloaded_function(FUNCS.mult, kernel->get("mult_i"));
    append_to_overloaded_function(FUNCS.mult, kernel->get("mult_f"));

    FUNCS.neg = create_overloaded_function(kernel, "neg(any n) -> any");
    append_to_overloaded_function(FUNCS.neg, kernel->get("neg_i"));
    append_to_overloaded_function(FUNCS.neg, kernel->get("neg_f"));
    as_function(FUNCS.neg)->formatSource = neg_function::formatSource;

    FUNCS.sub = create_overloaded_function(kernel, "sub(any a,any b) -> any");
    append_to_overloaded_function(FUNCS.sub, kernel->get("sub_i"));
    append_to_overloaded_function(FUNCS.sub, kernel->get("sub_f"));

    // Create vectorized functions
    Term* add_v = create_function(kernel, "add_v");
    create_function_vectorized_vv(function_contents(add_v), FUNCS.add, TYPES.list, TYPES.list);
    Term* add_s = create_function(kernel, "add_s");
    create_function_vectorized_vs(function_contents(add_s), FUNCS.add, TYPES.list, TYPES.any);

    append_to_overloaded_function(FUNCS.add, add_v);
    append_to_overloaded_function(FUNCS.add, add_s);

    Term* sub_v = create_function(kernel, "sub_v");
    create_function_vectorized_vv(function_contents(sub_v), FUNCS.sub, TYPES.list, TYPES.list);
    Term* sub_s = create_function(kernel, "sub_s");
    create_function_vectorized_vs(function_contents(sub_s), FUNCS.sub, TYPES.list, TYPES.any);
    
    append_to_overloaded_function(FUNCS.sub, sub_v);
    append_to_overloaded_function(FUNCS.sub, sub_s);

    // Create vectorized mult() functions
    Term* mult_v = create_function(kernel, "mult_v");
    create_function_vectorized_vv(function_contents(mult_v), FUNCS.mult, TYPES.list, TYPES.list);
    Term* mult_s = create_function(kernel, "mult_s");
    create_function_vectorized_vs(function_contents(mult_s), FUNCS.mult, TYPES.list, TYPES.any);

    append_to_overloaded_function(FUNCS.mult, mult_v);
    append_to_overloaded_function(FUNCS.mult, mult_s);

    Term* div_s = create_function(kernel, "div_s");
    create_function_vectorized_vs(function_contents(div_s), FUNCS.div, TYPES.list, TYPES.any);

    // Need dynamic_method before any hosted functions
    FUNCS.dynamic_method = import_function(kernel, dynamic_method_call,
            "def dynamic_method(any inputs :multiple) -> any");

    // Load the standard library from stdlib.ca
    parser::compile(kernel, parser::statement_list, STDLIB_CA_TEXT);

    // Install C functions
    static const ImportRecord records[] = {
        {"assert", hosted_assert},
        {"cppbuild:build_module", cppbuild_function::build_module},
        {"file:version", file__version},
        {"file:exists", file__exists},
        {"file:read_text", file__read_text},
        {"length", length},
        {"from_string", from_string},
        {"to_string_repr", to_string_repr},
        {"call_actor", call_actor_func},
        {"send", send_func},
        {"test_spy", test_spy},
        {"test_oracle", test_oracle},
        {"refactor:rename", refactor__rename},
        {"refactor:change_function", refactor__change_function},
        {"reflect:this_block", reflect__this_block},
        {"reflect:kernel", reflect__kernel},
        {"sys:module_search_paths", sys__module_search_paths},
        {"sys:perf_stats_reset", sys__perf_stats_reset},
        {"sys:perf_stats_dump", sys__perf_stats_dump},

        {"Dict.count", Dict__count},
        {"Dict.get", Dict__get},
        {"Dict.set", Dict__set},

        {"Function.block", Function__block},

        {"empty_list", empty_list},
        {"List.append", List__append},
        {"List.concat", List__concat},
        {"List.resize", List__resize},
        {"List.count", List__count},
        {"List.insert", List__insert},
        {"List.length", List__length},
        {"List.join", List__join},
        {"List.slice", List__slice},
        {"List.get", List__get},
        {"List.set", List__set},

        {"Map.contains", Map__contains},
        {"Map.remove", Map__remove},
        {"Map.get", Map__get},
        {"Map.set", Map__set},
        {"Map.insertPairs", Map__insertPairs},

        {"Mutable.get", Mutable__get},
        {"Mutable.set", Mutable__set},

        {"String.char_at", String__char_at},
        {"String.ends_with", String__ends_with},
        {"String.length", String__length},
        {"String.substr", String__substr},
        {"String.slice", String__slice},
        {"String.starts_with", String__starts_with},
        {"String.split", String__split},
        {"String.to_camel_case", String__to_camel_case},
        {"String.to_upper", String__to_upper},
        {"String.to_lower", String__to_lower},
        
        {"Type.name", Type__name},
        {"Type.property", Type__property},
        {"Type.declaringTerm", Type__declaringTerm},
        {"type", typeof_func},
        {"static_type", static_type_func},

        {NULL, NULL}
    };

    install_function_list(kernel, records);

    closures_install_functions(kernel);
    modules_install_functions(kernel);
    reflection_install_functions(kernel);
    interpreter_install_functions(kernel);

    // Fetch refereneces to certain builtin funcs.
    FUNCS.block_dynamic_call = kernel->get("Block.call");
    FUNCS.dll_patch = kernel->get("sys:dll_patch");
    FUNCS.dynamic_call = kernel->get("dynamic_call");
    FUNCS.has_effects = kernel->get("has_effects");
    FUNCS.length = kernel->get("length");
    FUNCS.list_append = kernel->get("List.append");
    FUNCS.native_patch = kernel->get("native_patch");
    FUNCS.not_func = kernel->get("not");
    FUNCS.output_explicit = kernel->get("output");
    FUNCS.type = kernel->get("type");

    block_set_has_effects(nested_contents(FUNCS.has_effects), true);

    // Finish setting up some hosted types
    TYPES.actor = as_type(kernel->get("Actor"));
    TYPES.color = as_type(kernel->get("Color"));
    TYPES.closure = as_type(kernel->get("Closure"));
    callable_t::setup_type(as_type(kernel->get("Callable")));
    TYPES.frame = as_type(kernel->get("Frame"));
    TYPES.point = as_type(kernel->get("Point"));
    TYPES.file_signature = as_type(kernel->get("FileSignature"));

    Type* mutableType = as_type(kernel->get("Mutable"));
    circa_setup_object_type(mutableType, sizeof(Value), MutableRelease);
    mutableType->initialize = MutableInitialize;

    color_t::setup_type(TYPES.color);

    as_function(FUNCS.list_append)->specializeType = List__append_specializeType;
}
Пример #7
0
void bootstrap_kernel()
{
    memset(&FUNCS, 0, sizeof(FUNCS));
    memset(&TYPES, 0, sizeof(TYPES));

    // Allocate a World object.
    g_world = alloc_world();
    g_world->bootstrapStatus = s_Bootstrapping;
    World* world = g_world;

    // Instanciate the types that are used by Type.
    TYPES.table = create_type_unconstructed();
    TYPES.nil = create_type_unconstructed();
    TYPES.string = create_type_unconstructed();
    TYPES.type = create_type_unconstructed();

    // Now we can fully instanciate types.
    type_finish_construction(TYPES.table);
    type_finish_construction(TYPES.nil);
    type_finish_construction(TYPES.string);
    type_finish_construction(TYPES.type);
    string_setup_type(TYPES.string);

    // Initialize remaining global types.
    TYPES.any = create_type();
    TYPES.blob = create_type();
    TYPES.block = create_type();
    TYPES.bool_type = create_type();
    TYPES.error = create_type();
    TYPES.float_type = create_type();
    TYPES.int_type = create_type();
    TYPES.list = create_type();
    TYPES.native_ptr = create_type();
    TYPES.table = create_type();
    TYPES.opaque_pointer = create_type();
    TYPES.symbol = create_type();
    TYPES.term = create_type();
    TYPES.vm = create_type();
    TYPES.void_type = create_type();

    for_each_root_type(type_set_root);

    any_setup_type(TYPES.any);
    blob_setup_type(TYPES.blob);
    block_setup_type(TYPES.block);
    bool_setup_type(TYPES.bool_type);
    hashtable_setup_type(TYPES.table);
    int_setup_type(TYPES.int_type);
    list_t::setup_type(TYPES.list);
    symbol_setup_type(TYPES.symbol);
    native_ptr_setup_type(TYPES.native_ptr);
    null_setup_type(TYPES.nil);
    number_setup_type(TYPES.float_type);
    opaque_pointer_setup_type(TYPES.opaque_pointer);
    term_setup_type(TYPES.term);
    string_setup_type(TYPES.error); // errors are just stored as strings for now
    type_t::setup_type(TYPES.type);
    void_setup_type(TYPES.void_type);
    vm_setup_type(TYPES.vm);

    // Finish initializing World (this requires List and Hashtable types)
    world_initialize(g_world);

    // Create builtins block.
    Value builtinsStr;
    set_string(&builtinsStr, "builtins");
    Block* builtins = create_module(g_world);
    module_set_name(world, builtins, &builtinsStr);
    g_world->builtins = builtins;

    // Create function_decl function.
    Term* functionDeclFunction = builtins->appendNew();
    rename(functionDeclFunction, "function_decl");
    FUNCS.function_decl = functionDeclFunction;
    FUNCS.function_decl->function = FUNCS.function_decl;
    make_nested_contents(FUNCS.function_decl);
    block_set_function_has_nested(nested_contents(FUNCS.function_decl), true);

    // Create value function
    Term* valueFunc = builtins->appendNew();
    rename(valueFunc, "value");
    FUNCS.value = valueFunc;

    // Create Type type
    Term* typeType = builtins->appendNew();
    typeType->function = FUNCS.value;
    typeType->type = TYPES.type;
    term_value(typeType)->value_type = TYPES.type;
    term_value(typeType)->value_data.ptr = TYPES.type;
    TYPES.type->declaringTerm = typeType;
    rename(typeType, "Type");

    // Create Any type
    Term* anyType = builtins->appendNew();
    anyType->function = valueFunc;
    anyType->type = TYPES.type;
    term_value(anyType)->value_type = TYPES.type;
    term_value(anyType)->value_data.ptr = TYPES.any;
    TYPES.any->declaringTerm = anyType;
    rename(anyType, "any");

    // Initialize value() func
    valueFunc->type = TYPES.any;
    valueFunc->function = FUNCS.function_decl;
    make_nested_contents(valueFunc);
    block_set_evaluation_empty(nested_contents(valueFunc), true);

    // Initialize primitive types (this requires value() function)
    create_type_value(builtins, TYPES.blob, "Blob");
    create_type_value(builtins, TYPES.bool_type, "bool");
    create_type_value(builtins, TYPES.block, "Block");
    create_type_value(builtins, TYPES.float_type, "number");
    create_type_value(builtins, TYPES.int_type, "int");
    create_type_value(builtins, TYPES.list, "List");
    create_type_value(builtins, TYPES.opaque_pointer, "opaque_pointer");
    create_type_value(builtins, TYPES.native_ptr, "native_ptr");
    create_type_value(builtins, TYPES.string, "String");
    create_type_value(builtins, TYPES.symbol, "Symbol");
    create_type_value(builtins, TYPES.term, "Term");
    create_type_value(builtins, TYPES.table, "Table");
    create_type_value(builtins, TYPES.void_type, "void");
    create_type_value(builtins, TYPES.vm, "VM");

    // Create global symbol table (requires Hashtable type)
    symbol_initialize_global_table();

    // Setup output_placeholder() function, needed to declare functions properly.
    FUNCS.output = apply(builtins, FUNCS.function_decl, TermList(), "output_placeholder");
    nested_contents(FUNCS.output)->overrides.specializeType = output_placeholder_specializeType;
    ca_assert(get_output_type(nested_contents(FUNCS.output), 0) == TYPES.any);

    // Now that output_placeholder is created, fix the value() function.
    {
        Term* output = append_output_placeholder(nested_contents(valueFunc), NULL);
        set_declared_type(output, TYPES.any);
        finish_building_function(nested_contents(valueFunc));
    }

    ca_assert(get_output_type(nested_contents(valueFunc), 0) == TYPES.any);

    // input_placeholder() is needed before we can declare a function with inputs
    FUNCS.input = apply(builtins, FUNCS.function_decl, TermList(), "input_placeholder");
    block_set_evaluation_empty(nested_contents(FUNCS.input), true);

    // Now that we have input_placeholder(), declare one input on output_placeholder()
    apply(nested_contents(FUNCS.output),
        FUNCS.input, TermList())->setBoolProp(s_Optional, true);

    // Initialize a few more types
    TYPES.selector = unbox_type(create_value(builtins, TYPES.type, "Selector"));
    list_t::setup_type(TYPES.selector);

    // Need the comment() function before parsing stdlib.ca
    FUNCS.comment = apply(builtins, FUNCS.function_decl, TermList(), "comment");

    // Parse stdlib.ca
    parse(builtins, parse_statement_list, find_builtin_file("$builtins/stdlib.ca"));
    set_string(block_insert_property(builtins, s_ModuleName), "stdlib");

    blob_install_functions(world->builtinPatch);
    selector_setup_funcs(world->builtinPatch);
    closures_install_functions(world->builtinPatch);
    reflection_install_functions(world->builtinPatch);
    misc_builtins_setup_functions(world->builtinPatch);
    type_install_functions(world->builtinPatch);
    vm_install_functions(world->builtinPatch);

    block_set_bool_prop(builtins, s_Builtins, true);

    ca_assert(FUNCS.declared_state != NULL);

    nested_contents(FUNCS.add)->overrides.specializeType = specializeType_add_sub_mult;
    nested_contents(FUNCS.sub)->overrides.specializeType = specializeType_add_sub_mult;
    nested_contents(FUNCS.mult)->overrides.specializeType = specializeType_add_sub_mult;
    nested_contents(FUNCS.div)->overrides.specializeType = specializeType_div;

    FUNCS.get_with_symbol = builtins->get("get_with_symbol");
    FUNCS.length = builtins->get("length");
    FUNCS.list_append = builtins->get("List.append");
    FUNCS.native_patch = builtins->get("native_patch");
    FUNCS.package = builtins->get("package");

    nested_contents(builtins->get("Type.cast"))->overrides.specializeType = Type_cast_specializeType;

    // Finish setting up types that are declared in stdlib.ca.
    TYPES.color = as_type(builtins->get("Color"));
    TYPES.func = as_type(builtins->get("Func"));
    TYPES.module_ref = as_type(builtins->get("Module"));
    TYPES.vec2 = as_type(builtins->get("Vec2"));

    // Fix function_decl now that Func type is available.
    {
        set_declared_type(append_output_placeholder(nested_contents(FUNCS.function_decl), NULL),
            TYPES.func);
        set_declared_type(FUNCS.function_decl, TYPES.func);
        finish_building_function(nested_contents(FUNCS.function_decl));
    }

    // Also, now that Func type is available, update all static closures.
    for (BlockIterator it(builtins); it; ++it) {
        Term* term = *it;
        if (is_function(term)) {
            set_declared_type(term, TYPES.func);
            if (term->owningBlock == builtins)
                // Functions at top level must be static closures
                update_static_closure_force(term);
            else
                update_static_closure_if_possible(term);
        }
    }

    nested_contents(FUNCS.list_append)->overrides.specializeType = List__append_specializeType;

    #define set_evaluation_empty(name) block_set_evaluation_empty(nested_contents(FUNCS.name), true)
        set_evaluation_empty(annotate);
        set_evaluation_empty(annotate_block);
        set_evaluation_empty(return_func);
        set_evaluation_empty(discard);
        set_evaluation_empty(break_func);
        set_evaluation_empty(continue_func);
        set_evaluation_empty(comment);
        set_evaluation_empty(extra_output);
        set_evaluation_empty(loop_iterator);
        set_evaluation_empty(static_error);
    #undef set_evaluation_empty

    block_link_missing_functions(builtins, builtins);
}