Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
84de748
feat(compiler): infer arrays, matrices, and tables
thiremani Jul 15, 2026
7acfba9
fix(compiler): dereference dot expression operands
thiremani Jul 15, 2026
d092fac
fix(compiler): unify table column ownership
thiremani Jul 15, 2026
f3a5604
fix(parser): require named table headers
thiremani Jul 15, 2026
255d480
fix(runtime): align table headers with values
thiremani Jul 15, 2026
f87308a
feat(compiler): support untyped empty collections
thiremani Jul 15, 2026
fa3dc2d
feat(compiler): add first-class empty arrays
thiremani Jul 15, 2026
7c7983c
feat(compiler): generalize arrays to rank-N rectangular values
thiremani Jul 15, 2026
ed84d1e
docs: define deferred multidimensional range semantics
thiremani Jul 16, 2026
9e31680
docs: clarify range-bound collector placement
thiremani Jul 16, 2026
03b1205
docs: define nested range construction shapes
thiremani Jul 16, 2026
25ebca4
fix(compiler): close collection shape edge cases
thiremani Jul 16, 2026
6785525
fix(array): align table headers with values
thiremani Jul 16, 2026
1bfac19
docs(array): consolidate collection semantics
thiremani Jul 16, 2026
0cb204b
refactor(array): share fixed literal lowering
thiremani Jul 16, 2026
21c5841
refactor(array): unify array string formatting
thiremani Jul 16, 2026
4a4a3bf
fix(ast): quote string literals in diagnostics
thiremani Jul 16, 2026
722e392
refactor(compiler): inline runtime trap branch
thiremani Jul 16, 2026
877f072
refactor(compiler): flatten bracket literal dispatch
thiremani Jul 16, 2026
ef6e830
refactor(compiler): trust solved array cell types
thiremani Jul 16, 2026
6fbe4d4
refactor(compiler): classify array literals by first cell
thiremani Jul 16, 2026
761fa2a
refactor(compiler): remove redundant array literal wrapper
thiremani Jul 16, 2026
517e84a
feat(compiler): zip every array dimension to its minimum
thiremani Jul 17, 2026
cbe5d65
refactor(compiler): avoid ignored rank-one dimensions
thiremani Jul 18, 2026
0d41d96
refactor(compiler): rely on array length contract
thiremani Jul 19, 2026
bf32f49
feat(compiler)!: distinguish inline and block array layouts
thiremani Jul 20, 2026
fb34a08
docs: clarify array whitespace semantics
thiremani Jul 20, 2026
ab24805
fix(compiler): unify ranged array domain lowering
thiremani Jul 20, 2026
141d796
refactor(compiler): simplify array compiler naming
thiremani Jul 20, 2026
07bd47c
refactor(compiler): rely on solved array cell arity
thiremani Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Intended for performance-sensitive scripting, numerical work, simulation, and sy

**Purity:** Functions have read-only inputs and writable outputs; structs are raw data with no hidden pointers.

Range-driven auto-vectorization, safe arrays and slices.
Range-driven auto-vectorization and safe arrays.

Scope-based memory (no nulls, no out-of-bounds, no GC), and concurrency by construction.

Expand All @@ -42,7 +42,7 @@ Scope-based memory (no nulls, no out-of-bounds, no GC), and concurrency by const
- Go front-end, LLVM back-end; emits native binaries
- Template functions in `.pt`: specialized per argument types (generics by use)
- Range literals with auto-vectorized execution
- First-class arrays (safe slicing) and link semantics
- First-class rectangular arrays of any rank, columnar tables, and link semantics
- Scope-based memory: no nulls, no out-of-bounds, no garbage collector
- printf-style formatting; arrays/ranges printable
- Cross-platform (Linux/macOS/Windows)
Expand Down Expand Up @@ -197,6 +197,47 @@ y = [1.1 2.2 3.3]

Arrays are safe by construction — out-of-bounds access is not possible. Comparisons like `arr > 2` produce element-wise masks (each element kept where it holds, else 0) that work anywhere an array does.

The same bracket syntax infers higher-rank arrays and tables without a type keyword:

