Skip to content

Commit 023f8fa

Browse files
Correct errors
1 parent 0b4ae44 commit 023f8fa

3 files changed

Lines changed: 54 additions & 156 deletions

File tree

docs/demos.md

Lines changed: 25 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,60 @@
11
# Demos
22

3-
Multilingual 1.0 showcases a new kind of AI-native, reactive, multilingual
4-
programming platform.
3+
A short tour of Multilingual in the browser and in the repository.
54

6-
## Core 1.0 flagship demos
5+
## Featured demos
76

8-
### Multilingual AI agent (3 languages)
7+
### Multilingual AI agent
98

10-
The most compelling demo: the same agent logic written in English, French, and
11-
Japanese, running identically. Proves that Multilingual is the only AI
12-
programming platform where agent code is idiomatic in any human language.
9+
The same agent logic written in three human languages with shared behavior.
1310

14-
- `examples/agent_en.multi` — English
15-
- `examples/agent_fr.multi` — French
16-
- `examples/agent_ja.multi` — Japanese
11+
- `examples/agent_en.multi`
12+
- `examples/agent_fr.multi`
13+
- `examples/agent_ja.multi`
1714

18-
### Memory Card Game (Reactive UI showcase)
15+
### Memory Game
1916

20-
Interactive game demonstrating `observe var`, `async/await`, and event binding within a reactive UI.
21-
Written in both English and French to prove polyglot semantics.
17+
Reactive UI, async handlers, and browser interaction in Multilingual.
2218

23-
**[Play the Memory Game](memory-game/)** (Compiled to WASM)
19+
**[Play the Memory Game](memory-game-demo.html)**
2420

25-
- `examples/memory_game_en.multi` — English version
26-
- `examples/memory_game_fr.multi` — French version (identical logic, different syntax)
21+
- `examples/memory_game_en.multi`
22+
- `examples/memory_game_fr.multi`
2723

2824
### Reactive counter
2925

30-
`observe var` + `on .change` + `canvas` — the simplest reactive web app.
26+
A compact reactive web app using state changes and canvas updates.
3127

3228
- `examples/reactive_counter.multi`
3329

34-
### Streaming chat (French)
30+
### Streaming chat
3531

36-
A streaming AI response bound to a reactive view, written in French.
32+
French-language example of streaming output bound to a reactive view.
3733

3834
- `examples/streaming_chat_fr.multi`
3935

40-
### Semantic search (Japanese)
36+
### Semantic search
4137

42-
`embed` + `nearest` + `~=` semantic match across Japanese user input.
38+
Japanese example using semantic matching concepts.
4339

4440
- `examples/semantic_search_ja.multi`
4541

46-
### Multilingual AI dashboard
42+
### Multilingual dashboard
4743

48-
`@agent`, reactive state, streaming output, and canvas composition.
44+
Combines agent-style behavior, reactive state, and UI composition.
4945

5046
- `examples/multilingual_dashboard.multi`
5147

52-
## CLI tools for Core 1.0
48+
## Browser tools
5349

54-
### Inspect the semantic IR
50+
- **[Open the Playground](playground.html)** for live editing and experimentation.
51+
- **[Open the WASM Demo Hub](browser/index.html)** for precompiled browser demos.
5552

56-
```
57-
multilingual ir my_program.multi
58-
multilingual ir my_program.multi --format json
59-
```
60-
61-
### Explain a program's structure
53+
## Useful CLI commands
6254

