Built-Ins
Stack comes with quite a few built-in functions (called intrinsics internally). They provide baseline functinoality for Stack.
Lists vs Functions
Unless explicitly stated in the description of a function, for all mentions of the type list, functions are also supported (e.g.: (fn 2 2 +) len).
Arithmetic
Note: Stack uses wrapping arithmetic, unlike Rust, which uses bounds checking in safe modes.
Add (+)
Signature: ([a: int] [b: int] -- int)
Equivalent Rust: a + b
Examples:
1 2 +
;; 3
Subtract (-)
Signature: ([a: int] [b: int] -- int)
Equivalent Rust: a - b
Examples:
2 1 -
;; 1
1 2 -
;; -1
Multiply (*)
Signature: ([a: int] [b: int] -- int)
Equivalent Rust: a * b
Examples:
2 3 *
;; 6
Divide (/)
Signature: ([a: int] [b: int] -- int)
Equivalent Rust: a / b
Examples:
6 3 /
;; 2
Remainder (%)
Signature: ([a: int] [b: int] -- int)
Equivalent Rust: a % b
Examples:
10 5 %
;; 0
11 5 %
;; 1
Comparison
Equal (=)
Signature: ([a] [b] -- bool)
Equivalent Rust: a == b
Examples:
2 2 =
;; true
"hello" "world" =
;; false
'(1 2) '(1 2) =
;; true
Not Equal (!=)
Signature: ([a] [b] -- bool)
Equivalent Rust: a != b
Examples:
2 2 !=
;; false
"hello" "world" !=
;; true
'(1 2) '(1 2) !=
;; false
Less Than (<)
Signature: ([a] [b] -- bool)
Equivalent Rust: a < b
Examples:
1 2 <
;; true
2 1 <
;; false
Less Than or Equal To (<=)
Signature: ([a] [b] -- bool)
Equivalent Rust: a <= b
Examples:
1 2 <=
;; true
2 2 <=
;; true
2 1 <=
;; false
Greater Than (>)
Signature: ([a] [b] -- bool)
Equivalent Rust: a > b
Examples:
1 2 >
;; false
2 1 >
;; true
Greater Than or Equal To (>=)
Signature: ([a] [b] -- bool)
Equivalent Rust: a >= b
Examples:
1 2 >=
;; false
2 2 >=
;; true
2 1 >=
;; true
Boolean
Or (or)
Signature: ([a: bool] [b: bool] -- bool)
Equivalent Rust: a || b
Examples:
false false or
;; false
false true or
;; true
true false or
;; true
true true or
;; true
And (and)
Signature: ([a: bool] [b: bool] -- bool)
Equivalent Rust: a && b
Examples:
false false and
;; false
false true and
;; false
true false and
;; false
true true and
;; true
Not (not)
Signature: ([a: bool] -- bool)
Equivalent Rust: !a
Examples:
false not
;; true
true not
;; false
Stack Ops
Drop (drop)
Signature: ([a] --)
Drops a from the stack
Examples:
"hey"
;; ["hey"]
drop
;; []
Duplicate (dupe)
Signature: ([a] -- a a)
Duplicates a on the stack
Examples:
"hey"
;; ["hey"]
dupe
;; ["hey" "hey"]
Swap (swap)
Signature: ([a] [b] -- b a)
Swaps a and b on the stack
Examples:
"hello" "world"
;; ["hello" "world"]
swap
;; ["world" "hello"]
Rotate (rot)
Signature: ([a] [b] [c] -- b c a)
Rotates a, b, and c on the stack
Examples:
"a" "b" "c"
;; ["a" "b" "c"]
rot
;; ["b" "c" "a"]
Lists
Length (len)
Signature: ([a: list|string|function] -- int)
Equivalent Rust: a.len()
Examples:
'[1 2 3] len
;; 3
"123" len
;; 3
Get at Index (nth)
Signature: ([a: list|function] [b: int] -- a any) or ([a: string] [b: int] -- a string)
Equivalent Rust: a[b] or a.get(b)
Examples:
'[1 2 3] 0 nth
;; [[1 2 3] 1]
'[1 2 3] 2 nth
;; [[1 2 3] 3]
"123" 0 nth
;; ["123" "1"]
"123" 2 nth
;; ["123" "3"]
Split (split)
Signature: ([a: list] [b: int] -- list list) or ([a: string] [b: int] -- string string)
Splits a at the separator b and returns both chunks.
Examples:
'[1 2 3] 1 split
;; [1] [2 3]
"123" 1 split
;; "1" "23"
Concat (concat)
Signatures:
- ([a: list] [b: list] -- list)
- ([a: string] [b: string] -- string)
- ([a: function] [b: function] -- function)
- ([a: function] [b: list] -- function)
- ([a: list] [b: function] -- list)
Concats a and b together (concats the two lists or two strings)
Examples:
'[1] '[2 3] concat
;; [1 2 3]
"1" "23" concat
;; "123"
Push (push)
Signature: ([a] [b: list|function] -- b) or ([a: string] [b: string] -- string)
Equivalent Rust: b.push(a)
Examples:
3 '[1 2] push
;; [1 2 3]
"3" "12" len
;; "123"
Pop (pop)
Signature: ([a: list|function] -- a any) or ([a: string] -- string)
Equivalent Rust: a.pop()
Examples:
'[1 2 3] pop
;; 3
"123" len
;; "3"
Records
Insert (insert)
Signature: ([value] [key] [c: record] -- record)
Equivalent Rust: c.insert(key, value)
Examples:
"value" "key" {} insert
;; {key: "value"}
true 'key {} insert
;; {key: true}
2 1 {} insert
;; {1: 2}
Property (prop)
Signature: ([a: record] [b] -- a any)
Equivalent Rust: a.get(b)
Examples:
{key "value"} "key" prop
;; [{key "value"} "value"]
{key "value"} "foo" prop
;; [{key "value"} nil]
{key "value"} 'key prop
;; [{key "value"} "value"]
{key "value"} 'foo prop
;; [{key "value"} nil]
{1 2} 1 prop
;; [{1 2} 2]
{1 2} 2 prop
;; [{1 2} nil]
Has (has)
Signature: ([a: record] [b] -- a bool)
Equivalent Rust: a.has(b)
Examples:
{key "value"} "key" has
;; [{key "value"} true]
{key "value"} "foo" has
;; [{key "value"} false]
{key "value"} 'key has
;; [{key "value"} true]
{key "value"} 'foo has
;; [{key "value"} false]
{1 2} 1 has
;; [{1 2} true]
{1 2} 2 has
;; [{1 2} false]
Remove (remove)
Signature: ([a: record] [b: string] -- record)
Equivalent Rust: a.remove(b)
Examples:
{key "value" foo "bar"} "foo" remove
;; [{key "value"}]
{key "value" foo "bar"} "bar" remove
;; [{key "value" foo "bar"}]
Keys (keys)
Signature: ([a: record] -- a list(symbol))
Equivalent Rust: a.keys()
Examples:
{key "value" foo "bar"} keys
;; [{key "value" foo "bar"} (key foo)]
{"key" "value" "foo" "bar"} keys
;; [{key "value" foo "bar"} (key foo)]
Values (values)
Signature: ([a: record] -- a list)
Equivalent Rust: a.values()
Examples:
{key "value" foo "bar"} values
;; [{key "value" foo "bar"} ["value" "bar"]]
{f (fn 2 2 +)} values
;; [{key (fn 2 2 +)} ((fn 2 2 +))]
{f '(fn 2 2 +)} values
;; [{key '(fn 2 2 +)} ('(fn 2 2 +))]
Types
Cast (cast)
Signature: ([a] [b: string] -- any)
Converts a to the type: b and returns the new type
Type of (typeof)
Signature: ([a] -- string)
Gets the type of a and pushes it as a string to the stack
Lazy (lazy)
Signature: ([a] -- lazy(a))
Wraps a with a lazy expression, making it lazy.
Examples:
1 lazy
;; '1
'[]
;; []
lazy
;; '[]
Control Flow
If (if)
Signature: ([a: bool] [b: list] --)
Equivalent Rust: if a { b }
Examples:
'["true"]
true
if
;; "true"
[4 4 =]
;; [true]
'["true"]
;; [true ["true"]]
if
;; ["true"]
Halt (halt)
Signature: (--)
Equivalent Rust: Halts execution.
Examples:
2 2 halt +
;; halts before the "+"
Recur (recur)
Signature: (-- symbol)
A QoL helper intrinsic that pushes the symbol: recur to the stack. Used to allow recur to be called without escaping with a lazy (such as 'recur).
Examples:
;; Define i
0 'i def
;; Function isn't lazy so it runs right away
(fn
  ;; Check if i is less than 5 (condition)
  i 5 <
  ;; Our if block
  '[
    ;; Push i to the stack
    i
    ;; Add 1 to i
    i 1 + 'i set
    ;; Recur
    recur
  ]
  ;; Run the if
  if
)
;; [0 1 2 3 4]
OrElse ('orelse')
Signature: ([a] [b] -- a|b)
Equivalent Rust: a.or(b)
If a is nil, returns b. Else, returns a.
Examples:
nil 2 orelse
;; 2
1 2 orelse
;; 1
Scopes and Variables
Define (def)
Signature: ([a] [b: symbol] --)
Equivalent Rust: let b = a
Examples:
0 'a def
a
;; 0
'(fn +) 'add def
2 2 add
;; 4
Set (set)
Signature: ([a] [b: symbol] --)
Equivalent Rust: b = a
Examples:
0 'a def
1 'a set
a
;; 1
1 'a set
;; throws since `a` is not defined
Call (call)
Signature: ([a] --)
Calls a and:
- If ais a function: Runs the function
- If ais a list: Runs each item in the list
- If ais a symbol: Calls the symbol from the scope
- If ais anything else: Pushes it back onto the stack
Examples:
2 2 
'(fn +) call
;; 4
'[2 2 +] call
;; 4
'[2 2 +] 'add def
add
;; [[2 2 +]]
call
;; [4]
'(fn +) 'add def
2 2 'add call
;; 4
0 'a def
'a call
;; 0
"foo" 'a def
'a call
;; "foo"
Let (let)
Signature: ([a: list] [b: list(symbol)] --)
Pops b.len() items off of the stack, assigning each item the corresponding symbol in b. Then, runs the code block a, injecting the symbols into the scope.
If list b was (first second), then they would be popped from the stack in order, following this signature: ([first] [second] --).
Important Note: Functions cannot be used as the block of a let (a). To use functions within lets, wrap them within the let block: 0 '((fn a)) '(a) let. Lets create create their own scopes, so any def will be isolated to that let.
Examples:
10 2 '[a b -] '[a b] let
;; 8
10 2
'[
  (fn a b -)
] '[a b] let
;; 8
10 2
(fn
  '[a b -]
  '[a b]
  let
) call
;; 8
Get (get)
Signature: ([a: symbol] -- any)
Equivalent Rust: a
Examples:
0 'a def
'a get
;; 0
'(fn +) 'add def
2 2 add
;; 4
'(fn +) 'add def
'add get
;; (fn +)
'(fn +) 'add def
2 2 
'add get call
;; 4
Debugging and I/O
Debug (debug)
Signature: ([a] -- a)
Equivalent Rust: dbg!(format!("{}", a))
Examples:
0 debug
;; prints 0
"hey" debug
;; prints "hey"
Assert (assert)
Signature: ([a] [b: bool] -- a)
Equivalent Rust: assert!(b, format!("{}", a))
Examples:
"my test" 2 2 = assert
;; nothing (it passes)
"my test" 1 2 = assert
;; error: assertion failed caused by my test
Import (import)
Signature: ([a: string] --)
Runs the file from path a in the current environment. Variables and stack changes will persist from file a.
Examples:
;; lib.stack
'(fn +) 'add def
;; main.stack
"lib.stack" import
2 2 add
;; 4