diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 32da7bd..a777d00 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -7,16 +7,24 @@
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -63,27 +71,31 @@
- {
- "keyToString": {
- "Cargo.Run whython-8.executor": "Run",
- "RunOnceActivity.OpenProjectViewOnStart": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "RunOnceActivity.rust.reset.selective.auto.import": "true",
- "git-widget-placeholder": "master",
- "ignore.virus.scanning.warn.message": "true",
- "node.js.detected.package.eslint": "true",
- "node.js.detected.package.tslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
- "org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
- "org.rust.first.attach.projects": "true",
- "settings.editor.selected.configurable": "preferences.pluginManager",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
+
+
+
@@ -167,7 +179,7 @@
-
+
@@ -369,7 +381,15 @@
1717819316020
-
+
+
+ 1717826853448
+
+
+
+ 1717826853448
+
+
@@ -403,6 +423,7 @@
-
+
+
\ No newline at end of file
diff --git a/build/out.asm b/build/out.asm
index e2b8171..c5a754c 100644
--- a/build/out.asm
+++ b/build/out.asm
@@ -2,40 +2,21 @@
section .text
-_2:
- push rbp
- mov rbp, rsp
-
- mov rax, qword [rbp+16]
- mov qword [rbp-16], rax
- mov rax, qword [rbp+24]
- mov qword [rbp-24], rax
- mov rax, qword [rbp-16]
- add rax, qword [rbp-24]
- mov qword [rbp-8], rax
- mov qword [rbp-32], 1
- mov rax, qword [rbp-8]
- add rax, qword [rbp-32]
- mov qword [rbp+32], rax
- leave
- ret
-
main:
push rbp
mov rbp, rsp
- mov qword [rbp-16], 3
- mov qword [rbp-24], 2
- mov rax, qword [rbp-16]
- mov qword [rbp-48], rax
+ mov qword [rbp-8], -12
+ mov rax, qword [rbp-8]
+ mov qword [rbp-24], rax
mov rax, qword [rbp-24]
- mov qword [rbp-56], rax
- sub rsp, 56
+ mov qword [rbp-40], rax
+ sub rsp, 40
call _1
- add rsp, 56
- mov rax, qword [rbp-40]
- mov qword [rbp-8], rax
- mov rax, qword [rbp-8]
+ add rsp, 40
+ mov rax, qword [rbp-32]
+ mov qword [rbp-16], rax
+ mov rax, qword [rbp-16]
leave
ret
@@ -43,19 +24,12 @@ _1:
push rbp
mov rbp, rsp
+ mov qword [rbp-8], 0
mov rax, qword [rbp+16]
- mov qword [rbp-8], rax
- mov rax, qword [rbp+24]
mov qword [rbp-16], rax
mov rax, qword [rbp-8]
- mov qword [rbp-40], rax
- mov rax, qword [rbp-16]
- mov qword [rbp-48], rax
- sub rsp, 48
- call _2
- add rsp, 48
- mov rax, qword [rbp-32]
- mov qword [rbp+32], rax
+ sub rax, qword [rbp-16]
+ mov qword [rbp+24], rax
leave
ret
diff --git a/build/out.o b/build/out.o
index 0567760..1c6972f 100644
Binary files a/build/out.o and b/build/out.o differ
diff --git a/build/out.out b/build/out.out
index 185dc2b..2363a9e 100755
Binary files a/build/out.out and b/build/out.out differ
diff --git a/main.why b/main.why
index e7dda27..fa319d3 100644
--- a/main.why
+++ b/main.why
@@ -1,14 +1,11 @@
impl int {
- fn sub(lhs: int, rhs: int) -> int {
- return lhs == rhs;
- }
-
- fn eq(lhs: int, rhs: int) -> int {
- return (lhs + rhs) + 1;
+ fn p_sub(self) -> Self {
+ return 0 - self;
}
}
fn main() -> int {
- return 3 - 2;
+ let x: int = -12;
+ return -x;
}
diff --git a/src/root/builtin/int/add.rs b/src/root/builtin/int/add.rs
index f68aa72..af8cb79 100644
--- a/src/root/builtin/int/add.rs
+++ b/src/root/builtin/int/add.rs
@@ -22,6 +22,7 @@ impl BuiltinInlineFunction for IntAdd {
fn signature(&self) -> FunctionSignature {
FunctionSignature::new_inline_builtin(
+ true,
&[("lhs", IntType::id().immediate()), ("rhs", IntType::id().immediate())],
Some(IntType::id().immediate())
)
diff --git a/src/root/builtin/int/mod.rs b/src/root/builtin/int/mod.rs
index 53ca065..bbcbaa3 100644
--- a/src/root/builtin/int/mod.rs
+++ b/src/root/builtin/int/mod.rs
@@ -1,8 +1,10 @@
mod add;
+mod sub;
use b_box::b;
use unique_type_id::UniqueTypeId;
use crate::root::builtin::int::add::IntAdd;
+use crate::root::builtin::int::sub::IntSub;
use crate::root::errors::WErr;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::parser::parse_function::parse_literal::{LiteralToken, LiteralTokens};
@@ -12,6 +14,7 @@ use crate::root::shared::types::Type;
pub fn register_int(global_table: &mut GlobalDefinitionTable) {
global_table.register_builtin_type(b!(IntType));
global_table.register_inline_function(&IntAdd);
+ global_table.register_inline_function(&IntSub);
}
#[derive(UniqueTypeId)]
diff --git a/src/root/builtin/int/sub.rs b/src/root/builtin/int/sub.rs
new file mode 100644
index 0000000..bb7b367
--- /dev/null
+++ b/src/root/builtin/int/sub.rs
@@ -0,0 +1,46 @@
+use unique_type_id::UniqueTypeId;
+use crate::root::builtin::{BuiltinInlineFunction, InlineFunctionGenerator};
+use crate::root::builtin::int::IntType;
+use crate::root::errors::WErr;
+use crate::root::name_resolver::name_resolvers::NameResult::Function;
+use crate::root::name_resolver::resolve_function_signatures::FunctionSignature;
+
+use crate::root::shared::common::{FunctionID, Indirection, LocalAddress, TypeID, TypeRef};
+
+#[derive(UniqueTypeId)]
+#[UniqueTypeIdType = "u16"]
+pub struct IntSub;
+
+impl BuiltinInlineFunction for IntSub {
+ fn id(&self) -> FunctionID {
+ FunctionID(-(IntSub::unique_type_id().0 as isize) - 1)
+ }
+
+ fn name(&self) -> &'static str {
+ "sub"
+ }
+
+ fn signature(&self) -> FunctionSignature {
+ FunctionSignature::new_inline_builtin(
+ true,
+ &[("lhs", IntType::id().immediate()), ("rhs", IntType::id().immediate())],
+ Some(IntType::id().immediate())
+ )
+ }
+
+ fn inline(&self) -> InlineFunctionGenerator {
+ |args: &[LocalAddress], return_into: Option| -> String {
+ let lhs = args[0];
+ let rhs = args[1];
+ let return_into = return_into.unwrap();
+ format!(
+" mov rax, qword {lhs}
+ sub rax, qword {rhs}
+ mov qword {return_into}, rax")
+ }
+ }
+
+ fn parent_type(&self) -> Option {
+ Some(IntType::id())
+ }
+}
diff --git a/src/root/compiler/compile_evaluable.rs b/src/root/compiler/compile_evaluable.rs
index 920e403..17e2847 100644
--- a/src/root/compiler/compile_evaluable.rs
+++ b/src/root/compiler/compile_evaluable.rs
@@ -90,22 +90,16 @@ pub fn compile_evaluable_into(
t.instantiate_from_literal(target.local_address(), literal)?
}
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 = String::new();
- // let (mut code, lhs) = compile_evaluable(fid, lhs, local_variables, global_table, function_calls)?;
let lhs_type = compile_evaluable_type_only(fid, lhs, local_variables, global_table, function_calls)?;
- // code += "\n";
let op_fn = global_table.get_operator_function(*lhs_type.type_id(), op, PrefixOrInfixEx::Infix)?;
let signature = global_table.get_function_signature(op_fn);
if signature.args().len() != 2 {
return Err(
WErr::n(
- EvalErrs::OpWrongArgumentCount(
+ EvalErrs::InfixOpWrongArgumentCount(
op.operator().to_str().to_string(),
global_table.get_type(*lhs_type.type_id()).name().to_string(),
op.operator().get_method_name(PrefixOrInfixEx::Infix).unwrap(),
@@ -127,18 +121,50 @@ pub fn compile_evaluable_into(
}
}
- // 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";
-
let (c, _) = call_function(fid, op_fn, &[Left(lhs), Left(rhs)], Some(target), global_table, local_variables, function_calls)?;
code += &c;
code
},
- EvaluableTokens::PrefixOperator(_, _) => todo!(),
+ EvaluableTokens::PrefixOperator(op, lhs) => {
+ let mut code = String::new();
+
+ let lhs_type = compile_evaluable_type_only(fid, lhs, local_variables, global_table, function_calls)?;
+ let op_fn = global_table.get_operator_function(*lhs_type.type_id(), op, PrefixOrInfixEx::Prefix)?;
+ let signature = global_table.get_function_signature(op_fn);
+
+ if signature.args().len() != 1 {
+ return Err(
+ WErr::n(
+ EvalErrs::InfixOpWrongArgumentCount(
+ op.operator().to_str().to_string(),
+ global_table.get_type(*lhs_type.type_id()).name().to_string(),
+ op.operator().get_method_name(PrefixOrInfixEx::Prefix).unwrap(),
+ 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 (c, _) = call_function(fid, op_fn, &[Left(lhs)], Some(target), global_table, local_variables, function_calls)?;
+
+ code += &c;
+
+ code
+ },
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
EvaluableTokens::FunctionCall(inner, args) => {
diff --git a/src/root/compiler/compile_function.rs b/src/root/compiler/compile_function.rs
index c584b57..5d78c47 100644
--- a/src/root/compiler/compile_function.rs
+++ b/src/root/compiler/compile_function.rs
@@ -13,7 +13,7 @@ use crate::root::shared::common::AddressedTypeRef;
pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table: &mut GlobalDefinitionTable) -> Result<(String, HashSet), WErr> {
let mut local_variables = LocalVariableTable::new();
- let (_location, _name, return_type, parameters, lines) = function.dissolve();
+ let (_location, _name, return_type, _, parameters, lines) = function.dissolve();
let return_type = if fid.is_main() { None } else { return_type };
@@ -67,7 +67,10 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia
local_variables.enter_block();
let mut contents = String::new();
+ let mut last_is_return = false;
+
for line in lines {
+ last_is_return = false;
match line {
LineTokens::Initialisation(it) => {
let (name, type_name, value) = (it.name(), it.type_name(), it.value());
@@ -79,6 +82,7 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia
LineTokens::If(_) => todo!(),
LineTokens::While(_) => todo!(),
LineTokens::Return(rt) => {
+ last_is_return = true;
if fid.is_main() {
if rt.return_value().is_none() {
todo!()
@@ -118,6 +122,10 @@ fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_varia
}
}
+ if (return_variable.is_some() || fid.is_main()) && !last_is_return {
+ todo!()
+ }
+
local_variables.leave_block();
Ok(contents)
diff --git a/src/root/errors/evaluable_errors.rs b/src/root/errors/evaluable_errors.rs
index 3219b9c..6787597 100644
--- a/src/root/errors/evaluable_errors.rs
+++ b/src/root/errors/evaluable_errors.rs
@@ -11,7 +11,9 @@ pub enum EvalErrs {
// #[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),
+ InfixOpWrongArgumentCount(String, String, String, usize),
+ #[error("Prefix operator ({0}) can only be used for type ({1}) if method ({2}) accepting 1 arguments is implemented for ({1}). ({2}) implementation only accepts ({3}) arguments")]
+ PrefixOpWrongArgumentCount(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")]
diff --git a/src/root/name_resolver/resolve_function_signatures.rs b/src/root/name_resolver/resolve_function_signatures.rs
index d71c5a9..02dd486 100644
--- a/src/root/name_resolver/resolve_function_signatures.rs
+++ b/src/root/name_resolver/resolve_function_signatures.rs
@@ -8,13 +8,15 @@ use crate::root::parser::parse_name::SimpleNameToken;
#[derive(Getters)]
pub struct FunctionSignature {
+ dynamic: bool,
args: Vec<(SimpleNameToken, TypeRef)>,
return_type: Option
}
impl FunctionSignature {
- pub fn new_inline_builtin(args: &[(&str, TypeRef)], return_type: Option) -> FunctionSignature {
+ pub fn new_inline_builtin(dynamic: bool, args: &[(&str, TypeRef)], return_type: Option) -> FunctionSignature {
FunctionSignature {
+ dynamic,
args: args.into_iter().map(|(name, t)| (SimpleNameToken::new_builtin(name.to_string()), t.clone())).collect_vec(),
return_type
}
@@ -37,7 +39,9 @@ pub fn resolve_function_signature(function_token: &FunctionToken, global_table:
))
}
+
Ok(FunctionSignature {
+ dynamic: *function_token.dynamic(),
args,
return_type
})
diff --git a/src/root/parser/parse_function.rs b/src/root/parser/parse_function.rs
index 33cb8ac..61e747b 100644
--- a/src/root/parser/parse_function.rs
+++ b/src/root/parser/parse_function.rs
@@ -29,6 +29,7 @@ pub struct FunctionToken {
location: Location,
name: SimpleNameToken,
return_type: Option,
+ dynamic: bool,
parameters: Parameters,
lines: Vec,
}
@@ -54,7 +55,7 @@ pub fn parse_function<'a, 'b>(s: Span<'a>, allow_self: Option<&'b SimpleNameToke
// } else { None };
let (s, contents) = default_section(s, '(')?;
- let (_, parameters) = parse_parameters(contents, allow_self)?;
+ let (_, (parameters, has_self)) = parse_parameters(contents, allow_self)?;
let (s, _) = discard_ignored(s)?;
@@ -74,6 +75,7 @@ pub fn parse_function<'a, 'b>(s: Span<'a>, allow_self: Option<&'b SimpleNameToke
Ok((
s,
FunctionToken {
+ dynamic: has_self,
location,
name,
return_type,
diff --git a/src/root/parser/parse_parameters.rs b/src/root/parser/parse_parameters.rs
index 3218d3e..a4799dc 100644
--- a/src/root/parser/parse_parameters.rs
+++ b/src/root/parser/parse_parameters.rs
@@ -7,15 +7,18 @@ use crate::root::parser::parse_util::discard_ignored;
pub type Parameters = Vec<(SimpleNameToken, FullNameWithIndirectionToken)>;
-pub fn parse_parameters<'a, 'b>(s: Span<'a>, mut allow_self: Option<&'b SimpleNameToken>) -> ParseResult<'a, (), Parameters> {
+pub fn parse_parameters<'a, 'b>(s: Span<'a>, mut allow_self: Option<&'b SimpleNameToken>) -> ParseResult<'a, (), (Parameters, bool)> {
let (mut s, _) = discard_ignored(s)?;
let mut parameters = Vec::new();
+ let mut has_self = false;
+
while !s.is_empty() {
let (ns, name) = parse_simple_name(s)?;
let (ns, p_type) = if allow_self.is_some() && parameters.is_empty() && *name.name() == "self" {
+ has_self = true;
let s = allow_self.take().unwrap();
(ns, FullNameWithIndirectionToken::from_simple(s.clone(), Some(s.clone()), name.location().clone()))
}
@@ -40,5 +43,5 @@ pub fn parse_parameters<'a, 'b>(s: Span<'a>, mut allow_self: Option<&'b SimpleNa
s = ns;
}
- Ok(((), parameters))
+ Ok(((), (parameters, has_self)))
}
diff --git a/src/root/parser/parse_struct.rs b/src/root/parser/parse_struct.rs
index 92d8677..1c2e23c 100644
--- a/src/root/parser/parse_struct.rs
+++ b/src/root/parser/parse_struct.rs
@@ -40,7 +40,7 @@ pub fn parse_struct(s: Span) -> ParseResult {
let (s, name) = parse_simple_name(s)?;
let (s, _) = discard_ignored(s)?;
let (s, contents) = default_section(s, '{')?;
- let (_, parameters) = parse_parameters(contents, None)?;
+ let (_, (parameters, _)) = parse_parameters(contents, None)?;
Ok((
s,
diff --git a/todo.txt b/todo.txt
index bac6808..2cb0a51 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,9 +1,7 @@
-3. Allow operators to be both prefix and infix i.e. -a or a - b
+3. Add function/method calling
4. Finish off evaluable compilation
5. Finish of handling of remaining lines
6. Add rich parser errors
7. Add all errors in
8. All other todos, of course
-
-?. Add support for multiple functions with the same name but different signatures ?
\ No newline at end of file
diff --git a/types.toml b/types.toml
index 977876b..bbec0b9 100644
--- a/types.toml
+++ b/types.toml
@@ -1,2 +1,3 @@
IntType=0
IntAdd=1
+IntSub=2