Skip to content

Commit ade13b6

Browse files
committed
introduce: hir
Signed-off-by: squeakbug <[email protected]>
1 parent 7c4997a commit ade13b6

File tree

6 files changed

+316
-56
lines changed

6 files changed

+316
-56
lines changed

crates/jpc/src/hir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod codegen;
2+
pub mod ssa;

crates/jpc/src/hir/codegen.rs

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
use std::{collections::HashMap, fmt::{self, Debug}, fs};
2+
3+
use core::{
4+
ast::{
5+
Block, DeclSection, DesignatorItem, Expr, ProcedureDeclaration,
6+
Program, Stmt, TypeDeclaration, UnlabeledStmt, VarDeclaration,
7+
},
8+
lexer::{self, Lexer},
9+
parser::{Parser, ParserError},
10+
sema::SemanticError,
11+
};
12+
13+
#[derive(Debug)]
14+
pub enum CodegenError {
15+
NotImplemented,
16+
UndefinedVariable,
17+
AssigmentToNotDefinedVariable,
18+
NoParentEnvironment,
19+
NotCallable,
20+
MismatchedTypes,
21+
MismathedArgumentsCount,
22+
AlreadyDefined,
23+
}
24+
25+
#[derive(Debug, Clone)]
26+
pub struct Var {
27+
pub number: usize,
28+
pub use_count: usize,
29+
}
30+
31+
#[derive(Debug, Clone)]
32+
pub enum Instruction {
33+
// Memory
34+
Store,
35+
Load,
36+
LoadConstant { dst: Var, const_num: usize },
37+
38+
// Arithmetic operators
39+
Add { dst: Var, src1: Var, src2: Var },
40+
Sub { dst: Var, src1: Var, src2: Var },
41+
Mul { dst: Var, src1: Var, src2: Var },
42+
Div { dst: Var, src1: Var, src2: Var },
43+
Mod { dst: Var, src1: Var, src2: Var },
44+
Negate { dst: Var, src: Var },
45+
46+
// Login operators
47+
LogAnd { dst: Var, src1: Var, src2: Var },
48+
LogOr { dst: Var, src1: Var, src2: Var },
49+
LogNot { dst: Var, src1: Var, src2: Var },
50+
Eq { dst: Var, src1: Var, src2: Var },
51+
Neq { dst: Var, src1: Var, src2: Var },
52+
Lt { dst: Var, src1: Var, src2: Var },
53+
Leq { dst: Var, src1: Var, src2: Var },
54+
Gt { dst: Var, src1: Var, src2: Var },
55+
Geq { dst: Var, src1: Var, src2: Var },
56+
}
57+
58+
#[derive(Debug, Clone)]
59+
pub enum Constant {
60+
Real(f64),
61+
Integer(i64),
62+
String(String),
63+
Boolean(bool),
64+
Null,
65+
}
66+
67+
pub struct CodeEmmiter {
68+
pub instructions: Vec<Instruction>,
69+
pub number: usize,
70+
pub constants: Vec<Constant>,
71+
}
72+
73+
impl CodeEmmiter {
74+
pub fn new() -> Self {
75+
CodeEmmiter {
76+
instructions: vec![],
77+
number: 0,
78+
constants: vec![],
79+
}
80+
}
81+
82+
fn add_const(&mut self, constant: Constant) -> usize {
83+
let num = self.constants.len();
84+
self.constants.push(constant);
85+
num
86+
}
87+
88+
fn add_var(&mut self, ) -> Var {
89+
self.number += 1;
90+
Var { number: self.number, use_count: 0 }
91+
}
92+
93+
fn visit_expr(&mut self, expr: &Box<Expr>) -> Result<Var, CodegenError> {
94+
match expr.as_ref() {
95+
Expr::Binary { left, operator, right } => {
96+
let src1 = self.visit_expr(left)?;
97+
let src2 = self.visit_expr(right)?;
98+
let dst = self.add_var();
99+
let inst = match operator.kind {
100+
lexer::TokenType::Plus => Ok(Instruction::Add { dst: dst.clone(), src1, src2 }),
101+
lexer::TokenType::Minus => Ok(Instruction::Sub { dst: dst.clone(), src1, src2 }),
102+
lexer::TokenType::Star => Ok(Instruction::Mul { dst: dst.clone(), src1, src2 }),
103+
lexer::TokenType::Slash => Ok(Instruction::Div { dst: dst.clone(), src1, src2 }),
104+
_ => Err(CodegenError::NotImplemented),
105+
}?;
106+
self.instructions.push(inst);
107+
Ok(dst)
108+
},
109+
Expr::Unary { operator, right } => {
110+
let src = self.visit_expr(right)?;
111+
match operator.kind {
112+
lexer::TokenType::Minus => {
113+
let dst = self.add_var();
114+
let inst = Instruction::Negate { dst: dst.clone(), src };
115+
self.instructions.push(inst);
116+
Ok(dst)
117+
},
118+
_ => Err(CodegenError::NotImplemented),
119+
}
120+
},
121+
Expr::Literal { value } => {
122+
match value.kind {
123+
lexer::TokenType::UnsignedInteger(ref num) => {
124+
match num.parse::<i64>() {
125+
Ok(num) => {
126+
let dst = self.add_var();
127+
let const_num = self.add_const(Constant::Integer(num));
128+
let inst = Instruction::LoadConstant {
129+
dst: dst.clone(),
130+
const_num
131+
};
132+
self.instructions.push(inst);
133+
Ok(dst)
134+
},
135+
Err(_) => Err(CodegenError::NotImplemented),
136+
}
137+
},
138+
lexer::TokenType::UnsignedReal(ref num) => {
139+
match num.parse::<f64>() {
140+
Ok(num) => {
141+
let dst = self.add_var();
142+
let const_num = self.add_const(Constant::Real(num));
143+
let inst = Instruction::LoadConstant { dst: dst.clone(), const_num };
144+
self.instructions.push(inst);
145+
Ok(dst)
146+
},
147+
Err(_) => Err(CodegenError::NotImplemented),
148+
}
149+
},
150+
lexer::TokenType::True => {
151+
let dst = self.add_var();
152+
let const_num = self.add_const(Constant::Boolean(true));
153+
let inst = Instruction::LoadConstant { dst: dst.clone(), const_num };
154+
self.instructions.push(inst);
155+
Ok(dst)
156+
},
157+
lexer::TokenType::False => {
158+
let dst = self.add_var();
159+
let const_num = self.add_const(Constant::Boolean(false));
160+
let inst = Instruction::LoadConstant { dst: dst.clone(), const_num };
161+
self.instructions.push(inst);
162+
Ok(dst)
163+
},
164+
lexer::TokenType::Nil => {
165+
let dst = self.add_var();
166+
let const_num = self.add_const(Constant::Null);
167+
let inst = Instruction::LoadConstant { dst: dst.clone(), const_num };
168+
self.instructions.push(inst);
169+
Ok(dst)
170+
},
171+
lexer::TokenType::StringLiteral(ref val) => {
172+
let dst = self.add_var();
173+
let const_num = self.add_const(Constant::String(val.clone()));
174+
let inst = Instruction::LoadConstant { dst: dst.clone(), const_num };
175+
self.instructions.push(inst);
176+
Ok(dst)
177+
},
178+
_ => Err(CodegenError::NotImplemented),
179+
}
180+
},
181+
Expr::Designator { designator } => Err(CodegenError::UndefinedVariable)
182+
}
183+
}
184+
185+
fn visit_type_declaration(&mut self, _decl: &TypeDeclaration) -> Result<(), CodegenError> {
186+
Ok(())
187+
}
188+
189+
fn visit_var_declaration(&mut self, decl: &VarDeclaration) -> Result<(), CodegenError> {
190+
Ok(())
191+
}
192+
193+
fn visit_procedure_declaration(
194+
&mut self,
195+
decl: &Box<ProcedureDeclaration>
196+
) -> Result<(), CodegenError> {
197+
Ok(())
198+
}
199+
200+
fn visit_decl_section(&mut self, section: &DeclSection) -> Result<(), CodegenError> {
201+
match section {
202+
DeclSection::Type(type_decl) => {
203+
self.visit_type_declaration(type_decl)?;
204+
Ok(())
205+
},
206+
DeclSection::Variable(var_decl) => {
207+
for decl in var_decl.iter() {
208+
self.visit_var_declaration(decl)?;
209+
}
210+
Ok(())
211+
},
212+
DeclSection::Procedure(proc_decl) => {
213+
self.visit_procedure_declaration(proc_decl)?;
214+
Ok(())
215+
},
216+
}
217+
}
218+
219+
fn visit_statement(&mut self, stmt: &Box<Stmt>) -> Result<(), CodegenError> {
220+
match stmt.statement.as_ref() {
221+
UnlabeledStmt::Assigment { left, right } => {
222+
let _ident = &left.name;
223+
let _value = self.visit_expr(right)?;
224+
Ok(())
225+
},
226+
_ => Ok(())
227+
}
228+
}
229+
230+
fn visit_block(&mut self, block: &Box<Block>) -> Result<(), CodegenError> {
231+
for section in block.decl_sections.iter() {
232+
self.visit_decl_section(section)?;
233+
}
234+
self.visit_statement(&block.body)
235+
}
236+
237+
pub fn visit_program(&mut self, program: &Box<Program>) -> Result<(), CodegenError> {
238+
self.visit_block(&program.block)
239+
}
240+
}

