Graffiticode Core Language Specification

Version: 0.1.4
Date: 2026-03-20

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.
  • Keywords: let, case, of, end, tag, true, false
  • 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

Functions have fixed arity, so applications can be parsed unambiguously without grouping syntax. For example, add 1 mul 2 3 parses as add(1, mul(2, 3)) because the parser knows add takes 2 arguments and mul takes 2 arguments.

Parentheses are used to defer application: map (double) [1 2 3]

3.2.2Lists

[1 2 3]

3.2.3Records

Records may use shorthand syntax for fields where the value is a reference to a variable of the same name.

let foo = 10..
{foo}         | equivalent to {foo: 10}

This provides a concise way to construct records using in-scope variable names as field keys and values.

You can also mix shorthand and explicit fields:

let x = 1..
let y = 2..
{x y z: 3}    | equivalent to {x: 1, y: 2, z: 3}
{ name: "Alice", age: 30 }

3.2.4Tags

A tag value is a symbolic value used to represent constants for pattern matching or other symbolic forms. Tags are identified by their name. Any two tags with the same name are equivalent.

The tag keyword followed by an identifier constructs a tag value:

let red = tag red..

Tag values:

  • Have value semantics — same name means same tag
  • Can be used anywhere a value is expected
let red = tag red..
let blue = tag blue..
let color = red..
case color of
  red: "warm"
  blue: "cool"
  _: "other"
end..

3.2.5Lambdas

<x: add x 1>

Multiple parameters: <x y: add x y>

3.2.6Let 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
Supports
Literalvalues
Tagvalues(matchedbyidentity)
Tupledestructuring:(a, b)
Recorddestructuring:{ name, age }
Wildcard_

Pattern matching on function arguments is disallowed.

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 and false.
  • json – Represents any JSON-compatible value (opaque, untyped).
  • any – Used internally to denote an unconstrained type (e.g., during inference).

4.2Composite Types

  • Lists – Written as [T] where T is any type. [string] | list of strings [number] | list of numbers [[bool]] | list of lists of booleans
  • Records – Key-value maps with known keys and types. { name: string, age: number }
  • Tuples – Ordered, fixed-length collections with heterogeneous types. (number, string, bool)

4.3Function Types

Functions are written using Graffiticode lambda signature syntax: <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: <number number: number> is equivalent to a function that returns another function: <number: <number: number>>

4.4Tag Type

Tag values are symbolic constants identified solely by their name. The same tag name refers to the same value regardless of where it appears. Tag values have the type tag.

let red = tag red..
let blue = tag blue..
let c = red..
case c of
  red: "warm"
  blue: "cool"
  _: "other"
end..

In this case, red and blue are tag patterns, and case matches by identity.

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
  • Undefined reference errors: raised during parsing when an identifier is not a known keyword, builtin, bound variable, or tag
  • 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
append <any list: list> Appends an element to the end of a list
apply <function list: any> Applies a function to a list of arguments
concat <string|list string|list: string|list> Concatenates two strings or two lists
cons <any list: list> Prepends an element to the front of a list
data <record: record> Returns upstream task data, or the argument if no input exists
div <number number: number> Divides numbers
drop <integer list: list> Returns a list with the first n elements removed
eq <number number: bool> Numeric equality
equiv <any any: bool> Semantic equivalence for any type, including tags
filter <function list: list> Keeps items matching predicate
ge <number number: bool> Returns true if first value is greater than or equal to second
get <string record: any> Retrieves a value from a record by key
gt <number number: bool> Returns true if first value is greater than second
hd <list: any> First item of list
isempty <list: bool> Returns true if the list is empty
json <string: any> Parses a string as JSON
last <list: any> Returns the last element of a list
le <number number: bool> Returns true if first value is less than or equal to second
length <list|string: integer> Returns the length of a list or string
log <any: any> Logs the value to console and returns it (identity function)
lt <number number: bool> Returns true if first value is less than second
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
ne <number number: bool> Returns true if the two values are not equal
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
pow <number number: number> Raises first number to the power of second
print <any: record> Outputs a value to the form
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
take <integer list: list> Returns the first n elements of a list
tl <list: list> All items except first

6.2.1add

Add two numbers.

add 2 3  | returns 5

6.2.2append

Append an element to the end of a list

append 4 [1 2 3]  | returns [1 2 3 4]
append 1 []       | returns [1]

6.2.3and

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.4apply

Apply a function to an argument list

apply add [1 2]  | returns 3

6.2.5concat

Concatenate two strings or two lists

concat "hello " "world"  | returns "hello world"
concat [1 2] [3 4]       | returns [1 2 3 4]

6.2.6cons

Prepend an element to the front of a list

cons 1 [2 3]  | returns [1 2 3]
cons 0 []     | returns [0]

6.2.7data

Returns the data from the upstream task, or the argument value if no input exists

data {x: 1, y: 2}  | returns {x: 1, y: 2} if no upstream input

6.2.8div

Divide the first number by the second

div 10 2  | returns 5

6.2.9drop

Returns a list with the first n elements removed

drop 2 [1 2 3 4 5]  | returns [3 4 5]
drop 0 [1 2 3]       | returns [1 2 3]

