YREA-SLS/stack_lang_spec (0.1).md

11 KiB

Stack Language Specification v0.1

1. Overview

A statically-typed, stack-based language with 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

  • All operations are postfix (RPN)
  • Stack-based execution (no local variables)
  • Static typing with type inference
  • Manual heap memory management
  • C-like syntax style adapted to postfix notation
  • Functions manipulate the stack directly

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)
42i64       // i64
0xFF        // hexadecimal
0b1010      // binary

Floating Point Literals

3.14        // f64 (default)
3.14f32     // 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<T> - Raw pointer to type T

3.2 Compound Types

Arrays

[T; N]      // Fixed-size array
[T]         // Dynamic array (heap-allocated)

Structs

struct Point {
    x: f64,
    y: f64,
}

Tagged Unions

union Result<T, E> {
    Ok(T),
    Err(E),
}

3.3 Type Inference

Types are inferred where possible but can be explicitly annotated:

42 :i64            // Annotate literal
x get :f32         // Annotate stack value

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 &&    // Logical AND
true false ||    // Logical OR
true !           // Logical NOT

5.4 Bitwise

0xFF 0x0F &      // Bitwise AND
0xFF 0x0F |      // Bitwise OR
0xFF 0x0F ^      // Bitwise XOR
0xFF ~           // Bitwise NOT
8 2 <<           // Left shift
8 2 >>           // Right shift

6. Functions

Functions consume arguments from the stack and push results to the stack.

6.1 Function Definition

fn add_point : (Point Point -- Point) {
    // Stack: p1 p2
    swap .x get     // p2.x
    swap .x get     // p1.x
    +               // sum_x
    
    swap .y get     // p2.y
    swap .y get     // p1.y
    +               // sum_y
    
    Point::new      // Create new Point
}

6.2 Function Signature

Format: (input_types -- output_types)

fn square : (i32 -- i32) {
    dup *
}

fn divmod : (i32 i32 -- i32 i32) {
    2dup / -rot %
}

fn no_op : (-- ) {
    // Takes nothing, returns nothing
}

6.3 Generic Functions

fn identity<T> : (T -- T) {
    // Simply returns the input
}

fn swap_pair<T, U> : (T U -- U T) {
    swap
}

7. Control Flow

7.1 Conditionals

// if-then
condition if {
    // Executed if true
}

// if-then-else
x 0 > if {
    // Positive
} else {
    // Non-positive
}

7.2 Loops

While Loop

// While condition is true
{ condition } while {
    // Loop body
}

// Example: sum 1 to 10
0 1                     // sum counter
{ dup 10 <= } while {
    2dup +              // Add counter to sum
    swap 1 + swap       // Increment counter
}
drop                    // Drop counter, leave sum

For Loop (Range-based)

1 10 for i {
    i print
}

// Equivalent to:
1 10 range each { print }

7.3 Loop Control

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

8. Memory Management

8.1 Stack vs Heap

  • Stack: Automatic, fixed-size types
  • Heap: Manual, dynamic allocations

8.2 Heap Operations

// Allocate
Point::new heap_alloc   // ( Point -- ptr<Point> )

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

// Store
value ptr !             // ( T ptr<T> -- )

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

8.3 Example

// Create heap-allocated point
3.0 4.0 Point::new heap_alloc   // ptr<Point>
dup .x get print                // Print x (3.0)
free                            // Clean up

9. Data Structures

9.1 Struct Definition and Usage

struct Rectangle {
    width: f64,
    height: f64,
}

// Constructor (auto-generated)
10.0 20.0 Rectangle::new    // Create Rectangle

// Field access (postfix)
rect .width get             // Get width
rect .width 15.0 set        // Set width

// Method-like functions
fn Rectangle::area : (Rectangle -- f64) {
    dup .width get
    swap .height get
    *
}

// Usage
rect Rectangle::area        // Calculate area

9.2 Tagged Unions

union Option<T> {
    Some(T),
    None,
}

// Construction
42 Option::Some             // Create Some(42)
Option::None                // Create None

// Pattern matching
value match {
    Some(x) => {
        x print
    },
    None => {
        "Nothing" print
    },
}

9.3 Enums

enum Status {
    Pending,
    Active,
    Complete,
}

Status::Active              // Create enum value

10. Traits

Traits define shared behavior across types.

10.1 Trait Definition

trait Drawable {
    fn draw : (Self -- );
}

trait Add<T> {
    fn add : (Self T -- Self);
}

10.2 Trait Implementation

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

impl Add<Point> for Point {
    fn add : (Point Point -- Point) {
        // Implementation from earlier
        swap .x get swap .x get + 
        swap .y get swap .y get +
        Point::new
    }
}

10.3 Trait Bounds

fn draw_twice<T: Drawable> : (T -- ) {
    dup draw
    draw
}

11. Array Operations (Uiua-inspired)

11.1 Basic Array Operations

// Creation
[1 2 3 4 5] range       // Create range array

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

// Element access
arr 2 @                  // Index access
arr [1 3] slice          // Slice array

11.2 Array Combinators

// Map
[1 2 3 4] { 2 * } map        // [2 4 6 8]

// Filter
[1 2 3 4 5] { 2 % 0 == } filter   // [2 4]

// Reduce
[1 2 3 4] 0 { + } reduce     // 10

// Each (apply to each element)
[[1 2] [3 4]] { sum } each   // [3 7]

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] ++      // 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

Execute code dynamically at runtime.

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

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

// Dynamic dispatch
operation_name " get" ++ eval  // Call function by name

Security Note: Eval should be used carefully as it can execute arbitrary code.

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" ++     // 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 to_f64               // Convert i32 to f64
"123" parse_i32         // Parse string to i32
3.14 to_string          // Convert to string

14. Example Programs

14.1 Factorial

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

5 factorial print       // 120

14.2 FizzBuzz

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

1 100 for i {
    i fizzbuzz
}

14.3 Using Structs and Traits

struct Circle {
    radius: f64,
}

impl Drawable for Circle {
    fn draw : (Circle -- ) {
        "Circle with radius: " print
        .radius get print
    }
}

fn Circle::area : (Circle -- f64) {
    .radius get
    2.0 **
    3.14159 *
}

// Usage
5.0 Circle::new
dup draw                // Draw the circle
Circle::area print      // Print area

14.4 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

15. Implementation Notes

15.1 Type Checking

  • Perform static type checking with full type inference
  • Track stack types at compile time
  • Ensure function signatures match actual stack effects

15.2 Interpreter Design

  • Value stack: runtime execution stack
  • Type stack: compile-time type tracking
  • Call stack: function call management
  • Heap: global allocator

15.3 Future Compilation

  • Compile to bytecode for interpretation
  • Potential LLVM backend for native compilation
  • Stack optimization for register allocation

16. Syntax Summary

Stack Manipulation

dup drop swap over rot pick roll

Arithmetic (postfix)

a b +  a b -  a b *  a b /  a b %  a b **

Comparison

a b <  a b >  a b <=  a b >=  a b ==  a b !=

Control Flow

cond if { ... }
cond if { ... } else { ... }
{ cond } while { ... }
start end for var { ... }

Functions

fn name : (inputs -- outputs) { body }
fn name<T, U> : (T U -- U) { body }

Memory

value heap_alloc  ptr @  value ptr !  ptr free

Arrays

[1 2 3]
arr { fn } map
arr { fn } filter
arr init { fn } reduce

Version: 0.1
Status: Draft Specification
License: Define your license here