Skip to content

Commit fbb3a42

Browse files
Feat: Implementing for, conditionals and type declaration (IT refactor).
1 parent 7b0543a commit fbb3a42

6 files changed

Lines changed: 224 additions & 126 deletions

File tree

compiler/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ log = "0.4"
2929
simple_logger = "5.0"
3030

3131
[dev-dependencies]
32+
serde = { version = "1", features = ["derive"] }
3233
serde_json = "1"

compiler/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn main() {
2929

3030
initialize_logger();
3131

32-
let source = "def add(a, b): a + b\nresult = add(1, 2)";
32+
let source = "x = 10\nif x > 20:\ny = 1\nelif x > 5:\ny = 2\nelse:\ny = 3";
3333

3434
let chunk = modules::parser::Parser::new(source, modules::lexer::lexer(source)).parse();
3535

@@ -46,5 +46,6 @@ fn main() {
4646

4747
info!("constants: {:?}", chunk.constants);
4848
info!("names: {:?}", chunk.names);
49+
info!("annotations: {:?}", chunk.annotations);
4950

5051
}

compiler/src/modules/parser.rs

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub enum OpCode {
5555
CallSorted, CallEnumerate, CallZip, CallList, CallTuple, CallDict,
5656
CallIsInstance, CallSet, CallInput, CallOrd, BuildDict, BuildList,
5757
NotEq, Lt, Gt, LtEq, GtEq, And,
58-
Or, Not
58+
Or, Not, JumpIfFalse, Jump, GetIter, ForIter
5959
}
6060

6161
#[derive(Debug)] pub struct Instruction { pub opcode: OpCode, pub operand: u16 }
@@ -68,7 +68,8 @@ pub struct SSAChunk {
6868
pub instructions: Vec<Instruction>,
6969
pub constants: Vec<Value>,
7070
pub names: Vec<String>,
71-
pub functions: Vec<(Vec<String>, SSAChunk)>
71+
pub functions: Vec<(Vec<String>, SSAChunk)>,
72+
pub annotations: HashMap<String, String>,
7273
}
7374

7475
impl SSAChunk {
@@ -122,7 +123,12 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
122123
}
123124

124125
pub fn parse(mut self) -> SSAChunk {
125-
while !self.at_end() { self.stmt(); if !self.at_end() { self.chunk.emit(OpCode::PopTop, 0); } }
126+
while !self.at_end() {
127+
let is_compound = matches!(self.peek(),
128+
Some(TokenType::For | TokenType::If | TokenType::While));
129+
self.stmt();
130+
if !self.at_end() && !is_compound { self.chunk.emit(OpCode::PopTop, 0); }
131+
}
126132
self.chunk.emit(OpCode::ReturnValue, 0);
127133
self.chunk
128134
}
@@ -171,13 +177,62 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
171177
match self.peek() {
172178
Some(TokenType::If) => self.if_stmt(),
173179
Some(TokenType::While) => self.while_stmt(),
174-
_ => self.expr(),
180+
Some(TokenType::For) => self.for_stmt(),
181+
_ => self.expr()
175182
}
176183
}
177184

178-
fn if_stmt(&mut self) { self.advance(); self.enter_block(); self.expr(); self.chunk.emit(OpCode::PopTop, 0); if matches!(self.peek(), Some(TokenType::Colon)) { self.advance(); } self.stmt(); self.commit_block(); }
179185
fn while_stmt(&mut self) { self.advance(); self.enter_block(); self.expr(); self.chunk.emit(OpCode::PopTop, 0); if matches!(self.peek(), Some(TokenType::Colon)) { self.advance(); } self.stmt(); self.commit_block(); }
180186

