Update syntax in docs

This commit is contained in:
Bruce Hill 2025-04-06 23:37:05 -04:00
parent 4a3db447ce
commit 1a196aa8f7
19 changed files with 100 additions and 100 deletions

View File

@ -5,14 +5,14 @@ language that cross-compiles to C. Tomo is designed to anticipate and influence
the language design decisions of the future.
```
func greeting(name:Text, add_exclamation:Bool -> Text):
func greeting(name:Text, add_exclamation:Bool -> Text)
message := "hello $name"
message = " ".join([w.title() for w in message.split_any(" ")])
if add_exclamation:
if add_exclamation
message ++= "!!!"
return message
func main(name:Text, shout=no):
func main(name:Text, shout=no)
to_say := greeting(name, add_exclamation=shout)
say(to_say)
```

View File

@ -5,10 +5,10 @@ Here's a simple example:
```tomo
# greet.tm
func main(name:Text, be_excited=no):
func main(name:Text, be_excited=no)
if be_excited
say("Hello $name!!!")
else:
else
say("Hi $name.")
```
@ -85,7 +85,7 @@ Parsing is case-insensitive:
```
# foo.tm
enum Foo(One, Two, Three)
func main(foo:Foo):
func main(foo:Foo)
>> foo
# Signature:
@ -104,7 +104,7 @@ List-of-text arguments can be passed like this:
```tomo
# many-texts.tm
func main(args:[Text]):
func main(args:[Text])
>> args
```

View File

@ -15,14 +15,14 @@ c := VariousThings.Nothing
## Pattern Matching
The values inside an enum can be accessed with pattern matching:
The values inside an enum can be accessed with pattern matching
```tomo
when x is AnInteger(i):
when x is AnInteger(i)
say("It was $i")
is TwoWords(x, y):
is TwoWords(x, y)
say("It was $x and $y")
is Nothing:
is Nothing
say("It was nothing")
```
@ -54,10 +54,10 @@ from a function with an explicit return type:
enum ArgumentType(AnInt(x:Int), SomeText(text:Text))
enum ReturnType(Nothing, AnInt(x:Int))
func increment(arg:ArgumentType -> ReturnType):
when arg is AnInt(x):
func increment(arg:ArgumentType -> ReturnType)
when arg is AnInt(x)
return AnInt(x + 1)
is SomeText:
is SomeText
return Nothing
...
@ -78,9 +78,9 @@ known.
Enums can also define their own methods and variables inside their namespace:
```tomo
enum VariousThings(AnInteger(i:Int), TwoWords(word1, word2:Text), Nothing):
enum VariousThings(AnInteger(i:Int), TwoWords(word1, word2:Text), Nothing)
meaningful_thing := AnInteger(42)
func doop(v:VariousThings):
func doop(v:VariousThings)
say("$v")
```

View File

@ -3,7 +3,7 @@
In Tomo, you can define functions with the `func` keyword:
```tomo
func add(x:Int, y:Int -> Int):
func add(x:Int, y:Int -> Int)
return x + y
```
@ -19,7 +19,7 @@ Instead of giving a type, you can provide a default argument and the type
checker will infer the type of the argument from that value:
```tomo
func increment(x:Int, amount=1 -> Int):
func increment(x:Int, amount=1 -> Int)
return x + amount
```
@ -47,7 +47,7 @@ and are bound to arguments first, followed by binding positional arguments to
any unbound arguments, in order:
```tomo
func foo(x:Int, y:Text, z:Num):
func foo(x:Int, y:Text, z:Num)
return "x=$x y=$y z=$z"
>> foo(x=1, y="hi", z=2.5)
@ -68,7 +68,7 @@ Tomo supports automatic function caching using the `cached` or `cache_size=N`
attributes on a function definition:
```tomo
func add(x, y:Int -> Int; cached):
func add(x, y:Int -> Int; cached)
return x + y
```
@ -78,15 +78,15 @@ return value for those arguments. The above example is functionally similar to
the following code:
```tomo
func _add(x, y:Int -> Int):
func _add(x, y:Int -> Int)
return x + y
struct add_args(x,y:Int)
add_cache : @{add_args=Int} = @{}
func add(x, y:Int -> Int):
func add(x, y:Int -> Int)
args := add_args(x, y)
if cached := add_cache[args]:
if cached := add_cache[args]
return cached
ret := _add(x, y)
add_cache[args] = ret
@ -98,7 +98,7 @@ evicted if the cache has reached the maximum size and needs to insert a new
entry:
```tomo
func doop(x:Int, y:Text, z:[Int]; cache_size=100 -> Text):
func doop(x:Int, y:Text, z:[Int]; cache_size=100 -> Text)
return "x=$x y=$y z=$z"
```
@ -108,7 +108,7 @@ Functions can also be given an `inline` attribute, which encourages the
compiler to inline the function when possible:
```tomo
func add(x, y:Int -> Int; inline):
func add(x, y:Int -> Int; inline)
return x + y
```
@ -128,8 +128,8 @@ The normal form of a lambda is to give a return expression after the colon,
but you can also use a block that includes statements:
```tomo
fn := func(x,y:Int):
if x == 0:
fn := func(x,y:Int)
if x == 0
return y
return x + y
```
@ -151,8 +151,8 @@ values. **Captured values are copied to a new location at the moment the lambda
is created and will not reflect changes to local variables.**
```tomo
func create_adder(n:Int -> func(i:Int -> Int)):
adder := func(i:Int):
func create_adder(n:Int -> func(i:Int -> Int))
adder := func(i:Int)
return n + i
n = -1 // This does not affect the adder

