YREA-SLS/postfix_lang_spec.md

6.5 KiB

APEX Language Specification v0.1

Array-oriented Postfix Expression Language

Design Philosophy

APEX combines the clarity of postfix notation (RPL), the power of systems programming (C), and modern array-oriented programming (Uiua). The language uses strict postfix (RPN) syntax where all operators follow their operands, promoting a natural stack-based evaluation model.


Tier System

Tier 1: Foundation

Core stack operations, basic arithmetic, simple control flow

Tier 2: Structured Programming

Functions, arrays, complex data types, advanced control structures

Tier 3: Systems Programming

Memory management, pointers, foreign function interface, concurrency


Tier 1: Foundation

Stack Operations

dup    - Duplicate top item: a → a a
drop   - Remove top item: a →
swap   - Swap top two items: a b → b a
over   - Copy second item: a b → a b a
rot    - Rotate three items: a b c → b c a

Arithmetic Operators (Postfix)

+      - Addition: a b → (a+b)
-      - Subtraction: a b → (a-b)
*      - Multiplication: a b → (a*b)
/      - Division: a b → (a/b)
%      - Modulo: a b → (a%b)
neg    - Negate: a → (-a)

Comparison Operators

=      - Equal: a b → bool
<      - Less than: a b → bool
>      - Greater than: a b → bool
<=     - Less or equal: a b → bool
>=     - Greater or equal: a b → bool
!=     - Not equal: a b → bool

Logical Operators

and    - Logical AND: a b → bool
or     - Logical OR: a b → bool
not    - Logical NOT: a → bool

Basic Control Flow

[ condition ] [ true-branch ] if
[ condition ] [ true-branch ] [ false-branch ] ifelse

Example:

5 3 > [ "greater" ] [ "not greater" ] ifelse print

Variables

var-name !     - Store to variable (pop from stack)
var-name @     - Load from variable (push to stack)

Example:

42 x !         # Store 42 to x
x @ 10 +       # Load x, add 10 → 52

Comments

# Single line comment
(* Multi-line
   comment *)

Tier 2: Structured Programming

Functions

Functions are defined with postfix syntax:

[ body ] function-name :

Example:

[ dup * ] square :          # Define square function
5 square                     # Call: 5 → 25

Functions with Local Variables

[ arg1 arg2 | body ] function-name :

The | separator indicates parameter binding from stack:

[ x y | x @ y @ + ] add :   # Pop two values, bind to x and y
3 5 add                      # → 8

Recursion

[ n | 
  n @ 1 <= 
  [ 1 ] 
  [ n @ n @ 1 - factorial * ] 
  ifelse 
] factorial :

5 factorial                  # → 120

Arrays (Uiua-inspired)

[ e1 e2 e3 ... ]   - Array literal
length             - Get array length: arr → n
@i                 - Index access: arr i → element
!i                 - Index store: arr i val →
range              - Create range: n → [0..n-1]
each               - Map function: arr [fn] → arr'
reduce             - Fold: arr init [fn] → value
filter             - Filter: arr [predicate] → arr'

Example:

[1 2 3 4 5]                 # Array on stack
[ 2 * ] each                # → [2 4 6 8 10]

10 range [ 2 % 0 = ] filter # Even numbers: [0 2 4 6 8]

Loops

[ condition ] [ body ] while
n [ body ] times

Example:

0 i !
[ i @ 10 < ] [ 
  i @ print 
  i @ 1 + i ! 
] while

5 [ "hello" print ] times   # Print "hello" 5 times

Structures (Records)

{ field1 field2 ... } struct-name struct

Example:

{ x y } Point struct

3 4 Point.new p !            # Create Point(3, 4)
p @ .x                       # Access field x → 3
p @ 5 .x!                    # Set field x to 5

Tier 3: Systems Programming

Memory Management

size alloc         - Allocate memory: n → ptr
ptr free           - Free memory
ptr @ peek         - Read from pointer: ptr → value
ptr value ! poke   - Write to pointer
sizeof             - Size of type: type → n

Pointers (C-inspired)

&var               - Address of variable: → ptr
ptr *              - Dereference: ptr → value
ptr n +ptr         - Pointer arithmetic: ptr n → ptr'

Example:

42 x !
&x                 # Get address of x
dup *              # Dereference: → 42
100 swap ! poke    # Write 100 to that address
x @                # x now contains 100

Type System

:i32 :i64 :f32 :f64    - Numeric types
:bool :char             - Basic types
:ptr                    - Pointer type
[ type ] :array         - Array type

Example with type annotations:

[ x:i32 y:i32 | x @ y @ + ]:i32 add :

Foreign Function Interface

"lib.so" import-lib
[ arg-types... ] ret-type "func_name" foreign

Example:

"libc.so.6" import-lib
[ :ptr ] :i32 "strlen" foreign strlen-ffi :

"hello" strlen-ffi      # Call C strlen

Concurrency

[ body ] spawn         - Spawn thread: → thread-id
thread-id join         - Wait for thread
value channel.send     - Send to channel
channel.recv           - Receive from channel: → value
lock.acquire
lock.release

Example:

[ 1 100 range [ . ] each ] spawn worker !
worker @ join

System Calls

:read :write :open :close syscall

Complete Example Program

# Fibonacci sequence generator (Tier 2)

[ n |
  n @ 0 =
  [ 0 ]
  [ n @ 1 =
    [ 1 ]
    [ n @ 1 - fib n @ 2 - fib + ]
    ifelse
  ]
  ifelse
] fib :

# Calculate and print first 10 Fibonacci numbers
10 [ 
  dup fib print 
] each

# Array operations (Uiua-style)
[1 2 3 4 5] 
[ dup * ] each           # Square each: [1 4 9 16 25]
0 [ + ] reduce           # Sum: 55
print

Syntax Summary

Key Principles

  1. Postfix everywhere: All operators come after operands
  2. Stack-based: Implicit stack for data flow
  3. Brackets for grouping: [ ] for code blocks and arrays
  4. Sigils for operations: ! for store, @ for load, . for field access
  5. Natural composition: Functions compose left-to-right

Operator Precedence

None! Being postfix eliminates precedence issues. Evaluation is strictly left-to-right, consuming operands from the stack.


Implementation Notes

  • Tier 1 can be implemented as a simple stack-based interpreter
  • Tier 2 requires a symbol table for functions and array support
  • Tier 3 needs memory management, type checking, and possibly compilation

The tier system allows learners to master concepts progressively while enabling systems programming when needed.