nomen-lang 0.1.0 → 0.2.1

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.
Files changed (43) hide show
  1. package/NOMEN_AGENTS.md +3 -3
  2. package/core/System/Buffer.nm +2 -2
  3. package/core/System/Channel.nm +1 -1
  4. package/core/System/ClassBuffer.nm +2 -2
  5. package/core/System/Console.nm +4 -4
  6. package/core/System/Graph.nm +1 -1
  7. package/core/System/LinkedList.nm +1 -1
  8. package/core/System/List.nm +3 -3
  9. package/core/System/Map.nm +5 -5
  10. package/core/System/Result.nm +1 -1
  11. package/core/System/Set.nm +4 -4
  12. package/core/System/Stream/File.nm +7 -7
  13. package/core/System/Stream/Http.nm +2 -2
  14. package/core/System/String.nm +3 -3
  15. package/core/System/Task.nm +2 -2
  16. package/core/System/Text/Json.nm +4 -4
  17. package/core/System/Text/Regex.nm +2 -2
  18. package/core/System/Tree.nm +1 -1
  19. package/core/System/bool.nm +1 -1
  20. package/core/System/char.nm +1 -1
  21. package/core/System/float.nm +1 -1
  22. package/core/System/float32.nm +1 -1
  23. package/core/System/float64.nm +1 -1
  24. package/core/System/int.nm +1 -1
  25. package/core/System/int16.nm +1 -1
  26. package/core/System/int32.nm +1 -1
  27. package/core/System/int64.nm +1 -1
  28. package/core/System/int8.nm +1 -1
  29. package/core/System/ufloat.nm +1 -1
  30. package/core/System/ufloat32.nm +1 -1
  31. package/core/System/ufloat64.nm +1 -1
  32. package/core/System/uint.nm +1 -1
  33. package/core/System/uint16.nm +1 -1
  34. package/core/System/uint32.nm +1 -1
  35. package/core/System/uint64.nm +1 -1
  36. package/core/System/uint8.nm +1 -1
  37. package/core/docs/System/Result.md +2 -2
  38. package/dist/index.mjs +3622 -3473
  39. package/package.json +1 -1
  40. package/src/index.ts +14 -4
  41. package/src/paths.ts +9 -0
  42. package/src/test.ts +47 -3
  43. package/src/types/Config.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nomen-lang",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "The CLI for the Nomen programming language.",
5
5
  "keywords": [],
6
6
  "license": "ISC",
package/src/index.ts CHANGED
@@ -14,7 +14,7 @@ import { parse_args, print_help, type Args } from "./args.ts";
14
14
  import { run_docs } from "./docs.ts";
15
15
  import render_errors, { render_warnings } from "./format_errors.ts";
16
16
  import { find_bundled, run_init } from "./init.ts";
17
- import { build_dir_for } from "./paths.ts";
17
+ import { build_dir_for, outfile_for } from "./paths.ts";
18
18
  import { runTests } from "./test.ts";
19
19
  import type Config from "./types/Config.ts";
20
20
 
@@ -104,7 +104,12 @@ try {
104
104
  const root = args.in ?? process.cwd();
105
105
  const filter = args.filter ? new RegExp(args.filter) : undefined;
106
106
  const arch = args.arch ?? "aarch64";
107
- const ok = runTests(root, { arch, filter });
107
+ const ok = runTests(root, {
108
+ arch,
109
+ filter,
110
+ audit: args.audit,
111
+ audit_runtime: args.audit_runtime,
112
+ });
108
113
  process.exit(ok ? 0 : 1);
109
114
  }
110
115
 
