MOXIEPORT.md raw

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:

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.

#TransformAST patternRewrite to
1int widthName.Value == "int" in type or conversion position"int64"
2uint widthName.Value == "uint" in type or conversion position"uint64"
3make sliceCallExpr where Fun is Name{"make"}, first arg is SliceTypeCompositeLit with SliceType + colon-length syntax
4make chanCallExpr where Fun is Name{"make"}, first arg is ChanTypeCompositeLit with ChanType + optional buffer arg
5make mapCallExpr where Fun is Name{"make"}, first arg is MapTypeCompositeLit with MapType
6new(T)CallExpr where Fun is Name{"new"}Operation{Op: And, X: CompositeLit{Type: T}} (i.e. &T{})
7string concatOperation{Op: Add} where operands are StringLitChange Op to Or (pipe). Conservative: only rewrite when at least one operand is StringLit. Flag X + Y where neither is a literal.
8strings importImportDecl with Path.Value == "strings"Change to "bytes"
9fallthroughBranchStmt{Tok: Fallthrough} in CaseClauseMerge this clause's Cases with next clause's Cases, combine bodies, remove the BranchStmt
10init renameFuncDecl with Name.Value == "init"Rename to init_N, add CallExpr at top of main()
11file extensionOutput 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.

FlagDetection
interface{} / anyInterfaceType with empty MethodList, or Name.Value == "any"
reflect importImportDecl path contains "reflect"
go statementCallStmt{Tok: Go}
sync.* importImportDecl path contains "sync"
context importImportDecl path contains "context"
uintptrName.Value == "uintptr" in type position
complex64/128Name.Value matches "complex64" or "complex128"
unsafe importImportDecl path is "unsafe"
Package-level varVarDecl at top-level DeclList
Remaining + on unknown typesOperation{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 <file.go> writes <file.mx> + prints report to stderr. moxieport <dir>/ 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:

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

Value