aboutsummaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-18 20:28:16 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-18 20:28:39 -0400
commitd804b09b02b9c4a6ea6b16ae85524a704796cbc1 (patch)
tree3379d64b028a80825a892c87176b6bb6d6cc3484 /api
parentc338c3f08c6a13242e975dd344bad63a3cec9eee (diff)
Added a .length field to arrays/sets/tables, added a .max_size field to
channels, and updated the API
Diffstat (limited to 'api')
-rw-r--r--api/arrays.md9
-rw-r--r--api/channels.md6
-rw-r--r--api/pointers.md104
-rw-r--r--api/sets.md9
-rw-r--r--api/tables.md12
5 files changed, 137 insertions, 3 deletions
diff --git a/api/arrays.md b/api/arrays.md
index 34da6e8f..0dede5dd 100644
--- a/api/arrays.md
+++ b/api/arrays.md
@@ -42,6 +42,15 @@ Comprehensions can be combined with regular items or other comprehensions:
= [-1, 30, 40, 50, 60, 70, 80, 1, 2, 3]
```
+## Length
+
+Array length can be accessed by the `.length` field:
+
+```tomo
+>> [10, 20, 30].length
+= 3
+```
+
## Indexing
Array values are accessed using square bracket indexing. Since arrays are
diff --git a/api/channels.md b/api/channels.md
index 4b8d416a..48116dc5 100644
--- a/api/channels.md
+++ b/api/channels.md
@@ -5,13 +5,13 @@ although they can also be used as a general-purpose queue.
## Syntax
-The syntax to create a channel is `|T|`, where `T` is the type that will be
+The syntax to create a channel is `|:T|`, where `T` is the type that will be
passed through the channel. You can also specify a maximum size for the
channel, which will cause pushing to block until the recipient has popped from
the channel if the maximum size is reached.
```tomo
-channel := |Int|
+channel := |:Int|
channel:push(10)
channel:push(20)
>> channel:pop()
@@ -19,7 +19,7 @@ channel:push(20)
>> channel:pop()
= 20
-small_channel := |Int; max_size=5|
+small_channel := |:Int; max_size=5|
```
## Channel Methods
diff --git a/api/pointers.md b/api/pointers.md
new file mode 100644
index 00000000..67043084
--- /dev/null
+++ b/api/pointers.md
@@ -0,0 +1,104 @@
+# Pointers
+
+Pointers are numeric values that represent a location in memory where some type
+of data lives. Pointers are created using either the `@` prefix operator to
+**a**llocate heap memory or the `&` prefix operator to get the address of a
+variable. Stack pointers (`&`) are more limited than heap pointers (`@`) and
+cannot be stored inside an array, set, table, struct, enum, or channel.
+However, stack pointers are useful for methods that mutate local variables and
+don't need to save the pointer anywhere.
+
+Pointers are the way in Tomo that you can create mutable data. All
+datastructures are by default, immutable, but using pointers, you can create
+a region of memory where different immutable values can be held, which change
+over time.
+
+```tomo
+func no_mutation_possible(nums:[Int]):
+ nums[1] = 10 // Type error!
+
+func do_mutation(nums:@[Int]):
+ nums[1] = 10 // okay
+
+...
+
+my_nums := @[0, 1, 2]
+do_mutation(my_nums)
+```
+
+In general, heap pointers can be used as stack pointers if necessary, since
+the usage of stack pointers is restricted, but heap pointers don't have the
+same restrictions, so it's good practice to define functions that don't need
+to store pointers to use stack references. This lets you pass references to
+local variables or pointers to heap data depending on your needs.
+
+```tomo
+func swap_first_two(data:&[Int]):
+ data[1], data[2] = data[2], data[1]
+
+...
+
+heap_nums := @[10, 20, 30]
+swap_first_two(heap_nums)
+
+local_nums := [10, 20, 30]
+swap_first_two(&local_nums)
+```
+
+## Dereferencing
+
+Pointers can be dereferenced to access the value that's stored at the pointer's
+memory location using the `[]` postfix operator (with no value inside).
+
+```tomo
+nums := @[10, 20]
+>> nums[]
+= [10, 20]
+```
+
+## Equality and Comparisons
+
+When comparing two pointers, the comparison operates on the _memory address_,
+not the contents of the memory. This is "referential" equality, not
+"structural" equality. The easy way to think about it is that two pointers are
+equal to each other only if doing a mutation to one of them is the same as
+doing a mutation to the other.
+
+```tomo
+x := @[10, 20, 30]
+y := @[10, 20, 30]
+>> x == y
+= no
+
+z := x
+>> x == z
+= yes
+```
+
+Pointers are ordered by memory address, which is somewhat arbitrary, but
+consistent.
+
+## Null Safety
+
+Tomo pointers are, by default, guaranteed to be non-null. If you write a
+function that takes either a `&T` or `@T`, the value that will be given
+is always non-null. However, optional pointers can be used by adding a
+question mark to the type: `&T?` or `@T?`. A null value can be created
+using the syntax `!@T` or `!&T`. You can also append a question mark to
+a pointer value so the type checker knows it's supposed to be optional:
+
+```
+optional := @[10, 20]?
+optional := &foo?
+```
+
+The compiler will not allow you to dereference an optionally null pointer
+without explicitly checking for null. To do so, use pattern matching like
+this:
+
+```
+when optional is @ptr:
+ ok := ptr[]
+else:
+ say("Oh, it was null")
+```
diff --git a/api/sets.md b/api/sets.md
index 6dcc9ca9..850d1443 100644
--- a/api/sets.md
+++ b/api/sets.md
@@ -48,6 +48,15 @@ set := {10, 20, 30}
= [10, 20, 30]
```
+## Length
+
+Set length can be accessed by the `.length` field:
+
+```tomo
+>> {10, 20, 30}.length
+= 3
+```
+
## Iteration
You can iterate over the items in a table like this:
diff --git a/api/tables.md b/api/tables.md
index f132d70a..f4753efb 100644
--- a/api/tables.md
+++ b/api/tables.md
@@ -50,6 +50,18 @@ t2 := {"B": 20; fallback=t}
= 10
```
+The fallback is available by the `.fallback` field, which returns an optional
+readonly pointer to the fallback table (if present) or null if it is not.
+
+## Length
+
+Table length can be accessed by the `.length` field:
+
+```tomo
+>> {"A":10, "B":20}.length
+= 2
+```
+
## Accessing Keys and Values
The keys and values of a table can be efficiently accessed as arrays using a