changed globaldecl to only allow const instead of let or var as keyword
This commit is contained in:
parent
efff2446bc
commit
2689179ed4
|
@ -69,6 +69,13 @@ pub enum Tag {
|
|||
explicit_type: Option<Node>,
|
||||
assignment: Option<Node>,
|
||||
},
|
||||
GlobalDecl {
|
||||
/// Ident
|
||||
name: Node,
|
||||
/// TypeName
|
||||
explicit_type: Option<Node>,
|
||||
assignment: Node,
|
||||
},
|
||||
DeclRef(Node),
|
||||
CallExpr {
|
||||
/// Ident | Expr
|
||||
|
|
102
src/parser.rs
102
src/parser.rs
|
@ -297,7 +297,7 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator, global: bool) -> Result<Node> {
|
||||
pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let let_or_var = match tokens
|
||||
.eat_token(Token::Let)
|
||||
.or_else(|| tokens.eat_token(Token::Var))
|
||||
|
@ -318,16 +318,7 @@ impl Tree {
|
|||
};
|
||||
|
||||
let name_str = self.nodes.get_ident_str(name).unwrap().to_owned();
|
||||
let node = if global {
|
||||
let node = match self.st.find_root_symbol(&name_str) {
|
||||
Some(r) => r.node(),
|
||||
None => self
|
||||
.st
|
||||
.insert_root_symbol(&name_str, self.nodes.reserve_node())
|
||||
.node(),
|
||||
};
|
||||
node
|
||||
} else {
|
||||
let node = {
|
||||
let node = self.nodes.reserve_node();
|
||||
self.st.insert_symbol(&name_str, node, SymbolKind::Var);
|
||||
node
|
||||
|
@ -357,11 +348,53 @@ impl Tree {
|
|||
Ok(assignment.unwrap_or(node))
|
||||
}
|
||||
|
||||
/// GLOBAL_DECL <-
|
||||
/// const IDENTIFIER (: TYPENAME)? = EXPR;
|
||||
pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let node = self.parse_var_decl(tokens, true)?;
|
||||
_ = tokens.expect_token(Token::Const)?;
|
||||
|
||||
let name = self.parse_ident(tokens)?;
|
||||
|
||||
let explicit_type = if tokens.eat_token(Token::Colon).is_some() {
|
||||
Some(self.parse_typename(tokens)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let name_str = self.nodes.get_ident_str(name).unwrap().to_owned();
|
||||
let node = {
|
||||
let node = match self.st.find_root_symbol(&name_str) {
|
||||
Some(r) => r.node(),
|
||||
None => self
|
||||
.st
|
||||
.insert_root_symbol(&name_str, self.nodes.reserve_node())
|
||||
.node(),
|
||||
};
|
||||
node
|
||||
};
|
||||
|
||||
_ = tokens.expect_token(Token::Equal)?;
|
||||
|
||||
let assignment = {
|
||||
let expr = self.parse_expr(tokens)?;
|
||||
self.nodes.push_tag(Tag::Assign {
|
||||
lhs: node,
|
||||
rhs: expr,
|
||||
})
|
||||
};
|
||||
|
||||
self.nodes.set_node(
|
||||
node,
|
||||
Tag::GlobalDecl {
|
||||
name,
|
||||
explicit_type,
|
||||
assignment,
|
||||
},
|
||||
);
|
||||
|
||||
tokens.expect_token(Token::Semi)?;
|
||||
|
||||
Ok(node)
|
||||
Ok(assignment)
|
||||
}
|
||||
|
||||
/// PARAMETER <-
|
||||
|
@ -499,7 +532,7 @@ impl Tree {
|
|||
stmts.push(self.try_parse_return_stmt(tokens)?.unwrap());
|
||||
}
|
||||
Token::Var | Token::Let => {
|
||||
let node = self.parse_var_decl(tokens, false)?;
|
||||
let node = self.parse_var_decl(tokens)?;
|
||||
tokens.expect_token(Token::Semi)?;
|
||||
|
||||
stmts.push(node);
|
||||
|
@ -608,7 +641,7 @@ impl Tree {
|
|||
match tokens.peek_token_or_err()?.token() {
|
||||
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
|
||||
Token::Var | Token::Let => {
|
||||
let node = self.parse_var_decl(tokens, false)?;
|
||||
let node = self.parse_var_decl(tokens)?;
|
||||
tokens.expect_token(Token::Semi)?;
|
||||
|
||||
Ok(node)
|
||||
|
@ -816,7 +849,7 @@ impl Tree {
|
|||
};
|
||||
|
||||
let decl = match token {
|
||||
Token::Var | Token::Let => self.parse_global_decl(tokens)?,
|
||||
Token::Const => self.parse_global_decl(tokens)?,
|
||||
Token::Fn => self.parse_fn_decl(tokens)?,
|
||||
_ => {
|
||||
eprintln!("unexpected token: {}", token);
|
||||
|
@ -994,6 +1027,26 @@ impl Tree {
|
|||
writeln!(writer, ");")?;
|
||||
Ok(())
|
||||
}
|
||||
Tag::GlobalDecl {
|
||||
name,
|
||||
explicit_type,
|
||||
..
|
||||
} => {
|
||||
self.render_node(writer, name, indent)?;
|
||||
explicit_type.map(|ty| self.render_node(writer, ty, indent));
|
||||
write_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = global_decl(name: \"{}\"",
|
||||
node.get(),
|
||||
self.nodes.get_ident_str(name).unwrap()
|
||||
)?;
|
||||
if let Some(ty) = explicit_type {
|
||||
write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
|
||||
}
|
||||
writeln!(writer, ");")?;
|
||||
Ok(())
|
||||
}
|
||||
Tag::CallExpr { .. } => todo!(),
|
||||
Tag::ArgumentList { .. } => todo!(),
|
||||
Tag::Argument { .. } => todo!(),
|
||||
|
@ -1344,6 +1397,21 @@ impl Tree {
|
|||
lhs.or(rhs)
|
||||
.expect("Type could not be automatically deduced.")
|
||||
}
|
||||
Tag::GlobalDecl {
|
||||
explicit_type,
|
||||
assignment, // this is a Tag::Assign
|
||||
..
|
||||
} => {
|
||||
let lhs = explicit_type.map(|n| self.type_of_node(n));
|
||||
let rhs = match self.nodes.get_node(*assignment) {
|
||||
Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if lhs.as_ref().zip(Some(&rhs)).map(|(l, r)| l != r) == Some(true) {
|
||||
eprintln!("vardecl: incompatible types {lhs:?} and {rhs:?}.");
|
||||
}
|
||||
lhs.unwrap_or(rhs)
|
||||
}
|
||||
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(),
|
||||
|
@ -1443,7 +1511,7 @@ fn main() -> void {
|
|||
let a: u32 = 0;
|
||||
a == global
|
||||
}
|
||||
let global: u32 = 42;
|
||||
const global: u32 = 42;
|
||||
";
|
||||
let tokens = Tokenizer::new(src.as_bytes()).unwrap();
|
||||
|
||||
|
|
122
src/triples.rs
122
src/triples.rs
|
@ -1,6 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
|
||||
use crate::{
|
||||
ast::{FloatingType, IntegralType, Node as AstNode, Tag, Type},
|
||||
|
@ -10,10 +10,17 @@ use crate::{
|
|||
|
||||
type Node = u32;
|
||||
|
||||
enum NodeOrList {
|
||||
Node(Node), // node of alloca location
|
||||
List(Vec<Node>), // list of references to `Node(_)`
|
||||
}
|
||||
|
||||
enum Inst {
|
||||
Label(String),
|
||||
Constant(Value),
|
||||
Parameter,
|
||||
UnresolvedRef,
|
||||
Ref(Node),
|
||||
Parameter { size: u32, align: u32 },
|
||||
Add { lhs: Node, rhs: Node },
|
||||
Sub { lhs: Node, rhs: Node },
|
||||
Div { lhs: Node, rhs: Node },
|
||||
|
@ -53,7 +60,7 @@ struct IRBuilder<'tree, 'ir> {
|
|||
ir: &'ir mut IR,
|
||||
tree: &'tree mut Tree,
|
||||
type_map: HashMap<AstNode, Type>,
|
||||
lookup: HashMap<AstNode, Node>,
|
||||
lookup: HashMap<AstNode, NodeOrList>,
|
||||
}
|
||||
|
||||
impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||
|
@ -66,6 +73,27 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn patch_unresolved(&mut self, node: AstNode, resolved: Node) {
|
||||
match self.lookup.entry(node) {
|
||||
Entry::Occupied(mut o) => {
|
||||
match o.get_mut() {
|
||||
NodeOrList::Node(_) => {
|
||||
panic!("there shouldn't be a node here.")
|
||||
}
|
||||
NodeOrList::List(refs) => {
|
||||
for &r in refs.iter() {
|
||||
self.ir.nodes[r as usize] = Inst::Ref(resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
o.insert(NodeOrList::Node(resolved));
|
||||
}
|
||||
Entry::Vacant(v) => {
|
||||
v.insert(NodeOrList::Node(resolved));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit(&mut self, node: AstNode) -> Node {
|
||||
match &self.tree.nodes[node].clone() {
|
||||
Tag::FunctionDecl { proto, body } => {
|
||||
|
@ -92,13 +120,12 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
|||
Tag::FunctionProto {
|
||||
parameters, name, ..
|
||||
} => {
|
||||
parameters.map(|p| self.visit(p));
|
||||
|
||||
let label = self.ir.push(Inst::Label(
|
||||
self.tree.nodes.get_ident_str(*name).unwrap().to_string(),
|
||||
));
|
||||
parameters.map(|p| self.visit(p));
|
||||
|
||||
self.lookup.insert(node, label);
|
||||
self.patch_unresolved(node, label);
|
||||
|
||||
label
|
||||
}
|
||||
|
@ -108,10 +135,14 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
|||
}
|
||||
!0
|
||||
}
|
||||
Tag::Parameter { .. } => {
|
||||
let param = self.ir.push(Inst::Parameter);
|
||||
Tag::Parameter { name, ty } => {
|
||||
let ty = self.tree.type_of_node(*ty);
|
||||
let param = self.ir.push(Inst::Parameter {
|
||||
size: ty.size_of(),
|
||||
align: ty.align_of(),
|
||||
});
|
||||
|
||||
self.lookup.insert(node, param);
|
||||
self.lookup.insert(node, NodeOrList::Node(param));
|
||||
param
|
||||
}
|
||||
Tag::Block {
|
||||
|
@ -134,7 +165,19 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
|||
size: ty.size_of(),
|
||||
align: ty.align_of(),
|
||||
});
|
||||
self.lookup.insert(node, alloca);
|
||||
self.patch_unresolved(node, alloca);
|
||||
alloca
|
||||
}
|
||||
Tag::GlobalDecl { name, .. } => {
|
||||
let ty = self.tree.type_of_node(node);
|
||||
let _label = self.ir.push(Inst::Label(
|
||||
self.tree.nodes.get_ident_str(*name).unwrap().to_string(),
|
||||
));
|
||||
let alloca = self.ir.push(Inst::Alloc {
|
||||
size: ty.size_of(),
|
||||
align: ty.align_of(),
|
||||
});
|
||||
self.patch_unresolved(node, alloca);
|
||||
alloca
|
||||
}
|
||||
Tag::ReturnStmt { expr } => {
|
||||
|
@ -257,7 +300,20 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
|||
let lhs = self.visit(*lhs);
|
||||
self.ir.push(Inst::Negate { lhs })
|
||||
}
|
||||
Tag::DeclRef(decl) => *self.lookup.get(decl).expect("declref not in lookup map"),
|
||||
Tag::DeclRef(decl) => match self.lookup.get_mut(decl) {
|
||||
Some(NodeOrList::Node(decl)) => *decl,
|
||||
Some(NodeOrList::List(refs)) => {
|
||||
let unresolved = self.ir.push(Inst::UnresolvedRef);
|
||||
refs.push(unresolved);
|
||||
unresolved
|
||||
}
|
||||
None => {
|
||||
let unresolved = self.ir.push(Inst::UnresolvedRef);
|
||||
self.lookup
|
||||
.insert(*decl, NodeOrList::List(vec![unresolved]));
|
||||
unresolved
|
||||
}
|
||||
},
|
||||
Tag::Ref { lhs } => {
|
||||
let lhs = self.visit(*lhs);
|
||||
self.ir.push(Inst::AddressOf(lhs))
|
||||
|
@ -294,12 +350,17 @@ impl IR {
|
|||
node
|
||||
}
|
||||
|
||||
pub fn build(&mut self, tree: &mut Tree, ast_node: crate::ast::Node) {
|
||||
pub fn build(&mut self, tree: &mut Tree) {
|
||||
let global_decls = tree.global_decls.clone();
|
||||
let mut builder = IRBuilder::new(self, tree);
|
||||
|
||||
builder.visit(ast_node);
|
||||
for node in &global_decls {
|
||||
builder.visit(*node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IR {
|
||||
fn render_node<W: core::fmt::Write>(
|
||||
&self,
|
||||
w: &mut W,
|
||||
|
@ -310,8 +371,21 @@ impl IR {
|
|||
Inst::Label(label) => {
|
||||
writeln_indented!(indent - 1, w, "%{} = {label}:", node)?;
|
||||
}
|
||||
Inst::Parameter => {
|
||||
writeln_indented!(indent, w, "%{} = Param", node)?;
|
||||
Inst::UnresolvedRef => {
|
||||
writeln_indented!(indent, w, "%{} = unresolved reference", node)?;
|
||||
}
|
||||
Inst::Ref(reference) => {
|
||||
writeln_indented!(indent, w, "%{} = reference(%{})", node, reference)?;
|
||||
}
|
||||
Inst::Parameter { size, align } => {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
w,
|
||||
"%{} = Param(size: {}, align: {})",
|
||||
node,
|
||||
size,
|
||||
align
|
||||
)?;
|
||||
}
|
||||
Inst::Constant(value) => {
|
||||
writeln_indented!(indent, w, "%{} = {}", node, value)?;
|
||||
|
@ -350,7 +424,7 @@ impl IR {
|
|||
writeln_indented!(indent, w, "%{} = return", node)?;
|
||||
}
|
||||
Inst::Alloc { size, align } => {
|
||||
writeln_indented!(indent, w, "%{} = alloca {size} (algin: {align})", node)?;
|
||||
writeln_indented!(indent, w, "%{} = alloca {size} (align: {align})", node)?;
|
||||
}
|
||||
Inst::AddressOf(val) => {
|
||||
writeln_indented!(indent, w, "%{} = addr %{val}", node)?;
|
||||
|
@ -383,11 +457,16 @@ mod tests {
|
|||
fn ir() {
|
||||
let src = "
|
||||
fn main() -> u32 {
|
||||
let a: u32 = 0 + 3;
|
||||
let ptr_a = &a;
|
||||
return *ptr_a * global;
|
||||
let a: u32 = 0 + 3;
|
||||
let ptr_a = &a;
|
||||
return *ptr_a * global;
|
||||
}
|
||||
let global: u32 = 42;
|
||||
|
||||
fn square(x: u32) -> u32 {
|
||||
x * x
|
||||
}
|
||||
|
||||
const global: u32 = 42;
|
||||
";
|
||||
let tokens = Tokenizer::new(src.as_bytes()).unwrap();
|
||||
|
||||
|
@ -399,8 +478,7 @@ let global: u32 = 42;
|
|||
println!("{buf}");
|
||||
|
||||
let mut ir = IR::new();
|
||||
let decl = *tree.global_decls.first().unwrap();
|
||||
ir.build(&mut tree, decl);
|
||||
ir.build(&mut tree);
|
||||
let mut buf = String::new();
|
||||
ir.render(&mut buf).unwrap();
|
||||
println!("{buf}");
|
||||
|
|
Loading…
Reference in a new issue