Analyzer -> SymbolTable

This commit is contained in:
2026-03-19 13:18:24 +01:00
parent e24763dfb6
commit 8758295641
4 changed files with 39 additions and 35 deletions

View File

@@ -1,8 +1,8 @@
use std::{collections::HashMap, fmt::Write}; use std::{collections::HashMap, fmt::Write};
use crate::{ use crate::{
analyzer::Analyzer,
parser::{Expr, Stmt}, parser::{Expr, Stmt},
symbol_table::SymbolTable,
tokenizer::{Token, TokenType, ZernError, error}, tokenizer::{Token, TokenType, ZernError, error},
}; };
@@ -74,17 +74,17 @@ pub struct CodegenX86_64<'a> {
data_section: String, data_section: String,
label_counter: usize, label_counter: usize,
data_counter: usize, data_counter: usize,
pub analyzer: &'a Analyzer, pub symbol_table: &'a SymbolTable,
} }
impl<'a> CodegenX86_64<'a> { impl<'a> CodegenX86_64<'a> {
pub fn new(analyzer: &'a Analyzer) -> CodegenX86_64<'a> { pub fn new(symbol_table: &'a SymbolTable) -> CodegenX86_64<'a> {
CodegenX86_64 { CodegenX86_64 {
output: String::new(), output: String::new(),
data_section: String::new(), data_section: String::new(),
label_counter: 0, label_counter: 0,
data_counter: 1, data_counter: 1,
analyzer, symbol_table,
} }
} }
@@ -223,7 +223,7 @@ _builtin_environ:
var_type, var_type,
initializer, initializer,
} => { } => {
// TODO: move to analyzer // TODO: move to typechecker?
if env.get_var(&name.lexeme).is_some() { if env.get_var(&name.lexeme).is_some() {
return error!( return error!(
name.loc, name.loc,
@@ -250,7 +250,7 @@ _builtin_environ:
emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset); emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset);
} }
Stmt::Const { name: _, value: _ } => { Stmt::Const { name: _, value: _ } => {
// handled in the analyzer // handled in SymbolTable
} }
Stmt::Block(statements) => { Stmt::Block(statements) => {
env.push_scope(); env.push_scope();
@@ -398,7 +398,7 @@ _builtin_environ:
emit!(&mut self.output, "extern {}", name.lexeme); emit!(&mut self.output, "extern {}", name.lexeme);
} }
Stmt::Struct { name: _, fields: _ } => { Stmt::Struct { name: _, fields: _ } => {
// handled in the analyzer // handled in SymbolTable
} }
} }
Ok(()) Ok(())
@@ -555,11 +555,11 @@ _builtin_environ:
} }
} }
Expr::Variable(name) => { Expr::Variable(name) => {
if self.analyzer.constants.contains_key(&name.lexeme) { if self.symbol_table.constants.contains_key(&name.lexeme) {
emit!( emit!(
&mut self.output, &mut self.output,
" mov rax, {}", " mov rax, {}",
self.analyzer.constants[&name.lexeme] self.symbol_table.constants[&name.lexeme]
); );
} else { } else {
let var = match env.get_var(&name.lexeme) { let var = match env.get_var(&name.lexeme) {
@@ -655,7 +655,11 @@ _builtin_environ:
} }
if let Expr::Variable(callee_name) = &**callee { if let Expr::Variable(callee_name) = &**callee {
if self.analyzer.functions.contains_key(&callee_name.lexeme) { if self
.symbol_table
.functions
.contains_key(&callee_name.lexeme)
{
// its a function (defined/builtin/extern) // its a function (defined/builtin/extern)
emit!(&mut self.output, " call {}", callee_name.lexeme); emit!(&mut self.output, " call {}", callee_name.lexeme);
} else { } else {
@@ -702,7 +706,7 @@ _builtin_environ:
} }
Expr::AddrOf { op, expr } => match *expr.clone() { Expr::AddrOf { op, expr } => match *expr.clone() {
Expr::Variable(name) => { Expr::Variable(name) => {
if self.analyzer.functions.contains_key(&name.lexeme) { if self.symbol_table.functions.contains_key(&name.lexeme) {
emit!(&mut self.output, " mov rax, {}", name.lexeme); emit!(&mut self.output, " mov rax, {}", name.lexeme);
} else { } else {
let var = match env.get_var(&name.lexeme) { let var = match env.get_var(&name.lexeme) {
@@ -726,7 +730,7 @@ _builtin_environ:
} }
}, },
Expr::New(struct_name) => { Expr::New(struct_name) => {
let struct_fields = &self.analyzer.structs[&struct_name.lexeme]; let struct_fields = &self.symbol_table.structs[&struct_name.lexeme];
// TODO: panic on mem.alloc error // TODO: panic on mem.alloc error
let memory_size = struct_fields.len() * 8; let memory_size = struct_fields.len() * 8;
@@ -771,7 +775,7 @@ _builtin_environ:
} }
}; };
let fields = match self.analyzer.structs.get(&struct_name) { let fields = match self.symbol_table.structs.get(&struct_name) {
Some(f) => f, Some(f) => f,
None => { None => {
return error!(&field.loc, format!("unknown struct type: {}", struct_name)); return error!(&field.loc, format!("unknown struct type: {}", struct_name));

View File

@@ -1,6 +1,6 @@
mod analyzer;
mod codegen_x86_64; mod codegen_x86_64;
mod parser; mod parser;
mod symbol_table;
mod tokenizer; mod tokenizer;
mod typechecker; mod typechecker;
@@ -44,17 +44,17 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
let parser = parser::Parser::new(tokenizer.tokenize()?); let parser = parser::Parser::new(tokenizer.tokenize()?);
statements.extend(parser.parse()?); statements.extend(parser.parse()?);
let mut analyzer = analyzer::Analyzer::new(); let mut symbol_table = symbol_table::SymbolTable::new();
for stmt in &statements { for stmt in &statements {
analyzer.register_declaration(stmt)?; symbol_table.register_declaration(stmt)?;
} }
let mut typechecker = typechecker::TypeChecker::new(&analyzer); let mut typechecker = typechecker::TypeChecker::new(&symbol_table);
for stmt in &statements { for stmt in &statements {
typechecker.typecheck_stmt(&mut typechecker::Env::new(), stmt)?; typechecker.typecheck_stmt(&mut typechecker::Env::new(), stmt)?;
} }
let mut codegen = codegen_x86_64::CodegenX86_64::new(&analyzer); let mut codegen = codegen_x86_64::CodegenX86_64::new(&symbol_table);
codegen.emit_prologue(args.use_gcc)?; codegen.emit_prologue(args.use_gcc)?;
for stmt in statements { for stmt in statements {
codegen.compile_stmt(&mut codegen_x86_64::Env::new(), &stmt)?; codegen.compile_stmt(&mut codegen_x86_64::Env::new(), &stmt)?;

View File

@@ -34,15 +34,15 @@ impl FnType {
} }
} }
pub struct Analyzer { pub struct SymbolTable {
pub functions: HashMap<String, FnType>, pub functions: HashMap<String, FnType>,
pub constants: HashMap<String, u64>, pub constants: HashMap<String, u64>,
pub structs: HashMap<String, HashMap<String, StructField>>, pub structs: HashMap<String, HashMap<String, StructField>>,
} }
impl Analyzer { impl SymbolTable {
pub fn new() -> Analyzer { pub fn new() -> SymbolTable {
Analyzer { SymbolTable {
functions: HashMap::from([ functions: HashMap::from([
("_builtin_heap_head".into(), FnType::new("ptr", vec![])), ("_builtin_heap_head".into(), FnType::new("ptr", vec![])),
("_builtin_heap_tail".into(), FnType::new("ptr", vec![])), ("_builtin_heap_tail".into(), FnType::new("ptr", vec![])),

View File

@@ -1,8 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
analyzer::{Analyzer, Type},
parser::{Expr, Stmt}, parser::{Expr, Stmt},
symbol_table::{SymbolTable, Type},
tokenizer::{TokenType, ZernError, error}, tokenizer::{TokenType, ZernError, error},
}; };
@@ -70,14 +70,14 @@ impl Env {
} }
pub struct TypeChecker<'a> { pub struct TypeChecker<'a> {
analyzer: &'a Analyzer, symbol_table: &'a SymbolTable,
current_function_return_type: String, current_function_return_type: String,
} }
impl<'a> TypeChecker<'a> { impl<'a> TypeChecker<'a> {
pub fn new(analyzer: &'a Analyzer) -> TypeChecker<'a> { pub fn new(symbol_table: &'a SymbolTable) -> TypeChecker<'a> {
TypeChecker { TypeChecker {
analyzer, symbol_table,
current_function_return_type: String::new(), current_function_return_type: String::new(),
} }
} }
@@ -110,7 +110,7 @@ impl<'a> TypeChecker<'a> {
env.define_var(name.lexeme.clone(), actual_type); env.define_var(name.lexeme.clone(), actual_type);
} }
Stmt::Const { name: _, value: _ } => { Stmt::Const { name: _, value: _ } => {
// handled in the analyzer // handled in SymbolTable
} }
Stmt::Block(stmts) => { Stmt::Block(stmts) => {
env.push_scope(); env.push_scope();
@@ -207,7 +207,7 @@ impl<'a> TypeChecker<'a> {
Stmt::Break => {} Stmt::Break => {}
Stmt::Continue => {} Stmt::Continue => {}
Stmt::Extern(_) => { Stmt::Extern(_) => {
// handled in the analyzer // handled in the SymbolTable
} }
Stmt::Struct { name: _, fields } => { Stmt::Struct { name: _, fields } => {
for field in fields { for field in fields {
@@ -304,7 +304,7 @@ impl<'a> TypeChecker<'a> {
} }
} }
Expr::Variable(name) => { Expr::Variable(name) => {
if self.analyzer.constants.contains_key(&name.lexeme) { if self.symbol_table.constants.contains_key(&name.lexeme) {
Ok("i64".into()) Ok("i64".into())
} else { } else {
match env.get_var_type(&name.lexeme) { match env.get_var_type(&name.lexeme) {
@@ -341,7 +341,7 @@ impl<'a> TypeChecker<'a> {
Expr::MemberAccess { left, field } => { Expr::MemberAccess { left, field } => {
let left_type = self.typecheck_expr(env, left)?; let left_type = self.typecheck_expr(env, left)?;
let fields = match self.analyzer.structs.get(&left_type) { let fields = match self.symbol_table.structs.get(&left_type) {
Some(f) => f, Some(f) => f,
None => { None => {
return error!( return error!(
@@ -373,7 +373,7 @@ impl<'a> TypeChecker<'a> {
args, args,
} => { } => {
if let Expr::Variable(callee_name) = &**callee { if let Expr::Variable(callee_name) = &**callee {
if let Some(fn_type) = self.analyzer.functions.get(&callee_name.lexeme) { if let Some(fn_type) = self.symbol_table.functions.get(&callee_name.lexeme) {
// its a function (defined/builtin/extern) // its a function (defined/builtin/extern)
if let Some(params) = fn_type.params.clone() { if let Some(params) = fn_type.params.clone() {
if params.len() != args.len() { if params.len() != args.len() {
@@ -432,7 +432,7 @@ impl<'a> TypeChecker<'a> {
} }
Expr::AddrOf { op, expr } => match expr.as_ref() { Expr::AddrOf { op, expr } => match expr.as_ref() {
Expr::Variable(name) => { Expr::Variable(name) => {
if self.analyzer.functions.contains_key(&name.lexeme) { if self.symbol_table.functions.contains_key(&name.lexeme) {
Ok("fnptr".into()) Ok("fnptr".into())
} else { } else {
Ok("ptr".into()) Ok("ptr".into())
@@ -443,7 +443,7 @@ impl<'a> TypeChecker<'a> {
} }
}, },
Expr::New(struct_name) => { Expr::New(struct_name) => {
if !self.analyzer.structs.contains_key(&struct_name.lexeme) { if !self.symbol_table.structs.contains_key(&struct_name.lexeme) {
return error!( return error!(
&struct_name.loc, &struct_name.loc,
format!("unknown struct name: {}", &struct_name.lexeme) format!("unknown struct name: {}", &struct_name.lexeme)
@@ -454,7 +454,7 @@ impl<'a> TypeChecker<'a> {
Expr::MemberAccess { left, field } => { Expr::MemberAccess { left, field } => {
let left_type = self.typecheck_expr(env, left)?; let left_type = self.typecheck_expr(env, left)?;
let fields = match self.analyzer.structs.get(&left_type) { let fields = match self.symbol_table.structs.get(&left_type) {
Some(f) => f, Some(f) => f,
None => { None => {
return error!(&field.loc, format!("unknown struct type: {}", left_type)); return error!(&field.loc, format!("unknown struct type: {}", left_type));
@@ -485,7 +485,7 @@ impl<'a> TypeChecker<'a> {
if BUILTIN_TYPES.contains(&name) { if BUILTIN_TYPES.contains(&name) {
return true; return true;
} }
if self.analyzer.structs.contains_key(name) { if self.symbol_table.structs.contains_key(name) {
return true; return true;
} }
false false