move symboltable into parser and tree, away from triples gen
This commit is contained in:
parent
66d08dadcc
commit
3bb4ba79bc
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag},
|
ast::{FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, Type},
|
||||||
common::NextIf,
|
common::NextIf,
|
||||||
lexer::{Radix, TokenIterator},
|
lexer::{Radix, TokenIterator},
|
||||||
symbol_table::{SymbolKind, SymbolTable},
|
symbol_table::{SymbolKind, SymbolTable},
|
||||||
|
@ -86,7 +86,7 @@ impl Nodes {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Tree {
|
pub struct Tree {
|
||||||
pub nodes: Nodes,
|
pub nodes: Nodes,
|
||||||
st: SymbolTable,
|
pub st: SymbolTable,
|
||||||
pub global_decls: Vec<Node>,
|
pub global_decls: Vec<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,6 +1287,92 @@ impl Tree {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn type_of_node(&self, node: Node) -> crate::ast::Type {
|
||||||
|
match self.nodes.get_node(node) {
|
||||||
|
Tag::FunctionDecl { proto, .. } => self.type_of_node(*proto),
|
||||||
|
Tag::FunctionProto {
|
||||||
|
parameters,
|
||||||
|
return_type,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let return_type = self.type_of_node(*return_type);
|
||||||
|
let parameter_types = parameters
|
||||||
|
.map(|p| match self.nodes.get_node(p) {
|
||||||
|
Tag::ParameterList { parameters } => parameters
|
||||||
|
.iter()
|
||||||
|
.map(|p| self.type_of_node(*p))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
_ => panic!("parameters is not a parameterlist!"),
|
||||||
|
})
|
||||||
|
.unwrap_or(Vec::new());
|
||||||
|
|
||||||
|
crate::ast::Type::Fn {
|
||||||
|
parameter_types,
|
||||||
|
return_type: Box::new(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::Parameter { ty, .. } => self.type_of_node(*ty),
|
||||||
|
Tag::Pointer { pointee } => Type::Pointer {
|
||||||
|
constness: false,
|
||||||
|
pointee: Box::new(self.type_of_node(*pointee)),
|
||||||
|
},
|
||||||
|
Tag::IntegralType(t) => Type::Integer(*t),
|
||||||
|
Tag::PrimitiveType(t) => match t {
|
||||||
|
PrimitiveType::FloatingType(t) => Type::Floating(*t),
|
||||||
|
PrimitiveType::IntegralType(t) => self.type_of_node(*t),
|
||||||
|
PrimitiveType::Bool => Type::bool(),
|
||||||
|
PrimitiveType::Void => Type::void(),
|
||||||
|
},
|
||||||
|
Tag::IntegralConstant { ty, .. } => Type::Integer(*ty),
|
||||||
|
Tag::FloatingConstant { ty, .. } => Type::Floating(*ty),
|
||||||
|
Tag::Block { trailing_expr, .. } => trailing_expr
|
||||||
|
.map(|n| self.type_of_node(n))
|
||||||
|
.unwrap_or(Type::void()),
|
||||||
|
Tag::VarDecl {
|
||||||
|
explicit_type,
|
||||||
|
assignment, // this is a Tag::Assign
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let lhs = explicit_type.map(|n| self.type_of_node(n));
|
||||||
|
let rhs = assignment.map(|n| match self.nodes.get_node(n) {
|
||||||
|
Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
|
||||||
|
_ => unreachable!(),
|
||||||
|
});
|
||||||
|
if lhs.as_ref().zip(rhs.as_ref()).map(|(l, r)| l != r) == Some(true) {
|
||||||
|
eprintln!("vardecl: incompatible types {lhs:?} and {rhs:?}.");
|
||||||
|
}
|
||||||
|
lhs.or(rhs)
|
||||||
|
.expect("Type could not be automatically deduced.")
|
||||||
|
}
|
||||||
|
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
||||||
|
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
|
||||||
|
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
||||||
|
Tag::Not { lhs } => self.type_of_node(*lhs),
|
||||||
|
Tag::Negate { lhs } => self.type_of_node(*lhs),
|
||||||
|
Tag::Or { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::And { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::BitOr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::BitAnd { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::BitXOr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Add { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Sub { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Mul { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Rem { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Div { lhs, .. } => self.type_of_node(*lhs),
|
||||||
|
Tag::Eq { .. } => Type::bool(),
|
||||||
|
Tag::NEq { .. } => Type::bool(),
|
||||||
|
Tag::Lt { .. } => Type::bool(),
|
||||||
|
Tag::Gt { .. } => Type::bool(),
|
||||||
|
Tag::Le { .. } => Type::bool(),
|
||||||
|
Tag::Ge { .. } => Type::bool(),
|
||||||
|
Tag::DeclRef(decl) => self.type_of_node(*decl),
|
||||||
|
_ => Type::void(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRECEDENCE_MAP: std::sync::LazyLock<HashMap<Token, u32>> = std::sync::LazyLock::new(|| {
|
static PRECEDENCE_MAP: std::sync::LazyLock<HashMap<Token, u32>> = std::sync::LazyLock::new(|| {
|
||||||
|
|
|
@ -30,15 +30,19 @@ pub struct SymbolTable {
|
||||||
// parameters, so any `x` may be redefined.
|
// parameters, so any `x` may be redefined.
|
||||||
ordered_identifiers: Vec<SymbolRecord>,
|
ordered_identifiers: Vec<SymbolRecord>,
|
||||||
orderless_identifiers: HashMap<String, SymbolRecord>,
|
orderless_identifiers: HashMap<String, SymbolRecord>,
|
||||||
parent: Option<Box<SymbolTable>>,
|
|
||||||
children: BTreeMap<Option<AstNode>, SymbolTable>,
|
children: BTreeMap<Option<AstNode>, SymbolTable>,
|
||||||
scope: Option<AstNode>,
|
scope: Option<AstNode>,
|
||||||
|
parent: Option<Box<SymbolTable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolTable {
|
impl SymbolTable {
|
||||||
pub fn new() -> SymbolTable {
|
pub fn new() -> SymbolTable {
|
||||||
Self {
|
Self {
|
||||||
..Default::default()
|
ordered_identifiers: Vec::new(),
|
||||||
|
orderless_identifiers: HashMap::new(),
|
||||||
|
children: BTreeMap::new(),
|
||||||
|
scope: None,
|
||||||
|
parent: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
263
src/triples.rs
263
src/triples.rs
|
@ -3,209 +3,11 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{FloatingType, IntegralType, Node as AstNode, PrimitiveType, Tag, Type},
|
ast::{FloatingType, IntegralType, Node as AstNode, Tag, Type},
|
||||||
parser::Tree,
|
parser::Tree,
|
||||||
writeln_indented,
|
writeln_indented,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SymbolRecord {
|
|
||||||
name: String,
|
|
||||||
decl: AstNode,
|
|
||||||
ty: Type,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SymbolTable<'a> {
|
|
||||||
tree: &'a Tree,
|
|
||||||
identifiers: Vec<SymbolRecord>,
|
|
||||||
parent: Option<Box<SymbolTable<'a>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SymbolTable<'a> {
|
|
||||||
pub fn root(tree: &'a Tree) -> Self {
|
|
||||||
Self {
|
|
||||||
tree,
|
|
||||||
identifiers: Vec::new(),
|
|
||||||
parent: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_symbol_with_name(&mut self, ast_node: AstNode, name: String) {
|
|
||||||
let ty = self.type_of_node(ast_node);
|
|
||||||
self.identifiers.push(SymbolRecord {
|
|
||||||
name,
|
|
||||||
decl: ast_node,
|
|
||||||
ty,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_return_symbol(&mut self, ast_node: AstNode) {
|
|
||||||
self.insert_symbol_with_name(ast_node, "return".to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_symbol(&mut self, ast_node: AstNode) {
|
|
||||||
let name = match self.tree.nodes.get_node(ast_node) {
|
|
||||||
Tag::VarDecl { name, .. } => self.tree.nodes.get_ident_str(*name).unwrap().to_string(),
|
|
||||||
Tag::Parameter { name, .. } => {
|
|
||||||
self.tree.nodes.get_ident_str(*name).unwrap().to_string()
|
|
||||||
}
|
|
||||||
Tag::FunctionProto { name, .. } => {
|
|
||||||
self.tree.nodes.get_ident_str(*name).unwrap().to_string()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("ast_node wasn't any kind of decl!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.insert_symbol_with_name(ast_node, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_symbol_name(&self, name: &str) -> Option<&SymbolRecord> {
|
|
||||||
self.identifiers
|
|
||||||
.iter()
|
|
||||||
.find(|r| r.name.as_str() == name)
|
|
||||||
.or_else(|| {
|
|
||||||
self.parent
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|parent| parent.find_symbol_name(name))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_symbol(&self, ident_node: AstNode) -> Option<&SymbolRecord> {
|
|
||||||
self.identifiers
|
|
||||||
.iter()
|
|
||||||
.find(|r| Some(r.name.as_str()) == self.tree.nodes.get_ident_str(ident_node))
|
|
||||||
.or_else(|| {
|
|
||||||
self.parent
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|parent| parent.find_symbol(ident_node))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn into_child_in_place(&mut self) {
|
|
||||||
let mut parent = Self {
|
|
||||||
parent: None,
|
|
||||||
tree: self.tree,
|
|
||||||
identifiers: Vec::new(),
|
|
||||||
};
|
|
||||||
core::mem::swap(self, &mut parent);
|
|
||||||
self.parent = Some(Box::new(parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_child(self) -> SymbolTable<'a> {
|
|
||||||
Self {
|
|
||||||
identifiers: Vec::new(),
|
|
||||||
tree: self.tree,
|
|
||||||
parent: Some(Box::new(self)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parent_mut(&mut self) -> Option<&mut SymbolTable<'a>> {
|
|
||||||
self.parent.as_mut().map(|parent| parent.as_mut())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_parent_in_place(&mut self) -> Option<SymbolTable<'a>> {
|
|
||||||
if let Some(child) = self.parent.take() {
|
|
||||||
let mut child = Box::into_inner(child);
|
|
||||||
core::mem::swap(self, &mut child);
|
|
||||||
Some(child)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_parent(self) -> Option<SymbolTable<'a>> {
|
|
||||||
self.parent.map(|parent| Box::into_inner(parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_of_node(&self, node: AstNode) -> crate::ast::Type {
|
|
||||||
match self.tree.nodes.get_node(node) {
|
|
||||||
Tag::Ident { name } => self
|
|
||||||
.find_symbol(node)
|
|
||||||
.map(|r| r.ty.clone())
|
|
||||||
.expect(&format!("identifier '{name}' not found in SymbolTable!")),
|
|
||||||
Tag::FunctionDecl { proto, .. } => self.type_of_node(*proto),
|
|
||||||
Tag::FunctionProto {
|
|
||||||
parameters,
|
|
||||||
return_type,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let return_type = self.type_of_node(*return_type);
|
|
||||||
let parameter_types = parameters
|
|
||||||
.map(|p| match self.tree.nodes.get_node(p) {
|
|
||||||
Tag::ParameterList { parameters } => parameters
|
|
||||||
.iter()
|
|
||||||
.map(|p| self.type_of_node(*p))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
_ => panic!("parameters is not a parameterlist!"),
|
|
||||||
})
|
|
||||||
.unwrap_or(Vec::new());
|
|
||||||
|
|
||||||
crate::ast::Type::Fn {
|
|
||||||
parameter_types,
|
|
||||||
return_type: Box::new(return_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::Parameter { ty, .. } => self.type_of_node(*ty),
|
|
||||||
Tag::Pointer { pointee } => Type::Pointer {
|
|
||||||
constness: false,
|
|
||||||
pointee: Box::new(self.type_of_node(*pointee)),
|
|
||||||
},
|
|
||||||
Tag::IntegralType(t) => Type::Integer(*t),
|
|
||||||
Tag::PrimitiveType(t) => match t {
|
|
||||||
PrimitiveType::FloatingType(t) => Type::Floating(*t),
|
|
||||||
PrimitiveType::IntegralType(t) => self.type_of_node(*t),
|
|
||||||
PrimitiveType::Bool => Type::bool(),
|
|
||||||
PrimitiveType::Void => Type::void(),
|
|
||||||
},
|
|
||||||
Tag::IntegralConstant { ty, .. } => Type::Integer(*ty),
|
|
||||||
Tag::FloatingConstant { ty, .. } => Type::Floating(*ty),
|
|
||||||
Tag::Block { trailing_expr, .. } => trailing_expr
|
|
||||||
.map(|n| self.type_of_node(n))
|
|
||||||
.unwrap_or(Type::void()),
|
|
||||||
Tag::VarDecl {
|
|
||||||
explicit_type,
|
|
||||||
assignment, // this is a Tag::Assign
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let lhs = explicit_type.map(|n| self.type_of_node(n));
|
|
||||||
let rhs = assignment.map(|n| match self.tree.nodes.get_node(n) {
|
|
||||||
Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
|
|
||||||
_ => unreachable!(),
|
|
||||||
});
|
|
||||||
if lhs.as_ref().zip(rhs.as_ref()).map(|(l, r)| l != r) == Some(true) {
|
|
||||||
eprintln!("vardecl: incompatible types {lhs:?} and {rhs:?}.");
|
|
||||||
}
|
|
||||||
lhs.or(rhs)
|
|
||||||
.expect("Type could not be automatically deduced.")
|
|
||||||
}
|
|
||||||
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
|
||||||
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
|
|
||||||
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
|
||||||
Tag::Not { lhs } => self.type_of_node(*lhs),
|
|
||||||
Tag::Negate { lhs } => self.type_of_node(*lhs),
|
|
||||||
Tag::Or { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::And { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::BitOr { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::BitAnd { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::BitXOr { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Add { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Sub { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Mul { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Rem { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Div { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Eq { .. } => Type::bool(),
|
|
||||||
Tag::NEq { .. } => Type::bool(),
|
|
||||||
Tag::Lt { .. } => Type::bool(),
|
|
||||||
Tag::Gt { .. } => Type::bool(),
|
|
||||||
Tag::Le { .. } => Type::bool(),
|
|
||||||
Tag::Ge { .. } => Type::bool(),
|
|
||||||
_ => Type::void(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Node = u32;
|
type Node = u32;
|
||||||
|
|
||||||
enum Inst {
|
enum Inst {
|
||||||
|
@ -249,47 +51,51 @@ impl core::fmt::Display for Value {
|
||||||
|
|
||||||
struct IRBuilder<'tree, 'ir> {
|
struct IRBuilder<'tree, 'ir> {
|
||||||
ir: &'ir mut IR,
|
ir: &'ir mut IR,
|
||||||
st: SymbolTable<'tree>,
|
tree: &'tree mut Tree,
|
||||||
|
type_map: HashMap<AstNode, Type>,
|
||||||
lookup: HashMap<AstNode, Node>,
|
lookup: HashMap<AstNode, Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
fn new(ir: &'ir mut IR, st: SymbolTable<'tree>) -> Self {
|
fn new(ir: &'ir mut IR, tree: &'tree mut Tree) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ir,
|
ir,
|
||||||
st,
|
tree,
|
||||||
|
type_map: HashMap::new(),
|
||||||
lookup: HashMap::new(),
|
lookup: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit(&mut self, node: AstNode) -> Node {
|
fn visit(&mut self, node: AstNode) -> Node {
|
||||||
match &self.st.tree.nodes[node] {
|
match &self.tree.nodes[node].clone() {
|
||||||
Tag::FunctionDecl { proto, body } => {
|
Tag::FunctionDecl { proto, body } => {
|
||||||
self.visit(*proto);
|
self.visit(*proto);
|
||||||
self.st.into_child_in_place();
|
self.tree.st.into_child(node);
|
||||||
let value = self.visit(*body);
|
let value = self.visit(*body);
|
||||||
// TODO: return value of body expression
|
// TODO: return value of body expression
|
||||||
let node = if value != !0 {
|
let node = if value != !0 {
|
||||||
self.type_check(self.st.find_symbol_name("return").unwrap().decl, *body);
|
let return_type = {
|
||||||
|
match self.tree.nodes.get_node(*proto) {
|
||||||
|
Tag::FunctionProto { return_type, .. } => *return_type,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.type_check(return_type, *body);
|
||||||
self.ir.push(Inst::ReturnValue { lhs: value })
|
self.ir.push(Inst::ReturnValue { lhs: value })
|
||||||
} else {
|
} else {
|
||||||
!0
|
!0
|
||||||
};
|
};
|
||||||
|
|
||||||
self.st.into_parent_in_place();
|
self.tree.st.into_parent();
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
Tag::FunctionProto {
|
Tag::FunctionProto {
|
||||||
parameters,
|
parameters, name, ..
|
||||||
return_type,
|
|
||||||
name,
|
|
||||||
} => {
|
} => {
|
||||||
self.st.insert_symbol(node);
|
|
||||||
self.st.insert_return_symbol(*return_type);
|
|
||||||
parameters.map(|p| self.visit(p));
|
parameters.map(|p| self.visit(p));
|
||||||
|
|
||||||
let label = self.ir.push(Inst::Label(
|
let label = self.ir.push(Inst::Label(
|
||||||
self.st.tree.nodes.get_ident_str(*name).unwrap().to_string(),
|
self.tree.nodes.get_ident_str(*name).unwrap().to_string(),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.lookup.insert(node, label);
|
self.lookup.insert(node, label);
|
||||||
|
@ -303,7 +109,6 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
!0
|
!0
|
||||||
}
|
}
|
||||||
Tag::Parameter { .. } => {
|
Tag::Parameter { .. } => {
|
||||||
self.st.insert_symbol(node);
|
|
||||||
let param = self.ir.push(Inst::Parameter);
|
let param = self.ir.push(Inst::Parameter);
|
||||||
|
|
||||||
self.lookup.insert(node, param);
|
self.lookup.insert(node, param);
|
||||||
|
@ -324,12 +129,11 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag::VarDecl { .. } => {
|
Tag::VarDecl { .. } => {
|
||||||
let ty = self.st.type_of_node(node);
|
let ty = self.tree.type_of_node(node);
|
||||||
let alloca = self.ir.push(Inst::Alloc {
|
let alloca = self.ir.push(Inst::Alloc {
|
||||||
size: ty.size_of(),
|
size: ty.size_of(),
|
||||||
align: ty.align_of(),
|
align: ty.align_of(),
|
||||||
});
|
});
|
||||||
self.st.insert_symbol(node);
|
|
||||||
self.lookup.insert(node, alloca);
|
self.lookup.insert(node, alloca);
|
||||||
alloca
|
alloca
|
||||||
}
|
}
|
||||||
|
@ -445,7 +249,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
self.ir.push(Inst::BitXOr { lhs, rhs })
|
self.ir.push(Inst::BitXOr { lhs, rhs })
|
||||||
}
|
}
|
||||||
Tag::Negate { lhs } => {
|
Tag::Negate { lhs } => {
|
||||||
let ty = self.st.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(*lhs);
|
||||||
if !ty.can_negate() {
|
if !ty.can_negate() {
|
||||||
eprintln!("negation is not available for type {ty:?}");
|
eprintln!("negation is not available for type {ty:?}");
|
||||||
}
|
}
|
||||||
|
@ -453,29 +257,21 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
self.ir.push(Inst::Negate { lhs })
|
self.ir.push(Inst::Negate { lhs })
|
||||||
}
|
}
|
||||||
Tag::Ident { name } => {
|
Tag::DeclRef(decl) => *self.lookup.get(decl).expect("declref not in lookup map"),
|
||||||
let decl = self
|
|
||||||
.st
|
|
||||||
.find_symbol(node)
|
|
||||||
.expect(&format!("symbol '{name}' not found in SymbolMap!"))
|
|
||||||
.decl;
|
|
||||||
|
|
||||||
*self.lookup.get(&decl).unwrap()
|
|
||||||
}
|
|
||||||
Tag::Ref { lhs } => {
|
Tag::Ref { lhs } => {
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
self.ir.push(Inst::AddressOf(lhs))
|
self.ir.push(Inst::AddressOf(lhs))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
dbg!(&self.st.tree.nodes[node]);
|
dbg!(&self.tree.nodes[node]);
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_check(&self, lhs: AstNode, rhs: AstNode) -> Type {
|
fn type_check(&self, lhs: AstNode, rhs: AstNode) -> Type {
|
||||||
let t_lhs = self.st.type_of_node(lhs);
|
let t_lhs = self.tree.type_of_node(lhs);
|
||||||
let t_rhs = self.st.type_of_node(rhs);
|
let t_rhs = self.tree.type_of_node(rhs);
|
||||||
if t_lhs != t_rhs {
|
if t_lhs != t_rhs {
|
||||||
eprintln!("incompatible types {t_lhs:?} and {t_rhs:?}!");
|
eprintln!("incompatible types {t_lhs:?} and {t_rhs:?}!");
|
||||||
}
|
}
|
||||||
|
@ -498,9 +294,8 @@ impl IR {
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&mut self, tree: &Tree, ast_node: crate::ast::Node) {
|
pub fn build(&mut self, tree: &mut Tree, ast_node: crate::ast::Node) {
|
||||||
let st = SymbolTable::root(tree);
|
let mut builder = IRBuilder::new(self, tree);
|
||||||
let mut builder = IRBuilder::new(self, st);
|
|
||||||
|
|
||||||
builder.visit(ast_node);
|
builder.visit(ast_node);
|
||||||
}
|
}
|
||||||
|
@ -590,8 +385,9 @@ mod tests {
|
||||||
fn main() -> u32 {
|
fn main() -> u32 {
|
||||||
let a: u32 = 0 + 3;
|
let a: u32 = 0 + 3;
|
||||||
let ptr_a = &a;
|
let ptr_a = &a;
|
||||||
return *ptr_a * 2;
|
return *ptr_a * global;
|
||||||
}
|
}
|
||||||
|
let global: u32 = 42;
|
||||||
";
|
";
|
||||||
let tokens = Tokenizer::new(src.as_bytes()).unwrap();
|
let tokens = Tokenizer::new(src.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
@ -603,7 +399,8 @@ return *ptr_a * 2;
|
||||||
println!("{buf}");
|
println!("{buf}");
|
||||||
|
|
||||||
let mut ir = IR::new();
|
let mut ir = IR::new();
|
||||||
ir.build(&tree, *tree.global_decls.first().unwrap());
|
let decl = *tree.global_decls.first().unwrap();
|
||||||
|
ir.build(&mut tree, decl);
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
ir.render(&mut buf).unwrap();
|
ir.render(&mut buf).unwrap();
|
||||||
println!("{buf}");
|
println!("{buf}");
|
||||||
|
|
Loading…
Reference in a new issue