aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-04-06 16:36:40 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-04-06 16:36:40 -0400
commit6d12f1dce744146dfa9072d574c540e1d49bb31b (patch)
tree4ffc721508ba25a6f125147873446365820dd0ff
parent2640c138b305b558bccf1d36f3f0d54fab96e84c (diff)
parent52e50e58c6674560056a4dcb787099d739284b02 (diff)
Merge branch 'main' into no-colons
-rw-r--r--docs/sets.md89
-rw-r--r--examples/learnxiny.tm11
-rw-r--r--examples/log/log.tm2
-rw-r--r--examples/tomodeps/tomodeps.tm30
-rw-r--r--src/parse.c13
-rw-r--r--src/stdlib/tables.c11
-rw-r--r--src/types.c4
-rw-r--r--test/enums.tm2
-rw-r--r--test/optionals.tm4
-rw-r--r--test/serialization.tm4
-rw-r--r--test/sets.tm31
-rw-r--r--test/structs.tm4
-rw-r--r--test/tables.tm4
13 files changed, 102 insertions, 107 deletions
diff --git a/docs/sets.md b/docs/sets.md
index 62351ed5..88e47e98 100644
--- a/docs/sets.md
+++ b/docs/sets.md
@@ -4,37 +4,36 @@ Sets represent an unordered collection of unique elements. These are
implemented using hash tables.
```tomo
-a := {10, 20, 30}
-b := {20, 30}
+a := |10, 20, 30|
+b := |20, 30|
>> a.overlap(b)
-= {20}
+= |20|
```
## Syntax
-Sets are written using `{...}` curly braces with comma-separated items:
+Sets are written using `|...|` vertical pipes with comma-separated items:
```tomo
-nums := {10, 20, 30}
+nums := |10, 20, 30|
```
-Empty sets must specify the set type explicitly and use `{/}` for an empty set
-(because `{}` is an empty table).
+Empty sets must specify the set type explicitly:
```tomo
-empty : {Int} = {/}
+empty : |Int| = ||
```
-For type annotations, a set that holds items with type `T` is written as `{T}`.
+For type annotations, a set that holds items with type `T` is written as `|T|`.
### Comprehensions
Similar to arrays, sets can use comprehensions:
```tomo
-set := {10*i for i in 10}
-set2 := {10*i for i in 10 if i mod 2 == 0}
-set3 := {-10, 10*i for i in 10}
+set := |10*i for i in 10|
+set2 := |10*i for i in 10 if i mod 2 == 0|
+set3 := |-10, 10*i for i in 10|
```
## Accessing Items
@@ -44,7 +43,7 @@ Sets internally store their items in an array, which you can access with the
view:
```tomo
-set := {10, 20, 30}
+set := |10, 20, 30|
>> set.items
= [10, 20, 30]
```
@@ -54,7 +53,7 @@ set := {10, 20, 30}
Set length can be accessed by the `.length` field:
```tomo
->> {10, 20, 30}.length
+>> |10, 20, 30|.length
= 3
```
@@ -76,23 +75,23 @@ iterating over any of the new values.
## Set Methods
-- [`func add(set:{T}, item: T -> Void)`](#add)
-- [`func add_all(set:@{T}, items: [T] -> Void)`](#add_all)
-- [`func clear(set:@{T} -> Void)`](#clear)
-- [`func has(set:{T}, item:T -> Bool)`](#has)
-- [`func (set: {T}, other: {T}, strict: Bool = no -> Bool)`](#is_subset_of)
-- [`func is_superset_of(set:{T}, other: {T}, strict: Bool = no -> Bool)`](#is_superset_of)
-- [`func overlap(set:{T}, other: {T} -> {T})`](#overlap)
-- [`func remove(set:@{T}, item: T -> Void)`](#remove)
-- [`func remove_all(set:@{T}, items: [T] -> Void)`](#remove_all)
-- [`func with(set:{T}, other: {T} -> {T})`](#with)
-- [`func without(set:{T}, other: {T} -> {T})`](#without)
+- [`func add(set:|T|, item: T -> Void)`](#add)
+- [`func add_all(set:@|T|, items: [T] -> Void)`](#add_all)
+- [`func clear(set:@|T| -> Void)`](#clear)
+- [`func has(set:|T|, item:T -> Bool)`](#has)
+- [`func (set: |T|, other: |T|, strict: Bool = no -> Bool)`](#is_subset_of)
+- [`func is_superset_of(set:|T|, other: |T|, strict: Bool = no -> Bool)`](#is_superset_of)
+- [`func overlap(set:|T|, other: |T| -> |T|)`](#overlap)
+- [`func remove(set:@|T|, item: T -> Void)`](#remove)
+- [`func remove_all(set:@|T|, items: [T] -> Void)`](#remove_all)
+- [`func with(set:|T|, other: |T| -> |T|)`](#with)
+- [`func without(set:|T|, other: |T| -> |T|)`](#without)
### `add`
Adds an item to the set.
```tomo
-func add(set:{T}, item: T -> Void)
+func add(set:|T|, item: T -> Void)
```
- `set`: The mutable reference to the set.
@@ -112,7 +111,7 @@ Nothing.
Adds multiple items to the set.
```tomo
-func add_all(set:@{T}, items: [T] -> Void)
+func add_all(set:@|T|, items: [T] -> Void)
```
- `set`: The mutable reference to the set.
@@ -132,7 +131,7 @@ Nothing.
Removes all items from the set.
```tomo
-func clear(set:@{T} -> Void)
+func clear(set:@|T| -> Void)
```
- `set`: The mutable reference to the set.
@@ -151,7 +150,7 @@ Nothing.
Checks if the set contains a specified item.
```tomo
-func has(set:{T}, item:T -> Bool)
+func has(set:|T|, item:T -> Bool)
```
- `set`: The set to check.
@@ -162,7 +161,7 @@ func has(set:{T}, item:T -> Bool)
**Example:**
```tomo
->> {10, 20}.has(20)
+>> |10, 20|.has(20)
= yes
```
@@ -172,7 +171,7 @@ func has(set:{T}, item:T -> Bool)
Checks if the set is a subset of another set.
```tomo
-func (set: {T}, other: {T}, strict: Bool = no -> Bool)
+func (set: |T|, other: |T|, strict: Bool = no -> Bool)
```
- `set`: The set to check.
@@ -184,7 +183,7 @@ func (set: {T}, other: {T}, strict: Bool = no -> Bool)
**Example:**
```tomo
->> {1, 2}.is_subset_of({1, 2, 3})
+>> |1, 2|.is_subset_of(|1, 2, 3|)
= yes
```
@@ -194,7 +193,7 @@ func (set: {T}, other: {T}, strict: Bool = no -> Bool)
Checks if the set is a superset of another set.
```tomo
-func is_superset_of(set:{T}, other: {T}, strict: Bool = no -> Bool)
+func is_superset_of(set:|T|, other: |T|, strict: Bool = no -> Bool)
```
- `set`: The set to check.
@@ -206,14 +205,14 @@ func is_superset_of(set:{T}, other: {T}, strict: Bool = no -> Bool)
**Example:**
```tomo
->> {1, 2, 3}.is_superset_of({1, 2})
+>> |1, 2, 3|.is_superset_of(|1, 2|)
= yes
```
### `overlap`
Creates a new set with items that are in both the original set and another set.
```tomo
-func overlap(set:{T}, other: {T} -> {T})
+func overlap(set:|T|, other: |T| -> |T|)
```
- `set`: The original set.
@@ -224,8 +223,8 @@ A new set containing only items present in both sets.
**Example:**
```tomo
->> {1, 2}.overlap({2, 3})
-= {2}
+>> |1, 2|.overlap(|2, 3|)
+= |2|
```
---
@@ -234,7 +233,7 @@ A new set containing only items present in both sets.
Removes an item from the set.
```tomo
-func remove(set:@{T}, item: T -> Void)
+func remove(set:@|T|, item: T -> Void)
```
- `set`: The mutable reference to the set.
@@ -254,7 +253,7 @@ Nothing.
Removes multiple items from the set.
```tomo
-func remove_all(set:@{T}, items: [T] -> Void)
+func remove_all(set:@|T|, items: [T] -> Void)
```
- `set`: The mutable reference to the set.
@@ -274,7 +273,7 @@ Nothing.
Creates a new set that is the union of the original set and another set.
```tomo
-func with(set:{T}, other: {T} -> {T})
+func with(set:|T|, other: |T| -> |T|)
```
- `set`: The original set.
@@ -285,8 +284,8 @@ A new set containing all items from both sets.
**Example:**
```tomo
->> {1, 2}.with({2, 3})
-= {1, 2, 3}
+>> |1, 2|.with(|2, 3|)
+= |1, 2, 3|
```
---
@@ -295,7 +294,7 @@ A new set containing all items from both sets.
Creates a new set with items from the original set but without items from another set.
```tomo
-func without(set:{T}, other: {T} -> {T})
+func without(set:|T|, other: |T| -> |T|)
```
- `set`: The original set.
@@ -306,6 +305,6 @@ A new set containing items from the original set excluding those in the other se
**Example:**
```tomo
->> {1, 2}.without({2, 3})
-= {1}
+>> |1, 2|.without(|2, 3|)
+= |1|
```
diff --git a/examples/learnxiny.tm b/examples/learnxiny.tm
index d05c92f2..5bf8e69f 100644
--- a/examples/learnxiny.tm
+++ b/examples/learnxiny.tm
@@ -159,20 +159,20 @@ func main()
# Sets are similar to tables, but they represent an unordered collection of
# unique values:
- set := {10, 20, 30}
+ set := |10, 20, 30|
>> set.has(20)
= yes
>> set.has(999)
= no
# You can do some operations on sets:
- other_set := {30, 40, 50}
+ other_set := |30, 40, 50|
>> set.with(other_set)
- = {10, 20, 30, 40, 50}
+ = |10, 20, 30, 40, 50|
>> set.without(other_set)
- = {10, 20}
+ = |10, 20|
>> set.overlap(other_set)
- = {30}
+ = |30|
# So far, the datastructures that have been discussed are all *immutable*,
# meaning you can't add, remove, or change their contents. If you want to
@@ -241,6 +241,7 @@ func takes_many_types(
text_aka_string:Text,
array_of_ints:[Int],
table_of_text_to_bools:{Text=Bool},
+ set_of_ints:|Int|,
pointer_to_mutable_array_of_ints:@[Int],
optional_int:Int?,
function_from_int_to_text:func(x:Int -> Text),
diff --git a/examples/log/log.tm b/examples/log/log.tm
index c6c45a21..3763303f 100644
--- a/examples/log/log.tm
+++ b/examples/log/log.tm
@@ -3,7 +3,7 @@ use <stdio.h>
timestamp_format := CString("%F %T")
-logfiles : @{Path} = @{/}
+logfiles : @|Path| = @||
func _timestamp(->Text)
c_str := inline C:CString {
diff --git a/examples/tomodeps/tomodeps.tm b/examples/tomodeps/tomodeps.tm
index 4ccbec2c..1aafa6bd 100644
--- a/examples/tomodeps/tomodeps.tm
+++ b/examples/tomodeps/tomodeps.tm
@@ -11,12 +11,12 @@ _HELP := "
enum Dependency(File(path:Path), Module(name:Text))
-func _get_file_dependencies(file:Path -> {Dependency})
+func _get_file_dependencies(file:Path -> |Dependency|)
if not file.is_file()
say("Could not read file: $file")
- return {/}
+ return ||
- deps : @{Dependency} = @{/}
+ deps : @|Dependency| = @||
if lines := file.by_line()
for line in lines
if line.matches_pattern($Pat/use {..}.tm/)
@@ -27,18 +27,18 @@ func _get_file_dependencies(file:Path -> {Dependency})
deps.add(Dependency.Module(module_name))
return deps[]
-func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency={Dependency}})
+func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency=|Dependency|})
return if dependencies.has(dep)
- dependencies[dep] = {/} # Placeholder
+ dependencies[dep] = || # Placeholder
dep_deps := when dep is File(path)
_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.extension() == ".tm"}
+ module_deps : @|Dependency| = @||
+ visited : @|Path| = @||
+ unvisited := @|f.resolved() for f in dir.files() if f.extension() == ".tm"|
while unvisited.length > 0
file := unvisited.items[-1]
unvisited.remove(file)
@@ -57,8 +57,8 @@ func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency={Dependen
for dep2 in dep_deps
_build_dependency_graph(dep2, dependencies)
-func get_dependency_graph(dep:Dependency -> {Dependency={Dependency}})
- graph : @{Dependency={Dependency}} = @{}
+func get_dependency_graph(dep:Dependency -> {Dependency=|Dependency|})
+ graph : @{Dependency=|Dependency|} = @{}
_build_dependency_graph(dep, graph)
return graph
@@ -72,7 +72,7 @@ func _printable_name(dep:Dependency -> Text)
else
return "$(\x1b)[31;1m$(f) (not found)$(\x1b)[m"
-func _draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}}, already_printed:@{Dependency}, prefix="", is_last=yes)
+func _draw_tree(dep:Dependency, dependencies:{Dependency=|Dependency|}, already_printed:@|Dependency|, prefix="", is_last=yes)
if already_printed.has(dep)
say(prefix ++ (if is_last "└── " else "├── ") ++ _printable_name(dep) ++ " $\x1b[2m(recursive)$\x1b[m")
return
@@ -82,16 +82,16 @@ func _draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}}, already_
child_prefix := prefix ++ (if is_last " " else "│ ")
- children := dependencies[dep] or {/}
+ children := dependencies[dep] or ||
for i,child in children.items
is_child_last := (i == children.length)
_draw_tree(child, dependencies, already_printed, child_prefix, is_child_last)
-func draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}})
- printed : @{Dependency} = @{/}
+func draw_tree(dep:Dependency, dependencies:{Dependency=|Dependency|})
+ printed : @|Dependency| = @||
say(_printable_name(dep))
printed.add(dep)
- deps := dependencies[dep] or {/}
+ deps := dependencies[dep] or ||
for i,child in deps.items
is_child_last := (i == deps.length)
_draw_tree(child, dependencies, already_printed=printed, is_last=is_child_last)
diff --git a/src/parse.c b/src/parse.c
index ca6a6af2..d9f06371 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -520,14 +520,13 @@ type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) {
type_ast_t *parse_set_type(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
- if (!match(&pos, "{")) return NULL;
+ if (!match(&pos, "|")) return NULL;
whitespace(&pos);
type_ast_t *item_type = parse_type(ctx, pos);
if (!item_type) return NULL;
pos = item_type->end;
whitespace(&pos);
- if (match(&pos, ",")) return NULL;
- expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this set type");
+ expect_closing(ctx, &pos, "|", "I wasn't able to parse the rest of this set type");
return NewTypeAST(ctx->file, start, pos, SetTypeAST, .item=item_type);
}
@@ -706,7 +705,6 @@ PARSER(parse_array) {
PARSER(parse_table) {
const char *start = pos;
- if (match(&pos, "{/}")) return NULL;
if (!match(&pos, "{")) return NULL;
whitespace(&pos);
@@ -768,10 +766,10 @@ PARSER(parse_table) {
PARSER(parse_set) {
const char *start = pos;
- if (match(&pos, "{/}"))
+ if (match(&pos, "||"))
return NewAST(ctx->file, start, pos, Set);
- if (!match(&pos, "{")) return NULL;
+ if (!match(&pos, "|")) return NULL;
whitespace(&pos);
@@ -780,7 +778,6 @@ PARSER(parse_set) {
ast_t *item = optional(ctx, &pos, parse_extended_expr);
if (!item) break;
whitespace(&pos);
- if (match(&pos, "=")) return NULL;
ast_t *suffixed = parse_comprehension_suffix(ctx, item);
while (suffixed) {
item = suffixed;
@@ -795,7 +792,7 @@ PARSER(parse_set) {
REVERSE_LIST(items);
whitespace(&pos);
- expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this set");
+ expect_closing(ctx, &pos, "|", "I wasn't able to parse the rest of this set");
return NewAST(ctx->file, start, pos, Set, .items=items);
}
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index 71b9c7f4..d59bc113 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -588,13 +588,13 @@ public Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *ty
Text("}"));
else
return Text$concat(
- Text("{"),
+ Text("|"),
generic_as_text(NULL, false, table.key),
- Text("}"));
+ Text("|"));
}
int64_t val_off = (int64_t)value_offset(type);
- Text_t text = Text("{");
+ Text_t text = table.value == &Void$info ? Text("|") : Text("{");
for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
if (i > 0)
text = Text$concat(text, Text(", "));
@@ -604,14 +604,11 @@ public Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *ty
text = Text$concat(text, Text("="), generic_as_text(entry + val_off, colorize, table.value));
}
- if (table.value == &Void$info)
- text = Text$concat(text, Text("/"));
-
if (t->fallback) {
text = Text$concat(text, Text("; fallback="), Table$as_text(t->fallback, colorize, type));
}
- text = Text$concat(text, Text("}"));
+ text = Text$concat(text, table.value == &Void$info ? Text("|") : Text("}"));
return text;
}
diff --git a/src/types.c b/src/types.c
index 29963f76..0b69a8c4 100644
--- a/src/types.c
+++ b/src/types.c
@@ -370,9 +370,7 @@ PUREFUNC bool can_promote(type_t *actual, type_t *needed)
if (actual->tag == ArrayType && needed->tag == ArrayType && Match(actual, ArrayType)->item_type == NULL)
return true; // [] -> [T]
if (actual->tag == SetType && needed->tag == SetType && Match(actual, SetType)->item_type == NULL)
- return true; // {/} -> {T}
- if (actual->tag == TableType && needed->tag == SetType && Match(actual, TableType)->key_type == NULL && Match(actual, TableType)->value_type == NULL)
- return true; // {} -> {T}
+ return true; // || -> |T|
if (actual->tag == TableType && needed->tag == TableType && Match(actual, TableType)->key_type == NULL && Match(actual, TableType)->value_type == NULL)
return true; // {} -> {K=V}
diff --git a/test/enums.tm b/test/enums.tm
index 3b3b31ea..901298a8 100644
--- a/test/enums.tm
+++ b/test/enums.tm
@@ -42,7 +42,7 @@ func main()
= yes
>> x := Foo.One(123)
- >> t := {x}
+ >> t := |x|
>> t.has(x)
= yes
>> t.has(Foo.Zero)
diff --git a/test/optionals.tm b/test/optionals.tm
index 1ec3c415..5344848d 100644
--- a/test/optionals.tm
+++ b/test/optionals.tm
@@ -245,8 +245,8 @@ func main()
= no
>> (5? == 5?)
= yes
- >> nones : {Int?} = {none, none}
- >> also_nones : {Int?} = {none}
+ >> nones : |Int?| = |none, none|
+ >> also_nones : |Int?| = |none|
>> nones == also_nones
>> [5?, none, none, 6?].sorted()
= [none, none, 5, 6]
diff --git a/test/serialization.tm b/test/serialization.tm
index 457442e5..258282c1 100644
--- a/test/serialization.tm
+++ b/test/serialization.tm
@@ -76,9 +76,9 @@ func main()
= yes
do
- >> obj := {10, 20, 30}
+ >> obj := |10, 20, 30|
>> bytes := obj.serialized()
- >> deserialize(bytes -> {Int}) == obj
+ >> deserialize(bytes -> |Int|) == obj
= yes
do
diff --git a/test/sets.tm b/test/sets.tm
index 1c395fba..fe2e91f8 100644
--- a/test/sets.tm
+++ b/test/sets.tm
@@ -1,39 +1,42 @@
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)
= no
- >> t2 := {30, 40}
+ >> t2 := |30, 40|
>> t1.with(t2)
- >> {10, 20, 30, 40}
+ >> |10, 20, 30, 40|
>> t1.without(t2)
- >> {10, 20}
+ >> |10, 20|
>> t1.overlap(t2)
- >> {30}
+ >> |30|
- >> {1,2}.is_subset_of({2,3})
+ >> |1,2|.is_subset_of(|2,3|)
= no
- >> {1,2}.is_subset_of({1,2,3})
+ >> |1,2|.is_subset_of(|1,2,3|)
= yes
- >> {1,2}.is_subset_of({1,2})
+ >> |1,2|.is_subset_of(|1,2|)
= yes
- >> {1,2}.is_subset_of({1,2}, strict=yes)
+ >> |1,2|.is_subset_of(|1,2|, strict=yes)
= no
>> 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}
+ >> |3, i for i in 5|
+ = |3, 1, 2, 4, 5|
+
+ >> empty : |Int| = ||
+ = ||
diff --git a/test/structs.tm b/test/structs.tm
index f1ae49d0..c340f1c9 100644
--- a/test/structs.tm
+++ b/test/structs.tm
@@ -32,7 +32,7 @@ func test_metamethods()
>> x < Pair(11, 20)
= yes
- >> set := {x}
+ >> set := |x|
>> set.has(x)
= yes
>> set.has(y)
@@ -49,7 +49,7 @@ func test_mixed()
= no
>> x < Mixed(11, "Hello")
= yes
- >> set := {x}
+ >> set := |x|
>> set.has(x)
= yes
>> set.has(y)
diff --git a/test/tables.tm b/test/tables.tm
index 67299142..9419d875 100644
--- a/test/tables.tm
+++ b/test/tables.tm
@@ -99,8 +99,8 @@ func main()
>> ints : [{Int=Int}] = [{}, {0=0}, {99=99}, {1=1, 2=2, 3=3}, {1=1, 99=99, 3=3}, {1=1, 2=-99, 3=3}, {1=1, 99=-99, 3=4}].sorted()
= [{}, {0=0}, {1=1, 2=-99, 3=3}, {1=1, 2=2, 3=3}, {1=1, 99=99, 3=3}, {1=1, 99=-99, 3=4}, {99=99}]
- >> other_ints : [{Int}] = [{/}, {1}, {2}, {99}, {0, 3}, {1, 2}, {99}].sorted()
- = [{/}, {0, 3}, {1}, {1, 2}, {2}, {99}, {99}]
+ >> other_ints : [|Int|] = [||, |1|, |2|, |99|, |0, 3|, |1, 2|, |99|].sorted()
+ = [||, |0, 3|, |1|, |1, 2|, |2|, |99|, |99|]
do
# Default values: