Skip to main content

Syntax Keywords

The alias keyword is the core keyword of the Alia language, used to define new syntax structures. This document describes the definition forms, matching mechanism, and invocation forms of alias.

1. Basic Syntax​

alias <Keys pattern> -> <Stack implementation>
alias <Keys pattern> -> <Stack implementation> => <Key aliasName>
alias <Keys pattern> -> <Object type> <Stack implementation>
alias <Keys pattern> -> <Object type> <Stack implementation> => <Key aliasName>
alias <Keys pattern> => <Key aliasName>
alias <Keys pattern>
alias <Keys pattern> -> <Object type>

-> <Object type> declares the return type of the implementation body, and => <Key aliasName> declares the registered name of the syntax keyword. Declarations without an implementation body only register the matching pattern and produce no executable action.

Inline Alias Expressions​

When evaluated as an expression, alias returns an Alias object:

alias <Keys pattern> -> <Stack implementation>
alias <Keys pattern> -> <Object type> <Stack implementation>

After an inline alias expression is assigned to a variable, the variable holds an Alias object, which can be passed as an argument or stored in an object.

const add = alias <Number a> and <Number b> -> Number { a + b }
assert (call add [1, 2]) == 3 error 'inline alias mismatch'

2. Matching Mechanism​

Match Priority​

When both short and long pattern definitions exist, matching the long pattern in code executes the long one:

alias testmatch <Boolean condition> <Stack stack> -> {
if condition { call stack.run }
}
alias testmatch <Boolean condition> <Stack stack1> else <Stack stack2> -> {
if condition { call stack1.run } else { call stack2.run }
}
let result1 = ''
testmatch true {
result1 = 'yes'
} else {
result1 = 'no'
}
assert result1 == 'yes' error 'long match mismatch'

3. Keyword Aliases​

=> provides a registered name for a matching pattern. When the first item of the pattern is not a keyword, the explicit name determines the invocation entry:

alias <Number a> and <Number b> -> Number { a + b } => add
assert (add 1 and 2) == 3 error 'named alias mismatch'

A named alias registers both the syntax keyword and an Alias object of the same name once defined. See Section 4 for how the object form is stored and invoked.

4. Anonymous Aliases​

An anonymous alias has no registered name; the alias expression returns an Alias object after evaluation and is assigned to a variable:

const add = alias <Number a> and <Number b> -> Number { a + b }
assert (add 1 and 2) == 3 error 'anonymous alias mismatch'
const applyOperation = alias <Alias op> and <Number a> and <Number b> -> Number {
call op [a, b]
}
assert (call applyOperation [add, 5, 3]) == 8 error 'higher order mismatch'

The alias expression returns an Alias object after evaluation; this object can be stored and passed like any ordinary value.

call Syntax Invocation (Dynamic Dispatch)​

Invocation with known patterns should prefer the syntax form. The call array/object forms are reserved for dynamic dispatch scenarios where the target or argument shape can only be determined at runtime, as well as expression positions where the syntax form cannot be used:

const add = alias <Number a> and <Number b> -> Number { a + b }
assert (call add [1, 2]) == 3 error 'array call mismatch'
assert (call add *[b:2, a:1]) == 3 error 'object call mismatch'
  • call alias [arg1, arg2, ...]: passes an Array, with values supplied in parameter declaration order
  • call alias *[key:value, key2:value2, ...]: passes an Object, with keys corresponding to parameter names and values serving as argument values

Aliases in Objects​

Once an anonymous alias is stored in an object, it is invoked through a member target:

const helpers = *[
add: alias <Number a> and <Number b> -> Number { a + b },
multiply: alias <Number a> and <Number b> -> Number { a * b }
]
assert (call helpers.add [3, 4]) == 7 error 'object alias add mismatch'
assert (call helpers.multiply [3, 4]) == 12 error 'object alias multiply mismatch'

Value Access and Execution for Zero-Argument Forms​

Zero-argument syntax keywords execute as standalone statements; retrieving their value in an expression position requires call. For a zero-argument Alias object, a direct reference obtains the object, while call executes it:

let a = 21
let b = 21
alias plusAandB -> { a + b }
assert (call plusAandB) == 42 error 'keyword call mismatch'
const plusAandBObj = alias -> Number { a + b }
assert (call plusAandBObj) == 42 error 'object call mismatch'

