Skip to content

Language Syntax

tazz edited this page Jun 4, 2026 · 1 revision

Immutable Values

You can redefine variables.
You cannot mutate their values.

For example:

let x = {
  name: "Person 1",
}
x = { name: "Person 2", }
// is valid

x.name = "Person 2"
// is not valid

Primitives

fn init() =>
  {                            # a record
    message: "This is a test", # a string
    success: false,            # a boolean
    count: 10,                 # a number
    items: [                   # a seq
      1,
      10,
      100,
    ]
  }

Kura supports the following primitives:

Sequences (Seq)

let data = [
  1px,
  1px,
  1px,
]

Sequences represent series - lists or arrays, of data.

The compiler will attempt to infer and optimize the layout of the Sequences internally. The compiler will not guarantee the layout of a Sequence.

You should not rely on it.

Always treat Sequences as just a sequence - or list, of data rather than a contiguous array of data.

Combining Sequences

// you can combine Sequences together using the + operator
let items1 = [ item1, item2 ]
let items2 = [ item3, item4 ]

let items = items1 + items2
// this creates a new Sequence named items
// Equivalent to: [ item1, item2, item3, item4 ]

Records

Records hold key-value pairs and become immutable. Like Python Dictionaries or Javascript / JSON Objects.

let data = {
  status: 10,
  success: false,
  message: "Hello World",
}

// the following is an invalid record definition:
data = {
  10,
}

// or this:
data = {
  get-data(),
}

// or this:
data = {
  get-data(),
}

// or this:
data = {
  property: value,
  get-data(),
}

// or this:
data = {
  property: value,
  10,
}

You cannot change the properties of a Record once you construct a Record instance. You can only create a new Record instance.

let data = {
  success: false
}

// the following is not allowed:
data.success = false
// neither is this
data.message = "Hello World"

// however, this is acceptable
data = { success: true }

// or this
data = {
  ...data,
  message: "Hello World",
}

Record Comprehension

You can also use "Record Comprehension" - just like in Python and other data heavy languages, to compose Records.

let props1 = {
  fill: blue,
}

// and:
let props2 = {
  ...props1,
  insets: [ 1px, 1px, 1px, 1px ],
} // becomes:
// {
//   fill: blue,
//   insets: [ 1px, 1px, 1px, 1px ],
// }

// and:
let props3 = {
  ...props1,
  ...props2,
  isDebug: true,
} // becomes:
// {
//   fill: blue,
//   insets: [ 1px, 1px, 1px, 1px ],
//   isDebug: true,
// }

Combining Records

You can also combine them together using the + operator

let r1 = { status: 10, }
let r2 = {
  success: true,
  message: "Finished",
}

let r3 = r1 + r2 // becomes
// {
//   status: 10,
//   success: true,
//   message: "Finished",
// }

And

let r4 = r3 + {
  isDebug: true,
} // becomes
// {
//   status: 10,
//   success: true,
//   message: "Finished",
//   isDebug: true,
// }

And

let r5 = {
  ...(r1 + r2),
  component: "Button",
} // becomes
// {
//   status: 10,
//   success: true,
//   message: "Finished",
//   component: "Button",
// }

Basic Blocks

Control Flow

If Statements

Pattern Matching

Functions

fn add(x, y) =>
  x + y

Kura supports first-class functions.

fn apply(op, x, y) => op(x, y)

Types

// Since no type is specified
// the compiler will infer the type of 'x'
let x = 10

Kura's compiler will use type-inference to determine types if no type specification exists. If it can't determine the type, or if an invalid type specification occurs, the compiler will throw an error.

// The type of "Sequence" is valid for the value of 'x'
// no compilation errors are thrown
let x: Sequence = [ "Hello World" ]

// The type of "Number" is not valid for the value of 'x'
// a compilation error will be thrown here
let y: Number = "Hello World"

You can use the following for Kura's primitive types:

Type Type Specification Example
Strings String type StringAlias = String
or
let x: String = "Hello World"
Numbers Number type NumberAlias = Number
or
let x: Number = 10
Bools Bool type BoolAlias = Bool
or
let x: Bool = false
Records Record type RecordAlias = Record
or
let x: Record = {}
Sequences Seq type SequenceAlias = Sequence
or
let x: Sequence = []
Functions Function type FunctionAlias = Function
or
let x = (Number, Number) => Number

Typed Records

You can also specify a "Typed Record" like so:

type Position = {
  x: Number,
  y: Number,
}

// this returns a Record that matches the type of Position
fn get-pos => {
  x: 10,
  y: 20,
}

Record types can also declare optional properties like so:

type Position = {
  x: Number,
  y: Number,
  z: Optional<Number>,
}

// the return of this function is a record that matches
// the type of Position
fn get-pos-2d => {
  x: 10,
  y: 10,
}

// same here, the return of this function
// is a record that matches the type of Position
fn get-pos-3d => {
  x: 10,
  y: 10,
  z: 10,
}

For some shorthand syntactical sugar you can express optional properties like so:

type Position = {
  x: Number,
  y: Number,
  z?: Number, // this just means Optional<Number> to the compiler.
}

Algebraic Types

Kura supports algebraic types.

This allows for type unions.

// type union
type Message = Click | Tick

Generic Types

You can also have generic types in Kura

type Optional<T> = Some(T) | None

// and

type Result<T, E> = Ok(T) | Error(E)

Directives

Directives influence what the compiler should do during compilation.

Directives hint to the compiler on what it should do.
Directives do not guarantee that the compiler will do something specific.

Example:

// the following will hint to the compiler that the
// sequence value can be treated like a vectorized array
// this can improve maths operations significantly

@simd
let pos = [ 10, 10, 10, ]

// by default, the compiler will attempt to do this automatically
// however by adding the directive you can influence its decision
// to apply related optimizations to the value

// this still does not mean it will do this by default
// nor does it mean that pos is a contiguous value.
// *do not rely on the directives*
// the value for pos may not be contiguous
// *these are only hints* to the compiler

You can read more about Directives including the currently supported ones in Directives.

Clone this wiki locally