YREA-SLS/stack_lang_spec (0.2).md

15 KiB

Stack Language Specification v0.2

1. Overview

A statically-typed, stack-based language with pure postfix notation combining the execution model of HP's RPL, the type system of C and Rust, and modern array operations from Uiua.

Design Principles

  • Everything is postfix - no exceptions
  • Stack-based execution (no local variables)
  • Static typing with type inference
  • Manual heap memory management
  • Types define what things are, traits define how things act
  • All constructs are implicitly generic

2. Lexical Structure

2.1 Comments

// Single-line comment

2.2 Identifiers

  • Start with letter or underscore: [a-zA-Z_][a-zA-Z0-9_]*
  • Case-sensitive

2.3 Literals

Integer Literals

42          // i32 (default)
42 i64      // Annotate as i64
0xFF        // hexadecimal
0b1010      // binary

Floating Point Literals

3.14        // f64 (default)
3.14 f32    // Annotate as f32

String Literals

"hello world"
"escape sequences: \n \t \\ \""

Boolean Literals

true
false

Array Literals

[1 2 3 4 5]              // array of i32
[1.0 2.0 3.0]            // array of f64
[[1 2] [3 4]]            // 2D array

3. Type System

3.1 Primitive Types

  • i8, i16, i32, i64 - Signed integers
  • u8, u16, u32, u64 - Unsigned integers
  • f32, f64 - Floating point
  • bool - Boolean
  • char - Single character (UTF-8)
  • ptr - Raw pointer (generic over pointed type)

3.2 Types vs Traits

Types define the concrete structure and memory layout:

Point struct              // Point is a type
Rectangle struct          // Rectangle is a type

Traits define behavioral contracts - how things act:

Drawable trait            // Drawable is a trait
Addable trait            // Addable is a trait

Key Distinction:

  • A value has a type (what it is structurally)
  • A value implements a trait (how it behaves)
  • Types are concrete; traits are interfaces
  • Functions can be generic over both types and traits

3.3 All Constructs are Generic

Every function, struct, and union is implicitly generic. Constraints are specified via traits:

// Function generic over any type T
(T -- T) { dup * } square fn

// Function requiring T to implement Addable trait
(T T -- T) Addable { + } add_two fn

// Struct generic over field types
(T T --) { x: y: } Point struct

// Union generic over variant types
(T --) { Some(T) None } Option union

4. Stack Operations

4.1 Stack Manipulation

dup         // ( a -- a a ) Duplicate top
drop        // ( a -- ) Remove top
swap        // ( a b -- b a ) Swap top two
over        // ( a b -- a b a ) Copy second to top
rot         // ( a b c -- b c a ) Rotate three items
-rot        // ( a b c -- c a b ) Rotate three items reverse
2dup        // ( a b -- a b a b ) Duplicate top two
2drop       // ( a b -- ) Drop top two
nip         // ( a b -- b ) Drop second
tuck        // ( a b -- b a b ) Copy top below second

4.2 Stack Inspection

depth       // ( -- n ) Push stack depth
pick        // ( n -- x ) Copy nth item to top (0 = top)
roll        // ( n -- ) Move nth item to top

5. Operators (Postfix)

5.1 Arithmetic

3 4 +       // ( a b -- result ) Addition
10 3 -      // Subtraction
5 6 *       // Multiplication
20 4 /      // Division
17 5 %      // Modulo
2 8 **      // Exponentiation

5.2 Comparison

5 3 >       // Greater than
5 3 >=      // Greater or equal
5 3 <       // Less than
5 3 <=      // Less or equal
5 5 ==      // Equal
5 3 !=      // Not equal

5.3 Logical

true false and    // Logical AND
true false or     // Logical OR
true not          // Logical NOT

5.4 Bitwise

0xFF 0x0F bitand     // Bitwise AND
0xFF 0x0F bitor      // Bitwise OR
0xFF 0x0F bitxor     // Bitwise XOR
0xFF bitnot          // Bitwise NOT
8 2 shl              // Left shift
8 2 shr              // Right shift

