Skip to content

Commit 4b362a7

Browse files
Feat: Add list list comprehension to demo.
1 parent b82c452 commit 4b362a7

7 files changed

Lines changed: 26 additions & 24 deletions

File tree

compiler/README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,13 @@ cargo test --features wasm-tests
142142
3. Cytron, Ferrante, Rosen, Wegman & Zadeck, *Efficiently Computing Static Single Assignment Form* (TOPLAS 1991). SSA, $\phi$-nodes.
143143
4. Gudeman, *Representing Type Information in Dynamically Typed Languages* (1993). NaN-boxing.
144144
5. Deutsch & Schiffman, *Efficient Implementation of the Smalltalk-80 System* (POPL 1984). Inline caching.
145-
6. Hölzle & Ungar, *Optimizing Dynamically-Dispatched Calls with Run-Time Type Feedback* (PLDI 1994). Adaptive rewriting.
146-
7. Michie, *Memo Functions and Machine Learning* (Nature 1968). Memoization.
147-
8. McCarthy, *Recursive Functions of Symbolic Expressions* (CACM 1960). Mark-sweep garbage collector.
148-
9. Shannon, PEP 659: *Specializing Adaptive Interpreter* (2021). Tiered specialization.
145+
6. Ertl & Gregg, *The Structure and Performance of Efficient Interpreters* (JILP 2003). Bytecode dispatch, superinstructions.
146+
7. Hölzle & Ungar, *Optimizing Dynamically-Dispatched Calls with Run-Time Type Feedback* (PLDI 1994). Adaptive rewriting.
147+
8. Michie, *Memo Functions and Machine Learning* (Nature 1968). Memoization.
148+
9. McCarthy, *Recursive Functions of Symbolic Expressions* (CACM 1960). Mark-sweep garbage collector.
149+
10. Knuth, *The Art of Computer Programming, Vol. 2: Seminumerical Algorithms* (1981). Arbitrary-precision arithmetic, §4.3.
150+
11. Shannon, PEP 659: *Specializing Adaptive Interpreter* (2021). Tiered specialization.
151+
12. O'Connor, PEP 709: *Inlined Comprehensions* (2023). Drain-and-reinject compilation.
149152

150153
### License
151154

