From 145a078387b8bce5e8e3c93c333c030aa7455e4c Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 9 Nov 2024 17:26:01 -0500 Subject: [PATCH] Make the compiler stricter about not promoting local value variables to pointers --- compile.c | 116 +++++++++++++++++++--------------- examples/ini/ini.tm | 4 +- examples/log/log.tm | 10 +-- examples/tomodeps/tomodeps.tm | 12 ++-- examples/wrap/wrap.tm | 6 +- test/arrays.tm | 22 +++---- test/iterators.tm | 4 +- test/sets.tm | 8 +-- test/tables.tm | 4 +- 9 files changed, 99 insertions(+), 87 deletions(-) diff --git a/compile.c b/compile.c index 66f2c9a..e8c24ea 100644 --- a/compile.c +++ b/compile.c @@ -2703,49 +2703,58 @@ CORD compile(env_t *env, ast_t *ast) case MethodCall: { auto call = Match(ast, MethodCall); type_t *self_t = get_type(env, call->self); - type_t *self_value_t = value_type(self_t); + int64_t pointer_depth = 0; + type_t *self_value_t = self_t; + for (; self_value_t->tag == PointerType; self_value_t = Match(self_value_t, PointerType)->pointed) + pointer_depth += 1; + + CORD self = compile(env, call->self); + +#define EXPECT_POINTER(article, name) do { \ + if (pointer_depth < 1) code_err(call->self, "I expected "article" "name" @pointer here, not "article" "name" value"); \ + else if (pointer_depth > 1) code_err(call->self, "I expected "article" "name" @pointer here, not a nested "name" pointer"); \ +} while (0) switch (self_value_t->tag) { case ArrayType: { type_t *item_t = Match(self_value_t, ArrayType)->item_type; CORD padded_item_size = CORD_asprintf("%ld", type_size(item_t)); ast_t *default_rng = FakeAST(InlineCCode, .code="default_rng", .type=RNG_TYPE); - if (streq(call->name, "insert")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=new(arg_t, .name="at", .type=INT_TYPE, .default_val=FakeAST(Int, .str="0"))); return CORD_all("Array$insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "insert_all")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); arg_t *arg_spec = new(arg_t, .name="items", .type=self_value_t, .next=new(arg_t, .name="at", .type=INT_TYPE, .default_val=FakeAST(Int, .str="0"))); return CORD_all("Array$insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "remove_at")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); arg_t *arg_spec = new(arg_t, .name="index", .type=INT_TYPE, .default_val=FakeAST(Int, .str="-1"), .next=new(arg_t, .name="count", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"))); return CORD_all("Array$remove_at(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "remove_item")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=new(arg_t, .name="max_count", .type=INT_TYPE, .default_val=FakeAST(Int, .str="-1"))); return CORD_all("Array$remove_item_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "random")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="rng", .type=RNG_TYPE, .default_val=default_rng); return CORD_all("Array$random_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type(item_t), ")"); } else if (streq(call->name, "has")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t); return CORD_all("Array$has_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "sample")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="count", .type=INT_TYPE, .next=new(arg_t, .name="weights", .type=Type(ArrayType, .item_type=Type(NumType)), .default_val=FakeAST(Null, .type=new(type_ast_t, .tag=ArrayTypeAST, @@ -2754,18 +2763,18 @@ CORD compile(env_t *env, ast_t *ast) return CORD_all("Array$sample(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "shuffle")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); arg_t *arg_spec = new(arg_t, .name="rng", .type=RNG_TYPE, .default_val=default_rng); return CORD_all("Array$shuffle(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "shuffled")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="rng", .type=RNG_TYPE, .default_val=default_rng); return CORD_all("Array$shuffled(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "sort") || streq(call->name, "sorted")) { - CORD self = streq(call->name, "sort") - ? compile_to_pointer_depth(env, call->self, 1, false) - // No need to do an ARRAY_COPY() here because it happens inside Array$sorted(): - : compile_to_pointer_depth(env, call->self, 0, false); + if (streq(call->name, "sort")) + EXPECT_POINTER("an", "array"); + else + self = compile_to_pointer_depth(env, call->self, 0, false); CORD comparison; if (call->args) { type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); @@ -2778,7 +2787,7 @@ CORD compile(env_t *env, ast_t *ast) } return CORD_all("Array$", call->name, "(", self, ", ", comparison, ", ", padded_item_size, ")"); } else if (streq(call->name, "heapify")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); CORD comparison; if (call->args) { type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); @@ -2791,7 +2800,7 @@ CORD compile(env_t *env, ast_t *ast) } return CORD_all("Array$heapify(", self, ", ", comparison, ", ", padded_item_size, ")"); } else if (streq(call->name, "heap_push")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), .ret=Type(IntType, .bits=TYPE_IBITS32)); @@ -2804,7 +2813,7 @@ CORD compile(env_t *env, ast_t *ast) CORD arg_code = compile_arguments(env, ast, arg_spec, call->args); return CORD_all("Array$heap_push_value(", self, ", ", arg_code, ", ", padded_item_size, ")"); } else if (streq(call->name, "heap_pop")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), .ret=Type(IntType, .bits=TYPE_IBITS32)); @@ -2816,7 +2825,7 @@ CORD compile(env_t *env, ast_t *ast) CORD arg_code = compile_arguments(env, ast, arg_spec, call->args); return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", padded_item_size, ", ", compile_type(item_t), ")"); } else if (streq(call->name, "binary_search")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL); + self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), .ret=Type(IntType, .bits=TYPE_IBITS32)); @@ -2829,43 +2838,43 @@ CORD compile(env_t *env, ast_t *ast) CORD arg_code = compile_arguments(env, ast, arg_spec, call->args); return CORD_all("Array$binary_search_value(", self, ", ", arg_code, ")"); } else if (streq(call->name, "clear")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("an", "array"); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Array$clear(", self, ")"); } else if (streq(call->name, "find")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t); return CORD_all("Array$find_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "first")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL); + self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true); type_t *predicate_type = Type( ClosureType, .fn=Type(FunctionType, .args=new(arg_t, .name="item", .type=item_ptr), .ret=Type(BoolType))); arg_t *arg_spec = new(arg_t, .name="predicate", .type=predicate_type); return CORD_all("Array$first(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")"); } else if (streq(call->name, "from")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, true); + self = compile_to_pointer_depth(env, call->self, 0, true); arg_t *arg_spec = new(arg_t, .name="first", .type=INT_TYPE); return CORD_all("Array$from(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")"); } else if (streq(call->name, "to")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, true); + self = compile_to_pointer_depth(env, call->self, 0, true); arg_t *arg_spec = new(arg_t, .name="last", .type=INT_TYPE); return CORD_all("Array$to(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")"); } else if (streq(call->name, "by")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, true); + self = compile_to_pointer_depth(env, call->self, 0, true); arg_t *arg_spec = new(arg_t, .name="stride", .type=INT_TYPE); return CORD_all("Array$by(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "reversed")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, true); + self = compile_to_pointer_depth(env, call->self, 0, true); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Array$reversed(", self, ", ", padded_item_size, ")"); } else if (streq(call->name, "unique")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Table$from_entries(", self, ", Set$info(", compile_type_info(env, item_t), "))"); } else if (streq(call->name, "counts")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Array$counts(", self, ", ", compile_type_info(env, self_value_t), ")"); } else code_err(ast, "There is no '%s' method for arrays", call->name); @@ -2873,61 +2882,63 @@ CORD compile(env_t *env, ast_t *ast) case SetType: { auto set = Match(self_value_t, SetType); if (streq(call->name, "has")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="key", .type=set->item_type); return CORD_all("Table$has_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "add")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "set"); arg_t *arg_spec = new(arg_t, .name="item", .type=set->item_type); return CORD_all("Table$set_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", NULL, ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "add_all")) { + EXPECT_POINTER("a", "set"); arg_t *arg_spec = new(arg_t, .name="items", .type=Type(ArrayType, .item_type=Match(self_value_t, SetType)->item_type)); - return CORD_all("({ Table_t *set = ", compile_to_pointer_depth(env, call->self, 1, false), "; ", + return CORD_all("({ Table_t *set = ", self, "; ", "Array_t to_add = ", compile_arguments(env, ast, arg_spec, call->args), "; ", "for (int64_t i = 0; i < to_add.length; i++)\n" "Table$set(set, to_add.data + i*to_add.stride, NULL, ", compile_type_info(env, self_value_t), ");\n", "(void)0; })"); } else if (streq(call->name, "remove")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "set"); arg_t *arg_spec = new(arg_t, .name="item", .type=set->item_type); return CORD_all("Table$remove_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "remove_all")) { + EXPECT_POINTER("a", "set"); arg_t *arg_spec = new(arg_t, .name="items", .type=Type(ArrayType, .item_type=Match(self_value_t, SetType)->item_type)); - return CORD_all("({ Table_t *set = ", compile_to_pointer_depth(env, call->self, 1, false), "; ", + return CORD_all("({ Table_t *set = ", self, "; ", "Array_t to_add = ", compile_arguments(env, ast, arg_spec, call->args), "; ", "for (int64_t i = 0; i < to_add.length; i++)\n" "Table$remove(set, to_add.data + i*to_add.stride, ", compile_type_info(env, self_value_t), ");\n", "(void)0; })"); } else if (streq(call->name, "clear")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "set"); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Table$clear(", self, ")"); } else if (streq(call->name, "with")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="other", .type=self_value_t); return CORD_all("Table$with(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "overlap")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="other", .type=self_value_t); return CORD_all("Table$overlap(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "without")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="other", .type=self_value_t); return CORD_all("Table$without(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "is_subset_of")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="other", .type=self_value_t, .next=new(arg_t, .name="strict", .type=Type(BoolType), .default_val=FakeAST(Bool, false))); return CORD_all("Table$is_subset_of(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "is_superset_of")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="other", .type=self_value_t, .next=new(arg_t, .name="strict", .type=Type(BoolType), .default_val=FakeAST(Bool, false))); return CORD_all("Table$is_superset_of(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), @@ -2940,31 +2951,31 @@ CORD compile(env_t *env, ast_t *ast) arg_t *front_default_end = new(arg_t, .name="front", .type=Type(BoolType), .default_val=FakeAST(Bool, false)); arg_t *front_default_start = new(arg_t, .name="front", .type=Type(BoolType), .default_val=FakeAST(Bool, true)); if (streq(call->name, "give")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=front_default_end); return CORD_all("Channel$give_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "give_all")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="to_give", .type=Type(ArrayType, .item_type=item_t), .next=front_default_end); return CORD_all("Channel$give_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "get")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = front_default_start; return CORD_all("Channel$get_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type(item_t), ", ", padded_item_size, ")"); } else if (streq(call->name, "peek")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = front_default_start; return CORD_all("Channel$peek_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type(item_t), ")"); } else if (streq(call->name, "clear")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Channel$clear(", self, ")"); } else if (streq(call->name, "view")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Channel$view(", self, ")"); } else code_err(ast, "There is no '%s' method for channels", call->name); @@ -2972,7 +2983,7 @@ CORD compile(env_t *env, ast_t *ast) case TableType: { auto table = Match(self_value_t, TableType); if (streq(call->name, "get")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type); return CORD_all( "Table$get_optional(", self, ", ", compile_type(table->key_type), ", ", @@ -2980,18 +2991,18 @@ CORD compile(env_t *env, ast_t *ast) "_, ", optional_into_nonnull(table->value_type, "(*_)"), ", ", compile_null(table->value_type), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "has")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type); return CORD_all("Table$has_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "set")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "table"); arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type, .next=new(arg_t, .name="value", .type=table->value_type)); return CORD_all("Table$set_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "bump")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "table"); if (!(table->value_type->tag == IntType || table->value_type->tag == NumType)) code_err(ast, "bump() is only supported for tables with numeric value types, not %T", self_value_t); ast_t *one = table->value_type->tag == IntType @@ -3002,16 +3013,16 @@ CORD compile(env_t *env, ast_t *ast) return CORD_all("Table$bump(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "remove")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "table"); arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type); return CORD_all("Table$remove_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "clear")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + EXPECT_POINTER("a", "table"); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Table$clear(", self, ")"); } else if (streq(call->name, "sorted")) { - CORD self = compile_to_pointer_depth(env, call->self, 0, false); + self = compile_to_pointer_depth(env, call->self, 0, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Table$sorted(", self, ", ", compile_type_info(env, self_value_t), ")"); } else code_err(ast, "There is no '%s' method for tables", call->name); @@ -3025,6 +3036,7 @@ CORD compile(env_t *env, ast_t *ast) return CORD_all(b->code, "(", compile_arguments(env, ast, Match(fn_t, FunctionType)->args, args), ")"); } } +#undef EXPECT_POINTER } case FunctionCall: { auto call = Match(ast, FunctionCall); diff --git a/examples/ini/ini.tm b/examples/ini/ini.tm index 4e5ec77..5952bb0 100644 --- a/examples/ini/ini.tm +++ b/examples/ini/ini.tm @@ -8,7 +8,7 @@ _HELP := " func parse_ini(path:Path -> {Text:{Text:Text}}): text := path:read() or exit("Could not read INI file: $\[31;1]$(path.text_content)$\[]") - sections := {:Text:@{Text:Text}} + sections := @{:Text:@{Text:Text}} current_section := @{:Text:Text} # Line wraps: @@ -26,7 +26,7 @@ func parse_ini(path:Path -> {Text:{Text:Text}}): value := line:replace($/{..}={..}/, "\2"):trim() current_section:set(key, value) - return {k:v[] for k,v in sections} + return {k:v[] for k,v in sections[]} func main(path:Path, key:Text?): keys := (key or ""):split($|/|) diff --git a/examples/log/log.tm b/examples/log/log.tm index f537b85..89557e5 100644 --- a/examples/log/log.tm +++ b/examples/log/log.tm @@ -3,7 +3,7 @@ use timestamp_format := CString("%F %T") -logfiles := {:Path} +logfiles := @{:Path} func _timestamp(->Text): c_str := inline C:CString { @@ -17,22 +17,22 @@ func _timestamp(->Text): func info(text:Text, newline=yes): say("$\[2]⚫ $text$\[]", newline) - for file in logfiles: + for file in logfiles[]: file:append("$(_timestamp()) [info] $text$\n") func debug(text:Text, newline=yes): say("$\[32]🟢 $text$\[]", newline) - for file in logfiles: + for file in logfiles[]: file:append("$(_timestamp()) [debug] $text$\n") func warn(text:Text, newline=yes): say("$\[33;1]🟡 $text$\[]", newline) - for file in logfiles: + for file in logfiles[]: file:append("$(_timestamp()) [warn] $text$\n") func error(text:Text, newline=yes): say("$\[31;1]🔴 $text$\[]", newline) - for file in logfiles: + for file in logfiles[]: file:append("$(_timestamp()) [error] $text$\n") func add_logfile(file:Path): diff --git a/examples/tomodeps/tomodeps.tm b/examples/tomodeps/tomodeps.tm index 1565575..fbe297e 100644 --- a/examples/tomodeps/tomodeps.tm +++ b/examples/tomodeps/tomodeps.tm @@ -14,7 +14,7 @@ func _get_file_dependencies(file:Path -> {Dependency}): !! Could not read file: $file return {:Dependency} - deps := {:Dependency} + deps := @{:Dependency} if lines := file:by_line(): for line in lines: if line:matches($/use {..}.tm/): @@ -23,7 +23,7 @@ func _get_file_dependencies(file:Path -> {Dependency}): else if line:matches($/use {id}/): module_name := line:replace($/use {..}/, "\1") deps:add(Dependency.Module(module_name)) - return deps + return deps[] func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency:{Dependency}}): return if dependencies:has(dep) @@ -34,9 +34,9 @@ func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency:{Dependen _get_file_dependencies(path) is Module(module): dir := (~/.local/share/tomo/installed/$module) - module_deps := {:Dependency} - visited := {:Path} - unvisited := {f:resolved() for f in dir:files() if f:ends_with(".tm")} + module_deps := @{:Dependency} + visited := @{:Path} + unvisited := @{f:resolved() for f in dir:files() if f:ends_with(".tm")} while unvisited.length > 0: file := unvisited.items[-1] unvisited:remove(file) @@ -48,7 +48,7 @@ func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency:{Dependen unvisited:add(f) is Module(m): module_deps:add(file_dep) - module_deps + module_deps[] dependencies:set(dep, dep_deps) diff --git a/examples/wrap/wrap.tm b/examples/wrap/wrap.tm index 1c43470..b6cf140 100644 --- a/examples/wrap/wrap.tm +++ b/examples/wrap/wrap.tm @@ -33,7 +33,7 @@ func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): ... and I can't split it without splitting into chunks smaller than $min_split. ") - lines := [:Text] + lines := @[:Text] line := "" for word in text:split($/{whitespace}/): letters := word:split() @@ -93,10 +93,10 @@ func main(files:[Path], width=80, inplace=no, min_split=3, rewrap=yes, hyphen=UN (/dev/stdout) first := yes - wrapped_paragraphs := [:Text] + wrapped_paragraphs := @[:Text] for paragraph in text:split($/{2+ nl}/): wrapped_paragraphs:insert( wrap(paragraph, width=width, min_split=min_split, hyphen=hyphen) ) - out:write(\n\n:join(wrapped_paragraphs) ++ \n) + out:write(\n\n:join(wrapped_paragraphs[]) ++ \n) diff --git a/test/arrays.tm b/test/arrays.tm index 7f1882a..7fa1ef6 100644 --- a/test/arrays.tm +++ b/test/arrays.tm @@ -84,31 +84,31 @@ func main(): = [30, 20, 10] do: - >> nums := [10, -20, 30] + >> nums := @[10, -20, 30] # Sorted function doesn't mutate original: >> nums:sorted() = [-20, 10, 30] >> nums - = [10, -20, 30] + = @[10, -20, 30] # Sort function does mutate in place: >> nums:sort() >> nums - = [-20, 10, 30] + = @[-20, 10, 30] # Custom sort functions: >> nums:sort(func(x,y:&Int): x:abs() <> y:abs()) >> nums - = [10, -20, 30] + = @[10, -20, 30] >> nums:sort(func(x,y:&Int): y[] <> x[]) >> nums - = [30, 10, -20] + = @[30, 10, -20] >> ["A", "B", "C"]:sample(10, [1.0, 0.5, 0.0]) do: - >> heap := [random:int(1, 50) for _ in 10] + >> heap := @[random:int(1, 50) for _ in 10] >> heap:heapify() >> heap - sorted := [:Int] + sorted := @[:Int] while heap.length > 0: sorted:insert(heap:heap_pop()) >> sorted == sorted:sorted() @@ -116,7 +116,7 @@ func main(): for _ in 10: heap:heap_push(random:int(1, 50)) >> heap - sorted = [:Int] + sorted = @[:Int] while heap.length > 0: sorted:insert(heap:heap_pop()) >> sorted == sorted:sorted() @@ -155,12 +155,12 @@ func main(): say("$(x)$(y)") do: - >> nums := [-7, -4, -1, 2, 5] + >> nums := @[-7, -4, -1, 2, 5] >> nums:sort() - >> [nums:binary_search(i) for i in nums] + >> [nums:binary_search(i) for i in nums[]] = [1, 2, 3, 4, 5] >> nums:sort(func(a,b:&Int): a:abs() <> b:abs()) - >> [nums:binary_search(i, func(a,b:&Int): a:abs() <> b:abs()) for i in nums] + >> [nums:binary_search(i, func(a,b:&Int): a:abs() <> b:abs()) for i in nums[]] = [1, 2, 3, 4, 5] >> ["a", "b", "c"]:find("b") diff --git a/test/iterators.tm b/test/iterators.tm index d6bcfa1..2adcab4 100644 --- a/test/iterators.tm +++ b/test/iterators.tm @@ -25,10 +25,10 @@ func main(): = ["AB", "BC", "CD"] do: - result := [:Text] + result := @[:Text] for foo in pairwise(values): result:insert("$(foo.x)$(foo.y)") - >> result + >> result[] = ["AB", "BC", "CD"] >> [i for i in range(5, 10)] diff --git a/test/sets.tm b/test/sets.tm index a6a9d57..7b285d6 100644 --- a/test/sets.tm +++ b/test/sets.tm @@ -1,7 +1,7 @@ func main(): - >> t1 := {10, 20, 30, 10} - = {10, 20, 30} + >> t1 := @{10, 20, 30, 10} + = @{10, 20, 30} >> t1:has(10) = yes >> t1:has(-999) @@ -30,10 +30,10 @@ func main(): >> t1:add_all(t2) >> t1 - = {10, 20, 30, 40} + = @{10, 20, 30, 40} >> t1:remove_all(t2) >> t1 - = {10, 20} + = @{10, 20} >> {3, i for i in 5} = {3, 1, 2, 4, 5} diff --git a/test/tables.tm b/test/tables.tm index 3dd27b0..650e4e1 100644 --- a/test/tables.tm +++ b/test/tables.tm @@ -57,10 +57,10 @@ func main(): >> {x:10*x for x in y if x > 1 for y in [3, 4, 5] if y < 5} = {2:20, 3:30, 4:40} - >> t3 := {1:10, 2:20, 3:30} + >> t3 := @{1:10, 2:20, 3:30} >> t3:remove(3) >> t3 - = {1:10, 2:20} + = @{1:10, 2:20} do: >> plain := {1:10, 2:20, 3:30}