6. Functions (Postfix Definition)

Functions are defined in postfix notation. The signature and body come before the name.

6.1 Basic Function Definition

Syntax: (inputs -- outputs) { body } name fn

// Define a square function
(i32 -- i32) { dup * } square fn

// Use it
5 square      // 25

// Multiple inputs and outputs
(i32 i32 -- i32 i32) {
    2dup / -rot %
} divmod fn

10 3 divmod   // 3 1 (quotient remainder)

6.2 Generic Functions with Trait Constraints

Syntax: (type_sig) trait_constraints { body } name fn

// Generic identity - works with any type
(T -- T) {} identity fn

// Requires T to be copyable
(T T -- T) Addable {
    +
} add_values fn

// Multiple trait constraints
(T U -- U T) Copyable Swappable {
    swap
} swap_generic fn

// Multiple type parameters with different traits
(T U -- T) Addable Numeric {
    dup U as +
} add_converted fn

6.3 Function Examples

// No-op function
(-- ) {} noop fn

// Factorial (recursive)
(i32 -- i32) {
    dup 1 { drop 1 } { dup 1 - factorial * } <= if
} factorial fn

// Constrained generic
(T -- T) Numeric {
    dup 0 > { } { 0 T as - } if
} abs fn

7. Control Flow (Postfix)

7.1 Conditionals

Syntax: condition { then-block } { else-block } if

// if-then (else block is empty)
x 0 > { "positive" print } {} if

// if-then-else
x 0 > 
    { "positive" print } 
    { "non-positive" print } 
if

// The condition comes first, then both blocks, then 'if'
a b > 
    { a } 
    { b } 
if max set

// Nested
x 0 >
    {
        y 0 >
            { "both positive" print }
            { "x positive, y not" print }
        if
    }
    { "x not positive" print }
if

7.2 Loops

While Loop

Syntax: { condition-block } { body-block } while

// Sum 1 to 10
0 1                              // sum counter
    { dup 10 <= }                // condition block
    {                            // body block
        2dup +                   // Add counter to sum
        swap 1 + swap            // Increment counter
    }
while
drop                             // Drop counter, leave sum

// Infinite loop with break
{ true } {
    // body
    condition { break } {} if
} while

For Loop

Syntax: start end { body-with-counter } for

// The loop variable is implicitly pushed to stack in each iteration
1 10 { 
    // Stack has loop counter on top
    dup print
} for

// More complex
1 100 {
    dup fizzbuzz
} for

7.3 Loop Control

break       // Exit loop
continue    // Skip to next iteration

7.4 Match/Pattern Matching

Syntax: value { pattern => block ... } match

value {
    Some(x) => { x print }
    None => { "Nothing" print }
} match

// With multiple patterns
status {
    Pending => { "Waiting" print }
    Active => { "Running" print }
    Complete => { "Done" print }
} match

8. Data Structures (Postfix)

8.1 Struct Definition

Syntax: (field_types -- ) { field_names } name struct

// Define Point struct - generic over coordinate types
(T T --) { x: y: } Point struct

// Use with specific types
3.0 4.0 Point       // Creates Point with f64 fields
3 4 Point           // Creates Point with i32 fields

// More complex struct
(T U V --) { 
    width: 
    height: 
    depth: 
} Box3D struct

10.0 20.0 30.0 Box3D

8.2 Struct Field Access

Syntax (postfix): struct field get or struct value field set

point x get         // Get x field
point 15.0 x set    // Set x field to 15.0

// Chaining
point x get 2 * y get +     // (point.x * 2) + point.y

8.3 Union Definition

Syntax: (variant_types -- ) { variants } name union

// Option type - generic over T
(T --) { 
    Some(T) 
    None 
} Option union

// Result type - generic over T and E
(T E --) { 
    Ok(T) 
    Err(E) 
} Result union

