jsharp 0.1.0__tar.gz

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.
Files changed (41) hide show
  1. jsharp-0.1.0/LICENSE +21 -0
  2. jsharp-0.1.0/PKG-INFO +149 -0
  3. jsharp-0.1.0/README.md +122 -0
  4. jsharp-0.1.0/pyproject.toml +44 -0
  5. jsharp-0.1.0/setup.cfg +4 -0
  6. jsharp-0.1.0/src/jsharp/__init__.py +4 -0
  7. jsharp-0.1.0/src/jsharp/ast_nodes.py +173 -0
  8. jsharp-0.1.0/src/jsharp/builtins.py +59 -0
  9. jsharp-0.1.0/src/jsharp/bytecode.py +55 -0
  10. jsharp-0.1.0/src/jsharp/bytecode_io.py +151 -0
  11. jsharp-0.1.0/src/jsharp/cli.py +208 -0
  12. jsharp-0.1.0/src/jsharp/compiler.py +315 -0
  13. jsharp-0.1.0/src/jsharp/errors.py +77 -0
  14. jsharp-0.1.0/src/jsharp/lexer.py +244 -0
  15. jsharp-0.1.0/src/jsharp/parser.py +354 -0
  16. jsharp-0.1.0/src/jsharp/stdlib/__init__.py +5 -0
  17. jsharp-0.1.0/src/jsharp/stdlib/fs.py +14 -0
  18. jsharp-0.1.0/src/jsharp/stdlib/http.py +63 -0
  19. jsharp-0.1.0/src/jsharp/stdlib/io.py +133 -0
  20. jsharp-0.1.0/src/jsharp/stdlib/jsonlib.py +13 -0
  21. jsharp-0.1.0/src/jsharp/tokens.py +85 -0
  22. jsharp-0.1.0/src/jsharp/values.py +24 -0
  23. jsharp-0.1.0/src/jsharp/vm.py +324 -0
  24. jsharp-0.1.0/src/jsharp.egg-info/PKG-INFO +149 -0
  25. jsharp-0.1.0/src/jsharp.egg-info/SOURCES.txt +39 -0
  26. jsharp-0.1.0/src/jsharp.egg-info/dependency_links.txt +1 -0
  27. jsharp-0.1.0/src/jsharp.egg-info/entry_points.txt +2 -0
  28. jsharp-0.1.0/src/jsharp.egg-info/requires.txt +5 -0
  29. jsharp-0.1.0/src/jsharp.egg-info/top_level.txt +1 -0
  30. jsharp-0.1.0/tests/test_build_bytecode.py +17 -0
  31. jsharp-0.1.0/tests/test_compiler_vm_arith.py +21 -0
  32. jsharp-0.1.0/tests/test_compiler_vm_control_flow.py +30 -0
  33. jsharp-0.1.0/tests/test_compiler_vm_functions.py +16 -0
  34. jsharp-0.1.0/tests/test_compiler_vm_loop_control.py +79 -0
  35. jsharp-0.1.0/tests/test_dump_disasm.py +17 -0
  36. jsharp-0.1.0/tests/test_fn_literals.py +35 -0
  37. jsharp-0.1.0/tests/test_lexer.py +56 -0
  38. jsharp-0.1.0/tests/test_lists.py +62 -0
  39. jsharp-0.1.0/tests/test_native_compat.py +104 -0
  40. jsharp-0.1.0/tests/test_parser.py +53 -0
  41. jsharp-0.1.0/tests/test_web_bridge_smoke.py +57 -0
