types
-
parameterized types desugar to compile-time functions
-
type aliases?
atomic types
-
int
- unbounded
- normally use a range type
- bounds are inferred in calculations
-
sym
-
written with prefix dot (infix dot is projection)
.ident
-
represents itself
-
used for tags
-
opaque value
-
symbols have attributes used for RTTI
-
does it make sense for a number (eg 4) or symbol to represent itself when used as a type? because of enum-unions
vector types
-
vector
- sized by an enum
- value type, not reference
-
slice
- reference to vector
-
buffer
- mutable / growable slice on heap
-
bits
bits # native lebits bebits
-
all distinct types, explicit conversion required
-
implicit (?) conversion / match to / from product of matching bits types
-
product types
- tuple
- record
union types
-
two kinds
-
enum = union of constants
- int
- sym
- range is special case of union of int
-
data = algebraic data type
- a union of tagged values
conditionals
simplified from “the ultimate conditional syntax” https://dl.acm.org/doi/10.1145/3689746
Instead of being syntactically fixed parts of an if
statement,
then
and else
are operators that are valid inside an if
expression. They desugar like:
"then" block -> "and" _if_ "<-" block
"else" block -> "or" _if_ "<-" block
The syntax
label "<-" expr
is like Rust break 'label expr
or BCPL resultis expr
: the label
identifies a surrounding scope; control leaves that scope yielding the
expression as the value of the scope. (Dunno if I like this syntax but
it’ll do as a placeholder. It has the advantage of not using Rust
'lifetime
syntax with its mismatched quote.)
The _if_
denotes a fresh name labelling the if
statement, which is
generated as part of the desugaring. You can’t use then
or else
outside an if
expression (where there’s no “if” in scope), and to
avoid confusion the “if” label’s scope does not reach into the then
or else
blocks.
if_expr = "if" or_expr
or_expr = and_expr "or" or_expr
/ and_expr
and_expr = bin_expr "is" pattern
/ bin_expr "and" and_expr
/ bin_expr
patterns mirror type expressions
operators
outfix
try to make each kind of bracket mean a different thing
() grouping
[] construct vector / record / tuple
{} code block
-
a function argument is typically a tuple or record, but traditionally uses ()
-
tho CPL used []
prefix
ranges
<= lo < hi
<= lo <= hi
-
open-ended ranges?
-
ranges work as values and as enum types
numbers
+ numeric identity
- numeric negation
numbers, bits, bytes, boolean
~ bitwise not
half-range constructors
< > <= >=
symbols
.
label
:
strings
$ $$
attributes
@ @@
infix
. projection
: type ascription
numbers
+ addition
- subtraction
* multiplication
/ division
% remainder
^ exponentiation
- how to deal with truncating vs flooring division?
numbers, bits, bytes
~ exclusive or
boolean, bits, bytes, ranges
-
quirky?
/\ bitwise and / intersection / conjunction \/ bitwise or / union / disjunction
-
basic?
and / or -- shortcutting flow control & / | -- bitwise
bits, bytes, strings, vectors
>< concatenation
all types
== equal
<> not equal
numbers, bits, bytes, strings
< less than
<= less than or equal
> greater
>= greater or equal
<=> compare for sorting
chainable operators
Infix operators do not have precedence. They may be chained only if the operators within round brackets are all from one of these sets:
+ -
~
*
/\
\/
><
< <= ==
> >= ==