// Create union values
42 Some             // Creates Option::Some(42)
None                // Creates Option::None
"success" Ok        // Creates Result::Ok("success")
"error" Err         // Creates Result::Err("error")

8.4 Enum Definition

Syntax: () { variants } name enum

() { 
    Pending 
    Active 
    Complete 
} Status enum

// Usage
Pending             // Creates Status::Pending
Active              // Creates Status::Active

9. Traits (Postfix)

9.1 Trait Definition

Syntax: { function_signatures } name trait

// Simple trait
{
    (Self -- ) draw:
} Drawable trait

// Trait with multiple methods
{
    (Self Self -- Self) add:
    (Self Self -- Self) sub:
    (Self -- Self) neg:
} Numeric trait

// Generic trait
{
    (Self T -- Self) append:
    (Self -- T) pop:
} Container trait

9.2 Trait Implementation

Syntax: type { method_implementations } trait impl

// Implement Drawable for Rectangle
Rectangle {
    (Rectangle -- ) {
        "Drawing rectangle" print
        dup width get print
        height get print
    } draw:
} Drawable impl

// Implement Numeric for Point
Point {
    (Point Point -- Point) {
        over x get over x get + 
        -rot y get swap y get +
        Point
    } add:
    
    (Point Point -- Point) {
        over x get over x get - 
        -rot y get swap y get -
        Point
    } sub:
    
    (Point -- Point) {
        dup x get 0 swap - x set
        dup y get 0 swap - y set
    } neg:
} Numeric impl

9.3 Using Traits in Functions

// Function requiring Drawable trait
(T -- ) Drawable {
    draw
} draw_twice fn

// Multiple trait requirements
(T -- T) Numeric Copyable {
    dup abs swap dup * +
} complex_calc fn

10. Memory Management (Postfix)

10.1 Heap Operations

// Allocate
3.0 4.0 Point alloc     // ( Point -- ptr<Point> )

// Dereference
ptr deref               // ( ptr<T> -- T )

// Store (dereference and update)
new_value ptr store     // ( T ptr<T> -- )

// Free
ptr free                // ( ptr<T> -- )

10.2 Example

// Create heap-allocated point
3.0 4.0 Point alloc     // Returns ptr<Point>
dup x get print         // Dereference and print x
free                    // Clean up

11. Array Operations (Postfix)

11.1 Basic Array Operations

// Creation
1 10 range              // Create range array [1..10]

// Shape operations
arr shape               // Get shape
arr 2 3 reshape         // Reshape to 2x3

// Element access
arr 2 at                // Index access
arr 1 3 slice           // Slice array

11.2 Array Combinators

// Map - apply function to each element
[1 2 3 4] { 2 * } map        // [2 4 6 8]

// Filter - keep elements matching predicate
[1 2 3 4 5] { 2 % 0 == } filter   // [2 4]

// Reduce - fold with function
[1 2 3 4] 0 { + } reduce     // 10

// Each - apply to each element (side effects)
[[1 2] [3 4]] { sum print } each

11.3 Array Arithmetic

[1 2 3] [4 5 6] +.      // Element-wise add: [5 7 9]
[1 2 3] [4 5 6] *.      // Element-wise multiply: [4 10 18]
[1 2 3] 2 *.            // Scalar multiply: [2 4 6]

11.4 Array Manipulation

[1 2 3] [4 5 6] concat  // Concatenate: [1 2 3 4 5 6]
[1 2 3] reverse         // [3 2 1]
[[1 2] [3 4]] transpose // [[1 3] [2 4]]
[1 2 3 4] 2 window      // [[1 2] [2 3] [3 4]]

12. Eval Operator (Postfix)

Execute code dynamically at runtime.

// Evaluate string as code
"2 3 +" eval            // Pushes 5

// Build and execute code
"(i32 -- i32) { dup * } square fn" eval
5 square                // 25

// Dynamic dispatch
operation_name " get" concat eval