View File

@ -362,7 +362,7 @@ An iterator function that counts onward from the starting integer.
**Example:**
```tomo
nums : &[Int] = &[]
for i in (5).onward():
for i in (5).onward()
nums.insert(i)
stop if i == 10
>> nums[]

View File

@ -24,7 +24,7 @@ successively gets one line from a file at a time until the file is exhausted:
>> iter()
= none : Text?
for line in (./test.txt).each_line():
for line in (./test.txt).each_line()
pass
```
@ -32,13 +32,13 @@ You can write your own iterator methods this way. For example, this iterator
iterates over prime numbers up to a given limit:
```tomo
func primes_up_to(limit:Int):
func primes_up_to(limit:Int)
n := 2
return func():
if n > limit:
return func()
if n > limit
return !Int
while not n.is_prime():
while not n.is_prime()
n += 1
n += 1

View File

@ -9,8 +9,8 @@ values and give type checking errors if you attempt to use one type of string
where a different type of string is needed.
```tomo
lang HTML:
convert(t:Text -> HTML):
lang HTML
convert(t:Text -> HTML)
t = t.translate({
"&" = "&",
"<" = "&lt;",
@ -20,7 +20,7 @@ lang HTML:
})
return HTML.from_text(t)
func paragraph(content:HTML -> HTML):
func paragraph(content:HTML -> HTML)
return $HTML"<p>$content</p>"
```
@ -73,11 +73,11 @@ instead of building a global function called `execute()` that takes a
`ShellScript` argument, you could instead build something like this:
```tomo
lang Sh:
convert(text:Text -> Sh):
lang Sh
convert(text:Text -> Sh)
return Sh.from_text("'" ++ text.replace("'", "''") ++ "'")
func execute(sh:Sh -> Text):
func execute(sh:Sh -> Text)
...
dir := ask("List which dir? ")
@ -92,14 +92,14 @@ keyword. Conversions can be defined either inside of the language's block,
another type's block or at the top level.
```tomo
lang Sh:
convert(text:Text -> Sh):
lang Sh
convert(text:Text -> Sh)
return Sh.from_text("'" ++ text.replace("'", "''") ++ "'")
struct Foo(x,y:Int):
convert(f:Foo -> Sh):
struct Foo(x,y:Int)
convert(f:Foo -> Sh)
return Sh.from_text("$(f.x),$(f.y)")
convert(texts:[Text] -> Sh):
convert(texts:[Text] -> Sh)
return $Sh" ".join([Sh(t) for t in texts])
```

View File

@ -50,10 +50,10 @@ Now, what happens if we want to _use_ the compiled object file?
// File: baz.tm
foo := use ./foo.tm
func say_stuff():
func say_stuff()
say("I got $(foo.my_variable) from foo")
func main():
func main()
say_stuff()
```

View File

@ -86,10 +86,10 @@ list access.
You can iterate over the items in a list like this:
```tomo
for item in list:
for item in list
...
for i, item in list:
for i, item in list
...
```

View File

@ -15,9 +15,9 @@ collide with a user-chosen name like `FooBaz`.
// File: foo.tm
my_var := 123
struct Baz(x:Int):
struct Baz(x:Int)
member := 5
func frob(b:Baz -> Int):
func frob(b:Baz -> Int)
return b.x
```

