58 lines
2.9 KiB
Markdown
58 lines
2.9 KiB
Markdown
|
|
# CLAUDE.md
|
||
|
|
|
||
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
|
|
||
|
|
## Project Overview
|
||
|
|
|
||
|
|
UCL is an embeddable command-based scripting language implemented in Go, with Tcl/shell-like syntax. It is a **library** — there is no root `main.go`. All executables live under `cmd/`.
|
||
|
|
|
||
|
|
## Build & Test Commands
|
||
|
|
|
||
|
|
- **Run all tests:** `make test` (or `go test ./ucl/...`)
|
||
|
|
- **Run a single test:** `go test ./ucl/... -run TestName`
|
||
|
|
- **Run builtin module tests:** `go test ./ucl/builtins/...`
|
||
|
|
- **Build site + WASM playground:** `make site`
|
||
|
|
- **Clean build artifacts:** `make clean`
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Core Package (`ucl/`)
|
||
|
|
|
||
|
|
The language engine follows a **parse → tree-walk evaluate** pipeline:
|
||
|
|
|
||
|
|
- **`ast.go`** — AST node types and parser (using `participle` library with struct-tag grammar)
|
||
|
|
- **`eval.go`** — Tree-walk evaluator: scripts, statements, commands, pipelines, arguments, dot-access, string interpolation
|
||
|
|
- **`objs.go`** — Object type system: `StringObject`, `IntObject`, `BoolObject`, `ListObject`, `HashObject`, `TimeObject`, plus proxy types for Go interop via reflection
|
||
|
|
- **`inst.go`** — `Inst` (interpreter instance): the public API for creating and configuring the evaluator
|
||
|
|
- **`builtins.go`** — Built-in functions and macros (control flow, math, collections)
|
||
|
|
- **`env.go`** — `evalCtx`: scoped evaluation context (linked-list chain for variable/command lookup)
|
||
|
|
- **`userbuiltin.go`** — Public embedding API (`BuiltinHandler`, `CallArgs` with reflection-based argument binding)
|
||
|
|
|
||
|
|
### Two Command Dispatch Kinds
|
||
|
|
|
||
|
|
- **Invokables** (`invokable` interface): receive fully-evaluated arguments. Used by all regular functions, Go builtins, user `proc`s, and blocks.
|
||
|
|
- **Macros** (`macroable` interface): receive unevaluated AST + evaluator. Used by `if`, `for`, `while`, `proc`, `try` for lazy evaluation control.
|
||
|
|
|
||
|
|
### Optional Builtin Modules (`ucl/builtins/`)
|
||
|
|
|
||
|
|
Modules (`strs`, `lists`, `itrs`, `fns`, `os`, `fs`, `log`, `csv`, `time`, `urls`) are opt-in via `ucl.WithModule(builtins.Strs())` etc. Each is a self-contained file.
|
||
|
|
|
||
|
|
### Other Packages
|
||
|
|
|
||
|
|
- **`repl/`** — REPL wrapper with `EvalAndDisplay()`, help system, and `AddTypePrinter[T]` generic
|
||
|
|
- **`cmd/cmsh/`** — Interactive shell using `readline`
|
||
|
|
- **`cmd/playwasm/`** — WASM playground (builds with `GOOS=js GOARCH=wasm`)
|
||
|
|
- **`cmd/gendocs/`** — Markdown-to-HTML doc site generator (goldmark + frontmatter)
|
||
|
|
|
||
|
|
## Testing Conventions
|
||
|
|
|
||
|
|
- Tests use `testify/assert` with **table-driven** patterns (`[]struct{ desc, expr string; want any }`)
|
||
|
|
- Test packages use the `_test` suffix for black-box testing
|
||
|
|
- Shared test helpers (e.g., `WithTestBuiltin()`) are in `ucl/builtins_test.go` and provide test-only commands (`firstarg`, `toUpper`, `sjoin`, etc.)
|
||
|
|
|
||
|
|
## CI
|
||
|
|
|
||
|
|
Forgejo workflows in `.forgejo/workflows/`:
|
||
|
|
- `test.yaml` — runs `make test` on `feature/*` branches
|
||
|
|
- `build.yaml` — runs tests + `make site-deploy` on `main`
|