This commit is contained in:
Kyler Olsen 2025-10-26 00:30:56 -06:00
parent e19a068ba3
commit 4700bda249
1 changed files with 86 additions and 49 deletions

View File

@ -1,6 +1,6 @@
# Stack Language Specification
**Version**: 0.6
**Version**: 0.6.1
**Status**: Draft Specification
**Changes**:
- 0.5 (AI)
@ -36,15 +36,14 @@
14. **Module system** - Added appendix entry for future imports
15. **Examples section** - Moved to appendix
16. **Syntax summary** - Moved to appendix and expanded
- 0.6.1 (AI)
1. **Variadic arguments** - Decision: Use array syntax for variable arguments (no special variadic syntax yet)
2. **Inheritance before trait** - Decision: Yes, inheritance declarations must come before trait definition
3. **`inher` operator** - Decision: No, merge inheritance into trait operator (removed `inher`)
4. **Separate `inher` vs `impl`** - Decision: Keep them separate (impl is for implementations only)
> **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.
> **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
@ -165,7 +164,25 @@ Type tuples represent stack effects and are used in function signatures to speci
(---) // No inputs, no outputs (side effects only)
```
> **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.
**Variable Arguments**: For operations that need variable numbers of arguments, use array syntax:
```
(-- Size) depth: // Zero arguments, returns stack depth
(String [Stringifiable] --) printf: // String plus array of printable values
([T] -- T) sum: // Array of values, returns sum
```
This approach:
- Keeps the type system simple (no special variadic syntax)
- Makes it clear that arguments are grouped together
- Works naturally with the existing array literal syntax
**Usage Example**:
```
"x=%d, y=%d, z=%d" [x y z] printf // Format string with array of values
[1 2 3 4 5] sum // Sum array of numbers
depth print // No arguments needed
```
**Token Strings**
@ -319,8 +336,7 @@ The `Stackable` trait provides fundamental stack manipulation operations:
The `Size` trait represents types suitable for indexing and sizing operations:
```
[ ::Addable ::Comparable ::Convertible<i64> ] ::Size inher
{ } ::Size trait
[ ::Addable ::Comparable ::Convertible<i64> ] { } ::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`).
@ -474,8 +490,7 @@ Types implementing `Size` can be used as indices, loop bounds, and array sizes.
The `Number` trait represents the full suite of numeric operations by inheriting from multiple traits:
```
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
{ } ::Number trait
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] { } ::Number trait
```
**Meta-Traits**
@ -496,13 +511,15 @@ Traits for defining and working with traits themselves:
### 4.2 Trait Definition
**Syntax**: `{ function_signatures } ::identifier trait`
**Syntax**: `inheritance_array? { function_signatures } ::identifier<type_params>? 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 (marker traits).
**Inheritance**: Traits can inherit from other traits by specifying an array of trait identifiers before the trait body. The inheritance array is optional.
**Example - Actual Language Definitions**:
```
// Trait with methods
// Trait with methods (no inheritance)
{
(Self -- ) draw:
} ::Drawable trait
@ -520,8 +537,17 @@ Traits can be defined with or without method signatures. Empty traits are valid
(Self -- T) pop:
} ::Container<T> trait
// Empty trait (marker trait)
// Empty trait (marker trait, no inheritance)
{ } ::Serializable trait
// Trait with inheritance (no additional methods)
[ ::Orderable ::Equatable ] { } ::Comparable trait
// Trait with inheritance and additional methods
[ ::Drawable ::Transformable ] {
(Self -- ) update:
(Self -- ) destroy:
} ::GameObject trait
```
Within the TokenString (the `{ }` block), identifiers like `Self`, `add:`, `draw:` are part of the trait definition syntax and should not use the `::` prefix.
@ -636,34 +662,51 @@ Within the TokenString (the `{ }` block), identifiers like `Self`, `add:`, `draw
### 4.4 Trait Inheritance
**Syntax**: `[ identifier_list ] ::identifier inher { } ::identifier trait`
**Syntax**: `[ identifier_list ] { methods } ::identifier<type_params>? 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 is specified by providing an array of trait identifiers before the trait body in the trait definition. The trait body may be empty if the trait only serves to combine inherited traits.
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.
**Inheritance Declaration**: The array of inherited traits must appear directly before the trait body TokenString. No separate `inher` operator is needed.
**Example - Actual Language Definitions**:
```
// Number inherits from multiple arithmetic traits
[ ::Addable ::Multiplyable ] ::BasicNumber inher
{ } ::BasicNumber trait
// Combine multiple arithmetic traits
[ ::Addable ::Multiplyable ] { } ::BasicNumber trait
// Full Number inherits everything numeric
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
{ } ::Number trait
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] { } ::Number trait
// Complex inheritance with additional methods
[ ::Drawable ::Transformable ::Collidable ] ::GameObject inher
{
// Inheritance with additional methods
[ ::Drawable ::Transformable ::Collidable ] {
(Self -- ) update:
(Self -- ) destroy:
} ::GameObject trait
// Size trait inherits and defines composite behavior
[ ::Addable ::Comparable ::Convertible<i64> ] ::Size inher
{ } ::Size trait
// Size trait with composite behavior
[ ::Addable ::Comparable ::Convertible<i64> ] { } ::Size trait
// String trait inheriting and adding methods
[ ::Concatenable ] {
(Self Size Size -- Self) substr:
(Self Self -- ArrayOf<Self>) split:
} ::String trait
```
**Generic Trait Inheritance**: When inheriting from generic traits, you must either make the inheriting trait similarly generic or specify concrete types:
```
// Inheriting trait is also generic (generic parameter matches)
[ ::Container<T> ] {
(Self -- T) pop:
} ::Stack<T> trait
// Inheriting trait specifies concrete type
[ ::Container<i32> ] {
(Self -- i32) pop:
} ::IntStack trait
// Multiple generic inheritance
[ ::Selectable<T> ::Sized ::Sliceable ] { } ::ArrayOf<T> trait
```
### 4.5 Using Traits in Functions
@ -1233,8 +1276,7 @@ Provides fundamental stack manipulation operations.
} ::Equatable trait
// Combined comparison (inherits both)
[ ::Orderable ::Equatable ] ::Comparable inher
{ } ::Comparable trait
[ ::Orderable ::Equatable ] { } ::Comparable trait
```
### A.4 Logical Operations
@ -1310,8 +1352,7 @@ Provides fundamental stack manipulation operations.
} ::Sliceable trait
// Complete array operations (inherits all above)
[ ::Sized ::Selectable<T> ::Sliceable ] ::ArrayOf<T> inher
{ } ::ArrayOf<T> trait
[ ::Sized ::Selectable<T> ::Sliceable ] { } ::ArrayOf<T> trait
```
### A.7 Conversion Traits
@ -1348,16 +1389,13 @@ Provides fundamental stack manipulation operations.
```
// Size for indexing
[ ::Addable ::Comparable ::Convertible<i64> ] ::Size inher
{ } ::Size trait
[ ::Addable ::Comparable ::Convertible<i64> ] { } ::Size trait
// Full numeric operations
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
{ } ::Number trait
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] { } ::Number trait
// String operations
[ ::Concatenable ] ::String inher
{
[ ::Concatenable ] {
// Extract substring from start to end
(Self Size Size -- Self) substr:
@ -1545,8 +1583,7 @@ This would provide stronger type safety but add complexity to the type checker.
{ (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
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] { } ::Number trait
```
### D.3 Logarithm Usage
@ -1711,13 +1748,13 @@ union_def ::= type_tuple token_string identifier_literal generic_params? "union"
enum_def ::= token_string identifier_literal "enum"
// Trait definition
trait_def ::= (inheritance)? token_string identifier_literal generic_params? "trait"
trait_def ::= inheritance? token_string identifier_literal generic_params? "trait"
// Trait implementation
trait_impl ::= identifier_literal token_string identifier_literal generic_params? "impl"
// Trait inheritance
inheritance ::= "[" identifier_list "]" identifier_literal generic_params? "inher"
// Trait inheritance (now part of trait definition)
inheritance ::= "[" identifier_list "]"
```
### E.4 Control Flow
@ -1746,11 +1783,11 @@ match_expr ::= expression token_string "match"
**Enums**: `{ Variant value?: ... } ::name enum`
**Traits**: `inheritance? { (sig) method: ... } ::identifier<type_params> trait`
**Traits**: `inheritance? { (sig) method: ... } ::identifier<type_params>? trait`
**Trait Impl**: `::trait_id { (sig) { body } method: ... } ::type_id<type_params> impl`
**Trait Impl**: `::trait_id { (sig) { body } method: ... } ::type_id<type_params>? impl`
**Trait Inheritance**: `[ identifier_list ] ::identifier<type_params> inher`
**Trait Inheritance**: `[ ::trait1 ::trait2 ... ] { methods } ::identifier<type_params>? trait`
**If**: `condition { then } { else } if`