Skip to content

Commit 6ed8787

Browse files
authored
Merge pull request #19 from MinecraftMetascript/feat/rewrite-again
Feat/rewrite again
2 parents 95df285 + 5cb16b7 commit 6ed8787

220 files changed

Lines changed: 93098 additions & 32647 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ gen
77
extensions/vscode-extension/node_modules
88
overworld.json
99
surface_rules_wiki.txt
10+
repomix-output.xml
11+
spec.md
12+
mms_dist

.helix/config.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[keys.normal]
2+
C-space = "completion"
3+
C-r = ":reload"
4+
[keys.normal.l]
5+
r = ":lsp-restart"
6+
f = ":reload"
7+
c = "completion"
8+
l = [ ":vsplit", ":log-open" ]
9+
o = [ ":sh echo \"\" > ~/.cache/helix/helix.log", ":reload" ]

.helix/languages.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ name = "mms"
77
scope = "source.mms"
88
injection-regex = "mms"
99
file-types = ["mms"]
10-
comment-tokens = "#"
11-
language-servers = [ "mms-lsp" ]
10+
comment-tokens = "//"
11+
language-servers = [ "mms-lsp" ]

.repomixignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Add patterns to ignore here, one per line
2+
# Example:
3+
# *.log
4+
# tmp/
5+
lang/grammar
6+
result
7+
vendor
8+
.junie
9+
.helix
10+
.github
11+
wasm/mms.js

