Skip to content

Quantumlyy/GulfOfAmerica

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GulfOfAmerica

πŸ¦…πŸ‡ΊπŸ‡Έ An interpreter (and a little bit of a compiler) β€” written in Rust β€” for TodePond's Gulf of Mexico (formerly DreamBerd), the perfect programming language.

The language spec is, ostensibly, a meme. We are nevertheless extremely serious about it.

Usage

cargo run --release -- examples/hello.gom
Hello, Gulf of America!
Be even bolder!
7
[debug] print(1 + 2*3) = undefined

The gulf binary also accepts subcommands:

Command What it does
gulf <file> / gulf run <file> Lex, parse, and execute a .gom program.
gulf check <file> Parse-only β€” report any diagnostics without running.
gulf tokens <file> Dump the token stream (debugging aid).
gulf parse <file> Dump the parsed AST (debugging aid).
gulf --help / --version The usual.

Diagnostics include source spans, file:line:column references, and explanatory notes β€” for example:

error[E0700]: cannot reassign `name`
  --> hello.gom:3:1
   |
 3 | name = "Lu"!
   | ^^^^ this variable was declared as `const const`, which forbids reassignment
   = note: to allow reassignment, declare it as `var const` or `var var`.

Feature matrix

Every example in the upstream README has a corresponding integration test in tests/spec.rs. 78 of 78 upstream spec tests pass, plus 33 lexer/parser unit tests, 11 std http tests, and a parser-recovery test.

