Overview
import {
std { compare.Ordering, io.stdin },
random { Random, thread_rng },
};
func read_number(buffer: $String) -> Result[U32, ParseError] {
buffer.clear;
stdin().read_line($buffer).expect;
buffer.trim.parse
}
func main() {
let mut buffer = String.new;
print("Please enter a number: ");
let number = while_failing {
read_number($buffer)
} {
print("Input must be a number.");
};
let correct = 0.to(number).random(thread_rng());
print("Guess a number 0 to \(number): ");
loop continue!{
let guess = read_number($buffer).catch {
print("Input must be a number.");
continue!();
};
correct.compare(&guess).match {
Ordering.Greater -> print("Higher..."),
Ordering.Less -> print("Lower..."),
Ordering.Equal -> {
print("Correct!");
return!();
},
};
};
};
Inspirations
Major Inspirations
| Language | Inspiration |
|---|---|
| Rust | philosophy, syntax, features |
| Gleam | philosophy, syntax, features |
| Smalltalk | philosophy, features |
| Swift | syntax, ergonomics |
Gleam was only discovered by me after significant design work for Sonance was already complete. Still, they two languages are very similar! That is why Gleam is listed as a major inspiration.
Minor Inspirations
Bibliography
Vscode Extension / TextMate Grammar
Unsorted
- https://without.boats/blog/references-are-like-jumps/
- https://rust-analyzer.github.io/book/contributing/architecture.html
- https://verdagon.dev/blog/group-borrowing
- https://verdagon.dev/grimoire/grimoire#the-list
- https://matklad.github.io/2024/12/24/minimal-version-selection-revisited.html
- https://sdiehl.github.io/typechecker-zoo/introduction.html
- https://rust-analyzer.github.io/blog
- https://matklad.github.io/2025/08/09/zigs-lovely-syntax.html
- https://mcyoung.xyz/2023/08/01/llvm-ir/
- https://futhark-lang.org/blog/2025-05-07-implement-your-language-twice.html
- https://kobzol.github.io/rust/2025/04/23/two-ways-of-interpreting-visibility-in-rust.html
- https://blog.polybdenum.com/2025/02/14/designing-type-inference-for-high-quality-type-errors.html
- https://blog.yoshuawuyts.com/a-survey-of-every-iterator-variant
- https://thunderseethe.dev/posts/bidirectional-constraint-generation/
- https://blog.yoshuawuyts.com/musings-on-iterator-trait-names/
- https://gist.github.com/boppreh/3b88231b7af15af54d292963f3d79b02
- https://stackoverflow.com/questions/42319737/reason-to-reverse-operands-in-array-access-subscripting
- https://en.m.wikipedia.org/wiki/Method_cascading
- https://verdagon.dev/blog/higher-raii-uses-linear-types
- https://stackoverflow.com/questions/1995113/strangest-language-feature/2023011#2023011
- https://verdagon.dev/blog/higher-raii-7drl
- https://www.mcmillen.dev/language_checklist.html
- https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/
- https://www.thedevtavern.com/blog/posts/structured-concurrency-explained/
- https://gleam.run/news/v0.25-introducing-use-expressions/
- https://without.boats/blog/patterns-and-abstractions/
- https://verdagon.dev/blog/on-removing-let-let-mut
- https://c9x.me/compile/
- https://internals.rust-lang.org/t/is-custom-allocators-the-right-abstraction/13460
- https://medium.com/@dhruvrajvanshi/type-inference-for-beginners-part-1-3e0a5be98a4b
- https://swift.org/documentation/api-design-guidelines/
- https://arrow-kt.io/docs/patterns/monad_comprehensions/
- https://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/
- https://medium.com/@olydis/uncluttered-programming-in-a-world-of-many-programming-concepts-81c5824a528d
- https://norasandler.com/2017/11/29/Write-a-Compiler.html
- https://verdagon.dev/blog/raii-next-steps
- https://without.boats/blog/notes-on-a-smaller-rust/
- https://without.boats/blog/revisiting-a-smaller-rust/
- https://without.boats/blog/the-problem-of-effects/
- https://www.digitalmars.com/articles/b90.html
- https://blog.ezyang.com/2013/05/the-ast-typing-problem/
- https://journal.stuffwithstuff.com/2015/09/08/the-hardest-program-ive-ever-written/
- https://bouvier.cc/2021/02/17/cranelift-codegen-primer/
- https://craftinginterpreters.com/
- https://kotlinlang.org/docs/coroutines-guide.html
- https://tratt.net/laurie/blog/2021/static_integer_types.html
- https://www.reddit.com/r/rust/comments/my3ipa/if_you_could_redesign_rust_from_scratch_today/
- https://internals.rust-lang.org/t/is-custom-allocators-the-right-abstraction/13460
- https://smallcultfollowing.com/babysteps/blog/2013/11/14/treating-vectors-like-any-other-container/
- https://matklad.github.io/2021/02/24/another-generic-dilemma.html
- https://medium.com/@dhruvrajvanshi/type-inference-for-beginners-part-1-3e0a5be98a4b
- https://soc.me/languages/stop-using-angle-brackets-for-generics.html
- https://course.ccs.neu.edu/cs4410sp19/lec_type-inference_notes.html
- https://joeduffyblog.com/2016/11/30/15-years-of-concurrency/
- https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/
- https://soc.me/languages/unified-condition-expressions.html
- https://mortoray.com/rejuvenating-the-ternary-conditional-with-optionals/
- https://mortoray.com/building-blocks-compiling-if-defer-break-continue-and-exceptions/
- https://makandracards.com/makandra/46939-ruby-small-summary-return-break-next-means-blocks
Language Reference
Keywords
| Context | Keyword | Description |
|---|---|---|
| Modules | module | Declare modules or implementations |
| Modules | import | Import items from other modules |
| Modules | export | Make item available to rest of current package |
| Modules | public | Make item available to external packages |
| Types | type | Declare or alias types |
| Types | trait | Declare or alias traits |
| Functions | func | Declare functions |
| Functions | do | Declare arguments in a block literal |
| Functions | block | Block type literal |
| Patterns | let | Declare variables |
| Patterns | mut | Make place mutable |
| Patterns | set | Assign value to place |
| Patterns | match | Pattern match an value |
Punctuation
| Name | Symbol | Description |
|---|---|---|
= | Assignment, labeled parameters | |
. | Pipeline | |
; | Statement ending | |
, | General purpose separator | |
: | Type ascription | |
() | Parameters, arguments, grouped expressions | |
{} | Code blocks | |
[] | Type parameters / generics | |
! | Label declaration, label call | |
? | Implicit argument, backpassing | |
-> | Return type ascription, match branches | |
& | Shared references | |
$ | Unique References |
Strings
Escape Codes
See Rust lol.
String Interpolation
Interpolation can be done with a special escape sequence \(...) where the ... is an arbitrary expression.
print("\(a) plus \(b) is \(a + b)");
Multiline Strings
Both after the opening quote and before closing quote must be only whitespace, which is stripped.
Starting whitespace of the closing quote is commonly stripped from all middle lines, syntax error if a line has less starting whitespace.
Newlines can be escaped using \ at the end of the line.
let example = "
foo\
bar
";
assert_equal(example, "foobar");
Raw Strings
Raw strings are created by prefixing the opening quote and suffixing the closing quote with a set number of # characters.
Within raw strings, normal special characters are interpreted literally, including sequences of lesser amounts of #.
To use escape sequences, prefix the \ character with the same amount of # as the opening and closing quotes.
let example ###"
"you can put whatever here"
##" not affected
###\n escape codes
###\(value) interpolation works
"###;
Functions
func add(x: U32, y: U32) -> U32 {
x + y
}
Modules
Basic Modules
module my_module {
...
}
Basic modules with no body can be used as a file heading. A file may have zero or one. This allows no identifier, instead using the file name. This is so you may attach attributes or documentation to a module declared by a file.
module;
Type Modules
Types themselves can act as modules, and you may declare and access items inside of them. To declare items as apart of a type, use the type keyword along with the type name instead of a module identifier. This may only be done within the file a type is defined, and cannot be used on type aliases.
module type MyType {
const num = 123;
}
print(MyType.num)
Trait Modules
Modules can implement a trait for a given type using ->. This must provide implementations of any items the trait requires, and will automatically provide them whenever the type is used in a context that requires that trait. Like inherent type modules, they contain the type keyword instead of a module identifier and must be declared in the same file as the type or the trait.
module type MyType -> MyTrait {
...
}
func use_trait[T: MyTrait](input: T) {
...
}
let value: MyType = ...;
use_trait(value);
Named Trait Modules
What if you needed to declare a trait module outside of where the type or trait is defined? Or if you want to provide an alternative to an existing trait module? In that case, you may provide a module name when creating a trait module. In this case, those items are only used when specifically requested. This also prevents the “HashMap problem” familiar to Rust’s justification of it’s orphan rules system.
module foo MyType -> MyTrait {
...
}
func use_trait[T: MyTrait](input: T) {
...
}
let value: MyType = ...;
use_trait(foo(value)); // Apply the named trait module before passing it
Types
Custom Types
type MyType {
VariantA,
VariantB,
}
Records
type MyRecord(foo: U32, bar: Boolean);
Anonymous Records
fn sincos(x: F64) -> type(F64, F64) {
type(x.sin, x.cos)
}
Type Aliases
type Alias = MyType;
Blocks
Example: scope
func scope[T](body: block() -> T) -> T {
body!()
}
Example: Option[T]
condition
.then { print("was true") }
.else { print("was false") }
func then[T](self: Boolean, body: block() -> T) -> Option[T] {
match(self) {
True -> Some(body!()),
False -> None,
}
}
func else[T](self: Option[T], body: block() -> T) -> T {
match(self) {
Some(value) -> value,
None -> body!(),
}
}
Example: while
let mut i = 1;
while { i < 6 } {
print(i);
i = i + 1;
}
func while(condition: block() -> Boolean, body: block()) {
loop {
condition!().then {
body!();
};
};
}
Labels
Backpassing
Function based
- Gleam’s
useexpressions - Koka’s
withstatement - Roc’s “backpassing” (which unfortunately appears to be a removed feature)
Monad based
Uses With Containers
func maybe_sum(x: Option[U32], y: Option[U32]) -> Option[U32] {
x.flat_map do(i) {
y.flat_map do(j) {
Some(i + j)
}
}
}
func maybe_sum(x: Option[U32], y: Option[U32]) -> Option[U32] {
let i = x.flat_map?;
let j = y.flat_map?;
Some(i + j)
}
Backpassing match Special Form
match(foo) {
True?,
False -> print("nope"),
};
print("yep");
Expression returns a tuple.
With values
match(foo) {
Pass(value)?,
Fail(error) -> print("oh no: \(error)"),
};
print("yippee: \(value)");
Traits
Advanced Modules
Week of 2025-09-08
Sunday 07
Converting this repository from solely housing the “book” into being a general purpose monorepo for the project. It makes sense I feel to keep everything in once spot, and the existing “book” is enough of a something to work from. Speaking of that, the “book” has gone from purely design notes to general purpose documentation. Now housing the starts of a bibliography (that I desperately need to organize), as well as this devlog, which should prove at the very least interesting in a few years, if not helping me gain support.
I also spent some time today starting the vscode extension, which gives us helpful things like syntax highlighting and basic convince features, but also will be an important stepping stone in getting the language server set up. This took some fumbling to get started and will likely take a lot of trial, error, and research to continue. Yay.
Tuesday 09
I spent sometime in class today cleaning up the design notes from the previous “version” of the “book”. I made the kinda whim decision of moving generics from <> to []. There’s plenty of logical and philosophical reasons why you can find online, I suppose. I figured I wouldn’t be used to it at first but I’m surprised it looks rather nice. I’m using the GitHub online vscode editor thing, to get around windows-linux file issues, but it doesn’t support things like formatting or spell checking. I remember something along the lines of .gitattributes I should look into. My next tasks are improving the design notes, especially the tokens reference.