13. Standard Library Concepts

13.1 I/O

"Hello" print           // Print to stdout
"Enter name: " input    // Read from stdin
"file.txt" read         // Read file contents
"data" "file.txt" write // Write to file

13.2 String Operations

"hello" " world" concat     // Concatenate: "hello world"
"hello" length              // 5
"hello" 1 3 substr          // "el"
"a,b,c" "," split           // ["a" "b" "c"]
["a" "b"] "," join          // "a,b"

13.3 Type Conversion

42 f64 as               // Convert i32 to f64
"123" i32 parse         // Parse string to i32
3.14 str as             // Convert to string

14. Complete Examples

14.1 Factorial

(i32 -- i32) {
    dup 1 
        { drop 1 } 
        { dup 1 - factorial * } 
    <= if
} factorial fn

5 factorial print       // 120

14.2 FizzBuzz

(i32 -- ) {
    dup 15 % 0 ==
        { drop "FizzBuzz" print }
        {
            dup 3 % 0 ==
                { drop "Fizz" print }
                {
                    dup 5 % 0 ==
                        { drop "Buzz" print }
                        { print }
                    if
                }
            if
        }
    if
} fizzbuzz fn

1 100 { fizzbuzz } for

14.3 Point with Traits

// Define Point struct
(T T --) { x: y: } Point struct

// Define Drawable trait
{ (Self -- ) draw: } Drawable trait

// Implement Drawable for Point
Point {
    (Point -- ) {
        "Point(" print
        dup x get print
        ", " print
        y get print
        ")" print
    } draw:
} Drawable impl

// Define distance function (requires Numeric)
(T T -- T) Numeric {
    over x get over x get - dup *
    swap y get swap y get - dup *
    + sqrt
} distance fn

// Usage
3.0 4.0 Point
5.0 12.0 Point
distance print          // 13.0

14.4 Generic Container

// Define a generic stack container
(T --) { 
    items: 
    size: 
} Stack struct

// Push function
(Stack T -- Stack) {
    over items get swap concat
    over size get 1 +
    Stack
} stack_push fn

// Pop function (returns Stack and popped value)
(Stack -- Stack T) {
    dup items get
    dup length 1 -
    over length 1 - at      // Get last item
    -rot 0 swap 1 - slice   // Remove last item
    over size get 1 -
    Stack
    swap
} stack_pop fn

// Usage
[] 0 Stack              // Empty stack
42 stack_push
100 stack_push
stack_pop drop          // Pop and discard value

14.5 Array Processing

// Sum of squares of even numbers from 1 to 10
[1 2 3 4 5 6 7 8 9 10]
    { 2 % 0 == } filter     // Keep even numbers
    { dup * } map           // Square each
    0 { + } reduce          // Sum
print                       // 220

// More complex: find max of absolute differences
[1 5 2 8 3]
[2 3 7 4 6]
    { - abs } map2          // Element-wise abs difference
    0 { max } reduce        // Find maximum
print                       // 4

14.6 Result Type Usage

// Define Result union
(T E --) { Ok(T) Err(E) } Result union

// Function that returns Result
(i32 i32 -- Result) {
    dup 0 ==
        { drop "Division by zero" Err }
        { / Ok }
    if
} safe_div fn

// Use it
10 2 safe_div {
    Ok(x) => { x print }
    Err(e) => { "Error: " print e print }
} match

15. Syntax Summary

Complete Grammar Patterns

Functions: (in -- out) constraints { body } name fn

Structs: (types -- ) { fields: } name struct

Unions: (types -- ) { Variant(T) ... } name union

Enums: () { Variant ... } name enum

Traits: { (sig) method: ... } name trait

Trait Impl: Type { (sig) { body } method: ... } Trait impl

If: condition { then } { else } if

While: { condition } { body } while

For: start end { body } for

Match: value { pattern => block ... } match


Version: 0.2
Status: Draft Specification - Pure Postfix Edition