View File

@ -71,7 +71,7 @@ y := 1.0
# implicit `!`:
x = x/y
func doop(x:Num -> Num):
func doop(x:Num -> Num)
# If a function's return type is non-optional and an optional value is
# used in a return statement, an implicit none check will be inserted and
# will error if the value is none:

View File

@ -98,8 +98,8 @@ This simplifies things if you want to do a reduction without writing a full
comprehension:
```tomo
struct Foo(x,y:Int):
func is_even(f:Foo)->Bool:
struct Foo(x,y:Int)
func is_even(f:Foo -> Bool)
return (f.x + f.y) mod 2 == 0
>> foos := [Foo(1, 2), Foo(-10, 20)]
@ -217,7 +217,7 @@ will be raised.
#### Addition
```
func plus(T, T)->T
func plus(T, T -> T)
```
In an addition expression `a + b` between two objects of the same type, the
@ -226,7 +226,7 @@ method `a.plus(b)` will be invoked, which returns a new value of the same type.
#### Subtraction
```
func minus(T, T)->T
func minus(T, T -> T)
```
In a subtraction expression `a - b` between two objects of the same type, the
@ -235,8 +235,8 @@ method `a.minus(b)` will be invoked, which returns a new value of the same type.
#### Multiplication
```
func times(T, T)->T
func scaled_by(T, N)->T
func times(T, T -> T)
func scaled_by(T, N -> T)
```
The multiplication expression `a * b` invokes either the `a.times(b)` method,
@ -247,7 +247,7 @@ non-numeric and `b` is numeric, or `b.scaled_by(a)` if `b` is non-numeric and
#### Division
```
func divided_by(T, N)->T
func divided_by(T, N -> T)
```
In a division expression `a / b` the method `a.divided_by(b)` will be invoked
@ -256,7 +256,7 @@ if `a` has type `T` and `b` has a numeric type `N`.
#### Exponentiation
```
func power(T, N)->T
func power(T, N -> T)
```
In an exponentiation expression, `a ^ b`, if `a` has type `T` and `b` has a
@ -265,8 +265,8 @@ numeric type `N`, then the method `a.power(b)` will be invoked.
#### Modulus
```
func mod(T, N)->T
func mod1(T, N)->T
func mod(T, N -> T)
func mod1(T, N -> T)
```
In a modulus expression, `a mod b` or `a mod1 b`, if `a` has type `T` and `b`
@ -275,7 +275,7 @@ has a numeric type `N`, then the method `mod()` or `mod1()` will be invoked.
#### Negative
```
func negative(T)->T
func negative(T -> T)
```
In a unary negative expression `-x`, the method `negative()` will be invoked
@ -284,13 +284,13 @@ and will return a value of the same type.
#### Bit Operations
```
func left_shifted(T, Int)->T
func right_shifted(T, Int)->T
func unsigned_left_shifted(T, Int)->T
func unsigned_right_shifted(T, Int)->T
func bit_and(T, T)->T
func bit_or(T, T)->T
func bit_xor(T, T)->T
func left_shifted(T, Int -> T)
func right_shifted(T, Int -> T)
func unsigned_left_shifted(T, Int -> T)
func unsigned_right_shifted(T, Int -> T)
func bit_and(T, T -> T)
func bit_or(T, T -> T)
func bit_xor(T, T -> T)
```
In a bit shifting expression, `a >> b` or `a << b`, if `a` has type `T` and `b`
@ -305,7 +305,7 @@ method `bit_and()`, `bit_or()`, or `bit_xor()` will be invoked, assuming that
#### Bitwise Negation
```
func negated(T)->T
func negated(T -> T)
```
In a unary bitwise negation expression `not x`, the method `negated()` will be

View File

@ -6,10 +6,10 @@ represent this case using enums like so:
```tomo
enum MaybeInt(AnInt(x:Int), NoInt)
func maybe_takes_int(maybe_x:MaybeInt):
when maybe_x is AnInt(x):
func maybe_takes_int(maybe_x:MaybeInt)
when maybe_x is AnInt(x)
say("Got an int: $x")
else:
else
say("Got nothing")
```
@ -18,10 +18,10 @@ situation where you might want to not have a value. Instead, Tomo has
built-in support for optional types:
```
func maybe_takes_int(x:Int?):
if x:
func maybe_takes_int(x:Int?)
if x
say("Got an int: $x")
else:
else
say("Got nothing")
```
@ -76,7 +76,7 @@ Here are some examples:
x := 5?
x = none
func doop(arg:Int?)->Text?:
func doop(arg:Int? -> Text?)
return none
doop(none)
@ -89,7 +89,7 @@ the need for an explicit `?` operator in the cases listed above:
x : Int? = none
x = 5
func doop(arg:Int?)->Text?:
func doop(arg:Int? -> Text?)
return "okay"
doop(123)
@ -115,10 +115,10 @@ maybe_x = none
>> maybe_x or fail("No value!")
# Failure!
func do_stuff(matches:[Text]):
func do_stuff(matches:[Text])
pass
for line in lines:
for line in lines
matches := line.matches($/{..},{..}/) or skip
# The `or skip` above means that if we're here, `matches` is non-none:
do_stuff(matches)

View File

@ -181,14 +181,14 @@ value if the file couldn't be read.
**Example:**
```tomo
# Safely handle file not being readable:
if lines := (./file.txt).by_line():
for line in lines:
if lines := (./file.txt).by_line()
for line in lines
say(line.upper())
else:
else
say("Couldn't read file!")
# Assume the file is readable and error if that's not the case:
for line in (/dev/stdin).by_line()!:
for line in (/dev/stdin).by_line()!
say(line.upper())
```

View File

@ -12,7 +12,7 @@ a new, different value and assigning it to a pointer's memory location to
replace the value that previously resided there.
```tomo
func no_mutation_possible(nums:[Int]):
func no_mutation_possible(nums:[Int])
nums[1] = 10 // This performs a copy-on-write and creates a new list
// The new list is only accessible as a local variable here
...
@ -21,7 +21,7 @@ no_mutation_possible(my_nums)
>> my_nums
= [0, 1, 2]
func do_mutation(nums:@[Int]):
func do_mutation(nums:@[Int])
nums[1] = 10 // The mutates the value at the given pointer's location
...
my_nums := @[0, 1, 2]
@ -82,9 +82,9 @@ this, and everywhere inside the truthy block will allow you to use the pointer
as a non-null pointer:
```
if optional:
if optional
ok := optional[]
else:
else
say("Oh, it was null")
```