crates/jpc/src/hir/ssa.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use core::ast::ProcedureDeclaration;
2+
use std::rc::Rc;
3+
4+
use super::codegen::Instruction;
5+
6+
pub struct IRBuilder {
7+
8+
}
9+
10+
pub struct BasicBlock {
11+
pub label: String,
12+
pub instructions: Vec<Instruction>,
13+
pub successors: Vec<Rc<BasicBlock>>,
14+
pub predecessors: Vec<Rc<BasicBlock>>,
15+
}
16+
17+
impl BasicBlock {
18+
pub fn new() -> Self {
19+
BasicBlock {
20+
label: String::new(),
21+
instructions: Vec::new(),
22+
successors: Vec::new(),
23+
predecessors: Vec::new(),
24+
}
25+
}
26+
}
27+
28+
pub struct ProcedureIR {
29+
pub name: String,
30+
pub entry_block: Rc<BasicBlock>,
31+
pub blocks: Vec<Rc<BasicBlock>>,
32+
}
33+
34+
impl IRBuilder {
35+
pub fn new() -> Self {
36+
IRBuilder {
37+
38+
}
39+
}
40+
41+
pub fn build(func_decl: ProcedureDeclaration) -> ProcedureIR {
42+
let entry_block = Rc::new(BasicBlock::new());
43+
let blocks = vec![Rc::clone(&entry_block)];
44+
45+
// TODO: generate IR for function body
46+
47+
ProcedureIR {
48+
name: func_decl.head.name.clone(),
49+
entry_block: Rc::clone(&entry_block),
50+
blocks,
51+
}
52+
}
53+
}