6.2.10eq

Numeric equality

eq 1 1  | returns true
eq 1 2  | returns false

6.2.11equiv

Semantic equivalence for any type, including tags

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

Tags can be compared with equiv:

let red = tag red..
let blue = tag blue..
equiv red red    | returns true
equiv red blue   | returns false

6.2.12filter

Filter elements matching predicate

6.2.13ge

Returns true if the first value is greater than or equal to the second

ge 5 3  | returns true
ge 3 3  | returns true
ge 2 3  | returns false
filter (<x: mod x 2>) [1 2 3 4]  | returns [1 3]

6.2.14get

Retrieve a record field

6.2.15gt

Returns true if the first value is greater than the second

gt 5 3  | returns true
gt 3 3  | returns false
get "b" {a: 1, b: 2}  | returns 2

6.2.16hd

Return the first item

hd [10 20 30]  | returns 10

6.2.17json

Parses a string as JSON

json "{\"a\": 1}"  | returns {a: 1}

6.2.18last

Returns the last element of a list

last [1 2 3]  | returns 3

6.2.19le

Returns true if the first value is less than or equal to the second

le 3 5  | returns true
le 3 3  | returns true
le 5 3  | returns false

6.2.20isempty

Return true if list is empty, otherwise return false

isempty []  | returns true

6.2.21length

Return the length of a list or string

length [1 2 3]    | returns 3
length "hello"    | returns 5
length []         | returns 0

6.2.22lt

Returns true if the first value is less than the second

lt 3 5  | returns true
lt 3 3  | returns false

6.2.23log

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.24map

Apply a function to each element

map (<x: add x 1>) [1 2 3]  | returns [2 3 4]

6.2.25max

Return the larger of two numbers

max 5 10  | returns 10

6.2.26min

Return the smaller of two numbers

min 5 10  | returns 5

6.2.27mod

Compute the remainder

mod 10 3  | returns 1

6.2.28mul

Multiply two numbers

mul 4 3  | returns 12

6.2.29ne

Returns true if the two values are not equal

ne 1 2  | returns true
ne 1 1  | returns false

6.2.30not

Logical NOT that inverts a boolean value

not true   | returns false
not false  | returns true

6.2.31nth

Get the nth item (0-based)

nth 1 [10 20 30]  | returns 20

6.2.32or

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.33print

Outputs a value to the form

print {x: 1, y: 2}  | outputs the record to the form

6.2.34pow

Raise the first number to the power of the second

pow 2 3  | returns 8
pow 5 2  | returns 25

6.2.35range

Produce a range list from start to end (exclusive) with step

range 1 10 2  | returns [1 3 5 7 9]

6.2.36reduce

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.37set

Return a new record with an updated field

set "a" 2 {a: 1}  | returns {a: 2}

6.2.38sub

Subtract the second number from the first

sub 5 2  | returns 3

6.2.39take

Returns the first n elements of a list

take 2 [1 2 3 4 5]  | returns [1 2]
take 0 [1 2 3]       | returns []

6.2.40tl

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..

---

§Index

  1. Supports
  1. 1Introduction
  2. 2Lexical Structure
    1. 2.1Tokens
    2. 2.2Comments
  3. 3Syntax
    1. 3.1Programs
    2. 3.2Expressions
      1. 3.2.1Function Application
      2. 3.2.2Lists
      3. 3.2.3Records
      4. 3.2.4Tags
      5. 3.2.5Lambdas
      6. 3.2.6Let Bindings
    3. 3.3Pattern Matching
  4. 4Type System
    1. 4.1Primitive Types
    2. 4.2Composite Types
    3. 4.3Function Types
    4. 4.4Tag Type
  5. 5Semantics
    1. 5.1Evaluation Model
    2. 5.2Functions
    3. 5.3Scoping
    4. 5.4Errors
  6. 6Base Library
    1. 6.1Types
    2. 6.2Built-in Functions
      1. 6.2.1add
      2. 6.2.2append
      3. 6.2.3and
      4. 6.2.4apply
      5. 6.2.5concat
      6. 6.2.6cons
      7. 6.2.7data
      8. 6.2.8div
      9. 6.2.9drop
      10. 6.2.10eq
      11. 6.2.11equiv
      12. 6.2.12filter
      13. 6.2.13ge
      14. 6.2.14get
      15. 6.2.15gt
      16. 6.2.16hd
      17. 6.2.17json
      18. 6.2.18last
      19. 6.2.19le
      20. 6.2.20isempty
      21. 6.2.21length
      22. 6.2.22lt
      23. 6.2.23log
      24. 6.2.24map
      25. 6.2.25max
      26. 6.2.26min
      27. 6.2.27mod
      28. 6.2.28mul
      29. 6.2.29ne
      30. 6.2.30not
      31. 6.2.31nth
      32. 6.2.32or
      33. 6.2.33print
      34. 6.2.34pow
      35. 6.2.35range
      36. 6.2.36reduce
      37. 6.2.37set
      38. 6.2.38sub
      39. 6.2.39take
      40. 6.2.40tl
  7. 7Program Examples
  8. §Index