integrated SymbolTable into AST/Parser

This commit is contained in:
Janis 2024-08-13 18:49:22 +02:00
parent c3157b1355
commit fe25d226d1
5 changed files with 515 additions and 170 deletions

View file

@ -2,7 +2,7 @@ use std::num::NonZero;
pub type Node = NonZero<u32>; pub type Node = NonZero<u32>;
#[derive(Debug)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Tag { pub enum Tag {
Undefined, Undefined,
Root, Root,
@ -69,6 +69,7 @@ pub enum Tag {
explicit_type: Option<Node>, explicit_type: Option<Node>,
assignment: Option<Node>, assignment: Option<Node>,
}, },
DeclRef(Node),
CallExpr { CallExpr {
/// Ident | Expr /// Ident | Expr
lhs: Node, lhs: Node,
@ -180,7 +181,7 @@ pub enum Tag {
}, },
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LetOrVar { pub enum LetOrVar {
Let, Let,
Var, Var,
@ -339,7 +340,7 @@ impl Type {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrimitiveType { pub enum PrimitiveType {
FloatingType(FloatingType), FloatingType(FloatingType),
IntegralType(Node), IntegralType(Node),

View file

@ -1,10 +1,12 @@
#![feature(extract_if, iter_advance_by, box_into_inner)] #![feature(extract_if, iter_advance_by, box_into_inner, hash_extract_if)]
#![allow(dead_code, unused_macros)] #![allow(dead_code, unused_macros)]
pub mod ast; pub mod ast;
pub mod codegen;
pub mod common; pub mod common;
pub mod lexer; pub mod lexer;
pub mod parser; pub mod parser;
pub mod symbol_table;
pub mod tokens; pub mod tokens;
pub mod triples; pub mod triples;

View file

@ -6,6 +6,7 @@ use crate::{
ast::{FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, Type}, ast::{FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, Type},
common::NextIf, common::NextIf,
lexer::{Radix, TokenIterator}, lexer::{Radix, TokenIterator},
symbol_table::{SymbolKind, SymbolTable},
tokens::Token, tokens::Token,
}; };
@ -27,12 +28,65 @@ pub enum Error {
pub type Result<T> = core::result::Result<T, Error>; pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug)]
pub struct Nodes {
inner: Vec<Tag>,
}
impl core::ops::Index<Node> for Nodes {
type Output = Tag;
fn index(&self, index: Node) -> &Self::Output {
&self.inner[index.get() as usize]
}
}
impl Nodes {
fn new() -> Nodes {
Self {
inner: vec![Tag::Root],
}
}
pub fn get_ident_str(&self, node: Node) -> Option<&str> {
match &self.inner[node.get() as usize] {
Tag::Ident { name } => Some(name.as_str()),
_ => None,
}
}
fn len(&self) -> u32 {
self.inner.len() as u32
}
fn set_node(&mut self, node: Node, tag: Tag) {
*self.get_node_mut(node) = tag;
}
fn get_node_mut(&mut self, node: Node) -> &mut Tag {
self.inner.get_mut(node.get() as usize).unwrap()
}
pub fn get_node(&self, node: Node) -> &Tag {
self.inner.get(node.get() as usize).unwrap()
}
fn push_tag(&mut self, tag: Tag) -> Node {
let node = Node::new(self.len()).unwrap();
self.inner.push(tag);
node
}
fn reserve_node(&mut self) -> Node {
self.push_tag(Tag::Undefined)
}
}
// TODO: add a string-table which stores strings and maybe other bytes and // TODO: add a string-table which stores strings and maybe other bytes and
// returns a range for identifiers, constants, etc. where bytes are stored // returns a range for identifiers, constants, etc. where bytes are stored
// flatly, and next to each other. // flatly, and next to each other.
#[derive(Debug)] #[derive(Debug)]
pub struct Tree { pub struct Tree {
nodes: Vec<Tag>, pub nodes: Nodes,
st: SymbolTable,
pub global_decls: Vec<Node>, pub global_decls: Vec<Node>,
} }
@ -69,36 +123,12 @@ macro_rules! writeln_indented {
impl Tree { impl Tree {
pub fn new() -> Tree { pub fn new() -> Tree {
Self { Self {
nodes: vec![Tag::Root], nodes: Nodes::new(),
st: SymbolTable::new(),
global_decls: Vec::new(), global_decls: Vec::new(),
} }
} }
fn reserve_node(&mut self) -> Node {
let node = Node::new(self.nodes.len() as u32).unwrap();
self.nodes.push(Tag::Undefined);
node
}
fn set_node(&mut self, node: Node, tag: Tag) {
*self.get_node_mut(node) = tag;
}
fn get_node_mut(&mut self, node: Node) -> &mut Tag {
self.nodes.get_mut(node.get() as usize).unwrap()
}
pub fn get_node(&self, node: Node) -> &Tag {
self.nodes.get(node.get() as usize).unwrap()
}
fn push_tag(&mut self, tag: Tag) -> Node {
let node = Node::new(self.nodes.len() as u32).unwrap();
self.nodes.push(tag);
node
}
fn is_integral_type(lexeme: &str) -> Option<()> { fn is_integral_type(lexeme: &str) -> Option<()> {
let mut iter = lexeme.chars(); let mut iter = lexeme.chars();
iter.next_if(|&c| c == 'u' || c == 'i')?; iter.next_if(|&c| c == 'u' || c == 'i')?;
@ -224,7 +254,7 @@ impl Tree {
fn parse_ident(&mut self, tokens: &mut TokenIterator) -> Result<Node> { fn parse_ident(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
let name = tokens.expect_token(Token::Ident)?.lexeme().to_owned(); let name = tokens.expect_token(Token::Ident)?.lexeme().to_owned();
Ok(self.push_tag(Tag::Ident { name })) Ok(self.nodes.push_tag(Tag::Ident { name }))
} }
pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
@ -239,7 +269,7 @@ impl Tree {
} }
}; };
Ok(self.push_tag(Tag::PrimitiveType(prim))) Ok(self.nodes.push_tag(Tag::PrimitiveType(prim)))
} }
pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
@ -247,7 +277,7 @@ impl Tree {
let _constness = tokens.eat_token(Token::Const); let _constness = tokens.eat_token(Token::Const);
let typename = self.parse_typename(tokens)?; let typename = self.parse_typename(tokens)?;
Ok(self.push_tag(Tag::Pointer { pointee: typename })) Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename }))
} }
pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
@ -256,8 +286,8 @@ impl Tree {
Token::Ident => { Token::Ident => {
let token = tokens.next().unwrap(); let token = tokens.next().unwrap();
match Self::try_parse_integral_type(token.lexeme())? { match Self::try_parse_integral_type(token.lexeme())? {
Some(int) => Ok(self.push_tag(Tag::IntegralType(int))), Some(int) => Ok(self.nodes.push_tag(Tag::IntegralType(int))),
None => Ok(self.push_tag(Tag::Ident { None => Ok(self.nodes.push_tag(Tag::Ident {
name: token.lexeme().to_owned(), name: token.lexeme().to_owned(),
})), })),
} }
@ -266,7 +296,7 @@ impl Tree {
} }
} }
pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator, global: bool) -> Result<Node> {
let let_or_var = match tokens let let_or_var = match tokens
.eat_token(Token::Let) .eat_token(Token::Let)
.or_else(|| tokens.eat_token(Token::Var)) .or_else(|| tokens.eat_token(Token::Var))
@ -286,11 +316,26 @@ impl Tree {
None None
}; };
let node = self.reserve_node(); let name_str = self.nodes.get_ident_str(name).unwrap().to_owned();
let node = if global {
let node = match self.st.root_mut().find_orderless_symbol(&name_str) {
Some(r) => r.node(),
None => self
.st
.root_mut()
.insert_orderless_symbol(&name_str, self.nodes.reserve_node())
.node(),
};
node
} else {
let node = self.nodes.reserve_node();
self.st.insert_symbol(&name_str, node, SymbolKind::Var);
node
};
let assignment = if tokens.eat_token(Token::Equal).is_some() { let assignment = if tokens.eat_token(Token::Equal).is_some() {
let expr = self.parse_expr(tokens)?; let expr = self.parse_expr(tokens)?;
Some(self.push_tag(Tag::Assign { Some(self.nodes.push_tag(Tag::Assign {
lhs: node, lhs: node,
rhs: expr, rhs: expr,
})) }))
@ -298,7 +343,7 @@ impl Tree {
None None
}; };
self.set_node( self.nodes.set_node(
node, node,
Tag::VarDecl { Tag::VarDecl {
let_or_var, let_or_var,
@ -313,7 +358,7 @@ impl Tree {
} }
pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
let node = self.parse_var_decl(tokens)?; let node = self.parse_var_decl(tokens, true)?;
tokens.expect_token(Token::Semi)?; tokens.expect_token(Token::Semi)?;
Ok(node) Ok(node)
@ -326,7 +371,15 @@ impl Tree {
tokens.expect_token(Token::Colon)?; tokens.expect_token(Token::Colon)?;
let ty = self.parse_typename(tokens)?; let ty = self.parse_typename(tokens)?;
Ok(self.push_tag(Tag::Parameter { name, ty })) let param = self.nodes.reserve_node();
self.st.insert_symbol(
self.nodes.get_ident_str(name).unwrap(),
param,
SymbolKind::Var,
);
self.nodes.set_node(param, Tag::Parameter { name, ty });
Ok(param)
} }
/// PARAMETER_LIST <- /// PARAMETER_LIST <-
@ -349,7 +402,7 @@ impl Tree {
_ = tokens.next(); _ = tokens.next();
} }
Ok(self.push_tag(Tag::ParameterList { parameters })) Ok(self.nodes.push_tag(Tag::ParameterList { parameters }))
} }
/// FUNCTION_PROTO <- /// FUNCTION_PROTO <-
@ -357,7 +410,7 @@ impl Tree {
/// fn IDENTIFIER () -> TYPENAME /// fn IDENTIFIER () -> TYPENAME
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) /// fn IDENTIFIER ( PARAMETER_LIST ,? )
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME /// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME
pub fn parse_fn_proto(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_fn_proto(&mut self, tokens: &mut TokenIterator) -> Result<(Node, Node)> {
tokens.expect_token(Token::Fn)?; tokens.expect_token(Token::Fn)?;
let name = self.parse_ident(tokens)?; let name = self.parse_ident(tokens)?;
tokens.expect_token(Token::OpenParens)?; tokens.expect_token(Token::OpenParens)?;
@ -374,38 +427,71 @@ impl Tree {
let return_type = if tokens.eat_token(Token::MinusGreater).is_some() { let return_type = if tokens.eat_token(Token::MinusGreater).is_some() {
self.parse_typename(tokens)? self.parse_typename(tokens)?
} else { } else {
self.push_tag(Tag::PrimitiveType(PrimitiveType::Void)) self.nodes.push_tag(Tag::PrimitiveType(PrimitiveType::Void))
}; };
Ok(self.push_tag(Tag::FunctionProto { let proto = self.nodes.push_tag(Tag::FunctionProto {
name, name,
parameters, parameters,
return_type, return_type,
})) });
Ok((proto, name))
} }
/// FUNCTION_DECL <- /// FUNCTION_DECL <-
/// FUNCTION_PROTO BLOCK /// FUNCTION_PROTO BLOCK
pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
let proto = self.parse_fn_proto(tokens)?; let (proto, name) = self.parse_fn_proto(tokens)?;
let body = self.parse_block(tokens)?; let decl = match self
.st
.find_orderless_symbol(self.nodes.get_ident_str(name).unwrap())
{
Some(record) => record.node(),
None => {
let decl = self.nodes.reserve_node();
self.st
.insert_orderless_symbol(self.nodes.get_ident_str(name).unwrap(), decl);
decl
}
};
Ok(self.push_tag(Tag::FunctionDecl { proto, body })) let block = self.nodes.reserve_node();
self.st.into_child(block);
let body = self.parse_block(tokens, Some(block))?;
let unresolved = self
.st
.extract_orderless_if(|_, v| self.nodes.get_node(v.node()) == &Tag::Undefined)
.collect::<Vec<_>>();
self.st.into_parent();
self.st.extend_orderless(unresolved);
self.nodes.set_node(decl, Tag::FunctionDecl { proto, body });
Ok(decl)
} }
/// BLOCK <- /// BLOCK <-
/// { STATEMENT* EXPRESSION? } /// { STATEMENT* EXPRESSION? }
pub fn parse_block(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_block(
&mut self,
tokens: &mut TokenIterator,
reserved_node: Option<Node>,
) -> Result<Node> {
let block = reserved_node.unwrap_or_else(|| self.nodes.reserve_node());
let mut stmts = Vec::new(); let mut stmts = Vec::new();
_ = tokens.expect_token(Token::OpenBrace)?; _ = tokens.expect_token(Token::OpenBrace)?;
let node = loop { loop {
if tokens.is_next_token(Token::CloseBrace) { if tokens.is_next_token(Token::CloseBrace) {
break self.push_tag(Tag::Block { break self.nodes.set_node(
statements: stmts, block,
trailing_expr: None, Tag::Block {
}); statements: stmts,
trailing_expr: None,
},
);
} }
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
@ -413,7 +499,7 @@ impl Tree {
stmts.push(self.try_parse_return_stmt(tokens)?.unwrap()); stmts.push(self.try_parse_return_stmt(tokens)?.unwrap());
} }
Token::Var | Token::Let => { Token::Var | Token::Let => {
let node = self.parse_var_decl(tokens)?; let node = self.parse_var_decl(tokens, false)?;
tokens.expect_token(Token::Semi)?; tokens.expect_token(Token::Semi)?;
stmts.push(node); stmts.push(node);
@ -422,10 +508,13 @@ impl Tree {
let node = self.parse_expr(tokens)?; let node = self.parse_expr(tokens)?;
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
Token::CloseBrace => { Token::CloseBrace => {
break self.push_tag(Tag::Block { break self.nodes.set_node(
statements: stmts, block,
trailing_expr: Some(node), Tag::Block {
}); statements: stmts,
trailing_expr: Some(node),
},
);
} }
Token::Semi => { Token::Semi => {
_ = tokens.next(); _ = tokens.next();
@ -437,11 +526,11 @@ impl Tree {
} }
} }
} }
}; }
tokens.expect_token(Token::CloseBrace)?; tokens.expect_token(Token::CloseBrace)?;
Ok(node) Ok(block)
} }
/// ASSIGNMENT_EXPR <- /// ASSIGNMENT_EXPR <-
@ -471,22 +560,22 @@ impl Tree {
let rhs = self.parse_expr(tokens)?; let rhs = self.parse_expr(tokens)?;
let rhs = match op.token() { let rhs = match op.token() {
Token::PlusEqual => self.push_tag(Tag::Add { lhs, rhs }), Token::PlusEqual => self.nodes.push_tag(Tag::Add { lhs, rhs }),
Token::MinusEqual => self.push_tag(Tag::Sub { lhs, rhs }), Token::MinusEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
Token::StarEqual => self.push_tag(Tag::Mul { lhs, rhs }), Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }),
Token::SlashEqual => self.push_tag(Tag::Sub { lhs, rhs }), Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
Token::PercentEqual => self.push_tag(Tag::Rem { lhs, rhs }), Token::PercentEqual => self.nodes.push_tag(Tag::Rem { lhs, rhs }),
Token::PipeEqual => self.push_tag(Tag::BitOr { lhs, rhs }), Token::PipeEqual => self.nodes.push_tag(Tag::BitOr { lhs, rhs }),
Token::CaretEqual => self.push_tag(Tag::BitXOr { lhs, rhs }), Token::CaretEqual => self.nodes.push_tag(Tag::BitXOr { lhs, rhs }),
Token::AmpersandEqual => self.push_tag(Tag::BitAnd { lhs, rhs }), Token::AmpersandEqual => self.nodes.push_tag(Tag::BitAnd { lhs, rhs }),
Token::LessLessEqual => self.push_tag(Tag::Shl { lhs, rhs }), Token::LessLessEqual => self.nodes.push_tag(Tag::Shl { lhs, rhs }),
Token::GreaterGreaterEqual => self.push_tag(Tag::Shr { lhs, rhs }), Token::GreaterGreaterEqual => self.nodes.push_tag(Tag::Shr { lhs, rhs }),
Token::Equal => rhs, Token::Equal => rhs,
_ => { _ => {
unreachable!() unreachable!()
} }
}; };
Ok(Some(self.push_tag(Tag::Assign { lhs, rhs }))) Ok(Some(self.nodes.push_tag(Tag::Assign { lhs, rhs })))
} else { } else {
Ok(None) Ok(None)
} }
@ -505,7 +594,7 @@ impl Tree {
}; };
tokens.expect_token(Token::Semi)?; tokens.expect_token(Token::Semi)?;
Ok(Some(self.push_tag(Tag::ReturnStmt { expr }))) Ok(Some(self.nodes.push_tag(Tag::ReturnStmt { expr })))
} else { } else {
Ok(None) Ok(None)
} }
@ -519,7 +608,7 @@ impl Tree {
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()), Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
Token::Var | Token::Let => { Token::Var | Token::Let => {
let node = self.parse_var_decl(tokens)?; let node = self.parse_var_decl(tokens, false)?;
tokens.expect_token(Token::Semi)?; tokens.expect_token(Token::Semi)?;
Ok(node) Ok(node)
@ -599,7 +688,7 @@ impl Tree {
_ => unreachable!(), _ => unreachable!(),
}; };
node = self.push_tag(tag); node = self.nodes.push_tag(tag);
} }
Ok(node) Ok(node)
@ -616,22 +705,22 @@ impl Tree {
Token::Bang => { Token::Bang => {
_ = tokens.next(); _ = tokens.next();
let lhs = self.parse_as_expr(tokens)?; let lhs = self.parse_as_expr(tokens)?;
Ok(self.push_tag(Tag::Not { lhs })) Ok(self.nodes.push_tag(Tag::Not { lhs }))
} }
Token::Minus => { Token::Minus => {
_ = tokens.next(); _ = tokens.next();
let lhs = self.parse_as_expr(tokens)?; let lhs = self.parse_as_expr(tokens)?;
Ok(self.push_tag(Tag::Negate { lhs })) Ok(self.nodes.push_tag(Tag::Negate { lhs }))
} }
Token::Ampersand => { Token::Ampersand => {
_ = tokens.next(); _ = tokens.next();
let lhs = self.parse_as_expr(tokens)?; let lhs = self.parse_as_expr(tokens)?;
Ok(self.push_tag(Tag::Ref { lhs })) Ok(self.nodes.push_tag(Tag::Ref { lhs }))
} }
Token::Star => { Token::Star => {
_ = tokens.next(); _ = tokens.next();
let lhs = self.parse_as_expr(tokens)?; let lhs = self.parse_as_expr(tokens)?;
Ok(self.push_tag(Tag::Deref { lhs })) Ok(self.nodes.push_tag(Tag::Deref { lhs }))
} }
_ => self.parse_as_expr(tokens), _ => self.parse_as_expr(tokens),
} }
@ -645,7 +734,7 @@ impl Tree {
if tokens.eat_token(Token::As).is_some() { if tokens.eat_token(Token::As).is_some() {
let typename = self.parse_typename(tokens)?; let typename = self.parse_typename(tokens)?;
Ok(self.push_tag(Tag::ExplicitCast { Ok(self.nodes.push_tag(Tag::ExplicitCast {
lhs: expr, lhs: expr,
typename, typename,
})) }))
@ -668,14 +757,27 @@ impl Tree {
pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> { pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
let token = tokens.peek_token_or_err()?; let token = tokens.peek_token_or_err()?;
match token.token() { match token.token() {
Token::Ident => Ok(self.parse_ident(tokens)?), Token::Ident => {
// Ok(self.parse_ident(tokens)?)
let ident = tokens.expect_token(Token::Ident)?;
let decl = match self.st.find_symbol(ident.lexeme()) {
Some(rec) => rec.node(),
None => self
.st
.insert_orderless_symbol(ident.lexeme(), self.nodes.reserve_node())
.node(),
};
Ok(self.nodes.push_tag(Tag::DeclRef(decl)))
}
Token::IntegerBinConstant Token::IntegerBinConstant
| Token::IntegerHexConstant | Token::IntegerHexConstant
| Token::IntegerOctConstant | Token::IntegerOctConstant
| Token::IntegerConstant => { | Token::IntegerConstant => {
_ = tokens.next(); _ = tokens.next();
let (bits, ty) = Self::parse_integral_constant(token.token(), token.lexeme()); let (bits, ty) = Self::parse_integral_constant(token.token(), token.lexeme());
Ok(self.push_tag(Tag::IntegralConstant { bits, ty })) Ok(self.nodes.push_tag(Tag::IntegralConstant { bits, ty }))
} }
Token::FloatingConstant Token::FloatingConstant
| Token::FloatingExpConstant | Token::FloatingExpConstant
@ -684,7 +786,7 @@ impl Tree {
_ = tokens.next(); _ = tokens.next();
let (bits, ty) = Self::parse_floating_constant(token.token(), token.lexeme()); let (bits, ty) = Self::parse_floating_constant(token.token(), token.lexeme());
Ok(self.push_tag(Tag::FloatingConstant { bits, ty })) Ok(self.nodes.push_tag(Tag::FloatingConstant { bits, ty }))
} }
Token::OpenParens => { Token::OpenParens => {
_ = tokens.next(); _ = tokens.next();
@ -693,7 +795,7 @@ impl Tree {
Ok(node) Ok(node)
} }
Token::OpenBrace => { Token::OpenBrace => {
let node = self.parse_block(tokens)?; let node = self.parse_block(tokens, None)?;
Ok(node) Ok(node)
} }
_ => unreachable!(), _ => unreachable!(),
@ -731,15 +833,8 @@ impl Tree {
self.parse_program(&mut tokens) self.parse_program(&mut tokens)
} }
pub fn get_ident_str(&self, node: Node) -> Option<&str> {
match &self.nodes[node.get() as usize] {
Tag::Ident { name } => Some(name.as_str()),
_ => None,
}
}
fn get_typename_str(&self, node: Node) -> Option<String> { fn get_typename_str(&self, node: Node) -> Option<String> {
match self.get_node(node) { match self.nodes.get_node(node) {
Tag::IntegralType(i) => Some(i.to_string()), Tag::IntegralType(i) => Some(i.to_string()),
Tag::Ident { name } => Some(name.clone()), Tag::Ident { name } => Some(name.clone()),
Tag::Pointer { pointee } => self.get_typename_str(*pointee), Tag::Pointer { pointee } => self.get_typename_str(*pointee),
@ -749,24 +844,28 @@ impl Tree {
} }
fn render_node<W: core::fmt::Write>( fn render_node<W: core::fmt::Write>(
&self, &mut self,
writer: &mut W, writer: &mut W,
node: Node, node: Node,
indent: u32, indent: u32,
) -> core::fmt::Result { ) -> core::fmt::Result {
match &self.nodes[node.get() as usize] { match self.nodes[node].clone() {
Tag::FunctionProto { Tag::FunctionProto {
name, name,
parameters, parameters,
return_type, return_type,
} => { } => {
self.render_node(writer, *name, indent)?; self.render_node(writer, name, indent)?;
self.render_node(writer, *return_type, indent)?; self.render_node(writer, return_type, indent)?;
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
self.render_node(writer, *parameters, indent)?; self.render_node(writer, parameters, indent)?;
} }
write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?; write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?;
write!(writer, "name: \"{}\"", self.get_ident_str(*name).unwrap())?; write!(
writer,
"name: \"{}\"",
self.nodes.get_ident_str(name).unwrap()
)?;
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
write!(writer, ", parameters: %{}", parameters.get())?; write!(writer, ", parameters: %{}", parameters.get())?;
} }
@ -776,7 +875,7 @@ impl Tree {
Tag::ParameterList { parameters } => { Tag::ParameterList { parameters } => {
writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?; writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?;
for param in parameters { for param in parameters {
self.render_node(writer, *param, indent + 1)?; self.render_node(writer, param, indent + 1)?;
} }
writeln_indented!(indent, writer, "]") writeln_indented!(indent, writer, "]")
} }
@ -786,8 +885,8 @@ impl Tree {
writer, writer,
"%{} = {}: {},", "%{} = {}: {},",
node.get(), node.get(),
self.get_ident_str(*name).unwrap(), self.nodes.get_ident_str(name).unwrap(),
self.get_typename_str(*ty).unwrap() self.get_typename_str(ty).unwrap()
) )
} }
Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => { Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => {
@ -801,7 +900,7 @@ impl Tree {
} }
Tag::PointerQualifier { constness } => todo!(), Tag::PointerQualifier { constness } => todo!(),
Tag::FunctionDecl { proto, body } => { Tag::FunctionDecl { proto, body } => {
self.render_node(writer, *proto, indent)?; self.render_node(writer, proto, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -810,7 +909,7 @@ impl Tree {
proto.get(), proto.get(),
body.get() body.get()
)?; )?;
self.render_node(writer, *body, indent + 1)?; self.render_node(writer, body, indent + 1)?;
writeln_indented!(indent, writer, "}}") writeln_indented!(indent, writer, "}}")
} }
Tag::Ident { name } => { Tag::Ident { name } => {
@ -841,11 +940,12 @@ impl Tree {
trailing_expr, trailing_expr,
} => { } => {
writeln_indented!(indent, writer, "%{} = {{", node.get())?; writeln_indented!(indent, writer, "%{} = {{", node.get())?;
self.st.into_find_child(node);
for stmt in statements { for stmt in statements {
self.render_node(writer, *stmt, indent + 1)?; self.render_node(writer, stmt, indent + 1)?;
} }
if let Some(expr) = trailing_expr { if let Some(expr) = trailing_expr {
self.render_node(writer, *expr, indent + 1)?; self.render_node(writer, expr, indent + 1)?;
writeln_indented!( writeln_indented!(
indent + 1, indent + 1,
writer, writer,
@ -854,24 +954,25 @@ impl Tree {
expr.get() expr.get()
)?; )?;
} }
self.st.into_parent();
writeln_indented!(indent, writer, "}}") writeln_indented!(indent, writer, "}}")
} }
Tag::ReturnStmt { expr } => { Tag::ReturnStmt { expr } => {
if let Some(expr) = expr { if let Some(expr) = expr {
self.render_node(writer, *expr, indent)?; self.render_node(writer, expr, indent)?;
writeln_indented!(indent, writer, "%{} = return %{};", node.get(), expr.get()) writeln_indented!(indent, writer, "%{} = return %{};", node.get(), expr.get())
} else { } else {
writeln_indented!(indent, writer, "%{} = return;", node.get()) writeln_indented!(indent, writer, "%{} = return;", node.get())
} }
} }
Tag::ExprStmt { expr } => self.render_node(writer, *expr, indent), Tag::ExprStmt { expr } => self.render_node(writer, expr, indent),
Tag::VarDecl { Tag::VarDecl {
let_or_var, let_or_var,
name, name,
explicit_type, explicit_type,
.. ..
} => { } => {
self.render_node(writer, *name, indent)?; self.render_node(writer, name, indent)?;
explicit_type.map(|ty| self.render_node(writer, ty, indent)); explicit_type.map(|ty| self.render_node(writer, ty, indent));
write_indented!( write_indented!(
indent, indent,
@ -886,10 +987,10 @@ impl Tree {
"mut" "mut"
} }
}, },
self.get_ident_str(*name).unwrap() self.nodes.get_ident_str(name).unwrap()
)?; )?;
if let Some(ty) = explicit_type { if let Some(ty) = explicit_type {
write!(writer, ", ty: {}", self.get_typename_str(*ty).unwrap())?; write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
} }
writeln!(writer, ");")?; writeln!(writer, ");")?;
Ok(()) Ok(())
@ -898,22 +999,22 @@ impl Tree {
Tag::ArgumentList { parameters } => todo!(), Tag::ArgumentList { parameters } => todo!(),
Tag::Argument { name, expr } => todo!(), Tag::Argument { name, expr } => todo!(),
Tag::ExplicitCast { lhs, typename } => { Tag::ExplicitCast { lhs, typename } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
"%{} = cast<{}>(%{})", "%{} = cast<{}>(%{})",
node.get(), node.get(),
self.get_typename_str(*typename).unwrap(), self.get_typename_str(typename).unwrap(),
lhs.get() lhs.get()
) )
} }
Tag::Deref { lhs } => { Tag::Deref { lhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!(indent, writer, "%{} = deref(%{})", node.get(), lhs.get()) writeln_indented!(indent, writer, "%{} = deref(%{})", node.get(), lhs.get())
} }
Tag::Ref { lhs } => { Tag::Ref { lhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -923,16 +1024,16 @@ impl Tree {
) )
} }
Tag::Not { lhs } => { Tag::Not { lhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!(indent, writer, "%{} = ", node.get(),) writeln_indented!(indent, writer, "%{} = ", node.get(),)
} }
Tag::Negate { lhs } => { Tag::Negate { lhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!(indent, writer, "%{} = not(%{})", node.get(), lhs.get()) writeln_indented!(indent, writer, "%{} = not(%{})", node.get(), lhs.get())
} }
Tag::Or { lhs, rhs } => { Tag::Or { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -943,8 +1044,8 @@ impl Tree {
) )
} }
Tag::And { lhs, rhs } => { Tag::And { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -955,8 +1056,8 @@ impl Tree {
) )
} }
Tag::BitOr { lhs, rhs } => { Tag::BitOr { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -967,8 +1068,8 @@ impl Tree {
) )
} }
Tag::BitAnd { lhs, rhs } => { Tag::BitAnd { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -979,8 +1080,8 @@ impl Tree {
) )
} }
Tag::BitXOr { lhs, rhs } => { Tag::BitXOr { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -991,8 +1092,8 @@ impl Tree {
) )
} }
Tag::Eq { lhs, rhs } => { Tag::Eq { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1003,8 +1104,8 @@ impl Tree {
) )
} }
Tag::NEq { lhs, rhs } => { Tag::NEq { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1015,8 +1116,8 @@ impl Tree {
) )
} }
Tag::Lt { lhs, rhs } => { Tag::Lt { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1027,8 +1128,8 @@ impl Tree {
) )
} }
Tag::Gt { lhs, rhs } => { Tag::Gt { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1039,8 +1140,8 @@ impl Tree {
) )
} }
Tag::Le { lhs, rhs } => { Tag::Le { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1051,8 +1152,8 @@ impl Tree {
) )
} }
Tag::Ge { lhs, rhs } => { Tag::Ge { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1063,8 +1164,8 @@ impl Tree {
) )
} }
Tag::Shl { lhs, rhs } => { Tag::Shl { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1075,8 +1176,8 @@ impl Tree {
) )
} }
Tag::Shr { lhs, rhs } => { Tag::Shr { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1087,8 +1188,8 @@ impl Tree {
) )
} }
Tag::Add { lhs, rhs } => { Tag::Add { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1099,8 +1200,8 @@ impl Tree {
) )
} }
Tag::Sub { lhs, rhs } => { Tag::Sub { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1111,8 +1212,8 @@ impl Tree {
) )
} }
Tag::Mul { lhs, rhs } => { Tag::Mul { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1123,8 +1224,8 @@ impl Tree {
) )
} }
Tag::Div { lhs, rhs } => { Tag::Div { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1135,8 +1236,8 @@ impl Tree {
) )
} }
Tag::Rem { lhs, rhs } => { Tag::Rem { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1147,8 +1248,8 @@ impl Tree {
) )
} }
Tag::Assign { lhs, rhs } => { Tag::Assign { lhs, rhs } => {
self.render_node(writer, *lhs, indent)?; self.render_node(writer, lhs, indent)?;
self.render_node(writer, *rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1158,12 +1259,29 @@ impl Tree {
rhs.get() rhs.get()
) )
} }
Tag::DeclRef(decl) => {
writeln_indented!(
indent,
writer,
"%{} = decl_ref(%{}, name: {})",
node.get(),
decl.get(),
self.st
.find_symbol_by_decl(decl)
.map(|a| a.name())
.unwrap_or(&format!(
"SymbolTable entry not found?, %{}, %{}",
node.get(),
decl.get()
))
)
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
pub fn render<W: core::fmt::Write>(&self, writer: &mut W) -> core::fmt::Result { pub fn render<W: core::fmt::Write>(&mut self, writer: &mut W) -> core::fmt::Result {
for decl in &self.global_decls { for decl in &self.global_decls.clone() {
self.render_node(writer, *decl, 0)?; self.render_node(writer, *decl, 0)?;
} }
@ -1232,4 +1350,23 @@ x * x
tree.render(&mut buf).unwrap(); tree.render(&mut buf).unwrap();
println!("{buf}"); println!("{buf}");
} }
#[test]
fn render_ast3() {
let src = "
fn main() -> void {
let a: u32 = 0;
a == global
}
let global: u32 = 42;
";
let tokens = Tokenizer::new(src.as_bytes()).unwrap();
let mut tree = Tree::new();
tree.parse(tokens.iter()).unwrap();
let mut buf = String::new();
tree.render(&mut buf).unwrap();
println!("{buf}");
}
} }

