//: So far we've been calling a fixed recipe in each instruction, but we'd //: also like to make the recipe a variable, pass recipes to "higher-order" //: recipes, return recipes from recipes and so on. void test_call_literal_recipe() { run( "def main [\n" " 1:num <- call f, 34\n" "]\n" "def f x:num -> y:num [\n" " local-scope\n" " load-ingredients\n" " y <- copy x\n" "]\n" ); CHECK_TRACE_CONTENTS( "mem: storing 34 in location 1\n" ); } :(before "End Mu Types Initialization") put(Type_ordinal, "recipe-literal", 0); // 'recipe' variables can store recipe-literal type_ordinal recipe = put(Type_ordinal, "recipe", Next_type_ordinal++); get_or_insert(Type, recipe).name = "recipe"; :(after "Deduce Missing Type(x, caller)") if (!x.type) try_initialize_recipe_literal(x, caller); :(before "Type Check in Type-ingredient-aware check_or_set_types_by_name") if (!x.type) try_initialize_recipe_literal(x, variant); :(code) void try_initialize_recipe_literal(reagent& x, const recipe& caller) { if (x.type) return; if (!contains_key(Recipe_ordinal, x.name)) return; if (contains_reagent_with_non_recipe_literal_type(caller, x.name)) return; x.type = new type_tree("recipe-literal"); x.set_value(get(Recipe_ordinal, x.name)); } bool contains_reagent_with_non_recipe_literal_type(const recipe& caller, const string& name) { for (int i = 0; i < SIZE(caller.steps); ++i) { const instruction& inst = caller.steps.at(i); for (int i = 0; i < SIZE(inst.ingredients); ++i) if (is_matching_non_recipe_literal(inst.ingredients.at(i), name)) return true; for (int i = 0; i < SIZE(inst.products); ++i) if (is_matching_non_recipe_literal(inst.products.at(i), name)) return true; } return false; } bool is_matching_non_recipe_literal(const reagent& x, const string& name) { if (x.name != name) return false; if (!x.type) return false; return !x.type->atom || x.type->name != "recipe-literal"; } //: It's confusing to use variable names that are also recipe names. Always //: assume variable types override recipe literals. void test_error_on_recipe_literal_used_as_a_variable() { Hide_errors = true; run( "def main [\n" " local-scope\n" " a:bool <- equal break 0\n" " break:bool <- copy 0\n" "]\n" ); CHECK_TRACE_CONTENTS( "error: main: missing type for 'break' in 'a:bool <- equal break, 0'\n" ); } :(before "End Primitive Recipe Declarations") CALL, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "call", CALL); :(before "End Primitive Recipe Checks") case CALL: { if (inst.ingredients.empty()) { raise << maybe(get(Recipe, r).name) << "'call' requires at least one ingredient (the recipe to call)\n" << end(); break; } if (!is_mu_recipe(inst.ingredients.at(0))) { raise << maybe(get(Recipe, r).name) << "first ingredient of 'call' should be a recipe, but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); break; } break; } :(before "End Primitive Recipe Implementations") case CALL: { // Begin Call trace(Callstack_depth+1, "trace") << "indirect 'call': incrementing callstack depth to " << Callstack_depth << end(); ++Callstack_depth; assert(Callstack_depth < Max_depth); if (!ingredients.at(0).at(0)) { raise << maybe(current_recipe_name()) << "tried to call empty recipe in '" << to_string(current_instruction()) << "'" << end(); break; } const call& caller_frame = current_call(); instruction/*copy*/ call_instruction = to_instruction(caller_frame); call_instruction.operation = ingredients.at(0).at(0); call_instruction.ingredients.erase(call_instruction.ingredients.begin()); Current_routine->calls.push_front(call(ingredients.at(0).at(0))); ingredients.erase(ingredients.begin()); // drop the callee finish_call_housekeeping(call_instruction, ingredients); // not done with caller write_products = false; fall_through_to_next_instruction = false; break; } :(code) void test_call_variable() { run( "def main [\n" " {1: (recipe number -> number)} <- copy f\n" " 2:num <- call {1: (recipe number -> number)}, 34\n" "]\n" "def f x:num -> y:num [\n" " local-scope\n" " load-ingredients\n" " y <- copy x\n" "]\n" ); CHECK_TRACE_CONTENTS( "mem: storing 34 in lo
discard """
nimout: '''0
0
0
'''
"""
import tables
# bug #5327
type
MyType* = object
counter: int
proc foo(t: var MyType) =
echo t.counter
proc bar(t: MyType) =
echo t.counter
static:
var myValue: MyType
myValue.foo # works nicely
var refValue: ref MyType
refValue.new
refValue[].foo # fails to compile
refValue[].bar # works again nicely
static:
var otherTable = newTable[string, string]()
otherTable["hallo"] = "123"
otherTable["welt"] = "456"
doAssert otherTable == {"hallo": "123", "welt": "456"}.newTable