Skip to content

Commit

Permalink
Added ability for first inline function to run
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-M-Lucas committed Jun 6, 2024
1 parent 3a23a23 commit d2c78a7
Show file tree
Hide file tree
Showing 18 changed files with 178 additions and 65 deletions.
21 changes: 16 additions & 5 deletions .idea/workspace.xml

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

20 changes: 14 additions & 6 deletions build/out.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
main:
push rbp
mov rbp, rsp
sub rsp, 32
sub rsp, 64
mov qword [rbp-8], 110
mov rax, qword [rbp-8]
mov qword [rbp-16], rax
mov qword [rbp-16], 100
mov qword [rbp-24], 100
mov rax, qword [rbp-16]
mov qword [rbp-24], rax
mov rax, qword [rbp-24]
add rax, qword [rbp-24]
mov qword [rbp-8], rax
mov rax, qword [rbp-8]
mov qword [rbp-40], rax
mov qword [rbp-48], 10
mov rax, qword [rbp-40]
add rax, qword [rbp-48]
mov qword [rbp-32], rax
mov rax, qword [rbp-32]
mov qword [rbp-56], rax
mov rax, qword [rbp-56]
leave
ret
Binary file modified build/out.o
Binary file not shown.
Binary file modified build/out.out
Binary file not shown.
2 changes: 1 addition & 1 deletion main.why
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ struct A {

fn main() -> int {
let a: int = 100 + 100;
let b: int = a;
let b: int = a + 10;
return b;
}
6 changes: 5 additions & 1 deletion src/root/builtin/int/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::root::shared::common::{AddressedTypeRef, ByteSize, FunctionID, LocalA
use crate::root::shared::types::Type;

pub fn register_int(global_table: &mut GlobalDefinitionTable) {
global_table.register_builtin_type("int".to_string(), b!(IntType{}));
global_table.register_builtin_type(b!(IntType{}));
global_table.register_inline_function(&IntAdd{});
}

Expand All @@ -31,6 +31,10 @@ impl Type for IntType {
ByteSize(8)
}

fn name(&self) -> &str {
"int"
}

fn instantiate_from_literal(&self, location: &LocalAddress, literal: &LiteralToken) -> Result<String, WErr> {
Ok(match literal.literal() {
LiteralTokens::Bool(value) => {
Expand Down
5 changes: 4 additions & 1 deletion src/root/compiler/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ pub fn compile(mut global_table: GlobalDefinitionTable, unprocessed_functions: H
let current_function = *open_set.iter().next().unwrap();
open_set.remove(&current_function);

let current_function_token = unprocessed_functions.remove(&current_function).unwrap();
let Some(current_function_token) = unprocessed_functions.remove(&current_function)
else {
continue; // Inline function
};

let (compiled, called_functions) = compile_function(current_function, current_function_token, &mut global_table)?;
compiled_len += compiled.len() + 10;
Expand Down
50 changes: 48 additions & 2 deletions src/root/compiler/compile_evaluable.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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::errors::evaluable_errors::EvalErrs;
use crate::root::errors::evaluable_errors::EvalErrs::{OpNoReturn, OpWrongReturnType};
use crate::root::errors::name_resolver_errors::NRErrors;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResult};
use crate::root::parser::parse_function::parse_evaluable::{EvaluableToken, EvaluableTokens};
use crate::root::parser::parse_function::parse_operator::get_method_name;
use crate::root::shared::common::{FunctionID, Indirection, TypeRef};
use crate::root::shared::common::AddressedTypeRef;

Expand Down Expand Up @@ -85,7 +86,52 @@ pub fn compile_evaluable_into(

t.instantiate_from_literal(target.local_address(), literal)?
}
EvaluableTokens::InfixOperator(lhs, op, rhs) => todo!(),
EvaluableTokens::InfixOperator(lhs, op, rhs) => {
if op.is_prefix_opt_t() {
return Err(WErr::n(EvalErrs::FoundPrefixNotInfixOp(op.operator().to_str().to_string()), op.location().clone()));
}

let (mut code, lhs) = compile_evaluable(fid, lhs, local_variables, global_table, function_calls)?;
code += "\n";
let op_fn = global_table.get_operator_function(*lhs.type_ref().type_id(), op)?;
let signature = global_table.get_function_signature(op_fn);

if signature.args().len() != 2 {
return Err(
WErr::n(
EvalErrs::OpWrongArgumentCount(
op.operator().to_str().to_string(),
global_table.get_type(*lhs.type_ref().type_id()).name().to_string(),
op.operator().get_method_name().to_string(),
signature.args().len()
),
op.location().clone()
)
);
}

match signature.return_type() {
None => {
return Err(WErr::n(OpNoReturn(global_table.get_type_name(target.type_ref())), op.location().clone()))
}
Some(rt) => {
if rt != target.type_ref() {
return Err(WErr::n(OpWrongReturnType(global_table.get_type_name(target.type_ref()), global_table.get_type_name(rt)), op.location().clone()))
}
}
}

let rhs_type_target = signature.args()[1].1.clone();
let rhs_box = global_table.add_local_variable_unnamed_base(rhs_type_target, local_variables);
code += &compile_evaluable_into(fid, rhs, rhs_box.clone(), local_variables, global_table, function_calls)?;
code += "\n";

code += &global_table.call_function(op_fn, &[*lhs.local_address(), *rhs_box.local_address()], Some(*target.local_address()))?;

function_calls.insert(op_fn);

code
},
EvaluableTokens::PrefixOperator(_, _) => todo!(),
EvaluableTokens::DynamicAccess(_, _) => todo!(), // Accessed methods must be called
EvaluableTokens::StaticAccess(_, n) => return Err(WErr::n(NRErrors::CannotFindConstantAttribute(n.name().clone()), n.location().clone())), // Accessed methods must be called
Expand Down
8 changes: 8 additions & 0 deletions src/root/errors/evaluable_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,12 @@ pub enum EvalErrs {
FunctionMustBeCalled(String),
#[error("Cannot evaluate a standalone type ({0})")]
CannotEvalStandaloneType(String),
#[error("Operator ({0}) can only be used as a prefix operator, not infix")]
FoundPrefixNotInfixOp(String),
#[error("Infix operator ({0}) can only be used for type ({1}) if method ({2}) accepting 2 arguments is implemented for ({1}). ({2}) implementation only accepts ({3}) arguments")]
OpWrongArgumentCount(String, String, String, usize),
#[error("Expected operation to return type ({0}) but found ({1})")]
OpWrongReturnType(String, String),
#[error("Expected operation to return type ({0}) but found no return")]
OpNoReturn(String)
}
4 changes: 3 additions & 1 deletion src/root/errors/name_resolver_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ pub enum NRErrors {
#[error("Cannot find name ({0})")]
CannotFindName(String),
#[error("Cannot find constant attribute ({0})")]
CannotFindConstantAttribute(String)
CannotFindConstantAttribute(String),
#[error("Method ({0}) not implemented for type ({1}) required for operator ({2})")]
OpMethodNotImplemented(String, String, String)
}
4 changes: 2 additions & 2 deletions src/root/errors/parser_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use thiserror::Error;

#[derive(Error, Debug)]
pub enum ParseError {
// #[error("Names cannot contain character '{0}' (UTF-8 Code: {1:?})")]
// BadName(char, Vec<u8>),
#[error("Parser Error (rich parser errors have not been implemented yet)")]
ParserErrorsNotImplemented
}
20 changes: 17 additions & 3 deletions src/root/name_resolver/name_resolvers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::root::parser::parse::Location;
use crate::root::shared::types::Type;
use crate::root::parser::parse_function::FunctionToken;
use crate::root::parser::parse_function::parse_evaluable::{FullNameToken, FullNameTokens, FullNameWithIndirectionToken};
use crate::root::parser::parse_function::parse_operator::OperatorToken;
use crate::root::parser::parse_function::parse_operator::{OperatorToken};
use crate::root::parser::parse_name::SimpleNameToken;
use crate::root::parser::parse_struct::StructToken;
use crate::root::POINTER_SIZE;
Expand Down Expand Up @@ -90,10 +90,10 @@ impl GlobalDefinitionTable {
builtin_function_name_table: Default::default(),
}
}
pub fn register_builtin_type(&mut self, name: String, t: Box<dyn Type>) {
pub fn register_builtin_type(&mut self, t: Box<dyn Type>) {
let id = t.id();
self.builtin_type_name_table.insert(t.name().to_string(), id);
self.type_definitions.insert(id, t);
self.builtin_type_name_table.insert(name, id);
}

// pub fn register_builtin_function(&mut self, name: String, t: FunctionSignature, id: FunctionID) {
Expand Down Expand Up @@ -260,6 +260,10 @@ impl GlobalDefinitionTable {
self.type_definitions.get(&type_id).as_ref().unwrap()
}

pub fn get_type_name(&self, type_ref: &TypeRef) -> String {
format!("{:&^1$}", self.get_type(*type_ref.type_id()).name(), type_ref.indirection().0)
}

pub fn resolve_name(&mut self, name: &SimpleNameToken, containing_class: Option<&SimpleNameToken>, local_variable_table: &LocalVariableTable) -> Result<NameResult, WErr> {
if let Some(variable) = local_variable_table.get_name(name.name()) {
return Ok(NameResult::Variable(variable))
Expand Down Expand Up @@ -298,6 +302,16 @@ impl GlobalDefinitionTable {
Err(WErr::n(NRErrors::CannotFindName(name.name().clone()), name.location().clone()))
}

pub fn get_operator_function(&self, lhs: TypeID, operator: &OperatorToken) -> Result<FunctionID, WErr> {
let op_name = operator.operator().get_method_name();
self.impl_definitions.get(&lhs).and_then(|f| f.get(op_name)).ok_or(
WErr::n(
NRErrors::OpMethodNotImplemented(op_name.to_string(), self.get_type(lhs).name().to_string(), operator.operator().to_str().to_string()),
operator.location().clone()
)
).copied()
}

pub fn call_function(&self, function: FunctionID, arguments: &[LocalAddress], return_address: Option<LocalAddress>) -> Result<String, WErr> {
if let Some(inline) = self.inline_functions.get(&function) {
return Ok(inline(arguments, return_address));
Expand Down
13 changes: 9 additions & 4 deletions src/root/name_resolver/resolve_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ use crate::root::shared::types::Type;
#[derive(Getters)]
pub struct UserType {
id: TypeID,
name: String,
size: ByteSize,
attributes: Vec<(usize, SimpleNameToken, TypeRef)>,
location: Location
}

impl UserType {
pub fn new(id: TypeID, size: ByteSize, attributes: Vec<(usize, SimpleNameToken, TypeRef)>, location: Location) -> UserType {
UserType { id, size, attributes, location }
pub fn new(id: TypeID, name: String, size: ByteSize, attributes: Vec<(usize, SimpleNameToken, TypeRef)>, location: Location) -> UserType {
UserType { id, name, size, attributes, location }
}
}

Expand All @@ -44,6 +45,10 @@ impl Type for UserType {
self.size
}

fn name(&self) -> &str {
&self.name
}

fn instantiate_from_literal(&self, location: &LocalAddress, literal: &LiteralToken) -> Result<String, WErr> {
todo!()
}
Expand Down Expand Up @@ -77,7 +82,7 @@ pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefiniti
for symbol in ast {
match symbol {
TopLevelTokens::Struct(st) => {
let (location, _, attributes, id) = st.dissolve();
let (location, name, attributes, id) = st.dissolve();
let id = id.unwrap();

let mut p_attributes: Vec<(SimpleNameToken, TypeRef)> = Vec::new();
Expand All @@ -91,7 +96,7 @@ pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefiniti
}
p_attributes.push((name, type_ref))
}
unsized_final_types.insert(id, UnsizedUserType::new(id, p_attributes, location));
unsized_final_types.insert(id, UnsizedUserType::new(id, name.take_name(), p_attributes, location));
}
TopLevelTokens::Impl(it) => {
let (location, name, functions) = it.dissolve();
Expand Down
9 changes: 5 additions & 4 deletions src/root/name_resolver/resolve_type_sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ use crate::root::shared::common::{ByteSize, TypeID};
#[derive(Dissolve)]
pub struct UnsizedUserType {
id: TypeID,
name: String,
attributes: Vec<(SimpleNameToken, TypeRef)>,
location: Location
}

impl UnsizedUserType {
pub fn new(id: TypeID, attributes: Vec<(SimpleNameToken, TypeRef)>, location: Location) -> UnsizedUserType {
UnsizedUserType { id, attributes, location }
pub fn new(id: TypeID, name: String, attributes: Vec<(SimpleNameToken, TypeRef)>, location: Location) -> UnsizedUserType {
UnsizedUserType { id, name, attributes, location }
}
}

Expand All @@ -28,7 +29,7 @@ pub fn resolve_type_sizes(
global_table: &GlobalDefinitionTable,
path: &mut Vec<TypeID>
) -> ByteSize {
let (id, attributes, location) = unsized_type.dissolve();
let (id, name, attributes, location) = unsized_type.dissolve();

if path.contains(&id) {
// TODO: Circular type def error
Expand Down Expand Up @@ -60,7 +61,7 @@ pub fn resolve_type_sizes(
processed_attributes.push((offset.0, attribute_name, attribute_type));
}

final_types.insert(id, UserType::new(id, size, processed_attributes, location));
final_types.insert(id, UserType::new(id, name, size, processed_attributes, location));

size
}
6 changes: 5 additions & 1 deletion src/root/parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::rc::Rc;
use color_print::cformat;
use derive_getters::Getters;
use lazy_static::lazy_static;
use crate::root::errors::parser_errors::ParseError;
use crate::root::errors::WErr;
use crate::root::parser::parse_toplevel::TopLevelTokens;

Expand Down Expand Up @@ -152,7 +153,10 @@ pub fn parse(path: PathBuf) -> Result<Vec<TopLevelTokens>, WErr> {

let (remaining, output) = match parse_toplevel::parse_toplevel(base) {
Ok(v) => v,
Err(_) => todo!()
Err(_) => {
// TODO:
return Err(WErr::n(ParseError::ParserErrorsNotImplemented, Location::builtin()));
}
};
debug_assert!(remaining.is_empty());

Expand Down
Loading

0 comments on commit d2c78a7

Please sign in to comment.