5. Complex Pattern Matching​

Patterns with Parameters​

alias <Number a> plus <Number b> equals <Number c> -> Boolean {
a + b == c
}
assert (1 plus 2 equals 3) == true error 'pattern match mismatch'
assert (2 plus 3 equals 6) == false error 'pattern mismatch mismatch'

Nested Patterns​

alias whenMatch <Boolean condition> then <Stack stack1> else <Stack stack2> -> {
condition ? call stack1.run : call stack2.run
}
let nestedResult = ''
whenMatch true then { nestedResult = 'yes' } else { nestedResult = 'no' }
assert nestedResult == 'yes' error 'nested match mismatch'

Parameter Type Semantics​

The matching behavior of parameters declared with <Type name> differs by type:

  • <Stack stack>: matches Stack values or stack literals — stack literals ({}/*{}/-> {}), variables holding a Stack, and expressions returning a Stack can all serve as arguments. The static type must be Stack; non-Stack values (such as numbers or strings) report TYPE_ARGUMENT_MISMATCH at check time and RUNTIME_TYPE_ERROR at runtime.
  • <Alias aliasObject>: matches Alias objects — alias ... -> {...} literals, variables holding an Alias, or a named alias identifier. The actual type of the argument is validated; non-Alias values (such as stack literals or numbers) report TYPE_ARGUMENT_MISMATCH at check time and RUNTIME_TYPE_ERROR at runtime.
const apply = alias <Alias op> and <Number a> -> Number { call op [a] }
const incAlias = alias <Number x> -> Number { x }
assert (call apply [incAlias, 5]) == 5 error 'alias param mismatch'
let caught = false
try { call apply [{}, 5] } catch e { caught = true }
assert caught == true error 'alias type check mismatch'

<Alias> parameters can receive stored Alias objects both in syntax-form invocations and in call array/object invocations.

6. Removing and Disabling Aliases​

Removing an Alias​

alias customPrint <Value val> -> {
print val
}
customPrint 'Hello'
remove customPrint

After removal the name no longer matches; invoking it raises an undefined-alias error:

alias tempAlias <Number val> -> Number {
val
}
assert (tempAlias 42) == 42 error 'before remove mismatch'
remove tempAlias
let removed = false
try { tempAlias 1 } catch e { removed = true }
assert removed == true error 'remove mismatch'

Disabling an Alias​

alias toggleAlias <String val> -> String {
'enabled: ' .. val
}
assert (toggleAlias 'test') == 'enabled: test' error 'before disable mismatch'
disable toggleAlias
let disabled = false
try { toggleAlias 'test' } catch e { disabled = true }
assert disabled == true error 'disable mismatch'
enable toggleAlias
assert (toggleAlias 'test') == 'enabled: test' error 'enable mismatch'

The targets of remove, disable, and enable are alias names, without any parameter pattern.

7. Example Code​

alias repeat3 <Number times> times <Stack stack> -> {
for { let i = 0 } i < times { i ++ } {
call stack.run
}
}
let repeatCount = 0
repeat3 3 times {
repeatCount = repeatCount + 1
}
assert repeatCount == 3 error 'repeat mismatch'
alias greet <String name> with <String? greeting> -> String {
(greeting ?? 'Hello') .. ', ' .. name .. '!'
}
assert (greet 'Alice' with 'Hello') == 'Hello, Alice!' error 'greet mismatch'
assert (greet 'Bob' with 'Hi') == 'Hi, Bob!' error 'greet with mismatch'
alias <Number num> squared -> Number {
num * num
}
alias <Number num> cubed -> Number {
num * num * num
}
assert (5 squared) == 25 error 'squared mismatch'
assert (3 cubed) == 27 error 'cubed mismatch'
alias choose <Boolean c> between <Value a> and <Value b> -> Value {
c ? a : b
}
assert (choose true between 'Yes' and 'No') == 'Yes' error 'choose mismatch'
const numbers = [1, 2, 3, 4, 5]
const double = alias <Number x> -> Number { x * 2 }
let doubledTotal = 0
each n in numbers {
const d = call double [n]
doubledTotal = doubledTotal + d
}
assert doubledTotal == 30 error 'each alias mismatch'

Next Steps​