novac 2.0.1 → 2.2.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/LICENSE +1 -1
- package/README.md +1574 -597
- package/bin/novac +468 -171
- package/bin/nvc +522 -0
- package/bin/nvml +78 -17
- package/demo.nv +0 -0
- package/demo_builtins.nv +0 -0
- package/demo_http.nv +0 -0
- package/examples/bf.nv +69 -0
- package/examples/math.nv +21 -0
- package/kits/birdAPI/kitdef.js +954 -0
- package/kits/kitRNG/kitdef.js +740 -0
- package/kits/kitSSH/kitdef.js +1272 -0
- package/kits/kitadb/kitdef.js +606 -0
- package/kits/kitai/kitdef.js +2185 -0
- package/kits/kitansi/kitdef.js +1402 -0
- package/kits/kitcanvas/kitdef.js +914 -0
- package/kits/kitclippy/kitdef.js +925 -0
- package/kits/kitformat/kitdef.js +1485 -0
- package/kits/kitgps/kitdef.js +1862 -0
- package/kits/kitlibproc/kitdef.js +3 -2
- package/kits/kitmatrix/ex.js +19 -0
- package/kits/kitmatrix/kitdef.js +960 -0
- package/kits/kitmorse/kitdef.js +229 -0
- package/kits/kitmpatch/kitdef.js +906 -0
- package/kits/kitnet/kitdef.js +1401 -0
- package/kits/kitnovacweb/README.md +1416 -143
- package/kits/kitnovacweb/kitdef.js +92 -2
- package/kits/kitnovacweb/nvml/executor.js +578 -176
- package/kits/kitnovacweb/nvml/index.js +2 -2
- package/kits/kitnovacweb/nvml/lexer.js +72 -69
- package/kits/kitnovacweb/nvml/parser.js +328 -159
- package/kits/kitnovacweb/nvml/renderer.js +770 -270
- package/kits/kitparse/kitdef.js +1688 -0
- package/kits/kitproto/kitdef.js +613 -0
- package/kits/kitqr/kitdef.js +637 -0
- package/kits/kitregex++/kitdef.js +1353 -0
- package/kits/kitrequire/kitdef.js +1599 -0
- package/kits/kitx11/kitdef.js +1 -0
- package/kits/kitx11/kitx11.js +2472 -0
- package/kits/kitx11/kitx11_conn.js +948 -0
- package/kits/kitx11/kitx11_worker.js +121 -0
- package/kits/libtea/kitdef.js +2691 -0
- package/kits/libterm/ex.js +285 -0
- package/kits/libterm/kitdef.js +1927 -0
- package/novac/LICENSE +21 -0
- package/novac/README.md +1823 -0
- package/novac/bin/novac +950 -0
- package/novac/bin/nvc +522 -0
- package/novac/bin/nvml +542 -0
- package/novac/demo.nv +245 -0
- package/novac/demo_builtins.nv +209 -0
- package/novac/demo_http.nv +62 -0
- package/novac/examples/bf.nv +69 -0
- package/novac/examples/math.nv +21 -0
- package/novac/kits/kitai/kitdef.js +2185 -0
- package/novac/kits/kitansi/kitdef.js +1402 -0
- package/novac/kits/kitformat/kitdef.js +1485 -0
- package/novac/kits/kitgps/kitdef.js +1862 -0
- package/novac/kits/kitlibfs/kitdef.js +231 -0
- package/{examples/example-project/nova_modules → novac/kits}/kitlibproc/kitdef.js +3 -2
- package/novac/kits/kitmatrix/ex.js +19 -0
- package/novac/kits/kitmatrix/kitdef.js +960 -0
- package/novac/kits/kitmpatch/kitdef.js +906 -0
- package/novac/kits/kitnovacweb/README.md +1572 -0
- package/novac/kits/kitnovacweb/demo.nv +12 -0
- package/novac/kits/kitnovacweb/demo.nvml +71 -0
- package/novac/kits/kitnovacweb/index.nova +12 -0
- package/novac/kits/kitnovacweb/kitdef.js +692 -0
- package/novac/kits/kitnovacweb/nova.kit.json +8 -0
- package/novac/kits/kitnovacweb/nvml/executor.js +739 -0
- package/novac/kits/kitnovacweb/nvml/index.js +67 -0
- package/novac/kits/kitnovacweb/nvml/lexer.js +263 -0
- package/novac/kits/kitnovacweb/nvml/parser.js +508 -0
- package/novac/kits/kitnovacweb/nvml/renderer.js +924 -0
- package/novac/kits/kitparse/kitdef.js +1688 -0
- package/novac/kits/kitregex++/kitdef.js +1353 -0
- package/novac/kits/kitrequire/kitdef.js +1599 -0
- package/novac/kits/kitx11/kitdef.js +1 -0
- package/novac/kits/kitx11/kitx11.js +2472 -0
- package/novac/kits/kitx11/kitx11_conn.js +948 -0
- package/novac/kits/kitx11/kitx11_worker.js +121 -0
- package/novac/kits/libtea/tf.js +2691 -0
- package/novac/kits/libterm/ex.js +285 -0
- package/novac/kits/libterm/kitdef.js +1927 -0
- package/novac/node_modules/chalk/license +9 -0
- package/novac/node_modules/chalk/package.json +83 -0
- package/novac/node_modules/chalk/readme.md +297 -0
- package/novac/node_modules/chalk/source/index.d.ts +325 -0
- package/novac/node_modules/chalk/source/index.js +225 -0
- package/novac/node_modules/chalk/source/utilities.js +33 -0
- package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
- package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
- package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
- package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
- package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
- package/novac/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
- package/novac/node_modules/commander/LICENSE +22 -0
- package/novac/node_modules/commander/Readme.md +1176 -0
- package/novac/node_modules/commander/esm.mjs +16 -0
- package/novac/node_modules/commander/index.js +24 -0
- package/novac/node_modules/commander/lib/argument.js +150 -0
- package/novac/node_modules/commander/lib/command.js +2777 -0
- package/novac/node_modules/commander/lib/error.js +39 -0
- package/novac/node_modules/commander/lib/help.js +747 -0
- package/novac/node_modules/commander/lib/option.js +380 -0
- package/novac/node_modules/commander/lib/suggestSimilar.js +101 -0
- package/novac/node_modules/commander/package-support.json +19 -0
- package/novac/node_modules/commander/package.json +82 -0
- package/novac/node_modules/commander/typings/esm.d.mts +3 -0
- package/novac/node_modules/commander/typings/index.d.ts +1113 -0
- package/novac/node_modules/node-addon-api/LICENSE.md +9 -0
- package/novac/node_modules/node-addon-api/README.md +95 -0
- package/novac/node_modules/node-addon-api/common.gypi +21 -0
- package/novac/node_modules/node-addon-api/except.gypi +25 -0
- package/novac/node_modules/node-addon-api/index.js +14 -0
- package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/novac/node_modules/node-addon-api/napi-inl.h +7165 -0
- package/novac/node_modules/node-addon-api/napi.h +3364 -0
- package/novac/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/novac/node_modules/node-addon-api/node_api.gyp +9 -0
- package/novac/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/novac/node_modules/node-addon-api/package-support.json +21 -0
- package/novac/node_modules/node-addon-api/package.json +480 -0
- package/novac/node_modules/node-addon-api/tools/README.md +73 -0
- package/novac/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/novac/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/novac/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/novac/node_modules/serialize-javascript/LICENSE +27 -0
- package/novac/node_modules/serialize-javascript/README.md +149 -0
- package/novac/node_modules/serialize-javascript/index.js +297 -0
- package/novac/node_modules/serialize-javascript/package.json +33 -0
- package/novac/package.json +27 -0
- package/novac/scripts/update-bin.js +24 -0
- package/novac/src/core/bstd.js +1035 -0
- package/novac/src/core/config.js +155 -0
- package/novac/src/core/describe.js +187 -0
- package/novac/src/core/emitter.js +499 -0
- package/novac/src/core/error.js +86 -0
- package/novac/src/core/executor.js +5606 -0
- package/novac/src/core/formatter.js +686 -0
- package/novac/src/core/lexer.js +1026 -0
- package/novac/src/core/nova_builtins.js +717 -0
- package/novac/src/core/nova_thread_worker.js +166 -0
- package/novac/src/core/parser.js +2181 -0
- package/novac/src/core/types.js +112 -0
- package/novac/src/index.js +28 -0
- package/novac/src/runtime/stdlib.js +244 -0
- package/package.json +6 -3
- package/scripts/update-bin.js +0 -0
- package/src/core/bstd.js +838 -362
- package/src/core/executor.js +2578 -170
- package/src/core/lexer.js +502 -54
- package/src/core/nova_builtins.js +21 -3
- package/src/core/parser.js +413 -72
- package/src/core/types.js +30 -2
- package/src/index.js +0 -0
- package/examples/example-project/README.md +0 -3
- package/examples/example-project/src/main.nova +0 -3
- package/src/core/environment.js +0 -0
- /package/{examples/example-project/bin/example-project.nv → novac/node_modules/node-addon-api/nothing.c} +0 -0
package/novac/demo.nv
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/! Nova Language v2 — Feature Showcase
|
|
2
|
+
let tcc
|
|
3
|
+
on "nv:tick" (ps) {tcc++}
|
|
4
|
+
// ── F-Strings ──
|
|
5
|
+
let name = "Nova";
|
|
6
|
+
core.print(f"Welcome to {name} v2!");
|
|
7
|
+
core.print(f"2^10 = {2**10}");
|
|
8
|
+
|
|
9
|
+
// ── Structs ──
|
|
10
|
+
struct Vec2 {
|
|
11
|
+
x: int = 0,
|
|
12
|
+
y: int = 0
|
|
13
|
+
}
|
|
14
|
+
let pos = Vec2({ x: 3, y: 4 });
|
|
15
|
+
core.print(f"pos = ({pos.x}, {pos.y})");
|
|
16
|
+
core.print(f"typeOf pos = {typeOf(pos)}");
|
|
17
|
+
|
|
18
|
+
// ── Enums ──
|
|
19
|
+
enum Status { Active, Inactive, Pending }
|
|
20
|
+
let st = Status.Active;
|
|
21
|
+
core.print(f"status = {st.__variant__}");
|
|
22
|
+
|
|
23
|
+
// ── Interfaces ──
|
|
24
|
+
interface Serializable { serialize() }
|
|
25
|
+
let doc = { serialize() { give "doc-json"; } };
|
|
26
|
+
let isSer = satisfies(doc, "Serializable");
|
|
27
|
+
core.print(f"satisfies Serializable: {isSer}");
|
|
28
|
+
|
|
29
|
+
// ── Pattern matching with range patterns ──
|
|
30
|
+
let score = 85;
|
|
31
|
+
match (score) {
|
|
32
|
+
when 90..100 { core.print("A grade"); }
|
|
33
|
+
when 80..89 { core.print("B grade"); }
|
|
34
|
+
when 70..79 { core.print("C grade"); }
|
|
35
|
+
default { core.print("Below C"); }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ── Pipe operator ──
|
|
39
|
+
func double(x) => { give x * 2; }
|
|
40
|
+
func addOne(x) => { give x + 1; }
|
|
41
|
+
let piped = 5 |> double |> addOne;
|
|
42
|
+
core.print(f"5 |> double |> addOne = {piped}");
|
|
43
|
+
|
|
44
|
+
// ── Each loop with index ──
|
|
45
|
+
let total = 0;
|
|
46
|
+
each n, i of [10, 20, 30, 40] {
|
|
47
|
+
total += n;
|
|
48
|
+
}
|
|
49
|
+
core.print(f"each total = {total}");
|
|
50
|
+
|
|
51
|
+
// ── Events ──
|
|
52
|
+
let tickCount = 0;
|
|
53
|
+
on "a" (count) {
|
|
54
|
+
tickCount += 1;
|
|
55
|
+
}
|
|
56
|
+
emit "a", 1;
|
|
57
|
+
emit "a", 2;
|
|
58
|
+
core.print(f"ticks received = {tickCount}");
|
|
59
|
+
|
|
60
|
+
// ── Where scoping ──
|
|
61
|
+
where (base = 100, taxRate = 0.15) {
|
|
62
|
+
let tax = base * taxRate;
|
|
63
|
+
print(f"tax = {tax}");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Array methods ──
|
|
67
|
+
let nums = [5, 3, 8, 1, 9, 2];
|
|
68
|
+
let evens = nums.filter(x => x % 2 == 0);
|
|
69
|
+
let doubled = nums.map(x => x * 2);
|
|
70
|
+
let sum = nums.reduce((acc, x) => acc + x, 0);
|
|
71
|
+
core.print(f"evens = {evens.join(", ")}");
|
|
72
|
+
core.print(f"doubled = {doubled.join(", ")}");
|
|
73
|
+
core.print(f"sum = {sum}");
|
|
74
|
+
core.print(f"sorted = {nums.sort().join(", ")}");
|
|
75
|
+
|
|
76
|
+
// ── Optional chaining ──
|
|
77
|
+
let user = { profile: { email: "a@b.com" } };
|
|
78
|
+
let email = user?.profile?.email;
|
|
79
|
+
let phone = user?.profile?.phone ?? "N/A";
|
|
80
|
+
core.print(f"email = {email}");
|
|
81
|
+
core.print(f"phone = {phone}");
|
|
82
|
+
|
|
83
|
+
// ── Spread / rest params ──
|
|
84
|
+
func stats(...ns) => {
|
|
85
|
+
let lo = ns.reduce((a, x) => a < x ? a : x);
|
|
86
|
+
let hi = ns.reduce((a, x) => a > x ? a : x);
|
|
87
|
+
give { min: lo, max: hi };
|
|
88
|
+
}
|
|
89
|
+
let st2 = stats(3, 7, 1, 9, 4);
|
|
90
|
+
core.print(f"min={st2.min} max={st2.max}");
|
|
91
|
+
|
|
92
|
+
// ── Nullish / logical assignment ──
|
|
93
|
+
let maybe = null;
|
|
94
|
+
maybe ??= "default";
|
|
95
|
+
core.print(f"nullish assign = {maybe}");
|
|
96
|
+
|
|
97
|
+
// ── Classes with inheritance ──
|
|
98
|
+
class Shape {
|
|
99
|
+
color: "black"
|
|
100
|
+
describe() { core.print(f"Shape ({this.color})"); }
|
|
101
|
+
}
|
|
102
|
+
class Circle extends Shape {
|
|
103
|
+
radius: 5
|
|
104
|
+
area() { give 3.14159 * this.radius * this.radius; }
|
|
105
|
+
describe() {
|
|
106
|
+
print(f"Circle r={this.radius} color={this.color}");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let c = Circle();
|
|
110
|
+
c.color = "red";
|
|
111
|
+
c.describe();
|
|
112
|
+
core.print(f"circle area = {c.area()}");
|
|
113
|
+
|
|
114
|
+
// ── Switch / case ──
|
|
115
|
+
let day = 3;
|
|
116
|
+
switch (day) {
|
|
117
|
+
case 1: core.print("Mon"); break;
|
|
118
|
+
case 2: core.print("Tue"); break;
|
|
119
|
+
case 3: core.print("Wed"); break;
|
|
120
|
+
default: core.print("Other"); break;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── Bitwise + range operators ──
|
|
124
|
+
core.print(f"6 & 3 = {6 & 3}");
|
|
125
|
+
core.print(f"6 | 3 = {6 | 3}");
|
|
126
|
+
core.print(f"2**10 = {2**10}");
|
|
127
|
+
core.print(f"5 in 1..10 = {5 in 1..10}");
|
|
128
|
+
|
|
129
|
+
// ── Assert ──
|
|
130
|
+
assert 2 + 2 == 4, "math broken";
|
|
131
|
+
assert typeof "x" == "string", "typeof broken";
|
|
132
|
+
core.print("all assertions passed");
|
|
133
|
+
|
|
134
|
+
// ── Preprocessor ──
|
|
135
|
+
#define LANG Nova
|
|
136
|
+
#define VER 2
|
|
137
|
+
core.print(f"Language: {LANG} v{VER}");
|
|
138
|
+
|
|
139
|
+
/! ── Nova Classic features demo ──
|
|
140
|
+
|
|
141
|
+
// foreach loop
|
|
142
|
+
let scores = { alice: 95, bob: 82, carol: 71 };
|
|
143
|
+
foreach(scores)(name, val) {
|
|
144
|
+
core.print(f" {name}: {val}");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// temp binding
|
|
148
|
+
let config = "production";
|
|
149
|
+
temp config = "test" => {
|
|
150
|
+
core.print(f"in temp scope: {config}");
|
|
151
|
+
}
|
|
152
|
+
core.print(f"after temp: {config}");
|
|
153
|
+
|
|
154
|
+
// keep (set-once)
|
|
155
|
+
keep serverPort = 8080;
|
|
156
|
+
keep serverPort = 9999;
|
|
157
|
+
core.print(f"port stays: {serverPort}");
|
|
158
|
+
|
|
159
|
+
// macro
|
|
160
|
+
macro VERSION = 2;
|
|
161
|
+
core.print(f"Nova v{VERSION}");
|
|
162
|
+
|
|
163
|
+
// addto
|
|
164
|
+
let evtLog = [];
|
|
165
|
+
addto evtLog "startup";
|
|
166
|
+
addto evtLog "ready";
|
|
167
|
+
core.print(f"log has {evtLog.length} entries");
|
|
168
|
+
|
|
169
|
+
// lambda
|
|
170
|
+
lambda square = x => x * x;
|
|
171
|
+
core.print(f"square(7) = {square(7)}");
|
|
172
|
+
|
|
173
|
+
// compose (fn pipeline with >>)
|
|
174
|
+
func trim(s) => { give s; }
|
|
175
|
+
func shout(s) => { give f"{s}!"; }
|
|
176
|
+
compose announce = trim >> shout;
|
|
177
|
+
core.print(announce("hello"));
|
|
178
|
+
|
|
179
|
+
// partial application
|
|
180
|
+
func multiply(a, b) => { give a * b; }
|
|
181
|
+
partial triple = multiply(3);
|
|
182
|
+
core.print(f"triple(7) = {triple(7)}");
|
|
183
|
+
|
|
184
|
+
// backup / retrieve
|
|
185
|
+
let userSession = "user_abc";
|
|
186
|
+
backup userSession = userSession;
|
|
187
|
+
let userSession = "guest";
|
|
188
|
+
retrieve userSession;
|
|
189
|
+
core.print(f"restored: {userSession}");
|
|
190
|
+
|
|
191
|
+
// Nova Classic infix operators
|
|
192
|
+
core.print(f"7 xor 7 = {7 xor 7}");
|
|
193
|
+
core.print(f"true nand true = {true nand true}");
|
|
194
|
+
let _numtype = "number"; core.print(f"42 istypeof number = {42 istypeof _numtype}");
|
|
195
|
+
let _hw = "hello"; let _pat = "hel"; core.print(f"hello matches hel = {_hw matches _pat}");
|
|
196
|
+
|
|
197
|
+
// set operations
|
|
198
|
+
let a = [1, 2, 3, 4];
|
|
199
|
+
let b = [3, 4, 5, 6];
|
|
200
|
+
core.print(f"intersect: {a intersect b}");
|
|
201
|
+
core.print(f"union: {a union b}");
|
|
202
|
+
core.print(f"diff: {a diff_arr b}");
|
|
203
|
+
|
|
204
|
+
// zip
|
|
205
|
+
let pairs = [1, 2, 3] zip ["a", "b", "c"];
|
|
206
|
+
core.print(f"zip[0]: {pairs[0][0]}-{pairs[0][1]}");
|
|
207
|
+
|
|
208
|
+
// numeric operators
|
|
209
|
+
core.print(f"8 avg 12 = {8 avg 12}");
|
|
210
|
+
core.print(f"gcd 12 8 = {12 gcd 8}");
|
|
211
|
+
core.print(f"lcm 4 6 = {4 lcm 6}");
|
|
212
|
+
|
|
213
|
+
// rate casts (typed casting)
|
|
214
|
+
core.print(f"rate(3.7) int = {rate(3.7) int}");
|
|
215
|
+
core.print(f"rate(300) u8 = {rate(300) u8}");
|
|
216
|
+
let _s = "hi"; core.print(f"rate(hi) char = {rate(_s) char}");
|
|
217
|
+
|
|
218
|
+
// classify
|
|
219
|
+
core.print(f"classify 42 as int = {classify 42 as int}");
|
|
220
|
+
core.print(f"classify type of 42 = {classify 42}");
|
|
221
|
+
|
|
222
|
+
// QAEs — query assertions / predicates
|
|
223
|
+
core.print(f"qae.prime(17) = {qae.prime(17)}");
|
|
224
|
+
let _rc="racecar"; core.print(f"qae.palindrome(racecar) = {qae.palindrome(_rc)}");
|
|
225
|
+
core.print(f"qae.even(8) = {qae.even(8)}");
|
|
226
|
+
core.print(f"qae.ascending([1,2,3]) = {qae.ascending([1,2,3])}");
|
|
227
|
+
|
|
228
|
+
// novaRegex — semantic regex
|
|
229
|
+
let emailRegex = novaRegex("<email>"); let _em = "a@b.com";
|
|
230
|
+
core.print(f"email match: {emailRegex.test(_em)}");
|
|
231
|
+
|
|
232
|
+
// step operator (range with step)
|
|
233
|
+
let evens = 0..10 step 2;
|
|
234
|
+
core.print(f"evens[0..3]: {evens[0]} {evens[1]} {evens[2]}");
|
|
235
|
+
|
|
236
|
+
// extend (object merge)
|
|
237
|
+
let base = { name: "Nova", version: 2 };
|
|
238
|
+
let ext = { stable: true };
|
|
239
|
+
let merged = base extend ext;
|
|
240
|
+
core.print(f"merged.stable = {merged.stable}");
|
|
241
|
+
|
|
242
|
+
// describe annotation
|
|
243
|
+
describe "Nova v2 feature showcase complete";
|
|
244
|
+
core.print("-- demo end --");
|
|
245
|
+
print('Total ticks: ' + tcc)
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/! Nova Built-in Objects + Unified Registry Demo
|
|
2
|
+
|
|
3
|
+
core.print("=== Unified nova Registry ===");
|
|
4
|
+
|
|
5
|
+
macro APP_NAME = NovaDemoApp;
|
|
6
|
+
macro BUILD = 2;
|
|
7
|
+
core.print(f"App: {nova.getMacro('APP_NAME')} build {nova.getMacro('BUILD')}");
|
|
8
|
+
core.print(f"Nova version: {nova.version}");
|
|
9
|
+
|
|
10
|
+
describe "Built-ins showcase";
|
|
11
|
+
core.print(f"descriptions: {nova.descriptions[0]}");
|
|
12
|
+
|
|
13
|
+
struct Config { host: string = "localhost", port: int = 8080 }
|
|
14
|
+
core.print(f"registered structs: {nova.types.structs[0]}");
|
|
15
|
+
|
|
16
|
+
let evResult = nova.eval("10 * 5 + 2");
|
|
17
|
+
core.print(f"nova.eval result: {evResult}");
|
|
18
|
+
|
|
19
|
+
core.print("\n=== ForLoop ===");
|
|
20
|
+
let squares = ForLoop({ from: 1, to: 5 }).map(i => i * i).collect();
|
|
21
|
+
core.print(f"squares: {squares.join(', ')}");
|
|
22
|
+
|
|
23
|
+
let evens = ForLoop({ from: 0, to: 20, step: 2 }).toArray();
|
|
24
|
+
core.print(f"evens[0..4]: {evens[0]} {evens[1]} {evens[2]} {evens[3]} {evens[4]}");
|
|
25
|
+
|
|
26
|
+
let sumResult = 0;
|
|
27
|
+
ForLoop({ from: 1, to: 100 }).do(i => { sumResult += i; }).run();
|
|
28
|
+
core.print(f"sum 1..100 = {sumResult}");
|
|
29
|
+
|
|
30
|
+
core.print("\n=== Pipeline ===");
|
|
31
|
+
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
32
|
+
let processed = Pipeline(data)
|
|
33
|
+
.filter(x => x % 2 == 0)
|
|
34
|
+
.map(x => x * x)
|
|
35
|
+
.take(4)
|
|
36
|
+
.collect();
|
|
37
|
+
core.print(f"pipeline result: {processed.join(', ')}");
|
|
38
|
+
|
|
39
|
+
let total = Pipeline([1, 2, 3, 4, 5]).reduce((acc, x) => acc + x, 0);
|
|
40
|
+
core.print(f"pipeline reduce: {total}");
|
|
41
|
+
|
|
42
|
+
core.print("\n=== IfBlock ===");
|
|
43
|
+
let score = 87;
|
|
44
|
+
let grade = IfBlock({ cond: score >= 90, then: () => "A" })
|
|
45
|
+
.elseIf(score >= 80, () => "B")
|
|
46
|
+
.elseIf(score >= 70, () => "C")
|
|
47
|
+
.else(() => "F")
|
|
48
|
+
.run();
|
|
49
|
+
core.print(f"grade for {score}: {grade}");
|
|
50
|
+
|
|
51
|
+
core.print("\n=== MatchBlock ===");
|
|
52
|
+
let status = MatchBlock(404)
|
|
53
|
+
.when(200, () => "OK")
|
|
54
|
+
.when(404, () => "Not Found")
|
|
55
|
+
.when(500, () => "Server Error")
|
|
56
|
+
.default(() => "Unknown")
|
|
57
|
+
.run();
|
|
58
|
+
core.print(f"HTTP 404 = {status}");
|
|
59
|
+
|
|
60
|
+
let rangeMatch = MatchBlock(75)
|
|
61
|
+
.when(90..100, x => "A")
|
|
62
|
+
.when(80..89, x => "B")
|
|
63
|
+
.when(70..79, x => "C")
|
|
64
|
+
.default(x => "F")
|
|
65
|
+
.run();
|
|
66
|
+
core.print(f"range match 75: {rangeMatch}");
|
|
67
|
+
|
|
68
|
+
core.print("\n=== TryCatch ===");
|
|
69
|
+
let caught = "";
|
|
70
|
+
TryCatch()
|
|
71
|
+
.try(() => { throw "oops"; })
|
|
72
|
+
.catch(e => { caught = e; })
|
|
73
|
+
.finally(() => core.print("finally ran"))
|
|
74
|
+
.run();
|
|
75
|
+
core.print(f"caught: {caught}");
|
|
76
|
+
|
|
77
|
+
core.print("\n=== Data Structures ===");
|
|
78
|
+
let stk = Stack();
|
|
79
|
+
stk.push(10); stk.push(20); stk.push(30);
|
|
80
|
+
core.print(f"Stack: push 10,20,30 → pop={stk.pop()} peek={stk.peek()}");
|
|
81
|
+
|
|
82
|
+
let que = Queue();
|
|
83
|
+
que.enqueue("first"); que.enqueue("second"); que.enqueue("third");
|
|
84
|
+
core.print(f"Queue: dequeue={que.dequeue()} size={que.size}");
|
|
85
|
+
|
|
86
|
+
let ll = LinkedList();
|
|
87
|
+
ll.push("a").push("b").push("c");
|
|
88
|
+
core.print(f"LinkedList size={ll.size} shift={ll.shift()} remaining={ll.size}");
|
|
89
|
+
|
|
90
|
+
let cnt = Counter(0);
|
|
91
|
+
cnt.increment(5); cnt.decrement(2); cnt.clamp(0, 10);
|
|
92
|
+
core.print(f"Counter: {cnt.value}");
|
|
93
|
+
|
|
94
|
+
core.print("\n=== State Machine ===");
|
|
95
|
+
let sm = State("idle");
|
|
96
|
+
sm.add("idle", "start", "running")
|
|
97
|
+
.add("running", "pause", "paused")
|
|
98
|
+
.add("paused", "resume","running")
|
|
99
|
+
.add("running", "done", "idle");
|
|
100
|
+
sm.onEnter("running", s => core.print(f" → entered {s}"));
|
|
101
|
+
sm.onExit("idle", s => core.print(f" ← leaving {s}"));
|
|
102
|
+
sm.dispatch("start");
|
|
103
|
+
sm.dispatch("pause");
|
|
104
|
+
sm.dispatch("resume");
|
|
105
|
+
sm.dispatch("done");
|
|
106
|
+
core.print(f"Final state: {sm.current}");
|
|
107
|
+
core.print(f"History: {sm.history.join(' → ')}");
|
|
108
|
+
|
|
109
|
+
core.print("\n=== Observable + Signal ===");
|
|
110
|
+
let obs = Observable(0);
|
|
111
|
+
let obsLog = [];
|
|
112
|
+
obs.subscribe(v => { addto obsLog v; });
|
|
113
|
+
obs.value = 10;
|
|
114
|
+
obs.value = 20;
|
|
115
|
+
obs.value = 30;
|
|
116
|
+
core.print(f"Observable changes: {obsLog.join(', ')}");
|
|
117
|
+
|
|
118
|
+
let sig = Signal(1);
|
|
119
|
+
let doubled = sig.derive(x => x * 2);
|
|
120
|
+
let quad = doubled.derive(x => x * 2);
|
|
121
|
+
core.print(f"Signal chain: {sig.value} → {doubled.value} → {quad.value}");
|
|
122
|
+
sig.value = 5;
|
|
123
|
+
core.print(f"After sig=5: {sig.value} → {doubled.value} → {quad.value}");
|
|
124
|
+
|
|
125
|
+
core.print("\n=== Validator ===");
|
|
126
|
+
let numV = Validator().required().type("number").min(0).max(100);
|
|
127
|
+
let r1 = numV.validate(50);
|
|
128
|
+
let r2 = numV.validate(-5);
|
|
129
|
+
let r3 = numV.validate(null);
|
|
130
|
+
core.print(f"validate(50): valid={r1.valid}");
|
|
131
|
+
core.print(f"validate(-5): valid={r2.valid} errors={r2.errors[0]}");
|
|
132
|
+
core.print(f"validate(null): valid={r3.valid} errors={r3.errors[0]}");
|
|
133
|
+
|
|
134
|
+
let emailV = Validator().email();
|
|
135
|
+
core.print(f"email ok: {emailV.validate('a@b.com').valid}");
|
|
136
|
+
core.print(f"email bad: {emailV.validate('notanemail').valid}");
|
|
137
|
+
|
|
138
|
+
core.print("\n=== DataStream ===");
|
|
139
|
+
let stream = DataStream([5, 3, 8, 1, 9, 2, 7, 4, 6]);
|
|
140
|
+
let top3 = stream.filter(x => x > 3).sort().reverse().take(3).collect();
|
|
141
|
+
core.print(f"top 3 > 3: {top3.join(', ')}");
|
|
142
|
+
|
|
143
|
+
let distinct = DataStream([1, 2, 2, 3, 3, 3, 4]).distinct().collect();
|
|
144
|
+
core.print(f"distinct: {distinct.join(', ')}");
|
|
145
|
+
|
|
146
|
+
core.print("\n=== Memo ===");
|
|
147
|
+
let calls = 0;
|
|
148
|
+
let expensiveFn = x => { calls++; give x * x * x; };
|
|
149
|
+
let memoFib = Memo(expensiveFn);
|
|
150
|
+
memoFib.call(5); memoFib.call(5); memoFib.call(5);
|
|
151
|
+
memoFib.call(3); memoFib.call(3);
|
|
152
|
+
core.print(f"Memo: 5 calls deduped to {calls} actual runs");
|
|
153
|
+
core.print(f"Stats: {memoFib.stats.hits} hits, {memoFib.stats.misses} misses");
|
|
154
|
+
|
|
155
|
+
core.print("\n=== Lazy ===");
|
|
156
|
+
let computed = false;
|
|
157
|
+
let lazy = Lazy(() => { computed = true; give "expensive result"; });
|
|
158
|
+
core.print(f"Before access: computed={computed}");
|
|
159
|
+
core.print(f"Value: {lazy.value}");
|
|
160
|
+
core.print(f"After access: computed={computed}");
|
|
161
|
+
core.print(f"Value again (cached): {lazy.value}");
|
|
162
|
+
|
|
163
|
+
core.print("\n=== Router ===");
|
|
164
|
+
let router = Router();
|
|
165
|
+
router.on("/api/users/(.*)", id => f"GET user {id}")
|
|
166
|
+
.on("/api/posts/(.*)", id => f"GET post {id}")
|
|
167
|
+
.on("/api/(.*)/delete", res => f"DELETE {res}")
|
|
168
|
+
.default(path => f"404: {path}");
|
|
169
|
+
|
|
170
|
+
core.print(router.dispatch("/api/users/42"));
|
|
171
|
+
core.print(router.dispatch("/api/posts/7"));
|
|
172
|
+
core.print(router.dispatch("/api/comments/delete"));
|
|
173
|
+
core.print(router.dispatch("/unknown"));
|
|
174
|
+
|
|
175
|
+
core.print("\n=== EventBus (standalone) ===");
|
|
176
|
+
let bus = EventBus();
|
|
177
|
+
let busLog = [];
|
|
178
|
+
bus.on("data", v => { addto busLog f"data:{v}"; });
|
|
179
|
+
bus.on("error", e => { addto busLog f"err:{e}"; });
|
|
180
|
+
bus.once("ready", () => { addto busLog "ready!"; });
|
|
181
|
+
bus.emit("ready");
|
|
182
|
+
bus.emit("data", 42);
|
|
183
|
+
bus.emit("data", 99);
|
|
184
|
+
bus.emit("error", "timeout");
|
|
185
|
+
bus.emit("ready"); // once — no second fire
|
|
186
|
+
core.print(f"Bus log: {busLog.join(', ')}");
|
|
187
|
+
|
|
188
|
+
core.print("\n=== Transformer ===");
|
|
189
|
+
let jsonT = TransformerJSON();
|
|
190
|
+
let encoded = jsonT.to({ name: "Nova", version: 2 });
|
|
191
|
+
core.print(f"JSON encode: {encoded}");
|
|
192
|
+
|
|
193
|
+
let b64T = TransformerBase64();
|
|
194
|
+
let b64enc = b64T.to("Hello Nova!");
|
|
195
|
+
let b64dec = b64T.from(b64enc);
|
|
196
|
+
core.print(f"Base64 round-trip: {b64dec}");
|
|
197
|
+
|
|
198
|
+
core.print("\n=== WhileLoop class ===");
|
|
199
|
+
let wn = 1;
|
|
200
|
+
WhileLoop({}).cond(() => wn < 32).do(() => { wn *= 2; }).run();
|
|
201
|
+
core.print(f"WhileLoop powers of 2: {wn}");
|
|
202
|
+
|
|
203
|
+
core.print("\n=== FuncDef ===");
|
|
204
|
+
let adder = FuncDef({ args: ["a", "b"], body: (a, b) => a + b }).named("add");
|
|
205
|
+
core.print(f"FuncDef call: {adder.call(10, 32)}");
|
|
206
|
+
let arrowFn = adder.toArrow();
|
|
207
|
+
core.print(f"FuncDef arrow: {arrowFn(7, 8)}");
|
|
208
|
+
|
|
209
|
+
core.print("\n-- builtins demo done --");
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/! Nova v2 — HTTP / Server feature demo
|
|
2
|
+
|
|
3
|
+
// ── 1. First-class URL token ──
|
|
4
|
+
let endpoint = https://jsonplaceholder.typicode.com/todos/1;
|
|
5
|
+
core.print(f"URL value: {endpoint}");
|
|
6
|
+
|
|
7
|
+
// ── 2. First-class HTTP method expression ──
|
|
8
|
+
core.print("Fetching todo via GET expression...");
|
|
9
|
+
let todo = get https://jsonplaceholder.typicode.com/todos/1();
|
|
10
|
+
core.print(f" title : {todo.body.title}");
|
|
11
|
+
core.print(f" status : {todo.status}");
|
|
12
|
+
core.print(f" ok : {todo.ok}");
|
|
13
|
+
|
|
14
|
+
// ── 3. Sync fetch() function ──
|
|
15
|
+
core.print("Fetching post via fetch()...");
|
|
16
|
+
let article = fetch("https://jsonplaceholder.typicode.com/posts/1");
|
|
17
|
+
core.print(f" article title: {article.body.title}");
|
|
18
|
+
|
|
19
|
+
// ── 4. fetch() statement form with => binding ──
|
|
20
|
+
fetch("https://jsonplaceholder.typicode.com/todos/2") => todo2;
|
|
21
|
+
core.print(f" todo2: {todo2.body.title}");
|
|
22
|
+
|
|
23
|
+
// ── 5. POST with body ──
|
|
24
|
+
core.print("POST request...");
|
|
25
|
+
let created = post https://jsonplaceholder.typicode.com/posts({ title: "Nova test", body: "hello", userId: 1 });
|
|
26
|
+
core.print(f" created id: {created.body.id}");
|
|
27
|
+
core.print(f" created status: {created.status}");
|
|
28
|
+
|
|
29
|
+
// ── 6. Server ──
|
|
30
|
+
core.print("Starting server on port 4242...");
|
|
31
|
+
server(4242) {
|
|
32
|
+
get "/hello"(req, res) {
|
|
33
|
+
return { message: "Hello from Nova!", method: req.method };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get "/echo/:msg"(req, res) {
|
|
37
|
+
return { echo: req.params.msg };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
post "/data"(req, res) {
|
|
41
|
+
let incoming = req.body;
|
|
42
|
+
return { received: true, data: incoming };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get "*"(req, res) {
|
|
46
|
+
res.status(404);
|
|
47
|
+
return { error: "Not found", path: req.path };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Hit the local server
|
|
52
|
+
core.print("Testing server with local requests...");
|
|
53
|
+
let r1 = get http://localhost:4242/hello();
|
|
54
|
+
core.print(f" /hello -> {r1.body.message}");
|
|
55
|
+
|
|
56
|
+
let r2 = get http://localhost:4242/echo/world();
|
|
57
|
+
core.print(f" /echo/world -> {r2.body.echo}");
|
|
58
|
+
|
|
59
|
+
let r3 = post http://localhost:4242/data({ name: "Nova", version: 2 });
|
|
60
|
+
core.print(f" /data received: {r3.body.received}");
|
|
61
|
+
|
|
62
|
+
core.print("All HTTP tests passed!");
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
let Tkit = includeKit("libterm");
|
|
2
|
+
let TView = Tkit.TView;
|
|
3
|
+
let Terminal = Tkit.Terminal;
|
|
4
|
+
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
// Boot Terminal (starts input, enters alt-screen, wires resize)
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
const term = Terminal({
|
|
10
|
+
altScreen: true,
|
|
11
|
+
mouse: true,
|
|
12
|
+
theme: 'dark',
|
|
13
|
+
logLevel: 'debug',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
// Layout: top bar / [left pane | right pane] / sensor bar / bottom bar
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
term.on('ready', async () => {
|
|
21
|
+
let view = term.createView();
|
|
22
|
+
let code = await view.prompt("Enter Brainfuck code:");
|
|
23
|
+
let input = await view.prompt("Enter input for Brainfuck code:");
|
|
24
|
+
let output = "";
|
|
25
|
+
let data = [0, 30000];
|
|
26
|
+
let dataPtr = 0;
|
|
27
|
+
let codePtr = 0;
|
|
28
|
+
while (codePtr < code.length) {
|
|
29
|
+
let cmd = code[codePtr];
|
|
30
|
+
if (cmd == '>') {
|
|
31
|
+
dataPtr++;
|
|
32
|
+
} else if (cmd == '<') {
|
|
33
|
+
dataPtr--;
|
|
34
|
+
} else if (cmd == '+') {
|
|
35
|
+
data[dataPtr] = (data[dataPtr] + 1) % 256;
|
|
36
|
+
} else if (cmd == '-') {
|
|
37
|
+
data[dataPtr] = (data[dataPtr] - 1) % 256;
|
|
38
|
+
} else if (cmd == '.') {
|
|
39
|
+
output += charAt(data[dataPtr]);
|
|
40
|
+
} else if (cmd == ',') {
|
|
41
|
+
if (input.length > 0) {
|
|
42
|
+
data[dataPtr] = (input[0]) as int;
|
|
43
|
+
input = input.substr(1);
|
|
44
|
+
} else {
|
|
45
|
+
data[dataPtr] = 0;
|
|
46
|
+
}
|
|
47
|
+
} else if (cmd == '[') {
|
|
48
|
+
if (data[dataPtr] == 0) {
|
|
49
|
+
let Loop = 1;
|
|
50
|
+
while (Loop > 0) {
|
|
51
|
+
codePtr++;
|
|
52
|
+
if (code[codePtr] == '[') Loop++;
|
|
53
|
+
else if (code[codePtr] == ']') Loop--;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} else if (cmd == ']') {
|
|
57
|
+
if (data[dataPtr] != 0) {
|
|
58
|
+
let Loop = 1;
|
|
59
|
+
while (Loop > 0) {
|
|
60
|
+
codePtr--;
|
|
61
|
+
if (code[codePtr] == ']') Loop++;
|
|
62
|
+
else if (code[codePtr] == '[') Loop--;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
codePtr++;
|
|
67
|
+
}
|
|
68
|
+
await view.writeText(0, 0, "Output: " + output, { color: 'green' });
|
|
69
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
let Tkit = includeKit("libterm");
|
|
2
|
+
let Terminal = Tkit.Terminal;
|
|
3
|
+
let parseExpr = includeKit('kitparse').parseExpr;
|
|
4
|
+
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
// Boot Terminal (starts input, enters alt-screen)
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
const term = Terminal({
|
|
10
|
+
altScreen: true,
|
|
11
|
+
mouse: true,
|
|
12
|
+
theme: 'dark',
|
|
13
|
+
logLevel: 'debug',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
term.on('ready', async () => {
|
|
17
|
+
let view = term.createView();
|
|
18
|
+
let code = await view.prompt("Enter Math:");
|
|
19
|
+
|
|
20
|
+
await view.writeText(0, 0, "Output: " + parseExpr(code), { color: 'green' });
|
|
21
|
+
})
|