xbintsc 0.1.6 → 0.1.9
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/README.md +7 -4
- package/dist/src/ast/common.d.ts +33 -0
- package/dist/src/ast/common.js +7 -0
- package/dist/src/ast/common.js.map +1 -0
- package/dist/src/ast/declarations.d.ts +110 -0
- package/dist/src/ast/declarations.js +5 -0
- package/dist/src/ast/declarations.js.map +1 -0
- package/dist/src/ast/expressions.d.ts +219 -0
- package/dist/src/ast/expressions.js +6 -0
- package/dist/src/ast/expressions.js.map +1 -0
- package/dist/src/ast/kinds.d.ts +160 -0
- package/dist/src/ast/kinds.js +171 -0
- package/dist/src/ast/kinds.js.map +1 -0
- package/dist/src/ast/modules.d.ts +61 -0
- package/dist/src/ast/modules.js +5 -0
- package/dist/src/ast/modules.js.map +1 -0
- package/dist/src/ast/nodes.d.ts +11 -839
- package/dist/src/ast/nodes.js +11 -237
- package/dist/src/ast/nodes.js.map +1 -1
- package/dist/src/ast/operators.d.ts +71 -0
- package/dist/src/ast/operators.js +77 -0
- package/dist/src/ast/operators.js.map +1 -0
- package/dist/src/ast/statements.d.ts +120 -0
- package/dist/src/ast/statements.js +5 -0
- package/dist/src/ast/statements.js.map +1 -0
- package/dist/src/ast/types.d.ts +123 -0
- package/dist/src/ast/types.js +6 -0
- package/dist/src/ast/types.js.map +1 -0
- package/dist/src/binder/binder.d.ts +35 -1
- package/dist/src/binder/binder.js +138 -0
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/codegen/generator/calls.d.ts +26 -0
- package/dist/src/codegen/generator/calls.js +373 -0
- package/dist/src/codegen/generator/calls.js.map +1 -0
- package/dist/src/codegen/generator/context.d.ts +47 -0
- package/dist/src/codegen/generator/context.js +164 -0
- package/dist/src/codegen/generator/context.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +25 -0
- package/dist/src/codegen/generator/expressions.js +454 -0
- package/dist/src/codegen/generator/expressions.js.map +1 -0
- package/dist/src/codegen/generator/generator.d.ts +22 -0
- package/dist/src/codegen/generator/generator.js +21 -0
- package/dist/src/codegen/generator/generator.js.map +1 -0
- package/dist/src/codegen/generator/module.d.ts +19 -0
- package/dist/src/codegen/generator/module.js +214 -0
- package/dist/src/codegen/generator/module.js.map +1 -0
- package/dist/src/codegen/generator/state.d.ts +42 -0
- package/dist/src/codegen/generator/state.js +125 -0
- package/dist/src/codegen/generator/state.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +22 -0
- package/dist/src/codegen/generator/statements.js +433 -0
- package/dist/src/codegen/generator/statements.js.map +1 -0
- package/dist/src/codegen/generator/tables.d.ts +23 -0
- package/dist/src/codegen/generator/tables.js +186 -0
- package/dist/src/codegen/generator/tables.js.map +1 -0
- package/dist/src/codegen/llvm.d.ts +4 -13
- package/dist/src/codegen/llvm.js +4 -1537
- package/dist/src/codegen/llvm.js.map +1 -1
- package/dist/src/driver/compiler.js +36 -11
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/modules.d.ts +24 -0
- package/dist/src/driver/modules.js +347 -0
- package/dist/src/driver/modules.js.map +1 -0
- package/dist/src/lexer/char.d.ts +78 -0
- package/dist/src/lexer/char.js +106 -0
- package/dist/src/lexer/char.js.map +1 -0
- package/dist/src/lexer/scanner.js +1 -98
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/context.d.ts +58 -0
- package/dist/src/parser/context.js +174 -0
- package/dist/src/parser/context.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +26 -0
- package/dist/src/parser/declarations.js +461 -0
- package/dist/src/parser/declarations.js.map +1 -0
- package/dist/src/parser/expressions.d.ts +27 -0
- package/dist/src/parser/expressions.js +440 -0
- package/dist/src/parser/expressions.js.map +1 -0
- package/dist/src/parser/helpers.d.ts +7 -0
- package/dist/src/parser/helpers.js +36 -0
- package/dist/src/parser/helpers.js.map +1 -0
- package/dist/src/parser/literals.d.ts +16 -0
- package/dist/src/parser/literals.js +193 -0
- package/dist/src/parser/literals.js.map +1 -0
- package/dist/src/parser/modules.d.ts +12 -0
- package/dist/src/parser/modules.js +175 -0
- package/dist/src/parser/modules.js.map +1 -0
- package/dist/src/parser/operators.d.ts +12 -0
- package/dist/src/parser/operators.js +172 -0
- package/dist/src/parser/operators.js.map +1 -0
- package/dist/src/parser/parser.d.ts +17 -122
- package/dist/src/parser/parser.js +18 -2311
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/speculation.d.ts +6 -0
- package/dist/src/parser/speculation.js +10 -0
- package/dist/src/parser/speculation.js.map +1 -0
- package/dist/src/parser/statements.d.ts +28 -0
- package/dist/src/parser/statements.js +402 -0
- package/dist/src/parser/statements.js.map +1 -0
- package/dist/src/parser/types.d.ts +21 -0
- package/dist/src/parser/types.js +338 -0
- package/dist/src/parser/types.js.map +1 -0
- package/dist/tests/codegen/llvm.test.js +1 -1
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/e2e/compile.test.js +86 -0
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/package.json +1 -1
- package/runtime/rt.h +55 -4
- package/runtime/rt_internal.h +169 -0
- package/runtime/xt_alloc.c +38 -0
- package/runtime/xt_builtins.c +238 -0
- package/runtime/xt_containers.c +312 -0
- package/runtime/xt_io.c +246 -0
- package/runtime/xt_promise.c +292 -0
- package/runtime/xt_stdlib.c +556 -0
- package/runtime/xt_stdlib2.c +1043 -0
- package/runtime/xt_values.c +291 -0
- package/scripts/build-runtime.mjs +8 -1
- package/src/ast/common.ts +210 -0
- package/src/ast/declarations.ts +130 -0
- package/src/ast/expressions.ts +275 -0
- package/src/ast/kinds.ts +176 -0
- package/src/ast/modules.ts +73 -0
- package/src/ast/nodes.ts +11 -1101
- package/src/ast/operators.ts +76 -0
- package/src/ast/statements.ts +148 -0
- package/src/ast/types.ts +173 -0
- package/src/binder/binder.ts +196 -0
- package/src/codegen/generator/calls.ts +433 -0
- package/src/codegen/generator/context.ts +190 -0
- package/src/codegen/generator/expressions.ts +508 -0
- package/src/codegen/generator/generator.ts +35 -0
- package/src/codegen/generator/module.ts +244 -0
- package/src/codegen/generator/state.ts +169 -0
- package/src/codegen/generator/statements.ts +480 -0
- package/src/codegen/generator/tables.ts +206 -0
- package/src/codegen/llvm.ts +4 -1720
- package/src/driver/compiler.ts +45 -12
- package/src/driver/modules.ts +377 -0
- package/src/lexer/char.ts +116 -0
- package/src/lexer/scanner.ts +9 -109
- package/src/parser/context.ts +196 -0
- package/src/parser/declarations.ts +502 -0
- package/src/parser/expressions.ts +468 -0
- package/src/parser/helpers.ts +42 -0
- package/src/parser/literals.ts +207 -0
- package/src/parser/modules.ts +194 -0
- package/src/parser/operators.ts +181 -0
- package/src/parser/parser.ts +35 -2373
- package/src/parser/speculation.ts +9 -0
- package/src/parser/statements.ts +457 -0
- package/src/parser/types.ts +365 -0
- package/runtime/xt_runtime.c +0 -1372
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc runtime — private internal header.
|
|
3
|
+
*
|
|
4
|
+
* Shared by the runtime translation units:
|
|
5
|
+
* xt_alloc.c heap arena + allocation kinds
|
|
6
|
+
* xt_values.c constructors, strings, conversions, arithmetic, comparison
|
|
7
|
+
* xt_containers.c objects, arrays, generic member access, boxes
|
|
8
|
+
* xt_stdlib.c Array/String methods and Math
|
|
9
|
+
* xt_builtins.c Object methods, globals and closures
|
|
10
|
+
* xt_io.c exceptions (try/catch) and console output
|
|
11
|
+
*
|
|
12
|
+
* This header declares the internal object layouts and the small set of
|
|
13
|
+
* helpers that cross translation-unit boundaries. Nothing here is part of the
|
|
14
|
+
* public ABI in `rt.h`; generated code only sees the `xt_*` prototypes there.
|
|
15
|
+
*
|
|
16
|
+
* Design notes
|
|
17
|
+
* ------------
|
|
18
|
+
* * Values are 64-bit NaN-boxed words (`xt_value`). Numbers travel unboxed;
|
|
19
|
+
* everything else is a tagged pointer into an allocation arena.
|
|
20
|
+
* * The allocator is a bump arena. It never frees, which keeps the generated
|
|
21
|
+
* code free of write barriers and makes the first implementation small and
|
|
22
|
+
* predictable. Replacing it with a precise/conservative collector is an
|
|
23
|
+
* isolated change behind `xt_alloc` plus root registration.
|
|
24
|
+
* * Strings are UTF-8. JavaScript measures string length in UTF-16 code
|
|
25
|
+
* units; `xt_string_length` currently reports code points (see README).
|
|
26
|
+
* * Objects use a small linear property list. Fine for the language subset
|
|
27
|
+
* xbintsc targets today; swap for a hash map when the profile demands it.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef XT_RT_INTERNAL_H
|
|
31
|
+
#define XT_RT_INTERNAL_H
|
|
32
|
+
|
|
33
|
+
#include "rt.h"
|
|
34
|
+
|
|
35
|
+
#include <stddef.h>
|
|
36
|
+
#include <stdint.h>
|
|
37
|
+
|
|
38
|
+
/* Allocation kinds recorded in `xt_header.kind`. */
|
|
39
|
+
#define XT_OBJECT_KIND_STRING 1
|
|
40
|
+
#define XT_OBJECT_KIND_OBJECT 2
|
|
41
|
+
#define XT_OBJECT_KIND_ARRAY 3
|
|
42
|
+
#define XT_OBJECT_KIND_FUNCTION 4
|
|
43
|
+
#define XT_OBJECT_KIND_PROMISE 5
|
|
44
|
+
#define XT_OBJECT_KIND_MAP 6
|
|
45
|
+
#define XT_OBJECT_KIND_SET 7
|
|
46
|
+
#define XT_OBJECT_KIND_DATE 8
|
|
47
|
+
#define XT_OBJECT_KIND_REGEXP 9
|
|
48
|
+
#define XT_OBJECT_KIND_SYMBOL 10
|
|
49
|
+
|
|
50
|
+
/* Common header for every heap object. */
|
|
51
|
+
typedef struct xt_header {
|
|
52
|
+
uint8_t kind;
|
|
53
|
+
uint8_t flags;
|
|
54
|
+
uint16_t reserved;
|
|
55
|
+
uint32_t size;
|
|
56
|
+
struct xt_header *gc_next;
|
|
57
|
+
} xt_header;
|
|
58
|
+
|
|
59
|
+
typedef struct {
|
|
60
|
+
xt_header header;
|
|
61
|
+
uint32_t length;
|
|
62
|
+
uint32_t capacity;
|
|
63
|
+
char *data;
|
|
64
|
+
} xt_string;
|
|
65
|
+
|
|
66
|
+
typedef struct {
|
|
67
|
+
xt_string *key;
|
|
68
|
+
xt_value value;
|
|
69
|
+
} xt_property;
|
|
70
|
+
|
|
71
|
+
typedef struct {
|
|
72
|
+
xt_header header;
|
|
73
|
+
uint32_t count;
|
|
74
|
+
uint32_t capacity;
|
|
75
|
+
xt_property *properties;
|
|
76
|
+
xt_value prototype;
|
|
77
|
+
uint8_t frozen;
|
|
78
|
+
uint8_t is_array_base;
|
|
79
|
+
uint16_t reserved2;
|
|
80
|
+
} xt_object;
|
|
81
|
+
|
|
82
|
+
typedef struct {
|
|
83
|
+
xt_header header;
|
|
84
|
+
uint32_t length;
|
|
85
|
+
uint32_t capacity;
|
|
86
|
+
xt_value *items;
|
|
87
|
+
} xt_array;
|
|
88
|
+
|
|
89
|
+
typedef struct {
|
|
90
|
+
xt_header header;
|
|
91
|
+
xt_code_fn code;
|
|
92
|
+
xt_value *environment;
|
|
93
|
+
int32_t environment_count;
|
|
94
|
+
int32_t arity;
|
|
95
|
+
xt_string *name;
|
|
96
|
+
xt_object *properties;
|
|
97
|
+
xt_value prototype;
|
|
98
|
+
} xt_function;
|
|
99
|
+
|
|
100
|
+
/* Allocation (xt_alloc.c). */
|
|
101
|
+
void *xt_alloc(size_t size, int kind);
|
|
102
|
+
|
|
103
|
+
/* Value / string helpers shared across translation units (xt_values.c). */
|
|
104
|
+
xt_string *xt_string_alloc(size_t length);
|
|
105
|
+
xt_string *xt_as_string(xt_value value);
|
|
106
|
+
int32_t xt_string_length(xt_string *s);
|
|
107
|
+
int xt_string_equals(xt_string *a, xt_string *b);
|
|
108
|
+
int32_t xt_to_int32(xt_value v);
|
|
109
|
+
|
|
110
|
+
/* Container helper (xt_containers.c). */
|
|
111
|
+
void xt_array_reserve(xt_array *array, uint32_t needed);
|
|
112
|
+
|
|
113
|
+
/* Object helpers used by the standard library. */
|
|
114
|
+
xt_object *xt_as_object(xt_value value);
|
|
115
|
+
xt_property *xt_object_find_property(xt_object *obj, xt_string *key);
|
|
116
|
+
|
|
117
|
+
/* Map / Set / Promise / Date / RegExp live in xt_stdlib.c and xt_promise.c. */
|
|
118
|
+
int xt_is_promise(xt_value value);
|
|
119
|
+
int xt_is_map(xt_value value);
|
|
120
|
+
int xt_is_set(xt_value value);
|
|
121
|
+
int xt_is_date(xt_value value);
|
|
122
|
+
int xt_is_regexp(xt_value value);
|
|
123
|
+
int32_t xt_map_size(xt_value value);
|
|
124
|
+
int32_t xt_set_size(xt_value value);
|
|
125
|
+
|
|
126
|
+
/* -- collection / date / regexp representations --------------------------- */
|
|
127
|
+
typedef struct {
|
|
128
|
+
xt_header header;
|
|
129
|
+
xt_value *keys;
|
|
130
|
+
xt_value *values;
|
|
131
|
+
uint32_t count;
|
|
132
|
+
uint32_t capacity;
|
|
133
|
+
} xt_map;
|
|
134
|
+
|
|
135
|
+
typedef struct {
|
|
136
|
+
xt_header header;
|
|
137
|
+
xt_value *values;
|
|
138
|
+
uint32_t count;
|
|
139
|
+
uint32_t capacity;
|
|
140
|
+
} xt_set_object;
|
|
141
|
+
|
|
142
|
+
typedef struct {
|
|
143
|
+
xt_header header;
|
|
144
|
+
double time;
|
|
145
|
+
} xt_date;
|
|
146
|
+
|
|
147
|
+
typedef struct {
|
|
148
|
+
xt_header header;
|
|
149
|
+
xt_value source;
|
|
150
|
+
xt_value flags;
|
|
151
|
+
} xt_regexp;
|
|
152
|
+
|
|
153
|
+
/* Extended method dispatch (xt_stdlib2.c). `*handled` is set when the method
|
|
154
|
+
* was recognised, allowing an intentional `undefined` result to be returned. */
|
|
155
|
+
xt_value xt_ext_array_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
156
|
+
xt_value xt_ext_string_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
157
|
+
xt_value xt_ext_number_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
158
|
+
xt_value xt_ext_object_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
159
|
+
xt_value xt_ext_container_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
160
|
+
xt_value xt_promise_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
|
|
161
|
+
|
|
162
|
+
/* JSON helpers used by Promise / Map immutability checks. */
|
|
163
|
+
int xt_value_equals(xt_value a, xt_value b);
|
|
164
|
+
|
|
165
|
+
/* Standard-library helpers (xt_stdlib.c). */
|
|
166
|
+
xt_array *xt_as_array(xt_value value);
|
|
167
|
+
xt_value xt_arg_at(int32_t argc, xt_value *argv, int32_t index);
|
|
168
|
+
|
|
169
|
+
#endif /* XT_RT_INTERNAL_H */
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc runtime — heap allocation.
|
|
3
|
+
*
|
|
4
|
+
* A bump-style arena shared by every object kind. Allocations are never
|
|
5
|
+
* reclaimed; the design keeps replacing this with a real collector isolated
|
|
6
|
+
* behind `xt_alloc` (see rt_internal.h).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include "rt_internal.h"
|
|
10
|
+
|
|
11
|
+
#include <stdio.h>
|
|
12
|
+
#include <stdlib.h>
|
|
13
|
+
|
|
14
|
+
/* ------------------------------------------------------------------------- */
|
|
15
|
+
/* Allocation */
|
|
16
|
+
/* ------------------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
static size_t g_heap_bytes = 0;
|
|
19
|
+
static size_t g_heap_allocations = 0;
|
|
20
|
+
static xt_header *g_heap_head = NULL;
|
|
21
|
+
|
|
22
|
+
void *xt_alloc(size_t size, int kind) {
|
|
23
|
+
xt_header *header = (xt_header *)calloc(1, size);
|
|
24
|
+
if (!header) {
|
|
25
|
+
fprintf(stderr, "xbintsc: out of memory allocating %zu bytes\n", size);
|
|
26
|
+
abort();
|
|
27
|
+
}
|
|
28
|
+
header->kind = (uint8_t)kind;
|
|
29
|
+
header->size = (uint32_t)size;
|
|
30
|
+
header->gc_next = g_heap_head;
|
|
31
|
+
g_heap_head = header;
|
|
32
|
+
g_heap_bytes += size;
|
|
33
|
+
g_heap_allocations++;
|
|
34
|
+
return header;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
size_t xt_heap_bytes(void) { return g_heap_bytes; }
|
|
38
|
+
size_t xt_heap_allocations(void) { return g_heap_allocations; }
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc runtime — builtins.
|
|
3
|
+
*
|
|
4
|
+
* `Object.*` statics and the free functions (`parseInt`, `isNaN`, `in`, ...),
|
|
5
|
+
* along with the closure representation and calling convention.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include "rt_internal.h"
|
|
9
|
+
|
|
10
|
+
#include <math.h>
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
#include <string.h>
|
|
13
|
+
|
|
14
|
+
/* ------------------------------------------------------------------------- */
|
|
15
|
+
/* Object methods and global functions */
|
|
16
|
+
/* ------------------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
xt_value xt_object_values(xt_value value) {
|
|
19
|
+
xt_value result = xt_array_new(0, NULL);
|
|
20
|
+
if (!XT_IS_OBJECT(value)) return result;
|
|
21
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
22
|
+
for (uint32_t i = 0; i < obj->count; i++) xt_array_push(result, obj->properties[i].value);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
xt_value xt_object_entries(xt_value value) {
|
|
27
|
+
xt_value result = xt_array_new(0, NULL);
|
|
28
|
+
if (!XT_IS_OBJECT(value)) return result;
|
|
29
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
30
|
+
for (uint32_t i = 0; i < obj->count; i++) {
|
|
31
|
+
xt_value pair = xt_array_new(0, NULL);
|
|
32
|
+
xt_array_push(pair, XT_FROM_PTR(XT_TAG_STRING, obj->properties[i].key));
|
|
33
|
+
xt_array_push(pair, obj->properties[i].value);
|
|
34
|
+
xt_array_push(result, pair);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
xt_value xt_object_assign(int32_t argc, xt_value *argv) {
|
|
40
|
+
if (argc <= 0) return xt_undefined();
|
|
41
|
+
xt_value target = argv[0];
|
|
42
|
+
if (!XT_IS_OBJECT(target)) return target;
|
|
43
|
+
for (int32_t i = 1; i < argc; i++) {
|
|
44
|
+
if (!XT_IS_OBJECT(argv[i])) continue;
|
|
45
|
+
xt_object *source = (xt_object *)XT_GET_PTR(argv[i]);
|
|
46
|
+
for (uint32_t j = 0; j < source->count; j++) {
|
|
47
|
+
xt_object_set(target, XT_FROM_PTR(XT_TAG_STRING, source->properties[j].key), source->properties[j].value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return target;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Copy every own enumerable property of `source` onto `target` (`{...source}`). */
|
|
54
|
+
xt_value xt_object_spread(xt_value target, xt_value source) {
|
|
55
|
+
xt_value args[2];
|
|
56
|
+
args[0] = target;
|
|
57
|
+
args[1] = source;
|
|
58
|
+
return xt_object_assign(2, args);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
xt_value xt_parse_int(int32_t argc, xt_value *argv) {
|
|
62
|
+
xt_string *s = xt_as_string(xt_to_string(xt_arg_at(argc, argv, 0)));
|
|
63
|
+
int32_t radix = argc >= 2 ? xt_to_int32(argv[1]) : 0;
|
|
64
|
+
char *end = NULL;
|
|
65
|
+
long value = strtol(s->data, &end, radix);
|
|
66
|
+
if (end == s->data) return xt_number(NAN);
|
|
67
|
+
return xt_number((double)value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
xt_value xt_parse_float(int32_t argc, xt_value *argv) {
|
|
71
|
+
xt_string *s = xt_as_string(xt_to_string(xt_arg_at(argc, argv, 0)));
|
|
72
|
+
char *end = NULL;
|
|
73
|
+
double value = strtod(s->data, &end);
|
|
74
|
+
if (end == s->data) return xt_number(NAN);
|
|
75
|
+
return xt_number(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
xt_value xt_is_nan(int32_t argc, xt_value *argv) {
|
|
79
|
+
double value = xt_to_number(xt_arg_at(argc, argv, 0));
|
|
80
|
+
return xt_bool(value != value);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
xt_value xt_is_finite(int32_t argc, xt_value *argv) {
|
|
84
|
+
double value = xt_to_number(xt_arg_at(argc, argv, 0));
|
|
85
|
+
return xt_bool(!isnan(value) && !isinf(value));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
xt_value xt_number_ctor(int32_t argc, xt_value *argv) {
|
|
89
|
+
if (argc == 0) return xt_number(0);
|
|
90
|
+
return xt_number(xt_to_number(argv[0]));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
xt_value xt_string_ctor(int32_t argc, xt_value *argv) {
|
|
94
|
+
if (argc == 0) return xt_string_from_cstr("");
|
|
95
|
+
return xt_to_string(argv[0]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
xt_value xt_boolean_ctor(int32_t argc, xt_value *argv) {
|
|
99
|
+
if (argc == 0) return XT_FALSE;
|
|
100
|
+
return xt_bool(xt_truthy(argv[0]));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
xt_value xt_in(xt_value key, xt_value value) {
|
|
104
|
+
if (XT_IS_OBJECT(value)) return xt_object_has(value, key);
|
|
105
|
+
if (XT_IS_ARRAY(value)) {
|
|
106
|
+
int32_t index = xt_to_int32(key);
|
|
107
|
+
return xt_bool(index >= 0 && (uint32_t)index < xt_as_array(value)->length);
|
|
108
|
+
}
|
|
109
|
+
if (XT_IS_STRING(value)) {
|
|
110
|
+
xt_string *s = xt_as_string(value);
|
|
111
|
+
xt_string *k = xt_as_string(xt_to_string(key));
|
|
112
|
+
if (k->length == 6 && memcmp(k->data, "length", 6) == 0) return XT_TRUE;
|
|
113
|
+
int32_t index = xt_to_int32(key);
|
|
114
|
+
return xt_bool(index >= 0 && (uint32_t)index < s->length);
|
|
115
|
+
}
|
|
116
|
+
return XT_FALSE;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
xt_value xt_delete(xt_value value, xt_value key) {
|
|
120
|
+
if (XT_IS_OBJECT(value)) {
|
|
121
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
122
|
+
xt_string *k = xt_as_string(xt_to_string(key));
|
|
123
|
+
for (uint32_t i = 0; i < obj->count; i++) {
|
|
124
|
+
if (xt_string_equals(obj->properties[i].key, k)) {
|
|
125
|
+
for (uint32_t j = i + 1; j < obj->count; j++) obj->properties[j - 1] = obj->properties[j];
|
|
126
|
+
obj->count--;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return XT_TRUE;
|
|
131
|
+
}
|
|
132
|
+
if (XT_IS_ARRAY(value)) {
|
|
133
|
+
xt_array_set(value, key, XT_UNDEFINED);
|
|
134
|
+
return XT_TRUE;
|
|
135
|
+
}
|
|
136
|
+
return XT_TRUE;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
xt_value xt_rest_args(int32_t argc, xt_value *argv, int32_t start) {
|
|
140
|
+
if (start < 0) start = 0;
|
|
141
|
+
int32_t count = argc - start;
|
|
142
|
+
if (count < 0) count = 0;
|
|
143
|
+
return xt_array_new(count, argv ? argv + start : NULL);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
/* ------------------------------------------------------------------------- */
|
|
148
|
+
/* Functions */
|
|
149
|
+
/* ------------------------------------------------------------------------- */
|
|
150
|
+
|
|
151
|
+
xt_value xt_arg(int32_t argc, xt_value *argv, int32_t index) {
|
|
152
|
+
if (index < 0 || index >= argc) return XT_UNDEFINED;
|
|
153
|
+
return argv[index];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
xt_value xt_closure_new(void *fn, int32_t env_count, xt_value *env) {
|
|
157
|
+
xt_function *function = (xt_function *)xt_alloc(sizeof(xt_function), XT_OBJECT_KIND_FUNCTION);
|
|
158
|
+
function->code = (xt_code_fn)fn;
|
|
159
|
+
function->environment_count = env_count;
|
|
160
|
+
function->arity = -1;
|
|
161
|
+
function->properties = NULL;
|
|
162
|
+
function->environment = NULL;
|
|
163
|
+
function->prototype = XT_UNDEFINED;
|
|
164
|
+
if (env_count > 0) {
|
|
165
|
+
function->environment = (xt_value *)malloc(sizeof(xt_value) * (size_t)env_count);
|
|
166
|
+
for (int32_t i = 0; i < env_count; i++) function->environment[i] = env[i];
|
|
167
|
+
}
|
|
168
|
+
return XT_FROM_PTR(XT_TAG_FUNCTION, function);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
xt_value xt_closure_call(xt_value value, int32_t argc, xt_value *argv) {
|
|
172
|
+
return xt_call_with_this(value, XT_UNDEFINED, argc, argv);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
xt_value xt_call_with_this(xt_value value, xt_value thisValue, int32_t argc, xt_value *argv) {
|
|
176
|
+
if (!XT_IS_FUNCTION(value)) {
|
|
177
|
+
xt_throw(xt_string_from_cstr("TypeError: value is not a function"));
|
|
178
|
+
return XT_UNDEFINED;
|
|
179
|
+
}
|
|
180
|
+
xt_function *function = (xt_function *)XT_GET_PTR(value);
|
|
181
|
+
/* The closure value itself is threaded through as `env` so the callee can
|
|
182
|
+
* read its captures with xt_closure_env(env, i). */
|
|
183
|
+
return function->code(thisValue, value, argc, argv);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
xt_value xt_this(void) { return XT_UNDEFINED; }
|
|
187
|
+
|
|
188
|
+
xt_value xt_function_set_prototype(xt_value value, xt_value proto) {
|
|
189
|
+
if (XT_IS_FUNCTION(value)) ((xt_function *)XT_GET_PTR(value))->prototype = proto;
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
xt_value xt_function_get_prototype(xt_value value) {
|
|
194
|
+
if (XT_IS_FUNCTION(value)) return ((xt_function *)XT_GET_PTR(value))->prototype;
|
|
195
|
+
return XT_UNDEFINED;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
xt_value xt_new(xt_value ctor, int32_t argc, xt_value *argv) {
|
|
199
|
+
if (!XT_IS_FUNCTION(ctor)) {
|
|
200
|
+
xt_throw(xt_string_from_cstr("TypeError: constructor is not a function"));
|
|
201
|
+
return XT_UNDEFINED;
|
|
202
|
+
}
|
|
203
|
+
xt_function *function = (xt_function *)XT_GET_PTR(ctor);
|
|
204
|
+
xt_value proto = function->prototype;
|
|
205
|
+
xt_value instance = xt_object_new_with_proto(XT_IS_OBJECT(proto) ? proto : XT_UNDEFINED);
|
|
206
|
+
xt_value result = function->code(instance, ctor, argc, argv);
|
|
207
|
+
if (XT_IS_OBJECT(result) || XT_IS_ARRAY(result)) return result;
|
|
208
|
+
return instance;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
xt_value xt_instance_of(xt_value value, xt_value ctor) {
|
|
212
|
+
if (!XT_IS_FUNCTION(ctor)) return XT_FALSE;
|
|
213
|
+
xt_value proto = ((xt_function *)XT_GET_PTR(ctor))->prototype;
|
|
214
|
+
if (!XT_IS_OBJECT(proto)) return XT_FALSE;
|
|
215
|
+
if (!XT_IS_OBJECT(value)) return XT_FALSE;
|
|
216
|
+
xt_object *cur = (xt_object *)XT_GET_PTR(value);
|
|
217
|
+
xt_object *target = (xt_object *)XT_GET_PTR(proto);
|
|
218
|
+
cur = (xt_object *)XT_GET_PTR(XT_IS_OBJECT(cur->prototype) ? cur->prototype : XT_UNDEFINED);
|
|
219
|
+
while (cur) {
|
|
220
|
+
if (cur == target) return XT_TRUE;
|
|
221
|
+
if (!XT_IS_OBJECT(cur->prototype)) break;
|
|
222
|
+
cur = (xt_object *)XT_GET_PTR(cur->prototype);
|
|
223
|
+
}
|
|
224
|
+
return XT_FALSE;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
xt_value xt_closure_env(xt_value value, int32_t index) {
|
|
228
|
+
if (!XT_IS_FUNCTION(value)) return XT_UNDEFINED;
|
|
229
|
+
xt_function *function = (xt_function *)XT_GET_PTR(value);
|
|
230
|
+
if (index < 0 || index >= function->environment_count) return XT_UNDEFINED;
|
|
231
|
+
return function->environment[index];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
int32_t xt_closure_arity(xt_value value) {
|
|
235
|
+
if (!XT_IS_FUNCTION(value)) return -1;
|
|
236
|
+
return ((xt_function *)XT_GET_PTR(value))->arity;
|
|
237
|
+
}
|
|
238
|
+
|