From 7e3c4e6d6236a3bdf2d652af761c73daacd043c2 Mon Sep 17 00:00:00 2001 From: Robert-M-Lucas Date: Wed, 5 Jun 2024 14:08:32 +0100 Subject: [PATCH] Added some name resolving support --- .idea/workspace.xml | 22 +++--- build/out.asm | 10 ++- build/out.o | Bin 592 -> 608 bytes build/out.out | Bin 16480 -> 16480 bytes main.why | 5 +- src/root/compiler/assembly/utils.rs | 72 ++++++++++++++++++ src/root/compiler/compile_evaluable.rs | 48 +++++++++--- src/root/compiler/compile_function.rs | 7 +- src/root/compiler/local_variable_table.rs | 4 + src/root/errors/evaluable_errors.rs | 7 ++ src/root/errors/mod.rs | 1 + src/root/name_resolver/name_resolvers.rs | 11 ++- .../parser/parse_function/parse_literal.rs | 4 +- src/root/shared/common.rs | 2 +- 14 files changed, 159 insertions(+), 34 deletions(-) create mode 100644 src/root/errors/evaluable_errors.rs diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 0a71e90..6aeb705 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -7,15 +7,7 @@ - - - - - - - - - + diff --git a/build/out.asm b/build/out.asm index b7dafd8..09080e1 100644 --- a/build/out.asm +++ b/build/out.asm @@ -5,9 +5,13 @@ main: push rbp mov rbp, rsp - sub rsp, 16 + sub rsp, 32 - mov qword [rbp-16], 12 - mov rax, qword [rbp-16] + mov qword [rbp-8], 110 + mov rax, qword [rbp-8] + mov qword [rbp-16], rax + mov rax, qword [rbp-16] + mov qword [rbp-24], rax + mov rax, qword [rbp-24] leave ret \ No newline at end of file diff --git a/build/out.o b/build/out.o index c3b9c575e80cd1f12f63e02dde29835ef8272425..34244f4ccedd8dd24aeaea0417bce6001d41c011 100644 GIT binary patch delta 62 zcmcb>@_=Q+0!Foo3(XlfOuT8&_+YXmqdlX;du0Qe^7#KXdU4M9Vx_$uC PAAs}=ApK(U6vjOO;>Q^C delta 46 zcmV+}0MY;81kePKpaB+(^b diff --git a/build/out.out b/build/out.out index 3213d3cca9640afc44c5c3ded83e8782c571f837..272fa11a1fc5430b6de53e7d84be337c1f56cab3 100755 GIT binary patch delta 195 zcmaFR!1$nnaRUbr;kA~Y#uiw<@ehrhE`Fe8=^K4#O z1&`ydKk|TTJ-S_gcyzjc0MZ|T^a~*UVzY|i8NN*l1$>Man+x^!Gjm!9I)IIJnA~V2 zJvqckh0_cwVg?dH7O@APTW9v*~L$1I$MQ}76^Wu-nF@gc{VSv zfX8vy4?IA%9^I}VHk$~Z;hSVEw3$gEkB?DfbD`dTW=;)32e45FlN*hsCx;lRaH>H? y)IcJryvYZQRJaYG@}`0glQ%LcZWb_p!3Z?%rwKbdBim#~8-2K$8k;R`)L8&g{w=5g diff --git a/main.why b/main.why index a3e89bd..f6fd401 100644 --- a/main.why +++ b/main.why @@ -4,6 +4,7 @@ struct A { } fn main() -> int { - let a: int = 13; - return a; + let a: int = 110; + let b: int = a; + return b; } diff --git a/src/root/compiler/assembly/utils.rs b/src/root/compiler/assembly/utils.rs index e351ea3..226cfd8 100644 --- a/src/root/compiler/assembly/utils.rs +++ b/src/root/compiler/assembly/utils.rs @@ -1,3 +1,4 @@ +use std::fmt::format; use crate::root::shared::common::{ByteSize, FunctionID, LocalAddress}; pub fn get_function_tag(id: FunctionID) -> String { @@ -54,4 +55,75 @@ pub fn get_qword_stack_pointer(address: &LocalAddress) -> String { } else { format!("qword [rbp{address}]") } +} + +pub fn get_dword_stack_pointer(address: &LocalAddress) -> String { + let address = address.0; + + if address >= 0 { + format!("dword [rbp+{address}]") + } else { + format!("dword [rbp{address}]") + } +} + +pub fn get_word_stack_pointer(address: &LocalAddress) -> String { + let address = address.0; + + if address >= 0 { + format!("word [rbp+{address}]") + } else { + format!("word [rbp{address}]") + } +} + +pub fn get_byte_stack_pointer(address: &LocalAddress) -> String { + let address = address.0; + + if address >= 0 { + format!("byte [rbp+{address}]") + } else { + format!("byte [rbp{address}]") + } +} + +pub fn copy(from: LocalAddress, to: LocalAddress, amount: ByteSize) -> String { + if amount == ByteSize(0) { return String::new(); } + + let from = from.0; + let to = to.0; + let mut written = 0; + + let mut output = String::new(); + + loop { + let to_write = amount.0 - written; + if to_write >= 8 { + output += &format!(" mov rax, {}\n", get_qword_stack_pointer(&LocalAddress(from + written as isize))); + output += &format!(" mov {}, rax", get_qword_stack_pointer(&LocalAddress(to + written as isize))); + written += 8; + } + else if to_write >= 4 { + output += &format!(" mov eax, {}\n", get_dword_stack_pointer(&LocalAddress(from + written as isize))); + output += &format!(" mov {}, eax", get_dword_stack_pointer(&LocalAddress(to + written as isize))); + written += 4; + } + else if to_write >= 2 { + output += &format!(" mov ax, {}\n", get_word_stack_pointer(&LocalAddress(from + written as isize))); + output += &format!(" mov {}, ax", get_word_stack_pointer(&LocalAddress(to + written as isize))); + written += 2; + } + else if to_write >= 1 { + output += &format!(" mov ah, {}\n", get_byte_stack_pointer(&LocalAddress(from + written as isize))); + output += &format!(" mov {}, ah", get_byte_stack_pointer(&LocalAddress(to + written as isize))); + written += 1; + } + else { + break; + } + if written == amount.0 { break; } + output += "\n"; + } + + output } \ No newline at end of file diff --git a/src/root/compiler/compile_evaluable.rs b/src/root/compiler/compile_evaluable.rs index 6248860..53cfb66 100644 --- a/src/root/compiler/compile_evaluable.rs +++ b/src/root/compiler/compile_evaluable.rs @@ -1,28 +1,56 @@ -use std::any::Any; use std::collections::HashSet; +use crate::root::compiler::assembly::utils::copy; use crate::root::compiler::local_variable_table::LocalVariableTable; -use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable; +use crate::root::errors::evaluable_errors::EvaluableErrors; +use crate::root::errors::WError; +use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResult}; use crate::root::parser::parse_function::parse_evaluable::{EvaluableToken, EvaluableTokens}; -use crate::root::shared::common::{FunctionID, TypeRef}; +use crate::root::shared::common::{FunctionID, Indirection, TypeRef}; use crate::root::shared::common::AddressedTypeRef; -pub fn compile_evaluable(fid: FunctionID, et: &EvaluableToken, target: Option, local_variables: &mut LocalVariableTable, global_table: &mut GlobalDefinitionTable, function_calls: &mut HashSet) -> (String, Option) { +pub fn compile_evaluable( + fid: FunctionID, + et: &EvaluableToken, + target: Option, + local_variables: &mut LocalVariableTable, + global_table: &mut GlobalDefinitionTable, + function_calls: &mut HashSet +) -> Result<(String, Option), WError> { + let et = et.token(); - match et { - EvaluableTokens::Name(_, _) => todo!(), + Ok(match et { + EvaluableTokens::Name(name, containing_class) => { + match global_table.resolve_name(name.name(), local_variables)? { + NameResult::Function(_) => todo!(), + NameResult::Type(_) => todo!(), + NameResult::Variable(address) => { + if let Some(target) = target { + if target.type_ref() != address.type_ref() { + todo!() + } + + (copy(*address.local_address(), *target.local_address(), global_table.get_size(target.type_ref())), Some(target)) + } + else { + let target = global_table.add_local_variable_unnamed_base(address.type_ref().clone(), local_variables); + (copy(*address.local_address(), *target.local_address(), global_table.get_size(target.type_ref())), Some(target)) + } + } + } + }, EvaluableTokens::Literal(literal) => { let (address, t) = if let Some(target) = target { if target.type_ref().indirection().has_indirection() { - todo!() + return Err(WError::n(EvaluableErrors::BadIndirection(target.type_ref().indirection().0, 0), literal.location().clone())); } let t = global_table.get_type(*target.type_ref().type_id()); (target, t) } else { let tid = literal.literal().default_type(); - let address = global_table.add_local_variable_unnamed_base(tid.clone(), local_variables); - let t = global_table.get_type(*tid.type_id()); + let address = global_table.add_local_variable_unnamed_base(TypeRef::new(tid.clone(), Indirection(0)), local_variables); + let t = global_table.get_type(tid); (address, t) }; @@ -33,5 +61,5 @@ pub fn compile_evaluable(fid: FunctionID, et: &EvaluableToken, target: Option todo!(), EvaluableTokens::StaticAccess(_, _) => todo!(), EvaluableTokens::FunctionCall(_, _, _) => todo!() - } + }) } \ No newline at end of file diff --git a/src/root/compiler/compile_function.rs b/src/root/compiler/compile_function.rs index 4e9e4bc..0696b80 100644 --- a/src/root/compiler/compile_function.rs +++ b/src/root/compiler/compile_function.rs @@ -73,14 +73,15 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia LineTokens::Initialisation(it) => { let (name, type_name, value) = (it.name(), it.type_name(), it.value()); let address = global_table.add_local_variable_named(name.name().clone(), type_name, &mut local_variables)?; - compile_evaluable(fid, value, Some(address), &mut local_variables, global_table, function_calls); + contents += "\n"; + contents += &compile_evaluable(fid, value, Some(address), &mut local_variables, global_table, function_calls)?.0; }, LineTokens::Assignment(_) => todo!(), LineTokens::If(_) => todo!(), LineTokens::While(_) => todo!(), LineTokens::Return(rt) => { if fid.is_main() { - let (code, location) = compile_evaluable(fid, rt.return_value(), None, &mut local_variables, global_table, function_calls); + let (code, location) = compile_evaluable(fid, rt.return_value(), None, &mut local_variables, global_table, function_calls)?; let location = location.unwrap(); contents += "\n"; contents += &code; @@ -93,7 +94,7 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia LineTokens::Break(_) => todo!(), LineTokens::NoOp(et) => { contents += "\n"; - contents += &compile_evaluable(fid, et, None, &mut local_variables, global_table, function_calls).0; + contents += &compile_evaluable(fid, et, None, &mut local_variables, global_table, function_calls)?.0; } } } diff --git a/src/root/compiler/local_variable_table.rs b/src/root/compiler/local_variable_table.rs index 7f1cb15..9b651a7 100644 --- a/src/root/compiler/local_variable_table.rs +++ b/src/root/compiler/local_variable_table.rs @@ -48,4 +48,8 @@ impl LocalVariableTable { None } } + + pub fn get_name(&self, name: &str) -> Option { + self.table.get(name).and_then(|a| Some(a.clone())) + } } \ No newline at end of file diff --git a/src/root/errors/evaluable_errors.rs b/src/root/errors/evaluable_errors.rs new file mode 100644 index 0000000..d0a5770 --- /dev/null +++ b/src/root/errors/evaluable_errors.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum EvaluableErrors { + #[error("Expected an indirection of {0} but found {1}")] + BadIndirection(usize, usize), +} diff --git a/src/root/errors/mod.rs b/src/root/errors/mod.rs index 07a7825..215d844 100644 --- a/src/root/errors/mod.rs +++ b/src/root/errors/mod.rs @@ -4,6 +4,7 @@ use crate::root::parser::parse::Location; pub mod parser_errors; pub mod name_resolver_errors; +pub mod evaluable_errors; pub struct WError { error: String, diff --git a/src/root/name_resolver/name_resolvers.rs b/src/root/name_resolver/name_resolvers.rs index a170ce7..21ba9d3 100644 --- a/src/root/name_resolver/name_resolvers.rs +++ b/src/root/name_resolver/name_resolvers.rs @@ -69,8 +69,7 @@ pub struct GlobalDefinitionTable { pub enum NameResult<'a> { Function(&'a FunctionSignature), Type(&'a dyn Type), - Variable(AddressedTypeRef, &'a dyn Type), - NotFound + Variable(AddressedTypeRef) } impl GlobalDefinitionTable { @@ -231,4 +230,12 @@ impl GlobalDefinitionTable { pub fn get_type(&self, type_id: TypeID) -> &Box { self.type_definitions.get(&type_id).as_ref().unwrap() } + + pub fn resolve_name(&mut self, name: &String, local_variable_table: &LocalVariableTable) -> Result { + if let Some(variable) = local_variable_table.get_name(name) { + return Ok(NameResult::Variable(variable)) + } + + todo!() + } } diff --git a/src/root/parser/parse_function/parse_literal.rs b/src/root/parser/parse_function/parse_literal.rs index 2e65172..cdbb843 100644 --- a/src/root/parser/parse_function/parse_literal.rs +++ b/src/root/parser/parse_function/parse_literal.rs @@ -20,13 +20,13 @@ pub enum LiteralTokens { } impl LiteralTokens { - pub fn default_type(&self) -> TypeRef { + pub fn default_type(&self) -> TypeID { match self { LiteralTokens::Bool(_) => { todo!() } LiteralTokens::Int(_) => { - TypeRef::new(IntType::id(), Indirection(0)) + IntType::id() } } } diff --git a/src/root/shared/common.rs b/src/root/shared/common.rs index 0bd533d..e8370a3 100644 --- a/src/root/shared/common.rs +++ b/src/root/shared/common.rs @@ -36,7 +36,7 @@ pub struct ByteSize(pub usize); #[display(fmt = "LocalAddress: {}", .0)] pub struct LocalAddress(pub isize); -#[derive(Getters, Clone)] +#[derive(Getters, Clone, PartialEq)] pub struct TypeRef { type_id: TypeID, indirection: Indirection