Skip to content

Commit 57f62e8

Browse files
Feat: Async and await methods.
1 parent 2afe1bf commit 57f62e8

2 files changed

Lines changed: 78 additions & 4 deletions

File tree

compiler/src/modules/parser.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub enum OpCode {
3838
In, NotIn, Is, IsNot, UnpackSequence, BuildTuple,
3939
SetupWith, ExitWith, Yield, Del, Assert, Global,
4040
Nonlocal, UnpackArgs, ListComp, SetComp, DictComp, BuildSet,
41-
RaiseFrom, UnpackEx, LoadEllipsis, GenExpr
41+
RaiseFrom, UnpackEx, LoadEllipsis, GenExpr, Await, MakeCoroutine
4242
}
4343

4444
// ─── Builtin dispatch table (O(1) lookup) ───────────────────────────────────
@@ -334,16 +334,41 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
334334
Some(TokenType::For) => { self.for_stmt(); false }
335335
Some(TokenType::Def) => { self.advance(); self.func_def(0); false }
336336
Some(TokenType::Match) => { self.match_stmt(); false }
337+
Some(TokenType::Async) => {
338+
self.advance();
339+
match self.peek() {
340+
Some(TokenType::Def) => {
341+
self.advance();
342+
self.async_func_def(0);
343+
}
344+
Some(TokenType::For) => { self.for_stmt(); }
345+
Some(TokenType::With) => { self.with_stmt(); }
346+
_ => {}
347+
}
348+
false
349+
}
350+
Some(TokenType::Await) => {
351+
self.advance();
352+
self.expr();
353+
self.chunk.emit(OpCode::Await, 0);
354+
true
355+
}
337356
Some(TokenType::At) => {
338357
let mut count = 0u16;
339358
while self.eat_if(TokenType::At) {
340359
self.expr();
341360
count += 1;
342361
}
343-
self.advance();
344-
self.func_def(count);
362+
if self.eat_if(TokenType::Async) {
363+
self.advance();
364+
self.async_func_def(count);
365+
} else {
366+
self.advance();
367+
self.func_def(count);
368+
}
345369
false
346-
} Some(TokenType::Class) => { self.advance(); self.class_def(); false }
370+
}
371+
Some(TokenType::Class) => { self.advance(); self.class_def(); false }
347372
Some(TokenType::Pass) => { self.advance(); false }
348373
Some(TokenType::Try) => { self.try_stmt(); false }
349374
Some(TokenType::Import) => { self.import_stmt(); false }
@@ -960,10 +985,29 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
960985
Some(TokenType::Minus) => { self.advance(); self.parse_unary(); self.chunk.emit(OpCode::Minus, 0); }
961986
Some(TokenType::Not) => { self.advance(); self.parse_unary(); self.chunk.emit(OpCode::Not, 0); }
962987
Some(TokenType::Tilde) => { self.advance(); self.parse_unary(); self.chunk.emit(OpCode::BitNot, 0); }
988+
Some(TokenType::Await) => { self.advance(); self.parse_unary(); self.chunk.emit(OpCode::Await, 0); }
963989
_ => self.parse_atom(),
964990
}
965991
}
966992

993+
fn async_func_def(&mut self, decorators: u16) {
994+
let fname = { let n = self.advance(); self.lexeme(&n).to_string() };
995+
let (params, defaults) = self.parse_params();
996+
let body = self.compile_body(&params);
997+
998+
let fi = self.chunk.functions.len() as u16;
999+
self.chunk.functions.push((params, body, defaults));
1000+
self.chunk.emit(OpCode::MakeCoroutine, fi);
1001+
1002+
for _ in 0..decorators {
1003+
self.chunk.emit(OpCode::Call, 1);
1004+
}
1005+
1006+
let ver = self.increment_version(&fname);
1007+
let i = self.chunk.push_name(&format!("{}_{}", fname, ver));
1008+
self.chunk.emit(OpCode::StoreName, i);
1009+
}
1010+
9671011
fn parse_not(&mut self) {
9681012
if matches!(self.peek(), Some(TokenType::Not)) {
9691013
self.advance(); self.parse_not(); self.chunk.emit(OpCode::Not, 0);

compiler/tests/cases/parser_cases.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,5 +1112,35 @@
11121112
"names": ["x_0", "c_1", "b_1", "a_1", "a_0", "a_2", "b_0", "b_2", "c_0", "c_2"],
11131113
"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]],
11141114
"annotations": {}
1115+
},
1116+
{
1117+
"src": "async def f():\n pass",
1118+
"constants": [],
1119+
"names": ["f_1"],
1120+
"instructions": [["MakeCoroutine",0], ["StoreName",0], ["ReturnValue",0]],
1121+
"annotations": {},
1122+
"functions": 1
1123+
},
1124+
{
1125+
"src": "async def f():\n await x",
1126+
"constants": [],
1127+
"names": ["f_1"],
1128+
"instructions": [["MakeCoroutine",0], ["StoreName",0], ["ReturnValue",0]],
1129+
"annotations": {},
1130+
"functions": 1
1131+
},
1132+
{
1133+
"src": "x = await y",
1134+
"constants": [],
1135+
"names": ["y_0", "x_1"],
1136+
"instructions": [["LoadName",0], ["Await",0], ["StoreName",1], ["ReturnValue",0]],
1137+
"annotations": {}
1138+
},
1139+
{
1140+
"src": "await f()",
1141+
"constants": [],
1142+
"names": ["f_0"],
1143+
"instructions": [["LoadName",0], ["Call",0], ["Await",0], ["PopTop",0], ["ReturnValue",0]],
1144+
"annotations": {}
11151145
}
11161146
]

0 commit comments

Comments
 (0)