1132 lines
32 KiB
Markdown
1132 lines
32 KiB
Markdown
# Stack Language Specification
|
|
|
|
**Version**: 0.5.1
|
|
**Status**: Draft Specification
|
|
**Changes**:
|
|
- 0.5 (AI)
|
|
1. **Escape sequences** - Added a complete list of escape sequences for string literals
|
|
2. **Type Tuples** - Defined them as function signatures representing stack effects
|
|
3. **Control flow TokenStrings** - Clarified that `if`, `while`, `match`, etc. use TokenStrings
|
|
4. **Generic constructs** - Clarified that generics need trait constraints when operations are performed
|
|
5. **Stack manipulation traits** - Combined into a single `Stackable` trait
|
|
6. **Size trait** - Added proper definition inheriting from `Addable`, `Comparable`, and `Convertible`
|
|
7. **Empty traits** - Clarified that traits can be empty (especially when used with inheritance)
|
|
8. **Trait inheritance** - Fixed syntax to require both `inher` and `trait` declarations
|
|
9. **Array combinators** - Clarified that the functions inside parse their TokenStrings
|
|
10. **`::` in TokenStrings** - Clarified it should NOT be used in trait/impl contexts
|
|
- 0.5.1 (Human)
|
|
1. Created TODOs
|
|
2. Made various corrections (not everything was corrected)
|
|
3. Reviewed and corrected some code blocks
|
|
4. Made a few adjustments manually
|
|
|
|
> **INSTRUCTIONS FOR AI:** AI agents are not allowed to change human reviewed md code blocks. If an AI reviewer thinks a change needs to be made to one of these blocks, the AI model can add a human todo explaining a suggested change or problem. It is totally possible for a md code block that was human reviewed and be correct for the current specification and new TODOs would change it, AIs are still not allowed to change it, only add a human todo. Reviewed md code blocks could also implement new TODOs already.
|
|
> **TODO:** All built-in operators should also include a natural language discription of what they do.
|
|
> **TODO:** Clarify that operators implement a trait, functions do not. Operators and functions cannot have the same name, if a name belongs to a function, it can not be used again for any operators.
|
|
> **TODO:** The `<>` is valid syntax for generic traits.
|
|
> **TODO:** Traits that inherit from a generic trait must also be similarly generic or specify the trait used by the generic trait.
|
|
> **TODO:** There are code blocks that use only parts from actual parts of the language while others include example code. Specify what are actual definitions, and which are examples (including actual definitions reused as examples).
|
|
> **TODO:** All built in operators should have their traits define in natural language and as possible in code. There should be appendix containing the whole of all of these traits.
|
|
|
|
> **INSTRUCTIONS FOR AI:** Current human todos have been repeated here for reference.
|
|
> **TODO: (FOR HUMAN)** How to identify an unspecified number of arguments? ie. the `(` *(What goes here?)* ` -- Size) depth:` operator actually accepts the entire stack, or a possible `(String ` *(What goes here?)* ` --) printf:` function that accepts multiple arguments after the string.
|
|
> **TODO: (FOR HUMAN)** Do all inheritances need to be define before the trait is?
|
|
> **TODO: (FOR HUMAN)** Is the `inher` operator required?
|
|
> **TODO: (FOR HUMAN)** Consider removing `inher` and replace it by just using `impl`. Would that be enough to replace it?
|
|
|
|
---
|
|
|
|
## 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
|
|
- Every operator is defined by a trait
|
|
|
|
## 2. Lexical Structure
|
|
|
|
### 2.1 Comments
|
|
```
|
|
// Single-line comment
|
|
```
|
|
|
|
### 2.2 Identifiers
|
|
|
|
**Regular Identifiers**
|
|
- Start with letter or underscore: `[a-zA-Z_][a-zA-Z0-9_]*`
|
|
- Case-sensitive
|
|
- When encountered, identifiers are executed immediately
|
|
|
|
**Identifier Literals**
|
|
- Prefix with `::` to push the identifier itself onto the stack instead of executing it
|
|
- Syntax: `::name` pushes the identifier `name` as a value
|
|
- Example: `::Addable` pushes the identifier `Addable` onto the stack
|
|
- Example: `::Point` pushes the identifier `Point` onto the stack
|
|
|
|
### 2.3 Literals
|
|
|
|
**Integer Literals**
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
42 // i64 (default)
|
|
42:i32 // Annotate as i32
|
|
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 \\ \""
|
|
```
|
|
|
|
**Escape Sequences**
|
|
- `\n` - Newline (LF)
|
|
- `\r` - Carriage return (CR)
|
|
- `\t` - Tab
|
|
- `\\` - Backslash
|
|
- `\"` - Double quote
|
|
- `\'` - Single quote
|
|
- `\0` - Null character
|
|
- `\xNN` - Hexadecimal byte (e.g., `\x41` for 'A')
|
|
- `\u{NNNN}` - Unicode code point (e.g., `\u{1F600}` for 😀)
|
|
|
|
**Boolean Literals**
|
|
```
|
|
true
|
|
false
|
|
```
|
|
|
|
**Array Literals**
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
[1 2 3 4 5] // array of i32
|
|
[1.0 2.0 3.0] // array of f64
|
|
[[1 2] [3 4]] // 2D array
|
|
```
|
|
|
|
**Type Tuples**
|
|
```
|
|
(T T -- T) // Function signature: two inputs of type T, one output of type T
|
|
(i32 f64 -- String) // Takes i32 and f64, returns String
|
|
(-- bool) // No inputs, returns bool
|
|
(Point --) // Takes Point, no outputs
|
|
```
|
|
|
|
> **TODO: (FOR HUMAN)** How to identify an unspecified number of arguments? ie. the `(` *(What goes here?)* ` -- Size) depth:` operator actually accepts the entire stack, or a possible `(String ` *(What goes here?)* ` --) printf:` function that accepts multiple arguments after the string.
|
|
|
|
Type tuples represent stack effects and are used in function signatures to specify what a function consumes from and produces to the stack.
|
|
|
|
**Token Strings**
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
{ code here } // TokenString - lexed but not parsed/executed
|
|
```
|
|
|
|
> **TODO:** `::` *is required* for identifier literals in code blocks. `::` *is not allowed* for trait definitions and implementations.
|
|
> **TODO:** List all of the control flow operators that use token strings.
|
|
> **TODO:** List what each operator causes the toekn strings to be parsed as. Function and eval token strings are parsed as code blocks.
|
|
> **TODO:** Add a `lambda` operator that parses a token string into a code block that can be used in place of a token string where ever they are parsed as a code block.
|
|
|
|
Token strings contain lexed tokens that are not parsed or executed until an operator causes them to be:
|
|
- `trait` operator parses the TokenString as a trait definition
|
|
- `fn` operator parses the TokenString as a function definition
|
|
- `impl` operator parses the TokenString as a trait implementation
|
|
- `eval` operator parses and executes the TokenString immediately
|
|
- Control flow operators (`if`, `while`, `match`, etc.) parse their TokenString arguments as code blocks
|
|
|
|
Within TokenStrings used for trait definitions and implementations, the `::` prefix should not be used. The context (trait definition or implementation) determines how identifiers are interpreted. For function bodies and eval contexts, `::` may be used to create identifier literals.
|
|
|
|
## 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:
|
|
- `{ ... } ::Addable trait` - Addable is a trait
|
|
- `{ ... } ::Drawable trait` - Drawable 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 traits
|
|
- Functions can have types and traits defined as return types
|
|
- Every operator must be backed by a trait
|
|
|
|
### 3.3 Generic Constructs
|
|
|
|
> **TODO:** Type parameters are currently only suggestions when parsing code blocks (see appendix).
|
|
> **TODO:** Add to appendix as a possilbe future feature that type parameters must actually constrain how operators and functions act, enforced as parse time.
|
|
|
|
Functions, structs, and unions can be generic over type parameters. Type parameters must be constrained by traits when operations are performed on them:
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
// Function generic over any type with Multiplyable constraint
|
|
(T -- T) { dup * } ::square<T:Multiplyable> fn
|
|
|
|
// Struct generic over field type T
|
|
(T T --) { x: y: } ::Point<T> struct
|
|
|
|
// Union generic over variant type T
|
|
(T --) { Some(T) None } ::Option<T> union
|
|
```
|
|
|
|
**Important**: Unconstrained generic functions (those that don't perform operations on their type parameters) can omit trait constraints.
|
|
|
|
```
|
|
// Generic identity - works with any type (no operations performed)
|
|
(--) { } ::identity fn
|
|
```
|
|
|
|
## 4. Trait System
|
|
|
|
### 4.1 Standard Traits
|
|
|
|
Traits define behavioral contracts. Every operator in the language is backed by one or more traits.
|
|
|
|
**Stack Manipulation Trait**
|
|
```
|
|
{
|
|
(Self -- Self Self) dup:
|
|
(Self -- ) drop:
|
|
(Self Self -- Self Self) swap:
|
|
(Self Self -- Self Self Self) over:
|
|
(Self Self Self -- Self Self Self) rot:
|
|
(Size -- Self) pick:
|
|
(Size Size -- ) roll:
|
|
(-- Size) depth:
|
|
} ::Stackable trait
|
|
```
|
|
|
|
**Size Trait**
|
|
|
|
The `Size` trait represents types suitable for indexing and sizing operations:
|
|
|
|
```
|
|
[ ::Addable ::Comparable ::Convertible ] ::Size inher
|
|
{ } ::Size trait
|
|
```
|
|
|
|
Types implementing `Size` can be used as indices, loop bounds, and array sizes. Standard implementations include all integer types (`i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`).
|
|
|
|
**Arithmetic Traits**
|
|
```
|
|
{ (Self Self -- Self) +: (Self Self -- Self) -: } ::Addable trait
|
|
|
|
{ (Self Self -- Self) *: (Self Self -- Self) /: (Self Self -- Self) %: } ::Multiplyable trait
|
|
|
|
{ (Self Self -- Self) ^: } ::Exponentiable trait
|
|
|
|
{ (Self Self -- Self) logb: (Self -- Self) log: (Self -- Self) ln: } ::Logarithmic trait
|
|
```
|
|
|
|
**Comparison Traits**
|
|
```
|
|
{ (Self Self -- bool) >: (Self Self -- bool) >=: (Self Self -- bool) <: (Self Self -- bool) <=: } ::Orderable trait
|
|
|
|
{ (Self Self -- bool) ==: (Self Self -- bool) !=: } ::Equatable trait
|
|
|
|
// Comparable combines ordering and equality
|
|
[ ::Orderable ::Equatable ] ::Comparable inher
|
|
{ } ::Comparable trait
|
|
```
|
|
|
|
**Logical Operations Traits**
|
|
```
|
|
{ (Self -- bool) truthy: (Self Self -- Self) and: (Self Self -- Self) or: (Self -- Self) not: } ::Logical trait
|
|
```
|
|
|
|
**Bitwise Operations Traits**
|
|
```
|
|
{ (Self Self -- Self) bitand: (Self Self -- Self) bitor: (Self Self -- Self) bitxor: (Self -- Self) bitnot: (Self Size -- Self) shl: (Self Size -- Self) shr: } ::Bitwise trait
|
|
```
|
|
|
|
**Container Traits**
|
|
```
|
|
{ (Self -- i64) length: } ::Sized trait
|
|
|
|
{ (Self Size -- T) at: } ::Selectable trait
|
|
|
|
{ (Self Self -- Self) concat: } ::Concatenable trait
|
|
|
|
{ (Self Size Size -- Self) slice: } ::Sliceable trait
|
|
|
|
[ ::Sized ::Selectable ::Sliceable ] ::ArrayOf inher
|
|
{ } ::ArrayOf trait
|
|
```
|
|
|
|
**String Traits**
|
|
```
|
|
[ ::Concatenable ] ::String inher
|
|
{ (Self Size Size -- Self) substr: (Self Self -- ArrayOf) split: } ::String trait
|
|
```
|
|
|
|
**Conversion Traits**
|
|
```
|
|
{ (Self Type -- T) as: } ::Convertible trait
|
|
|
|
{ (Self -- String) str: } ::Stringifiable trait
|
|
|
|
{ (String -- Self) parse: } ::Parseable trait
|
|
```
|
|
|
|
> **TODO:** Change type conversions to: explicit conversion functions: 42 to_f64.
|
|
|
|
**Numeric Composite Trait**
|
|
|
|
The `Number` trait represents the full suite of numeric operations by inheriting from multiple traits:
|
|
|
|
```
|
|
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
|
|
{ } ::Number trait
|
|
```
|
|
|
|
**Meta-Traits**
|
|
|
|
Traits for defining and working with traits themselves:
|
|
|
|
```
|
|
{ } ::Identifier trait
|
|
|
|
{ (TokenString Identifier --) trait: (Identifier TokenString Identifier --) impl: (ArrayOf<Identifier> --) inher: } ::Implementable trait
|
|
```
|
|
|
|
### 4.2 Trait Definition
|
|
|
|
**Syntax**: `{ function_signatures } ::identifier trait`
|
|
|
|
Traits can be defined with or without method signatures. Empty traits are valid and are typically used when inheriting from other traits to create composite traits.
|
|
|
|
```
|
|
// Trait with methods
|
|
{
|
|
(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
|
|
|
|
// Empty trait (typically used with inheritance)
|
|
{ } ::Printable trait
|
|
```
|
|
|
|
Within the TokenString (the `{ }` block), identifiers like `Self`, `add:`, `draw:` are part of the trait definition syntax and should not use the `::` prefix.
|
|
|
|
### 4.3 Trait Implementation
|
|
|
|
> **TODO:** Implementing a trait for itself, implements the trait for everything.
|
|
> **TODO:** A trait must be defined before it can be implemented for types or traits.
|
|
> **TODO:** It is not required for all operators of a trait being implemented to all be in the same implementation block.
|
|
|
|
**Syntax**: `::trait_identifier { method_implementations } ::type_or_trait_identifier impl`
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
// Implement Addable for i32
|
|
::Addable {
|
|
(Self Self -- Self) {
|
|
// Native addition implementation
|
|
} +:
|
|
|
|
(Self Self -- Self) {
|
|
// Native subtraction implementation
|
|
} -:
|
|
} ::i32 impl
|
|
|
|
// Implement Drawable for Rectangle
|
|
::Drawable {
|
|
(Self -- ) {
|
|
"Drawing rectangle" print
|
|
dup ::width get print
|
|
::height get print
|
|
} draw:
|
|
} ::Rectangle impl
|
|
```
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
// Implement Addable for Point
|
|
::Addable {
|
|
(Self<T> Self<T> -- Self<T>) {
|
|
over ::x get over ::x get +
|
|
3 pick ::y get 3 pick ::y get +
|
|
Point
|
|
} +:
|
|
|
|
(Self<T> Addable -- Self<T>) {
|
|
over ::x get over +
|
|
3 pick ::y get 3 pick +
|
|
Point
|
|
} +:
|
|
|
|
(Addable Self<T> -- Self<T>) {
|
|
over over ::x get +
|
|
3 pick 3 pick ::y get +
|
|
Point
|
|
} +:
|
|
|
|
(Self<T> Self<T> -- Self<T>) {
|
|
over ::x get over ::x get -
|
|
3 pick ::y get 3 pick ::y get -
|
|
Point
|
|
} -:
|
|
|
|
(Self<T> Addable -- Self<T>) {
|
|
over ::x get over -
|
|
3 pick ::y get 3 pick -
|
|
Point
|
|
} -:
|
|
} ::Point<T> impl
|
|
|
|
// Implement Logical for everything
|
|
::Logical {
|
|
(Self -- bool) { true } truthy:
|
|
|
|
(Self Self -- Self) {
|
|
over truthy { } { swap } if drop
|
|
} and:
|
|
|
|
(Self Self -- Self) {
|
|
over truthy { swap } { } if drop
|
|
} or:
|
|
} ::Logical impl
|
|
|
|
// Overload Logical for bool
|
|
::Logical {
|
|
(Self -- Self) { } truthy:
|
|
} ::bool impl
|
|
|
|
// Overload Logical for Numeric
|
|
::Logical {
|
|
(Self -- bool) { 0 != } truthy:
|
|
} ::Number impl
|
|
|
|
// Overload Logical for Option
|
|
::Logical {
|
|
(Self<T> -- bool) { { Some(_) => { true } None => { false } } match } truthy:
|
|
} ::Option<T> impl
|
|
|
|
// Overload Logical for Result
|
|
::Logical {
|
|
(Self<T U> -- bool) { { Ok(_) => { true } Err(_) => { false } } match } truthy:
|
|
} ::Result<T U> impl
|
|
```
|
|
|
|
### 4.4 Trait Inheritance
|
|
|
|
**Syntax**: `[ identifier_list ] ::identifier inher { } ::identifier trait`
|
|
|
|
> **TODO: (FOR HUMAN)** Do all inheritances need to be define before the trait is?
|
|
> **TODO: (FOR HUMAN)** Is the `inher` operator required?
|
|
> **TODO: (FOR HUMAN)** Consider removing `inher` and replace it by just using `impl`. Would that be enough to replace it?
|
|
|
|
Trait inheritance must be declared before the trait definition. The inheritance declaration is followed by the trait definition itself, which may be empty if the trait only serves to combine inherited traits.
|
|
|
|
```
|
|
// Number inherits from multiple arithmetic traits
|
|
[ ::Addable ::Multiplyable ] ::BasicNumber inher
|
|
{ } ::BasicNumber trait
|
|
|
|
// Full Number inherits everything numeric
|
|
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
|
|
{ } ::Number trait
|
|
|
|
// Complex inheritance with additional methods
|
|
[ ::Drawable ::Transformable ::Collidable ] ::GameObject inher
|
|
{
|
|
(Self -- ) update:
|
|
(Self -- ) destroy:
|
|
} ::GameObject trait
|
|
|
|
// Size trait inherits and defines composite behavior
|
|
[ ::Addable ::Comparable ::Convertible ] ::Size inher
|
|
{ } ::Size trait
|
|
```
|
|
|
|
### 4.5 Using Traits in Functions
|
|
|
|
```
|
|
// Function requiring Drawable trait
|
|
(Drawable -- ) {
|
|
draw
|
|
} ::draw_twice fn
|
|
|
|
// Function requiring multiple trait bounds
|
|
(Number Number -- Number) {
|
|
dup * swap dup * + // Pythagorean: a² + b²
|
|
} ::sum_of_squares fn
|
|
```
|
|
|
|
## 5. Stack Operations
|
|
|
|
### 5.1 Stack Manipulation
|
|
|
|
All stack operations are backed by the `Stackable` trait.
|
|
|
|
```
|
|
dup // ( a -- a a ) Duplicate top [Stackable]
|
|
drop // ( a -- ) Remove top [Stackable]
|
|
swap // ( a b -- b a ) Swap top two [Stackable]
|
|
over // ( a b -- a b a ) Copy second to top [Stackable]
|
|
rot // ( a b c -- b c a ) Rotate three items [Stackable]
|
|
```
|
|
|
|
### 5.2 Stack Inspection
|
|
```
|
|
depth // ( -- n ) Push stack depth [Stackable]
|
|
pick // ( n -- x ) Copy nth item to top (0 = top) [Stackable]
|
|
roll // ( n times -- ) Rotate n items, times times [Stackable]
|
|
```
|
|
|
|
**Roll Examples:**
|
|
```
|
|
// Stack: a b c d e
|
|
3 1 roll // Rotate top 3 items once: a b d e c
|
|
3 2 roll // Rotate top 3 items twice: a b e c d
|
|
5 1 roll // Rotate all 5 items once: b c d e a
|
|
4 3 roll // Rotate top 4 items three times: a d e c b
|
|
```
|
|
|
|
## 6. Operators (Postfix)
|
|
|
|
**Every operator is backed by a trait and must be implemented for types that use it.**
|
|
|
|
### 6.1 Arithmetic
|
|
|
|
```
|
|
3 4 + // ( a b -- result ) Addition [Addable]
|
|
10 3 - // Subtraction [Addable]
|
|
5 6 * // Multiplication [Multiplyable]
|
|
20 4 / // Division [Multiplyable]
|
|
17 5 % // Modulo [Multiplyable]
|
|
2 8 ^ // Exponentiation [Exponentiable]
|
|
100 log // Log base 10 [Logarithmic]
|
|
2.718 ln // Natural logarithm [Logarithmic]
|
|
```
|
|
|
|
### 6.2 Comparison
|
|
|
|
```
|
|
5 3 > // Greater than [Orderable]
|
|
5 3 >= // Greater or equal [Orderable]
|
|
5 3 < // Less than [Orderable]
|
|
5 3 <= // Less or equal [Orderable]
|
|
5 5 == // Equal [Equatable]
|
|
5 3 != // Not equal [Equatable]
|
|
```
|
|
|
|
### 6.3 Logical
|
|
|
|
```
|
|
true false and // Logical AND [Logical]
|
|
true false or // Logical OR [Logical]
|
|
true not // Logical NOT [Logical]
|
|
```
|
|
|
|
### 6.4 Bitwise
|
|
|
|
```
|
|
0xFF 0x0F bitand // Bitwise AND [Bitwise]
|
|
0xFF 0x0F bitor // Bitwise OR [Bitwise]
|
|
0xFF 0x0F bitxor // Bitwise XOR [Bitwise]
|
|
0xFF bitnot // Bitwise NOT [Bitwise]
|
|
8 2 shl // Left shift [Bitwise]
|
|
8 2 shr // Right shift [Bitwise]
|
|
```
|
|
|
|
## 7. Functions (Postfix Definition)
|
|
|
|
Functions are defined in postfix notation. The signature and body come before the name.
|
|
|
|
### 7.1 Basic Function Definition
|
|
|
|
**Syntax**: `(inputs -- outputs) trait_constraint { body } ::name fn`
|
|
|
|
```
|
|
// Define a square function (requires Multiplyable)
|
|
(T -- T) ::Multiplyable { dup * } ::square fn
|
|
|
|
// Use it
|
|
5 square // 25
|
|
|
|
// Multiple inputs and outputs
|
|
(Number Number -- Number Number) {
|
|
over over / swap %
|
|
} ::divmod fn
|
|
|
|
10 3 divmod // 3 1 (quotient remainder)
|
|
```
|
|
|
|
### 7.2 Generic Functions with Trait Constraints
|
|
|
|
**Syntax**: `(type_sig) trait_constraint { body } ::name fn`
|
|
|
|
```
|
|
// Generic identity - works with any type (no operations, no constraint needed)
|
|
(T -- T) { } ::identity fn
|
|
|
|
// Requires Addable
|
|
(T T -- T) ::Addable {
|
|
+
|
|
} ::add_values fn
|
|
|
|
// Requires Number
|
|
(T -- T) ::Number {
|
|
dup 0 > { } { 0 swap - } if
|
|
} ::abs fn
|
|
```
|
|
|
|
## 8. Control Flow (Postfix)
|
|
|
|
### 8.1 Conditionals
|
|
|
|
**Syntax**: `condition { then-block } { else-block } if`
|
|
|
|
Control flow operators (`if`, `while`, `for`, `match`) parse their TokenString arguments as code blocks.
|
|
|
|
```
|
|
// 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
|
|
|
|
// Nested
|
|
x 0 >
|
|
{
|
|
y 0 >
|
|
{ "both positive" print }
|
|
{ "x positive, y not" print }
|
|
if
|
|
}
|
|
{ "x not positive" print }
|
|
if
|
|
```
|
|
|
|
### 8.2 Loops
|
|
|
|
**While Loop**
|
|
|
|
**Syntax**: `{ condition-block } { body-block } while`
|
|
|
|
```
|
|
// Sum 1 to 10
|
|
0 1 // sum counter
|
|
{ dup 10 <= } // condition block
|
|
{ // body block
|
|
over over + // 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
|
|
```
|
|
|
|
### 8.3 Loop Control
|
|
```
|
|
break // Exit loop
|
|
continue // Skip to next iteration
|
|
```
|
|
|
|
### 8.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
|
|
```
|
|
|
|
## 9. Data Structures (Postfix)
|
|
|
|
### 9.1 Struct Definition
|
|
|
|
**Syntax**: `(field_types -- ) { field_names } ::name struct`
|
|
|
|
> **For AI Reviewers:** The following block has been human verified to be syntactically and logically correct. **NO AI IS ALLOWED TO CHANGE THIS.** If there is a discrepancy between this block and others, follow the syntax in this block.
|
|
|
|
```
|
|
// Define Point struct - generic over coordinate types
|
|
(T T --) { x: y: } ::Point<T> struct
|
|
|
|
// Use with specific types
|
|
3.0 4.0 Point // Creates Point with f64 fields
|
|
3 4 Point // Creates Point with i64 fields
|
|
|
|
// More complex struct
|
|
(T U V --) {
|
|
width:
|
|
height:
|
|
depth:
|
|
} ::Box3D<T U V> struct
|
|
|
|
10.0 20.0 30.0 Box3D
|
|
```
|
|
|
|
### 9.2 Struct Field Access
|
|
|
|
**Syntax (postfix)**: `struct ::field get` or `struct value ::field set`
|
|
|
|
```
|
|
point dup ::x get // Get x field
|
|
point 15.0 ::x set // Set x field to 15.0
|
|
|
|
// Chaining
|
|
point dup ::x get 2 * over ::y get + // (point.x * 2) + point.y
|
|
```
|
|
|
|
### 9.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 Option::Some // Creates Option::Some(42)
|
|
Option::None // Creates Option::None
|
|
"success" Result::Ok // Creates Result::Ok("success")
|
|
"error" Result::Err // Creates Result::Err("error")
|
|
```
|
|
|
|
### 9.4 Enum Definition
|
|
|
|
**Syntax**: `{ variants } ::name enum`
|
|
|
|
```
|
|
{
|
|
Pending 1: // Normally starts at 0
|
|
Active: // Defaults to 2 (one plus the last)
|
|
Complete 0:
|
|
} ::Status enum
|
|
|
|
// Usage
|
|
Status::Pending // Creates Status::Pending
|
|
Status::Active // Creates Status::Active
|
|
```
|
|
|
|
## 10. Memory Management (Postfix)
|
|
|
|
> **TODO:** Leave out memory management for now. Move this to an appendix as a possible future feature. Include the following brainstorming in that appendix.
|
|
|
|
> Memory Management - Leave out or redo?
|
|
> Options:
|
|
>
|
|
> A) Manual (current): Keep alloc, deref, store, free
|
|
>
|
|
> Pros: Full control, predictable
|
|
> Cons: Error-prone, verbose
|
|
>
|
|
> B) Reference counting: Automatic management with rc<T> type
|
|
>
|
|
> Pros: Safer, automatic cleanup
|
|
> Cons: Runtime overhead, cycles
|
|
>
|
|
> C) Ownership system (Rust-like): Linear types, move semantics
|
|
>
|
|
> Pros: Safe, zero overhead
|
|
> Cons: Complex type system, restricts stack operations
|
|
>
|
|
> D) Arena/Region-based: Allocate in arenas, free all at once
|
|
>
|
|
> Pros: Fast, simple
|
|
> Cons: Less granular control
|
|
>
|
|
> My suggestion: Start with manual management for simplicity, but consider adding arena support later. The stack-based nature makes ownership tracking tricky.
|
|
|
|
### 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
|
|
|
|
Array combinators take TokenString arguments containing the function bodies to apply. The `if`, `while`, and other control structures inside these function bodies parse their own TokenString arguments.
|
|
|
|
```
|
|
// 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. The `eval` operator parses and executes its TokenString argument immediately.
|
|
|
|
```
|
|
// Evaluate string as code
|
|
"2 3 +" eval // Pushes 5
|
|
|
|
// Build and execute code
|
|
"(T -- T) ::Multiplyable { dup * } ::square fn" eval
|
|
5 square // 25
|
|
|
|
// Dynamic dispatch
|
|
operation_name " get" concat eval
|
|
```
|
|
|
|
## 13. Standard Library Concepts
|
|
|
|
> **TODO:** Everything is automatically in scope *for now*. Add a section to appendix for the following future solution: `::std::math::sqrt use`.
|
|
|
|
### 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
|
|
|
|
> **TODO:** Change type conversions to: explicit conversion functions: 42 to_f64.
|
|
|
|
```
|
|
42 f64 as // Convert i32 to f64
|
|
"123" i32 parse // Parse string to i32
|
|
3.14 str as // Convert to string
|
|
```
|
|
|
|
## 14. Complete Examples
|
|
|
|
> **TODO:** Move this to appendix.
|
|
|
|
### 14.1 Trait Implementation Example
|
|
|
|
```
|
|
// Define the Addable trait
|
|
{
|
|
(Self Self -- Self) +:
|
|
(Self Self -- Self) -:
|
|
} ::Addable trait
|
|
|
|
// Implement for i32
|
|
::Addable {
|
|
(Self Self -- Self) {
|
|
// Native addition
|
|
} +:
|
|
|
|
(Self Self -- Self) {
|
|
// Native subtraction
|
|
} -:
|
|
} ::i32 impl
|
|
|
|
// Implement for Point
|
|
::Addable {
|
|
(Self Self -- Self) {
|
|
over ::x get over ::x get +
|
|
swap ::y get swap ::y get +
|
|
Point
|
|
} +:
|
|
|
|
(Self Self -- Self) {
|
|
over ::x get over ::x get -
|
|
swap ::y get swap ::y get -
|
|
Point
|
|
} -:
|
|
} ::Point impl
|
|
```
|
|
|
|
### 14.2 Trait Inheritance Example
|
|
|
|
```
|
|
// Define base traits
|
|
{ (Self Self -- Self) +: (Self Self -- Self) -: } ::Addable trait
|
|
{ (Self Self -- Self) *: (Self Self -- Self) /: } ::Multiplyable trait
|
|
{ (Self Self -- Self) ^: } ::Exponentiable trait
|
|
{ (Self Self -- Self) logb: (Self -- Self) log: (Self -- Self) ln: } ::Logarithmic trait
|
|
|
|
// Number inherits from multiple traits
|
|
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
|
|
{ } ::Number trait
|
|
```
|
|
|
|
### 14.3 Logarithm Usage
|
|
|
|
```
|
|
// Calculate log base 10
|
|
100 log print // 2.0
|
|
1000 log print // 3.0
|
|
|
|
// Calculate natural logarithm
|
|
2.718 ln print // ~1.0
|
|
7.389 ln print // ~2.0
|
|
|
|
// Combine with other operations
|
|
10 3 ^ log print // 3.0 (log of 1000)
|
|
```
|
|
|
|
### 14.4 Factorial
|
|
|
|
```
|
|
(T -- T) ::Number {
|
|
dup 1
|
|
{ drop 1 }
|
|
{ dup 1 - factorial * }
|
|
<= if
|
|
} ::factorial fn
|
|
|
|
5 factorial print // 120
|
|
```
|
|
|
|
### 14.5 FizzBuzz
|
|
|
|
```
|
|
(T -- ) ::Number {
|
|
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.6 Using Roll
|
|
|
|
```
|
|
// Stack: 1 2 3 4 5
|
|
3 1 roll // Rotate top 3 once: 1 2 4 5 3
|
|
3 2 roll // Rotate top 3 twice: 1 2 5 3 4
|
|
|
|
// More complex example
|
|
10 20 30 40 50
|
|
4 2 roll // Rotate top 4, twice: 10 30 40 50 20
|
|
```
|
|
|
|
### 14.7 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
|
|
```
|
|
|
|
### 14.8 Identifier Literals in Practice
|
|
|
|
```
|
|
// Push identifier literal to stack
|
|
::Point // Pushes identifier "Point"
|
|
|
|
// Use with trait definition
|
|
{ (Self -- ) draw: } ::Drawable trait
|
|
|
|
// Use with struct definition
|
|
(T T --) { x: y: } ::Point struct
|
|
|
|
// Dynamic trait implementation
|
|
::MyType { ... } ::MyTrait impl
|
|
```
|
|
|
|
## 15. Syntax Summary
|
|
|
|
> **TODO:** Move this to appendix.
|
|
> **TODO:** Update and fill this out more.
|
|
|
|
### Complete Grammar Patterns
|
|
|
|
**Functions**: `(in -- out) trait_constraint { body } ::name fn`
|
|
|
|
**Structs**: `(types -- ) { fields: } ::name struct`
|
|
|
|
**Unions**: `(types -- ) { Variant(T) ... } ::name union`
|
|
|
|
**Enums**: `{ Variant value: ... } ::name enum`
|
|
|
|
**Traits**: `{ (sig) method: ... } ::identifier trait`
|
|
|
|
**Trait Impl**: `::identifier { (sig) { body } method: ... } ::identifier impl`
|
|
|
|
**Trait Inheritance**: `[ identifier_list ] ::identifier inher { } ::identifier trait`
|
|
|
|
**If**: `condition { then } { else } if`
|
|
|
|
**While**: `{ condition } { body } while`
|
|
|
|
**For**: `start end { body } for`
|
|
|
|
**Match**: `value { pattern => block ... } match`
|
|
|
|
**Identifier Literal**: `::name` pushes identifier instead of executing
|