crates/jpc/src/ir.rs

Lines changed: 0 additions & 48 deletions
This file was deleted.

crates/jpc/src/main.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
mod riscv;
2-
mod ir;
2+
mod hir;
33

4+
use core::{lexer::Lexer, parser::Parser};
45
use std::{
5-
env,
6-
io::{self, Read},
7-
fs::File,
6+
env, fs::{self, File}, io::{self, Read}
87
};
98

10-
use riscv::codegen::CodeEmmiter;
9+
use hir::codegen::CodeEmmiter;
1110

1211
pub fn read_file(filepath: &str) -> io::Result<String> {
1312
let mut file = File::open(filepath)?;
@@ -25,7 +24,17 @@ fn main() -> io::Result<()> {
2524

2625
let mut gen = CodeEmmiter::new();
2726
let source = read_file(&args[1])?;
28-
let result = gen.codegen(&source).expect("Failed to codegen");
27+
28+
let mb_tokens = Lexer::new(source.chars()).collect::<Vec<_>>();
29+
let tokens = mb_tokens.into_iter().collect::<Result<Vec<_>, _>>()
30+
.expect("Failed to scan");
31+
fs::write("tokens.txt", format!("{:#?}", &tokens)).unwrap();
32+
33+
let mut parser = Parser::new(tokens.into_iter());
34+
let ast = parser.parse().expect("Failed to parse");
35+
fs::write("ast.txt", format!("{:#?}", &ast)).unwrap();
36+
37+
gen.visit_program(&Box::new(ast)).expect("Failed to codegen");
2938

3039
Ok(())
3140
}

0 commit comments

Comments
 (0)