NomiScript Language Reference

Table of Contents

Language features

Basic syntax

The language is based on S-expressions being a kind of domain-specific LISP dialect. The approach is chosen to simplify the processing of lists, provide lower complexity and flattened learning curve.

Comments

Comments start with a semicolon (;) and extend to the end of the line:

; This is a comment
(defun square (x)  ; inline comment
  (* x x))

Comments are ignored by the parser and do not affect program execution.

Annotations

Annotations are special comments that start with ; @ followed by an annotation name and an optional S-expression value:

; @test (= (count 'defun) 5)
; @version 1
; @author "John Doe"

Annotations are parsed and stored separately from program expressions, making them available for tooling, testing, and metadata processing. The annotation value can be any valid S-expression.

Types

Nil

The nil literal represents the absence of a value and the empty list. It is falsy in boolean contexts.

Booleans

Boolean literals are #t for true and #f for false:

#t  ; true
#f  ; false

Numbers

The only supported number primitive is a fraction. Every numeric input is converted to appropriate fraction (i.e. 10 becomes (/ 10 1)).

Decimal input is supported as syntax sugar (i.e. 0.1 becomes (/ 1 10)) but all the internal processing is only done in fractions.

Negative numbers are supported with a leading minus sign: -42, -0.5.

Strings

UTF-8 strings can be defined via:

  • " character: "Hello" is a string, escaping with \ is supported
  • """ sequence for long and multi-line strings and texts

Supported escape sequences: \n (newline), \t (tab), \r (carriage return), \\ (backslash), \" (quote).

Symbols

Symbols are literal names of language objects that can contain any non-space characters, they can also be internalized from the Strings.

Symbols cannot start with digits and cannot contain parentheses, quotes, or whitespace.

  • Defining and converting

    There are usual intern, quote, and eval for conversions.

Cons cells (pairs)

Cons cells are the fundamental building block for compound data. A cons cell contains two values: car (first) and cdr (rest). Dotted pair notation creates cons cells directly:

(a . b)           ; cons cell with car=a, cdr=b
(1 . (2 . nil))   ; chain forming a proper list (1 2)
(1 2 . 3)         ; improper list ending in 3

Proper lists (where the final cdr is nil) are displayed without dots:

(a . (b . (c . nil)))  ; displays as (a b c)

Lists

Lists are sequences of expressions enclosed in parentheses:

(1 2 3)
(+ a b)
(defun foo (x) (* x x))

Lists are syntactic sugar - internally they may be represented as chains of cons cells or as vectors depending on context. They are used for both data and code (function calls, special forms).

Quoted expressions

The quote character (') prevents evaluation of the following expression: #+beginsrc lisp 'foo ; the symbol foo, not its value '(1 2 3) ; a list, not a function call '(+ 1 2) ; the list (+ 1 2), not 3

Functions

Functions are parts of code having arguments (0 or more) and return value (0 or 1).

In-place functions

There's a lambda keyword for declaring function right in place

(lambda () 1)

Named functions

Traditional defun allows to define a function with a name

(defun sum (a b)
  "Sums `A' and `B' numbers"
  (+ a b))

Entity API

The entity API provides access to the binary input/output format defined in the script format specification.

Available entity functions

Entity-related functions registered in symbol.rs:

  • entity-count
  • context-type
  • primary-entity-type
  • primary-entity-idx
  • entity-type
  • entity-parent-idx
  • transaction-split-count
  • transaction-tag-count
  • transaction-is-multi-currency
  • transaction-post-date
  • transaction-enter-date
  • split-value-num
  • split-value-denom
  • split-value
  • split-reconcile-state
  • split-reconcile-date
  • create-tag
  • tag-name
  • tag-value
  • delete-entity

Entity type constants

Extracted from symbol.rs and scripting/format/src/lib.rs:

  • +ENTITY-TRANSACTION+ = 0
  • +ENTITY-SPLIT+ = 1
  • +ENTITY-TAG+ = 2
  • +ENTITY-ACCOUNT+ = 3
  • +ENTITY-COMMODITY+ = 4

Context type constants

  • +CONTEXT-CREATE+ = 0
  • +CONTEXT-UPDATE+ = 1
  • +CONTEXT-DELETE+ = 2
  • +CONTEXT-BATCH+ = 3

Financial struct definitions

Struct fields from symbol.rs, registered via DEFSTRUCT:

  • TRANSACTION: id parent-idx post-date enter-date split-count tag-count is-multi-currency
  • SPLIT: id parent-idx account-id commodity-id value-num value-denom reconcile-state reconcile-date
  • TAG: id parent-idx name value
  • ACCOUNT: id parent-idx parent-account-id name path tag-count
  • COMMODITY: id parent-idx symbol name tag-count

Output functions

(create-tag parent-idx name value)  ; create a tag entity in output
(delete-entity entity-idx)          ; mark entity for deletion in output

Trigger function

Define should-apply to control when a script runs:

(defun should-apply ()
    (= (primary-entity-type) +entity-transaction+))

If not defined, the script always runs (default returns 1).