Compare commits
No commits in common. "4844cebd56b423bfb36d562e2740505c7d49f8c6" and "1c83ca44ab874a73028c3ad6d39b6db9ef152753" have entirely different histories.
4844cebd56
...
1c83ca44ab
@ -9,8 +9,8 @@ contains the relevant abstraction to produce a more Rust'y API from that.
|
|||||||
Much of the syntax in Reid is directly inspired by rust, but mostly it is driven
|
Much of the syntax in Reid is directly inspired by rust, but mostly it is driven
|
||||||
by simplicity.
|
by simplicity.
|
||||||
|
|
||||||
Specifications and a bunch of [documentation for the language can be found
|
Specifications and documentation for the language can be found
|
||||||
here](./documentation/).
|
[here](./documentation/).
|
||||||
|
|
||||||
Reid is currently able to (non-exhaustively):
|
Reid is currently able to (non-exhaustively):
|
||||||
- Do basic algebra binary and unary-operations (e.g. Add, Sub, Div, Mult, And,
|
- Do basic algebra binary and unary-operations (e.g. Add, Sub, Div, Mult, And,
|
||||||
|
@ -18,12 +18,6 @@ A collection of documentation and examples to get you going can be found at [the
|
|||||||
Book of Reid](./book.md). It is recommended you read through the chapter about
|
Book of Reid](./book.md). It is recommended you read through the chapter about
|
||||||
Syntax first though to familiarize yourself with the basic concepts of Reid.
|
Syntax first though to familiarize yourself with the basic concepts of Reid.
|
||||||
|
|
||||||
## Intrinsics
|
|
||||||
|
|
||||||
Reid also has intrinsic functions that are good to know about. These are more
|
|
||||||
in-depth, but when you're feeling up to it, you can read about them
|
|
||||||
[here](./intrinsics.md).
|
|
||||||
|
|
||||||
## Syntax and general information
|
## Syntax and general information
|
||||||
|
|
||||||
Syntax for Reid is very much inspired by rust, and examples of the language can
|
Syntax for Reid is very much inspired by rust, and examples of the language can
|
||||||
@ -253,8 +247,6 @@ calls, literals, or if-expressions. Types of supported expressions include:
|
|||||||
- **Function calls**, to invoke a predefined function with given parameters
|
- **Function calls**, to invoke a predefined function with given parameters
|
||||||
- **Associated function calls**, to invoke a predefined function on a certain
|
- **Associated function calls**, to invoke a predefined function on a certain
|
||||||
*associated type* with given parameters.
|
*associated type* with given parameters.
|
||||||
- **Accessing function calls**, a shorthand to call associated function calls
|
|
||||||
which have `&self` or `&mut self` as their first parameter.
|
|
||||||
- **Block-expressions**, which can return a value to the higher-level expression
|
- **Block-expressions**, which can return a value to the higher-level expression
|
||||||
if they have a statement with a soft-return. Otherwise they return void.
|
if they have a statement with a soft-return. Otherwise they return void.
|
||||||
- **If-expressions**, which can execute one of two expressions depending on the
|
- **If-expressions**, which can execute one of two expressions depending on the
|
||||||
@ -271,7 +263,7 @@ In formal grammar:
|
|||||||
<array> | <struct> |
|
<array> | <struct> |
|
||||||
<indexing> | <accessing> |
|
<indexing> | <accessing> |
|
||||||
<binary-exp> | <unary-exp> |
|
<binary-exp> | <unary-exp> |
|
||||||
<function-call> | <accessing-function-call> | <assoc-function-call>
|
<function-call> | <assoc-function-call>
|
||||||
<block> | <if-expr> | <cast> |
|
<block> | <if-expr> | <cast> |
|
||||||
( "(" <expression> ")" )
|
( "(" <expression> ")" )
|
||||||
|
|
||||||
@ -286,7 +278,6 @@ In formal grammar:
|
|||||||
<binary-exp> :: <expression> <binop> <expression>
|
<binary-exp> :: <expression> <binop> <expression>
|
||||||
<unary-exp> :: <unary> <expression>
|
<unary-exp> :: <unary> <expression>
|
||||||
<function-call> :: <expression> "(" [ <expression> ( "," <expression> )* ] ")"
|
<function-call> :: <expression> "(" [ <expression> ( "," <expression> )* ] ")"
|
||||||
<accessing-function-call> :: <accessing> "(" [ <expression> ( "," <expression> )* ] ")"
|
|
||||||
<assoc-function-call> :: <type> "::" <function-call>
|
<assoc-function-call> :: <type> "::" <function-call>
|
||||||
<if-expr> :: "if" <expression> <expression> [ "else" <expression> ]
|
<if-expr> :: "if" <expression> <expression> [ "else" <expression> ]
|
||||||
<cast> :: <expression> "as" <type>
|
<cast> :: <expression> "as" <type>
|
||||||
@ -305,7 +296,6 @@ test.first // Accessing
|
|||||||
!bool_value // Unary
|
!bool_value // Unary
|
||||||
func(value, 14) // Function call
|
func(value, 14) // Function call
|
||||||
Test::get_field(&test); // Associated function call
|
Test::get_field(&test); // Associated function call
|
||||||
test.get_field(); // Same, but using a the dot-form shorthand
|
|
||||||
if varname {} else {} // If-expression
|
if varname {} else {} // If-expression
|
||||||
value as u32 // cast
|
value as u32 // cast
|
||||||
(value + 2) // Binop within parenthesis
|
(value + 2) // Binop within parenthesis
|
||||||
|
@ -22,7 +22,6 @@ or simply casting the value (e.g. `5 as u32`).
|
|||||||
## Table of Contents:
|
## Table of Contents:
|
||||||
- [Hello World](#hello-world)
|
- [Hello World](#hello-world)
|
||||||
- [Borrowing and Pointers](#borrowing-and-pointers)
|
- [Borrowing and Pointers](#borrowing-and-pointers)
|
||||||
- [Harder Hello World](#harder-hello-world)
|
|
||||||
|
|
||||||
### Hello World
|
### Hello World
|
||||||
|
|
||||||
@ -121,73 +120,3 @@ This example will always return `17`. Notice also, how a **mutable** borrow was
|
|||||||
passed to `mutate`-function. While borrows do not always need to be mutable,
|
passed to `mutate`-function. While borrows do not always need to be mutable,
|
||||||
this example would not work without the `mut`-keyword. Try it out for yourself
|
this example would not work without the `mut`-keyword. Try it out for yourself
|
||||||
to see why!
|
to see why!
|
||||||
|
|
||||||
### Harder Hello World
|
|
||||||
|
|
||||||
A little bit harder example to the previous hello world would be
|
|
||||||
`hello_world_harder.reid` from [examples](../examples/hello_world_harder.reid)
|
|
||||||
|
|
||||||
```rust
|
|
||||||
import std::print;
|
|
||||||
import std::String;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut test = String::from("hello");
|
|
||||||
|
|
||||||
test.push(String::from(" world: "));
|
|
||||||
test.push_num(175);
|
|
||||||
|
|
||||||
print(test);
|
|
||||||
|
|
||||||
test.free();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's go through this again line-by-line
|
|
||||||
|
|
||||||
```rust
|
|
||||||
import std::print;
|
|
||||||
import std::String;
|
|
||||||
```
|
|
||||||
|
|
||||||
At the start are the standard imports, like in the original Hello World, but
|
|
||||||
notice that instead of importing just functions we import the type `String` as
|
|
||||||
well. When importing types, not only are the type imported, but also any binary
|
|
||||||
functions or associated functions related to it with it.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let mut test = String::from("hello");
|
|
||||||
```
|
|
||||||
|
|
||||||
Next we create the initial string, just like in our original example, but this
|
|
||||||
time the message is not complete. We also use an associated function to create
|
|
||||||
the string instead one of the now-deprecated global functions.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
test.push(String::from(" world: "));
|
|
||||||
test.push_num(175);
|
|
||||||
```
|
|
||||||
|
|
||||||
After that we edit the message by first pushing ` world: ` to it, and also
|
|
||||||
appending the number `175` at the end of it. For both of these operations we are
|
|
||||||
again using associated functions, but in a different short-hand syntax.
|
|
||||||
|
|
||||||
These two lines would be actually equivalent to the above ones:
|
|
||||||
```rust
|
|
||||||
String::push(&mut test, String::from(" world: "));
|
|
||||||
String::push_num(&mut test, 175);
|
|
||||||
```
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
```rust
|
|
||||||
|
|
||||||
print(test);
|
|
||||||
|
|
||||||
test.free();
|
|
||||||
return;
|
|
||||||
```
|
|
||||||
|
|
||||||
After that we simply print the string, and free up the string (again with an
|
|
||||||
associated function) before returning. Nothing special there!
|
|
@ -1,28 +0,0 @@
|
|||||||
## Intrinsics
|
|
||||||
|
|
||||||
Intrinsics are functions that are defined within the language compiler but not
|
|
||||||
in standard library, thus they do not require importing in order to use (and
|
|
||||||
trying to re-define these will end up causing issues). Intrinsics include all
|
|
||||||
pre-existing binary-operators, but also some regular functions and associated
|
|
||||||
functions (that every type has by-default). This document lists them all (except
|
|
||||||
for the binary operators, because there are hundreds of those).
|
|
||||||
|
|
||||||
### Associated Intrinsics
|
|
||||||
|
|
||||||
#### `<T>::sizeof() -> u64`
|
|
||||||
|
|
||||||
Simply returns the size of type `T` in bits.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
i32::sizeof(); // Returns 32
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `<T>::alloca(size: u64) -> *T`
|
|
||||||
|
|
||||||
Allocates `T::sizeof() * size` bits and returns a pointer to `T`.
|
|
||||||
|
|
||||||
**Note:** This does not seem to work correctly currently.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
i32::alloca(30); // Returns *i32
|
|
||||||
```
|
|
@ -10,58 +10,30 @@ Has the following binops defined:
|
|||||||
- `String` + `*char` = `String`
|
- `String` + `*char` = `String`
|
||||||
- `String` + `u64` = `String`
|
- `String` + `u64` = `String`
|
||||||
|
|
||||||
##### `String::new() -> String`
|
#### `pub fn print(message: String)`
|
||||||
|
|
||||||
Returns a new empty `String`-object, which must later be manually freed.
|
Prints given `message` to the standard output
|
||||||
|
|
||||||
##### `String::from(str: *char) -> String`
|
|
||||||
|
|
||||||
Creates a new `String`-object containing initially data from the given string-literal which must be later freed.
|
|
||||||
|
|
||||||
##### `String::set(&mut self, c: char, position: u64)`
|
|
||||||
|
|
||||||
Edits given `string` by setting the character at index `position` to be `c`.
|
|
||||||
|
|
||||||
##### `String::push_num(&mut self, num: u64)`
|
|
||||||
|
|
||||||
Formats the given number into the end of the string.
|
|
||||||
|
|
||||||
##### `String::concat(&mut self, source: String)`
|
|
||||||
|
|
||||||
Concatenates `source` to the end of `destination`.
|
|
||||||
|
|
||||||
### Deprecated functions
|
|
||||||
|
|
||||||
#### `pub fn new_string() -> String`
|
#### `pub fn new_string() -> String`
|
||||||
|
|
||||||
Returns a new empty `String`-object, which must later be manually freed.
|
Returns a new empty `String`-object, which must later be manually freed.
|
||||||
|
|
||||||
_deprecated: Use `String::new()`_
|
|
||||||
|
|
||||||
#### `pub fn from_str(string: *char) -> String`
|
#### `pub fn from_str(string: *char) -> String`
|
||||||
|
|
||||||
Creates a new `String`-object containing initially data from the given string-literal which must be later freed.
|
Creates a new `String`-object containing initially data from the given string-literal which must be later freed.
|
||||||
|
|
||||||
_deprecated: Use `String::from()`_
|
|
||||||
|
|
||||||
#### `pub fn set_char(string: &mut String, c: char, position: u64)`
|
#### `pub fn set_char(string: &mut String, c: char, position: u64)`
|
||||||
|
|
||||||
Edits given `string` by setting the character at index `position` to be `c`.
|
Edits given `string` by setting the character at index `position` to be `c`.
|
||||||
|
|
||||||
_deprecated: Use `String::set()`_
|
|
||||||
|
|
||||||
#### `pub fn add_num_to_string(string: &mut String, num: u64)`
|
#### `pub fn add_num_to_string(string: &mut String, num: u64)`
|
||||||
|
|
||||||
Formats the given number into the end of the string.
|
Formats the given number into the end of the string.
|
||||||
|
|
||||||
_deprecated: Use `String::push_num()`_
|
|
||||||
|
|
||||||
#### `pub fn concat_strings(destination: &mut String, source: String)`
|
#### `pub fn concat_strings(destination: &mut String, source: String)`
|
||||||
|
|
||||||
Concatenates `source` to the end of `destination`.
|
Concatenates `source` to the end of `destination`.
|
||||||
|
|
||||||
_deprecated: Use `String::concat()`_
|
|
||||||
|
|
||||||
## General
|
## General
|
||||||
|
|
||||||
#### `pub fn allocate(size: u64) -> *u8`
|
#### `pub fn allocate(size: u64) -> *u8`
|
||||||
|
@ -7,8 +7,8 @@ struct Otus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Otus {
|
impl Otus {
|
||||||
fn test(&self) -> u32 {
|
fn test(self) -> u32 {
|
||||||
*self.field
|
self.field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,25 @@
|
|||||||
import std::print;
|
import std::print;
|
||||||
import std::String;
|
import std::from_str;
|
||||||
|
import std::add_char;
|
||||||
|
import std::set_char;
|
||||||
|
import std::free_string;
|
||||||
|
import std::new_string;
|
||||||
|
import std::add_num_to_str;
|
||||||
|
import std::concat_strings;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut test = String::from("hello");
|
let mut test = from_str("hello");
|
||||||
|
|
||||||
test.push(String::from(" world: "));
|
concat_strings(&mut test, from_str(" world"));
|
||||||
|
|
||||||
test.push_num(175);
|
add_char(&mut test, '!');
|
||||||
|
add_char(&mut test, '\n');
|
||||||
|
|
||||||
|
add_num_to_str(&mut test, 175);
|
||||||
|
|
||||||
print(test);
|
print(test);
|
||||||
|
|
||||||
test.free();
|
free_string(&test);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11,88 +11,6 @@ struct String {
|
|||||||
must_be_freed: bool,
|
must_be_freed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl String {
|
|
||||||
pub fn new() -> String {
|
|
||||||
String {
|
|
||||||
inner: allocate(0),
|
|
||||||
length: 0,
|
|
||||||
max_length: 0,
|
|
||||||
must_be_freed: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from(str: *char) -> String {
|
|
||||||
let length = str_length(str) as u64;
|
|
||||||
let mut new = String::new();
|
|
||||||
let static = String {
|
|
||||||
inner: str,
|
|
||||||
length: length - 1,
|
|
||||||
max_length: length,
|
|
||||||
must_be_freed: false,
|
|
||||||
};
|
|
||||||
concat_strings(&mut new, static);
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, other: String) {
|
|
||||||
for i in 0 .. (str_length(other.inner) - 1) {
|
|
||||||
add_char(self, other.inner[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_char(&mut self, c: char) {
|
|
||||||
if ((*self).length + 1) >= (*self).max_length {
|
|
||||||
let new = allocate((*self).max_length + 4) as *char;
|
|
||||||
copy_bits((*self).inner, new, (*self).max_length);
|
|
||||||
|
|
||||||
if (*self).must_be_freed == true {
|
|
||||||
free((*self).inner as *u8);
|
|
||||||
}
|
|
||||||
(*self).max_length = (*self).max_length + 4;
|
|
||||||
(*self).inner = new;
|
|
||||||
(*self).must_be_freed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*self).inner[(*self).length] = c;
|
|
||||||
(((*self).inner) as *u8)[(*self).length + 1] = 0;
|
|
||||||
(*self).length = (*self).length + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_num(&mut self, num: u64) {
|
|
||||||
if num >= 10 {
|
|
||||||
self.push_num(num / 10)
|
|
||||||
}
|
|
||||||
let rem = num % 10;
|
|
||||||
|
|
||||||
if rem == 0 { self.add_char('0'); }
|
|
||||||
else if rem == 1 { self.add_char('1'); }
|
|
||||||
else if rem == 2 { self.add_char('2'); }
|
|
||||||
else if rem == 3 { self.add_char('3'); }
|
|
||||||
else if rem == 4 { self.add_char('4'); }
|
|
||||||
else if rem == 5 { self.add_char('5'); }
|
|
||||||
else if rem == 6 { self.add_char('6'); }
|
|
||||||
else if rem == 7 { self.add_char('7'); }
|
|
||||||
else if rem == 8 { self.add_char('8'); }
|
|
||||||
else if rem == 9 { self.add_char('9'); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn concat(&mut self, other: &String) {
|
|
||||||
for i in 0 .. *other.length {
|
|
||||||
self.add_char(*other.inner[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, c: char, position: u64) {
|
|
||||||
if position <= (*self).length {
|
|
||||||
(*self).inner[position] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn free(&self) {
|
|
||||||
free((*self).inner as *u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl binop (lhs: String) + (rhs: *char) -> String {
|
impl binop (lhs: String) + (rhs: *char) -> String {
|
||||||
let mut new = lhs;
|
let mut new = lhs;
|
||||||
let added = from_str(rhs);
|
let added = from_str(rhs);
|
||||||
|
@ -80,8 +80,8 @@ pub struct Expression(pub ExpressionKind, pub TokenRange);
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ExpressionKind {
|
pub enum ExpressionKind {
|
||||||
VariableName(String),
|
VariableName(String),
|
||||||
Borrow(Box<Expression>, bool),
|
Borrow(String, bool),
|
||||||
Deref(Box<Expression>),
|
Deref(String),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Array(Vec<Expression>),
|
Array(Vec<Expression>),
|
||||||
ArrayShort(Box<Expression>, u64),
|
ArrayShort(Box<Expression>, u64),
|
||||||
|
@ -179,36 +179,6 @@ impl Parse for AssociatedFunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_inner<T>(expr: PrimaryExpression, fun: T) -> Expression
|
|
||||||
where
|
|
||||||
T: FnOnce(PrimaryExpression) -> Expression,
|
|
||||||
{
|
|
||||||
match &expr.0 .0 {
|
|
||||||
ExpressionKind::Indexed(value_expr, index_expr) => Expression(
|
|
||||||
ExpressionKind::Indexed(
|
|
||||||
Box::new(apply_inner(PrimaryExpression(*value_expr.clone()), fun)),
|
|
||||||
index_expr.clone(),
|
|
||||||
),
|
|
||||||
expr.0 .1,
|
|
||||||
),
|
|
||||||
ExpressionKind::Accessed(value_expr, index_name) => Expression(
|
|
||||||
ExpressionKind::Accessed(
|
|
||||||
Box::new(apply_inner(PrimaryExpression(*value_expr.clone()), fun)),
|
|
||||||
index_name.clone(),
|
|
||||||
),
|
|
||||||
expr.0 .1,
|
|
||||||
),
|
|
||||||
ExpressionKind::AccessCall(value_expr, fn_call) => Expression(
|
|
||||||
ExpressionKind::AccessCall(
|
|
||||||
Box::new(apply_inner(PrimaryExpression(*value_expr.clone()), fun)),
|
|
||||||
fn_call.clone(),
|
|
||||||
),
|
|
||||||
expr.0 .1,
|
|
||||||
),
|
|
||||||
_ => fun(expr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PrimaryExpression(Expression);
|
pub struct PrimaryExpression(Expression);
|
||||||
|
|
||||||
@ -225,21 +195,18 @@ impl Parse for PrimaryExpression {
|
|||||||
} else if let (Some(Token::Et), Some(Token::MutKeyword)) = (stream.peek(), stream.peek2()) {
|
} else if let (Some(Token::Et), Some(Token::MutKeyword)) = (stream.peek(), stream.peek2()) {
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
stream.next(); // Consume mut
|
stream.next(); // Consume mut
|
||||||
Expression(
|
let Some(Token::Identifier(name)) = stream.next() else {
|
||||||
Kind::Borrow(Box::new(stream.parse()?), true),
|
return Err(stream.expected_err("identifier")?);
|
||||||
stream.get_range().unwrap(),
|
};
|
||||||
)
|
Expression(Kind::Borrow(name, true), stream.get_range().unwrap())
|
||||||
} else if let Some(Token::Et) = stream.peek() {
|
} else if let (Some(Token::Et), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
Expression(
|
stream.next(); // Consume identifier
|
||||||
Kind::Borrow(Box::new(stream.parse()?), false),
|
Expression(Kind::Borrow(name, false), stream.get_range().unwrap())
|
||||||
stream.get_range().unwrap(),
|
} else if let (Some(Token::Star), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
|
||||||
)
|
|
||||||
} else if let Some(Token::Star) = stream.peek() {
|
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
apply_inner(stream.parse()?, |e| {
|
stream.next(); // Consume identifier
|
||||||
Expression(Kind::Deref(Box::new(e.0)), stream.get_range().unwrap())
|
Expression(Kind::Deref(name), stream.get_range().unwrap())
|
||||||
})
|
|
||||||
} else if let Ok(unary) = stream.parse() {
|
} else if let Ok(unary) = stream.parse() {
|
||||||
Expression(
|
Expression(
|
||||||
Kind::UnaryOperation(unary, Box::new(stream.parse()?)),
|
Kind::UnaryOperation(unary, Box::new(stream.parse()?)),
|
||||||
@ -691,23 +658,12 @@ impl Parse for FunctionSignature {
|
|||||||
|
|
||||||
let self_kind = stream.parse::<SelfParam>().map(|s| s.0).unwrap_or(SelfKind::None);
|
let self_kind = stream.parse::<SelfParam>().map(|s| s.0).unwrap_or(SelfKind::None);
|
||||||
|
|
||||||
match &self_kind {
|
if let Ok(param) = stream.parse::<FunctionParam>() {
|
||||||
SelfKind::None => {
|
params.push((param.0, param.1));
|
||||||
if let Ok(param) = stream.parse::<FunctionParam>() {
|
while let Some(Token::Comma) = stream.peek() {
|
||||||
params.push((param.0, param.1));
|
stream.next();
|
||||||
while let Some(Token::Comma) = stream.peek() {
|
let param = stream.parse::<FunctionParam>()?;
|
||||||
stream.next();
|
params.push((param.0, param.1));
|
||||||
let param = stream.parse::<FunctionParam>()?;
|
|
||||||
params.push((param.0, param.1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
while let Some(Token::Comma) = stream.peek() {
|
|
||||||
stream.next();
|
|
||||||
let param = stream.parse::<FunctionParam>()?;
|
|
||||||
params.push((param.0, param.1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,20 +1019,15 @@ impl Parse for AssociatedFunctionBlock {
|
|||||||
let ty = stream.parse::<Type>()?;
|
let ty = stream.parse::<Type>()?;
|
||||||
stream.expect(Token::BraceOpen)?;
|
stream.expect(Token::BraceOpen)?;
|
||||||
let mut functions = Vec::new();
|
let mut functions = Vec::new();
|
||||||
loop {
|
while let Some(Token::FnKeyword) = stream.peek() {
|
||||||
match stream.peek() {
|
let mut fun: FunctionDefinition = stream.parse()?;
|
||||||
Some(Token::FnKeyword) | Some(Token::PubKeyword) => {
|
fun.0.self_kind = match fun.0.self_kind {
|
||||||
let mut fun: FunctionDefinition = stream.parse()?;
|
SelfKind::Owned(_) => SelfKind::Owned(ty.0.clone()),
|
||||||
fun.0.self_kind = match fun.0.self_kind {
|
SelfKind::Borrow(_) => SelfKind::Borrow(ty.0.clone()),
|
||||||
SelfKind::Owned(_) => SelfKind::Owned(ty.0.clone()),
|
SelfKind::MutBorrow(_) => SelfKind::MutBorrow(ty.0.clone()),
|
||||||
SelfKind::Borrow(_) => SelfKind::Borrow(ty.0.clone()),
|
SelfKind::None => SelfKind::None,
|
||||||
SelfKind::MutBorrow(_) => SelfKind::MutBorrow(ty.0.clone()),
|
};
|
||||||
SelfKind::None => SelfKind::None,
|
functions.push(fun);
|
||||||
};
|
|
||||||
functions.push(fun);
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.expect(Token::BraceClose)?;
|
stream.expect(Token::BraceClose)?;
|
||||||
|
@ -36,7 +36,6 @@ impl ast::Module {
|
|||||||
ExternFunction(signature) => {
|
ExternFunction(signature) => {
|
||||||
let def = mir::FunctionDefinition {
|
let def = mir::FunctionDefinition {
|
||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
linkage_name: None,
|
|
||||||
is_pub: false,
|
is_pub: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: signature
|
return_type: signature
|
||||||
@ -150,7 +149,6 @@ impl ast::FunctionDefinition {
|
|||||||
);
|
);
|
||||||
mir::FunctionDefinition {
|
mir::FunctionDefinition {
|
||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
linkage_name: None,
|
|
||||||
is_pub: *is_pub,
|
is_pub: *is_pub,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: signature
|
return_type: signature
|
||||||
@ -363,10 +361,19 @@ impl ast::Expression {
|
|||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
),
|
),
|
||||||
ast::ExpressionKind::Borrow(expr, mutable) => {
|
ast::ExpressionKind::Borrow(name, mutable) => mir::ExprKind::Borrow(
|
||||||
mir::ExprKind::Borrow(Box::new(expr.process(module_id)), *mutable)
|
NamedVariableRef(
|
||||||
}
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
ast::ExpressionKind::Deref(expr) => mir::ExprKind::Deref(Box::new(expr.process(module_id))),
|
name.clone(),
|
||||||
|
self.1.as_meta(module_id),
|
||||||
|
),
|
||||||
|
*mutable,
|
||||||
|
),
|
||||||
|
ast::ExpressionKind::Deref(name) => mir::ExprKind::Deref(NamedVariableRef(
|
||||||
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
|
name.clone(),
|
||||||
|
self.1.as_meta(module_id),
|
||||||
|
)),
|
||||||
ast::ExpressionKind::UnaryOperation(unary_operator, expr) => match unary_operator {
|
ast::ExpressionKind::UnaryOperation(unary_operator, expr) => match unary_operator {
|
||||||
ast::UnaryOperator::Plus => mir::ExprKind::BinOp(
|
ast::UnaryOperator::Plus => mir::ExprKind::BinOp(
|
||||||
mir::BinaryOperator::Add,
|
mir::BinaryOperator::Add,
|
||||||
@ -417,13 +424,7 @@ impl ast::Expression {
|
|||||||
),
|
),
|
||||||
ast::ExpressionKind::AccessCall(expression, fn_call_expr) => {
|
ast::ExpressionKind::AccessCall(expression, fn_call_expr) => {
|
||||||
let mut params: Vec<_> = fn_call_expr.1.iter().map(|e| e.process(module_id)).collect();
|
let mut params: Vec<_> = fn_call_expr.1.iter().map(|e| e.process(module_id)).collect();
|
||||||
params.insert(
|
params.insert(0, expression.process(module_id));
|
||||||
0,
|
|
||||||
mir::Expression(
|
|
||||||
mir::ExprKind::Borrow(Box::new(expression.process(module_id)), true),
|
|
||||||
expression.1.as_meta(module_id),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
mir::ExprKind::AssociatedFunctionCall(
|
mir::ExprKind::AssociatedFunctionCall(
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
mir::FunctionCall {
|
mir::FunctionCall {
|
||||||
|
@ -40,7 +40,6 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
|
|||||||
match name {
|
match name {
|
||||||
"sizeof" => Some(FunctionDefinition {
|
"sizeof" => Some(FunctionDefinition {
|
||||||
name: "sizeof".to_owned(),
|
name: "sizeof".to_owned(),
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
is_pub: true,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: TypeKind::U64,
|
return_type: TypeKind::U64,
|
||||||
@ -49,7 +48,6 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
|
|||||||
}),
|
}),
|
||||||
"alloca" => Some(FunctionDefinition {
|
"alloca" => Some(FunctionDefinition {
|
||||||
name: "alloca".to_owned(),
|
name: "alloca".to_owned(),
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
is_pub: true,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
||||||
@ -58,7 +56,6 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
|
|||||||
}),
|
}),
|
||||||
"null" => Some(FunctionDefinition {
|
"null" => Some(FunctionDefinition {
|
||||||
name: "null".to_owned(),
|
name: "null".to_owned(),
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
is_pub: true,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
||||||
|
@ -187,7 +187,7 @@ impl mir::Module {
|
|||||||
let is_main = self.is_main && function.name == "main";
|
let is_main = self.is_main && function.name == "main";
|
||||||
let func = match &function.kind {
|
let func = match &function.kind {
|
||||||
mir::FunctionDefinitionKind::Local(_, _) => Some(module.function(
|
mir::FunctionDefinitionKind::Local(_, _) => Some(module.function(
|
||||||
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
&function.name,
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(&type_values),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
@ -198,7 +198,7 @@ impl mir::Module {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
mir::FunctionDefinitionKind::Extern(imported) => Some(module.function(
|
mir::FunctionDefinitionKind::Extern(imported) => Some(module.function(
|
||||||
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
&function.name,
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(&type_values),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
@ -238,7 +238,7 @@ impl mir::Module {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
mir::FunctionDefinitionKind::Extern(imported) => Some(module.function(
|
mir::FunctionDefinitionKind::Extern(imported) => Some(module.function(
|
||||||
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
&function.name,
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(&type_values),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
@ -1144,8 +1144,12 @@ impl mir::Expression {
|
|||||||
TypeKind::CustomType(type_key),
|
TypeKind::CustomType(type_key),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Borrow(expr, mutable) => {
|
mir::ExprKind::Borrow(varref, mutable) => {
|
||||||
let v = expr.codegen(scope, &state.load(false))?.unwrap();
|
varref.0.known().expect("variable type unknown");
|
||||||
|
let v = scope
|
||||||
|
.stack_values
|
||||||
|
.get(&varref.1)
|
||||||
|
.expect("Variable reference not found?!");
|
||||||
|
|
||||||
let TypeKind::CodegenPtr(ptr_inner) = &v.1 else {
|
let TypeKind::CodegenPtr(ptr_inner) = &v.1 else {
|
||||||
panic!();
|
panic!();
|
||||||
@ -1156,8 +1160,12 @@ impl mir::Expression {
|
|||||||
TypeKind::Borrow(Box::new(*ptr_inner.clone()), *mutable),
|
TypeKind::Borrow(Box::new(*ptr_inner.clone()), *mutable),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Deref(expr) => {
|
mir::ExprKind::Deref(varref) => {
|
||||||
let v = expr.codegen(scope, &state.load(false))?.unwrap();
|
varref.0.known().expect("variable type unknown");
|
||||||
|
let v = scope
|
||||||
|
.stack_values
|
||||||
|
.get(&varref.1)
|
||||||
|
.expect("Variable reference not found?!");
|
||||||
|
|
||||||
let TypeKind::CodegenPtr(ptr_inner) = &v.1 else {
|
let TypeKind::CodegenPtr(ptr_inner) = &v.1 else {
|
||||||
panic!();
|
panic!();
|
||||||
@ -1166,7 +1174,7 @@ impl mir::Expression {
|
|||||||
let var_ptr_instr = scope
|
let var_ptr_instr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build_named(
|
||||||
format!("{}.deref", expr.backing_var().unwrap().1),
|
format!("{}.deref", varref.1),
|
||||||
Instr::Load(v.0.instr(), ptr_inner.get_type(scope.type_values)),
|
Instr::Load(v.0.instr(), ptr_inner.get_type(scope.type_values)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -1179,7 +1187,7 @@ impl mir::Expression {
|
|||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build_named(
|
||||||
format!("{}.deref.inner", expr.backing_var().unwrap().1),
|
format!("{}.deref.inner", varref.1),
|
||||||
Instr::Load(var_ptr_instr, inner.get_type(scope.type_values)),
|
Instr::Load(var_ptr_instr, inner.get_type(scope.type_values)),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@ -1292,9 +1300,6 @@ fn codegen_function_call<'ctx, 'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let val = if let Some(ty) = associated_type {
|
let val = if let Some(ty) = associated_type {
|
||||||
// Unwrap type from borrow if it is in a borrow
|
|
||||||
let ty = if let TypeKind::Borrow(inner, _) = ty { inner } else { ty };
|
|
||||||
|
|
||||||
let assoc_key = AssociatedFunctionKey(ty.clone(), call.name.clone());
|
let assoc_key = AssociatedFunctionKey(ty.clone(), call.name.clone());
|
||||||
let intrinsic_def = get_intrinsic_assoc_func(&ty, &call.name);
|
let intrinsic_def = get_intrinsic_assoc_func(&ty, &call.name);
|
||||||
let intrinsic = intrinsic_def.map(|func_def| {
|
let intrinsic = intrinsic_def.map(|func_def| {
|
||||||
|
@ -208,19 +208,6 @@ impl TypeKind {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unroll_borrows(&self) -> TypeKind {
|
|
||||||
match self {
|
|
||||||
TypeKind::Borrow(type_kind, mut1) => match *type_kind.clone() {
|
|
||||||
TypeKind::Borrow(type_kind, mut2) => match (mut1, mut2) {
|
|
||||||
(false, false) => TypeKind::Borrow(Box::new(*type_kind.clone()), false),
|
|
||||||
_ => TypeKind::Borrow(Box::new(*type_kind.clone()), true),
|
|
||||||
},
|
|
||||||
_ => self.clone(),
|
|
||||||
},
|
|
||||||
_ => self.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryOperator {
|
impl BinaryOperator {
|
||||||
@ -438,15 +425,15 @@ impl Expression {
|
|||||||
ReturnKind::Soft,
|
ReturnKind::Soft,
|
||||||
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
||||||
)),
|
)),
|
||||||
Borrow(expr, mutable) => {
|
Borrow(var, mutable) => {
|
||||||
let ret_type = expr.return_type(refs, mod_id)?;
|
let ret_type = var.return_type()?;
|
||||||
Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable)))
|
Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable)))
|
||||||
}
|
}
|
||||||
Deref(expr) => {
|
Deref(var) => {
|
||||||
let (kind, ret_type) = expr.return_type(refs, mod_id)?;
|
let (kind, ret_type) = var.return_type()?;
|
||||||
match ret_type.resolve_weak(refs) {
|
match ret_type.resolve_weak(refs) {
|
||||||
TypeKind::Borrow(type_kind, _) => Ok((kind, *type_kind)),
|
TypeKind::Borrow(type_kind, _) => Ok((kind, *type_kind)),
|
||||||
_ => Err(ReturnTypeOther::DerefNonBorrow(expr.1)),
|
_ => Err(ReturnTypeOther::DerefNonBorrow(var.2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) {
|
CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) {
|
||||||
@ -465,8 +452,8 @@ impl Expression {
|
|||||||
ExprKind::Variable(var_ref) => Some(var_ref),
|
ExprKind::Variable(var_ref) => Some(var_ref),
|
||||||
ExprKind::Indexed(lhs, _, _) => lhs.backing_var(),
|
ExprKind::Indexed(lhs, _, _) => lhs.backing_var(),
|
||||||
ExprKind::Accessed(lhs, _, _) => lhs.backing_var(),
|
ExprKind::Accessed(lhs, _, _) => lhs.backing_var(),
|
||||||
ExprKind::Borrow(expr, _) => expr.backing_var(),
|
ExprKind::Borrow(var, _) => Some(var),
|
||||||
ExprKind::Deref(expr) => expr.backing_var(),
|
ExprKind::Deref(var) => Some(var),
|
||||||
ExprKind::Block(block) => block.backing_var(),
|
ExprKind::Block(block) => block.backing_var(),
|
||||||
ExprKind::Array(_) => None,
|
ExprKind::Array(_) => None,
|
||||||
ExprKind::Struct(_, _) => None,
|
ExprKind::Struct(_, _) => None,
|
||||||
|
@ -227,8 +227,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
importer_module.functions.push(FunctionDefinition {
|
importer_module.functions.push(FunctionDefinition {
|
||||||
name: func_name.clone(),
|
name: func_name,
|
||||||
linkage_name: None,
|
|
||||||
is_pub: false,
|
is_pub: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type,
|
return_type,
|
||||||
@ -269,66 +268,6 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
FunctionDefinitionKind::Intrinsic(_) => {}
|
FunctionDefinitionKind::Intrinsic(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ty, func) in &mut imported.associated_functions {
|
|
||||||
if *ty != imported_ty {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let func_name = func.name.clone();
|
|
||||||
dbg!(&func_name);
|
|
||||||
|
|
||||||
if !func.is_pub {
|
|
||||||
state.ok::<_, Infallible>(
|
|
||||||
Err(ErrorKind::FunctionIsPrivate(module_name.clone(), func_name.clone())),
|
|
||||||
import.1,
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
func.is_imported = true;
|
|
||||||
|
|
||||||
if let Some((_, existing)) = importer_module
|
|
||||||
.associated_functions
|
|
||||||
.iter()
|
|
||||||
.find(|(ty, f)| *ty == imported_ty && f.name == *func_name)
|
|
||||||
{
|
|
||||||
if let Err(e) = existing.equals_as_imported(func) {
|
|
||||||
state.ok::<_, Infallible>(
|
|
||||||
Err(ErrorKind::FunctionImportIssue(
|
|
||||||
module_name.clone(),
|
|
||||||
func_name.clone(),
|
|
||||||
e,
|
|
||||||
)),
|
|
||||||
import.1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let types = import_type(&func.return_type, false);
|
|
||||||
let return_type = func.return_type.clone();
|
|
||||||
imported_types.extend(types);
|
|
||||||
|
|
||||||
let mut param_tys = Vec::new();
|
|
||||||
for (param_name, param_ty) in &func.parameters {
|
|
||||||
let types = import_type(¶m_ty, false);
|
|
||||||
imported_types.extend(types);
|
|
||||||
param_tys.push((param_name.clone(), param_ty.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
importer_module.associated_functions.push((
|
|
||||||
ty.clone(),
|
|
||||||
FunctionDefinition {
|
|
||||||
name: func_name.clone(),
|
|
||||||
linkage_name: Some(format!("{}::{}", ty, func_name)),
|
|
||||||
is_pub: false,
|
|
||||||
is_imported: false,
|
|
||||||
return_type,
|
|
||||||
parameters: param_tys,
|
|
||||||
kind: super::FunctionDefinitionKind::Extern(true),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
Err(ErrorKind::ImportDoesNotExist(module_name.clone(), import_name.clone())),
|
Err(ErrorKind::ImportDoesNotExist(module_name.clone(), import_name.clone())),
|
||||||
@ -462,12 +401,13 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
}
|
}
|
||||||
super::ExprKind::BinOp(.., type_kind) => *type_kind = type_kind.update_imported(extern_types, mod_id),
|
super::ExprKind::BinOp(.., type_kind) => *type_kind = type_kind.update_imported(extern_types, mod_id),
|
||||||
|
|
||||||
super::ExprKind::Borrow(..) => {}
|
super::ExprKind::Borrow(var_ref, _) => {
|
||||||
super::ExprKind::Deref(..) => {}
|
var_ref.0 = var_ref.0.update_imported(extern_types, mod_id);
|
||||||
super::ExprKind::CastTo(_, type_kind) => *type_kind = type_kind.update_imported(extern_types, mod_id),
|
|
||||||
super::ExprKind::AssociatedFunctionCall(type_kind, _) => {
|
|
||||||
*type_kind = type_kind.update_imported(extern_types, mod_id)
|
|
||||||
}
|
}
|
||||||
|
super::ExprKind::Deref(var_ref) => {
|
||||||
|
var_ref.0 = var_ref.0.update_imported(extern_types, mod_id);
|
||||||
|
}
|
||||||
|
super::ExprKind::CastTo(_, type_kind) => *type_kind = type_kind.update_imported(extern_types, mod_id),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ pub struct NamedVariableRef(pub TypeKind, pub String, pub Metadata);
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Import(pub Vec<String>, pub Metadata);
|
pub struct Import(pub Vec<String>, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
Variable(NamedVariableRef),
|
Variable(NamedVariableRef),
|
||||||
Indexed(Box<Expression>, TypeKind, Box<Expression>),
|
Indexed(Box<Expression>, TypeKind, Box<Expression>),
|
||||||
@ -261,19 +261,19 @@ pub enum ExprKind {
|
|||||||
AssociatedFunctionCall(TypeKind, FunctionCall),
|
AssociatedFunctionCall(TypeKind, FunctionCall),
|
||||||
If(IfExpression),
|
If(IfExpression),
|
||||||
Block(Block),
|
Block(Block),
|
||||||
Borrow(Box<Expression>, bool),
|
Borrow(NamedVariableRef, bool),
|
||||||
Deref(Box<Expression>),
|
Deref(NamedVariableRef),
|
||||||
CastTo(Box<Expression>, TypeKind),
|
CastTo(Box<Expression>, TypeKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Expression(pub ExprKind, pub Metadata);
|
pub struct Expression(pub ExprKind, pub Metadata);
|
||||||
|
|
||||||
/// Condition, Then, Else
|
/// Condition, Then, Else
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option<Expression>>);
|
pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option<Expression>>);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub return_type: TypeKind,
|
pub return_type: TypeKind,
|
||||||
@ -284,7 +284,6 @@ pub struct FunctionCall {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FunctionDefinition {
|
pub struct FunctionDefinition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub linkage_name: Option<String>,
|
|
||||||
/// Whether this function is visible to outside modules
|
/// Whether this function is visible to outside modules
|
||||||
pub is_pub: bool,
|
pub is_pub: bool,
|
||||||
/// Whether this module is from an external module, and has been imported
|
/// Whether this module is from an external module, and has been imported
|
||||||
@ -328,7 +327,7 @@ impl FunctionDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// List of non-returning statements
|
/// List of non-returning statements
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
@ -336,10 +335,10 @@ pub struct Block {
|
|||||||
pub meta: Metadata,
|
pub meta: Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Statement(pub StmtKind, pub Metadata);
|
pub struct Statement(pub StmtKind, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub enum StmtKind {
|
pub enum StmtKind {
|
||||||
/// Variable name++mutability+type, evaluation
|
/// Variable name++mutability+type, evaluation
|
||||||
Let(NamedVariableRef, bool, Expression),
|
Let(NamedVariableRef, bool, Expression),
|
||||||
@ -349,7 +348,7 @@ pub enum StmtKind {
|
|||||||
While(WhileStatement),
|
While(WhileStatement),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct WhileStatement {
|
pub struct WhileStatement {
|
||||||
pub condition: Expression,
|
pub condition: Expression,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
|
@ -171,27 +171,18 @@ impl<Data: Clone + Default> Scope<Data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_associated_function(&mut self, key: &AssociatedFunctionKey) -> Option<ScopeFunction> {
|
pub fn get_associated_function(&mut self, key: &AssociatedFunctionKey) -> Option<ScopeFunction> {
|
||||||
let ty = if let TypeKind::Borrow(inner, _) = &key.0 {
|
let func = self.associated_functions.get(key);
|
||||||
*inner.clone()
|
|
||||||
} else {
|
|
||||||
key.0.clone()
|
|
||||||
};
|
|
||||||
let key = AssociatedFunctionKey(ty, key.1.clone());
|
|
||||||
|
|
||||||
let func = self.associated_functions.get(&key);
|
|
||||||
if let Some(func) = func {
|
if let Some(func) = func {
|
||||||
Some(func.clone())
|
Some(func.clone())
|
||||||
} else if let Some(func) = get_intrinsic_assoc_func(&key.0, &key.1) {
|
} else if let Some(func) = get_intrinsic_assoc_func(&key.0, &key.1) {
|
||||||
self.associated_functions
|
self.associated_functions.set(
|
||||||
.set(
|
key.clone(),
|
||||||
key.clone(),
|
ScopeFunction {
|
||||||
ScopeFunction {
|
ret: func.return_type,
|
||||||
ret: func.return_type,
|
params: func.parameters.iter().map(|(_, p)| p.clone()).collect(),
|
||||||
params: func.parameters.iter().map(|(_, p)| p.clone()).collect(),
|
},
|
||||||
},
|
);
|
||||||
)
|
self.associated_functions.get(key).cloned()
|
||||||
.unwrap();
|
|
||||||
self.associated_functions.get(&key).cloned()
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -519,8 +510,7 @@ impl Statement {
|
|||||||
StmtKind::Let(_, _, expression) => {
|
StmtKind::Let(_, _, expression) => {
|
||||||
expression.pass(pass, state, scope, mod_id)?;
|
expression.pass(pass, state, scope, mod_id)?;
|
||||||
}
|
}
|
||||||
StmtKind::Set(set_expr, expression) => {
|
StmtKind::Set(_, expression) => {
|
||||||
set_expr.pass(pass, state, scope, mod_id)?;
|
|
||||||
expression.pass(pass, state, scope, mod_id)?;
|
expression.pass(pass, state, scope, mod_id)?;
|
||||||
}
|
}
|
||||||
StmtKind::Import(_) => {}
|
StmtKind::Import(_) => {}
|
||||||
@ -566,52 +556,6 @@ impl Expression {
|
|||||||
mod_id: SourceModuleId,
|
mod_id: SourceModuleId,
|
||||||
) -> PassResult {
|
) -> PassResult {
|
||||||
pass.expr(self, PassState::from(state, scope, Some(mod_id)))?;
|
pass.expr(self, PassState::from(state, scope, Some(mod_id)))?;
|
||||||
match &mut self.0 {
|
|
||||||
ExprKind::Variable(_) => {}
|
|
||||||
ExprKind::Indexed(value_expr, _, index_expr) => {
|
|
||||||
pass.expr(value_expr.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
pass.expr(index_expr.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
ExprKind::Accessed(value_expr, ..) => {
|
|
||||||
pass.expr(value_expr.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
ExprKind::Array(expressions) => {
|
|
||||||
for expr in expressions {
|
|
||||||
pass.expr(expr, PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Struct(_, items) => {
|
|
||||||
for (_, expr) in items {
|
|
||||||
pass.expr(expr, PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Literal(_) => {}
|
|
||||||
ExprKind::BinOp(_, lhs, rhs, _) => {
|
|
||||||
pass.expr(lhs.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
pass.expr(rhs.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
ExprKind::FunctionCall(FunctionCall { parameters, .. }) => {
|
|
||||||
for expr in parameters {
|
|
||||||
pass.expr(expr, PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::AssociatedFunctionCall(_, FunctionCall { parameters, .. }) => {
|
|
||||||
for expr in parameters {
|
|
||||||
pass.expr(expr, PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
|
||||||
pass.expr(cond.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
pass.expr(lhs.as_mut(), PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
if let Some(rhs) = rhs.as_mut() {
|
|
||||||
pass.expr(rhs, PassState::from(state, scope, Some(mod_id)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Block(block) => pass.block(block, PassState::from(state, scope, Some(mod_id)))?,
|
|
||||||
ExprKind::Borrow(expression, _) => pass.expr(expression, PassState::from(state, scope, Some(mod_id)))?,
|
|
||||||
ExprKind::Deref(expression) => pass.expr(expression, PassState::from(state, scope, Some(mod_id)))?,
|
|
||||||
ExprKind::CastTo(expression, _) => pass.expr(expression, PassState::from(state, scope, Some(mod_id)))?,
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,7 @@ pub enum ErrorKind {
|
|||||||
#[error("This type of expression can not be used for assignment")]
|
#[error("This type of expression can not be used for assignment")]
|
||||||
InvalidSetExpression,
|
InvalidSetExpression,
|
||||||
#[error("Can not deref {0}, as it is not a borrow")]
|
#[error("Can not deref {0}, as it is not a borrow")]
|
||||||
AttemptedDerefNonBorrow(TypeKind),
|
AttemptedDerefNonBorrow(String),
|
||||||
#[error("Can not borrow this kind of expression")]
|
|
||||||
ImpossibleBorrow,
|
|
||||||
#[error("Types {0} and {1} differ in mutability")]
|
#[error("Types {0} and {1} differ in mutability")]
|
||||||
TypesDifferMutability(TypeKind, TypeKind),
|
TypesDifferMutability(TypeKind, TypeKind),
|
||||||
#[error("Cannot mutably borrow variable {0}, which is not declared as mutable")]
|
#[error("Cannot mutably borrow variable {0}, which is not declared as mutable")]
|
||||||
@ -154,7 +152,7 @@ impl TypeKind {
|
|||||||
(TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => {
|
(TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => {
|
||||||
// Extracted to give priority for other collapse-error
|
// Extracted to give priority for other collapse-error
|
||||||
let collapsed = val1.narrow_into(val2)?;
|
let collapsed = val1.narrow_into(val2)?;
|
||||||
if mut1 == mut2 || (*mut1 && !mut2) {
|
if mut1 == mut2 {
|
||||||
Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2))
|
Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2))
|
||||||
} else {
|
} else {
|
||||||
Err(ErrorKind::TypesDifferMutability(self.clone(), other.clone()))
|
Err(ErrorKind::TypesDifferMutability(self.clone(), other.clone()))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module contains code relevant to doing a type checking pass on the MIR.
|
//! This module contains code relevant to doing a type checking pass on the MIR.
|
||||||
//! During typechecking relevant types are also coerced if possible.
|
//! During typechecking relevant types are also coerced if possible.
|
||||||
use std::{collections::HashSet, convert::Infallible, hint, iter};
|
use std::{collections::HashSet, convert::Infallible, iter};
|
||||||
|
|
||||||
use crate::{mir::*, util::try_all};
|
use crate::{mir::*, util::try_all};
|
||||||
use VagueType as Vague;
|
use VagueType as Vague;
|
||||||
@ -668,50 +668,61 @@ impl Expression {
|
|||||||
|
|
||||||
Ok(TypeKind::CustomType(type_key))
|
Ok(TypeKind::CustomType(type_key))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(expr, mutable) => {
|
ExprKind::Borrow(var_ref, mutable) => {
|
||||||
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
let scope_var = state.scope.variables.get(&var_ref.1).cloned();
|
||||||
if let TypeKind::Borrow(inner, _) = hint_t {
|
|
||||||
HintKind::Coerce(*inner)
|
|
||||||
} else {
|
|
||||||
return Err(ErrorKind::TypesIncompatible(
|
|
||||||
hint_t,
|
|
||||||
TypeKind::Borrow(Box::new(TypeKind::Vague(VagueType::Unknown)), *mutable),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hint_t
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr_ty = expr.typecheck(state, typerefs, hint_t)?.resolve_ref(typerefs);
|
let existing = state
|
||||||
|
.or_else(
|
||||||
|
scope_var
|
||||||
|
.clone()
|
||||||
|
.map(|var| var.ty)
|
||||||
|
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
||||||
|
TypeKind::Vague(Vague::Unknown),
|
||||||
|
var_ref.2,
|
||||||
|
)
|
||||||
|
.resolve_ref(typerefs);
|
||||||
|
|
||||||
if let Some(backing_var) = expr.backing_var() {
|
if let Some(scope_var) = scope_var {
|
||||||
if let Some(scope_var) = state.scope.variables.get(&backing_var.1) {
|
if !scope_var.mutable && *mutable {
|
||||||
if !scope_var.mutable && *mutable {
|
return Err(ErrorKind::ImpossibleMutableBorrow(var_ref.1.clone()));
|
||||||
return Err(ErrorKind::ImpossibleMutableBorrow(backing_var.1.clone()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(ErrorKind::VariableNotDefined(backing_var.1.clone()));
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return Err(ErrorKind::ImpossibleBorrow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TypeKind::Borrow(Box::new(expr_ty.clone()), *mutable))
|
// Update typing to be more accurate
|
||||||
}
|
var_ref.0 = state.or_else(
|
||||||
ExprKind::Deref(expr) => {
|
var_ref.0.resolve_ref(typerefs).narrow_into(&existing),
|
||||||
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
TypeKind::Vague(Vague::Unknown),
|
||||||
HintKind::Coerce(TypeKind::Borrow(Box::new(hint_t), false))
|
var_ref.2,
|
||||||
} else {
|
);
|
||||||
hint_t
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr_ty = expr.typecheck(state, typerefs, hint_t)?.resolve_ref(typerefs);
|
Ok(TypeKind::Borrow(Box::new(var_ref.0.clone()), *mutable))
|
||||||
|
}
|
||||||
|
ExprKind::Deref(var_ref) => {
|
||||||
|
let existing = state
|
||||||
|
.or_else(
|
||||||
|
state
|
||||||
|
.scope
|
||||||
|
.variables
|
||||||
|
.get(&var_ref.1)
|
||||||
|
.map(|var| &var.ty)
|
||||||
|
.cloned()
|
||||||
|
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
||||||
|
TypeKind::Vague(Vague::Unknown),
|
||||||
|
var_ref.2,
|
||||||
|
)
|
||||||
|
.resolve_ref(typerefs);
|
||||||
|
|
||||||
// Update typing to be more accurate
|
// Update typing to be more accurate
|
||||||
let TypeKind::Borrow(inner, _) = expr_ty else {
|
let TypeKind::Borrow(inner, mutable) = state.or_else(
|
||||||
return Err(ErrorKind::AttemptedDerefNonBorrow(expr_ty.clone()));
|
var_ref.0.resolve_ref(typerefs).narrow_into(&existing),
|
||||||
|
TypeKind::Vague(Vague::Unknown),
|
||||||
|
var_ref.2,
|
||||||
|
) else {
|
||||||
|
return Err(ErrorKind::AttemptedDerefNonBorrow(var_ref.1.clone()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var_ref.0 = TypeKind::Borrow(inner.clone(), mutable);
|
||||||
|
|
||||||
Ok(*inner)
|
Ok(*inner)
|
||||||
}
|
}
|
||||||
ExprKind::CastTo(expression, type_kind) => {
|
ExprKind::CastTo(expression, type_kind) => {
|
||||||
@ -749,9 +760,7 @@ impl Expression {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
|
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
|
||||||
|
|
||||||
for (i, (param, true_param_t)) in
|
for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) {
|
||||||
function_call.parameters.iter_mut().zip(true_params_iter).enumerate()
|
|
||||||
{
|
|
||||||
// Typecheck every param separately
|
// Typecheck every param separately
|
||||||
let param_res = param.typecheck(state, &typerefs, HintKind::Coerce(true_param_t.clone()));
|
let param_res = param.typecheck(state, &typerefs, HintKind::Coerce(true_param_t.clone()));
|
||||||
let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);
|
let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);
|
||||||
|
@ -12,9 +12,8 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mir::{
|
mir::{
|
||||||
pass::{AssociatedFunctionKey, ScopeVariable},
|
pass::AssociatedFunctionKey, BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition,
|
||||||
BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind,
|
FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement,
|
||||||
IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement,
|
|
||||||
},
|
},
|
||||||
util::try_all,
|
util::try_all,
|
||||||
};
|
};
|
||||||
@ -250,18 +249,6 @@ impl Block {
|
|||||||
var.0 = var_ref.as_type();
|
var.0 = var_ref.as_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
state
|
|
||||||
.scope
|
|
||||||
.variables
|
|
||||||
.set(
|
|
||||||
var.1.clone(),
|
|
||||||
ScopeVariable {
|
|
||||||
ty: var.0.clone(),
|
|
||||||
mutable: *mutable,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
// Infer hints for the expression itself
|
// Infer hints for the expression itself
|
||||||
let inferred = expr.infer_types(&mut state, &inner_refs);
|
let inferred = expr.infer_types(&mut state, &inner_refs);
|
||||||
let mut expr_ty_ref = state.ok(inferred, expr.1);
|
let mut expr_ty_ref = state.ok(inferred, expr.1);
|
||||||
@ -570,23 +557,37 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
Ok(type_refs.from_type(&TypeKind::CustomType(type_key.clone())).unwrap())
|
Ok(type_refs.from_type(&TypeKind::CustomType(type_key.clone())).unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(expr, mutable) => {
|
ExprKind::Borrow(var, mutable) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
let type_ref = expr.infer_types(state, type_refs)?;
|
let type_ref = type_refs
|
||||||
|
.find_var(&var.1)
|
||||||
|
.map(|(_, hint)| hint)
|
||||||
|
.ok_or(ErrorKind::VariableNotDefined(var.1.clone()));
|
||||||
|
|
||||||
|
// Update MIR type to TypeRef if found
|
||||||
|
if let Ok(hint) = &type_ref {
|
||||||
|
var.0 = hint.as_type();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(type_refs
|
Ok(type_refs
|
||||||
.from_type(&TypeKind::Borrow(Box::new(type_ref.as_type()), *mutable))
|
.from_type(&TypeKind::Borrow(Box::new(var.0.clone()), *mutable))
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Deref(expr) => {
|
ExprKind::Deref(var) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
let type_ref = expr.infer_types(state, type_refs)?;
|
let type_ref = type_refs
|
||||||
|
.find_var(&var.1)
|
||||||
|
.map(|(_, hint)| hint)
|
||||||
|
.ok_or(ErrorKind::VariableNotDefined(var.1.clone()));
|
||||||
|
|
||||||
// Update typing to be more accurate
|
// Update MIR type to TypeRef if found
|
||||||
|
if let Ok(hint) = &type_ref {
|
||||||
|
var.0 = hint.as_type();
|
||||||
|
}
|
||||||
|
|
||||||
match type_ref.resolve_weak().unwrap() {
|
match &var.0.resolve_weak(type_refs.types) {
|
||||||
Borrow(inner, _) => Ok(type_refs.from_type(&inner).unwrap()),
|
Borrow(type_kind, _) => Ok(type_refs.from_type(&type_kind).unwrap()),
|
||||||
_ => Err(ErrorKind::AttemptedDerefNonBorrow(type_ref.resolve_deep().unwrap())),
|
_ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::CastTo(expression, type_kind) => {
|
ExprKind::CastTo(expression, type_kind) => {
|
||||||
@ -594,42 +595,17 @@ impl Expression {
|
|||||||
Ok(type_refs.from_type(type_kind).unwrap())
|
Ok(type_refs.from_type(type_kind).unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::AssociatedFunctionCall(type_kind, function_call) => {
|
ExprKind::AssociatedFunctionCall(type_kind, function_call) => {
|
||||||
match type_kind.is_known(state) {
|
if type_kind.is_known(state).is_err() {
|
||||||
Ok(_) => {}
|
let first_param = function_call
|
||||||
Err(ErrorKind::NoSuchType(name, mod_id)) => return Err(ErrorKind::NoSuchType(name, mod_id)),
|
.parameters
|
||||||
Err(_) => {
|
.get_mut(0)
|
||||||
let first_param = function_call
|
.expect("Unknown-type associated function NEEDS to always have at least one parameter!");
|
||||||
.parameters
|
let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep();
|
||||||
.get_mut(0)
|
*type_kind = state.or_else(
|
||||||
.expect("Unknown-type associated function NEEDS to always have at least one parameter!");
|
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
|
||||||
let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep();
|
Void,
|
||||||
*type_kind = state
|
first_param.1,
|
||||||
.or_else(
|
);
|
||||||
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
|
|
||||||
Void,
|
|
||||||
first_param.1,
|
|
||||||
)
|
|
||||||
.unroll_borrows()
|
|
||||||
.resolve_ref(type_refs.types);
|
|
||||||
let backing_var = first_param.backing_var().expect("todo").1.clone();
|
|
||||||
|
|
||||||
*first_param = if backing_var == "self" {
|
|
||||||
let ExprKind::Borrow(val, _) = &first_param.0 else {
|
|
||||||
panic!()
|
|
||||||
};
|
|
||||||
*val.clone()
|
|
||||||
} else {
|
|
||||||
first_param.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((mutable, _)) = type_refs.find_var(&backing_var) {
|
|
||||||
if !mutable {
|
|
||||||
first_param.remove_borrow_mutability();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(ErrorKind::VariableNotDefined(backing_var));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get function definition and types
|
// Get function definition and types
|
||||||
@ -659,21 +635,4 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_borrow_mutability(&mut self) {
|
|
||||||
match &mut self.0 {
|
|
||||||
ExprKind::Variable(_) => {}
|
|
||||||
ExprKind::Indexed(value_expr, ..) => value_expr.remove_borrow_mutability(),
|
|
||||||
ExprKind::Accessed(value_expr, ..) => value_expr.remove_borrow_mutability(),
|
|
||||||
ExprKind::Block(block) => {
|
|
||||||
if let Some((_, Some(ret_expr))) = &mut block.return_expression {
|
|
||||||
ret_expr.remove_borrow_mutability();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Borrow(_, mutable) => {
|
|
||||||
*mutable = false;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,6 @@ impl<'scope> TypeRef<'scope> {
|
|||||||
let resolved_elem_ty = self.1.from_type(&elem_ty).unwrap().resolve_weak()?;
|
let resolved_elem_ty = self.1.from_type(&elem_ty).unwrap().resolve_weak()?;
|
||||||
Some(TypeKind::Array(Box::new(resolved_elem_ty), len))
|
Some(TypeKind::Array(Box::new(resolved_elem_ty), len))
|
||||||
}
|
}
|
||||||
TypeKind::Borrow(inner_ty, mutable) => {
|
|
||||||
let resolved_elem_ty = self.1.from_type(&inner_ty).unwrap().resolve_weak()?;
|
|
||||||
Some(TypeKind::Borrow(Box::new(resolved_elem_ty), mutable))
|
|
||||||
}
|
|
||||||
_ => Some(resolved),
|
_ => Some(resolved),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user