Graffiticode Core Language Specification
Version: 0.1.1
Date: 2025-07-07
1Introduction
This document defines the Graffiticode Core Language Specification, covering syntax, semantics, and the base library. It excludes dialect-specific constructs, runtime behavior, and extended libraries.
2Lexical Structure
2.1Tokens
- Identifiers: Alphanumeric symbols beginning with a letter.
- Numbers: Integers and floats. Negative numbers start with
-
. - Strings: Double-quoted UTF-8 strings.
- Symbols:
(
,)
,[
,]
,{
,}
,:
,..
,<
,>
,,
2.2Comments
- Line Comments: Begin with
|
and continue to end of line.
3Syntax
3.1Programs
A Graffiticode program is a sequence of one or more let
declarations, followed by a single top-level expression, and terminated with ..
.
let double = <x: mul 2 x>..
map (double) [1 2 3]..
The top-level expression must always be followed by ..
.
3.2Expressions
3.2.1Function Application
Function application is written in prefix style: add 1 2
Parentheses are used to defer application: map (double) [1 2 3]
3.2.2Lists
[1 2 3]
3.2.3Records
{ name: "Alice", age: 30 }
3.2.4Lambdas
<x: add x 1>
Multiple parameters: <x y: add x y>
3.2.5Let Bindings
let double = <x: mul 2 x>..
3.3Pattern Matching
Pattern matching is done using case
: case x of 0: "zero" 1: "one" _: "other" end
Pattern matching on function arguments is disallowed.
3.3.1Tag Values
A tag value is an arity-0 symbolic value that can be used in pattern matching or to encode variant types.
red
Tag values:
- Are unbound identifiers that appear in expression position.
- May optionally be introduced via implicit enum definitions.
- Match directly in
case
expressions:
case color of
red: "warm"
blue: "cool"
_: "other"
end
Tags are resolved as special constants with symbolic identity. They are case-sensitive and may be compared for equality using regular pattern match semantics.
4Type System
Graffiticode includes a implicit structural type system. Every expression has a statically inferred type, and type errors are detected at compile time. Explicit type annotations are not included in the grammar.
4.1Primitive Types
number
– Represents integers or floating-point numbers.string
– Represents UTF-8 strings.bool
– Represents Boolean values:true
andfalse
.json
– Represents any JSON-compatible value (opaque, untyped).any
– Used internally to denote an unconstrained type (e.g., during inference).
4.2Non-Nullable Types
Graffiticode types are nullable by default. To indicate that a value must not be null
, append an exclamation mark (!
) to the type name.
string! | a non-nullable string
[number]! | a non-nullable list of numbers
A non-nullable type is guaranteed to hold a value. Nullable types may be null
or missing.
In general:
T
allowsnull
T!
disallowsnull
Type inference will propagate non-nullability when safe.
4.3Composite Types
- Lists – Written as
[T]
whereT
is any type.gc [string] | list of strings [number] | list of numbers [[bool]] | list of lists of booleans
- Records – Key-value maps with known keys and types.
gc { name: string, age: number }
- Tuples – Ordered, fixed-length collections with heterogeneous types.
gc (number, string, bool)
4.4Function Types
Functions are written using Graffiticode lambda signature syntax: gc <number number: number> | function taking two numbers and returning a number <string: [string]> | function taking a string and returning a list of strings <list record: record> | common signature for structural transformation
Function types are curried by default. That means: gc <number number: number>
is equivalent to a function that returns another function: gc <number: <number: number>>
4.5Tag Value Type
Tag values are symbolic constants with no arguments or payload. They are considered members of an implicit tag set, and their type is usually inferred based on the context in which they appear—such as in pattern matching.
4.5.1Default Type: `tag`
By default, a tag value has the type:
tag
If your program uses a fixed set of tags in a certain context (e.g., red
, green
, blue
), you can think of the type of those values as a discriminated union:
tag ∈ { red, green, blue }
However, Graffiticode does not currently support enumerating or defining tag types explicitly. Instead:
- All tags are treated as having type
tag
. - They are comparable for equality using
case
and pattern matching. - Their type can unify with record fields, parameters, or variants if used consistently.
4.5.2Example
case color of
red: "warm"
blue: "cool"
_: "other"
end
In this case, color
is assumed to be of type tag
.
4.6Example: Annotated Definitions
let inc = <x: add x 1> | type: <number: number>
let greet = <name: concat ["Hello, " name]> | type: <string: string>
let zip = <xs ys: zipLists xs ys> | type: <[T] [U]: [(T, U)]>
(Note: actual Graffiticode does not use type annotations in let
bindings; types are inferred.) (for illustration)
let inc = <x: add x 1> | type: <number: number>
let greet = <name: concat ["Hello, " name]> | type: <string: string>
let zip = <xs ys: zipLists xs ys> | type: <[T] [U]: [(T, U)]>
(Note: actual Graffiticode does not use type annotations in let
bindings; types are inferred.)
5Semantics
5.1Evaluation Model
- Purely functional: no side effects
- Strict evaluation: arguments evaluated before function application
- Immutable data: all values are immutable
Many built-in functions in Graffiticode follow a model-threading pattern. In this pattern, functions are defined to take one or more arguments followed by a model, which represents the current state of the program or view. The function uses the earlier arguments to compute an update to the model and returns a new model as its result.
This style enables a declarative and order-independent composition of functions. Since each function call returns a new model, multiple calls can be reordered without changing the final result, provided the functional dependencies are preserved.
This approach draws inspiration from Model-View-Update (MVU) architectures, in which the model represents the application state and functions describe pure, deterministic transformations of that state.
5.2Functions
- Fixed arity: every function has a known number of parameters
- Curried by default: partial application supported
5.3Scoping
- Lexical scoping
- Shadowing allowed within nested scopes
5.4Errors
- Syntax errors: raised during parsing
- Type errors: raised during compilation
- Runtime errors: e.g., out-of-bounds access
6Base Library
6.1Types
number
string
bool
list
record
tuple
json
6.2Built-in Functions
Function | Signature | Description |
---|---|---|
add |
<number number: number> |
Adds two numbers |
and |
<bool bool: bool> |
Logical AND operation |
apply |
<function list: any> |
Applies a function to a list of arguments |
div |
<number number: number> |
Divides numbers |
equiv |
<any any: bool> |
Tests if two values are strictly equivalent |
filter |
<function list: list> |
Keeps items matching predicate |
get |
<string record: any> |
Retrieves a value from a record by key |
hd |
<list: any> |
First item of list |
isEmpty |
<list: bool> |
Returns true if the list is empty |
log |
<any: any> |
Logs the value to console and returns it (identity function) |
map |
<function list: list> |
Applies function to each item |
max |
<number number: number> |
Returns the larger of two numbers |
min |
<number number: number> |
Returns the smaller of two numbers |
mod |
<number number: number> |
Remainder of division |
mul |
<number number: number> |
Multiplies numbers |
not |
<bool: bool> |
Logical NOT operation, inverts a boolean value |
nth |
<number list: any> |
Nth element of list |
or |
<bool bool: bool> |
Logical OR operation |
range |
<number number number: list> |
Generates a range list |
reduce |
<function any list: any> |
Combines list using a reducer with initial value |
set |
<string any record: record> |
Returns a new record with a key set to a value |
sub |
<number number: number> |
Subtracts numbers |
tl |
<list: list> |
All items except first |
6.2.1add
Add two numbers.
add 2 3 | returns 5
6.2.2and
Logical AND operation
and false false | returns false
and false true | returns false
and true false | returns false
and true true | returns true
6.2.3apply
Apply a function to an argument list
apply add [1 2] | returns 3
6.2.4div
Divide the first number by the second
div 10 2 | returns 5
6.2.5equiv
Tests if two values are strictly equivalent
equiv 1 1 | returns true
equiv "a" "a" | returns true
equiv true true | returns true
equiv 1 2 | returns false
equiv "a" "b" | returns false
6.2.6filter
Filter elements matching predicate
filter (<x: mod x 2>) [1 2 3 4] | returns [1 3]
6.2.7get
Retrieve a record field
get "b" {a: 1, b: 2} | returns 2
6.2.8hd
Return the first item
hd [10 20 30] | returns 10
6.2.9isEmpty
Return true if list is empty, otherwise return false
isEmpty [] | returns true
6.2.10log
Log a value to the console and return the value unchanged
log "Hello" | prints "Hello" to console and returns "Hello"
log (add 1 2) | prints 3 to console and returns 3
6.2.11map
Apply a function to each element
map (<x: add x 1>) [1 2 3] | returns [2 3 4]
6.2.12max
Return the larger of two numbers
max 5 10 | returns 10
6.2.13min
Return the smaller of two numbers
min 5 10 | returns 5
6.2.14mod
Compute the remainder
mod 10 3 | returns 1
6.2.15mul
Multiply two numbers
mul 4 3 | returns 12
6.2.16not
Logical NOT that inverts a boolean value
not true | returns false
not false | returns true
6.2.17nth
Get the nth item (0-based)
nth 1 [10 20 30] | returns 20
6.2.18or
Logical OR operation
or false false | returns false
or false true | returns true
or true false | returns true
or true true | returns true
6.2.19range
Produce a range list from start to end (exclusive) with step
range 1 10 2 | returns [1 3 5 7 9]
6.2.20reduce
Reduce a list to a single value, starting with an initial value
reduce (<a b: add a b>) 0 [1 2 3 4] | returns 10
6.2.21set
Return a new record with an updated field
set "a" 2 {a: 1} | returns {a: 2}
6.2.22sub
Subtract the second number from the first
sub 5 2 | returns 3
6.2.23tl
Return all but the first item
tl [10 20 30] | returns [20 30]
7Program Examples
let double = <x: mul 2 x>..
map (double) [1 2 3]..
case age of
18: "adult"
_: "other"
end..
---