jaclang 0.8.9__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.
- jaclang/cli/cli.py +147 -25
- jaclang/cli/cmdreg.py +144 -8
- jaclang/compiler/__init__.py +6 -1
- jaclang/compiler/codeinfo.py +16 -1
- jaclang/compiler/constant.py +33 -13
- jaclang/compiler/jac.lark +130 -31
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +567 -176
- jaclang/compiler/passes/__init__.py +2 -1
- jaclang/compiler/passes/ast_gen/__init__.py +5 -0
- jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
- jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
- jaclang/compiler/passes/ecmascript/__init__.py +25 -0
- jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
- jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
- jaclang/compiler/passes/ecmascript/estree.py +972 -0
- jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
- jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
- jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
- jaclang/compiler/passes/main/__init__.py +0 -3
- jaclang/compiler/passes/main/annex_pass.py +23 -1
- jaclang/compiler/passes/main/pyast_gen_pass.py +324 -234
- jaclang/compiler/passes/main/pyast_load_pass.py +46 -11
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
- jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
- jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -2
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
- jaclang/compiler/passes/main/type_checker_pass.py +7 -0
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +115 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
- jaclang/compiler/passes/transform.py +9 -1
- jaclang/compiler/passes/uni_pass.py +5 -7
- jaclang/compiler/program.py +22 -25
- jaclang/compiler/tests/test_client_codegen.py +113 -0
- jaclang/compiler/tests/test_importer.py +12 -10
- jaclang/compiler/tests/test_parser.py +249 -3
- jaclang/compiler/type_system/type_evaluator.jac +169 -50
- jaclang/compiler/type_system/type_utils.py +1 -1
- jaclang/compiler/type_system/types.py +6 -0
- jaclang/compiler/unitree.py +430 -84
- jaclang/langserve/engine.jac +224 -288
- jaclang/langserve/sem_manager.jac +12 -8
- jaclang/langserve/server.jac +48 -48
- jaclang/langserve/tests/fixtures/greet.py +17 -0
- jaclang/langserve/tests/fixtures/md_path.jac +22 -0
- jaclang/langserve/tests/fixtures/user.jac +15 -0
- jaclang/langserve/tests/test_server.py +66 -371
- jaclang/lib.py +1 -1
- jaclang/runtimelib/client_bundle.py +169 -0
- jaclang/runtimelib/client_runtime.jac +586 -0
- jaclang/runtimelib/constructs.py +2 -0
- jaclang/runtimelib/machine.py +259 -100
- jaclang/runtimelib/meta_importer.py +111 -22
- jaclang/runtimelib/mtp.py +15 -0
- jaclang/runtimelib/server.py +1089 -0
- jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
- jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
- jaclang/runtimelib/tests/test_client_bundle.py +55 -0
- jaclang/runtimelib/tests/test_client_render.py +63 -0
- jaclang/runtimelib/tests/test_serve.py +1069 -0
- jaclang/settings.py +0 -2
- jaclang/tests/fixtures/iife_functions.jac +142 -0
- jaclang/tests/fixtures/iife_functions_client.jac +143 -0
- jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
- jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
- jaclang/tests/fixtures/needs_import_dup.jac +6 -4
- jaclang/tests/fixtures/py_run.py +7 -5
- jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
- jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +10 -39
- jaclang/tests/test_reference.py +17 -2
- jaclang/utils/NonGPT.py +375 -0
- jaclang/utils/helpers.py +44 -16
- jaclang/utils/lang_tools.py +31 -4
- jaclang/utils/tests/test_lang_tools.py +1 -1
- jaclang/utils/treeprinter.py +8 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/RECORD +96 -66
- jaclang/compiler/passes/main/binder_pass.py +0 -594
- jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
- jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
- jaclang/langserve/tests/session.jac +0 -294
- jaclang/langserve/tests/test_dev_server.py +0 -80
- jaclang/runtimelib/importer.py +0 -351
- jaclang/tests/test_typecheck.py +0 -542
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
- {jaclang-0.8.9.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Sample Jac module containing client-side declarations."""
|
|
2
|
+
|
|
3
|
+
cl let API_LABEL: str = "Runtime Test";
|
|
4
|
+
|
|
5
|
+
cl obj ButtonProps {
|
|
6
|
+
has label: str = "Tap Me";
|
|
7
|
+
has color: str = "primary";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
cl def client_page() {
|
|
11
|
+
let props = ButtonProps(label="Tap Me", color="primary");
|
|
12
|
+
return <div class="app">
|
|
13
|
+
<h1>{API_LABEL}</h1>
|
|
14
|
+
<button class={props.color} data-id="button">
|
|
15
|
+
{props.label}
|
|
16
|
+
</button>
|
|
17
|
+
</div>;
|
|
18
|
+
}
|
|
@@ -43,10 +43,8 @@ walker create_custom_object {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
can exit1 with `root exit {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
print(jid(o));
|
|
49
|
-
print(o);
|
|
46
|
+
print(jid(self.obj));
|
|
47
|
+
print(self.obj);
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
50
|
|
|
@@ -87,6 +85,7 @@ walker delete_custom_object {
|
|
|
87
85
|
has object_id: str;
|
|
88
86
|
|
|
89
87
|
can enter1 with `root entry {
|
|
90
|
-
|
|
88
|
+
savable_object = &(self.object_id);
|
|
89
|
+
del savable_object;
|
|
91
90
|
}
|
|
92
91
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Example Jac program for REST API server."""
|
|
2
|
+
|
|
3
|
+
# Define some nodes
|
|
4
|
+
node Task {
|
|
5
|
+
has title: str;
|
|
6
|
+
has completed: bool = False;
|
|
7
|
+
has priority: int = 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
node User {
|
|
11
|
+
has name: str;
|
|
12
|
+
has email: str;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Define a walker to create tasks
|
|
16
|
+
walker CreateTask {
|
|
17
|
+
has title: str;
|
|
18
|
+
has priority: int = 1;
|
|
19
|
+
|
|
20
|
+
can create with `root entry {
|
|
21
|
+
task_list = here ++> Task(title=self.title, priority=self.priority);
|
|
22
|
+
task = task_list[0] if task_list else None;
|
|
23
|
+
if task {
|
|
24
|
+
print("Created task: " + task.title);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Define a walker to list all tasks
|
|
30
|
+
walker ListTasks {
|
|
31
|
+
has tasks: list = [];
|
|
32
|
+
|
|
33
|
+
can collect with `root entry {
|
|
34
|
+
visit [-->];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
can gather with Task entry {
|
|
38
|
+
print("Found task: " + here.title);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Define a walker to mark tasks as complete
|
|
43
|
+
walker CompleteTask {
|
|
44
|
+
has title: str;
|
|
45
|
+
|
|
46
|
+
can search with `root entry {
|
|
47
|
+
visit [-->];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
can mark_complete with Task entry {
|
|
51
|
+
if here.title == self.title {
|
|
52
|
+
here.completed = True;
|
|
53
|
+
print("Completed task: " + here.title);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
"""Function to add two numbers together."""
|
|
59
|
+
def add_numbers(a: int, b: int) -> int {
|
|
60
|
+
return a + b;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
"""Function to generate a greeting message."""
|
|
64
|
+
def greet(name: str = "World") -> str {
|
|
65
|
+
return "Hello, " + name + "!";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
cl let WELCOME_TITLE: str = "Runtime Test";
|
|
69
|
+
|
|
70
|
+
cl def client_page() {
|
|
71
|
+
return <section class="welcome">
|
|
72
|
+
<h1>{WELCOME_TITLE}</h1>
|
|
73
|
+
<p>{greet()}</p>
|
|
74
|
+
</section>;
|
|
75
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Tests for client bundle generation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from jaclang.runtimelib.client_bundle import ClientBundleBuilder
|
|
8
|
+
from jaclang.runtimelib.machine import JacMachine as Jac
|
|
9
|
+
from jaclang.utils.test import TestCase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ClientBundleBuilderTests(TestCase):
|
|
13
|
+
"""Validate client bundle compilation."""
|
|
14
|
+
|
|
15
|
+
def setUp(self) -> None:
|
|
16
|
+
Jac.reset_machine()
|
|
17
|
+
return super().setUp()
|
|
18
|
+
|
|
19
|
+
def tearDown(self) -> None:
|
|
20
|
+
Jac.reset_machine()
|
|
21
|
+
return super().tearDown()
|
|
22
|
+
|
|
23
|
+
def test_build_bundle_for_module(self) -> None:
|
|
24
|
+
"""Compile a Jac module and ensure client bundle metadata is emitted."""
|
|
25
|
+
fixtures_dir = Path(__file__).parent / "fixtures"
|
|
26
|
+
(module,) = Jac.jac_import("client_app", str(fixtures_dir))
|
|
27
|
+
|
|
28
|
+
builder = ClientBundleBuilder()
|
|
29
|
+
bundle = builder.build(module)
|
|
30
|
+
|
|
31
|
+
self.assertIn("function __jacJsx", bundle.code)
|
|
32
|
+
# Check that registration mechanism is present
|
|
33
|
+
self.assertIn('moduleFunctions[funcName] = funcRef;', bundle.code)
|
|
34
|
+
self.assertIn('scope[funcName] = funcRef;', bundle.code)
|
|
35
|
+
self.assertIn('moduleGlobals[gName] = existing;', bundle.code)
|
|
36
|
+
self.assertIn('scope[gName] = defaultValue;', bundle.code)
|
|
37
|
+
# Check that actual client functions and globals are defined
|
|
38
|
+
self.assertIn('function client_page()', bundle.code)
|
|
39
|
+
self.assertIn('class ButtonProps', bundle.code)
|
|
40
|
+
self.assertIn('const API_LABEL = "Runtime Test";', bundle.code)
|
|
41
|
+
# Check hydration logic is present
|
|
42
|
+
self.assertIn("__jacHydrateFromDom", bundle.code)
|
|
43
|
+
self.assertIn("__jacEnsureHydration", bundle.code)
|
|
44
|
+
self.assertIn('getElementById("__jac_init__")', bundle.code)
|
|
45
|
+
self.assertIn('getElementById("__jac_root")', bundle.code)
|
|
46
|
+
# Check globals iteration logic
|
|
47
|
+
self.assertIn("for (const gName of __objectKeys(payloadGlobals))", bundle.code)
|
|
48
|
+
self.assertIn("client_page", bundle.client_functions)
|
|
49
|
+
self.assertIn("ButtonProps", bundle.client_functions)
|
|
50
|
+
self.assertIn("API_LABEL", bundle.client_globals)
|
|
51
|
+
self.assertGreater(len(bundle.hash), 10)
|
|
52
|
+
|
|
53
|
+
cached = builder.build(module)
|
|
54
|
+
self.assertEqual(bundle.hash, cached.hash)
|
|
55
|
+
self.assertEqual(bundle.code, cached.code)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Offline tests for client page rendering without sockets."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from jaclang.runtimelib.machine import JacMachine as Jac
|
|
10
|
+
from jaclang.runtimelib.server import JacAPIServer
|
|
11
|
+
from jaclang.utils.test import TestCase
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ClientRenderTests(TestCase):
|
|
15
|
+
"""Validate client bundle helpers without opening sockets."""
|
|
16
|
+
|
|
17
|
+
def setUp(self) -> None:
|
|
18
|
+
Jac.reset_machine()
|
|
19
|
+
super().setUp()
|
|
20
|
+
|
|
21
|
+
def tearDown(self) -> None:
|
|
22
|
+
Jac.reset_machine()
|
|
23
|
+
super().tearDown()
|
|
24
|
+
|
|
25
|
+
def _make_server(self) -> JacAPIServer:
|
|
26
|
+
fixtures_dir = Path(__file__).parent / "fixtures"
|
|
27
|
+
Jac.jac_import("client_app", str(fixtures_dir))
|
|
28
|
+
server = JacAPIServer(
|
|
29
|
+
module_name="client_app", session_path=str(self.fixture_abs_path("client.session"))
|
|
30
|
+
)
|
|
31
|
+
server.load_module()
|
|
32
|
+
return server
|
|
33
|
+
|
|
34
|
+
def test_render_client_page_returns_html(self) -> None:
|
|
35
|
+
server = self._make_server()
|
|
36
|
+
server.user_manager.create_user("tester", "pass")
|
|
37
|
+
html_bundle = server.render_client_page("client_page", {}, "tester")
|
|
38
|
+
|
|
39
|
+
self.assertIn("<!DOCTYPE html>", html_bundle["html"])
|
|
40
|
+
self.assertIn('<div id="__jac_root"></div>', html_bundle["html"])
|
|
41
|
+
self.assertIn("/static/client.js?hash=", html_bundle["html"])
|
|
42
|
+
|
|
43
|
+
init_match = re.search(
|
|
44
|
+
r'<script id="__jac_init__" type="application/json">([^<]*)</script>',
|
|
45
|
+
html_bundle["html"],
|
|
46
|
+
)
|
|
47
|
+
self.assertIsNotNone(init_match)
|
|
48
|
+
payload = json.loads(init_match.group(1)) if init_match else {}
|
|
49
|
+
self.assertEqual(payload.get("module"), "client_app")
|
|
50
|
+
self.assertEqual(payload.get("function"), "client_page")
|
|
51
|
+
self.assertEqual(payload.get("globals", {}).get("API_LABEL"), "Runtime Test")
|
|
52
|
+
self.assertEqual(payload.get("argOrder"), [])
|
|
53
|
+
|
|
54
|
+
bundle_code = server.get_client_bundle_code()
|
|
55
|
+
self.assertIn("function __jacJsx", bundle_code)
|
|
56
|
+
self.assertEqual(bundle_code, html_bundle["bundle_code"])
|
|
57
|
+
|
|
58
|
+
def test_render_unknown_page_raises(self) -> None:
|
|
59
|
+
server = self._make_server()
|
|
60
|
+
server.user_manager.create_user("tester", "pass")
|
|
61
|
+
|
|
62
|
+
with self.assertRaises(ValueError):
|
|
63
|
+
server.render_client_page("missing", {}, "tester")
|