View File

@ -62,10 +62,10 @@ Set length can be accessed by the `.length` field:
You can iterate over the items in a table like this:
```tomo
for item in set:
for item in set
...
for i, item in set:
for i, item in set
...
```

View File

@ -21,13 +21,13 @@ Structs can define their own methods that can be called with a `:` or different
values that are stored on the type itself.
```tomo
struct Foo(name:Text, age:Int):
struct Foo(name:Text, age:Int)
oldest := Foo("Methuselah", 969)
func greet(f:Foo):
func greet(f:Foo)
say("Hi my name is $f.name and I am $f.age years old!")
func get_older(f:@Foo):
func get_older(f:@Foo)
f.age += 1
...
my_foo := @Foo("Alice", 28)

View File

@ -139,10 +139,10 @@ t := {"A"=10, "B"=20}
You can iterate over the key/value pairs in a table like this:
```tomo
for key, value in table:
for key, value in table
...
for key in table:
for key in table
...
```

View File

@ -370,7 +370,7 @@ text := "
line one
line two
"
for line in text.by_line():
for line in text.by_line()
# Prints: "line one" then "line two":
say(line)
```
@ -398,7 +398,7 @@ delimiter (the default) will iterate over single grapheme clusters in the text.
**Example:**
```tomo
text := "one,two,three"
for chunk in text.by_split(","):
for chunk in text.by_split(",")
# Prints: "one" then "two" then "three":
say(chunk)
```
@ -425,7 +425,7 @@ given delimiter characters, until it runs out and returns `none`.
**Example:**
```tomo
text := "one,two,;,three"
for chunk in text.by_split_any(",;"):
for chunk in text.by_split_any(",;")
# Prints: "one" then "two" then "three":
say(chunk)
```