myna-lang 0.4.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.
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0 (2026-10-24)
4
+
5
+ - `myna run` now resolves relative imports (`<.util:{f}`, `<.pkg.mod:{f}`) to sibling
6
+ `.myna` modules and package directories, with lazy compilation and normal
7
+ `sys.modules` caching. `myna compile` is still per-file, and `-t js` is single-file.
8
+ - Add `myna bundle input.myna -o app.py`, which embeds the relative-import graph in a
9
+ single standalone Python file that needs only the standard library at runtime. With
10
+ `--zipapp` it writes a runnable, reproducible `.pyz` archive with real module files.
11
+ - Lex/parse errors raised while running or importing a module now include the source
12
+ file path.
13
+ - Fix `:?` runtime checks with compound types (`[T]`, `{K:V}`, `{T}`, `Name[T]`): they
14
+ emitted invalid Python (`isinstance(x, [s])`) and JS (`x instanceof [s]`). They now
15
+ check the runtime origin type (`list`, `dict`, `set`, `Name`); `(A, B)` remains a union.
16
+ - Fix `pip install -e .` failing because setuptools flat-layout discovery treated
17
+ `skills/` as a package; the distributed packages are now declared explicitly.
18
+
19
+ ## 0.3.0
20
+
21
+ - Add module-level `@target(...)` declarations and compile-time `@target(...) { ... }` blocks.
22
+ - Add `myna targets` to report declared target support and likely JavaScript import incompatibilities.
23
+ - Harden Python-to-Myna round-trips: corpus tests, lossless byte literals, f-string conversions, clearer `DecompileError` failures.
24
+ - Improve parser handling of tuple conditions, brace-adjacent definition sigils, and f-string error locations.
25
+ - Print concise language errors from the CLI instead of tracebacks.
26
+
27
+ ## 0.2.0
28
+
29
+ - Initial public release of Myna with Python and JavaScript backends, Python decompilation, and token-efficiency stats.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joseph Hicks
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.
@@ -0,0 +1,7 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include SPEC.md
5
+ recursive-include examples *.myna
6
+ recursive-include skills *.md
7
+ recursive-include tests *.py
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: myna-lang
3
+ Version: 0.4.0
4
+ Summary: Myna: An AI-friendly, token-efficient symbolic language that transpiles to/from Python and JavaScript
5
+ Author: Joseph Hicks
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jhicksdev/myna
8
+ Project-URL: Repository, https://github.com/jhicksdev/myna
9
+ Project-URL: Issues, https://github.com/jhicksdev/myna/issues
10
+ Project-URL: Changelog, https://github.com/jhicksdev/myna/blob/main/CHANGELOG.md
11
+ Keywords: language,transpiler,compiler,python,javascript,llm,code-generation
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Code Generators
20
+ Classifier: Topic :: Software Development :: Compilers
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Dynamic: license-file
25
+
26
+ # Myna (`myna-lang`)
27
+
28
+ **Myna** is an ultra-dense, symbol-based, AI-native programming language designed to cut LLM token and character usage by **~50%** while transpiling 1:1 to **Python 3.12+** and **JavaScript (ES2024+)**—and decompiling existing Python code back into Myna.
29
+
30
+ ---
31
+
32
+ ## Why Myna?
33
+
34
+ Coding agents spend thousands of context and output tokens on repetitive syntactic boilerplate (`def __init__(self, ...):`, `self.`, `Optional[...]`, `try ... except Exception as e:`, quoted JSON keys, and 4-space indentation blocks).
35
+
36
+ Myna replaces verbose multi-token boilerplate with **tokenizer-friendly ASCII sigils and digraphs** (`$$`, `@`, `~@`, `=>`, `??`, `!?`, `!&`, `$`, `$?`) and brace-delimited blocks (`{}`):
37
+ - **~46%–52% fewer LLM tokens** and **~48%–58% fewer characters** than equivalent Python (compact and ultra-compact modes).
38
+ - **Zero indentation fragility:** Blocks use `{ ... }` or `=>`, making partial diffs and single-line generation rock-solid for AI agents.
39
+ - **Bi-directional (`Python <-> Myna`) & Multi-Target (`Myna -> Python / JS`):** Compress existing Python codebases into `.myna` to fit twice as much code into an agent's context window, or let agents write `.myna` and transpile to clean Python or JavaScript.
40
+ - **Agent-Ready:** Ships with a compact Rosetta Stone skill (`skills/myna/SKILL.md`) that teaches any coding agent to read and write idiomatic Myna in one shot.
41
+
42
+ ---
43
+
44
+ ## Side-by-Side Comparison
45
+
46
+ ### Python (21 lines, 611 chars)
47
+ ```python
48
+ from dataclasses import dataclass
49
+ import asyncio
50
+
51
+ @dataclass
52
+ class Task:
53
+ id: int
54
+ title: str
55
+ priority: int = 1
56
+ done: bool = False
57
+
58
+ def to_dict(self) -> dict[str, object]:
59
+ return {"id": self.id, "title": self.title, "done": self.done}
60
+
61
+ async def pending(tasks: list[Task], min_p: int = 1) -> list[dict[str, object]]:
62
+ try:
63
+ await asyncio.sleep(0.01)
64
+ items = [t for t in tasks if not t.done and t.priority >= min_p]
65
+ return [t.to_dict() for t in sorted(items, key=lambda t: -t.priority)]
66
+ except Exception as e:
67
+ print(f"Error: {e}")
68
+ return []
69
+ ```
70
+
71
+ ### Myna (11 lines, 299 chars — 51% smaller)
72
+ ```myna
73
+ <asyncio
74
+ $$Task(id:i,title:s,priority:i=1,done:b=F){
75
+ @to_dict->{s:A}=>{.id,.title,.done}
76
+ }
77
+ ~@pending(tasks:[Task],min_p:i=1)->[{s:A}]{
78
+ !{
79
+ ~asyncio.sleep(0.01)
80
+ items=[t|t<-tasks?!t.done&&t.priority>=min_p]
81
+ ^[t.to_dict()|t<-@srt(items,key=t=>-t.priority)]
82
+ }!!e{p(`Error: {e}`);^[]}
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Quickstart
89
+
90
+ Myna requires **Python 3.11+** and has **zero external dependencies**.
91
+
92
+ ```bash
93
+ # Install from PyPI
94
+ pip install myna-lang # or: uv tool install myna-lang / pipx install myna-lang
95
+
96
+ # Install for local development (from a checkout)
97
+ pip install -e .
98
+
99
+ # Create and run a script
100
+ printf 'p(`hello from {1+1}`)\n' > hello.myna
101
+ myna run hello.myna
102
+
103
+ # The remaining examples are in a checkout of the repository.
104
+ # Run a Myna script directly (via Python)
105
+ python3 -m myna run examples/demo.myna
106
+
107
+ # Run a portable Myna script via Node.js (JavaScript target)
108
+ python3 -m myna run -t js examples/cross_target.myna
109
+
110
+ # Compile Myna -> Python (.py)
111
+ python3 -m myna compile examples/rest_api.myna -o rest_api.py
112
+
113
+ # Compile Myna -> JavaScript (.js)
114
+ python3 -m myna compile -t js examples/cross_target.myna -o cross_target.js
115
+
116
+ # Bundle a multi-file program into one standalone Python file
117
+ python3 -m myna bundle src/main.myna -o app.py
118
+
119
+ # ...or into a runnable zipapp (stdlib-only, executable)
120
+ python3 -m myna bundle src/main.myna --zipapp -o app.pyz
121
+
122
+ # Compress existing Python -> Myna (.myna)
123
+ python3 -m myna decompile script.py -o script.myna
124
+
125
+ # Ultra-compact decompilation (with local variable minification)
126
+ python3 -m myna decompile -m script.py -o script.min.myna
127
+
128
+ # Compare token & character efficiency
129
+ python3 -m myna stats examples/books_api.myna
130
+
131
+ # Report declared/inferred Python & JavaScript support
132
+ python3 -m myna targets examples/demo.myna
133
+ ```
134
+
135
+ ### Multi-file programs
136
+
137
+ `myna run` gives relative imports a package context, so a program can be split into
138
+ sibling `.myna` files:
139
+
140
+ ```myna
141
+ # main.myna
142
+ <.util:{slug}
143
+ p(slug("Hello World"))
144
+ ```
145
+
146
+ ```myna
147
+ # util.myna
148
+ @slug(text:s)->s { ^ text.lower().replace(" ", "-") }
149
+ ```
150
+
151
+ - `<.util:{slug}` → `util.myna` beside the entry file.
152
+ - `<.pkg.helper:{parse}` → `pkg/helper.myna`; `pkg` may have an `__init__.myna` or be a
153
+ plain directory (namespace package).
154
+ - Absolute imports (`<json`, `<mypkg>alias`) keep their normal Python meaning.
155
+ - Imported files are compiled on first import and cached by Python's import system.
156
+ - `myna bundle src/main.myna -o app.py` embeds the whole relative-import graph in one
157
+ standalone Python file. It runs with a plain `python3` and does not need `myna`
158
+ installed; absolute imports still come from the environment.
159
+ - `myna bundle src/main.myna --zipapp -o app.pyz` writes a runnable, executable zipapp
160
+ containing real module files (`python3 app.pyz`). It is reproducible: rebuilding the
161
+ same sources produces identical bytes. Without `-o`, the archive lands next to the
162
+ entry file as `<name>.pyz`.
163
+ - `myna compile` still compiles one file at a time. If you use relative imports, the
164
+ emitted `.py` files must be placed in a matching Python package.
165
+ - `myna run -t js` is single-file for now; multi-file resolution and bundling are
166
+ Python-target only.
167
+
168
+ ---
169
+
170
+ ## Token & Character Efficiency Benchmarks
171
+
172
+ Measured by compiling each example to Python and running `python3 -m myna stats` on the generated file (so the Myna columns reflect the decompiler's `compact` and `-m` modes). Counts use the built-in `bpe-approx` estimator unless `tiktoken` is installed:
173
+
174
+ ```bash
175
+ python3 -m myna compile examples/demo.myna -o /tmp/demo.py
176
+ python3 -m myna stats /tmp/demo.py
177
+ ```
178
+
179
+ Running `stats` directly on a `.myna` file instead compares the generated Python against that file as written, so its Myna counts will differ from the table.
180
+
181
+ | Example Program | Python Tokens / Chars | Myna (Compact) | Myna (Ultra-Compact `-m`) |
182
+ | :--- | :--- | :--- | :--- |
183
+ | **`examples/demo.myna`** (Async Task Pipeline) | `517` toks / `953` chars | `271` toks (**-47.6%**) / `463` chars (**-51.4%**) | **`247` toks (-52.2%)** / **`397` chars (-58.3%)** |
184
+ | **`examples/rest_api.myna`** (Todo HTTP REST API) | `4,105` toks / `8,011` chars | `2,183` toks (**-46.8%**) / `3,932` chars (**-50.9%**) | **`2,045` toks (-50.2%)** / **`3,573` chars (-55.4%)** |
185
+ | **`examples/books_api.myna`** (Library Catalog API) | `4,402` toks / `8,515` chars | `2,371` toks (**-46.1%**) / `4,381` chars (**-48.5%**) | **`2,289` toks (-48.0%)** / **`4,104` chars (-51.8%)** |
186
+
187
+ ---
188
+
189
+ ## Language Cheat Sheet
190
+
191
+ | Feature | Myna Syntax | Python Equivalent | JavaScript Equivalent |
192
+ | :--- | :--- | :--- | :--- |
193
+ | **Literals** | `T`, `F`, `N`, `U`, `_` | `True`, `False`, `None`, `None`, `pass` | `true`, `false`, `null`, `undefined`, `/*noop*/` |
194
+ | **Types** | `i`, `f`, `s`, `b`, `B`, `A`, `T?`, `[T]`, `{K:V}` | `int`, `float`, `str`, `bool`, `bytes`, `Any`, `T \| None`, `list[T]`, `dict[K, V]` | *(Type annotations stripped in JS)* |
195
+ | **Imports** | `<os, numpy>np` / `<mod:{a, b>c}` | `import os, numpy as np` / `from mod import a, b as c` | `import * as ...` / `import { a, b as c } from ...` |
196
+ | **Targets** | `@target(py)` / `@target(py) { ... }` | Python-only module / Python-only block | JS-only module / JS-only block |
197
+ | **Functions** | `@f(a:i, b=1)->i { ^a+b }` or `@f(a)=>a+1` | `def f(a: int, b=1) -> int: return a + b` | `function f(a, b = 1) { return a + b; }` |
198
+ | **Async / Gen** | `~@f` / `~expr` / `*@gen` / `^*val` | `async def` / `await` / generator / `yield` | `async function` / `await` / `function*` / `yield` |
199
+ | **Classes** | `$C < Base { @init(x){ .x=x } }` | `class C(Base): def __init__(self, x): self.x = x` | `class C extends Base { constructor(x) { this.x = x; } }` |
200
+ | **Dataclasses** | `$$User(id:i, name:s="anon")` | `@dataclass class User: ...` | `class User { constructor(id, name = "anon") ... }` |
201
+ | **Dict Shorthands** | `{.id, .title, =name, ok: T}` | `{"id": self.id, "title": self.title, "name": name, "ok": True}` | `({id: this.id, title: this.title, name, ok: true})` |
202
+ | **Key Lookup** | `d$key` / `d$?key ?? "def"` | `d["key"]` / `d.get("key") or "def"` | `d["key"]` / `d.get("key") ?? "def"` |
203
+ | **Branching** | `? c1 {...} :? c2 {...} : {...}` | `if c1: ... elif c2: ... else: ...` | `if (c1) {...} else if (c2) {...} else {...}` |
204
+ | **Pattern Match** | `?? v { 0 => {...}; x ? x>0 => {...}; _ => {...} }` | `match v: case 0: ... case x if x > 0: ... case _: ...` | Block-scoped pattern & guard dispatch |
205
+ | **Loops** | `% x <- 0..10 { ... }` / `%? cond { ... }` | `for x in range(10): ...` / `while cond: ...` | `for (let x = 0; x < 10; x += 1)` / `while (cond)` |
206
+ | **Comprehensions** | `[x*2 \| x <- items ? x > 0]` | `[x * 2 for x in items if x > 0]` | `items.filter(x => x > 0).map(x => x * 2)` |
207
+ | **Exceptions** | `!{ ... } !!e:ValueError { ... } !: { ... }` | `try: ... except ValueError as e: ... finally: ...` | `try { ... } catch (e) { ... } finally { ... }` |
208
+ | **With / Assert** | `!& f=open(p) { ... }` / `!? cond, "msg"` | `with open(p) as f:` / `assert cond, "msg"` | Scoped try/finally `.close()` / `if (!cond) throw ...` |
209
+ | **Built-in Aliases** | `p`, `#x`, `@j`, `@J`, `@u8`, `@u8d`, `@srt`, `@sum` | `print`, `len(x)`, `json.loads`, `json.dumps`, `.encode`, `.decode`, `sorted`, `sum` | `console.log`, `len`, `JSON.parse`, `JSON.stringify`, `TextEncoder`, `TextDecoder`, `.sort`, `.reduce` |
210
+
211
+ See [`SPEC.md`](https://github.com/jhicksdev/myna/blob/main/SPEC.md) for the complete language specification and [`skills/myna/SKILL.md`](https://github.com/jhicksdev/myna/blob/main/skills/myna/SKILL.md) for the AI agent skill file.
212
+
213
+ ---
214
+
215
+ ## Running Tests
216
+
217
+ ```bash
218
+ python3 -m unittest discover -s tests -v
219
+ ```
220
+
221
+ ---
222
+
223
+ ## License
224
+
225
+ [MIT](https://github.com/jhicksdev/myna/blob/main/LICENSE)
@@ -0,0 +1,200 @@
1
+ # Myna (`myna-lang`)
2
+
3
+ **Myna** is an ultra-dense, symbol-based, AI-native programming language designed to cut LLM token and character usage by **~50%** while transpiling 1:1 to **Python 3.12+** and **JavaScript (ES2024+)**—and decompiling existing Python code back into Myna.
4
+
5
+ ---
6
+
7
+ ## Why Myna?
8
+
9
+ Coding agents spend thousands of context and output tokens on repetitive syntactic boilerplate (`def __init__(self, ...):`, `self.`, `Optional[...]`, `try ... except Exception as e:`, quoted JSON keys, and 4-space indentation blocks).
10
+
11
+ Myna replaces verbose multi-token boilerplate with **tokenizer-friendly ASCII sigils and digraphs** (`$$`, `@`, `~@`, `=>`, `??`, `!?`, `!&`, `$`, `$?`) and brace-delimited blocks (`{}`):
12
+ - **~46%–52% fewer LLM tokens** and **~48%–58% fewer characters** than equivalent Python (compact and ultra-compact modes).
13
+ - **Zero indentation fragility:** Blocks use `{ ... }` or `=>`, making partial diffs and single-line generation rock-solid for AI agents.
14
+ - **Bi-directional (`Python <-> Myna`) & Multi-Target (`Myna -> Python / JS`):** Compress existing Python codebases into `.myna` to fit twice as much code into an agent's context window, or let agents write `.myna` and transpile to clean Python or JavaScript.
15
+ - **Agent-Ready:** Ships with a compact Rosetta Stone skill (`skills/myna/SKILL.md`) that teaches any coding agent to read and write idiomatic Myna in one shot.
16
+
17
+ ---
18
+
19
+ ## Side-by-Side Comparison
20
+
21
+ ### Python (21 lines, 611 chars)
22
+ ```python
23
+ from dataclasses import dataclass
24
+ import asyncio
25
+
26
+ @dataclass
27
+ class Task:
28
+ id: int
29
+ title: str
30
+ priority: int = 1
31
+ done: bool = False
32
+
33
+ def to_dict(self) -> dict[str, object]:
34
+ return {"id": self.id, "title": self.title, "done": self.done}
35
+
36
+ async def pending(tasks: list[Task], min_p: int = 1) -> list[dict[str, object]]:
37
+ try:
38
+ await asyncio.sleep(0.01)
39
+ items = [t for t in tasks if not t.done and t.priority >= min_p]
40
+ return [t.to_dict() for t in sorted(items, key=lambda t: -t.priority)]
41
+ except Exception as e:
42
+ print(f"Error: {e}")
43
+ return []
44
+ ```
45
+
46
+ ### Myna (11 lines, 299 chars — 51% smaller)
47
+ ```myna
48
+ <asyncio
49
+ $$Task(id:i,title:s,priority:i=1,done:b=F){
50
+ @to_dict->{s:A}=>{.id,.title,.done}
51
+ }
52
+ ~@pending(tasks:[Task],min_p:i=1)->[{s:A}]{
53
+ !{
54
+ ~asyncio.sleep(0.01)
55
+ items=[t|t<-tasks?!t.done&&t.priority>=min_p]
56
+ ^[t.to_dict()|t<-@srt(items,key=t=>-t.priority)]
57
+ }!!e{p(`Error: {e}`);^[]}
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Quickstart
64
+
65
+ Myna requires **Python 3.11+** and has **zero external dependencies**.
66
+
67
+ ```bash
68
+ # Install from PyPI
69
+ pip install myna-lang # or: uv tool install myna-lang / pipx install myna-lang
70
+
71
+ # Install for local development (from a checkout)
72
+ pip install -e .
73
+
74
+ # Create and run a script
75
+ printf 'p(`hello from {1+1}`)\n' > hello.myna
76
+ myna run hello.myna
77
+
78
+ # The remaining examples are in a checkout of the repository.
79
+ # Run a Myna script directly (via Python)
80
+ python3 -m myna run examples/demo.myna
81
+
82
+ # Run a portable Myna script via Node.js (JavaScript target)
83
+ python3 -m myna run -t js examples/cross_target.myna
84
+
85
+ # Compile Myna -> Python (.py)
86
+ python3 -m myna compile examples/rest_api.myna -o rest_api.py
87
+
88
+ # Compile Myna -> JavaScript (.js)
89
+ python3 -m myna compile -t js examples/cross_target.myna -o cross_target.js
90
+
91
+ # Bundle a multi-file program into one standalone Python file
92
+ python3 -m myna bundle src/main.myna -o app.py
93
+
94
+ # ...or into a runnable zipapp (stdlib-only, executable)
95
+ python3 -m myna bundle src/main.myna --zipapp -o app.pyz
96
+
97
+ # Compress existing Python -> Myna (.myna)
98
+ python3 -m myna decompile script.py -o script.myna
99
+
100
+ # Ultra-compact decompilation (with local variable minification)
101
+ python3 -m myna decompile -m script.py -o script.min.myna
102
+
103
+ # Compare token & character efficiency
104
+ python3 -m myna stats examples/books_api.myna
105
+
106
+ # Report declared/inferred Python & JavaScript support
107
+ python3 -m myna targets examples/demo.myna
108
+ ```
109
+
110
+ ### Multi-file programs
111
+
112
+ `myna run` gives relative imports a package context, so a program can be split into
113
+ sibling `.myna` files:
114
+
115
+ ```myna
116
+ # main.myna
117
+ <.util:{slug}
118
+ p(slug("Hello World"))
119
+ ```
120
+
121
+ ```myna
122
+ # util.myna
123
+ @slug(text:s)->s { ^ text.lower().replace(" ", "-") }
124
+ ```
125
+
126
+ - `<.util:{slug}` → `util.myna` beside the entry file.
127
+ - `<.pkg.helper:{parse}` → `pkg/helper.myna`; `pkg` may have an `__init__.myna` or be a
128
+ plain directory (namespace package).
129
+ - Absolute imports (`<json`, `<mypkg>alias`) keep their normal Python meaning.
130
+ - Imported files are compiled on first import and cached by Python's import system.
131
+ - `myna bundle src/main.myna -o app.py` embeds the whole relative-import graph in one
132
+ standalone Python file. It runs with a plain `python3` and does not need `myna`
133
+ installed; absolute imports still come from the environment.
134
+ - `myna bundle src/main.myna --zipapp -o app.pyz` writes a runnable, executable zipapp
135
+ containing real module files (`python3 app.pyz`). It is reproducible: rebuilding the
136
+ same sources produces identical bytes. Without `-o`, the archive lands next to the
137
+ entry file as `<name>.pyz`.
138
+ - `myna compile` still compiles one file at a time. If you use relative imports, the
139
+ emitted `.py` files must be placed in a matching Python package.
140
+ - `myna run -t js` is single-file for now; multi-file resolution and bundling are
141
+ Python-target only.
142
+
143
+ ---
144
+
145
+ ## Token & Character Efficiency Benchmarks
146
+
147
+ Measured by compiling each example to Python and running `python3 -m myna stats` on the generated file (so the Myna columns reflect the decompiler's `compact` and `-m` modes). Counts use the built-in `bpe-approx` estimator unless `tiktoken` is installed:
148
+
149
+ ```bash
150
+ python3 -m myna compile examples/demo.myna -o /tmp/demo.py
151
+ python3 -m myna stats /tmp/demo.py
152
+ ```
153
+
154
+ Running `stats` directly on a `.myna` file instead compares the generated Python against that file as written, so its Myna counts will differ from the table.
155
+
156
+ | Example Program | Python Tokens / Chars | Myna (Compact) | Myna (Ultra-Compact `-m`) |
157
+ | :--- | :--- | :--- | :--- |
158
+ | **`examples/demo.myna`** (Async Task Pipeline) | `517` toks / `953` chars | `271` toks (**-47.6%**) / `463` chars (**-51.4%**) | **`247` toks (-52.2%)** / **`397` chars (-58.3%)** |
159
+ | **`examples/rest_api.myna`** (Todo HTTP REST API) | `4,105` toks / `8,011` chars | `2,183` toks (**-46.8%**) / `3,932` chars (**-50.9%**) | **`2,045` toks (-50.2%)** / **`3,573` chars (-55.4%)** |
160
+ | **`examples/books_api.myna`** (Library Catalog API) | `4,402` toks / `8,515` chars | `2,371` toks (**-46.1%**) / `4,381` chars (**-48.5%**) | **`2,289` toks (-48.0%)** / **`4,104` chars (-51.8%)** |
161
+
162
+ ---
163
+
164
+ ## Language Cheat Sheet
165
+
166
+ | Feature | Myna Syntax | Python Equivalent | JavaScript Equivalent |
167
+ | :--- | :--- | :--- | :--- |
168
+ | **Literals** | `T`, `F`, `N`, `U`, `_` | `True`, `False`, `None`, `None`, `pass` | `true`, `false`, `null`, `undefined`, `/*noop*/` |
169
+ | **Types** | `i`, `f`, `s`, `b`, `B`, `A`, `T?`, `[T]`, `{K:V}` | `int`, `float`, `str`, `bool`, `bytes`, `Any`, `T \| None`, `list[T]`, `dict[K, V]` | *(Type annotations stripped in JS)* |
170
+ | **Imports** | `<os, numpy>np` / `<mod:{a, b>c}` | `import os, numpy as np` / `from mod import a, b as c` | `import * as ...` / `import { a, b as c } from ...` |
171
+ | **Targets** | `@target(py)` / `@target(py) { ... }` | Python-only module / Python-only block | JS-only module / JS-only block |
172
+ | **Functions** | `@f(a:i, b=1)->i { ^a+b }` or `@f(a)=>a+1` | `def f(a: int, b=1) -> int: return a + b` | `function f(a, b = 1) { return a + b; }` |
173
+ | **Async / Gen** | `~@f` / `~expr` / `*@gen` / `^*val` | `async def` / `await` / generator / `yield` | `async function` / `await` / `function*` / `yield` |
174
+ | **Classes** | `$C < Base { @init(x){ .x=x } }` | `class C(Base): def __init__(self, x): self.x = x` | `class C extends Base { constructor(x) { this.x = x; } }` |
175
+ | **Dataclasses** | `$$User(id:i, name:s="anon")` | `@dataclass class User: ...` | `class User { constructor(id, name = "anon") ... }` |
176
+ | **Dict Shorthands** | `{.id, .title, =name, ok: T}` | `{"id": self.id, "title": self.title, "name": name, "ok": True}` | `({id: this.id, title: this.title, name, ok: true})` |
177
+ | **Key Lookup** | `d$key` / `d$?key ?? "def"` | `d["key"]` / `d.get("key") or "def"` | `d["key"]` / `d.get("key") ?? "def"` |
178
+ | **Branching** | `? c1 {...} :? c2 {...} : {...}` | `if c1: ... elif c2: ... else: ...` | `if (c1) {...} else if (c2) {...} else {...}` |
179
+ | **Pattern Match** | `?? v { 0 => {...}; x ? x>0 => {...}; _ => {...} }` | `match v: case 0: ... case x if x > 0: ... case _: ...` | Block-scoped pattern & guard dispatch |
180
+ | **Loops** | `% x <- 0..10 { ... }` / `%? cond { ... }` | `for x in range(10): ...` / `while cond: ...` | `for (let x = 0; x < 10; x += 1)` / `while (cond)` |
181
+ | **Comprehensions** | `[x*2 \| x <- items ? x > 0]` | `[x * 2 for x in items if x > 0]` | `items.filter(x => x > 0).map(x => x * 2)` |
182
+ | **Exceptions** | `!{ ... } !!e:ValueError { ... } !: { ... }` | `try: ... except ValueError as e: ... finally: ...` | `try { ... } catch (e) { ... } finally { ... }` |
183
+ | **With / Assert** | `!& f=open(p) { ... }` / `!? cond, "msg"` | `with open(p) as f:` / `assert cond, "msg"` | Scoped try/finally `.close()` / `if (!cond) throw ...` |
184
+ | **Built-in Aliases** | `p`, `#x`, `@j`, `@J`, `@u8`, `@u8d`, `@srt`, `@sum` | `print`, `len(x)`, `json.loads`, `json.dumps`, `.encode`, `.decode`, `sorted`, `sum` | `console.log`, `len`, `JSON.parse`, `JSON.stringify`, `TextEncoder`, `TextDecoder`, `.sort`, `.reduce` |
185
+
186
+ See [`SPEC.md`](https://github.com/jhicksdev/myna/blob/main/SPEC.md) for the complete language specification and [`skills/myna/SKILL.md`](https://github.com/jhicksdev/myna/blob/main/skills/myna/SKILL.md) for the AI agent skill file.
187
+
188
+ ---
189
+
190
+ ## Running Tests
191
+
192
+ ```bash
193
+ python3 -m unittest discover -s tests -v
194
+ ```
195
+
196
+ ---
197
+
198
+ ## License
199
+
200
+ [MIT](https://github.com/jhicksdev/myna/blob/main/LICENSE)