```python
matrix = [
1 2
3 4
]

cube = [
[1 2] [3 4]
[5 6] [7 8]
]

scores = [
: Name Score
"Ada" 10
"Lin" 12
]
```

Inline literals such as `[1 2 3]` contribute one array axis. A block literal,
where `[` is followed by a newline, contributes row and column axes even when
it contains one row. Thus the matrix above is equivalent to
`[[1 2] [3 4]]`. Use `\` to continue a long inline array across physical
lines without starting block layout. Array-valued cells stack recursively
while storage remains flat and row-major. Ragged literals are compile errors.

A header row produces a columnar table, with named columns projected as arrays
such as `scores.Score`. The shown hanging `:` is the preferred layout because
the first header aligns with the first value; spacing within header and data
rows is otherwise non-semantic.

The empty literal `[]` has type `[Empty]`: it prints as `[]`, can be passed to
functions, and adopts an element type when concatenated with a concrete array.
Once a variable has a concrete array type, assigning `[]` empties its value but
preserves that element type. Operations such as indexing or arithmetic still
require a concrete element type.

See [Pluto Array Semantics](docs/Pluto%20Array%20Semantics.md) for complete
inference, shape, indexing, empty-value, and table rules.

String-array elements print quoted so boundaries stay unambiguous:

```python
Expand Down
50 changes: 30 additions & 20 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ type StringLiteral struct {

func (sl *StringLiteral) expressionNode() {}
func (sl *StringLiteral) Tok() token.Token { return sl.Token }
func (sl *StringLiteral) String() string { return sl.Token.Literal }
func (sl *StringLiteral) String() string { return `"` + sl.Token.Literal + `"` }

// RangeLiteral represents start:stop[:step]
type RangeLiteral struct {
Expand All @@ -300,7 +300,8 @@ func (rl *RangeLiteral) String() string {

type ArrayLiteral struct {
Token token.Token // the '[' token
Headers []string // column headers (empty for matrices)
Block bool // '[' is followed by a newline; source rows form two layout axes
Headers []string // column names; empty for arrays and unnamed tables
Rows [][]Expression // row data
Indices map[string][]int // named row indices like "books": [2,3]
}
Expand All @@ -310,43 +311,51 @@ func (al *ArrayLiteral) Tok() token.Token { return al.Token }
func (al *ArrayLiteral) String() string {
var out bytes.Buffer
out.WriteString("[")
if len(al.Headers) == 0 && !al.Block {
if len(al.Rows) == 1 {
writeArrayRow(&out, al.Rows[0])
}
out.WriteString("]")
return out.String()
}

// Print headers if present
if len(al.Headers) > 0 {
out.WriteString("\n : ") // 2 spaces after :
out.WriteString("\n : ")
for j, header := range al.Headers {
if j > 0 {
out.WriteString(" ")
}
out.WriteString(header)
}
out.WriteString("\n")
}

// Print rows
for _, row := range al.Rows {
if len(al.Headers) > 0 {
out.WriteString(" ") // 5 spaces for header tables
} else {
out.WriteString(" ") // 4 spaces for matrices
}
for j, expr := range row {
if j > 0 {
out.WriteString(" ")
}
if expr != nil {
out.WriteString(expr.String())
} else {
out.WriteString("<nil>")
}
}
out.WriteString("\n")
out.WriteString("\n ")
writeArrayRow(&out, row)
}

if al.Block || len(al.Headers) > 0 || len(al.Rows) > 0 {
out.WriteString("\n")
}
out.WriteString("]")
return out.String()
}

func writeArrayRow(out *bytes.Buffer, row []Expression) {
for i, expr := range row {
if i > 0 {
out.WriteString(" ")
}
if expr == nil {
out.WriteString("<nil>")
continue
}
out.WriteString(expr.String())
}
}

// StructLiteral represents a struct value declared in .pt code mode.
// Example:
// p = Person
Expand Down Expand Up @@ -627,6 +636,7 @@ func RewriteExpr(expr Expression, rewrite func(Expression) Expression) Expressio
}
return &ArrayLiteral{
Token: e.Token,
Block: e.Block,
Headers: append([]string(nil), e.Headers...),
Rows: rows,
Indices: maps.Clone(e.Indices),
Expand Down
Loading
Loading