diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/out.out b/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/out.out
deleted file mode 100644
index 9bc1f10..0000000
Binary files a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/out.out and /dev/null differ
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/shelved.patch
deleted file mode 100644
index 1320d35..0000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06_[Changes]/shelved.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-Index: .idea/workspace.xml
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+>\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n "lastFilter": {\r\n "state": "OPEN",\r\n "assignee": "Robert-M-Lucas"\r\n }\r\n}\r\n \r\n \r\n \r\n {\r\n "selectedUrlAndAccountId": {\r\n "url": "https://github.com/Robert-M-Lucas/whython-8.git",\r\n "accountId": "dcb8df19-0b39-47e1-9073-4a54f7034be8"\r\n }\r\n}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n "customColor": "",\r\n "associatedIndex": 4\r\n}\r\n \r\n \r\n \r\n \r\n \r\n {\r\n "keyToString": {\r\n "Cargo.Run whython-8.executor": "Run",\r\n "RunOnceActivity.OpenProjectViewOnStart": "true",\r\n "RunOnceActivity.ShowReadmeOnStart": "true",\r\n "RunOnceActivity.rust.reset.selective.auto.import": "true",\r\n "git-widget-placeholder": "master",\r\n "ignore.virus.scanning.warn.message": "true",\r\n "node.js.detected.package.eslint": "true",\r\n "node.js.detected.package.tslint": "true",\r\n "node.js.selected.package.eslint": "(autodetect)",\r\n "node.js.selected.package.tslint": "(autodetect)",\r\n "nodejs_package_manager_path": "npm",\r\n "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",\r\n "org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",\r\n "org.rust.first.attach.projects": "true",\r\n "settings.editor.selected.configurable": "reference.settingsdialog.IDE.editor.colors.Rust",\r\n "vue.rearranger.settings.migration": "true"\r\n }\r\n}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n 1714088144106\r\n \r\n \r\n 1714088144106\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n 1714089790504\r\n \r\n \r\n \r\n 1714089790504\r\n \r\n \r\n \r\n 1717349672242\r\n \r\n \r\n \r\n 1717349672242\r\n \r\n \r\n \r\n 1717355914137\r\n \r\n \r\n \r\n 1717355914137\r\n \r\n \r\n \r\n 1717432257327\r\n \r\n \r\n \r\n 1717432257327\r\n \r\n \r\n \r\n 1717432916642\r\n \r\n \r\n \r\n 1717432916642\r\n \r\n \r\n \r\n 1717434442792\r\n \r\n \r\n \r\n 1717434442792\r\n \r\n \r\n \r\n 1717469659146\r\n \r\n \r\n \r\n 1717469659146\r\n \r\n \r\n \r\n 1717473113692\r\n \r\n \r\n \r\n 1717473113692\r\n \r\n \r\n \r\n 1717473365560\r\n \r\n \r\n \r\n 1717473365560\r\n \r\n \r\n \r\n 1717562697947\r\n \r\n \r\n \r\n 1717562697947\r\n \r\n \r\n \r\n 1717570846946\r\n \r\n \r\n \r\n 1717570846946\r\n \r\n \r\n \r\n 1717572031837\r\n \r\n \r\n \r\n 1717572031837\r\n \r\n \r\n \r\n 1717578308406\r\n \r\n \r\n \r\n 1717578308406\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
-diff --git a/.idea/workspace.xml b/.idea/workspace.xml
---- a/.idea/workspace.xml (revision 7e3c4e6d6236a3bdf2d652af761c73daacd043c2)
-+++ b/.idea/workspace.xml (date 1718644000241)
-@@ -7,7 +7,11 @@
-
-
-
--
-+
-+
-+
-+
-+
-
-
-
-@@ -34,7 +38,7 @@
-
- {
- "selectedUrlAndAccountId": {
-- "url": "https://github.com/Robert-M-Lucas/whython-8.git",
-+ "url": "https://github.com/Robert-M-Lucas/whython-8",
- "accountId": "dcb8df19-0b39-47e1-9073-4a54f7034be8"
- }
- }
-@@ -140,6 +144,8 @@
-
-
-
-+
-+
-
-
-
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06__Changes_.xml
deleted file mode 100644
index 80901e1..0000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_17_06_2024_18_06__Changes_.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index e83ccea..1b73510 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -8,13 +8,18 @@
+
+
+
-
-
-
+
+
+
+
+
@@ -40,12 +45,12 @@
- {
+ "selectedUrlAndAccountId": {
+ "url": "https://github.com/Robert-M-Lucas/whython-8.git",
+ "accountId": "dcb8df19-0b39-47e1-9073-4a54f7034be8"
}
-}]]>
+}
@@ -216,6 +221,7 @@
+
diff --git a/build/out.asm b/build/out.asm
index e105f69..44a5803 100644
--- a/build/out.asm
+++ b/build/out.asm
@@ -2,17 +2,6 @@
section .text
-_2:
- push rbp
- mov rbp, rsp
- mov qword [rbp-8], 1
- mov rax, rbp
- add rax, -8
- mov qword [rbp+16], rax
- leave
- ret
-
-
main:
push rbp
mov rbp, rsp
@@ -44,5 +33,16 @@ main:
ret
+_2:
+ push rbp
+ mov rbp, rsp
+ mov qword [rbp-8], 1
+ mov rax, rbp
+ add rax, -8
+ mov qword [rbp+16], rax
+ leave
+ ret
+
+
section .data_readonly
__8_fstr db `Integer: %ld\n`,0
\ No newline at end of file
diff --git a/build/out.o b/build/out.o
index c2a33bb..bc35102 100644
Binary files a/build/out.o and b/build/out.o differ
diff --git a/build/out.out b/build/out.out
index 32edf1b..1f543f6 100755
Binary files a/build/out.out and b/build/out.out differ
diff --git a/src/root/assembler/assembly_builder.rs b/src/root/assembler/assembly_builder.rs
index 9ccd856..67774a8 100644
--- a/src/root/assembler/assembly_builder.rs
+++ b/src/root/assembler/assembly_builder.rs
@@ -1,4 +1,6 @@
+/// A helper for correctly formatting strings for assembly.
+/// Will have no preceding newline and a trailing newline.
pub struct AssemblyBuilder {
inner: String
}
@@ -14,21 +16,26 @@ impl AssemblyBuilder {
AssemblyBuilder { inner: String::new() }
}
+ /// Adds a single, indented line with a trailing newline
pub fn line(&mut self, line: &str) {
self.inner += " ";
self.inner += line;
self.inner.push('\n');
}
+ /// Adds a single, non-indented line with a trailing newline
pub fn toplevel(&mut self, line: &str) {
self.inner += line;
self.inner.push('\n');
}
+ /// Adds the output from another `AssemblyBuilder`.
+ /// Adds no indentation and assumes `other` has its own trailing newline
pub fn other(&mut self, other: &str) {
self.inner += other;
}
+ /// Returns the internal string - no preceding newline with a trailing newline
pub fn finish(self) -> String {
self.inner
}
diff --git a/src/root/builtin/core/mod.rs b/src/root/builtin/core/mod.rs
new file mode 100644
index 0000000..6ade159
--- /dev/null
+++ b/src/root/builtin/core/mod.rs
@@ -0,0 +1 @@
+pub mod referencing;
\ No newline at end of file
diff --git a/src/root/builtin/core/referencing.rs b/src/root/builtin/core/referencing.rs
new file mode 100644
index 0000000..ad06bea
--- /dev/null
+++ b/src/root/builtin/core/referencing.rs
@@ -0,0 +1,27 @@
+use crate::root::compiler::assembly::utils::copy_from_indirect;
+use crate::root::errors::evaluable_errors::EvalErrs::{ExpectedDifferentType, OpWrongReturnType};
+use crate::root::errors::WErr;
+use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
+use crate::root::parser::parse::Location;
+use crate::root::shared::common::AddressedTypeRef;
+
+/// Sets `into` to the address of `to_ref`
+pub fn set_reference(location: &Location, to_ref: AddressedTypeRef, into: AddressedTypeRef, global_table: &GlobalDefinitionTable) -> Result {
+ let new_type = to_ref.type_ref().type_id().with_indirection(to_ref.type_ref().indirection().0 + 1);
+ if new_type != *into.type_ref() {
+ return WErr::ne(OpWrongReturnType(global_table.get_type_name(into.type_ref()), global_table.get_type_name(&new_type)), location.clone());
+ }
+
+ Ok(format!(" mov rax, rbp
+ add rax, {}
+ mov qword {}, rax\n", to_ref.local_address().0, into.local_address()))
+}
+
+/// Sets `into` to the value pointed to by `to_deref`
+pub fn set_deref(location: &Location, to_deref: AddressedTypeRef, into: AddressedTypeRef, global_table: &mut GlobalDefinitionTable) -> Result {
+ let expected = into.type_ref().plus_one_indirect();
+ if to_deref.type_ref() != &expected {
+ return WErr::ne(ExpectedDifferentType(global_table.get_type_name(&expected), global_table.get_type_name(to_deref.type_ref())), location.clone());
+ }
+ Ok(copy_from_indirect(*to_deref.local_address(), *into.local_address(), global_table.get_size(into.type_ref())))
+}
\ No newline at end of file
diff --git a/src/root/builtin/mod.rs b/src/root/builtin/mod.rs
index c48ea25..59ac4fa 100644
--- a/src/root/builtin/mod.rs
+++ b/src/root/builtin/mod.rs
@@ -1,5 +1,7 @@
pub mod types;
pub mod functions;
+pub mod core;
+mod core;
use crate::root::builtin::functions::register_functions;
use crate::root::builtin::types::bool::register_bool;
@@ -9,22 +11,27 @@ use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable};
use crate::root::name_resolver::resolve_function_signatures::FunctionSignature;
use crate::root::shared::common::{ByteSize, FunctionID, LocalAddress, TypeID};
+/// Registers all the builtin types and their relevant functions
pub fn register_builtin(global_table: &mut GlobalDefinitionTable) {
register_functions(global_table);
register_int(global_table);
register_bool(global_table);
}
+/// Function that takes context and generates inline assembly to be used within a functions
pub type InlineFunctionGenerator = fn(&[LocalAddress], Option, &mut GlobalTracker, ByteSize) -> String;
+/// Converts a u16 unique ID to a non-zero, negative `FunctionID`
const fn f_id(id: u16) -> FunctionID {
FunctionID(-(id as isize) - 1)
}
+/// Converts a u16 unique ID to a non-zero, negative `FunctionID`
const fn t_id(id: u16) -> TypeID {
TypeID(-(id as isize) - 1)
}
+/// Trait for a 'function' implemented as inline assembly
pub trait BuiltinInlineFunction {
fn id(&self) -> FunctionID;
fn name(&self) -> &'static str;
diff --git a/src/root/builtin/types/int/mod.rs b/src/root/builtin/types/int/mod.rs
index 259e7c1..fe10bbd 100644
--- a/src/root/builtin/types/int/mod.rs
+++ b/src/root/builtin/types/int/mod.rs
@@ -12,7 +12,7 @@ use crate::root::builtin::types::int::p_add::IntPAdd;
use crate::root::builtin::types::int::p_sub::{IntAsSub, IntPSub};
use crate::root::builtin::types::int::printi::PrintI;
use crate::root::builtin::types::int::sub::IntSub;
-use crate::root::compiler::compiler_errors::CError;
+use crate::root::compiler::compiler_errors::CErrs;
use crate::root::errors::evaluable_errors::EvalErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
@@ -95,10 +95,10 @@ impl Type for IntType {
}
LiteralTokens::Int(value) => {
if *value > i64::MAX as i128 {
- return WErr::ne(CError::IntLiteralExceedsMax(*value, i64::MAX as i128), literal.location().clone());
+ return WErr::ne(CErrs::IntLiteralExceedsMax(*value, i64::MAX as i128), literal.location().clone());
}
if *value < i64::MIN as i128 {
- return WErr::ne(CError::IntLiteralBelowMin(*value, i64::MAX as i128), literal.location().clone());
+ return WErr::ne(CErrs::IntLiteralBelowMin(*value, i64::MAX as i128), literal.location().clone());
}
let value = *value as i64;
diff --git a/src/root/compiler/assembly/utils.rs b/src/root/compiler/assembly/utils.rs
index cc8eccf..8053490 100644
--- a/src/root/compiler/assembly/utils.rs
+++ b/src/root/compiler/assembly/utils.rs
@@ -16,6 +16,7 @@ use crate::root::shared::common::{ByteSize, LocalAddress};
// }
// }
+/// Align a number of bytes to the next multiple of 16
pub fn align_16_bytes(bytes: ByteSize) -> ByteSize {
let bytes = bytes.0;
if bytes % 16 == 0 {
@@ -25,6 +26,7 @@ pub fn align_16_bytes(bytes: ByteSize) -> ByteSize {
}
}
+/// Align a number of bytes to the next multiple of 16 + 8
pub fn align_16_bytes_plus_8(bytes: ByteSize) -> ByteSize {
let bytes = bytes.0;
if bytes % 16 == 8 {
@@ -74,6 +76,8 @@ pub fn align_16_bytes_plus_8(bytes: ByteSize) -> ByteSize {
// }
// }
+/// Copies data. Expects `from` to be the address of a pointer pointing to the data to move
+/// and `to` to be the target
pub fn copy_from_indirect(from: LocalAddress, to: LocalAddress, amount: ByteSize) -> String {
if amount == ByteSize(0) { return String::new(); }
@@ -113,6 +117,8 @@ pub fn copy_from_indirect(from: LocalAddress, to: LocalAddress, amount: ByteSize
output.finish()
}
+/// Copies data. Expects `from` to be the address of the data to move
+/// and `to` to be a pointer to the target
pub fn copy_to_indirect(from: LocalAddress, to: LocalAddress, amount: ByteSize) -> String {
if amount == ByteSize(0) { return String::new(); }
@@ -152,6 +158,8 @@ pub fn copy_to_indirect(from: LocalAddress, to: LocalAddress, amount: ByteSize)
output.finish()
}
+/// Copies data. Expects `from` to be the address of the data to move
+/// and `to` to be the target
pub fn copy(from: LocalAddress, to: LocalAddress, amount: ByteSize) -> String {
if amount == ByteSize(0) { return String::new(); }
diff --git a/src/root/compiler/compile.rs b/src/root/compiler/compile.rs
index da01c20..47a3def 100644
--- a/src/root/compiler/compile.rs
+++ b/src/root/compiler/compile.rs
@@ -6,6 +6,7 @@ use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::parser::parse_function::FunctionToken;
use crate::root::shared::common::FunctionID;
+/// Compiles the entire program. Returns assembly.
pub fn compile(mut global_table: GlobalDefinitionTable, unprocessed_functions: HashMap) -> Result {
let mut unprocessed_functions = unprocessed_functions;
let mut compiled_functions = HashMap::new();
diff --git a/src/root/compiler/compile_evaluable.rs b/src/root/compiler/compile_evaluable.rs
index 13c61e7..ec9a41f 100644
--- a/src/root/compiler/compile_evaluable.rs
+++ b/src/root/compiler/compile_evaluable.rs
@@ -1,13 +1,14 @@
use std::any::Any;
use either::{Left, Right};
use itertools::Itertools;
+use crate::root::builtin::core::referencing::{set_deref, set_reference};
use crate::root::compiler::assembly::utils::{copy, copy_from_indirect, copy_to_indirect};
use crate::root::compiler::compile_function_call::call_function;
use crate::root::compiler::global_tracker::GlobalTracker;
use crate::root::compiler::local_variable_table::LocalVariableTable;
use crate::root::errors::evaluable_errors::EvalErrs;
use crate::root::errors::evaluable_errors::EvalErrs::{ExpectedDifferentType, ExpectedFunctionName, ExpectedNotNone, ExpectedReference, ExpectedType, OpNoReturn, OpWrongReturnType};
-use crate::root::errors::name_resolver_errors::NRErrors;
+use crate::root::errors::name_resolver_errors::NRErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResult};
use crate::root::parser::parse::Location;
@@ -16,30 +17,12 @@ use crate::root::parser::parse_function::parse_operator::{OperatorTokens, Prefix
use crate::root::shared::common::{FunctionID, Indirection, TypeRef};
use crate::root::shared::common::AddressedTypeRef;
+/// Error on an empty address
fn expect_addr(r: (String, Option)) -> Result<(String, AddressedTypeRef), WErr> {
Ok((r.0, r.1.unwrap())) // TODO
}
-pub fn set_reference(location: &Location, to_ref: AddressedTypeRef, into: AddressedTypeRef, global_table: &GlobalDefinitionTable) -> Result {
- let new_type = to_ref.type_ref().type_id().with_indirection(to_ref.type_ref().indirection().0 + 1);
- if new_type != *into.type_ref() {
- return WErr::ne(OpWrongReturnType(global_table.get_type_name(into.type_ref()), global_table.get_type_name(&new_type)), location.clone());
- }
-
- Ok(format!(" mov rax, rbp
- add rax, {}
- mov qword {}, rax\n", to_ref.local_address().0, into.local_address()))
-}
-
-pub fn set_deref(location: &Location, to_deref: AddressedTypeRef, into: AddressedTypeRef, global_table: &mut GlobalDefinitionTable) -> Result {
- let expected = into.type_ref().plus_one_indirect();
- if to_deref.type_ref() != &expected {
- return WErr::ne(ExpectedDifferentType(global_table.get_type_name(&expected), global_table.get_type_name(to_deref.type_ref())), location.clone());
- }
- Ok(copy_from_indirect(*to_deref.local_address(), *into.local_address(), global_table.get_size(into.type_ref())))
-}
-
-/// Will always evaluate into new address
+/// Evaluates `et` into a new address
pub fn compile_evaluable(
fid: FunctionID,
et: &EvaluableToken,
@@ -165,7 +148,7 @@ pub fn compile_evaluable(
(c, return_into)
},
EvaluableTokens::DynamicAccess(_, _) => todo!(), // Accessed methods must be called
- EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrors::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
+ EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrs::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
EvaluableTokens::FunctionCall(inner, args) => {
let (slf, ifid, name) = compile_evaluable_function_only(fid, inner, local_variables, global_table, global_tracker)?;
@@ -193,7 +176,7 @@ pub fn compile_evaluable(
}
-/// Will always put result into target
+/// Evaluates `et` putting the result into `target`
pub fn compile_evaluable_into(
fid: FunctionID,
et: &EvaluableToken,
@@ -327,7 +310,7 @@ pub fn compile_evaluable_into(
c
},
EvaluableTokens::DynamicAccess(_, _) => todo!(), // Accessed methods must be called
- EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrors::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
+ EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrs::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
EvaluableTokens::FunctionCall(inner, args) => {
let (slf, ifid, name) = compile_evaluable_function_only(fid, inner, local_variables, global_table, global_tracker)?;
@@ -351,7 +334,7 @@ pub fn compile_evaluable_into(
})
}
-/// Will try to return a reference i.e. not allocate stack
+/// Evaluates `et` attempting to return a reference to an existing variable as opposed to allocating
pub fn compile_evaluable_reference(
fid: FunctionID,
et: &EvaluableToken,
@@ -376,7 +359,7 @@ pub fn compile_evaluable_reference(
EvaluableTokens::InfixOperator(_, _, _) => compile_evaluable(fid, et, local_variables, global_table, global_tracker)?,
EvaluableTokens::PrefixOperator(_, _) => compile_evaluable(fid, et, local_variables, global_table, global_tracker)?,
EvaluableTokens::DynamicAccess(_, _) => todo!(), // Accessed methods must be called
- EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrors::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
+ EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrs::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
EvaluableTokens::FunctionCall(_, _) => compile_evaluable(fid, et, local_variables, global_table, global_tracker)?,
EvaluableTokens::None => {
(String::new(), None)
@@ -384,7 +367,7 @@ pub fn compile_evaluable_reference(
})
}
-/// Will always return a function pointer (and self)
+/// Evaluates `name` into a `FunctionID`
pub fn compile_evaluable_function_only(
fid: FunctionID,
name: &EvaluableToken,
@@ -405,7 +388,7 @@ pub fn compile_evaluable_function_only(
})
}
-/// Will ignore everything other than type
+/// Evaluates the type `et` evaluates to. Does not generate any assembly.
pub fn compile_evaluable_type_only(
fid: FunctionID,
et: &EvaluableToken,
@@ -465,7 +448,7 @@ pub fn compile_evaluable_type_only(
signature.get().return_type().as_ref().unwrap().clone()
},
EvaluableTokens::DynamicAccess(_, _) => todo!(), // Accessed methods must be called
- EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrors::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
+ EvaluableTokens::StaticAccess(_, n) => return WErr::ne(NRErrs::CannotFindConstantAttribute(n.name().clone()), n.location().clone()), // Accessed methods must be called
EvaluableTokens::FunctionCall(inner, args) => {
let (slf, ifid, _) = compile_evaluable_function_only(fid, inner, local_variables, global_table, global_tracker)?;
@@ -480,16 +463,16 @@ pub fn compile_evaluable_type_only(
}
/// Will ignore everything other than type with a target type
-pub fn compile_evaluable_type_only_into(
- fid: FunctionID,
- et: &EvaluableToken,
- target: TypeRef,
- local_variables: &mut LocalVariableTable,
- global_table: &mut GlobalDefinitionTable,
- global_tracker: &mut GlobalTracker
-) -> Result {
-
- let et = et.token();
-
- todo!()
-}
\ No newline at end of file
+// pub fn compile_evaluable_type_only_into(
+// fid: FunctionID,
+// et: &EvaluableToken,
+// target: TypeRef,
+// local_variables: &mut LocalVariableTable,
+// global_table: &mut GlobalDefinitionTable,
+// global_tracker: &mut GlobalTracker
+// ) -> Result {
+//
+// let et = et.token();
+//
+// todo!()
+// }
\ No newline at end of file
diff --git a/src/root/compiler/compile_function.rs b/src/root/compiler/compile_function.rs
index 68469fd..0449fb2 100644
--- a/src/root/compiler/compile_function.rs
+++ b/src/root/compiler/compile_function.rs
@@ -2,7 +2,7 @@ use crate::root::assembler::assembly_builder::AssemblyBuilder;
use crate::root::builtin::types::bool::BoolType;
use crate::root::builtin::types::int::IntType;
use crate::root::compiler::compile_evaluable::{compile_evaluable_into, compile_evaluable_reference};
-use crate::root::compiler::compiler_errors::CError::{CannotBreak, ExpectedNoReturn, ExpectedReturn, ExpectedReturnType, ExpectedSomeReturn};
+use crate::root::compiler::compiler_errors::CErrs::{CannotBreak, ExpectedNoReturn, ExpectedReturn, ExpectedReturnType, ExpectedSomeReturn};
use crate::root::compiler::global_tracker::GlobalTracker;
use crate::root::compiler::local_variable_table::LocalVariableTable;
use crate::root::errors::WErr;
@@ -13,6 +13,7 @@ use crate::root::shared::common::{FunctionID, Indirection, LocalAddress, TypeRef
use crate::root::shared::common::AddressedTypeRef;
use crate::root::utils::warn;
+/// Compiles a given function into assembly
pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table: &mut GlobalDefinitionTable, global_tracker: &mut GlobalTracker) -> Result {
let mut local_variables = LocalVariableTable::new();
@@ -70,8 +71,9 @@ pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table:
Ok(final_contents)
}
+/// Recursively compiles lines provided to it e.g. function body, while body, etc. Returns assembly
fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_variable: &Option, break_tag: &Option<&str>, local_variables: &mut LocalVariableTable, global_table: &mut GlobalDefinitionTable, global_tracker: &mut GlobalTracker) -> Result<(String, bool), WErr> {
- local_variables.enter_block();
+ local_variables.enter_scope();
let mut contents = AssemblyBuilder::new();
let mut last_is_return = false;
@@ -191,7 +193,7 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia
}
}
- local_variables.leave_block();
+ local_variables.leave_scope();
Ok((contents.finish(), last_is_return))
}
\ No newline at end of file
diff --git a/src/root/compiler/compile_function_call.rs b/src/root/compiler/compile_function_call.rs
index e9f7910..25e33ee 100644
--- a/src/root/compiler/compile_function_call.rs
+++ b/src/root/compiler/compile_function_call.rs
@@ -3,7 +3,7 @@ use itertools::Itertools;
use crate::root::assembler::assembly_builder::AssemblyBuilder;
use crate::root::compiler::assembly::utils::{align_16_bytes, align_16_bytes_plus_8, copy};
use crate::root::compiler::compile_evaluable::compile_evaluable_into;
-use crate::root::compiler::compiler_errors::CError::{BadFunctionArgCount, BadFunctionReturn, ExpectedFunctionReturn, ExpectedSomeReturn};
+use crate::root::compiler::compiler_errors::CErrs::{BadFunctionArgCount, BadFunctionReturn, ExpectedFunctionReturn, ExpectedSomeReturn};
use crate::root::compiler::global_tracker::GlobalTracker;
use crate::root::compiler::local_variable_table::LocalVariableTable;
use crate::root::errors::WErr;
@@ -15,6 +15,7 @@ use crate::root::utils::warn;
// TODO: Cleanup code
+/// Calls a given function with arguments
pub fn call_function(
parent_fid: FunctionID,
fid: FunctionID,
@@ -124,7 +125,7 @@ pub fn call_function(
};
// ? Enter block
- local_variables.enter_block();
+ local_variables.enter_scope();
// ? Arguments
for arg in args.iter().rev() {
@@ -137,7 +138,7 @@ pub fn call_function(
code.line(&format!("add rsp, {}", local_variables.stack_size().0));
// ? Leave block (invalidate parameters)
- local_variables.leave_block();
+ local_variables.leave_scope();
let return_addr = if let Some(return_address) = return_address {
if return_addr.is_none() {
diff --git a/src/root/compiler/compiler_errors.rs b/src/root/compiler/compiler_errors.rs
index b490c8f..420b9d6 100644
--- a/src/root/compiler/compiler_errors.rs
+++ b/src/root/compiler/compiler_errors.rs
@@ -1,7 +1,8 @@
use thiserror::Error;
+/// An error in the compiler step, excluding errors covered in `EvalErrs`
#[derive(Error, Debug)]
-pub enum CError {
+pub enum CErrs {
#[error("Int literal ({0}) exceeds maximum value ({1}) for type")]
IntLiteralExceedsMax(i128, i128),
#[error("Int literal ({0}) below minimum value ({1}) for type")]
diff --git a/src/root/compiler/global_tracker.rs b/src/root/compiler/global_tracker.rs
index 4749d7b..5f35635 100644
--- a/src/root/compiler/global_tracker.rs
+++ b/src/root/compiler/global_tracker.rs
@@ -2,6 +2,7 @@ use std::collections::HashSet;
use derive_getters::{Dissolve, Getters};
use crate::root::shared::common::FunctionID;
+/// Tracks data between function compilations
#[derive(Default, Dissolve, Getters)]
pub struct GlobalTracker {
function_calls: HashSet,
@@ -15,14 +16,17 @@ impl GlobalTracker {
&mut self.function_calls
}
+ /// Stores that a function has been called to ensure it gets compiled
pub fn f_call(&mut self, fid: FunctionID) {
self.function_calls.insert(fid);
}
+ /// Clears the function calls
pub fn reset_functions(&mut self) {
self.function_calls = Default::default();
}
+ /// Adds readonly data to be appended to the assembly, ensuring data is not stored twice
pub fn add_readonly_data(&mut self, name: &str, data: &str) {
if !self.readonly_contents.contains(name) {
self.readonly_contents.insert(name.to_string());
@@ -31,6 +35,7 @@ impl GlobalTracker {
}
}
+ /// Returns a program-wide unique tag e.g. for jump instructions
pub fn get_unique_tag(&mut self, function: FunctionID) -> String {
let r = format!("{}_{}", function.string_id(), self.unique_tag_counter);
self.unique_tag_counter += 1;
diff --git a/src/root/compiler/local_variable_table.rs b/src/root/compiler/local_variable_table.rs
index 7c73f79..886c5da 100644
--- a/src/root/compiler/local_variable_table.rs
+++ b/src/root/compiler/local_variable_table.rs
@@ -25,30 +25,35 @@ impl LocalVariableTable {
*self.stack_size.last().unwrap()
}
- pub fn enter_block(&mut self){
+ /// Creates a new variable scope
+ pub fn enter_scope(&mut self){
self.stack_size.push(*self.stack_size.last().unwrap());
self.table.push(Default::default());
}
- pub fn leave_block(&mut self) {
+ /// Removes the topmost variable scope
+ pub fn leave_scope(&mut self) {
self.table.pop();
self.stack_size.pop();
}
+ /// Adds an allocated, named variable to the variable table and stack size
pub fn add_existing(&mut self, name: String, addressed_type_ref: AddressedTypeRef) {
self.table.last_mut().unwrap().insert(name, addressed_type_ref);
}
+ /// Adds a variable that can't be referenced to the stack size
pub fn add_new_unnamed(&mut self, size: ByteSize) -> LocalAddress {
*self.stack_size.last_mut().unwrap() += size;
LocalAddress(-(self.stack_size.last().unwrap().0 as isize))
}
- pub fn get_ref(&self, name: &str) -> Option {
- self.table.last().unwrap().get(name).cloned()
- }
+ // pub fn get_ref(&self, name: &str) -> Option {
+ // self.table.last().unwrap().get(name).cloned()
+ // }
- pub fn get_name(&self, name: &str) -> Option {
+ /// Returns a local variable
+ pub fn get(&self, name: &str) -> Option {
for table in self.table.iter().rev() {
if let Some(v) = table.get(name) {
return Some(v.clone());
diff --git a/src/root/errors/evaluable_errors.rs b/src/root/errors/evaluable_errors.rs
index 2984bbe..70d5073 100644
--- a/src/root/errors/evaluable_errors.rs
+++ b/src/root/errors/evaluable_errors.rs
@@ -2,6 +2,7 @@ use thiserror::Error;
#[allow(dead_code)]
#[derive(Error, Debug)]
+/// Errors occurring during evaluation
pub enum EvalErrs {
#[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 3b6882e..2e952d8 100644
--- a/src/root/errors/mod.rs
+++ b/src/root/errors/mod.rs
@@ -9,31 +9,41 @@ pub mod parser_errors;
pub mod name_resolver_errors;
pub mod evaluable_errors;
+/// Universal error for Whython-8
pub struct WErr {
error: String,
location: Option // ! Important, don't do file reads unless necessary (i.e. Display)
}
impl WErr {
+ /// Create a new error
+ ///
+ /// EXPENSIVE - Use only for irrecoverable errors!
pub fn n(error: impl Display, location: Location) -> WErr {
let w = WErr {
error: format!("{error}"),
location: Some(location)
};
#[cfg(debug_assertions)]
+ panic!();
if DEBUG_ON_ERROR {
+
println!("{}", Backtrace::capture());
println!("\n{w}");
}
w
}
+ /// Create a new error wrapped in `Err`
+ ///
+ /// EXPENSIVE - Use only for irrecoverable errors!
pub fn ne(error: impl Display, location: Location) -> Result {
let w = WErr {
error: format!("{error}"),
location: Some(location)
};
#[cfg(debug_assertions)]
+ panic!();
if DEBUG_ON_ERROR {
println!("{}", Backtrace::capture());
println!("\n{w}");
@@ -41,6 +51,7 @@ impl WErr {
Err(w)
}
+ /// Create an error with no location information. Use only if truly applicable e.g. no main
pub fn locationless(error: impl Display) -> Result {
Err(WErr {
error: format!("{error}"),
diff --git a/src/root/errors/name_resolver_errors.rs b/src/root/errors/name_resolver_errors.rs
index 68c948b..7b53b75 100644
--- a/src/root/errors/name_resolver_errors.rs
+++ b/src/root/errors/name_resolver_errors.rs
@@ -2,7 +2,8 @@ use thiserror::Error;
#[allow(dead_code)]
#[derive(Error, Debug)]
-pub enum NRErrors {
+/// Errors occurring during name resolution
+pub enum NRErrs {
#[error("No top-level main function found")]
NoMain,
#[error("Cannot create 'impl' for an indirect type")]
diff --git a/src/root/errors/parser_errors.rs b/src/root/errors/parser_errors.rs
index 732f642..88615aa 100644
--- a/src/root/errors/parser_errors.rs
+++ b/src/root/errors/parser_errors.rs
@@ -1,6 +1,7 @@
use thiserror::Error;
#[derive(Error, Debug)]
+/// Errors occurring during parsing
pub enum ParseError {
#[error("Parser Error (rich parser errors have not been implemented yet)")]
ParserErrorsNotImplemented
diff --git a/src/root/name_resolver/name_resolvers.rs b/src/root/name_resolver/name_resolvers.rs
index aa01ab7..633406f 100644
--- a/src/root/name_resolver/name_resolvers.rs
+++ b/src/root/name_resolver/name_resolvers.rs
@@ -3,7 +3,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use crate::root::builtin::{BuiltinInlineFunction, InlineFunctionGenerator};
use crate::root::compiler::local_variable_table::LocalVariableTable;
-use crate::root::errors::name_resolver_errors::NRErrors;
+use crate::root::errors::name_resolver_errors::NRErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::resolve_function_signatures::FunctionSignature;
use crate::root::ob::OB;
@@ -177,7 +177,7 @@ impl GlobalDefinitionTable {
let (name, containing) = match full_name.token() {
FullNameTokens::Name(n, c) => (n, c),
- _ => WErr::ne(NRErrors::ExpectedTypeNotMethodOrAttribute, find_error_point(full_name, full_name.location()))?
+ _ => WErr::ne(NRErrs::ExpectedTypeNotMethodOrAttribute, find_error_point(full_name, full_name.location()))?
};
let name = if name.name() == "Self" && containing.is_some() {
@@ -188,7 +188,7 @@ impl GlobalDefinitionTable {
tree.get_entry(name.name()).map(|val| match val {
NameTreeEntry::Type(t) => Ok(TypeRef::new(*t, *indirection)),
NameTreeEntry::Function(_) => {
- WErr::ne(NRErrors::FoundFunctionNotType(name.name().clone()), full_name.location().clone())
+ WErr::ne(NRErrs::FoundFunctionNotType(name.name().clone()), full_name.location().clone())
}
})
};
@@ -209,10 +209,10 @@ impl GlobalDefinitionTable {
}
if let Some(r) = self.builtin_function_name_table.get(name.name()) {
- return WErr::ne(NRErrors::FoundFunctionNotType(name.name().clone()), full_name.location().clone())
+ return WErr::ne(NRErrs::FoundFunctionNotType(name.name().clone()), full_name.location().clone())
}
- WErr::ne(NRErrors::TypeNotFound(name.name().clone()), full_name.location().clone())
+ WErr::ne(NRErrs::TypeNotFound(name.name().clone()), full_name.location().clone())
}
pub fn get_size(&mut self, t: &TypeRef) -> ByteSize {
@@ -272,7 +272,7 @@ impl GlobalDefinitionTable {
}
pub fn resolve_name(&mut self, name: &SimpleNameToken, containing_class: Option<&SimpleNameToken>, local_variable_table: &LocalVariableTable) -> Result {
- if let Some(variable) = local_variable_table.get_name(name.name()) {
+ if let Some(variable) = local_variable_table.get(name.name()) {
return Ok(NameResult::Variable(variable))
}
@@ -303,7 +303,7 @@ impl GlobalDefinitionTable {
return Ok(NameResult::Function(*r));
}
- WErr::ne(NRErrors::CannotFindName(name.name().clone()), name.location().clone())
+ WErr::ne(NRErrs::CannotFindName(name.name().clone()), name.location().clone())
}
pub fn get_operator_function(&self, lhs: TypeID, operator: &OperatorToken, kind: PrefixOrInfixEx) -> Result {
@@ -312,15 +312,15 @@ impl GlobalDefinitionTable {
if let Some(op_name) = op_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()),
+ NRErrs::OpMethodNotImplemented(op_name.to_string(), self.get_type(lhs).name().to_string(), operator.operator().to_str().to_string()),
operator.location().clone()
)
).copied()
}
else {
WErr::ne(match kind {
- PrefixOrInfixEx::Prefix => NRErrors::OpCantBePrefix(operator.operator().to_str().to_string()),
- PrefixOrInfixEx::Infix => NRErrors::OpCantBeInfix(operator.operator().to_str().to_string()),
+ PrefixOrInfixEx::Prefix => NRErrs::OpCantBePrefix(operator.operator().to_str().to_string()),
+ PrefixOrInfixEx::Infix => NRErrs::OpCantBeInfix(operator.operator().to_str().to_string()),
}, operator.location().clone())
}
}
diff --git a/src/root/name_resolver/resolve.rs b/src/root/name_resolver/resolve.rs
index 8d86e10..b5beed6 100644
--- a/src/root/name_resolver/resolve.rs
+++ b/src/root/name_resolver/resolve.rs
@@ -1,6 +1,6 @@
use std::collections::HashMap;
use crate::root::builtin::register_builtin;
-use crate::root::errors::name_resolver_errors::NRErrors;
+use crate::root::errors::name_resolver_errors::NRErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::name_resolver::resolve_names::resolve_names;
@@ -14,7 +14,7 @@ pub fn resolve(ast: Vec) -> Result<(GlobalDefinitionTable, HashM
let unprocessed_functions = resolve_names(ast, &mut global_table)?;
if !global_table.has_main() {
- return WErr::locationless(NRErrors::NoMain)
+ return WErr::locationless(NRErrs::NoMain)
}
Ok((global_table, unprocessed_functions))
diff --git a/src/root/name_resolver/resolve_names.rs b/src/root/name_resolver/resolve_names.rs
index 8460863..9114acf 100644
--- a/src/root/name_resolver/resolve_names.rs
+++ b/src/root/name_resolver/resolve_names.rs
@@ -2,7 +2,7 @@ use std::any::Any;
use std::collections::HashMap;
use derive_getters::Getters;
-use crate::root::errors::name_resolver_errors::NRErrors;
+use crate::root::errors::name_resolver_errors::NRErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable};
@@ -90,7 +90,7 @@ pub fn resolve_names(ast: Vec, global_table: &mut GlobalDefiniti
for (e_name, _) in &p_attributes {
if e_name.name() == name.name() {
- return WErr::ne(NRErrors::SameAttributeName(name.name().clone()), name.location().clone());
+ return WErr::ne(NRErrs::SameAttributeName(name.name().clone()), name.location().clone());
}
}
p_attributes.push((name, type_ref))
diff --git a/src/root/name_resolver/resolve_type_sizes.rs b/src/root/name_resolver/resolve_type_sizes.rs
index 9b9afaa..d698863 100644
--- a/src/root/name_resolver/resolve_type_sizes.rs
+++ b/src/root/name_resolver/resolve_type_sizes.rs
@@ -1,6 +1,6 @@
use std::collections::HashMap;
use derive_getters::Dissolve;
-use crate::root::errors::name_resolver_errors::NRErrors;
+use crate::root::errors::name_resolver_errors::NRErrs;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::shared::common::TypeRef;
@@ -54,7 +54,7 @@ pub fn resolve_type_sizes(
}
else {
// Type not in unsized_types or type table due to circular definition
- return WErr::ne(NRErrors::CircularType(name), attribute_name.location().clone());
+ return WErr::ne(NRErrs::CircularType(name), attribute_name.location().clone());
}
processed_attributes.push((offset.0, attribute_name, attribute_type));