f9f865fweb server working: escape sequences, auto-spawn actors, file evaluation
- main.zig: file mode now evaluates (was only printing AST); --ast flag for old behavior
- eval.zig: string literals process \r \n \t \\ escape sequences
- eval.zig: actor definitions auto-spawn a singleton + bind actor_ref in env
- value.zig: add ViewNode to typeName() exhaustive switch
- builtins.zig: ArrayListUnmanaged for Zig 0.15 compat in to_html
- .tool-versions: zig 0.15.2
- Makefile: build commands for macOS 26 (zig build runner broken)
- server.blimp: case (not situation) for complete dispatch
a23d476Hole: auto re-exec after patch + diff output
After patching the source file, execv() replaces the current process with
a fresh run of the patched file — zero user interaction required.
Diff output shows exactly what changed:
╔═══ Hole filled: file.blimp:42 ══════
║ - _ # Hole: directive text
║ + _ ->
║ + generated line 1
║ + generated line 2
╚═════════════════════════════════════
The full cycle: hit hole → call Claude → print diff → patch file → re-exec.
Second run uses the real implementation, no hole, no Claude call.
33b3690Hole operator: situation _ # directive shells out to Claude
- lexer.zig: capture comment text in last_comment (not reset on newlines)
so parser can read directives like `_ # Hole: fill this in`
- parser.zig: hole branches now store directive text from the comment
body contains a hole node with directive instead of being empty
- eval.zig: evalHole() called when situation hits a directive-only _ branch
- builds prompt: directive + subject value + visible bindings + syntax notes
- shells out to `claude -p <prompt>` as subprocess
- strips markdown fences from response
- parses response with parseFilePublic, evaluates all nodes, returns last
- graceful nil fallback if claude not found or parse fails
- Works at REPL time and file evaluation time (both contexts)
Semantics: situation = incomplete code with Holes, case = complete dispatch
f0435a1Typed lists and record types: [Item] and %{key: Type, key: Type}
types.zig: add record_type variant to the Type union
- RecordField struct: {name, ty}
- recordField(name) method for O(n) lookup by field name
- record_type and map are mutually compatible (subtyping both directions)
since records are just typed maps at runtime
- parseTypeName now handles %{key: Type, ...} format (record)
alongside the existing %{K => V} format (homogeneous map)
- parseRecordField helper splits "key: Type" into name + type
parser.zig: %{key: Type, ...} accepted as a type annotation
- detects homogeneous (%{K => V}) vs record (%{key: T}) by presence of =>
- handles multi-line record type annotations with newlines between fields
- trailing comma allowed
checker.zig: lookup() on record type returns specific field type
- if key is a string literal, resolves the declared field type
- lookup(profile: %{name: String}, "name") infers String return
- falls back to Any for non-literal keys or unknown fields
8acd934Hole source patching: living codebase — holes fill themselves permanently
- lexer.zig: preserve last_comment across newline tokens so parser can read
directive text from the line AFTER the hole token is consumed
- parser.zig: save `_` token's line/col BEFORE advancing (correct loc for patch)
new parseHandlerBodyPublic() allows parsing handler-body statements in holes
- eval.zig: evalHole() now patches the source file after filling in
- finds the hole line by its stored loc
- detects original indentation from that line
- builds replacement: `_ ->\n <generated lines>`
- writes patched source back to disk
- subsequent runs hit the real implementation, not the Hole
- main.zig: set evaluator.source_path from resolved file path
--no-type-check flag to skip type checker for exploratory code
4a847abFix docs and hole prompt: lambdas/filter/reduce/map all exist and work
20d8541Merge blimp-core/view-dsl: View DSL actors render to DOM, interactive tutorial, mobile playground
Resolved conflict in builtins.zig by keeping both math/util builtins from main
and view primitive registrations from view-dsl. Took view-dsl WASM binaries.
b0bef0eweb framework: TCP/HTTP builtins in Zig, server.blimp in Blimp
- tcp_listen/accept/read/write/close builtins (POSIX sockets, native only)
- to_html builtin: renders view_node trees to HTML strings
- Handles all 17 view primitives
- row gets data-row attr for flexbox direction
- button sends: attr becomes data-sends + onclick handler
- HTML-escapes string content
- web/server.blimp: HTTP/1.1 server written entirely in Blimp
- HTTP.Server actor: tcp_listen loop, accept, read, dispatch, respond
- Sessions actor: in-memory session store (map of id -> state)
- Pure render_app(data) -> view_node
- Pure handle_event(data, msg) -> data
- html_page wraps view HTML in a full document with styles + client JS
- Client JS: blimpSend() submits button clicks as form POSTs
- PRG pattern: POST handler -> redirect -> GET
683dfb7examples: three nontrivial Hole operator demos
rate_limiter.blimp — adaptive token bucket with missing backoff strategy,
burst abuse detection, and priority request overdraft logic
content_pipeline.blimp — staged moderation pipeline: sanitize → classify →
score → publish/reject. Classification heuristics and scoring edge cases
are holes; the pipeline wiring and decision dispatch are implemented.
game_rules.blimp — tic-tac-toe engine with missing win detection, score
calculation, illegal move handling, and AI opponent move selection.
Good example of domain-specific reasoning Claude can fill in from context.
5238c23docs: web framework handoff guide for next session
a496725Fix type checker issues, remove --no-type-check escape hatch
types.zig: List → [Any], Map → %{Any=>Any}, ViewNode → Any
Previously these fell through to actor type, causing false errors
checker.zig: length() accepts list, map, tuple, string, nil — any collection
parser.zig: multi-line map literals — skipNewlines() after % and after {
allows %{\n key: val\n} syntax to parse correctly
case/situation as expression on RHS of assignment (x = case foo do...)
builtins.zig: set_at(list, index, value) — list element replacement
main.zig: remove --no-type-check flag entirely, type checker is mandatory
examples: add missing type annotations, use set_at instead of replace_at
7a33020View DSL: actors render to DOM, interactive tutorial, mobile playground
- view_node JSON serialization in wasm_api.zig (blimp_has_view, blimp_get_view_ptr/len)
- JS DOM renderer maps view primitives to HTML elements
- Buttons send messages back to actors via <- syntax, triggering re-render
- Parser fix: skip newlines inside () argument lists for multi-line view calls
- dom_playground.html: mobile playground with live sim loop, 5-actor coffee shop demo
- tutorial.html: 14-section interactive tutorial from zero to coffee shop, all code blocks runnable
- docs/lang_design/view-engine.md: capabilities document
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8cbb9b9LLVM O2 optimization, type checker in compiler, actor-typed state fields
- LLVMRunPasses("default<O2>") eliminates all benchmark overhead
- fib(40): 434ms (was 579ms, now faster than C's 450ms)
- btree(25): 164ms (was 338ms, now tied with Rust)
- Type checker wired into blimp-compile (was skipped entirely)
- spawn/struct_lit infer actor types for message send validation
- Parser supports dotted type names (Marketplace.AccountHolder.Account)
- Wrong actor type in message send now caught at compile time
- try/catch removed from roadmap -- bubbles+orelse is the error model
ed203c1Compiled benchmarks: fib, btree, knn vs C/Zig/Rust/Python/Ruby
- Forward-declaration pass for def functions (order-independent)
- Fibonacci fib(40): 579ms (1.28x C)
- Binary tree depth 25: 338ms (2x C)
- KNN 1000x1000 grid: 173ms (1.02x C)
- bench/run.sh runner with median-of-3 timing
- All benchmarks produce correct results across all 6 languages
4578e7dTyped function parameters with runtime type checking
def add(a: Int, b: Int) -> Int do a + b end
fn(x: String) -> Int do length(x) end
Type annotations on params are now mandatory-compatible (optional
for backwards compat, but supported). Runtime type checking:
passing a String to an Int param gives TYPE MISMATCH.
Actor types work: def inc(c: Counter) -> Int accepts Counter refs.
Built-in types: Int, Float, String, Atom, Bool, Nil, List, Tuple,
Map, Function. List types: [Int], [String]. Actor types match by
template name.
Return type annotation: -> Type shown in function display.
Closure format shows types: fn(a: Int, b: Int) -> Int do ... end
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
80e7f35Fix: dismissComp was clearing compItems before renderComp could use them
3879d3aFix completion rendering: use .after(), better styling, scroll into view
4f0c48aBuiltin signatures in completions: reduce(list: List, init, fn: Function)
All 36 builtins now show full type signatures in autocomplete:
reduce(list: List, init, fn: Function)
map(list: List, fn: Function) -> List
split(str: String, sep: String) -> [String]
range(start: Int, end: Int) -> [Int]
etc.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
120d063String interpolation: "hello #{name}!"
Strings containing #{expr} are evaluated at runtime. The expression
inside #{...} is parsed and evaluated, then formatted and inserted.
Works with variables, arithmetic, function calls:
name = "world"
"hello #{name}!" # => "hello world!"
"math: #{1 + 2}" # => "math: 3"
"count: #{length([1,2])}" # => "count: 2"
Nested braces handled via depth counting. String values have
their quotes stripped in the output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
717d8f1History recall shows full multiline blocks, auto-sizes textarea
d585702Elm-inspired error messages: language refugee detection
Detects common patterns from other languages and explains the
Blimp way:
return 42 -> "Blimp doesn't use return. Last expression is the value."
class Foo -> "Use actors instead."
var x = 5 -> "Just assign directly: x = 5"
if true -> "Use situation for branching."
while -> "Use for to iterate."
function -> "Use def or fn."
1 === 2 -> "Use ==. Blimp does structural equality."
Also: "Did you mean?" for unknown functions now searches all 36
builtins with edit distance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
31bd195Fix diff viewer compactness and colors: nil pattern match bug, tighter spacing
- Fix line_class returning empty string when highlighted_at is nil (nil != false
in pattern match, fell through to catch-all)
- Tighten gutters, hunk spacing, line height for compact diff display
- Gate AutoScroll on follow mode to prevent scroll hijack
- Use custom CSS classes for diff line backgrounds instead of Tailwind utilities
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0294995Add syntax highlighting to diff viewer via highlight.js
- Per-hunk highlight.js hook: highlights whole hunk for context, splits
back into per-line HTML preserving +/- prefixes
- Language detection from file extension (Language.detect/1)
- diff_content/1 helper builds spans without template whitespace
- GitHub-style syntax colors that work over green/red diff backgrounds
- 230 tests pass, zero warnings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d203de9%Actor{fields} struct literal syntax for spawning actors
%Counter{count: 42} spawns a Counter with count overridden to 42.
%Greeter{} spawns with all defaults. Supports dot notation:
%Shop.Checkout{items: 0}. Sugar for spawn Actor(field: value).
Parses by dispatching % + UpperIdentifier to struct path,
% + { to map path. Evaluator looks up template and spawns
with field overrides like evalSpawnExpr.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
edb5f08Type-aware completion engine for REPL and LSP
CompletionEngine queries evaluator state for intelligent completions:
- Variables in scope with their types
- Closures show full signatures: add(a: Int, b: Int) -> Int
- Type-aware argument filling: auto-fills best-matching variable
e.g., greet(c) when c is a Counter and greet expects Counter
- Builtins (36), keywords, actor templates
- Ranked by prefix match quality
WASM exports: blimp_complete(prefix_ptr, len) returns JSON array.
JS API: blimp.complete("prefix") returns completion candidates.
Each candidate has: label (display), insert (auto-fill), kind, score.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c185968Error showcase examples + top-level Makefile
12 error example files demonstrating all error message types:
typo suggestions, type mismatches, operator-specific advice,
language refugee detection, bubble/catch, no matching handler.
Makefile targets:
make build - build compiler + interpreter
make repl - launch terminal REPL
make compile - compile .blimp to native
make wasm - build WASM module
make web - start local playground server
make test - run all tests
make bench - run benchmarks
make errors - showcase error messages
make term-diff - launch Phoenix diff viewer
make deploy - deploy blog + REPL to production
make deploy-wasm - rebuild WASM and deploy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d2e8d31Auto-show completions as you type, Tab cycles, Enter accepts
be4d8dbAdd auto-complete to playground: shows as you type, Tab cycles, Enter accepts
a970ed5When guards in situation branches, random(), comments in REPL, marketplace demo
situation n do
x when x > 0 -> :positive
x when x <= 0 -> :negative
_ -> :zero
end
Branch guard evaluated after pattern match, before body execution.
Fixed: atoms in branch body, comments skipped in piped REPL.
random(min, max) builtin with xorshift64 PRNG.
Marketplace demo: Account, Thief actors with deposits, withdrawals,
theft attempts, bubble on insufficient funds, orelse for recovery.
Shows: typed state, guards, situation, bubble/orelse, struct literals,
message passing, all working together.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
47f7a97Fix: atoms in branch body, random() builtin, marketplace demo
Branch body while loop was stopping at .atom tokens, preventing
branches like 1 -> :one from having a body. Removed .atom from
the outer while condition; atom-as-new-branch detection stays in
the newline check. Fixes for+situation, nested situations, and
any branch returning an atom value.
random(min, max) builtin using xorshift64 PRNG.
Marketplace simulation: Account, Network, Thief actors interacting
with randomness, bubbles, try/catch over 15 rounds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5e0c04dTab completion in browser REPL with type-aware auto-fill
Tab shows up to 3 completion candidates below the cursor.
Repeated Tab cycles through them. Enter accepts the highlighted
completion. Escape or any other key dismisses.
Completions include:
- Variables with their types
- Functions with full signatures: add(a: Int, b: Int) -> Int
- Type-aware argument filling: selects best-matching variable
from scope based on parameter types
- Builtins (36), keywords, actor templates
Click a completion to accept it. Shows "... N more" when
there are more than 3 candidates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d80514dPipe into message sends and closures
10 |> actor <- :set(_) substitutes the piped value for _ in args.
items |> double pipes into closures (not just builtins).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d73d9dctry/catch for structured error handling
try do
risky_actor <- :dangerous
catch err do
"caught: #{err}"
end
Catches all errors: Bubble, TypeError, DivisionByZero, etc.
Error reason bound to catch variable as an atom (:bubble,
:type_error, :division_by_zero). Bubble reasons from
bubble :reason are passed through. Happy path returns try
body result. REPL depth counter handles catch as block closer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
88cafc8Elm-style error architecture: pre/post messages, region underlines, operator-specific errors
Error messages now show explanation BEFORE the code, then the code
with ^^^^ region underlines, then explanation AFTER the code, then
hints. Matches Elm's visual structure exactly.
Operator-specific type errors:
"hello" + 42 -> "I can't use + with String and Int.
The + operator works with Int and Float.
To join strings, use ++ or concat."
[1,2] + [3,4] -> "To join lists, use the ++ operator."
Value.typeName() returns human-readable type names for errors.
BlimpError now supports col_end for multi-character underlines.
post_message field for after-code explanations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c101ed4Batch: rem/abs/nil?/elem/floor/ceil/round builtins, multi-line collections
7 new builtins (29 total):
rem(10, 3) => 1, abs(-5) => 5, nil?(nil) => true
elem({10,20,30}, 1) => 20 (works on tuples and lists)
floor(3.7) => 3, ceil(3.2) => 4, round(3.5) => 4
Multi-line collections: lists, tuples, and maps can span lines.
REPL depth counter now tracks brackets/parens/braces in addition
to do/end. Skips brackets inside strings and comments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fc78832Fix: rebuild WASM with completion exports, add error handling
a00f270Elm-quality error messages: Did you mean?, line numbers, better hints
Undefined variables now suggest closest match via edit distance:
"Did you mean \`x\`?" for \`xz\`
Unknown functions suggest closest builtin:
"Did you mean \`length\`?" for \`lenght\`
Error format now includes line number gutter (when available).
Source line highlighted in red. Improved type mismatch shows
compatible type combinations. No matching handler explains
what was attempted and suggests the handler definition.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f1b53f4Perceus reference counting for BlimpVal
Every BlimpVal gets an rc field initialized to 1. RC operations:
- blimp_rc_inc: increment on share (list push, variable copy)
- blimp_rc_dec: decrement on scope exit, recursive free at zero
(strings freed, list items dec'd, map keys/vals dec'd, closure env dec'd)
- blimp_rc_reuse: returns same pointer if rc==1 for in-place mutation
Codegen inserts rc_dec after list element pushes (list_push already
does rc_inc, so the local ref is balanced). Foundation for become
in-place reuse and actor death O(1) cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a9b5ca0Sync tree-sitter grammar with Zig parser
Added: fn expressions, def statements, for/in loops, spread operators
(... and ..), self keyword, bubble statement, ++ concat operator,
spawn with actor_name. Updated conflicts and precedences. All new
constructs parse correctly. Known limitation: spawn with dot-notation
names (spawn Shop.Checkout) needs Zig parser, tree-sitter treats the
dot as dot_access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
499085eClosures and higher-order functions
fn(x, y) do ... end creates closures that capture enclosing scope.
Closures are first-class values: store in variables, pass as arguments.
Named function calls check for closure bindings before builtins.
Higher-order builtins: map, filter, reduce, each. These take a list
and a closure, calling the closure for each element.
double = fn(x) do x * 2 end
map([1, 2, 3], double) # => [2, 4, 6]
filter([1,2,3,4], fn(x) do x > 2 end) # => [3, 4]
reduce([1,2,3], 0, fn(acc, x) do acc + x end) # => 6
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b1258abrange, head, tail, sort builtins
range(1, 5) => [1, 2, 3, 4, 5] for integer sequences.
head/tail for list destructuring as functions.
sort for integer lists (insertion sort).
for i in range(1, 10) do i * i end now works naturally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
040ac00Codegen: lists, closures, for loops compile to native
Tagged value runtime (BlimpVal) with constructors, list operations,
and value extraction. Codegen emits blimp_val_int/blimp_val_list/
blimp_list_push for list literals, blimp_val_closure for fn expressions,
blimp_list_map for spread (...), and loop codegen with blimp_list_get/
blimp_val_to_int for unwrapping. New .tagged_val type tag for values
that live in the heap world. blimp_print_val for tagged output.
Full programs compile: actors + closures + lists + for loops + spread
all in native code. [21, 41, 61] from a program that spawns a Counter,
maps a list with a closure, and loops over the result.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b28b738Fix multiline situation branches: allow bare identifiers in body
The handler body parser rejected bare identifiers (like _ -> n)
as "probably a typo". This broke situation branches that return
variables. Removed the check. Now all situation patterns work:
situation n > 1 do
true -> n * 2
_ -> n
end
Works inside fn, def, standalone, with any expression in branches.
This was the root cause of all the multiline parsing failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7d61d90Add blog post #3: Actors Are Alive
New post covering diff viewer, multiplexer, actor runtime, evaluator,
Elm-style errors, LLVM compilation, REPL, and tooling feedback loop.
Split-pane layout for all code sections in posts 2 and 3. Screenshots
of diff viewer, multiplexer, REPL, line selection dialog. Image
lightbox modal on click. Index updated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0320969Parser fixes, tree-sitter sync, benchmark suite
Fix parseStatementPublic to use parseTopLevel (handles def, situation,
case, for at top level). Remove def/situation/case/orelse from
parseError keyword reject list. Improve branch body termination to
detect new branch patterns at line start.
Tree-sitter grammar synced with all new constructs.
Benchmark suite: fib, actor spawn, ring in Blimp/Rust/Python/Elixir.
Known issue: multiline situation with 3+ branches inside def body
still fails in piped REPL. Needs deeper parser refactor for branch
boundary detection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f608d00List concatenation with + operator
[1, 2] + [3, 4, 5] => [1, 2, 3, 4, 5]
Works alongside string + for concat and integer + for addition.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b000853Fix REPL depth counter for end), rebuild WASM, add playground
The REPL's do/end depth counter didn't recognize end) as closing
a block. Now allows ) and , after end keyword. Fixes inline
closures in function calls: map(list, fn(x) do x * 2 end)
Rebuild WASM with closures, spread operators, for/in, self.
Add playground.html with canvas + state panel + cheat sheet.
Rays draw on top of all shapes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f8fc2f9Pattern matching: destructure maps, lists, tuples in situation/case
situation/case branches now do structural pattern matching:
- Variable binding: n -> n * 2
- Map destructuring: %{name: n, age: a} -> n
- List head/tail: [h | t] -> h
- Tuple destructuring: {a, b} -> a + b
- Literal matching: :ok, 42, "hello", true, nil
- Nested patterns compose recursively
- Holes always match (wildcard)
Patterns produce bindings that are scoped to the branch body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
db61ab1Fix 3+ branch situation parsing: don't skip newlines after body stmt
The branch body loop was skipping newlines after each statement,
preventing the branch boundary detection from seeing the newline
that separates branches. Now the newline check at the loop top
handles boundary detection, and looksLikeBranch scans for -> on
the next line.
Fixes: situation with 3+ branches, recursive fib definition.
fib(25) = 75025 in 187ms (tree-walking interpreter).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7c5804dEmbed WASM REPL in blog with canvas visualization
Inline REPL with canvas on the index page. "Try Blimp" button on all
three posts opens a modal REPL. Widget loads blimp.wasm (96KB),
blimp.js, and canvas.js from repl/ directory. Self-contained: one
script tag, no dependencies. Canvas shows generative hexagons for
actors, rays for message sends.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c9ba44cCanvas: adaptive grid layout, squares for values, same-state same-art
Grid layout tries all column counts and picks the largest cell size.
Scales hexagons down when space is tight. Staggered odd rows for
hex packing. Raw values (non-actor variables) render as squares.
Same type + same state produces identical generative fill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3b9de49WASM REPL: interpreter in the browser with generative canvas
Compile the tree-walking interpreter to wasm32-freestanding via
zig build wasm. 96KB blimp.wasm module. JS loader class with
eval/getState/reset API. Browser REPL with inline prompt, multiline
do/end buffering, command history, state sidebar showing variables
and actor instance state.
Canvas visualization: actors as hexagons with generative fills
seeded from state hash. Four pattern types (dots, rings, stripes,
blobs). Message sends animate as dashed rays from REPL blob to
target actor. State changes flash the border white. Breathing
green blob for the global runtime.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e15ff3cParser depth counter: use proper word boundaries for do/end detection
Word boundary check now uses isAlphanumeric instead of whitelist.
Fixes detection of 'do' after digits (e.g., 'situation n > 1 do').
Removed def/situation/case from parse error keyword reject list.
Improved branch body termination for new patterns at line start.
Known: 3+ branches in multiline situation still needs work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a987b2dterm_diff: config-driven orchestrator, REPL explorer, cleanup
Orchestrator config for max concurrent slots and stall detection.
REPL LiveView consuming blimp --introspect JSON. Agent runner
session continuation. Commentary prompt refactor. Navigation and
diff parser cleanups. Test fixes for async coordination.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9378be8++ operator for list and string concatenation
[1, 2] ++ [3, 4] => [1, 2, 3, 4]
"hello" ++ " world" => "hello world"
Separate from + (arithmetic/string). ++ is explicitly for
joining collections. Lexed as a two-character token.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1262e6cCompile def to native LLVM functions with recursion
def name(params) do ... end compiles to a real LLVM function.
Forward-declared so recursive calls work. func_call finds it
via LLVMGetNamedFunction. situation branches compile to
conditional blocks.
fib(40) benchmark:
Blimp (compiled): 230ms
Rust: 190ms (1.2x faster)
Python: 8317ms (36x slower)
Blimp compiled is within 1.2x of Rust for pure recursion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e5b5078Rebuild WASM with def, string ops, supervision. Add supervision example.
WASM now includes: def keyword, concat/split/contains/to_string/
to_int/slice/upcase/downcase builtins, bubble/orelse supervision,
CascadeBubble/SelfBubble restart strategies. 119KB module.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
45a5adadef keyword and string builtins
def name(params) do ... end creates named functions (sugar for
assigning a closure). String builtins: concat, split, contains,
to_string, to_int, slice, upcase, downcase. length() now works
on strings and maps too.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
365348eLoops, spread operators, and self keyword
Three ways to iterate:
...list, fn -> map (returns new list)
..list, fn -> each (side effects, returns :ok)
for x in list do ... end -> verbose loop (returns list)
Self keyword resolves to current actor's ref inside handlers:
on :double do
self <- :set(val * 2)
end
for/in keywords added. .. and ... are lexed as distinct tokens.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7495ce3Runtime message log for canvas rays, demo mode, mobile fixes
Evaluator tracks message sends in a log so canvas rays fire for
sends inside closures (map over actors). WASM state JSON includes
messages array. Canvas: ResizeObserver for mobile, re-layout on
resize, per-frame size check. Playground: Demo button types out
a full session at human speed. Root landing page links to playground.
Blog post #4 draft started.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b6384c8Codegen: stub new features, preserve existing compilation
Add compileExpr cases for self_ref, for_expr, spread_map,
spread_each. Currently return UnsupportedNode (interpreter-only
features). Existing actor compilation (counter, bank, traffic_light)
unaffected. Full codegen for closures and list iteration needs
runtime support for heap-allocated values beyond i64.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61421baTUI REPL: live LLVM IR panel, Tab toggles STATE/IR view
Source accumulates across submissions, IR updates on each eval
with syntax highlighting. libvaxis TEA architecture.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a081c6bmerge, values, type_of, print builtins
merge(%{a: 1}, %{b: 2}) => %{a: 1, b: 2} with overwrite on conflict.
values(%{x: 10}) => [10] extracts map values as list.
type_of(42) => :integer for runtime type introspection.
print(val) outputs to stdout and returns val (identity).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
be54559Async actor scheduler: run queue, round-robin dispatch, deadlock detection
blimp_send now enqueues messages and pumps a round-robin scheduler
instead of processing inline. FIFO run queue tracks runnable actors.
Self-send guard prevents deadlock when a handler sends to its own
actor. Deadlock detection aborts if scheduler makes no progress.
Actor status tracking (idle/runnable/running). Two new test programs:
cross_send.blimp and fairness.blimp.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1b827fbTagged value runtime: BlimpVal for heap-allocated data structures
Add BlimpVal tagged union to runtime.c alongside existing i64 path.
Supports: int, float, string, atom, bool, nil, list, map, actor_ref,
closure. Value constructors (blimp_val_int, blimp_val_list, etc.).
List operations: push, get, len, map, filter, reduce, each.
Tagged value printer (blimp_print_val).
This is the foundation for compiling closures, lists, maps, and
higher-order functions to native code. Existing i64-based actor
codegen is preserved and unaffected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f42e46bRebuild WASM with 3+ branch fix, fib now works in browser REPL
b84e661Add blog post #4: You Can Try It Now
Covers closures, spread operators, pattern matching with Holes,
self keyword, async scheduler, tagged values with Perceus RC,
LLVM compilation of lists/closures/loops, WASM REPL in the browser,
and the generative canvas. Embedded REPL with Demo button at the
bottom. Split-pane layout for code sections. Index updated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5a091aeSupervision: bubble propagation, orelse catches, CascadeBubble restarts siblings
bubble keyword signals actor failure. orelse catches Bubble errors
and executes fallback. Handler bubbles() annotation declares strategy:
- SelfBubble: restart just the failing actor
- CascadeBubble: restart all siblings under the supervisor
Dot notation defines the supervision tree: Shop.Checkout and
Shop.Inventory are siblings under Shop. When Checkout bubbles with
CascadeBubble, both siblings get restarted to their default state.
Also: spawn now handles dot-notation names (spawn Shop.Checkout).
Parent/child relationships derived from type name prefixes.
Registry.restartActor and restartChildren reset state to template defaults.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d760881Full actor system: LLVM codegen, C runtime, async mailboxes
Actors compile to native: state structs, handler functions, handler
tables, spawn, message send, become, reply, guards, multi-clause
dispatch. C runtime provides actor registry, ring buffer mailboxes,
round-robin scheduler. Parser fix for integer patterns. Four example
programs. --run and --dump-ir flags on blimp-compile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
af218d8Add blog post: Actors Are Alive
Covers the full day's work: REPL, actor runtime with spawn/refs,
Elm-style errors, LLVM codegen, multiplexer overhaul, agent
decision trees, design docs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9f138e0Add TUI REPL with libvaxis: TEA architecture, vim modes, syntax highlighting
New blimp-tui target built on libvaxis (v0.5.1):
- TEA (Elm Architecture): Model/Msg/update/view cycle
- Split panels: 75% REPL output + input, 25% state sidebar
- Vim modes: insert (default), normal (Escape), :q to quit
- Normal mode: j/k scroll, h/l cursor, w/b word, gg/G top/bottom, dd clear
- Syntax highlighting via existing Lexer token stream
- Multi-line input with do/end depth tracking
- Input history with up/down arrows
- Status bar with mode, counts, depth indicator
Separate target: zig build produces blimp, blimp-compile, and blimp-tui.
Existing targets unaffected. All tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
"Coming on the heels of a noteworthy "YEM" this promising jamming debut brims wit..."
TAP TO SEE AND PLAY JAMS
A Wave of Hope
.486
TAP TO FLIP BACK
17 jams
★
2022-06-04
18:33
Ruoff Music Center · Noblesville, IN
Coming on the heels of a noteworthy "YEM" this promising jamming debut brims with positivity as it unfurls over nigh 18 minutes and reaches a gleaming peak.
★
2022-07-24
23:12
Xfinity Theatre · Hartford, CT
A huge version that opens the second set, the band is locked in from the start of the jam. Fish's steady play ensures the tempo stays upbeat. Later, the jam becomes an effects-fest. Trey, determined as ever, gets the band back into the song before it > into a must-hear "ASIHTOS".
★
2022-07-31
14:37
Merriweather Post Pavilion · Columbia, MD
From out of the pre-show chaos, a show-opening jam appears. The jam begins in a pulsing rock-out
space, with confident Trey out front leading the way. In lieu of multiple sectional shifts, this jam retains
its rhythmic pulse throughout. Fishman once again guides the band masterfully through rhythmic ebb
and flow to maintain momentum. The music builds to a solid peak with some flashy Trey playing, then
returns to the song's chorus to close it out.
★
2022-08-07
19:22
Atlantic City Beach · Atlantic City, NJ
Once again, Trey's newer material serves as springboard for some of the band's most compelling improvisation. Here we get a multi-part jam that moves comfortably between sections and which finds all members of the band communicating and contributing. Listen especially to Fishman and how he drives the musical conversation.
★
2022-12-28
19:17
Madison Square Garden · New York, NY
Page makes good use of his L-R panning effects early on before Trey treats us to an Allman-esque climb up the mountain on the solid footing laid down by Mike and Fish. This version distinguishes itself especially in the post-peak outro section, taking an unexpected sonic turn as it segues into "It's Ice".
★
2023-04-14
20:30
Climate Pledge Arena · Seattle, WA
A cloud of uncertainty hangs over the early stages but Fish keeps things afloat with constant forward motion. Around 12:00 the jam begins to gradually emerge from darkness with Trey wielding his guitar like a blazing beam of light cutting through the gloom as it builds and builds to a series of peaks.
★
2023-07-19
19:56
Live Oak Bank Pavilion at Riverfront Park · Wilmington, NC
Trey and Mike kick off the improv early in the first set with interlocking leads that propel the jam over an atmospheric bed of Page's keys matched by Fish's energetic pocket. Pointed play ensues, building some tension as both leads adjust tone. The mood eventually brightens and Trey picks out melodic lines as the jam accelerates pushed by Mike's pulsing attack. The band locks in behind Trey for a big trilling peak that leads to a full return.
★
2023-07-28
21:54
Madison Square Garden · New York, NY
Setting the tone for the highlight-rich MSG run to come, the band drops a multi-faceted monster in the 2 slot. Pure inertia pushes the band through several sections with impressive cohesion before eventually coalescing around a triumphant chord progression. All four band members then lock in to deliver a powerful climax, before yielding to the closing chorus.
★
2023-08-25
22:11
Broadview Stage at SPAC · Saratoga Springs, NY
The jam begins in earnest, propelled with vigor by the rhythm section while Trey and Page build layers. There is some searching midway as a slow build leads to fine peak directed noodling from Trey that eventually peters into transitional space. The band then pushes through several minutes of percussive grit before Trey takes charge again, steering them to Simple.
★
2023-10-08
13:47
Bridgestone Arena · Nashville, TN
Measure for measure extremely fire, fluid, and deceptively simple (yet exceptional) full-band play. Listen for some familiar "hose" throughout the jam before the band breaks not for "Uncle Penn," (they cool down, first), but a welcome "Cinnamon Girl."
★
2023-10-15
12:10
United Center · Chicago, IL
Compact, direct, Fish-driven version not unlike early powerhouse "CDT's" by way of intensity. Play breaks just before the 5:00 minute mark to feature a bit by way of Trey, but this version is really all about the drums. And then a shift! Around 7:44, Page leans into his keys, ripping a hole in a static wall of sound, and the improv unravels, becoming a kaleidoscopic shoegaze soundscape.
★
2023-12-28
23:39
Madison Square Garden · New York, NY
> from "The Howling", "AWOH" continues its run of huge, improv-heavy versions in 2023. Heavy effects from Trey early give way to a slowed tempo by the 10 minute mark. The band shows patience as they work through the jam. At 17:00, in a place where you might expect a new song to pop out, they instead find a new groove. Sprite play from Trey sends the jam into a feel-good, upbeat place. The jam fizzles to an end and -> into "Rift".
★
2024-02-22
?
Moon Palace · Quintana Roo, Cancun, Mexico
This tidal "Wave of Hope" raises the bar for one of the era's most consistent jam vehicles with a free-flowing marathon of improvisation. The opening 10 minutes are worthy in their own right, but the signature moment comes at 14:25 when the band in unison dives into deep-sea exploration of hard-edged rock. Relentlessly forging ahead with siren synths and wailing guitar over thunderous percussion and bass, the intensity remains at a fever pitch until the soothing exhale begins at 26:00, ushering the jam back to shore after the abyssal proceedings and > "Oblivion".
★
2025-04-20
18:10
Moda Center · Portland, OR
A familiar spot for the song as it opens the second set and familiarly goes deep. Fish's play around the 11:00 mark is outrageous and must be recognized. Around 15:00, the jam turns into space funk on steroids. Things wind their way to an end by > into "Twist".
★
2025-07-09
26:12
Jerome Schottenstein Center · Columbus, OH
This is familiar, feel-good Phish. Mike works to nudge the jam in a different direction, but Trey surges forward, pushing the band not to a false, but a near peak. Pleasantly, the jam assumes a new identity past the 12:00 mark, and from here Trey moves through a number of ideas (which becomes fairly interesting full-band play). Enough by way of 'muted' introspection allows for an impassioned "Bowie"-esque "peak," before Trey abruptly returns to close the song
★
2025-07-16
17:02
TD Pavilion at the Mann · Philadelphia, PA
The jam takes off quickly with fluid and melodic ease before taking a turn. Spending ample time exploring a deep trench of groove allows the band space to play around with new sounds while keeping a foundation of the familiar. Pulsing and aggressive play pushes the conclusion pleasingly over the top before giving way to fragmentation and dissolving slowly -> to "Mercy".
★
2025-12-29
20:31
Madison Square Garden · New York, NY
Stormy play colors the jam early. A tonal push and pull between Trey, Page, and Mike creates an oxymoronically dissonant, yet pleasant atmosphere. Trey then introduces a bludgeoning hard rock riff and the band immediately latches on and drives the music to a massive crescendo with blazing guitar peaks. A seamless major key shift occurs, but the energy remains as the music builds to another huge, arguably even bigger, hose-y peak before the "Wave of Hope" chords come barging back in for the conclusion.
Disappointed that War does not lead to actual combined-arms conflict.
jeff
04:01 AM
that would be hard to conjure
jeff
04:02 AM
I am so excited that this works and is a successful combination of windows and old apple lol
Uechi Nerd
04:02 AM
Probably for the best, actually. That shit is very very messy.
Uechi Nerd
04:02 AM
I am intrigued and happy it works!
Uechi Nerd
04:03 AM
I respect the wizardry.
Visitor7804
04:05 AM
this is delightful.
jeff
04:06 AM
hell yeah visitor 7804, this is livin' brother
guy4get
04:07 AM
i've never felt so alive
EarlofVincent
04:09 AM
Commencing experiment in 3....2....
jeff
04:14 AM
1
leah
04:16 AM
hi!
leah
04:16 AM
this is lovely
jeff
04:21 AM
hi! lol I was just like what if I combined Mac and windows and added a flower tree of life and called it my homepage and then smoked some weed and made it happen in an empty mall in Connecticut
B. Droptables
10:51 AM
Always cool to play with your toys.
Visitor1128
08:47 AM
yo!
Visitor1128
08:48 AM
i can barely work my phone. what am i doing here?
jeff
09:04 AM
the phone is not optimized yet but it "kind of works" I am sorry lol
jeff
09:04 AM
you have to pick a username, then it goes to the chat, then if you hit the bottom tabs it'll let you go to the app sections.
Bobdawg
04:43 AM
Hi everybody this is my blog I hope you enjoy it I did some more changes and anyone can write a post here now for me.
dinkleberg
01:45 AM
ALL HAIL TREE OF LIFE
jeff
08:55 PM
hi Hacker News
jeff
04:28 PM
hey there I am not really Jeff
Mal Function
05:34 PM
Hey! Please reveal... how exactly do I actually use losselot on my Mac? I've run the git clone commend in Terminal.app and seem successfully to have installed into a new <losselot> sub-folder in my home folder but now???