.windsurfrules

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Minecraft Metascript (MMS) — Workspace AI Rules
2+
3+
These are project-specific rules and context the AI must follow when working in this repository.
4+
5+
## Project Context
6+
- Language: Go (go 1.23)
7+
- Module path: `github.com/minecraftmetascript/mms`
8+
- Vendoring: `vendor/` is present; builds typically use vendored deps
9+
- Parsing: ANTLR4 grammars in `grammar/*.g4` generate Go code into `lang/grammar/`
10+
- CLI: Cobra-based entrypoint
11+
- WASM: Browser-targeted build via [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0) and `wasm/`
12+
- Nix: Optional flake provides reproducible builds and ANTLR generation
13+
14+
## Repository Layout (high-signal paths)
15+
- `lang/`: Core API (Project, File, traversal, constructs, generated grammar package)
16+
- `lang/grammar/`: GENERATED by ANTLR. Do not edit manually.
17+
- `lang/constructs/...`: Construct registry and implementations (e.g., worldgen/surface_rules)
18+
- `lang/traversal/...`: Parser traversal, construct registry, scopes
19+
- `grammar/`: Handwritten ANTLR grammars
20+
- `cmd/`: Cobra root command ([mms](cci:7://file:///Users/brian/code/minecraftmetascript/mms/test.mms:0:0-0:0))
21+
- `wasm/`: JS glue (`mms.js`), package.json, and wasm artifacts
22+
- `examples/`: MMS examples (e.g., surface rules) for manual parsing checks
23+
24+
## Absolute Rules (Do/Don’t)
25+
- DO keep all imports at the top of files; never insert imports mid-file.
26+
- DO run `gofmt`/`goimports` and `go vet` before committing or proposing changes.
27+
- DO regenerate grammar output rather than editing anything under `lang/grammar/`.
28+
- DO keep vendoring consistent. After editing [go.mod](cci:7://file:///Users/brian/code/minecraftmetascript/mms/go.mod:0:0-0:0)/[go.sum](cci:7://file:///Users/brian/code/minecraftmetascript/mms/go.sum:0:0-0:0): `go mod tidy` then `go mod vendor`.
29+
- DO cite files/paths with backticks like `path/to/file.go` in explanations and PR notes.
30+
- DON’T modify generated files under `lang/grammar/` directly.
31+
- DON’T break build tags:
32+
- [main.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main.go:0:0-0:0): `//go:build !js && !wasm`
33+
- [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0): `//go:build js && wasm`
34+
35+
## Builds & Tasks (Preferred Flows)
36+
- Nix (recommended):
37+
- Native CLI: `nix build` → produces `./result/bin/mms` (runs ANTLR generation first)
38+
- WASM: `nix build ".#wasm"` → produces `./result/js/` with `dist/main.wasm` and assets
39+
- Dev shell: `nix develop` (provides `antlr-build`)
40+
- Regenerate grammar (Nix): `antlr-build`
41+
- Non-Nix ANTLR regeneration (if `antlr4` is in PATH):
42+
- Lexer: `antlr4 -Dlanguage=Go grammar/Main_Lexer.g4 -o lang -package grammar`
43+
- Parser: `antlr4 -Dlanguage=Go grammar/Main_Parser.g4 -lib lang/grammar -o lang -package grammar`
44+
- Vendoring:
45+
- After dependency changes: `go mod tidy && go mod vendor`
46+
47+
## WASM Notes
48+
- [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0) exports (js/wasm build tags):
49+
- `updateFile(filename: string, content: string, cb: (serializedProject: string) => void)`
50+
- `getFileDiag(filename: string, cb: (json: string) => void)`
51+
- `wasm/package.json` exposes `./mms.js` and `./dist/main.wasm` for NPM packaging.
52+
53+
## Testing Guidance
54+
- Important API change: `Project.Diagnostics` is a METHOD now, not a field.
55+
- Replace: `len(p.Diagnostics)` → `len(p.Diagnostics())`
56+
- Replace: `for d := range p.Diagnostics { ... }` → range over `p.Diagnostics()`
57+
- Running tests:
58+
- Full (may fail due to legacy `test/` pkg): `go test ./...`
59+
- Preferred during migration: `go test ./lang`
60+
- Specific test: `go test ./lang -run TestName -v`
61+
- Pattern for new tests:
62+
- Create a `Project`, add a `File`, call `Parse()`
63+
- Assert on `File.Diagnostics`, `Project.Diagnostics()`
64+
- For exports, use `Project.BuildFsLike(root)`
65+
66+
## Construct & Export Model
67+
- New constructs register via `traversal.ConstructRegistry.Register(...)`
68+
- `Project.BuildFsLike(root)` walks `GlobalScope` and calls `ExportSymbol` on constructs to build a directory-like export structure (used by WASM packaging)
69+
70+
## Coding Style & Quality
71+
- Follow idiomatic Go. Keep functions cohesive and small.
72+
- Keep generated code in `lang/grammar/` untouched; regenerate via ANTLR on grammar changes.
73+
- Prefer package-local tests near code under test.
74+
- Keep explanations concise and always reference changed files and symbols with backticks.
75+
76+
## Quick Commands Reference
77+
- Native build: `nix build`
78+
- WASM build: `nix build ".#wasm"`
79+
- Dev shell (Nix): `nix develop`
80+
- Regenerate grammar (Nix): `antlr-build`
81+
- Regenerate grammar (manual):
82+
- `antlr4 -Dlanguage=Go grammar/Main_Lexer.g4 -o lang -package grammar`
83+
- `antlr4 -Dlanguage=Go grammar/Main_Parser.g4 -lib lang/grammar -o lang -package grammar`
84+
- Core package tests: `go test ./lang -v`
85+
86+
## AI Execution Preferences
87+
- When asked to modify code:
88+
- Respect vendoring and ANTLR regeneration steps.
89+
- Never place imports mid-file—add at the top and adjust separately if needed.
90+
- Avoid large monolithic diffs; break up edits logically.
91+
- When suggesting commands, prefer Nix flows where available.
92+
- If a change would touch `lang/grammar`, instruct to regenerate via ANTLR instead of manual edits.

cmd/build.go

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"io/fs"
77
"log"
88
"os"
9+
"path"
10+
"strings"
911

10-
"github.com/minecraftmetascript/mms/lang"
11-
12+
"github.com/minecraftmetascript/mms/lib"
13+
_project "github.com/minecraftmetascript/mms/project"
1214
"github.com/spf13/cobra"
1315
)
1416

@@ -19,6 +21,7 @@ var buildCmd = &cobra.Command{
1921
Long: ``,
2022
ValidArgs: []cobra.Completion{"Input", "Output"},
2123
Run: func(cmd *cobra.Command, args []string) {
24+
log.SetFlags(log.LstdFlags | log.Lshortfile)
2225
if len(args) < 1 {
2326
log.Println("Please provide an input file or directory")
2427
return
@@ -39,10 +42,9 @@ var buildCmd = &cobra.Command{
3942
log.Println(
4043
fmt.Sprintf("Building your project from %s to %s", inFile, outFile),
4144
)
42-
4345
}
4446

45-
project := lang.NewProject()
47+
project := _project.NewProject()
4648

4749
stat, err := fs.Stat(os.DirFS("."), inFile)
4850

@@ -57,29 +59,85 @@ var buildCmd = &cobra.Command{
5759
if content, err := os.ReadFile(inFile); err != nil {
5860
log.Println("Error reading project:", err)
5961
} else {
60-
f := project.AddFile(inFile, string(content))
61-
err = f.Parse()
62+
_, err := project.AddFile(inFile, string(content))
63+
6264
if err != nil {
6365
log.Println("Error parsing project:", err)
6466
}
6567
}
6668
}
67-
r, err := json.MarshalIndent(project.BuildFsLike(outFile), "", " ")
69+
fsLike := project.BuildFsLike(outFile)
70+
if err != nil {
71+
log.Println("Error exporting project:", err)
72+
return
73+
}
74+
75+
_, err = fs.Stat(os.DirFS("."), outFile)
76+
if err != nil {
77+
if strings.HasSuffix(err.Error(), "no such file or directory") {
78+
err = os.MkdirAll(outFile, 0755)
79+
if err != nil {
80+
log.Println("Error creating output directory:", err)
81+
return
82+
}
83+
} else {
84+
log.Println("Error building project", err)
85+
}
86+
return
87+
}
88+
89+
flushProject(fsLike, outFile)
6890

6991
if debugMode {
92+
r, err := json.MarshalIndent(project.Symbols(), "", " ")
7093
log.Println(
7194
string(r),
7295
err,
7396
)
97+
} else {
98+
// induce serialization for logging
99+
_, e := json.MarshalIndent(project.Symbols(), "", " ")
100+
if e != nil {
101+
log.Println("Error serializing project:", e)
102+
}
74103
}
104+
},
105+
}
75106

76-
if len(project.Diagnostics()) > 0 {
77-
for _, diag := range project.Diagnostics() {
78-
log.Println(diag)
107+
func flushProject(root *lib.FileTreeLike, rootPath string) {
108+
log.Println(root.Name)
109+
for _, file := range root.Children {
110+
targetPath := path.Join(rootPath, file.Name)
111+
if file.IsDir {
112+
err := mkdirIfNotExists(targetPath)
113+
if err != nil {
114+
log.Println("Error creating directory:", err)
115+
}
116+
flushProject(file, targetPath)
117+
} else {
118+
err := os.WriteFile(targetPath, []byte(file.Content), 0644)
119+
if err != nil {
120+
log.Println("Error writing file:", err)
79121
}
122+
80123
}
81124

82-
},
125+
}
126+
}
127+
128+
func mkdirIfNotExists(dirPath string) error {
129+
_, err := fs.Stat(os.DirFS("."), dirPath)
130+
if err != nil {
131+
if os.IsNotExist(err) {
132+
err = os.MkdirAll(dirPath, 0755)
133+
if err != nil {
134+
return err
135+
}
136+
} else {
137+
return err
138+
}
139+
}
140+
return nil
83141
}
84142

85143
func init() {

cmd/lint.go

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
/*
2-
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
3-
*/
41
package cmd
52

63
import (
7-
"io/fs"
8-
"log"
9-
"os"
10-
"strings"
11-
12-
"github.com/minecraftmetascript/mms/lang"
134
"github.com/spf13/cobra"
145
)
156

@@ -20,41 +11,41 @@ var lintCmd = &cobra.Command{
2011
Long: ``,
2112
ValidArgs: []cobra.Completion{"Input"},
2213
Run: func(cmd *cobra.Command, args []string) {
23-
if len(args) < 1 {
24-
log.Println("Please provide an input file or directory")
25-
return
26-
}
27-
inFile := args[0]
28-
if strings.HasSuffix(inFile, "/") {
29-
inFile = strings.TrimSuffix(inFile, "/")
30-
}
31-
32-
project := lang.NewProject()
33-
34-
stat, err := fs.Stat(os.DirFS("."), inFile)
35-
36-
if err != nil {
37-
log.Println("Error building project.", err)
38-
return
39-
}
40-
if stat.IsDir() {
41-
log.Println("Project is a directory")
42-
} else {
43-
if content, err := os.ReadFile(inFile); err != nil {
44-
log.Println("Error building project:")
45-
} else {
46-
f := project.AddFile(inFile, string(content))
47-
f.Parse()
48-
}
49-
}
50-
51-
if len(project.Diagnostics()) > 0 {
52-
for _, diag := range project.Diagnostics() {
53-
log.Println(diag)
54-
}
55-
} else {
56-
log.Println("Project has no errors or warnings")
57-
}
14+
//if len(args) < 1 {
15+
// log.Println("Please provide an input file or directory")
16+
// return
17+
//}
18+
//inFile := args[0]
19+
//if strings.HasSuffix(inFile, "/") {
20+
// inFile = strings.TrimSuffix(inFile, "/")
21+
//}
22+
//
23+
//project := lang.NewProject()
24+
//
25+
//stat, err := fs.Stat(os.DirFS("."), inFile)
26+
//
27+
//if err != nil {
28+
// log.Println("Error building project.", err)
29+
// return
30+
//}
31+
//if stat.IsDir() {
32+
// log.Println("Project is a directory")
33+
//} else {
34+
// if content, err := os.ReadFile(inFile); err != nil {
35+
// log.Println("Error building project:")
36+
// } else {
37+
// f := project.AddFile(inFile, string(content))
38+
// f.Parse()
39+
// }
40+
//}
41+
//
42+
//if len(project.Diagnostics()) > 0 {
43+
// for _, diag := range project.Diagnostics() {
44+
// log.Println(diag)
45+
// }
46+
//} else {
47+
// log.Println("Project has no errors or warnings")
48+
//}
5849

5950
},
6051
}

cmd/lsp.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package cmd
22

33
import (
4-
"fmt"
4+
"log"
55

66
"github.com/minecraftmetascript/mms/lsp"
7+
78
"github.com/spf13/cobra"
89
)
910

@@ -12,10 +13,9 @@ var lspCmd = &cobra.Command{
1213
Use: "lsp",
1314

1415
Run: func(cmd *cobra.Command, args []string) {
15-
if lsp.Start() != nil {
16-
panic("Failed to start LSP server")
17-
} else {
18-
fmt.Println("LSP Started")
16+
17+
if err := lsp.Start(); err != nil {
18+
log.Fatalf("Failed to start LSP server: %v\n", err)
1919
}
2020
},
2121
}

0 commit comments

Comments
 (0)