nomen-lang 0.2.2 → 0.3.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nomen-lang",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "The CLI for the Nomen programming language.",
5
5
  "keywords": [],
6
6
  "license": "ISC",
package/src/index.ts CHANGED
@@ -310,7 +310,9 @@ function processFolder(folder: string, config: Config, mode: Mode, program_args:
310
310
  let dirent;
311
311
  while ((dirent = dir.readSync()) !== null) {
312
312
  if (shouldProcessFile(dirent.name)) {
313
- processFile(path.join(folder, dirent.name), config, mode, program_args);
313
+ // Folder mode checks each file in its own context — anchoring
314
+ // here would recompile the whole project once per file.
315
+ processFile(path.join(folder, dirent.name), config, mode, program_args, false);
314
316
  // @ts-ignore
315
317
  let _ = fs.watch;
316
318
  }
@@ -322,7 +324,46 @@ function shouldProcessFile(filename: string) {
322
324
  return path.extname(filename) === SUPPORTED_EXTENSION;
323
325
  }
324
326
 
325
- function processFile(filename: string, config: Config, mode: Mode, program_args: string[]) {
327
+ /**
328
+ * The project's entry file for `file_path`: walk up to the nearest
329
+ * `package.jsonc` and resolve its `entry` field, so any file inside a project
330
+ * is checked with the entry's import context (`import types` resolves
331
+ * against the project's `src/`, not the file's own folder). Returns
332
+ * undefined when the file is standalone, IS the entry, sits in an
333
+ * entry-less project (e.g. a library checkout), or the config is malformed.
334
+ */
335
+ function project_entry_for(file_path: string): string | undefined {
336
+ let dir = path.dirname(file_path);
337
+ for (let i = 0; i < 20; i++) {
338
+ const config_path = path.join(dir, "package.jsonc");
339
+ if (fs.existsSync(config_path)) {
340
+ try {
341
+ const raw = fs.readFileSync(config_path, "utf8");
342
+ const json = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
343
+ const parsed = JSON.parse(json);
344
+ if (parsed.entry) {
345
+ const entry = path.resolve(dir, parsed.entry);
346
+ if (entry !== file_path && fs.existsSync(entry)) return entry;
347
+ }
348
+ } catch {
349
+ // malformed config — keep the file's own context
350
+ }
351
+ return undefined;
352
+ }
353
+ const parent = path.dirname(dir);
354
+ if (parent === dir) return undefined;
355
+ dir = parent;
356
+ }
357
+ return undefined;
358
+ }
359
+
360
+ function processFile(
361
+ filename: string,
362
+ config: Config,
363
+ mode: Mode,
364
+ program_args: string[],
365
+ anchor_to_project = true,
366
+ ) {
326
367
  console.log("Processing", filename);
327
368
 
328
369
  const arch = config.arch || "aarch64";
@@ -333,12 +374,22 @@ function processFile(filename: string, config: Config, mode: Mode, program_args:
333
374
  config.lib = resolve_lib(resolved);
334
375
  }
335
376
 
377
+ // A `*.test.nm` file keeps its own join context: the test harness
378
+ // anchors at the test's folder and pulls the program's `src/` module in
379
+ // with `main` stripped, which the entry's context would not do.
380
+ const anchor =
381
+ anchor_to_project && !resolved.endsWith(".test.nm")
382
+ ? (project_entry_for(resolved) ?? resolved)
383
+ : resolved;
384
+ if (anchor !== resolved) {
385
+ console.log("Anchored to project entry", anchor);
386
+ }
387
+
336
388
  let startTime = performance.now();
337
389
 
338
- const resolved_path = path.resolve(filename);
339
- const input = join(resolved_path, config.lib);
390
+ const input = join(anchor, config.lib);
340
391
  const library = config.lib ? get_library(config.lib) : undefined;
341
- const parsed = parse(input, library, resolved_path);
392
+ const parsed = parse(input, library, anchor);
342
393
 
343
394
  let errors = parsed.errors;
344
395
 
@@ -373,14 +424,14 @@ function processFile(filename: string, config: Config, mode: Mode, program_args:
373
424
  const basename = path.basename(filename, ".nm");
374
425
  // Output lives in the project's `build/` — `build/test` for *.test.nm —
375
426
  // unless an explicit --out names the linked binary.
376
- const buildDir = build_dir_for(resolved_path, filename.endsWith(".test.nm"));
427
+ const buildDir = build_dir_for(resolved, filename.endsWith(".test.nm"));
377
428
  if (!fs.existsSync(buildDir)) {
378
429
  fs.mkdirSync(buildDir, { recursive: true });
379
430
  }
380
431
  const ext = arch === "aarch64" ? ".s" : platform === "macos" || platform === "ios" ? ".m" : ".c";
381
432
  const headerfile = path.join(buildDir, "main.h");
382
433
  const codefile = path.join(buildDir, basename + ext);
383
- const outfile = outfile_for(resolved_path, filename.endsWith(".test.nm"), config.out);
434
+ const outfile = outfile_for(resolved, filename.endsWith(".test.nm"), config.out);
384
435
  if (!fs.existsSync(path.dirname(outfile))) {
385
436
  fs.mkdirSync(path.dirname(outfile), { recursive: true });
386
437
  }