Spec section Status Notes
Exclamation marks (!, !!!, ?) βœ… ? runs the statement and prints the source plus result.
; as the not prefix βœ…
const const / const var / var const / var var βœ… Reassignment + mutation rules enforced with friendly diagnostics.
const const const (eternal) βœ… Parsed and tagged; honours an eternal flag on the binding.
Unicode names, naming numbers (const const 5 = 4!) βœ… Numeric literal evaluation consults the binding table first.
Arrays starting at -1 βœ…
Float index insertion (scores[0.5] = 4) βœ…
when watchers βœ… Re-checked after every statement; rising-edge fires the body.
Lifetimes β€” <N>, <Ns>, <Infinity>, <-N> (hoisting) βœ… Lines/seconds expiry; negative lifetimes hoist.
Three-valued booleans (true, false, maybe) βœ… maybe matches anything in ==.
Whitespace-significant arithmetic precedence βœ… 1 + 2*3 = 7, 1+2 * 3 = 9.
Number names (one + two = 3) βœ… zero through twelve.
Four equality levels (=, ==, ===, ====) βœ… ==== is identity-aware: pi ==== pi true, 3.14 ==== pi false.
All "function" prefixes (f, fn, fun, func, functi, function) βœ…
Divide by zero β†’ undefined βœ… Same for modulo.
Strings with any number of matching quotes (incl. zero) βœ… Bareword strings: an undeclared identifier evaluates to its own name as a string.
Currency-symbol interpolation (${}, Β£{}, Β₯{}, {}€, {a$b}) βœ… Cape Verdean escudo form lowers to member access.
Type annotations βœ… Parsed and ignored.
File separators (=====+, optional name) βœ… Each section runs with a fresh global scope.
One-instance-per-class; factory-class workaround βœ… Diagnostic wording matches the README verbatim.
delete (primitives, names) βœ… Tombstone is checked at literal evaluation and on arithmetic results.
Overload priorities via !-count and Β‘ βœ… Lookup picks the highest-priority live binding.
Parentheses are whitespace βœ… (add (3, 2))!, add 3, 2! and add)3, 2(! all work.
previous / next / current βœ… current is now; previous is the value before the last reassignment; next peeks at the next assignment in the file.
Async functions (line-interleaved execution) βœ… Un-await-ed calls queue a task that ticks one statement per main-thread statement; await runs synchronously and returns the result.
Signals (use(0), destructured pairs) βœ… [get, set] = use(initial) materialises a getter/setter pair sharing one cell. A non-destructured signal is itself callable: sig() reads, sig(v) writes.
reverse! βœ… Reverses the remaining statements in the file.
import / export to βœ… export <name> to "file.gom"! deposits a binding for import <name>! in the named =====-separated file. import <name>! also resolves built-in std packages (currently http) when no user export is in scope.
DBX (HTML-in-source) ❌
AI features (Lu Wilson auto-completion) ❌ We unfortunately do not have Lu's email.

Standard packages

import <name>! falls back to a small built-in stdlib registry when no user-level export matches. User exports always win, so existing programs keep their semantics.

Package Surface
http http.get(url), http.post(url, body), http.request({method, url, body, headers}), http.serve(addr, handler), http.serve_once(addr, handler). Plain HTTP/1.1 over TCP β€” no TLS. Successful responses are {ok: true, status, reason, body, headers}. Connection / parse failures come back as data: {ok: false, error, status: 0, body: "", headers: {}} so user code can branch instead of aborting. The client decodes Transfer-Encoding: chunked. Handlers receive {method, path, body, headers} and may return a string body or a {status, body, headers, reason} object.
import http!
function handle(req) => { return {status: 200, body: "hi " + req.path}! }
http.serve_once("127.0.0.1:8765", handle)!

Editor support (LSP)

gulf-lsp is a Language Server for .gom files. It is feature-gated so the core interpreter stays dependency-free:

cargo build --release --features lsp --bin gulf-lsp
# or:
cargo install --path . --features lsp

Then point your editor at the gulf-lsp binary as the language server for gulf / dreamberd / *.gom. Capabilities in v0:

  • Diagnostics on open/change/save β€” lex + parse errors, with codes and notes preserved. The parser recovers past statement-level errors so a single broken line doesn't hide every other one in the file.
  • Hover for keywords, builtins, and the http std package.
  • Document symbols for top-level function / class / lets, with class fields and methods nested as children.
  • Goto-definition for identifiers that resolve to a binding declared at top level, inside a function body, or as a class method/field.

Completion, semantic tokens, and formatting are intentionally out of scope for the first cut.

Architecture

src/
β”œβ”€β”€ source.rs         SourceFile + Span: byte offsets ↔ (line, col)
β”œβ”€β”€ diagnostic.rs     codespan-style error rendering (no deps)
β”œβ”€β”€ token.rs          TokenKind incl. run-length tokens (Bang(n), Eq(n), …)
β”œβ”€β”€ lexer.rs          hand-rolled lexer; multi-quote strings, currency
β”‚                     interpolation, whitespace tracking
β”œβ”€β”€ ast.rs            AST: every quirk of the language is represented
β”œβ”€β”€ parser/
β”‚   β”œβ”€β”€ expr.rs       Pratt-style with whitespace-significant precedence
β”‚   └── stmt.rs       declarations, control flow, classes, no-paren calls
β”œβ”€β”€ value.rs          runtime values + per-allocation InstanceId for `====`
β”œβ”€β”€ env.rs            scope chain with overload-priority + lifetime expiry
β”œβ”€β”€ interpreter.rs    tree-walking evaluator
β”œβ”€β”€ interpreter/
β”‚   β”œβ”€β”€ builtins.rs   default globals (`print`, …)
β”‚   └── stdlib/       packages reachable via `import <name>!`
β”‚       └── http.rs   HTTP/1.1 client + server primitives
β”œβ”€β”€ lsp.rs            Language Server (feature = "lsp")
β”œβ”€β”€ bin/
β”‚   └── gulf-lsp.rs   thin stdio entry point for `gulf-lsp`
└── main.rs           CLI: run / check / tokens / parse subcommands

The implementation is zero-dependency by design β€” only std. It compiles under #![forbid(unsafe_code)].

Tests

cargo test                     # 122: 33 unit + 89 spec
cargo test --features lsp      # adds 14 lsp tests (= 136 total)
cargo clippy --all-targets

Every code block in the upstream README has a matching #[test] in tests/spec.rs, with the expected output taken straight from the // note that the README pairs with the example.

License

MIT. See LICENSE.

About

πŸ¦…πŸ‡ΊπŸ‡Έ

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages