jaclang 0.8.8__py3-none-any.whl → 0.8.10__py3-none-any.whl

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.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (114) hide show
  1. jaclang/cli/cli.py +194 -10
  2. jaclang/cli/cmdreg.py +144 -8
  3. jaclang/compiler/__init__.py +6 -1
  4. jaclang/compiler/codeinfo.py +16 -1
  5. jaclang/compiler/constant.py +33 -8
  6. jaclang/compiler/jac.lark +154 -62
  7. jaclang/compiler/larkparse/jac_parser.py +2 -2
  8. jaclang/compiler/parser.py +656 -149
  9. jaclang/compiler/passes/__init__.py +2 -1
  10. jaclang/compiler/passes/ast_gen/__init__.py +5 -0
  11. jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
  12. jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
  13. jaclang/compiler/passes/ecmascript/__init__.py +25 -0
  14. jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
  15. jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
  16. jaclang/compiler/passes/ecmascript/estree.py +972 -0
  17. jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
  18. jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
  19. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
  20. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
  21. jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
  22. jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
  23. jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
  24. jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
  25. jaclang/compiler/passes/main/__init__.py +0 -3
  26. jaclang/compiler/passes/main/annex_pass.py +23 -1
  27. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  28. jaclang/compiler/passes/main/pyast_gen_pass.py +413 -255
  29. jaclang/compiler/passes/main/pyast_load_pass.py +48 -11
  30. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
  31. jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
  32. jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
  33. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
  34. jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
  35. jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
  36. jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
  37. jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -3
  38. jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
  39. jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
  40. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
  41. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
  42. jaclang/compiler/passes/main/type_checker_pass.py +7 -0
  43. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +219 -20
  44. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
  45. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
  46. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  47. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
  48. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
  49. jaclang/compiler/passes/transform.py +9 -1
  50. jaclang/compiler/passes/uni_pass.py +5 -7
  51. jaclang/compiler/program.py +27 -26
  52. jaclang/compiler/tests/test_client_codegen.py +113 -0
  53. jaclang/compiler/tests/test_importer.py +12 -10
  54. jaclang/compiler/tests/test_parser.py +249 -3
  55. jaclang/compiler/type_system/type_evaluator.jac +1078 -0
  56. jaclang/compiler/type_system/type_utils.py +1 -1
  57. jaclang/compiler/type_system/types.py +6 -0
  58. jaclang/compiler/unitree.py +438 -82
  59. jaclang/langserve/engine.jac +224 -288
  60. jaclang/langserve/sem_manager.jac +12 -8
  61. jaclang/langserve/server.jac +48 -48
  62. jaclang/langserve/tests/fixtures/greet.py +17 -0
  63. jaclang/langserve/tests/fixtures/md_path.jac +22 -0
  64. jaclang/langserve/tests/fixtures/user.jac +15 -0
  65. jaclang/langserve/tests/test_server.py +66 -371
  66. jaclang/lib.py +17 -0
  67. jaclang/runtimelib/archetype.py +25 -25
  68. jaclang/runtimelib/client_bundle.py +169 -0
  69. jaclang/runtimelib/client_runtime.jac +586 -0
  70. jaclang/runtimelib/constructs.py +4 -2
  71. jaclang/runtimelib/machine.py +308 -139
  72. jaclang/runtimelib/meta_importer.py +111 -22
  73. jaclang/runtimelib/mtp.py +15 -0
  74. jaclang/runtimelib/server.py +1089 -0
  75. jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
  76. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  77. jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
  78. jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
  79. jaclang/runtimelib/tests/test_client_bundle.py +55 -0
  80. jaclang/runtimelib/tests/test_client_render.py +63 -0
  81. jaclang/runtimelib/tests/test_serve.py +1069 -0
  82. jaclang/settings.py +0 -3
  83. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  84. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  85. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  86. jaclang/tests/fixtures/iife_functions.jac +142 -0
  87. jaclang/tests/fixtures/iife_functions_client.jac +143 -0
  88. jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
  89. jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
  90. jaclang/tests/fixtures/needs_import_dup.jac +6 -4
  91. jaclang/tests/fixtures/py2jac_empty.py +0 -0
  92. jaclang/tests/fixtures/py_run.py +7 -5
  93. jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
  94. jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
  95. jaclang/tests/test_cli.py +134 -18
  96. jaclang/tests/test_language.py +120 -32
  97. jaclang/tests/test_reference.py +20 -3
  98. jaclang/utils/NonGPT.py +375 -0
  99. jaclang/utils/helpers.py +64 -20
  100. jaclang/utils/lang_tools.py +31 -4
  101. jaclang/utils/tests/test_lang_tools.py +5 -16
  102. jaclang/utils/treeprinter.py +8 -3
  103. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
  104. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/RECORD +106 -71
  105. jaclang/compiler/passes/main/binder_pass.py +0 -594
  106. jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
  107. jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
  108. jaclang/compiler/type_system/type_evaluator.py +0 -844
  109. jaclang/langserve/tests/session.jac +0 -294
  110. jaclang/langserve/tests/test_dev_server.py +0 -80
  111. jaclang/runtimelib/importer.py +0 -351
  112. jaclang/tests/test_typecheck.py +0 -542
  113. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
  114. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,586 @@
1
+ """Client-side runtime for Jac JSX and walker interactions."""
2
+
3
+ # JSX factory function
4
+ cl def __jacJsx(tag: any, props: dict = {}, children: list = []) -> dict {
5
+ return {"tag": tag, "props": props, "children": children};
6
+ }
7
+
8
+ # DOM rendering function
9
+ cl def renderJsxTree(node: any, container: any) -> None {
10
+ container.replaceChildren(__buildDom(node));
11
+ }
12
+
13
+ # Internal: Build DOM from JSX tree
14
+ cl def __buildDom(node: any) -> any {
15
+ if node == None {
16
+ return document.createTextNode("");
17
+ }
18
+
19
+ if not __isObject(node) {
20
+ return document.createTextNode(String(node));
21
+ }
22
+
23
+ # Handle component functions
24
+ tag = node.get("tag");
25
+ if __isFunction(tag) {
26
+ props = node.get("props", {});
27
+ return __buildDom(tag(props));
28
+ }
29
+
30
+ # Create element
31
+ element = document.createElement(tag if tag else "div");
32
+
33
+ # Apply properties
34
+ props = node.get("props", {});
35
+ for key in __objectKeys(props) {
36
+ value = props.get(key);
37
+ __applyProp(element, key, value);
38
+ }
39
+
40
+ # Render children
41
+ children = node.get("children", []);
42
+ for child in children {
43
+ childDom = __buildDom(child);
44
+ if childDom {
45
+ element.appendChild(childDom);
46
+ }
47
+ }
48
+
49
+ return element;
50
+ }
51
+
52
+ # Internal: Apply property to DOM element
53
+ cl def __applyProp(element: any, key: str, value: any) -> None {
54
+ if key.startswith("on") {
55
+ # Event handler: onclick -> click
56
+ event = key[2:].lower();
57
+ element.addEventListener(event, value);
58
+ } elif key == "className" or key == "class" {
59
+ element.className = value;
60
+ } elif key == "style" and __isObject(value) {
61
+ # Style object
62
+ for styleKey in __objectKeys(value) {
63
+ element.style[styleKey] = value.get(styleKey);
64
+ }
65
+ } elif key != "children" {
66
+ element.setAttribute(key, String(value));
67
+ }
68
+ }
69
+
70
+ # Walker spawn function
71
+ cl async def __jacSpawn(walker: str, fields: dict = {}) -> any {
72
+ token = __getLocalStorage("jac_token");
73
+
74
+ response = await fetch(
75
+ f"/walker/{walker}",
76
+ {
77
+ "method": "POST",
78
+ "headers": {
79
+ "Content-Type": "application/json",
80
+ "Authorization": f"Bearer {token}" if token else ""
81
+ },
82
+ "body": JSON.stringify({"nd": "root", **fields})
83
+ }
84
+ );
85
+
86
+ if not response.ok {
87
+ error_text = await response.text();
88
+ raise Exception(f"Walker {walker} failed: {error_text}");
89
+ }
90
+
91
+ return JSON.parse(await response.text());
92
+ }
93
+
94
+ # Function call function - calls server-side functions from client
95
+ cl async def __jacCallFunction(function_name: str, args: dict = {}) -> any {
96
+ token = __getLocalStorage("jac_token");
97
+
98
+ response = await fetch(
99
+ f"/function/{function_name}",
100
+ {
101
+ "method": "POST",
102
+ "headers": {
103
+ "Content-Type": "application/json",
104
+ "Authorization": f"Bearer {token}" if token else ""
105
+ },
106
+ "body": JSON.stringify({"args": args})
107
+ }
108
+ );
109
+
110
+ if not response.ok {
111
+ error_text = await response.text();
112
+ raise Exception(f"Function {function_name} failed: {error_text}");
113
+ }
114
+
115
+ data = JSON.parse(await response.text());
116
+ return data.get("result");
117
+ }
118
+
119
+ # Authentication helpers
120
+ cl async def jacSignup(username: str, password: str) -> dict {
121
+ response = await fetch(
122
+ "/user/create",
123
+ {
124
+ "method": "POST",
125
+ "headers": {"Content-Type": "application/json"},
126
+ "body": JSON.stringify({"username": username, "password": password})
127
+ }
128
+ );
129
+
130
+ if response.ok {
131
+ data = JSON.parse(await response.text());
132
+ token = data.get("token");
133
+ if token {
134
+ __setLocalStorage("jac_token", token);
135
+ return {"success": True, "token": token, "username": username};
136
+ }
137
+ return {"success": False, "error": "No token received"};
138
+ } else {
139
+ error_text = await response.text();
140
+ try {
141
+ error_data = JSON.parse(error_text);
142
+ return {"success": False, "error": error_data.get("error", "Signup failed")};
143
+ } except Exception {
144
+ return {"success": False, "error": error_text};
145
+ }
146
+ }
147
+ }
148
+
149
+ cl async def jacLogin(username: str, password: str) -> bool {
150
+ response = await fetch(
151
+ "/user/login",
152
+ {
153
+ "method": "POST",
154
+ "headers": {"Content-Type": "application/json"},
155
+ "body": JSON.stringify({"username": username, "password": password})
156
+ }
157
+ );
158
+
159
+ if response.ok {
160
+ data = JSON.parse(await response.text());
161
+ token = data.get("token");
162
+ if token {
163
+ __setLocalStorage("jac_token", token);
164
+ return True;
165
+ }
166
+ }
167
+ return False;
168
+ }
169
+
170
+ cl def jacLogout() -> None {
171
+ __removeLocalStorage("jac_token");
172
+ }
173
+
174
+ cl def jacIsLoggedIn() -> bool {
175
+ token = __getLocalStorage("jac_token");
176
+ return token != None and token != "";
177
+ }
178
+
179
+ # Browser API shims
180
+ cl def __getLocalStorage(key: str) -> str {
181
+ storage = globalThis.localStorage;
182
+ return storage.getItem(key) if storage else "";
183
+ }
184
+
185
+ cl def __setLocalStorage(key: str, value: str) -> None {
186
+ storage = globalThis.localStorage;
187
+ if storage {
188
+ storage.setItem(key, value);
189
+ }
190
+ }
191
+
192
+ cl def __removeLocalStorage(key: str) -> None {
193
+ storage = globalThis.localStorage;
194
+ if storage {
195
+ storage.removeItem(key);
196
+ }
197
+ }
198
+
199
+ cl def __isObject(value: any) -> bool {
200
+ if value == None {
201
+ return False;
202
+ }
203
+ return Object.prototype.toString.call(value) == "[object Object]";
204
+ }
205
+
206
+ cl def __isFunction(value: any) -> bool {
207
+ return Object.prototype.toString.call(value) == "[object Function]";
208
+ }
209
+
210
+ cl def __objectKeys(obj: any) -> list {
211
+ if obj == None {
212
+ return [];
213
+ }
214
+ return Object.keys(obj);
215
+ }
216
+
217
+ # Low-level helpers
218
+ cl def __jacHasOwn(obj: any, key: any) -> bool {
219
+ try {
220
+ return Object.prototype.hasOwnProperty.call(obj, key);
221
+ } except Exception {
222
+ return False;
223
+ }
224
+ }
225
+
226
+ # Internal polyfill for Python-style dict.get on plain JS objects
227
+ cl def __jacEnsureObjectGetPolyfill() -> None {
228
+ proto = Object.prototype;
229
+ if proto.get {
230
+ return;
231
+ }
232
+
233
+ # Define the polyfill function inline
234
+ def get_polyfill(key: any, defaultValue: any = None) -> any {
235
+ if __jacHasOwn(this, key) {
236
+ return this[key];
237
+ }
238
+ if defaultValue != None {
239
+ return defaultValue;
240
+ }
241
+ return None;
242
+ }
243
+
244
+ Object.defineProperty(
245
+ proto,
246
+ "get",
247
+ {
248
+ "value": get_polyfill,
249
+ "configurable": True,
250
+ "writable": True
251
+ }
252
+ );
253
+ }
254
+
255
+ # Common utility helpers
256
+ cl def __jacGetDocument(scope: any) -> any {
257
+ try {
258
+ return scope.document;
259
+ } except Exception {
260
+ return None;
261
+ }
262
+ }
263
+
264
+ cl def __jacParseJsonObject(text: str) -> any {
265
+ try {
266
+ parsed = JSON.parse(text);
267
+ if __isObject(parsed) {
268
+ return parsed;
269
+ }
270
+ console.error("[Jac] Hydration payload is not an object");
271
+ return None;
272
+ } except Exception as err {
273
+ console.error("[Jac] Failed to parse hydration payload", err);
274
+ return None;
275
+ }
276
+ }
277
+
278
+ cl def __jacBuildOrderedArgs(order: list, argsDict: dict) -> list {
279
+ result = [];
280
+ if not order {
281
+ return result;
282
+ }
283
+ values = argsDict if __isObject(argsDict) else {};
284
+ for name in order {
285
+ result.push(values.get(name));
286
+ }
287
+ return result;
288
+ }
289
+
290
+ cl def __jacResolveRenderer(scope: any) -> any {
291
+ if scope.renderJsxTree {
292
+ return scope.renderJsxTree;
293
+ }
294
+ if __isFunction(renderJsxTree) {
295
+ return renderJsxTree;
296
+ }
297
+ return None;
298
+ }
299
+
300
+ cl def __jacResolveTarget(
301
+ moduleRecord: dict,
302
+ registry: dict,
303
+ name: str
304
+ ) -> any {
305
+ moduleFunctions = (
306
+ moduleRecord.moduleFunctions
307
+ if moduleRecord and moduleRecord.moduleFunctions
308
+ else {}
309
+ );
310
+ if __jacHasOwn(moduleFunctions, name) {
311
+ return moduleFunctions[name];
312
+ }
313
+ registryFunctions = (
314
+ registry.functions
315
+ if registry and registry.functions
316
+ else {}
317
+ );
318
+ if __jacHasOwn(registryFunctions, name) {
319
+ return registryFunctions[name];
320
+ }
321
+ return None;
322
+ }
323
+
324
+ cl def __jacSafeCallTarget(
325
+ target: any,
326
+ scope: any,
327
+ orderedArgs: list,
328
+ targetName: str
329
+ ) -> dict {
330
+ try {
331
+ result = target.apply(scope, orderedArgs);
332
+ return {"ok": True, "value": result};
333
+ } except Exception as err {
334
+ console.error("[Jac] Error executing client function " + targetName, err);
335
+ return {"ok": False, "value": None};
336
+ }
337
+ }
338
+
339
+ # Runtime support helpers for client module registration / hydration
340
+ cl def __jacGlobalScope() -> any {
341
+ try {
342
+ return globalThis;
343
+ } except Exception {}
344
+ try {
345
+ return window;
346
+ } except Exception {}
347
+ try {
348
+ return self;
349
+ } except Exception {}
350
+ return {};
351
+ }
352
+
353
+ cl def __jacEnsureRegistry() -> dict {
354
+ scope = __jacGlobalScope();
355
+ registry = scope.__jacClient;
356
+ if not registry {
357
+ registry = {
358
+ "functions": {},
359
+ "globals": {},
360
+ "modules": {},
361
+ "state": {"globals": {}},
362
+ "__hydration": {"registered": False},
363
+ "lastModule": None
364
+ };
365
+ scope.__jacClient = registry;
366
+ return registry;
367
+ }
368
+ if not registry.functions {
369
+ registry.functions = {};
370
+ }
371
+ if not registry.globals {
372
+ registry.globals = {};
373
+ }
374
+ if not registry.modules {
375
+ registry.modules = {};
376
+ }
377
+ if not registry.state {
378
+ registry.state = {"globals": {}};
379
+ } elif not registry.state.globals {
380
+ registry.state.globals = {};
381
+ }
382
+ if not registry.__hydration {
383
+ registry.__hydration = {"registered": False};
384
+ }
385
+ return registry;
386
+ }
387
+
388
+ cl def __jacApplyRender(renderer: any, container: any, node: any) -> None {
389
+ if not renderer or not container {
390
+ return;
391
+ }
392
+ try {
393
+ renderer(node, container);
394
+ } except Exception as err {
395
+ console.error("[Jac] Failed to render JSX tree", err);
396
+ }
397
+ }
398
+
399
+ cl def __jacHydrateFromDom(defaultModuleName: str) -> None {
400
+ __jacEnsureObjectGetPolyfill();
401
+ scope = __jacGlobalScope();
402
+ documentRef = __jacGetDocument(scope);
403
+ if not documentRef {
404
+ return;
405
+ }
406
+
407
+ initEl = documentRef.getElementById("__jac_init__");
408
+ rootEl = documentRef.getElementById("__jac_root");
409
+ if not initEl or not rootEl {
410
+ return;
411
+ }
412
+
413
+ dataset = initEl.dataset if initEl.dataset else None;
414
+ if dataset and dataset.jacHydrated == "true" {
415
+ return;
416
+ }
417
+ if dataset {
418
+ dataset.jacHydrated = "true";
419
+ }
420
+
421
+ payloadText = initEl.textContent if initEl.textContent else "{}";
422
+ payload = __jacParseJsonObject(payloadText);
423
+ if not payload {
424
+ return;
425
+ }
426
+
427
+ targetName = payload.get("function");
428
+ if not targetName {
429
+ return;
430
+ }
431
+
432
+ fallbackModule = defaultModuleName if defaultModuleName else "";
433
+ moduleCandidate = payload.get("module");
434
+ moduleName = moduleCandidate if moduleCandidate else fallbackModule;
435
+
436
+ registry = __jacEnsureRegistry();
437
+ modulesStore = registry.modules if registry.modules else {};
438
+ moduleRecord = modulesStore[moduleName] if __jacHasOwn(modulesStore, moduleName) else None;
439
+ if not moduleRecord {
440
+ console.error("[Jac] Client module not registered: " + moduleName);
441
+ return;
442
+ }
443
+
444
+ argOrderRaw = payload.get("argOrder", []);
445
+ argOrder = argOrderRaw if Array.isArray(argOrderRaw) else [];
446
+ argsDictRaw = payload.get("args", {});
447
+ argsDict = argsDictRaw if __isObject(argsDictRaw) else {};
448
+ orderedArgs = __jacBuildOrderedArgs(argOrder, argsDict);
449
+
450
+ payloadGlobalsRaw = payload.get("globals", {});
451
+ payloadGlobals = payloadGlobalsRaw if __isObject(payloadGlobalsRaw) else {};
452
+ registry.state.globals[moduleName] = payloadGlobals;
453
+ for gName in __objectKeys(payloadGlobals) {
454
+ gValue = payloadGlobals[gName];
455
+ scope[gName] = gValue;
456
+ registry.globals[gName] = gValue;
457
+ }
458
+
459
+ target = __jacResolveTarget(moduleRecord, registry, targetName);
460
+ if not target {
461
+ console.error("[Jac] Client function not found: " + targetName);
462
+ return;
463
+ }
464
+
465
+ renderer = __jacResolveRenderer(scope);
466
+ if not renderer {
467
+ console.warn("[Jac] renderJsxTree is not available in client bundle");
468
+ }
469
+
470
+ callOutcome = __jacSafeCallTarget(target, scope, orderedArgs, targetName);
471
+ if not callOutcome or not callOutcome.get("ok") {
472
+ return;
473
+ }
474
+ value = callOutcome.get("value");
475
+
476
+ if value and __isObject(value) and __isFunction(value.then) {
477
+ value.then(
478
+ lambda node: any -> None {
479
+ __jacApplyRender(renderer, rootEl, node);
480
+ }
481
+ ).catch(
482
+ lambda err: any -> None {
483
+ console.error("[Jac] Error resolving client function promise", err);
484
+ }
485
+ );
486
+ } else {
487
+ __jacApplyRender(renderer, rootEl, value);
488
+ }
489
+ }
490
+
491
+ cl def __jacExecuteHydration() -> None {
492
+ registry = __jacEnsureRegistry();
493
+ defaultModule = registry.lastModule if registry.lastModule else "";
494
+ __jacHydrateFromDom(defaultModule);
495
+ }
496
+
497
+ cl def __jacEnsureHydration(moduleName: str) -> None {
498
+ __jacEnsureObjectGetPolyfill();
499
+ registry = __jacEnsureRegistry();
500
+ registry.lastModule = moduleName;
501
+
502
+ existingHydration = registry.__hydration if registry.__hydration else None;
503
+ hydration = existingHydration if existingHydration else {"registered": False};
504
+ registry.__hydration = hydration;
505
+
506
+ scope = __jacGlobalScope();
507
+ documentRef = __jacGetDocument(scope);
508
+ if not documentRef {
509
+ return;
510
+ }
511
+
512
+ alreadyRegistered = hydration.registered if hydration.registered else False;
513
+ if not alreadyRegistered {
514
+ hydration.registered = True;
515
+ documentRef.addEventListener(
516
+ "DOMContentLoaded",
517
+ lambda _event: any -> None {
518
+ __jacExecuteHydration();
519
+ },
520
+ {"once": True}
521
+ );
522
+ }
523
+
524
+ if documentRef.readyState != "loading" {
525
+ __jacExecuteHydration();
526
+ }
527
+ }
528
+
529
+ cl def __jacRegisterClientModule(
530
+ moduleName: str,
531
+ clientFunctions: list = [],
532
+ clientGlobals: dict = {}
533
+ ) -> None {
534
+ __jacEnsureObjectGetPolyfill();
535
+ scope = __jacGlobalScope();
536
+ registry = __jacEnsureRegistry();
537
+
538
+ moduleFunctions = {};
539
+ registeredFunctions = [];
540
+ if clientFunctions {
541
+ for funcName in clientFunctions {
542
+ funcRef = scope[funcName];
543
+ if not funcRef {
544
+ console.error("[Jac] Client function not found during registration: " + funcName);
545
+ continue;
546
+ }
547
+ moduleFunctions[funcName] = funcRef;
548
+ registry.functions[funcName] = funcRef;
549
+ scope[funcName] = funcRef;
550
+ registeredFunctions.push(funcName);
551
+ }
552
+ }
553
+
554
+ moduleGlobals = {};
555
+ globalNames = [];
556
+ globalsMap = clientGlobals if clientGlobals else {};
557
+ for gName in __objectKeys(globalsMap) {
558
+ globalNames.push(gName);
559
+ defaultValue = globalsMap[gName];
560
+ existing = scope[gName];
561
+ if existing == None {
562
+ scope[gName] = defaultValue;
563
+ moduleGlobals[gName] = defaultValue;
564
+ } else {
565
+ moduleGlobals[gName] = existing;
566
+ }
567
+ registry.globals[gName] = scope[gName];
568
+ }
569
+
570
+ modulesStore = registry.modules if registry.modules else {};
571
+ existingRecord = modulesStore[moduleName] if __jacHasOwn(modulesStore, moduleName) else None;
572
+ moduleRecord = existingRecord if existingRecord else {};
573
+ moduleRecord.moduleFunctions = moduleFunctions;
574
+ moduleRecord.moduleGlobals = moduleGlobals;
575
+ moduleRecord.functions = registeredFunctions;
576
+ moduleRecord.globals = globalNames;
577
+ moduleRecord.defaults = globalsMap;
578
+ registry.modules[moduleName] = moduleRecord;
579
+
580
+ stateGlobals = registry.state.globals;
581
+ if not __jacHasOwn(stateGlobals, moduleName) {
582
+ stateGlobals[moduleName] = {};
583
+ }
584
+
585
+ __jacEnsureHydration(moduleName);
586
+ }
@@ -7,17 +7,18 @@ from .archetype import (
7
7
  AccessLevel,
8
8
  Anchor,
9
9
  Archetype,
10
- DataSpatialFunction,
11
10
  EdgeAnchor,
12
11
  EdgeArchetype,
13
12
  GenericEdge,
14
13
  NodeAnchor,
15
14
  NodeArchetype,
15
+ ObjectSpatialFunction,
16
16
  Root,
17
17
  WalkerAnchor,
18
18
  WalkerArchetype,
19
19
  )
20
20
  from .memory import Memory, ShelfStorage
21
+ from .mtp import MTIR
21
22
  from .test import JacTestCheck, JacTestResult, JacTextTestRunner
22
23
 
23
24
  __all__ = [
@@ -32,7 +33,8 @@ __all__ = [
32
33
  "WalkerArchetype",
33
34
  "GenericEdge",
34
35
  "Root",
35
- "DataSpatialFunction",
36
+ "MTIR",
37
+ "ObjectSpatialFunction",
36
38
  "Memory",
37
39
  "ShelfStorage",
38
40
  "JacTestResult",