@fraczak/k 6.5.0 → 6.7.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.
@@ -5,13 +5,14 @@
5
5
  #include <string.h>
6
6
 
7
7
  enum {
8
- K_ARENA_BLOCK_SIZE = 262144
8
+ K_ARENA_BLOCK_SIZE = 4194304
9
9
  };
10
10
 
11
11
  typedef enum {
12
12
  K_VALUE_UNIT,
13
13
  K_VALUE_PRODUCT,
14
- K_VALUE_VARIANT
14
+ K_VALUE_VARIANT,
15
+ K_VALUE_FORWARDED = 99
15
16
  } k_value_kind;
16
17
 
17
18
  typedef struct {
@@ -221,6 +222,390 @@ void k_rt_rewind(k_rt *rt, k_rt_checkpoint mark) {
221
222
  rt->has_reusable_blocks = has_reusable;
222
223
  }
223
224
 
225
+ typedef struct {
226
+ size_t *offsets;
227
+ size_t count;
228
+ size_t capacity;
229
+ } k_fixup_list;
230
+
231
+ static void fixup_add(k_fixup_list *list, size_t offset) {
232
+ if (list->count == list->capacity) {
233
+ size_t new_cap = list->capacity == 0 ? 1024 : list->capacity * 2;
234
+ size_t *new_offsets = (size_t *)realloc(list->offsets, new_cap * sizeof(size_t));
235
+ if (new_offsets == NULL) abort();
236
+ list->offsets = new_offsets;
237
+ list->capacity = new_cap;
238
+ }
239
+ list->offsets[list->count++] = offset;
240
+ }
241
+
242
+ static int is_after_mark(k_rt *rt, const void *ptr, k_rt_checkpoint mark) {
243
+ if (rt == NULL || ptr == NULL) return 0;
244
+ const unsigned char *p = (const unsigned char *)ptr;
245
+ k_arena_block *mb = (k_arena_block *)mark.block;
246
+ if (mb == NULL) {
247
+ for (k_arena_block *b = rt->blocks; b != NULL; b = b->next) {
248
+ if (p >= b->data && p < b->data + b->capacity) {
249
+ return 1;
250
+ }
251
+ }
252
+ return 0;
253
+ }
254
+ if (rt->blocks == mb) {
255
+ return (p >= mb->data + mark.used && p < mb->data + mb->capacity);
256
+ }
257
+ for (k_arena_block *b = rt->blocks; b != NULL; b = b->next) {
258
+ if (b == mb) {
259
+ return (p >= b->data + mark.used && p < b->data + b->capacity);
260
+ }
261
+ if (p >= b->data && p < b->data + b->capacity) {
262
+ return 1;
263
+ }
264
+ }
265
+ return 0;
266
+ }
267
+
268
+ static size_t bytes_since_mark(k_rt *rt, k_rt_checkpoint mark) {
269
+ if (rt == NULL || rt->blocks == NULL) return 0;
270
+ k_arena_block *mb = (k_arena_block *)mark.block;
271
+ if (rt->blocks == mb) {
272
+ return rt->blocks->used >= mark.used ? rt->blocks->used - mark.used : 0;
273
+ }
274
+ size_t total = 0;
275
+ if (mb == NULL) {
276
+ for (k_arena_block *b = rt->blocks; b != NULL; b = b->next) {
277
+ total += b->used;
278
+ }
279
+ return total;
280
+ }
281
+ for (k_arena_block *b = rt->blocks; b != NULL; b = b->next) {
282
+ if (b == mb) {
283
+ if (b->used > mark.used) {
284
+ total += (b->used - mark.used);
285
+ }
286
+ break;
287
+ }
288
+ total += b->used;
289
+ }
290
+ return total;
291
+ }
292
+
293
+ static void *staging_alloc(unsigned char **staging_ptr, size_t *used, size_t *capacity, size_t size, k_fixup_list *fixups) {
294
+ size = align_size(size == 0 ? 1 : size);
295
+ if (*used + size > *capacity) {
296
+ size_t old_cap = *capacity;
297
+ size_t new_cap = (old_cap + size) * 2;
298
+ unsigned char *old_buf = *staging_ptr;
299
+ unsigned char *new_buf = (unsigned char *)realloc(old_buf, new_cap);
300
+ if (new_buf == NULL) abort();
301
+ if (new_buf != old_buf) {
302
+ ptrdiff_t realloc_diff = new_buf - old_buf;
303
+ for (size_t i = 0; i < fixups->count; i++) {
304
+ size_t off = fixups->offsets[i];
305
+ unsigned char **p = (unsigned char **)(new_buf + off);
306
+ *p += realloc_diff;
307
+ }
308
+ }
309
+ *staging_ptr = new_buf;
310
+ *capacity = new_cap;
311
+ }
312
+ void *p = *staging_ptr + *used;
313
+ *used += size;
314
+ return p;
315
+ }
316
+
317
+ static k_value *copy_value(k_rt *rt, k_value *root, unsigned char **staging_ptr, size_t *staging_used, size_t *staging_cap, k_fixup_list *fixups, k_rt_checkpoint mark) {
318
+ if (root == NULL || !is_after_mark(rt, root, mark)) {
319
+ return root;
320
+ }
321
+ if ((int)root->kind == K_VALUE_FORWARDED) {
322
+ return root->as.variant.payload;
323
+ }
324
+
325
+ if (root->kind == K_VALUE_VARIANT) {
326
+ k_value *first_staged = NULL;
327
+ k_value *prev_staged = NULL;
328
+ k_value *curr = root;
329
+
330
+ while (curr != NULL) {
331
+ if (!is_after_mark(rt, curr, mark)) {
332
+ if (prev_staged != NULL) {
333
+ prev_staged->as.variant.payload = curr;
334
+ }
335
+ if (first_staged == NULL) {
336
+ first_staged = curr;
337
+ }
338
+ break;
339
+ }
340
+
341
+ if ((int)curr->kind == K_VALUE_FORWARDED) {
342
+ k_value *staged_target = curr->as.variant.payload;
343
+ if (prev_staged != NULL) {
344
+ prev_staged->as.variant.payload = staged_target;
345
+ fixup_add(fixups, (unsigned char *)&prev_staged->as.variant.payload - *staging_ptr);
346
+ }
347
+ if (first_staged == NULL) {
348
+ first_staged = staged_target;
349
+ }
350
+ break;
351
+ }
352
+
353
+ if (curr->as.variant.tag != NULL) {
354
+ if (bytes_equal(curr->as.variant.tag, curr->as.variant.tag_length, "Float64", 7)) {
355
+ k_value *staged_v = (k_value *)staging_alloc(staging_ptr, staging_used, staging_cap, sizeof(k_value), fixups);
356
+ staged_v->kind = K_VALUE_VARIANT;
357
+ staged_v->rt = rt;
358
+ staged_v->as.variant.tag = curr->as.variant.tag;
359
+ staged_v->as.variant.tag_length = curr->as.variant.tag_length;
360
+ staged_v->as.variant.payload = NULL;
361
+
362
+ if (is_after_mark(rt, curr->as.variant.tag, mark)) {
363
+ char *staged_tag = (char *)staging_alloc(staging_ptr, staging_used, staging_cap, curr->as.variant.tag_length + 1, fixups);
364
+ memcpy(staged_tag, curr->as.variant.tag, curr->as.variant.tag_length);
365
+ staged_tag[curr->as.variant.tag_length] = 0;
366
+ staged_v->as.variant.tag = staged_tag;
367
+ fixup_add(fixups, (unsigned char *)&staged_v->as.variant.tag - *staging_ptr);
368
+ }
369
+
370
+ if (curr->as.variant.payload != NULL && is_after_mark(rt, curr->as.variant.payload, mark)) {
371
+ void *raw = staging_alloc(staging_ptr, staging_used, staging_cap, sizeof(double), fixups);
372
+ memcpy(raw, curr->as.variant.payload, sizeof(double));
373
+ staged_v->as.variant.payload = (k_value *)raw;
374
+ fixup_add(fixups, (unsigned char *)&staged_v->as.variant.payload - *staging_ptr);
375
+ } else {
376
+ staged_v->as.variant.payload = curr->as.variant.payload;
377
+ }
378
+
379
+ if (prev_staged != NULL) {
380
+ prev_staged->as.variant.payload = staged_v;
381
+ fixup_add(fixups, (unsigned char *)&prev_staged->as.variant.payload - *staging_ptr);
382
+ }
383
+ if (first_staged == NULL) {
384
+ first_staged = staged_v;
385
+ }
386
+ curr->kind = (k_value_kind)K_VALUE_FORWARDED;
387
+ curr->as.variant.payload = staged_v;
388
+ break;
389
+ }
390
+
391
+ if (bytes_equal(curr->as.variant.tag, curr->as.variant.tag_length, "Int32", 5)) {
392
+ k_value *staged_v = (k_value *)staging_alloc(staging_ptr, staging_used, staging_cap, sizeof(k_value), fixups);
393
+ staged_v->kind = K_VALUE_VARIANT;
394
+ staged_v->rt = rt;
395
+ staged_v->as.variant.tag = curr->as.variant.tag;
396
+ staged_v->as.variant.tag_length = curr->as.variant.tag_length;
397
+ staged_v->as.variant.payload = NULL;
398
+
399
+ if (is_after_mark(rt, curr->as.variant.tag, mark)) {
400
+ char *staged_tag = (char *)staging_alloc(staging_ptr, staging_used, staging_cap, curr->as.variant.tag_length + 1, fixups);
401
+ memcpy(staged_tag, curr->as.variant.tag, curr->as.variant.tag_length);
402
+ staged_tag[curr->as.variant.tag_length] = 0;
403
+ staged_v->as.variant.tag = staged_tag;
404
+ fixup_add(fixups, (unsigned char *)&staged_v->as.variant.tag - *staging_ptr);
405
+ }
406
+
407
+ if (curr->as.variant.payload != NULL && is_after_mark(rt, curr->as.variant.payload, mark)) {
408
+ void *raw = staging_alloc(staging_ptr, staging_used, staging_cap, sizeof(int32_t), fixups);
409
+ memcpy(raw, curr->as.variant.payload, sizeof(int32_t));
410
+ staged_v->as.variant.payload = (k_value *)raw;
411
+ fixup_add(fixups, (unsigned char *)&staged_v->as.variant.payload - *staging_ptr);
412
+ } else {
413
+ staged_v->as.variant.payload = curr->as.variant.payload;
414
+ }
415
+
416
+ if (prev_staged != NULL) {
417
+ prev_staged->as.variant.payload = staged_v;
418
+ fixup_add(fixups, (unsigned char *)&prev_staged->as.variant.payload - *staging_ptr);
419
+ }
420
+ if (first_staged == NULL) {
421
+ first_staged = staged_v;
422
+ }
423
+ curr->kind = (k_value_kind)K_VALUE_FORWARDED;
424
+ curr->as.variant.payload = staged_v;
425
+ break;
426
+ }
427
+ }
428
+
429
+ if (curr->kind != K_VALUE_VARIANT) {
430
+ k_value *staged_child = copy_value(rt, curr, staging_ptr, staging_used, staging_cap, fixups, mark);
431
+ if (prev_staged != NULL) {
432
+ prev_staged->as.variant.payload = staged_child;
433
+ if (staged_child != NULL && (unsigned char *)staged_child >= *staging_ptr && (unsigned char *)staged_child < *staging_ptr + *staging_used) {
434
+ fixup_add(fixups, (unsigned char *)&prev_staged->as.variant.payload - *staging_ptr);
435
+ }
436
+ }
437
+ if (first_staged == NULL) {
438
+ first_staged = staged_child;
439
+ }
440
+ break;
441
+ }
442
+
443
+ k_value *staged_v = (k_value *)staging_alloc(staging_ptr, staging_used, staging_cap, sizeof(k_value), fixups);
444
+ staged_v->kind = K_VALUE_VARIANT;
445
+ staged_v->rt = rt;
446
+ staged_v->as.variant.tag = curr->as.variant.tag;
447
+ staged_v->as.variant.tag_length = curr->as.variant.tag_length;
448
+ staged_v->as.variant.payload = NULL;
449
+
450
+ if (curr->as.variant.tag != NULL && is_after_mark(rt, curr->as.variant.tag, mark)) {
451
+ char *staged_tag = (char *)staging_alloc(staging_ptr, staging_used, staging_cap, curr->as.variant.tag_length + 1, fixups);
452
+ memcpy(staged_tag, curr->as.variant.tag, curr->as.variant.tag_length);
453
+ staged_tag[curr->as.variant.tag_length] = 0;
454
+ staged_v->as.variant.tag = staged_tag;
455
+ fixup_add(fixups, (unsigned char *)&staged_v->as.variant.tag - *staging_ptr);
456
+ }
457
+
458
+ if (prev_staged != NULL) {
459
+ prev_staged->as.variant.payload = staged_v;
460
+ fixup_add(fixups, (unsigned char *)&prev_staged->as.variant.payload - *staging_ptr);
461
+ }
462
+ if (first_staged == NULL) {
463
+ first_staged = staged_v;
464
+ }
465
+
466
+ k_value *next = curr->as.variant.payload;
467
+ curr->kind = (k_value_kind)K_VALUE_FORWARDED;
468
+ curr->as.variant.payload = staged_v;
469
+
470
+ prev_staged = staged_v;
471
+ curr = next;
472
+ }
473
+
474
+ return first_staged;
475
+ }
476
+
477
+ size_t header_size = align_size(sizeof(k_value));
478
+ size_t fields_size = root->as.product.count * sizeof(k_field);
479
+ size_t total_size = header_size + fields_size;
480
+
481
+ k_value *staged_p = (k_value *)staging_alloc(staging_ptr, staging_used, staging_cap, total_size, fixups);
482
+ staged_p->kind = root->kind;
483
+ staged_p->rt = rt;
484
+ staged_p->as.product.count = root->as.product.count;
485
+ staged_p->as.product.capacity = root->as.product.count;
486
+
487
+ if (root->as.product.count > 0) {
488
+ k_field *staged_fields = (k_field *)((unsigned char *)staged_p + header_size);
489
+ staged_p->as.product.fields = staged_fields;
490
+ fixup_add(fixups, (unsigned char *)&staged_p->as.product.fields - *staging_ptr);
491
+
492
+ k_field *old_fields = root->as.product.fields;
493
+ size_t count = root->as.product.count;
494
+
495
+ root->kind = (k_value_kind)K_VALUE_FORWARDED;
496
+ root->as.variant.payload = staged_p;
497
+
498
+ for (size_t i = 0; i < count; i++) {
499
+ staged_fields[i].label_length = old_fields[i].label_length;
500
+ staged_fields[i].label = old_fields[i].label;
501
+ if (old_fields[i].label != NULL && is_after_mark(rt, old_fields[i].label, mark)) {
502
+ char *staged_label = (char *)staging_alloc(staging_ptr, staging_used, staging_cap, old_fields[i].label_length + 1, fixups);
503
+ memcpy(staged_label, old_fields[i].label, old_fields[i].label_length);
504
+ staged_label[old_fields[i].label_length] = 0;
505
+ staged_fields[i].label = staged_label;
506
+ fixup_add(fixups, (unsigned char *)&staged_fields[i].label - *staging_ptr);
507
+ }
508
+
509
+ k_value *child = copy_value(rt, old_fields[i].value, staging_ptr, staging_used, staging_cap, fixups, mark);
510
+ staged_fields[i].value = child;
511
+ if (child != NULL && (unsigned char *)child >= *staging_ptr && (unsigned char *)child < *staging_ptr + *staging_used) {
512
+ fixup_add(fixups, (unsigned char *)&staged_fields[i].value - *staging_ptr);
513
+ }
514
+ }
515
+ } else {
516
+ staged_p->as.product.fields = NULL;
517
+ root->kind = (k_value_kind)K_VALUE_FORWARDED;
518
+ root->as.variant.payload = staged_p;
519
+ }
520
+
521
+ return staged_p;
522
+ }
523
+
524
+ static void rt_rewind_and_free(k_rt *rt, k_rt_checkpoint mark) {
525
+ if (rt == NULL) return;
526
+ if (mark.block == NULL) {
527
+ k_arena_block *b = rt->blocks;
528
+ while (b != NULL) {
529
+ k_arena_block *next = b->next;
530
+ free(b);
531
+ b = next;
532
+ }
533
+ rt->blocks = NULL;
534
+ rt->unit_cache = NULL;
535
+ rt->bit0_cache = NULL;
536
+ rt->bit1_cache = NULL;
537
+ rt->has_reusable_blocks = 0;
538
+ return;
539
+ }
540
+ k_arena_block *b = rt->blocks;
541
+ while (b != NULL && b != (k_arena_block *)mark.block) {
542
+ k_arena_block *next = b->next;
543
+ free(b);
544
+ b = next;
545
+ }
546
+ rt->blocks = (k_arena_block *)mark.block;
547
+ if (rt->blocks != NULL) {
548
+ rt->blocks->used = mark.used;
549
+ }
550
+ rt->unit_cache = NULL;
551
+ rt->bit0_cache = NULL;
552
+ rt->bit1_cache = NULL;
553
+ rt->has_reusable_blocks = 0;
554
+ }
555
+
556
+ k_value *k_rt_compact(k_rt *rt, k_value *root, k_rt_checkpoint *mark_ptr) {
557
+ if (rt == NULL || root == NULL || mark_ptr == NULL) return root;
558
+
559
+ size_t bytes = bytes_since_mark(rt, *mark_ptr);
560
+ if (bytes < 4194304) {
561
+ return root;
562
+ }
563
+
564
+ if (!is_after_mark(rt, root, *mark_ptr)) {
565
+ rt_rewind_and_free(rt, *mark_ptr);
566
+ return root;
567
+ }
568
+
569
+ size_t staging_cap = bytes + 65536;
570
+ unsigned char *staging = (unsigned char *)malloc(staging_cap);
571
+ if (staging == NULL) abort();
572
+ size_t staging_used = 0;
573
+
574
+ k_fixup_list fixups = {NULL, 0, 0};
575
+
576
+ k_value *staged_root = copy_value(rt, root, &staging, &staging_used, &staging_cap, &fixups, *mark_ptr);
577
+
578
+ rt_rewind_and_free(rt, *mark_ptr);
579
+
580
+ if (staging_used == 0) {
581
+ free(staging);
582
+ if (fixups.offsets != NULL) free(fixups.offsets);
583
+ return staged_root;
584
+ }
585
+
586
+ void *arena_dest = rt_alloc(rt, staging_used);
587
+ if (arena_dest == NULL) abort();
588
+
589
+ ptrdiff_t diff = (unsigned char *)arena_dest - staging;
590
+
591
+ for (size_t i = 0; i < fixups.count; i++) {
592
+ size_t off = fixups.offsets[i];
593
+ unsigned char **p = (unsigned char **)(staging + off);
594
+ *p += diff;
595
+ }
596
+
597
+ memcpy(arena_dest, staging, staging_used);
598
+
599
+ k_value *new_root = (staged_root != NULL && (unsigned char *)staged_root >= staging && (unsigned char *)staged_root < staging + staging_used)
600
+ ? (k_value *)((unsigned char *)staged_root + diff)
601
+ : staged_root;
602
+
603
+ free(staging);
604
+ if (fixups.offsets != NULL) free(fixups.offsets);
605
+
606
+ return new_root;
607
+ }
608
+
224
609
  void k_rt_free(k_rt *rt) {
225
610
  if (rt == NULL) return;
226
611
  k_arena_block *block = rt->blocks;
@@ -66,6 +66,7 @@ k_rt *k_rt_new(void);
66
66
  void k_rt_reset(k_rt *rt);
67
67
  k_rt_checkpoint k_rt_mark(k_rt *rt);
68
68
  void k_rt_rewind(k_rt *rt, k_rt_checkpoint mark);
69
+ k_value *k_rt_compact(k_rt *rt, k_value *root, k_rt_checkpoint *mark_ptr);
69
70
  void *k_rt_alloc(k_rt *rt, size_t size);
70
71
  void k_rt_free(k_rt *rt);
71
72
 
@@ -0,0 +1,153 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { compileLibrary, compileObjectBuffer, decodeObject, loadLibrary } from "@fraczak/k/object.mjs";
4
+
5
+ export function readAll(stream) {
6
+ return new Promise((resolve, reject) => {
7
+ const chunks = [];
8
+ stream.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
9
+ stream.on("end", () => resolve(Buffer.concat(chunks)));
10
+ stream.on("error", reject);
11
+ });
12
+ }
13
+
14
+ export function parseCompileOptions(args) {
15
+ const libraries = [];
16
+ const exportSpecs = [];
17
+ let loadedLibrary = false;
18
+
19
+ while (args.length > 0) {
20
+ if (args[0] === "--") {
21
+ args.shift();
22
+ break;
23
+ }
24
+ if (args[0] === "--lib") {
25
+ if (loadedLibrary) throw new Error("--lib may only be specified once");
26
+ args.shift();
27
+ const libPath = args.shift();
28
+ if (!libPath) throw new Error("--lib requires a file argument");
29
+ const ext = path.extname(libPath).toLowerCase();
30
+ if (ext === ".k") {
31
+ libraries.push(loadLibrary(compileLibrary(fs.readFileSync(libPath, "utf8"), { source: libPath })));
32
+ } else {
33
+ libraries.push(loadLibrary(decodeObject(fs.readFileSync(libPath))));
34
+ }
35
+ loadedLibrary = true;
36
+ } else if (args[0] === "--export") {
37
+ args.shift();
38
+ const spec = args.shift();
39
+ if (!spec) throw new Error("--export requires a spec argument (name or libname:localname)");
40
+ exportSpecs.push(spec);
41
+ } else if (args[0].startsWith("--")) {
42
+ break;
43
+ } else {
44
+ break;
45
+ }
46
+ }
47
+
48
+ return { libraries, exportSpecs };
49
+ }
50
+
51
+ export function fileInputType(filePath) {
52
+ const ext = path.extname(filePath).toLowerCase();
53
+ if (ext === ".ko") return "ko";
54
+ if (ext === ".kvm") return "kvm";
55
+ if (ext === ".klib") return "klib";
56
+ return "source-file";
57
+ }
58
+
59
+ export function resolveProgramInput(args, { allowStdinSource = false } = {}) {
60
+ const inputArg = args.shift() ?? null;
61
+ if (inputArg == null) {
62
+ if (!allowStdinSource) throw new Error("Missing script argument");
63
+ return { kind: "stdin-source", sourceName: "<stdin>" };
64
+ }
65
+
66
+ const ext = path.extname(inputArg).toLowerCase();
67
+ if (fs.existsSync(inputArg)) {
68
+ const kind = fileInputType(inputArg);
69
+ return { kind, path: inputArg, sourceName: inputArg };
70
+ }
71
+
72
+ if ([".k", ".ko", ".kvm", ".klib"].includes(ext)) {
73
+ throw new Error(`Input file not found: ${inputArg}`);
74
+ }
75
+
76
+ return { kind: "inline-source", source: inputArg, sourceName: "<inline>" };
77
+ }
78
+
79
+ export function buildExportPreamble(exports = [], libraries = []) {
80
+ if (exports.length === 0) return "";
81
+ const aliasMap = {};
82
+ for (const lib of libraries) {
83
+ for (const [name, hash] of Object.entries(lib.relAlias || {})) {
84
+ if (name !== "__main__") aliasMap[name] = hash;
85
+ }
86
+ for (const [hash, entry] of Object.entries(lib.meta || {})) {
87
+ if (entry?.type !== "rel") continue;
88
+ for (const origin of entry?.origins || []) {
89
+ if (origin?.name && origin.name !== "__main__") {
90
+ aliasMap[origin.name] = hash;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ const lines = [];
96
+ for (const spec of exports) {
97
+ const [libName, localName] = spec.includes(":") ? spec.split(":", 2) : [spec, spec];
98
+ const hash = aliasMap[libName];
99
+ if (!hash) throw new Error(`--export: '${libName}' not found in loaded libraries`);
100
+ const body = hash.startsWith("@") ? hash.slice(1) : hash;
101
+ lines.push(`${localName} = @${body};`);
102
+ }
103
+ return lines.join("\n") + "\n";
104
+ }
105
+
106
+ export async function compileProgramInputToObject(
107
+ input,
108
+ { libraries = [], exportSpecs = [], stdin = null } = {}
109
+ ) {
110
+ let object;
111
+ if (input.kind === "inline-source") {
112
+ const preamble = buildExportPreamble(exportSpecs, libraries);
113
+ const objBuffer = compileObjectBuffer(preamble + input.source, {
114
+ libraries,
115
+ source: input.sourceName
116
+ });
117
+ object = decodeObject(objBuffer);
118
+ } else if (input.kind === "stdin-source") {
119
+ if (!stdin) throw new Error("stdin source requested without a stdin stream");
120
+ const source = (await readAll(stdin)).toString("utf8");
121
+ const preamble = buildExportPreamble(exportSpecs, libraries);
122
+ const objBuffer = compileObjectBuffer(preamble + source, {
123
+ libraries,
124
+ source: input.sourceName
125
+ });
126
+ object = decodeObject(objBuffer);
127
+ } else if (input.kind === "source-file") {
128
+ const source = fs.readFileSync(input.path, "utf8");
129
+ const preamble = buildExportPreamble(exportSpecs, libraries);
130
+ const objBuffer = compileObjectBuffer(preamble + source, {
131
+ libraries,
132
+ source: input.sourceName
133
+ });
134
+ object = decodeObject(objBuffer);
135
+ } else if (input.kind === "ko" || input.kind === "klib") {
136
+ object = decodeObject(fs.readFileSync(input.path));
137
+ } else if (input.kind === "kvm") {
138
+ throw new Error("Compiling directly from .kvm to LLVM is not yet supported; use .k or .ko input.");
139
+ } else {
140
+ throw new Error(`Unsupported input kind: ${input.kind}`);
141
+ }
142
+
143
+ return object;
144
+ }
145
+
146
+ export default {
147
+ buildExportPreamble,
148
+ compileProgramInputToObject,
149
+ fileInputType,
150
+ parseCompileOptions,
151
+ readAll,
152
+ resolveProgramInput
153
+ };
@@ -531,7 +531,7 @@ export function compileLLVMToExecutable(llvm, outputPath, { driver = stdioDriver
531
531
  driverPath,
532
532
  llPath,
533
533
  "-o",
534
- outputPath
534
+ path.resolve(outputPath)
535
535
  ]);
536
536
  } finally {
537
537
  fs.rmSync(tmpDir, { recursive: true, force: true });