void test_if_joining() { Branch branch; // Test that a name defined in one branch is not rebound in outer scope branch.eval("if true { apple = 5 }"); test_assert(!branch.contains("apple")); // Test that a name which exists in the outer scope is rebound Term* original_banana = create_int(&branch, 10, "banana"); branch.eval("if true { banana = 15 }"); test_assert(branch["banana"] != original_banana); // Test that if a name is defined in both 'if' and 'else' branches, that it gets // defined in the outer scope. branch.eval("if true { Cardiff = 5 } else { Cardiff = 11 }"); test_assert(branch.contains("Cardiff")); // Test that the type of the joined name is correct branch.compile("if true { a = 4 } else { a = 5 }; a = a"); test_equals(get_output_type(branch["a"])->name, "int"); }
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); }
void query (void) { ProgTime TotalStartTime, TotalInvfTime, TotalTextTime; InitQueryTimes iqt; query_data *qd; TotalStartTime.RealTime = TotalStartTime.CPUTime = 0; TotalInvfTime.RealTime = TotalInvfTime.CPUTime = 0; TotalTextTime.RealTime = TotalTextTime.CPUTime = 0; qd = InitQuerySystem (GetDefEnv ("mgdir", "./"), GetDefEnv ("mgname", ""), &iqt); if (!qd) FatalError (1, mg_errorstrs[mg_errno], mg_error_data); start_up_stats (qd, iqt); while (1) { ProgTime StartTime, InvfTime, TextTime; char QueryType; char OutputType; char *line; ResetFileStats (qd); qd->max_mem_in_use = qd->mem_in_use = 0; qd->tot_hops_taken += qd->hops_taken; qd->tot_num_of_ptrs += qd->num_of_ptrs; qd->tot_num_of_accum += qd->num_of_accum; qd->tot_num_of_terms += qd->num_of_terms; qd->tot_num_of_ans += qd->num_of_ans; qd->tot_text_idx_lookups += qd->text_idx_lookups; qd->hops_taken = qd->num_of_ptrs = 0; qd->num_of_accum = qd->num_of_ans = qd->num_of_terms = 0; qd->text_idx_lookups = 0; Display_Stats (stderr); Clear_Stats (); line = get_query (qd); if (!line || Quitting) break; GetPostProc (line); GetTime (&StartTime); FreeQueryDocs (qd); QueryType = get_query_type (); OutputType = get_output_type (); /* No point in hiliting words on a docnum query */ if (OutputType == OUTPUT_HILITE && QueryType == QUERY_DOCNUMS) OutputType = OUTPUT_TEXT; switch (QueryType) { case QUERY_BOOLEAN: { char *maxdocs; BooleanQueryInfo bqi; maxdocs = GetDefEnv ("maxdocs", "all"); bqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1; BooleanQuery (qd, line, &bqi); break; } case QUERY_APPROX: case QUERY_RANKED: { char *maxdocs; char *maxterms; char *maxaccum; RankedQueryInfo rqi; maxdocs = GetDefEnv ("maxdocs", "all"); maxterms = GetDefEnv ("max_terms", "all"); maxaccum = GetDefEnv ("max_accumulators", "all"); rqi.Sort = BooleanEnv (GetEnv ("sorted_terms"), 0); rqi.QueryFreqs = BooleanEnv (GetEnv ("qfreq"), 1); rqi.Exact = QueryType == QUERY_RANKED; rqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1; rqi.MaxTerms = strcmp (maxterms, "all") ? atoi (maxterms) : -1; rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve; if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas")) rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas")); rqi.AccumMethod = toupper (*GetDefEnv ("accumulator_method", "A")); rqi.MaxAccums = strcmp (maxaccum, "all") ? atoi (maxaccum) : -1; rqi.HashTblSize = IntEnv (GetEnv ("hash_tbl_size"), 1000); rqi.StopAtMaxAccum = BooleanEnv (GetEnv ("stop_at_max_accum"), 0); rqi.skip_dump = GetEnv ("skip_dump"); RankedQuery (qd, line, &rqi); break; } case QUERY_DOCNUMS: { DocnumsQuery (qd, line); break; } } GetTime (&InvfTime); if (qd->DL) MoreDocs (qd, line, OutputType); GetTime (&TextTime); if (BooleanEnv (GetEnv ("timestats"), 0) || BooleanEnv (GetEnv ("briefstats"), 0)) QueryTimeStats (&StartTime, &InvfTime, &TextTime); if (BooleanEnv (GetEnv ("diskstats"), 0) || BooleanEnv (GetEnv ("briefstats"), 0)) File_Stats (qd); if (BooleanEnv (GetEnv ("memstats"), 0) || BooleanEnv (GetEnv ("briefstats"), 0)) MemStats (qd); if (BooleanEnv (GetEnv ("sizestats"), 0)) SizeStats (qd); TotalInvfTime.RealTime += InvfTime.RealTime - StartTime.RealTime; TotalInvfTime.CPUTime += InvfTime.CPUTime - StartTime.CPUTime; TotalTextTime.RealTime += TextTime.RealTime - StartTime.RealTime; TotalTextTime.CPUTime += TextTime.CPUTime - StartTime.CPUTime; } if (isatty (fileno (InFile)) && !Quitting) fprintf (stderr, "\n"); shut_down_stats (qd, &TotalStartTime, &TotalInvfTime, &TotalTextTime); Display_Stats (stderr); }
Type* extra_output_specializeType(Term* term) { ca_assert(term->input(0)->owningBlock == term->owningBlock); int myOutputIndex = term->index - term->input(0)->index; return get_output_type(term->input(0), myOutputIndex); }