compiler/src/modules/parser/control.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
188188
let before = sp as u16;
189189
let after = (vars.len() - sp - 1) as u16;
190190
self.chunk.emit(OpCode::UnpackEx, (before << 8) | after);
191-
for var in vars.iter().rev() {
191+
for var in &vars {
192192
self.store_name(var.clone());
193193
}
194194
} else {
195195
self.chunk.emit(OpCode::UnpackSequence, vars.len() as u16);
196-
for var in vars.iter().rev() {
196+
for var in &vars {
197197
self.store_name(var.clone());
198198
}
199199
}

compiler/src/modules/parser/literals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
130130
self.store_name(vars[0].clone());
131131
} else {
132132
self.chunk.emit(OpCode::UnpackSequence, vars.len() as u16);
133-
for var in vars.iter().rev() {
133+
for var in &vars {
134134
self.store_name(var.clone());
135135
}
136136
}

compiler/src/modules/parser/stmt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
195195
self.expr();
196196
let after = (targets.len() - 1) as u16;
197197
self.chunk.emit(OpCode::UnpackEx, after);
198-
for target in targets.into_iter().rev() {
198+
for target in targets {
199199
self.store_name(target.trim_start_matches('*').to_string());
200200
}
201201
false
@@ -408,7 +408,7 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
408408
} else {
409409
self.chunk.emit(OpCode::UnpackSequence, targets.len() as u16);
410410
}
411-
for target in targets.into_iter().rev() {
411+
for target in targets {
412412
self.store_name(target.trim_start_matches('*').to_string());
413413
}
414414
false

compiler/src/modules/vm/builtins.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ impl<'a> VM<'a> {
1414
*/
1515

1616
pub fn call_print(&mut self, op: u16) -> Result<(), VmErr> {
17-
let mut args = self.pop_n(op as usize)?;
18-
args.reverse();
17+
let args = self.pop_n(op as usize)?;
1918
let s = args.iter().map(|v| self.display(*v)).collect::<Vec<_>>().join(" ");
2019
self.output.push(s);
2120
Ok(())

compiler/tests/cases/parser_cases.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -668,14 +668,14 @@
668668
{
669669
"src": "a, b = 1, 2",
670670
"constants": ["1", "2"],
671-
"names": ["b_1", "a_1"],
671+
"names": ["a_1", "b_1"],
672672
"instructions": [["LoadConst",0], ["LoadConst",1], ["BuildTuple",2], ["UnpackSequence",2], ["StoreName",0], ["StoreName",1], ["ReturnValue",0]],
673673
"annotations": {}
674674
},
675675
{
676676
"src": "a, b, c = 1, 2, 3",
677677
"constants": ["1", "2", "3"],
678-
"names": ["c_1", "b_1", "a_1"],
678+
"names": ["a_1", "b_1", "c_1"],
679679
"instructions": [["LoadConst",0], ["LoadConst",1], ["LoadConst",2], ["BuildTuple",3], ["UnpackSequence",3], ["StoreName",0], ["StoreName",1], ["StoreName",2], ["ReturnValue",0]],
680680
"annotations": {}
681681
},
@@ -988,21 +988,21 @@
988988
{
989989
"src": "*a, b = [1, 2, 3]",
990990
"constants": ["1", "2", "3"],
991-
"names": ["b_1", "a_1"],
991+
"names": ["a_1", "b_1"],
992992
"instructions": [["LoadConst",0], ["LoadConst",1], ["LoadConst",2], ["BuildList",3], ["UnpackEx",1], ["StoreName",0], ["StoreName",1], ["ReturnValue",0]],
993993
"annotations": {}
994994
},
995995
{
996996
"src": "a, *b = [1, 2, 3]",
997997
"constants": ["1", "2", "3"],
998-
"names": ["b_1", "a_1"],
998+
"names": ["a_1", "b_1"],
999999
"instructions": [["LoadConst",0], ["LoadConst",1], ["LoadConst",2], ["BuildList",3], ["UnpackEx",256], ["StoreName",0], ["StoreName",1], ["ReturnValue",0]],
10001000
"annotations": {}
10011001
},
10021002
{
10031003
"src": "a, *b, c = [1, 2, 3, 4]",
10041004
"constants": ["1", "2", "3", "4"],
1005-
"names": ["c_1", "b_1", "a_1"],
1005+
"names": ["a_1", "b_1", "c_1"],
10061006
"instructions": [["LoadConst",0], ["LoadConst",1], ["LoadConst",2], ["LoadConst",3], ["BuildList",4], ["UnpackEx",257], ["StoreName",0], ["StoreName",1], ["StoreName",2], ["ReturnValue",0]],
10071007
"annotations": {}
10081008
},
@@ -1095,14 +1095,14 @@
10951095
{
10961096
"src": "for a, b in x:\n pass",
10971097
"constants": [],
1098-
"names": ["x_0", "b_1", "a_1", "a_0", "a_2", "b_0", "b_2"],
1098+
"names": ["x_0", "a_1", "b_1", "a_0", "a_2", "b_0", "b_2"],
10991099
"instructions": [["LoadName",0], ["GetIter",0], ["ForIter",7], ["UnpackSequence",2], ["StoreName",1], ["StoreName",2], ["Jump",2], ["Phi",4], ["Phi",6], ["ReturnValue",0]],
11001100
"annotations": {}
11011101
},
11021102
{
11031103
"src": "for a, b, c in x:\n pass",
11041104
"constants": [],
1105-
"names": ["x_0", "c_1", "b_1", "a_1", "a_0", "a_2", "b_0", "b_2", "c_0", "c_2"],
1105+
"names": ["x_0", "a_1", "b_1", "c_1", "a_0", "a_2", "b_0", "b_2", "c_0", "c_2"],
11061106
"instructions": [["LoadName",0], ["GetIter",0], ["ForIter",8], ["UnpackSequence",3], ["StoreName",1], ["StoreName",2], ["StoreName",3], ["Jump",2], ["Phi",5], ["Phi",7], ["Phi",9], ["ReturnValue",0]],
11071107
"annotations": {}
11081108
},
@@ -1155,14 +1155,14 @@
11551155
{
11561156
"src": "for (a, b) in x:\n pass",
11571157
"constants": [],
1158-
"names": ["x_0", "b_1", "a_1", "a_0", "a_2", "b_0", "b_2"],
1158+
"names": ["x_0", "a_1", "b_1", "a_0", "a_2", "b_0", "b_2"],
11591159
"instructions": [["LoadName",0], ["GetIter",0], ["ForIter",7], ["UnpackSequence",2], ["StoreName",1], ["StoreName",2], ["Jump",2], ["Phi",4], ["Phi",6], ["ReturnValue",0]],
11601160
"annotations": {}
11611161
},
11621162
{
11631163
"src": "for a, *b in x:\n pass",
11641164
"constants": [],
1165-
"names": ["x_0", "b_1", "a_1", "a_0", "a_2", "b_0", "b_2"],
1165+
"names": ["x_0", "a_1", "b_1", "a_0", "a_2", "b_0", "b_2"],
11661166
"instructions": [["LoadName",0], ["GetIter",0], ["ForIter",7], ["UnpackEx",256], ["StoreName",1], ["StoreName",2], ["Jump",2], ["Phi",4], ["Phi",6], ["ReturnValue",0]],
11671167
"annotations": {}
11681168
},
@@ -1543,10 +1543,10 @@
15431543
{
15441544
"src": "x = {k: v for k, v in items}",
15451545
"constants": [],
1546-
"names": ["k_0", "v_0", "items_0", "v_1", "k_1", "x_1"],
1547-
"instructions": [["BuildDict",0], ["LoadName",2], ["GetIter",0], ["ForIter",11], ["UnpackSequence",2], ["StoreName",3], ["StoreName",4], ["LoadName",4], ["LoadName",3], ["MapAdd",0], ["Jump",3], ["StoreName",5], ["ReturnValue",0]],
1546+
"names": ["k_0", "v_0", "items_0", "k_1", "v_1", "x_1"],
1547+
"instructions": [["BuildDict",0], ["LoadName",2], ["GetIter",0], ["ForIter",11], ["UnpackSequence",2], ["StoreName",3], ["StoreName",4], ["LoadName",3], ["LoadName",4], ["MapAdd",0], ["Jump",3], ["StoreName",5], ["ReturnValue",0]],
15481548
"annotations": {}
1549-
}
1549+
},
15501550
{
15511551
"src": "a[0] = 1",
15521552
"constants": ["0","1"],

demo/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const WASM_SOURCES = DEV
1313
? [`https://demo.edgepython.com/compiler_lib.wasm${_bust}`]
1414
: [`./compiler_lib.wasm${_bust}`];
1515

16-
const DEFAULT_CODE = `"""\nImplements a pure functional pipeline using head-tail recursion to avoid state mutation.\n\nReferences:\n* Backus, J. (1978). Algebra of Programs (Function composition).\n"""\n\ndef double(n: int) -> int:\n return n * 2\n\ndef square(n: int) -> int:\n return n * n\n\ndef apply_pipeline(value: int, steps: list[int]) -> int:\n # Stop recursion when no steps remain\n if not steps:\n return value\n\n first_fn = steps[0]\n remaining_steps = steps[1:]\n\n return apply_pipeline(first_fn(value), remaining_steps)\n\ndef transform_list(elements: list[int], steps: list[int]) -> list[int]:\n # Stop recursion when list is empty\n if not elements:\n return []\n\n head = elements[0]\n tail = elements[1:]\n\n transformed = apply_pipeline(head, steps)\n\n return [transformed] + transform_list(tail, steps)\n\ndata: list[int] = [1, 2, 3]\npipeline: list = [double, square]\n\nresult = transform_list(data, pipeline)\n\nprint(f"Input: {data}")\nprint(f"Output: {result}")`;
16+
const DEFAULT_CODE = `"""\nImplements a functional pipeline using function composition and list comprehensions.\nReferences: Backus, J. (1978).\n"""\n\ndef double(n: int) -> int:\n return n * 2\n\ndef square(n: int) -> int:\n return n * n\n\ndef apply_pipeline(value: int, steps: list) -> int:\n # Stop recursion when no steps remain\n if not steps:\n return value\n\n first_fn = steps[0]\n remaining_steps = steps[1:]\n\n return apply_pipeline(first_fn(value), remaining_steps)\n\ndata: list[int] = [1, 2, 3]\npipeline: list = [double, square]\n\nresult = [apply_pipeline(x, pipeline) for x in data] # Stop recursion when list is empty\n\nprint(f"Input: {data}")\nprint(f"Output: {result}")`;
1717

1818
const CLS = { ok: 'ml-auto text-[#7daf7a]', err: 'ml-auto text-[#d67f6d]' };
1919
const MAX_LINES = 99;

0 commit comments

Comments
 (0)