# moxieport - Plan Mechanical Go-to-Moxie source transformer. Uses the Moxie compiler's own parser (`compile.ParseFile`), rewrites the AST in-place, emits transformed source, produces a semantic report of constructs requiring manual intervention. ## Status: v1 complete All 11 mechanical transforms implemented and verified. Round-trip test (parse->print->parse->print->diff) passes with zero diff. Installed at `~/.local/bin/moxieport`. ## Known upstream bug: os.Args broken `os.Args` is always empty in standalone Moxie binaries. Root cause: `os.runtime_args` (defined in `runtime_unix.mx` via `//go:linkname`) is not compiled into `sysroot/runtime.bc`. The `runtime.initAll()` function generated by the compiler calls `os.runtime_args()` and stores the result in `os.Args`, but since the function doesn't exist in the binary, `initAll` compiles to just `ret`. moxieport works around this by reading `/proc/self/cmdline`. ## Location `/home/mleku/s/moxie/moxieport/` - new package, single binary. ## Three components ### 1. AST Printer (largest piece) `Print(w io.Writer, f *compile.File)` - walks a `*File` and emits syntactically valid Moxie source. Must handle all node types in `compile/nodes.mx`: - Declarations: `ImportDecl`, `ConstDecl`, `TypeDecl`, `VarDecl`, `FuncDecl` - Expressions: `Name`, `BasicLit`, `CallExpr`, `SelectorExpr`, `IndexExpr`, `SliceExpr`, `Operation`, `CompositeLit`, `KeyValueExpr`, `FuncLit`, `AssertExpr`, `ParenExpr`, `ListExpr` - Types: `ArrayType`, `SliceType`, `StructType`, `InterfaceType`, `FuncType`, `MapType`, `ChanType`, `DotsType` - Statements: `BlockStmt`, `ExprStmt`, `SendStmt`, `AssignStmt`, `ReturnStmt`, `IfStmt`, `ForStmt`, `RangeClause`, `SwitchStmt`, `CaseClause`, `SelectStmt`, `CommClause`, `BranchStmt`, `LabeledStmt`, `CallStmt`, `DeclStmt`, `EmptyStmt` No comment preservation (parser discards them). Pragmas (`//go:` directives, `//export`) preserved via `Pragma` fields on nodes. ### 2. AST Transforms (mechanical, deterministic) Each transform is `func(f *compile.File)`, mutates AST in-place, applied in sequence before printing. | # | Transform | AST pattern | Rewrite to | |---|-----------|-------------|------------| | 1 | **int width** | `Name.Value == "int"` in type or conversion position | `"int64"` | | 2 | **uint width** | `Name.Value == "uint"` in type or conversion position | `"uint64"` | | 3 | **make slice** | `CallExpr` where `Fun` is `Name{"make"}`, first arg is `SliceType` | `CompositeLit` with `SliceType` + colon-length syntax | | 4 | **make chan** | `CallExpr` where `Fun` is `Name{"make"}`, first arg is `ChanType` | `CompositeLit` with `ChanType` + optional buffer arg | | 5 | **make map** | `CallExpr` where `Fun` is `Name{"make"}`, first arg is `MapType` | `CompositeLit` with `MapType` | | 6 | **new(T)** | `CallExpr` where `Fun` is `Name{"new"}` | `Operation{Op: And, X: CompositeLit{Type: T}}` (i.e. `&T{}`) | | 7 | **string concat** | `Operation{Op: Add}` where operands are `StringLit` | Change `Op` to `Or` (pipe). Conservative: only rewrite when at least one operand is `StringLit`. Flag `X + Y` where neither is a literal. | | 8 | **strings import** | `ImportDecl` with `Path.Value == "strings"` | Change to `"bytes"` | | 9 | **fallthrough** | `BranchStmt{Tok: Fallthrough}` in `CaseClause` | Merge this clause's `Cases` with next clause's `Cases`, combine bodies, remove the `BranchStmt` | | 10 | **init rename** | `FuncDecl` with `Name.Value == "init"` | Rename to `init_N`, add `CallExpr` at top of `main()` | | 11 | **file extension** | Output filename | `.go` -> `.mx` | Match on `Name.Value` must be exact-equal, not prefix (avoid mangling `int32`, `int64`, `uint16`, etc.). ### 3. Semantic Reporter Walk the transformed AST. One line per flag, file:line:col + construct. Machine-parseable for claude code consumption. | Flag | Detection | |------|-----------| | `interface{}` / `any` | `InterfaceType` with empty `MethodList`, or `Name.Value == "any"` | | `reflect` import | `ImportDecl` path contains `"reflect"` | | `go` statement | `CallStmt{Tok: Go}` | | `sync.*` import | `ImportDecl` path contains `"sync"` | | `context` import | `ImportDecl` path contains `"context"` | | `uintptr` | `Name.Value == "uintptr"` in type position | | `complex64/128` | `Name.Value` matches `"complex64"` or `"complex128"` | | `unsafe` import | `ImportDecl` path is `"unsafe"` | | Package-level `var` | `VarDecl` at top-level `DeclList` | | Remaining `+` on unknown types | `Operation{Op: Add}` not rewritten by transform #7 | ## Build order 1. **AST Printer** - implement and verify round-trip: parse a `.mx` file, print it, parse the output, compare AST structure. Validates the printer independently of transforms. 2. **Transforms** - one at a time, each verified by: parse Go file -> transform -> print -> parse output -> verify target pattern is gone. 3. **Reporter** - walks the already-transformed AST, outputs the checklist. 4. **CLI** - `moxieport ` writes `` + prints report to stderr. `moxieport /` processes all `.go` files. ## Pre-build investigation Before writing the printer, read how the parser represents `CompositeLit` with colon-length syntax (`[]T{:n}`, `[]T{:n:c}`, `chan T{n}`). The AST representation determines: - How the printer emits these constructs - How the make-to-literal transform constructs its output nodes Check the parser's `compositeLit` / `complitexpr` handling to determine whether the colon-length form uses `KeyValueExpr` with a nil key, a dedicated node type, or some other encoding. Do not assume the structure. ## What moxieport does NOT do - No type checking. Raw parsed AST only. - No semantic transformation. Does not convert goroutine patterns to spawn/channel. - No dependency resolution. Processes files individually. - No formatting opinions beyond faithful AST emission. Indentation follows block depth. ## Value - Eliminates mechanical drudgery of Go-to-Moxie porting (90% of keystrokes, 0% of thinking). - Exercises the self-hosted compiler's parser through a non-compilation use case. - Semantic report turns "port this Go package" from open-ended conversation into bounded checklist with file:line locations for claude code.