@@ -165,6 +170,7 @@ try {
165
170
  if (args.audit_runtime) config.audit_runtime = args.audit_runtime;
166
171
  if (args.release) config.release = args.release;
167
172
  if (args.fast_math) config.fast_math = args.fast_math;
173
+ if (args.out) config.out = args.out;
168
174
 
169
175
  // Is the --in path a folder
170
176
  if (fs.lstatSync(args.in).isDirectory()) {
@@ -365,7 +371,8 @@ function processFile(filename: string, config: Config, mode: Mode, program_args:
365
371
  }
366
372
 
367
373
  const basename = path.basename(filename, ".nm");
368
- // Output lives in the project's `build/` — `build/test` for *.test.nm.
374
+ // Output lives in the project's `build/` — `build/test` for *.test.nm —
375
+ // unless an explicit --out names the linked binary.
369
376
  const buildDir = build_dir_for(resolved_path, filename.endsWith(".test.nm"));
370
377
  if (!fs.existsSync(buildDir)) {
371
378
  fs.mkdirSync(buildDir, { recursive: true });
@@ -373,7 +380,10 @@ function processFile(filename: string, config: Config, mode: Mode, program_args:
373
380
  const ext = arch === "aarch64" ? ".s" : platform === "macos" || platform === "ios" ? ".m" : ".c";
374
381
  const headerfile = path.join(buildDir, "main.h");
375
382
  const codefile = path.join(buildDir, basename + ext);
376
- const outfile = path.join(buildDir, basename);
383
+ const outfile = outfile_for(resolved_path, filename.endsWith(".test.nm"), config.out);
384
+ if (!fs.existsSync(path.dirname(outfile))) {
385
+ fs.mkdirSync(path.dirname(outfile), { recursive: true });
386
+ }
377
387
  fs.writeFileSync(headerfile, result.headers);
378
388
  fs.writeFileSync(codefile, result.code);
379
389
 
package/src/paths.ts CHANGED
@@ -26,3 +26,12 @@ export function build_dir_for(input_path: string, is_test: boolean): string {
26
26
  ? path.join(project_root_for(input_path), "build", "test")
27
27
  : path.join(project_root_for(input_path), "build");
28
28
  }
29
+
30
+ /**
31
+ * The linked binary path for `input_path`: an explicit `--out` wins,
32
+ * otherwise `<build dir>/<entry basename>`.
33
+ */
34
+ export function outfile_for(input_path: string, is_test: boolean, out?: string): string {
35
+ if (out) return path.resolve(out);
36
+ return path.join(build_dir_for(input_path, is_test), path.basename(input_path, ".nm"));
37
+ }
package/src/test.ts CHANGED
@@ -259,6 +259,8 @@ export function run_test_file(
259
259
  entry_path: string,
260
260
  lib_path: string | undefined,
261
261
  arch: string,
262
+ audit = false,
263
+ audit_runtime?: string,
262
264
  ): TestFileResult {
263
265
  const start = performance.now();
264
266
  const source_text = fs.readFileSync(entry_path, "utf8");
@@ -294,7 +296,10 @@ export function run_test_file(
294
296
  return result;
295
297
  }
296
298
 
297
- const buildResult = build(parsed.root, { arch: arch as "aarch64" | "c", audit: false });
299
+ const buildResult = build(parsed.root, {
300
+ arch: arch as "aarch64" | "c",
301
+ audit,
302
+ });
298
303
  if (buildResult.errors && buildResult.errors.length) {
299
304
  result.ok = false;
300
305
  result.crashed = buildResult.errors
@@ -306,6 +311,24 @@ export function run_test_file(
306
311
 
307
312
  const buildDir = build_dir_for(resolved, true);
308
313
  if (!fs.existsSync(buildDir)) fs.mkdirSync(buildDir, { recursive: true });
314
+ // With --audit, compile the audit runtime (malloc/free counting) and link
315
+ // it in; the generated main calls nomen_audit_check() at exit, printing
316
+ // "LEAK: N allocation(s)" when the balance is nonzero.
317
+ let audit_obj: string | undefined;
318
+ if (audit) {
319
+ const runtime_src = audit_runtime
320
+ ? path.resolve(audit_runtime)
321
+ : find_audit_runtime(path.dirname(resolved));
322
+ if (!runtime_src || !fs.existsSync(runtime_src)) {
323
+ result.ok = false;
324
+ result.crashed =
325
+ "Audit enabled but audit_runtime.c was not found. Pass --audit-runtime <path>.";
326
+ result.ms = performance.now() - start;
327
+ return result;
328
+ }
329
+ audit_obj = path.join(buildDir, "audit_runtime.o");
330
+ execFileSync("clang", ["-c", runtime_src, "-o", audit_obj]);
331
+ }
309
332
  const ext = arch === "aarch64" ? ".s" : ".c";
310
333
  const codefile = path.join(buildDir, path.basename(entry_path, ".nm") + ext);
311
334
  const outfile = path.join(buildDir, path.basename(entry_path, ".nm"));
@@ -316,8 +339,10 @@ export function run_test_file(
316
339
 
317
340
  // Link the harness binary. The harness uses only Console/Time (printf,
318
341
  // clock_gettime), so no platform frameworks are required.
342
+ const link_args = ["-o", outfile, codefile];
343
+ if (audit_obj) link_args.push(audit_obj);
319
344
  try {
320
- execFileSync("clang", ["-o", outfile, codefile], {
345
+ execFileSync("clang", link_args, {
321
346
  encoding: "utf8",
322
347
  stdio: ["ignore", "pipe", "pipe"],
323
348
  });
@@ -427,6 +452,25 @@ export function report_file(result: TestFileResult): void {
427
452
  export interface RunTestsOptions {
428
453
  arch?: string;
429
454
  filter?: RegExp;
455
+ audit?: boolean;
456
+ audit_runtime?: string;
457
+ }
458
+
459
+ /**
460
+ * Locate audit_runtime.c for an audited test build: an explicit path wins,
461
+ * otherwise walk up from `dir` looking for a `src/audit_runtime.c` (the same
462
+ * convention the run/build commands use).
463
+ */
464
+ function find_audit_runtime(dir: string): string | undefined {
465
+ let cur = dir;
466
+ for (let i = 0; i < 20; i++) {
467
+ const candidate = path.join(cur, "src", "audit_runtime.c");
468
+ if (fs.existsSync(candidate)) return candidate;
469
+ const parent = path.dirname(cur);
470
+ if (parent === cur) break;
471
+ cur = parent;
472
+ }
473
+ return undefined;
430
474
  }
431
475
 
432
476
  /** Discover, run, and report every `*.test.nm` under `root`. */
@@ -441,7 +485,7 @@ export function runTests(root: string, options: RunTestsOptions = {}): boolean {
441
485
 
442
486
  const results: TestFileResult[] = [];
443
487
  for (const file of files) {
444
- const result = run_test_file(file, lib, arch);
488
+ const result = run_test_file(file, lib, arch, options.audit, options.audit_runtime);
445
489
  report_file(result);
446
490
  results.push(result);
447
491
  }
@@ -6,4 +6,5 @@ export default interface Config {
6
6
  audit_runtime?: string;
7
7
  release?: boolean;
8
8
  fast_math?: boolean;
9
+ out?: string;
9
10
  }