Skip to content

Commit

Permalink
Added some name resolving support
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-M-Lucas committed Jun 5, 2024
1 parent fdf1740 commit 7e3c4e6
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 34 deletions.
22 changes: 11 additions & 11 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions build/out.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Binary file modified build/out.o
Binary file not shown.
Binary file modified build/out.out
Binary file not shown.
5 changes: 3 additions & 2 deletions main.why
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
72 changes: 72 additions & 0 deletions src/root/compiler/assembly/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fmt::format;
use crate::root::shared::common::{ByteSize, FunctionID, LocalAddress};

pub fn get_function_tag(id: FunctionID) -> String {
Expand Down Expand Up @@ -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
}
48 changes: 38 additions & 10 deletions src/root/compiler/compile_evaluable.rs
Original file line number Diff line number Diff line change
@@ -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<AddressedTypeRef>, local_variables: &mut LocalVariableTable, global_table: &mut GlobalDefinitionTable, function_calls: &mut HashSet<FunctionID>) -> (String, Option<AddressedTypeRef>) {
pub fn compile_evaluable(
fid: FunctionID,
et: &EvaluableToken,
target: Option<AddressedTypeRef>,
local_variables: &mut LocalVariableTable,
global_table: &mut GlobalDefinitionTable,
function_calls: &mut HashSet<FunctionID>
) -> Result<(String, Option<AddressedTypeRef>), 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)
};

Expand All @@ -33,5 +61,5 @@ pub fn compile_evaluable(fid: FunctionID, et: &EvaluableToken, target: Option<Ad
EvaluableTokens::DynamicAccess(_, _) => todo!(),
EvaluableTokens::StaticAccess(_, _) => todo!(),
EvaluableTokens::FunctionCall(_, _, _) => todo!()
}
})
}
7 changes: 4 additions & 3 deletions src/root/compiler/compile_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/root/compiler/local_variable_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ impl LocalVariableTable {
None
}
}

pub fn get_name(&self, name: &str) -> Option<AddressedTypeRef> {
self.table.get(name).and_then(|a| Some(a.clone()))
}
}
7 changes: 7 additions & 0 deletions src/root/errors/evaluable_errors.rs
Original file line number Diff line number Diff line change
@@ -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),
}
1 change: 1 addition & 0 deletions src/root/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 9 additions & 2 deletions src/root/name_resolver/name_resolvers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -231,4 +230,12 @@ impl GlobalDefinitionTable {
pub fn get_type(&self, type_id: TypeID) -> &Box<dyn Type> {
self.type_definitions.get(&type_id).as_ref().unwrap()
}

pub fn resolve_name(&mut self, name: &String, local_variable_table: &LocalVariableTable) -> Result<NameResult, WError> {
if let Some(variable) = local_variable_table.get_name(name) {
return Ok(NameResult::Variable(variable))
}

todo!()
}
}
4 changes: 2 additions & 2 deletions src/root/parser/parse_function/parse_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/root/shared/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 7e3c4e6

Please sign in to comment.