The Trail Language
Silly ideas about how a language should have all its syntax trailing.
- Identifiers can be used as procedure arguments.
- Blocks are a comptime primitive type and can contain undefined identifiers.
- All code can be marked to be comptime.
- No generics. Instead, generate types or procedures needed using comptime procedure execution.
- No grouping executions using parentheses.
Syntax
- Keywords are capitalized letters.
- They will look fine with syntax highlighting.
- White spaces separate tokens.
a+b
is a single token, it can not involve procedure call.
- Expressions are evaluated left to right, with no operator precedence.
- Tuples are space-separated and expressions inside are lazy-evaluated.
=
and many other side-effects-only procedures return( )
.
1 = a -- Assign `1` to `a` by calling procedure `=` at comptime.
true =M b -- Mutable variable.
a / 2.0 = a/2 -- Call procedure `/` with `a` and `2.0` and assign to `a/2`.
false =R b -- Reassign `b`.
0 .. 10 do { "Hey" print } -- Print "Hey" 10 times.
( 1 2 ) nth 0 assert_eq 1
Procedures
=>
is a comptime procedure that takes a tuple of identifiers and a block as arguments and returns a procedure.- The last expression of a block is its return value.
- No “return” keyword.
- Procedures that take arguments are automatically called with the expression before it and the appropriate number of expressions after it.
- If a procedure does not take any arguments, it cannot be called by itself and requires a comptime procedure
call
to call it. - If an expression is not callable, the expression before it is discarded when the execution reaches it.
- If a procedure does not take any arguments, it cannot be called by itself and requires a comptime procedure
- Procedure
+doc
takes anything and a string as its two arguments, and apply the string as documentation to the first argument. - Limited polymorphism: the first argument of the procedure decides what the rest of the procedure arguments could be.
( a b ) => { a + b } = add -- Procedure `add`.
( ) => { "hell" ++ "o" } +doc "Return \"hello\"." = greet -- Procedure `greet`.
greet doc starts_with "Return" assert -- Assert the documentation of `greet`.
greet = also_greet
greet call = hello -- => "hello"
Names
Symbols can be names.
( a b ) => { a pow b } = ** -- Procedure `**`.
Compile-time (comptime) computation
The program is interpreted into a program that gets compiled.
- During interpretation, expressions marked with
C
are calculated. - Global variables are always calculated at compile time and immutable at run time.
- Comptime variables can also be declared “mutable at comptime.”
32 * 32 = TWO_TO_TEN -- Comptime.
( a b ) => {
b * b = b_square -- Run-time.
a * TWO_TO_TEN + b_square -- Run-time.
} = hyperbole -- Comptime.
( x ) => {
2 hyperbole 7 C = LUCKY_NUMBER -- Comptime.
LUCKY_NUMBER is_comptime assert -- Assert that `LUCKY_NUMBER` is comptime.
x + LUCKY_NUMBER -- Run-time.
} = add_luck -- Comptime.
2 =M TO_BE_CHANGED -- Comptime mutable.
0 .. 10 do { TO_BE_CHANGED * TO_BE_CHANGED =R TO_BE_CHANGED } -- Comptime
-- `TO_BE_CHANGED` = 4294967296
-- Assign a procedure type that take one argument of `Any` type and returns
-- an instance of `( )` to `equal_type`.
( Any ) proc_type ( ) = equal_type
= s_type assert_eq equal_type -- Assert `=`'s type.