jsharp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 J# Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
jsharp-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: jsharp
3
+ Version: 0.1.0
4
+ Summary: J# language: lexer -> parser -> AST -> bytecode -> VM
5
+ Author: J# Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/jsharp-lang/jsharp
8
+ Project-URL: Repository, https://github.com/jsharp-lang/jsharp
9
+ Project-URL: Issues, https://github.com/jsharp-lang/jsharp/issues
10
+ Keywords: programming-language,bytecode,vm,compiler,education
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Compilers
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest; extra == "dev"
24
+ Requires-Dist: ruff; extra == "dev"
25
+ Requires-Dist: build; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # J# (J-sharp)
29
+
30
+ J# is a language project with a real execution pipeline:
31
+
32
+ `source (.jsh) -> lexer -> parser -> AST -> bytecode -> VM`
33
+
34
+ J# programs are not executed with Python `eval`/`exec`, and the runtime does not transpile J# source to Python/JS for execution.
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ cd jsharp
40
+ python -m pip install -e .
41
+ ```
42
+
43
+ If install is not available in your environment:
44
+
45
+ ```bash
46
+ python jsh.py run examples/hello.jsh
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ### Hello
52
+
53
+ ```bash
54
+ python jsh.py run examples/hello.jsh
55
+ ```
56
+
57
+ ### Web demo
58
+
59
+ ```bash
60
+ python jsh.py run examples/web.jsh
61
+ ```
62
+
63
+ Then open [http://localhost:8080](http://localhost:8080).
64
+
65
+ ### Dump and debug
66
+
67
+ ```bash
68
+ python jsh.py dump examples/hello.jsh
69
+ python jsh.py run --debug examples/hello.jsh
70
+ ```
71
+
72
+ ## CLI
73
+
74
+ - `python jsh.py run <file.jsh>`
75
+ - `python jsh.py run --debug <file.jsh>`
76
+ - `python jsh.py run --native <file.jsh>`
77
+ - `python jsh.py dump <file.jsh>`
78
+ - `python jsh.py build <file.jsh> -o out.jbc`
79
+
80
+ If installed as a package, `jsh` is available as a console script.
81
+
82
+ ## Architecture (text diagram)
83
+
84
+ ```text
85
+ .jsh source
86
+ |
87
+ v
88
+ Lexer -> token stream
89
+ |
90
+ v
91
+ Parser -> AST
92
+ |
93
+ v
94
+ Compiler -> bytecode chunks (per function)
95
+ |
96
+ v
97
+ VM (stack + frames + globals)
98
+ ```
99
+
100
+ ## Current Feature Set (v0.1)
101
+
102
+ - Function declarations and function literals
103
+ - `let`, assignment, `if/else`, `while`, `break`, `continue`, `return`
104
+ - Numbers, strings, bools, none
105
+ - Lists (`[1,2,3]`), indexing (`a[i]`), indexed assignment (`a[i] = x`)
106
+ - Calls, attribute access, short-circuit `&&` / `||`
107
+ - Stdlib objects: `http`, `io`, `fs`, `json`
108
+ - Builtins: `print`, `len`, `div`
109
+
110
+ ## Competitive Programming
111
+
112
+ Use the `io` module for fast buffered input/output.
113
+
114
+ - `examples/cp_sum.jsh`
115
+ - `examples/cp_minmax.jsh`
116
+ - `examples/cp_prefix_sum.jsh`
117
+ - Full guide: `docs/cp-guide.md`
118
+
119
+ ## Native Runtime Path
120
+
121
+ - `python jsh.py build file.jsh -o file.jbc` emits serialized bytecode.
122
+ - `python jsh.py run --native file.jsh` compiles to temp `.jbc` and executes `jsh-native` when available.
123
+ - If `jsh-native` is unavailable, CLI prints guidance and falls back to Python VM execution.
124
+ - Bytecode format spec: `docs/bytecode-spec.md`
125
+
126
+ ## Roadmap Summary
127
+
128
+ Near-term goals:
129
+ - expand stdlib and diagnostics,
130
+ - strengthen Python/native runtime compatibility tests,
131
+ - keep web demo smooth in Python VM path,
132
+ - improve performance with targeted compiler/VM optimizations.
133
+
134
+ Detailed plans: `docs/roadmap.md`.
135
+
136
+ ## Project Docs
137
+
138
+ - `LANGUAGE_REFERENCE.md`
139
+ - `docs/getting-started.md`
140
+ - `docs/standard-library.md`
141
+ - `docs/internals.md`
142
+ - `docs/cp-guide.md`
143
+ - `docs/bytecode-spec.md`
144
+ - `docs/roadmap.md`
145
+
146
+ ## Limitations (current)
147
+
148
+ - Closures/captures are intentionally disabled in v0.1 function literals.
149
+ - Native VM path is focused on CP/runtime core; Python VM remains the primary path for full web demo behavior.
jsharp-0.1.0/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # J# (J-sharp)
2
+
3
+ J# is a language project with a real execution pipeline:
4
+
5
+ `source (.jsh) -> lexer -> parser -> AST -> bytecode -> VM`
6
+
7
+ J# programs are not executed with Python `eval`/`exec`, and the runtime does not transpile J# source to Python/JS for execution.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ cd jsharp
13
+ python -m pip install -e .
14
+ ```
15
+
16
+ If install is not available in your environment:
17
+
18
+ ```bash
19
+ python jsh.py run examples/hello.jsh
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Hello
25
+
26
+ ```bash
27
+ python jsh.py run examples/hello.jsh
28
+ ```
29
+
30
+ ### Web demo
31
+
32
+ ```bash
33
+ python jsh.py run examples/web.jsh
34
+ ```
35
+
36
+ Then open [http://localhost:8080](http://localhost:8080).
37
+
38
+ ### Dump and debug
39
+
40
+ ```bash
41
+ python jsh.py dump examples/hello.jsh
42
+ python jsh.py run --debug examples/hello.jsh
43
+ ```
44
+
45
+ ## CLI
46
+
47
+ - `python jsh.py run <file.jsh>`
48
+ - `python jsh.py run --debug <file.jsh>`
49
+ - `python jsh.py run --native <file.jsh>`
50
+ - `python jsh.py dump <file.jsh>`
51
+ - `python jsh.py build <file.jsh> -o out.jbc`
52
+
53
+ If installed as a package, `jsh` is available as a console script.
54
+
55
+ ## Architecture (text diagram)
56
+
57
+ ```text
58
+ .jsh source
59
+ |
60
+ v
61
+ Lexer -> token stream
62
+ |
63
+ v
64
+ Parser -> AST
65
+ |
66
+ v
67
+ Compiler -> bytecode chunks (per function)
68
+ |
69
+ v
70
+ VM (stack + frames + globals)
71
+ ```
72
+
73
+ ## Current Feature Set (v0.1)
74
+
75
+ - Function declarations and function literals
76
+ - `let`, assignment, `if/else`, `while`, `break`, `continue`, `return`
77
+ - Numbers, strings, bools, none
78
+ - Lists (`[1,2,3]`), indexing (`a[i]`), indexed assignment (`a[i] = x`)
79
+ - Calls, attribute access, short-circuit `&&` / `||`
80
+ - Stdlib objects: `http`, `io`, `fs`, `json`
81
+ - Builtins: `print`, `len`, `div`
82
+
83
+ ## Competitive Programming
84
+
85
+ Use the `io` module for fast buffered input/output.
86
+
87
+ - `examples/cp_sum.jsh`
88
+ - `examples/cp_minmax.jsh`
89
+ - `examples/cp_prefix_sum.jsh`
90
+ - Full guide: `docs/cp-guide.md`
91
+
92
+ ## Native Runtime Path
93
+
94
+ - `python jsh.py build file.jsh -o file.jbc` emits serialized bytecode.
95
+ - `python jsh.py run --native file.jsh` compiles to temp `.jbc` and executes `jsh-native` when available.
96
+ - If `jsh-native` is unavailable, CLI prints guidance and falls back to Python VM execution.
97
+ - Bytecode format spec: `docs/bytecode-spec.md`
98
+
99
+ ## Roadmap Summary
100
+
101
+ Near-term goals:
102
+ - expand stdlib and diagnostics,
103
+ - strengthen Python/native runtime compatibility tests,
104
+ - keep web demo smooth in Python VM path,
105
+ - improve performance with targeted compiler/VM optimizations.
106
+
107
+ Detailed plans: `docs/roadmap.md`.
108
+
109
+ ## Project Docs
110
+
111
+ - `LANGUAGE_REFERENCE.md`
112
+ - `docs/getting-started.md`
113
+ - `docs/standard-library.md`
114
+ - `docs/internals.md`
115
+ - `docs/cp-guide.md`
116
+ - `docs/bytecode-spec.md`
117
+ - `docs/roadmap.md`
118
+
119
+ ## Limitations (current)
120
+
121
+ - Closures/captures are intentionally disabled in v0.1 function literals.
122
+ - Native VM path is focused on CP/runtime core; Python VM remains the primary path for full web demo behavior.
@@ -0,0 +1,44 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "jsharp"
7
+ version = "0.1.0"
8
+ description = "J# language: lexer -> parser -> AST -> bytecode -> VM"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "J# Contributors" }]
13
+ keywords = ["programming-language", "bytecode", "vm", "compiler", "education"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Topic :: Software Development :: Compilers",
23
+ ]
24
+ dependencies = []
25
+
26
+ [project.optional-dependencies]
27
+ dev = ["pytest", "ruff", "build"]
28
+
29
+ [project.scripts]
30
+ jsh = "jsharp.cli:main"
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/jsharp-lang/jsharp"
34
+ Repository = "https://github.com/jsharp-lang/jsharp"
35
+ Issues = "https://github.com/jsharp-lang/jsharp/issues"
36
+
37
+ [tool.setuptools]
38
+ package-dir = {"" = "src"}
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["src"]
42
+
43
+ [tool.pytest.ini_options]
44
+ pythonpath = ["src"]
jsharp-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ """J# language implementation package."""
2
+
3
+ __all__ = ["__version__"]
4
+ __version__ = "0.1.0"
@@ -0,0 +1,173 @@
1
+ """AST dataclasses for J#. Keep this file simple and beginner-readable."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Optional
7
+
8
+
9
+ @dataclass
10
+ class Program:
11
+ functions: list["FnDecl"]
12
+
13
+
14
+ @dataclass
15
+ class FnDecl:
16
+ name: str
17
+ params: list[str]
18
+ body: list["Stmt"]
19
+ line: int
20
+ col: int
21
+
22
+
23
+ class Stmt:
24
+ pass
25
+
26
+
27
+ @dataclass
28
+ class LetStmt(Stmt):
29
+ name: str
30
+ expr: "Expr"
31
+ line: int
32
+ col: int
33
+
34
+
35
+ @dataclass
36
+ class AssignStmt(Stmt):
37
+ name: str
38
+ expr: "Expr"
39
+ line: int
40
+ col: int
41
+
42
+
43
+ @dataclass
44
+ class IndexSetStmt(Stmt):
45
+ obj: "Expr"
46
+ index: "Expr"
47
+ value: "Expr"
48
+ line: int
49
+ col: int
50
+
51
+
52
+ @dataclass
53
+ class ExprStmt(Stmt):
54
+ expr: "Expr"
55
+ line: int
56
+ col: int
57
+
58
+
59
+ @dataclass
60
+ class IfStmt(Stmt):
61
+ cond: "Expr"
62
+ then_body: list[Stmt]
63
+ else_body: Optional[list[Stmt]]
64
+ line: int
65
+ col: int
66
+
67
+
68
+ @dataclass
69
+ class WhileStmt(Stmt):
70
+ cond: "Expr"
71
+ body: list[Stmt]
72
+ line: int
73
+ col: int
74
+
75
+
76
+ @dataclass
77
+ class BreakStmt(Stmt):
78
+ line: int
79
+ col: int
80
+
81
+
82
+ @dataclass
83
+ class ContinueStmt(Stmt):
84
+ line: int
85
+ col: int
86
+
87
+
88
+ @dataclass
89
+ class ReturnStmt(Stmt):
90
+ value: Optional["Expr"]
91
+ line: int
92
+ col: int
93
+
94
+
95
+ class Expr:
96
+ pass
97
+
98
+
99
+ @dataclass
100
+ class LiteralExpr(Expr):
101
+ value: object
102
+ line: int
103
+ col: int
104
+
105
+
106
+ @dataclass
107
+ class ListLitExpr(Expr):
108
+ items: list["Expr"]
109
+ line: int
110
+ col: int
111
+
112
+
113
+ @dataclass
114
+ class VarExpr(Expr):
115
+ name: str
116
+ line: int
117
+ col: int
118
+
119
+
120
+ @dataclass
121
+ class UnaryExpr(Expr):
122
+ op: str
123
+ right: Expr
124
+ line: int
125
+ col: int
126
+
127
+
128
+ @dataclass
129
+ class BinaryExpr(Expr):
130
+ left: Expr
131
+ op: str
132
+ right: Expr
133
+ line: int
134
+ col: int
135
+
136
+
137
+ @dataclass
138
+ class CallExpr(Expr):
139
+ callee: Expr
140
+ args: list[Expr]
141
+ line: int
142
+ col: int
143
+
144
+
145
+ @dataclass
146
+ class GetAttrExpr(Expr):
147
+ obj: Expr
148
+ name: str
149
+ line: int
150
+ col: int
151
+
152
+
153
+ @dataclass
154
+ class IndexGetExpr(Expr):
155
+ obj: Expr
156
+ index: Expr
157
+ line: int
158
+ col: int
159
+
160
+
161
+ @dataclass
162
+ class GroupExpr(Expr):
163
+ expr: Expr
164
+ line: int
165
+ col: int
166
+
167
+
168
+ @dataclass
169
+ class FnLitExpr(Expr):
170
+ params: list[str]
171
+ body: list[Stmt]
172
+ line: int
173
+ col: int
@@ -0,0 +1,59 @@
1
+ """Builtin/native symbols registered in VM.globals."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from jsharp.stdlib import fs, http, io, jsonlib
6
+ from jsharp.stdlib.io import IOState
7
+ from jsharp.values import NativeFn
8
+
9
+
10
+ def _native_print(vm, *args):
11
+ print(*args)
12
+ return None
13
+
14
+
15
+ def _native_len(vm, value):
16
+ try:
17
+ return len(value)
18
+ except TypeError as exc:
19
+ raise RuntimeError(f"len() not supported for type {type(value).__name__}") from exc
20
+
21
+
22
+ def _native_div(vm, a, b):
23
+ if isinstance(a, bool) or isinstance(b, bool) or not isinstance(a, int) or not isinstance(b, int):
24
+ raise RuntimeError("div(a,b) expects integer arguments")
25
+ if b == 0:
26
+ raise RuntimeError("division by zero")
27
+ # Truncate toward zero for C-like competitive-programming semantics.
28
+ return int(a / b)
29
+
30
+
31
+ def make_builtins(vm):
32
+ if not hasattr(vm, "_io_state"):
33
+ vm._io_state = IOState()
34
+
35
+ return {
36
+ "print": NativeFn("print", _native_print),
37
+ "len": NativeFn("len", _native_len),
38
+ "div": NativeFn("div", _native_div),
39
+ "http": {
40
+ "serve": NativeFn("http.serve", http.serve),
41
+ },
42
+ "fs": {
43
+ "read_text": NativeFn("fs.read_text", fs.read_text),
44
+ "write_text": NativeFn("fs.write_text", fs.write_text),
45
+ },
46
+ "json": {
47
+ "parse": NativeFn("json.parse", jsonlib.parse),
48
+ "stringify": NativeFn("json.stringify", jsonlib.stringify),
49
+ },
50
+ "io": {
51
+ "read_all": NativeFn("io.read_all", io.read_all),
52
+ "read_line": NativeFn("io.read_line", io.read_line),
53
+ "read_int": NativeFn("io.read_int", io.read_int),
54
+ "read_str": NativeFn("io.read_str", io.read_str),
55
+ "write": NativeFn("io.write", io.write),
56
+ "writeln": NativeFn("io.writeln", io.writeln),
57
+ "flush": NativeFn("io.flush", io.flush),
58
+ },
59
+ }
@@ -0,0 +1,55 @@
1
+ """Bytecode container and disassembler for J# VM."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+
8
+
9
+ @dataclass
10
+ class Instruction:
11
+ op: str
12
+ arg: Any = None
13
+ line: int = 0
14
+
15
+
16
+ class Chunk:
17
+ def __init__(self) -> None:
18
+ self.code: list[Instruction] = []
19
+ self.consts: list[Any] = []
20
+
21
+ def add_const(self, value: Any) -> int:
22
+ self.consts.append(value)
23
+ return len(self.consts) - 1
24
+
25
+ def emit(self, op: str, arg: Any = None, line: int = 0) -> int:
26
+ self.code.append(Instruction(op=op, arg=arg, line=line))
27
+ return len(self.code) - 1
28
+
29
+ def patch(self, index: int, arg: Any) -> None:
30
+ self.code[index].arg = arg
31
+
32
+ def disassemble(self, fn_name: str = "<fn>") -> str:
33
+ def fmt_const(value: Any) -> str:
34
+ # Keep disassembly stable even for function object constants.
35
+ if hasattr(value, "name") and hasattr(value, "chunk"):
36
+ return f"<fn {getattr(value, 'name', '?')}>"
37
+ return repr(value)
38
+
39
+ lines = [f"== Function {fn_name} ==", "Constants:"]
40
+ if not self.consts:
41
+ lines.append(" <none>")
42
+ else:
43
+ for i, c in enumerate(self.consts):
44
+ lines.append(f" [{i}] {fmt_const(c)}")
45
+
46
+ lines.append("Code:")
47
+ for i, ins in enumerate(self.code):
48
+ if ins.arg is None:
49
+ lines.append(f" {i:04d} {ins.op}")
50
+ elif ins.op == "CONST" and isinstance(ins.arg, int) and 0 <= ins.arg < len(self.consts):
51
+ lines.append(f" {i:04d} {ins.op} {ins.arg} ; {fmt_const(self.consts[ins.arg])}")
52
+ else:
53
+ lines.append(f" {i:04d} {ins.op} {ins.arg}")
54
+
55
+ return "\n".join(lines)