Top > Design docs > Core design > Part 04
Sigmal surface syntax is:
All constructs are expressions.
Identifiers:
_Identifiers are never reserved.
Their meaning depends solely on syntactic position.
Only symbolic tokens are reserved:
\ abstraction
$ universe
@ symbol injection
& record
## inductive
. projection
{ } block
( ) grouping
: type annotation
= binding (blocks/records)
; definition separator
-> arrow sugar
^ pattern match
=> match arm separator
No alphanumeric keyword is reserved.
Sigmal defines no user-definable infix operators or precedence rules.
All constructs are expressions.
There are no statements.
There is no let, import, or match keyword.
Dependent abstraction:
\ (x : A) -> T = body
This single form serves both:
Multiple parameters:
\ (x : A) (y : B) -> T = body
Arrow sugar:
A -> B
means:
Application is whitespace-based.
f x
f x y
g f x
Application is left-associative:
f x y ≡ (f x) y
Parentheses are used only for grouping:
f (g x)
Parentheses are not used for function calls.
&{
k1 : T1;
k2 : T2;
}
&{
k1 = v1;
k2 = v2;
}
Field order is irrelevant.
Trailing semicolon inside records is optional.
#{
C1;
C2(v : T);
}
Constructors may carry arguments.
Pattern matching uses ^:
^ x {
C1 => e1;
C2(y) => e2;
}
Patterns must be exhaustive.
^ introduces a match expression.
=> separates patterns from result expressions.
Projection uses ..
r.k
means:
r.@{ TextSym "k" }
Projection is left-associative:
a.b.c
means:
(a.b).c
There is no alternate meaning of . anywhere in the language.
The operator . denotes record projection.
A dot-starting projection expression:
.std.alloc
is interpreted as projection from a distinguished top-level module record supplied by the resolver.
The core language does not define a value corresponding to . itself.
Instead, the resolver provides the root record used for dot-starting projection.
A resolver may choose to:
Provided that resolution is deterministic for a fixed resolver configuration and target.
The core language defines only structural record projection. Any meaning assigned to dot-starting projection is external to the core type system.
Symbol injection syntax:
@{ e }
where:
e : Syme must be const-normalizableValid only in symbol-key positions:
Identifiers in key positions are sugar for:
@{ TextSym "identifier" }
Note:
TextSym(and related symbol construction utilities) are provided by.std.core.
Universe levels:
$ { e }
where:
e : Nate must be const-normalizableSugar:
$0 ≡ $ { 0 }
$1 ≡ $ { 1 }
A source file consists of:
Definition syntax:
name = expr;
The final expression:
;There is no implicit record wrapping of definitions.
If the final expression is a record, the compilation unit may serve as a namespace.
If not, it is simply a value.
Single-line comments:
// comment
Block comments:
/* comment */
Block comment nesting is implementation-defined.
Parsing is deterministic because:
\ (...) -> ... = ... always introduces abstraction^ expr { ... } always introduces match&{ ... } always introduces record#{ ... } always introduces inductive$ { ... } always introduces universe@{ ... } always introduces symbol injection. is always projection=> appears only inside match armsNo token changes meaning based on context.
There are no reserved alphanumeric keywords.
Sigmal surface syntax:
\ for abstraction^ for pattern matching. for projection everywhere. as an expressionAll syntax corresponds directly to core semantic constructs.
Sigmal.org - the calculus we can build on