63-
```
55+
```bash
56+
multilingual ir my_program.multi
6457
multilingual explain my_program.multi
65-
```
66-
67-
Output: a plain-English summary of all declared functions, agents, tools,
68-
reactive bindings, effects, and type declarations.
69-
70-
### Preview reactive UI output
71-
72-
```
73-
multilingual ui-preview my_program.ml
7458
multilingual ui-preview my_program.ml --html
75-
multilingual ui-preview my_program.ml --js
76-
```
77-
78-
### Validate with Core IR before running
79-
80-
```
8159
multilingual run my_program.ml --mode core
8260
```
83-
84-
Validates the semantic IR (checks capabilities, binding names, match
85-
statement completeness) before executing.
86-
87-
## Browser deployment models
88-
89-
### 1. Pyodide playground
90-
91-
Use for live editing, full interpreter behavior, IR inspection, and teaching.
92-
93-
**[Open the Pyodide Playground](playground.html)**
94-
95-
### 2. Precompiled Multilingual to WASM
96-
97-
Use for ahead-of-time compilation to `module.wasm` and minimal JavaScript host.
98-
99-
**[Open the Browser WASM Demo Hub](browser/index.html)**
100-
101-
## What each demo proves
102-
103-
| Demo | Shows |
104-
|------|-------|
105-
| Multilingual agent (3 languages) | Agent logic is idiomatic in any human language |
106-
| Memory Card Game | `observe var`, `async/await`, event binding in reactive UI; polyglot semantics (English + French) |
107-
| Reactive counter | `observe var` + `on .change` + `canvas` reactive model |
108-
| Streaming chat (French) | AI stream bound to reactive view in French |
109-
| Semantic search (Japanese) | `~=` and `embed` across multilingual input |
110-
| Pyodide playground | Live browser compilation and IR inspection |
111-
| Browser WASM demo | Production-ready prebuilt artifact deployment |
112-

multilingualprogramming/core/semantic_lowering.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,13 @@ def _fix_misplaced_ui_elements(self, children: list) -> list:
12901290

12911291
while len(loop_body) > 1:
12921292
last = loop_body[-1]
1293-
if isinstance(last, IRUIElement) or (hasattr(last, '__class__') and 'Expr' in last.__class__.__name__):
1293+
if (
1294+
isinstance(last, IRUIElement)
1295+
or (
1296+
hasattr(last, "__class__")
1297+
and "Expr" in last.__class__.__name__
1298+
)
1299+
):
12941300
extracted.insert(0, last)
12951301
loop_body.pop()
12961302
else:

tests/core1/test_ui_output_validation.py

Lines changed: 22 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,21 @@
77
from multilingualprogramming.codegen.ui_lowering import lower_to_ui
88

99

10-
def test_memory_game_html_has_required_structure():
11-
"""Generated HTML has all required structural elements."""
10+
def _load_memory_game_ui():
11+
"""Compile the memory game example and return the UI lowering result."""
1212
game_file = Path("examples/memory_game_en.multi")
13-
source = game_file.read_text()
13+
source = game_file.read_text(encoding="utf-8")
1414
lexer = Lexer(source, lang="en")
1515
tokens = lexer.tokenize()
1616
parser = Parser(tokens, lang="en")
1717
program = parser.parse()
1818
ir_program = lower_to_semantic_ir(program, lang="en")
19-
ui_result = lower_to_ui(ir_program)
19+
return lower_to_ui(ir_program)
20+
21+
22+
def test_memory_game_html_has_required_structure():
23+
"""Generated HTML has all required structural elements."""
24+
ui_result = _load_memory_game_ui()
2025
html = ui_result.emit_html()
2126

2227
# Check doctype
@@ -38,14 +43,7 @@ def test_memory_game_html_has_required_structure():
3843

3944
def test_memory_game_html_has_css_styling():
4045
"""Generated HTML includes CSS for game styling."""
41-
game_file = Path("examples/memory_game_en.multi")
42-
source = game_file.read_text()
43-
lexer = Lexer(source, lang="en")
44-
tokens = lexer.tokenize()
45-
parser = Parser(tokens, lang="en")
46-
program = parser.parse()
47-
ir_program = lower_to_semantic_ir(program, lang="en")
48-
ui_result = lower_to_ui(ir_program)
46+
ui_result = _load_memory_game_ui()
4947
html = ui_result.emit_html()
5048

5149
# Check for stylesheet
@@ -66,14 +64,7 @@ def test_memory_game_html_has_css_styling():
6664

6765
def test_memory_game_js_has_required_functions():
6866
"""Generated JS has all required signal and function declarations."""
69-
game_file = Path("examples/memory_game_en.multi")
70-
source = game_file.read_text()
71-
lexer = Lexer(source, lang="en")
72-
tokens = lexer.tokenize()
73-
parser = Parser(tokens, lang="en")
74-
program = parser.parse()
75-
ir_program = lower_to_semantic_ir(program, lang="en")
76-
ui_result = lower_to_ui(ir_program)
67+
ui_result = _load_memory_game_ui()
7768
js = ui_result.emit_js()
7869

7970
# Check for signal declarations
@@ -91,14 +82,7 @@ def test_memory_game_js_has_required_functions():
9182

9283
def test_memory_game_js_no_undefined_calls():
9384
"""Generated JS does not contain calls to undefined functions."""
94-
game_file = Path("examples/memory_game_en.multi")
95-
source = game_file.read_text()
96-
lexer = Lexer(source, lang="en")
97-
tokens = lexer.tokenize()
98-
parser = Parser(tokens, lang="en")
99-
program = parser.parse()
100-
ir_program = lower_to_semantic_ir(program, lang="en")
101-
ui_result = lower_to_ui(ir_program)
85+
ui_result = _load_memory_game_ui()
10286
js = ui_result.emit_js()
10387

10488
# Should not call memory_game() as a function (it's not in JS context)
@@ -110,14 +94,7 @@ def test_memory_game_js_no_undefined_calls():
11094

11195
def test_memory_game_js_has_render_initialization():
11296
"""Generated JS initializes render on page load."""
113-
game_file = Path("examples/memory_game_en.multi")
114-
source = game_file.read_text()
115-
lexer = Lexer(source, lang="en")
116-
tokens = lexer.tokenize()
117-
parser = Parser(tokens, lang="en")
118-
program = parser.parse()
119-
ir_program = lower_to_semantic_ir(program, lang="en")
120-
ui_result = lower_to_ui(ir_program)
97+
ui_result = _load_memory_game_ui()
12198
js = ui_result.emit_js()
12299

123100
# Check for initialization
@@ -126,14 +103,7 @@ def test_memory_game_js_has_render_initialization():
126103

127104
def test_memory_game_js_signal_change_bindings():
128105
"""Generated JS binds signal changes to re-render."""
129-
game_file = Path("examples/memory_game_en.multi")
130-
source = game_file.read_text()
131-
lexer = Lexer(source, lang="en")
132-
tokens = lexer.tokenize()
133-
parser = Parser(tokens, lang="en")
134-
program = parser.parse()
135-
ir_program = lower_to_semantic_ir(program, lang="en")
136-
ui_result = lower_to_ui(ir_program)
106+
ui_result = _load_memory_game_ui()
137107
js = ui_result.emit_js()
138108

139109
# Check that signals are wired to re-render
@@ -143,14 +113,7 @@ def test_memory_game_js_signal_change_bindings():
143113

144114
def test_memory_game_js_has_reactive_runtime():
145115
"""Generated JS includes ReactiveSignal and ReactiveList classes."""
146-
game_file = Path("examples/memory_game_en.multi")
147-
source = game_file.read_text()
148-
lexer = Lexer(source, lang="en")
149-
tokens = lexer.tokenize()
150-
parser = Parser(tokens, lang="en")
151-
program = parser.parse()
152-
ir_program = lower_to_semantic_ir(program, lang="en")
153-
ui_result = lower_to_ui(ir_program)
116+
ui_result = _load_memory_game_ui()
154117
js = ui_result.emit_js()
155118

156119
# Check for reactive runtime
@@ -162,14 +125,7 @@ def test_memory_game_js_has_reactive_runtime():
162125

163126
def test_memory_game_js_for_loop_structure():
164127
"""Generated JS has correct for-loop structure for game board."""
165-
game_file = Path("examples/memory_game_en.multi")
166-
source = game_file.read_text()
167-
lexer = Lexer(source, lang="en")
168-
tokens = lexer.tokenize()
169-
parser = Parser(tokens, lang="en")
170-
program = parser.parse()
171-
ir_program = lower_to_semantic_ir(program, lang="en")
172-
ui_result = lower_to_ui(ir_program)
128+
ui_result = _load_memory_game_ui()
173129
js = ui_result.emit_js()
174130

175131
# Check for loop iterations 0-7
@@ -192,21 +148,16 @@ def test_memory_game_js_for_loop_structure():
192148
if 'className = \'reset-btn\'' in line:
193149
reset_button_line = i
194150

195-
if for_loop_line and status_div_line:
196-
# Status div should be after for loop
151+
if for_loop_line is not None and status_div_line is not None:
152+
# Status div and reset button should be after the card loop.
197153
assert status_div_line > for_loop_line
154+
if for_loop_line is not None and reset_button_line is not None:
155+
assert reset_button_line > for_loop_line
198156

199157

200158
def test_memory_game_html_valid_utf8():
201159
"""Generated HTML is valid UTF-8 and encodes properly."""
202-
game_file = Path("examples/memory_game_en.multi")
203-
source = game_file.read_text()
204-
lexer = Lexer(source, lang="en")
205-
tokens = lexer.tokenize()
206-
parser = Parser(tokens, lang="en")
207-
program = parser.parse()
208-
ir_program = lower_to_semantic_ir(program, lang="en")
209-
ui_result = lower_to_ui(ir_program)
160+
ui_result = _load_memory_game_ui()
210161
html = ui_result.emit_html()
211162

212163
# Should be valid UTF-8 and encodable without errors
@@ -218,14 +169,7 @@ def test_memory_game_html_valid_utf8():
218169

219170
def test_memory_game_js_event_handlers():
220171
"""Generated JS has event handlers for card clicks."""
221-
game_file = Path("examples/memory_game_en.multi")
222-
source = game_file.read_text()
223-
lexer = Lexer(source, lang="en")
224-
tokens = lexer.tokenize()
225-
parser = Parser(tokens, lang="en")
226-
program = parser.parse()
227-
ir_program = lower_to_semantic_ir(program, lang="en")
228-
ui_result = lower_to_ui(ir_program)
172+
ui_result = _load_memory_game_ui()
229173
js = ui_result.emit_js()
230174

231175
# Check for event handler attachment

0 commit comments

Comments
 (0)