187+
fn if_stmt(&mut self) {
188+
self.advance(); // consume 'if' o 'elif'
189+
self.expr();
190+
self.chunk.emit(OpCode::JumpIfFalse, 0);
191+
let jf = self.chunk.instructions.len() - 1;
192+
self.eat(TokenType::Colon);
193+
self.stmt();
194+
self.chunk.emit(OpCode::PopTop, 0);
195+
196+
match self.peek() {
197+
Some(TokenType::Elif) => { self.chunk.emit(OpCode::Jump, 0); let jmp = self.chunk.instructions.len() - 1; self.patch(jf); self.if_stmt(); self.patch(jmp); }
198+
Some(TokenType::Else) => { self.advance(); self.chunk.emit(OpCode::Jump, 0); let jmp = self.chunk.instructions.len() - 1; self.patch(jf); self.eat(TokenType::Colon); self.stmt(); self.chunk.emit(OpCode::PopTop, 0); self.patch(jmp); }
199+
_ => { self.patch(jf); }
200+
}
201+
}
202+
203+
fn for_stmt(&mut self) {
204+
self.advance();
205+
let var = { let t = self.advance(); self.lexeme(&t).to_string() };
206+
self.eat(TokenType::In);
207+
self.expr();
208+
self.chunk.emit(OpCode::GetIter, 0);
209+
210+
let loop_start = self.chunk.instructions.len() as u16;
211+
self.chunk.emit(OpCode::ForIter, 0);
212+
let fi = self.chunk.instructions.len() - 1;
213+
214+
let ver = self.increment_version(&var);
215+
let idx = self.chunk.push_name(&format!("{}_{}", var, ver));
216+
self.chunk.emit(OpCode::StoreName, idx);
217+
218+
self.eat(TokenType::Colon);
219+
self.stmt();
220+
self.chunk.emit(OpCode::PopTop, 0); // ← nuevo
221+
self.chunk.emit(OpCode::Jump, loop_start);
222+
self.patch(fi);
223+
}
224+
225+
// helpers
226+
fn patch(&mut self, pos: usize) {
227+
self.chunk.instructions[pos].operand = self.chunk.instructions.len() as u16;
228+
}
229+
fn eat(&mut self, kind: TokenType) {
230+
if matches!(self.peek(), Some(k) if k == kind) { self.advance(); }
231+
}
232+
fn eat_if(&mut self, kind: TokenType) -> bool {
233+
if matches!(self.peek(), Some(k) if k == kind) { self.advance(); true } else { false }
234+
}
235+
181236
fn expr(&mut self) {
182237
let t = self.advance();
183238
match t.kind {
@@ -260,11 +315,16 @@ impl<'src, I: Iterator<Item = Token>> Parser<'src, I> {
260315

261316
fn name(&mut self, t: Token) {
262317
let name = self.lexeme(&t).to_string();
263-
if matches!(self.peek(), Some(TokenType::Colon)) { self.advance(); self.advance(); }
318+
319+
if self.eat_if(TokenType::Colon) {
320+
let ann = { let t = self.advance(); self.lexeme(&t).to_string() };
321+
self.chunk.annotations.insert(name.clone(), ann);
322+
}
323+
264324
match self.peek() {
265325
Some(TokenType::Equal) => self.assign(name),
266326
Some(TokenType::Lpar) => self.call(name),
267-
_ => self.emit_load_ssa(name),
327+
_ => self.emit_load_ssa(name),
268328
}
269329
}
270330

compiler/tests/cases/lexer_cases.json

Lines changed: 67 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,87 @@
11
[
2-
["1 + 1", ["Int", "Plus", "Int", "Endmarker"]],
3-
["x - 1", ["Name", "Minus", "Int", "Endmarker"]],
4-
["x * 2", ["Name", "Star", "Int", "Endmarker"]],
5-
["x / 2", ["Name", "Slash", "Int", "Endmarker"]],
6-
["x % 2", ["Name", "Percent", "Int", "Endmarker"]],
7-
["x & 2", ["Name", "Amper", "Int", "Endmarker"]],
8-
["x | 2", ["Name", "Vbar", "Int", "Endmarker"]],
2+
["1 + 1", ["Int", "Plus", "Int", "Endmarker"]],
3+
["x - 1", ["Name", "Minus", "Int", "Endmarker"]],
4+
["x * 2", ["Name", "Star", "Int", "Endmarker"]],
5+
["x / 2", ["Name", "Slash", "Int", "Endmarker"]],
6+
["x % 2", ["Name", "Percent", "Int", "Endmarker"]],
7+
["x & 2", ["Name", "Amper", "Int", "Endmarker"]],
8+
["x | 2", ["Name", "Vbar", "Int", "Endmarker"]],
99
["x ^ 2", ["Name", "Circumflex", "Int", "Endmarker"]],
10-
["~x", ["Tilde", "Name", "Endmarker"]],
11-
["x @ y", ["Name", "At", "Name", "Endmarker"]],
12-
["x < 2", ["Name", "Less", "Int", "Endmarker"]],
13-
["x > 2", ["Name", "Greater", "Int", "Endmarker"]],
14-
["x ** 2", ["Name", "DoubleStar", "Int", "Endmarker"]],
10+
["~x", ["Tilde", "Name", "Endmarker"]],
11+
["x @ y", ["Name", "At", "Name", "Endmarker"]],
12+
["x ** 2", ["Name", "DoubleStar", "Int", "Endmarker"]],
1513
["x // 2", ["Name", "DoubleSlash", "Int", "Endmarker"]],
16-
["x >> 2", ["Name", "RightShift", "Int", "Endmarker"]],
17-
["x << 2", ["Name", "LeftShift", "Int", "Endmarker"]],
14+
["x >> 2", ["Name", "RightShift", "Int", "Endmarker"]],
15+
["x << 2", ["Name", "LeftShift", "Int", "Endmarker"]],
16+
17+
["x < 2", ["Name", "Less", "Int", "Endmarker"]],
18+
["x > 2", ["Name", "Greater", "Int", "Endmarker"]],
1819
["x >= 2", ["Name", "GreaterEqual", "Int", "Endmarker"]],
19-
["x <= 2", ["Name", "LessEqual", "Int", "Endmarker"]],
20-
["x == 5", ["Name", "EqEqual", "Int", "Endmarker"]],
21-
["x != 5", ["Name", "NotEqual", "Int", "Endmarker"]],
22-
["...", ["Ellipsis", "Endmarker"]],
20+
["x <= 2", ["Name", "LessEqual", "Int", "Endmarker"]],
21+
["x == 5", ["Name", "EqEqual", "Int", "Endmarker"]],
22+
["x != 5", ["Name", "NotEqual", "Int", "Endmarker"]],
23+
["...", ["Ellipsis", "Endmarker"]],
2324

24-
["x = 5", ["Name", "Equal", "Int", "Endmarker"]],
25-
["x += 1", ["Name", "PlusEqual", "Int", "Endmarker"]],
26-
["x -= 1", ["Name", "MinEqual", "Int", "Endmarker"]],
27-
["x *= 2", ["Name", "StarEqual", "Int", "Endmarker"]],
28-
["x /= 2", ["Name", "SlashEqual", "Int", "Endmarker"]],
29-
["x %= 2", ["Name", "PercentEqual", "Int", "Endmarker"]],
30-
["x &= 2", ["Name", "AmperEqual", "Int", "Endmarker"]],
31-
["x |= 2", ["Name", "VbarEqual", "Int", "Endmarker"]],
32-
["x ^= 2", ["Name", "CircumflexEqual", "Int", "Endmarker"]],
33-
["x @= y", ["Name", "AtEqual", "Name", "Endmarker"]],
34-
["x **= 2", ["Name", "DoubleStarEqual", "Int", "Endmarker"]],
35-
["x //= 2", ["Name", "DoubleSlashEqual", "Int", "Endmarker"]],
36-
["x >>= 2", ["Name", "RightShiftEqual", "Int", "Endmarker"]],
37-
["x <<= 2", ["Name", "LeftShiftEqual", "Int", "Endmarker"]],
38-
["x -> y", ["Name", "Rarrow", "Name", "Endmarker"]],
39-
["x := 5", ["Name", "ColonEqual", "Int", "Endmarker"]],
25+
["x = 5", ["Name", "Equal", "Int", "Endmarker"]],
26+
["x += 1", ["Name", "PlusEqual", "Int", "Endmarker"]],
27+
["x -= 1", ["Name", "MinEqual", "Int", "Endmarker"]],
28+
["x *= 2", ["Name", "StarEqual", "Int", "Endmarker"]],
29+
["x /= 2", ["Name", "SlashEqual", "Int", "Endmarker"]],
30+
["x %= 2", ["Name", "PercentEqual", "Int", "Endmarker"]],
31+
["x &= 2", ["Name", "AmperEqual", "Int", "Endmarker"]],
32+
["x |= 2", ["Name", "VbarEqual", "Int", "Endmarker"]],
33+
["x ^= 2", ["Name", "CircumflexEqual", "Int", "Endmarker"]],
34+
["x @= y", ["Name", "AtEqual", "Name", "Endmarker"]],
35+
["x **= 2", ["Name", "DoubleStarEqual", "Int", "Endmarker"]],
36+
["x //= 2", ["Name", "DoubleSlashEqual", "Int", "Endmarker"]],
37+
["x >>= 2", ["Name", "RightShiftEqual", "Int", "Endmarker"]],
38+
["x <<= 2", ["Name", "LeftShiftEqual", "Int", "Endmarker"]],
39+
["x -> y", ["Name", "Rarrow", "Name", "Endmarker"]],
40+
["x := 5", ["Name", "ColonEqual", "Int", "Endmarker"]],
4041

41-
["42", ["Int", "Endmarker"]],
42-
["1_000_000", ["Int", "Endmarker"]],
43-
["0xFF", ["Int", "Endmarker"]],
44-
["0b1010", ["Int", "Endmarker"]],
45-
["0o77", ["Int", "Endmarker"]],
46-
["3.14", ["Float", "Endmarker"]],
47-
[".5", ["Float", "Endmarker"]],
48-
["1e-5", ["Float", "Endmarker"]],
49-
["3j", ["Complex", "Endmarker"]],
50-
["2.5J", ["Complex", "Endmarker"]],
42+
["42", ["Int", "Endmarker"]],
43+
["1_000_000", ["Int", "Endmarker"]],
44+
["0xFF", ["Int", "Endmarker"]],
45+
["0b1010", ["Int", "Endmarker"]],
46+
["0o77", ["Int", "Endmarker"]],
47+
["3.14", ["Float", "Endmarker"]],
48+
[".5", ["Float", "Endmarker"]],
49+
["1e-5", ["Float", "Endmarker"]],
50+
["3j", ["Complex", "Endmarker"]],
51+
["2.5J", ["Complex", "Endmarker"]],
5152

52-
["\"hello\"", ["String", "Endmarker"]],
53-
["'hello'", ["String", "Endmarker"]],
54-
["b\"bytes\"", ["String", "Endmarker"]],
55-
["r\"raw\"", ["String", "Endmarker"]],
56-
["u\"unicode\"", ["String", "Endmarker"]],
57-
["\"\"\"triple\"\"\"", ["String", "Endmarker"]],
53+
["'hello'", ["String", "Endmarker"]],
54+
["b'bytes'", ["String", "Endmarker"]],
55+
["r'raw'", ["String", "Endmarker"]],
56+
["u'unicode'", ["String", "Endmarker"]],
5857
["'''triple'''", ["String", "Endmarker"]],
5958

60-
["f\"hello\"", ["FstringStart", "FstringMiddle", "FstringEnd", "Endmarker"]],
61-
["f\"hello {x}\"", ["FstringStart", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
62-
["f\"{a} and {b}\"", ["FstringStart", "Lbrace", "Name", "Rbrace", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
63-
["f\"\"\"multi\nline\"\"\"", ["FstringStart", "FstringMiddle", "FstringEnd", "Endmarker"]],
64-
["f\"\"\"multi\n{x}\"\"\"", ["FstringStart", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
59+
["f'hello'", ["FstringStart", "FstringMiddle", "FstringEnd", "Endmarker"]],
60+
["f'hello {x}'", ["FstringStart", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
61+
["f'{a} and {b}'", ["FstringStart", "Lbrace", "Name", "Rbrace", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
62+
["f'''multi\nline'''", ["FstringStart", "FstringMiddle", "FstringEnd", "Endmarker"]],
63+
["f'''multi\n{x}'''", ["FstringStart", "FstringMiddle", "Lbrace", "Name", "Rbrace", "FstringEnd", "Endmarker"]],
6564

66-
["# comment", ["Comment", "Endmarker"]],
65+
["# comment", ["Comment", "Endmarker"]],
6766
["x = 1 # inline", ["Name", "Equal", "Int", "Comment", "Endmarker"]],
6867

69-
["", ["Endmarker"]],
70-
[" ", ["Endmarker"]],
71-
["\n", ["Newline", "Endmarker"]],
68+
["", ["Endmarker"]],
69+
[" ", ["Endmarker"]],
70+
["\n", ["Newline", "Endmarker"]],
7271
["# N/a\n", ["Comment", "Newline", "Endmarker"]],
7372

74-
["if x:\n pass\n", ["If", "Name", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Endmarker"]],
75-
["if True:\n\tpass\n", ["If", "True", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Endmarker"]],
76-
["def f():\n if True:\n pass\n", ["Def", "Name", "Lpar", "Rpar", "Colon", "Newline", "Indent", "If", "True", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Dedent", "Endmarker"]],
73+
["x = 1", ["Name", "Equal", "Int", "Endmarker"]],
74+
["(\n)\n", ["Lpar", "Nl", "Rpar", "Newline", "Endmarker"]],
75+
["[\n1,\n2\n]\n", ["Lsqb", "Nl", "Int", "Comma", "Nl", "Int", "Nl", "Rsqb", "Newline", "Endmarker"]],
76+
77+
["if x:\n pass\n", ["If", "Name", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Endmarker"]],
78+
["if True:\n\tpass\n", ["If", "True", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Endmarker"]],
7779
["if x:\n pass\n\n pass\n", ["If", "Name", "Colon", "Newline", "Indent", "Pass", "Nl", "Newline", "Pass", "Newline", "Dedent", "Endmarker"]],
78-
["if x:\n \tpass\n", ["If", "Name", "Colon", "Newline", "Endmarker"]],
80+
["if x:\n \tpass\n", ["If", "Name", "Colon", "Newline", "Endmarker"]],
7981
["if x:\n if y:\n pass\nz\n", ["If", "Name", "Colon", "Newline", "Indent", "If", "Name", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Dedent", "Name", "Newline", "Endmarker"]],
80-
["x = 1", ["Name", "Equal", "Int", "Endmarker"]],
81-
["(\n)\n", ["Lpar", "Nl", "Rpar", "Newline", "Endmarker"]],
82-
["[\n1,\n2\n]\n", ["Lsqb", "Nl", "Int", "Comma", "Nl", "Int", "Nl", "Rsqb", "Newline", "Endmarker"]],
82+
["def f():\n if True:\n pass\n", ["Def", "Name", "Lpar", "Rpar", "Colon", "Newline", "Indent", "If", "True", "Colon", "Newline", "Indent", "Pass", "Newline", "Dedent", "Dedent", "Endmarker"]],
8383

84-
["match = 5", ["Name", "Equal", "Int", "Endmarker"]],
84+
["match = 5", ["Name", "Equal", "Int", "Endmarker"]],
8585
["case = True", ["Name", "Equal", "True", "Endmarker"]],
8686
["type = None", ["Name", "Equal", "None", "Endmarker"]],
8787
["type X = int\n", ["Type", "Name", "Equal", "Name", "Newline", "Endmarker"]],

0 commit comments

Comments
 (0)