202
src/symbol_table.rs Normal file
View file

@ -0,0 +1,202 @@
use std::collections::{BTreeMap, HashMap};
use crate::ast::Node as AstNode;
#[derive(Debug)]
pub struct SymbolRecord {
name: String,
decl: AstNode,
}
impl SymbolRecord {
pub fn node(&self) -> AstNode {
self.decl
}
pub fn name(&self) -> &str {
&self.name
}
}
pub enum SymbolKind {
Var, // or Let
Orderless,
}
#[derive(Debug, Default)]
pub struct SymbolTable {
// this is a `Vec<_>` because order matters. Some symbols such as functions
// cannot be shadowed, but I really like shadowing variables and function
// parameters, so any `x` may be redefined.
ordered_identifiers: Vec<SymbolRecord>,
orderless_identifiers: HashMap<String, SymbolRecord>,
parent: Option<Box<SymbolTable>>,
children: BTreeMap<Option<AstNode>, SymbolTable>,
scope: Option<AstNode>,
}
impl SymbolTable {
pub fn new() -> SymbolTable {
Self {
..Default::default()
}
}
pub fn root_ref(&self) -> &SymbolTable {
match self.parent.as_ref() {
Some(parent) => parent.root_ref(),
None => self,
}
}
pub fn root_mut(&mut self) -> &mut SymbolTable {
let this = self as *mut Self;
unsafe {
match (&mut *this).parent.as_mut() {
Some(parent) => parent.root_mut(),
None => self,
}
}
}
pub fn parent_ref(&self) -> &SymbolTable {
match self.parent.as_ref() {
Some(parent) => Box::as_ref(parent),
None => self,
}
}
pub fn parent_mut(&mut self) -> &mut SymbolTable {
let this = self as *mut Self;
unsafe {
match (&mut *this).parent.as_mut() {
Some(parent) => Box::as_mut(parent),
None => self,
}
}
}
pub fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord {
match kind {
SymbolKind::Var => {
self.ordered_identifiers.push(SymbolRecord {
name: name.to_owned(),
decl: node,
});
self.ordered_identifiers.last().unwrap()
}
_ => {
self.orderless_identifiers.insert(
name.to_owned(),
SymbolRecord {
name: name.to_owned(),
decl: node,
},
);
self.orderless_identifiers.get(name).unwrap()
}
}
}
pub fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord {
self.orderless_identifiers.insert(
name.to_owned(),
SymbolRecord {
name: name.to_owned(),
decl: node,
},
);
self.orderless_identifiers.get(name).unwrap()
}
pub fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord
where
F: FnOnce() -> (AstNode, SymbolKind),
{
let this = self as *mut Self;
if let Some(record) = unsafe { &*this }.find_symbol(name) {
record
} else {
let (node, kind) = cb();
self.insert_symbol(name, node, kind)
}
}
pub fn find_symbol_by_decl(&self, decl: AstNode) -> Option<&SymbolRecord> {
self.ordered_identifiers
.iter()
.find(|r| r.decl == decl)
.or_else(|| {
self.orderless_identifiers
.iter()
.find(|(_, v)| v.decl == decl)
.map(|(_, v)| v)
})
.or_else(|| {
self.parent
.as_ref()
.and_then(|p| p.find_symbol_by_decl(decl))
})
}
pub fn find_symbol(&self, name: &str) -> Option<&SymbolRecord> {
self.ordered_identifiers
.iter()
.find(|r| r.name.as_str() == name)
.or_else(|| self.orderless_identifiers.get(name))
.or_else(|| self.parent.as_ref().and_then(|p| p.find_symbol(name)))
}
pub fn find_orderless_symbol(&self, name: &str) -> Option<&SymbolRecord> {
self.orderless_identifiers.get(name).or_else(|| {
self.parent
.as_ref()
.and_then(|p| p.find_orderless_symbol(name))
})
}
pub fn into_find_child(&mut self, scope: AstNode) -> Option<()> {
if let Some(mut parent) = self.children.remove(&Some(scope)) {
core::mem::swap(self, &mut parent);
self.parent = Some(Box::new(parent));
Some(())
} else {
None
}
}
pub fn into_child(&mut self, scope: AstNode) {
let mut parent = Self {
scope: Some(scope),
..Default::default()
};
core::mem::swap(self, &mut parent);
self.parent = Some(Box::new(parent));
}
pub fn extend_orderless<I>(&mut self, iter: I)
where
I: IntoIterator<Item = (String, SymbolRecord)>,
{
self.orderless_identifiers.extend(iter)
}
pub fn extract_orderless_if<F>(
&mut self,
pred: F,
) -> std::collections::hash_map::ExtractIf<String, SymbolRecord, F>
where
F: FnMut(&String, &mut SymbolRecord) -> bool,
{
self.orderless_identifiers.extract_if(pred)
}
/// returns `self` if `self.parent` was `Some(_)`.
pub fn into_parent(&mut self) {
if let Some(child) = self.parent.take() {
let mut child = Box::into_inner(child);
core::mem::swap(self, &mut child);
self.children.insert(child.scope, child);
}
}
}

