bonescript-compiler 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cli.ts CHANGED
@@ -12,6 +12,7 @@ import { TypeChecker } from "./typechecker";
12
12
  import { Lowering } from "./lowering";
13
13
  import { ConstraintSolver } from "./solver";
14
14
  import { FullEmitter } from "./emit_full";
15
+ import { NakamaEmitter } from "./emit_nakama";
15
16
  import { Verifier } from "./verifier";
16
17
  import { ModuleLoader } from "./module_loader";
17
18
  import { Formatter } from "./formatter";
@@ -31,7 +32,7 @@ function main() {
31
32
 
32
33
  switch (command) {
33
34
  case "compile":
34
- requireFile(args[1], runCompile);
35
+ requireFile(args[1], (src, res) => runCompile(src, res, args.slice(2)));
35
36
  break;
36
37
  case "lex":
37
38
  requireFile(args[1], runLex);
@@ -74,10 +75,10 @@ function main() {
74
75
  }
75
76
 
76
77
  function showHelp() {
77
- console.log("BoneScript compiler v0.2.0");
78
+ console.log("BoneScript compiler v0.5.4");
78
79
  console.log("");
79
80
  console.log("Usage:");
80
- console.log(" bonec compile <file> Compile to runnable project");
81
+ console.log(" bonec compile <file> [--target <target>] Compile to runnable project");
81
82
  console.log(" bonec check <file> Lex + parse + type check (no codegen)");
82
83
  console.log(" bonec lex <file> Show token stream");
83
84
  console.log(" bonec parse <file> Show AST");
@@ -86,6 +87,10 @@ function showHelp() {
86
87
  console.log(" bonec watch <file> Recompile on change");
87
88
  console.log(" bonec diff <old.bone> <new.bone> Show schema migration diff");
88
89
  console.log("");
90
+ console.log("compile options:");
91
+ console.log(" --target <name> Output target (default: express)");
92
+ console.log(" Options: express, nakama");
93
+ console.log("");
89
94
  console.log("init options:");
90
95
  console.log(" bonec init <name> --domain <name> Scaffold from a domain template");
91
96
  console.log(" --domain <name> Domain template (default: saas_platform)");
@@ -267,7 +272,26 @@ function runInit(args: string[]) {
267
272
 
268
273
  // ─── Compile (full pipeline) ─────────────────────────────────────────────────
269
274
 
270
- function runCompile(source: string, resolved: string) {
275
+ function runCompile(source: string, resolved: string, extraArgs: string[] = []) {
276
+ // Parse --target flag (default: express)
277
+ let target: "express" | "nakama" = "express";
278
+ for (let i = 0; i < extraArgs.length; i++) {
279
+ if (extraArgs[i] === "--target" && extraArgs[i + 1]) {
280
+ const t = extraArgs[i + 1];
281
+ if (t !== "express" && t !== "nakama") {
282
+ console.error(`Unknown target '${t}'. Valid targets: express, nakama`);
283
+ process.exit(1);
284
+ }
285
+ target = t;
286
+ i++;
287
+ }
288
+ }
289
+
290
+ if (target === "nakama") {
291
+ runCompileNakama(source, resolved);
292
+ return;
293
+ }
294
+
271
295
  try {
272
296
  const tokens = new Lexer(source).tokenize();
273
297
  console.log(` [1/7] Lexed: ${tokens.length} tokens`);
@@ -418,6 +442,62 @@ function runCompile(source: string, resolved: string) {
418
442
 
419
443
  main();
420
444
 
445
+ // ─── Compile (Nakama target) ──────────────────────────────────────────────────
446
+
447
+ function runCompileNakama(source: string, resolved: string) {
448
+ try {
449
+ const tokens = new Lexer(source).tokenize();
450
+ console.log(` [1/5] Lexed: ${tokens.length} tokens`);
451
+
452
+ const loader = new ModuleLoader();
453
+ const loadResult = loader.load(resolved);
454
+ if (loadResult.errors.length > 0) {
455
+ for (const e of loadResult.errors.slice(0, 10)) {
456
+ console.log(` ${path.basename(e.file)}: ${e.error.message}`);
457
+ }
458
+ if (!loadResult.ast) process.exit(1);
459
+ }
460
+ const ast = loadResult.ast!;
461
+ console.log(` [2/5] Parsed: ${ast.systems.length} system(s)`);
462
+
463
+ const typeErrors = new TypeChecker().check(ast);
464
+ if (typeErrors.length > 0) {
465
+ for (const err of typeErrors) {
466
+ console.log(` ${err.code} at ${err.loc.line}:${err.loc.column}: ${err.message}`);
467
+ }
468
+ } else {
469
+ console.log(` [3/5] Type check: v (0 errors)`);
470
+ }
471
+
472
+ const sourceHash = createHash("sha256").update(source).digest("hex").slice(0, 16);
473
+ const irSystems = new Lowering().lower(ast, sourceHash);
474
+ console.log(` [4/5] Lowered to IR: ${irSystems.reduce((s, sys) => s + sys.modules.length, 0)} modules`);
475
+
476
+ const emitter = new NakamaEmitter();
477
+ const allFiles: ReturnType<typeof emitter.emit> = [];
478
+ for (const sys of irSystems) {
479
+ allFiles.push(...emitter.emit(sys));
480
+ }
481
+ console.log(` [5/5] Nakama emit: ${allFiles.length} files`);
482
+
483
+ const outputDir = path.resolve(path.dirname(resolved), "output-nakama");
484
+ for (const f of allFiles) {
485
+ const outPath = path.join(outputDir, f.path);
486
+ const dir = path.dirname(outPath);
487
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
488
+ fs.writeFileSync(outPath, f.content, "utf-8");
489
+ }
490
+
491
+ console.log(`\nv Nakama compilation complete. ${allFiles.length} files written to output-nakama/`);
492
+ console.log(`\nNext steps:`);
493
+ console.log(` cd output-nakama && npm install && npm run build`);
494
+ console.log(` # Copy build/ to your Nakama runtime path`);
495
+ } catch (e: any) {
496
+ console.error(`x ${e.message}`);
497
+ process.exit(1);
498
+ }
499
+ }
500
+
421
501
  // ─── Diff ─────────────────────────────────────────────────────────────────────
422
502
 
423
503
  function runDiff(args: string[]) {