View file

@ -43,10 +43,14 @@ impl<'a> SymbolTable<'a> {
} }
pub fn insert_symbol(&mut self, ast_node: AstNode) { pub fn insert_symbol(&mut self, ast_node: AstNode) {
let name = match self.tree.get_node(ast_node) { let name = match self.tree.nodes.get_node(ast_node) {
Tag::VarDecl { name, .. } => self.tree.get_ident_str(*name).unwrap().to_string(), Tag::VarDecl { name, .. } => self.tree.nodes.get_ident_str(*name).unwrap().to_string(),
Tag::Parameter { name, .. } => self.tree.get_ident_str(*name).unwrap().to_string(), Tag::Parameter { name, .. } => {
Tag::FunctionProto { name, .. } => self.tree.get_ident_str(*name).unwrap().to_string(), 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!"); panic!("ast_node wasn't any kind of decl!");
} }
@ -69,7 +73,7 @@ impl<'a> SymbolTable<'a> {
pub fn find_symbol(&self, ident_node: AstNode) -> Option<&SymbolRecord> { pub fn find_symbol(&self, ident_node: AstNode) -> Option<&SymbolRecord> {
self.identifiers self.identifiers
.iter() .iter()
.find(|r| Some(r.name.as_str()) == self.tree.get_ident_str(ident_node)) .find(|r| Some(r.name.as_str()) == self.tree.nodes.get_ident_str(ident_node))
.or_else(|| { .or_else(|| {
self.parent self.parent
.as_ref() .as_ref()
@ -113,7 +117,7 @@ impl<'a> SymbolTable<'a> {
} }
fn type_of_node(&self, node: AstNode) -> crate::ast::Type { fn type_of_node(&self, node: AstNode) -> crate::ast::Type {
match self.tree.get_node(node) { match self.tree.nodes.get_node(node) {
Tag::Ident { name } => self Tag::Ident { name } => self
.find_symbol(node) .find_symbol(node)
.map(|r| r.ty.clone()) .map(|r| r.ty.clone())
@ -126,7 +130,7 @@ impl<'a> SymbolTable<'a> {
} => { } => {
let return_type = self.type_of_node(*return_type); let return_type = self.type_of_node(*return_type);
let parameter_types = parameters let parameter_types = parameters
.map(|p| match self.tree.get_node(p) { .map(|p| match self.tree.nodes.get_node(p) {
Tag::ParameterList { parameters } => parameters Tag::ParameterList { parameters } => parameters
.iter() .iter()
.map(|p| self.type_of_node(*p)) .map(|p| self.type_of_node(*p))
@ -163,7 +167,7 @@ impl<'a> SymbolTable<'a> {
.. ..
} => { } => {
let lhs = explicit_type.map(|n| self.type_of_node(n)); let lhs = explicit_type.map(|n| self.type_of_node(n));
let rhs = assignment.map(|n| match self.tree.get_node(n) { let rhs = assignment.map(|n| match self.tree.nodes.get_node(n) {
Tag::Assign { rhs, .. } => self.type_of_node(*rhs), Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
_ => unreachable!(), _ => unreachable!(),
}); });
@ -259,8 +263,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
} }
fn visit(&mut self, node: AstNode) -> Node { fn visit(&mut self, node: AstNode) -> Node {
println!("visiting %{}", node.get()); match &self.st.tree.nodes[node] {
match self.st.tree.get_node(node) {
Tag::FunctionDecl { proto, body } => { Tag::FunctionDecl { proto, body } => {
self.visit(*proto); self.visit(*proto);
self.st.into_child_in_place(); self.st.into_child_in_place();
@ -286,7 +289,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
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.get_ident_str(*name).unwrap().to_string(), self.st.tree.nodes.get_ident_str(*name).unwrap().to_string(),
)); ));
self.lookup.insert(node, label); self.lookup.insert(node, label);
@ -464,7 +467,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
self.ir.push(Inst::AddressOf(lhs)) self.ir.push(Inst::AddressOf(lhs))
} }
_ => { _ => {
dbg!(self.st.tree.get_node(node)); dbg!(&self.st.tree.nodes[node]);
todo!() todo!()
} }
} }