Compare commits
11 Commits
1c83ca44ab
...
4844cebd56
Author | SHA1 | Date | |
---|---|---|---|
4844cebd56 | |||
195d3d3af8 | |||
00c91fff60 | |||
8838223a7d | |||
1f56fa5dc3 | |||
dc360ef196 | |||
5104555890 | |||
9d5a20e76a | |||
a6a903a45d | |||
676554b6a0 | |||
cc367a38e7 |
@ -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 documentation for the language can be found
|
Specifications and a bunch of [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,6 +18,12 @@ 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
|
||||||
@ -247,6 +253,8 @@ 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
|
||||||
@ -263,7 +271,7 @@ In formal grammar:
|
|||||||
<array> | <struct> |
|
<array> | <struct> |
|
||||||
<indexing> | <accessing> |
|
<indexing> | <accessing> |
|
||||||
<binary-exp> | <unary-exp> |
|
<binary-exp> | <unary-exp> |
|
||||||
<function-call> | <assoc-function-call>
|
<function-call> | <accessing-function-call> | <assoc-function-call>
|
||||||
<block> | <if-expr> | <cast> |
|
<block> | <if-expr> | <cast> |
|
||||||
( "(" <expression> ")" )
|
( "(" <expression> ")" )
|
||||||
|
|
||||||
@ -278,6 +286,7 @@ 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>
|
||||||
@ -296,6 +305,7 @@ 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,6 +22,7 @@ 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
|
||||||
|
|
||||||
@ -119,4 +120,74 @@ fn mutate(value: &mut [u32; 3]) {
|
|||||||
This example will always return `17`. Notice also, how a **mutable** borrow was
|
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!
|
28
documentation/intrinsics.md
Normal file
28
documentation/intrinsics.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
## 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,30 +10,58 @@ Has the following binops defined:
|
|||||||
- `String` + `*char` = `String`
|
- `String` + `*char` = `String`
|
||||||
- `String` + `u64` = `String`
|
- `String` + `u64` = `String`
|
||||||
|
|
||||||
#### `pub fn print(message: String)`
|
##### `String::new() -> String`
|
||||||
|
|
||||||
Prints given `message` to the standard output
|
Returns a new empty `String`-object, which must later be manually freed.
|
||||||
|
|
||||||
|
##### `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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +12,4 @@ fn main() -> u32 {
|
|||||||
fn mutate(value: &mut [u32; 3]) {
|
fn mutate(value: &mut [u32; 3]) {
|
||||||
// Dereference the borrow to mutate it
|
// Dereference the borrow to mutate it
|
||||||
*value[1] = 17;
|
*value[1] = 17;
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,16 @@
|
|||||||
import std::print;
|
import std::print;
|
||||||
import std::from_str;
|
import std::String;
|
||||||
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 = from_str("hello");
|
let mut test = String::from("hello");
|
||||||
|
|
||||||
concat_strings(&mut test, from_str(" world"));
|
test.push(String::from(" world: "));
|
||||||
|
|
||||||
add_char(&mut test, '!');
|
test.push_num(175);
|
||||||
add_char(&mut test, '\n');
|
|
||||||
|
|
||||||
add_num_to_str(&mut test, 175);
|
|
||||||
|
|
||||||
print(test);
|
print(test);
|
||||||
|
|
||||||
free_string(&test);
|
test.free();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,88 @@ 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(String, bool),
|
Borrow(Box<Expression>, bool),
|
||||||
Deref(String),
|
Deref(Box<Expression>),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Array(Vec<Expression>),
|
Array(Vec<Expression>),
|
||||||
ArrayShort(Box<Expression>, u64),
|
ArrayShort(Box<Expression>, u64),
|
||||||
|
@ -179,6 +179,36 @@ 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);
|
||||||
|
|
||||||
@ -195,18 +225,21 @@ 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
|
||||||
let Some(Token::Identifier(name)) = stream.next() else {
|
Expression(
|
||||||
return Err(stream.expected_err("identifier")?);
|
Kind::Borrow(Box::new(stream.parse()?), true),
|
||||||
};
|
stream.get_range().unwrap(),
|
||||||
Expression(Kind::Borrow(name, true), stream.get_range().unwrap())
|
)
|
||||||
} else if let (Some(Token::Et), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
|
} else if let Some(Token::Et) = stream.peek() {
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
stream.next(); // Consume identifier
|
Expression(
|
||||||
Expression(Kind::Borrow(name, false), stream.get_range().unwrap())
|
Kind::Borrow(Box::new(stream.parse()?), false),
|
||||||
} else if let (Some(Token::Star), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
|
stream.get_range().unwrap(),
|
||||||
|
)
|
||||||
|
} else if let Some(Token::Star) = stream.peek() {
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
stream.next(); // Consume identifier
|
apply_inner(stream.parse()?, |e| {
|
||||||
Expression(Kind::Deref(name), stream.get_range().unwrap())
|
Expression(Kind::Deref(Box::new(e.0)), 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()?)),
|
||||||
@ -658,12 +691,23 @@ 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);
|
||||||
|
|
||||||
if let Ok(param) = stream.parse::<FunctionParam>() {
|
match &self_kind {
|
||||||
params.push((param.0, param.1));
|
SelfKind::None => {
|
||||||
while let Some(Token::Comma) = stream.peek() {
|
if let Ok(param) = stream.parse::<FunctionParam>() {
|
||||||
stream.next();
|
params.push((param.0, param.1));
|
||||||
let param = stream.parse::<FunctionParam>()?;
|
while let Some(Token::Comma) = stream.peek() {
|
||||||
params.push((param.0, param.1));
|
stream.next();
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,15 +1063,20 @@ 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();
|
||||||
while let Some(Token::FnKeyword) = stream.peek() {
|
loop {
|
||||||
let mut fun: FunctionDefinition = stream.parse()?;
|
match stream.peek() {
|
||||||
fun.0.self_kind = match fun.0.self_kind {
|
Some(Token::FnKeyword) | Some(Token::PubKeyword) => {
|
||||||
SelfKind::Owned(_) => SelfKind::Owned(ty.0.clone()),
|
let mut fun: FunctionDefinition = stream.parse()?;
|
||||||
SelfKind::Borrow(_) => SelfKind::Borrow(ty.0.clone()),
|
fun.0.self_kind = match fun.0.self_kind {
|
||||||
SelfKind::MutBorrow(_) => SelfKind::MutBorrow(ty.0.clone()),
|
SelfKind::Owned(_) => SelfKind::Owned(ty.0.clone()),
|
||||||
SelfKind::None => SelfKind::None,
|
SelfKind::Borrow(_) => SelfKind::Borrow(ty.0.clone()),
|
||||||
};
|
SelfKind::MutBorrow(_) => SelfKind::MutBorrow(ty.0.clone()),
|
||||||
functions.push(fun);
|
SelfKind::None => SelfKind::None,
|
||||||
|
};
|
||||||
|
functions.push(fun);
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.expect(Token::BraceClose)?;
|
stream.expect(Token::BraceClose)?;
|
||||||
|
@ -36,6 +36,7 @@ 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
|
||||||
@ -149,6 +150,7 @@ 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
|
||||||
@ -361,19 +363,10 @@ impl ast::Expression {
|
|||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
),
|
),
|
||||||
ast::ExpressionKind::Borrow(name, mutable) => mir::ExprKind::Borrow(
|
ast::ExpressionKind::Borrow(expr, mutable) => {
|
||||||
NamedVariableRef(
|
mir::ExprKind::Borrow(Box::new(expr.process(module_id)), *mutable)
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
}
|
||||||
name.clone(),
|
ast::ExpressionKind::Deref(expr) => mir::ExprKind::Deref(Box::new(expr.process(module_id))),
|
||||||
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,
|
||||||
@ -424,7 +417,13 @@ 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(0, expression.process(module_id));
|
params.insert(
|
||||||
|
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,6 +40,7 @@ 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,
|
||||||
@ -48,6 +49,7 @@ 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())),
|
||||||
@ -56,6 +58,7 @@ 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.name,
|
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
||||||
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.name,
|
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
||||||
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.name,
|
&function.linkage_name.clone().unwrap_or(function.name.clone()),
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(&type_values),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
@ -1144,12 +1144,8 @@ impl mir::Expression {
|
|||||||
TypeKind::CustomType(type_key),
|
TypeKind::CustomType(type_key),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Borrow(varref, mutable) => {
|
mir::ExprKind::Borrow(expr, mutable) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
let v = expr.codegen(scope, &state.load(false))?.unwrap();
|
||||||
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!();
|
||||||
@ -1160,12 +1156,8 @@ impl mir::Expression {
|
|||||||
TypeKind::Borrow(Box::new(*ptr_inner.clone()), *mutable),
|
TypeKind::Borrow(Box::new(*ptr_inner.clone()), *mutable),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Deref(varref) => {
|
mir::ExprKind::Deref(expr) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
let v = expr.codegen(scope, &state.load(false))?.unwrap();
|
||||||
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!();
|
||||||
@ -1174,7 +1166,7 @@ impl mir::Expression {
|
|||||||
let var_ptr_instr = scope
|
let var_ptr_instr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build_named(
|
||||||
format!("{}.deref", varref.1),
|
format!("{}.deref", expr.backing_var().unwrap().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();
|
||||||
@ -1187,7 +1179,7 @@ impl mir::Expression {
|
|||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build_named(
|
||||||
format!("{}.deref.inner", varref.1),
|
format!("{}.deref.inner", expr.backing_var().unwrap().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(),
|
||||||
@ -1300,6 +1292,9 @@ 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,6 +208,19 @@ 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 {
|
||||||
@ -425,15 +438,15 @@ impl Expression {
|
|||||||
ReturnKind::Soft,
|
ReturnKind::Soft,
|
||||||
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
||||||
)),
|
)),
|
||||||
Borrow(var, mutable) => {
|
Borrow(expr, mutable) => {
|
||||||
let ret_type = var.return_type()?;
|
let ret_type = expr.return_type(refs, mod_id)?;
|
||||||
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(var) => {
|
Deref(expr) => {
|
||||||
let (kind, ret_type) = var.return_type()?;
|
let (kind, ret_type) = expr.return_type(refs, mod_id)?;
|
||||||
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(var.2)),
|
_ => Err(ReturnTypeOther::DerefNonBorrow(expr.1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) {
|
CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) {
|
||||||
@ -452,8 +465,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(var, _) => Some(var),
|
ExprKind::Borrow(expr, _) => expr.backing_var(),
|
||||||
ExprKind::Deref(var) => Some(var),
|
ExprKind::Deref(expr) => expr.backing_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,7 +227,8 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
importer_module.functions.push(FunctionDefinition {
|
importer_module.functions.push(FunctionDefinition {
|
||||||
name: func_name,
|
name: func_name.clone(),
|
||||||
|
linkage_name: None,
|
||||||
is_pub: false,
|
is_pub: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type,
|
return_type,
|
||||||
@ -268,6 +269,66 @@ 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())),
|
||||||
@ -401,13 +462,12 @@ 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(var_ref, _) => {
|
super::ExprKind::Borrow(..) => {}
|
||||||
var_ref.0 = var_ref.0.update_imported(extern_types, mod_id);
|
super::ExprKind::Deref(..) => {}
|
||||||
}
|
|
||||||
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),
|
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)
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
#[derive(Debug, Clone)]
|
||||||
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(NamedVariableRef, bool),
|
Borrow(Box<Expression>, bool),
|
||||||
Deref(NamedVariableRef),
|
Deref(Box<Expression>),
|
||||||
CastTo(Box<Expression>, TypeKind),
|
CastTo(Box<Expression>, TypeKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Expression(pub ExprKind, pub Metadata);
|
pub struct Expression(pub ExprKind, pub Metadata);
|
||||||
|
|
||||||
/// Condition, Then, Else
|
/// Condition, Then, Else
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub return_type: TypeKind,
|
pub return_type: TypeKind,
|
||||||
@ -284,6 +284,7 @@ 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
|
||||||
@ -327,7 +328,7 @@ impl FunctionDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// List of non-returning statements
|
/// List of non-returning statements
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
@ -335,10 +336,10 @@ pub struct Block {
|
|||||||
pub meta: Metadata,
|
pub meta: Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Statement(pub StmtKind, pub Metadata);
|
pub struct Statement(pub StmtKind, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum StmtKind {
|
pub enum StmtKind {
|
||||||
/// Variable name++mutability+type, evaluation
|
/// Variable name++mutability+type, evaluation
|
||||||
Let(NamedVariableRef, bool, Expression),
|
Let(NamedVariableRef, bool, Expression),
|
||||||
@ -348,7 +349,7 @@ pub enum StmtKind {
|
|||||||
While(WhileStatement),
|
While(WhileStatement),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WhileStatement {
|
pub struct WhileStatement {
|
||||||
pub condition: Expression,
|
pub condition: Expression,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
|
@ -171,18 +171,27 @@ 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 func = self.associated_functions.get(key);
|
let ty = if let TypeKind::Borrow(inner, _) = &key.0 {
|
||||||
|
*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.set(
|
self.associated_functions
|
||||||
key.clone(),
|
.set(
|
||||||
ScopeFunction {
|
key.clone(),
|
||||||
ret: func.return_type,
|
ScopeFunction {
|
||||||
params: func.parameters.iter().map(|(_, p)| p.clone()).collect(),
|
ret: func.return_type,
|
||||||
},
|
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
|
||||||
}
|
}
|
||||||
@ -510,7 +519,8 @@ impl Statement {
|
|||||||
StmtKind::Let(_, _, expression) => {
|
StmtKind::Let(_, _, expression) => {
|
||||||
expression.pass(pass, state, scope, mod_id)?;
|
expression.pass(pass, state, scope, mod_id)?;
|
||||||
}
|
}
|
||||||
StmtKind::Set(_, expression) => {
|
StmtKind::Set(set_expr, 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(_) => {}
|
||||||
@ -556,6 +566,52 @@ 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,7 +65,9 @@ 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(String),
|
AttemptedDerefNonBorrow(TypeKind),
|
||||||
|
#[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")]
|
||||||
@ -152,7 +154,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 {
|
if mut1 == mut2 || (*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, iter};
|
use std::{collections::HashSet, convert::Infallible, hint, iter};
|
||||||
|
|
||||||
use crate::{mir::*, util::try_all};
|
use crate::{mir::*, util::try_all};
|
||||||
use VagueType as Vague;
|
use VagueType as Vague;
|
||||||
@ -668,60 +668,49 @@ impl Expression {
|
|||||||
|
|
||||||
Ok(TypeKind::CustomType(type_key))
|
Ok(TypeKind::CustomType(type_key))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(var_ref, mutable) => {
|
ExprKind::Borrow(expr, mutable) => {
|
||||||
let scope_var = state.scope.variables.get(&var_ref.1).cloned();
|
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
||||||
|
if let TypeKind::Borrow(inner, _) = hint_t {
|
||||||
let existing = state
|
HintKind::Coerce(*inner)
|
||||||
.or_else(
|
} else {
|
||||||
scope_var
|
return Err(ErrorKind::TypesIncompatible(
|
||||||
.clone()
|
hint_t,
|
||||||
.map(|var| var.ty)
|
TypeKind::Borrow(Box::new(TypeKind::Vague(VagueType::Unknown)), *mutable),
|
||||||
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
));
|
||||||
TypeKind::Vague(Vague::Unknown),
|
|
||||||
var_ref.2,
|
|
||||||
)
|
|
||||||
.resolve_ref(typerefs);
|
|
||||||
|
|
||||||
if let Some(scope_var) = scope_var {
|
|
||||||
if !scope_var.mutable && *mutable {
|
|
||||||
return Err(ErrorKind::ImpossibleMutableBorrow(var_ref.1.clone()));
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
hint_t
|
||||||
// Update typing to be more accurate
|
|
||||||
var_ref.0 = state.or_else(
|
|
||||||
var_ref.0.resolve_ref(typerefs).narrow_into(&existing),
|
|
||||||
TypeKind::Vague(Vague::Unknown),
|
|
||||||
var_ref.2,
|
|
||||||
);
|
|
||||||
|
|
||||||
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
|
|
||||||
let TypeKind::Borrow(inner, mutable) = state.or_else(
|
|
||||||
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);
|
let expr_ty = expr.typecheck(state, typerefs, hint_t)?.resolve_ref(typerefs);
|
||||||
|
|
||||||
|
if let Some(backing_var) = expr.backing_var() {
|
||||||
|
if let Some(scope_var) = state.scope.variables.get(&backing_var.1) {
|
||||||
|
if !scope_var.mutable && *mutable {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
ExprKind::Deref(expr) => {
|
||||||
|
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
||||||
|
HintKind::Coerce(TypeKind::Borrow(Box::new(hint_t), false))
|
||||||
|
} else {
|
||||||
|
hint_t
|
||||||
|
};
|
||||||
|
|
||||||
|
let expr_ty = expr.typecheck(state, typerefs, hint_t)?.resolve_ref(typerefs);
|
||||||
|
|
||||||
|
// Update typing to be more accurate
|
||||||
|
let TypeKind::Borrow(inner, _) = expr_ty else {
|
||||||
|
return Err(ErrorKind::AttemptedDerefNonBorrow(expr_ty.clone()));
|
||||||
|
};
|
||||||
|
|
||||||
Ok(*inner)
|
Ok(*inner)
|
||||||
}
|
}
|
||||||
@ -760,7 +749,9 @@ impl Expression {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
|
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
|
||||||
|
|
||||||
for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) {
|
for (i, (param, true_param_t)) in
|
||||||
|
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,8 +12,9 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mir::{
|
mir::{
|
||||||
pass::AssociatedFunctionKey, BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition,
|
pass::{AssociatedFunctionKey, ScopeVariable},
|
||||||
FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement,
|
BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind,
|
||||||
|
IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement,
|
||||||
},
|
},
|
||||||
util::try_all,
|
util::try_all,
|
||||||
};
|
};
|
||||||
@ -249,6 +250,18 @@ 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);
|
||||||
@ -557,37 +570,23 @@ 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(var, mutable) => {
|
ExprKind::Borrow(expr, mutable) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
let type_ref = type_refs
|
let type_ref = expr.infer_types(state, 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(var.0.clone()), *mutable))
|
.from_type(&TypeKind::Borrow(Box::new(type_ref.as_type()), *mutable))
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Deref(var) => {
|
ExprKind::Deref(expr) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
let type_ref = type_refs
|
let type_ref = expr.infer_types(state, type_refs)?;
|
||||||
.find_var(&var.1)
|
|
||||||
.map(|(_, hint)| hint)
|
|
||||||
.ok_or(ErrorKind::VariableNotDefined(var.1.clone()));
|
|
||||||
|
|
||||||
// Update MIR type to TypeRef if found
|
// Update typing to be more accurate
|
||||||
if let Ok(hint) = &type_ref {
|
|
||||||
var.0 = hint.as_type();
|
|
||||||
}
|
|
||||||
|
|
||||||
match &var.0.resolve_weak(type_refs.types) {
|
match type_ref.resolve_weak().unwrap() {
|
||||||
Borrow(type_kind, _) => Ok(type_refs.from_type(&type_kind).unwrap()),
|
Borrow(inner, _) => Ok(type_refs.from_type(&inner).unwrap()),
|
||||||
_ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())),
|
_ => Err(ErrorKind::AttemptedDerefNonBorrow(type_ref.resolve_deep().unwrap())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::CastTo(expression, type_kind) => {
|
ExprKind::CastTo(expression, type_kind) => {
|
||||||
@ -595,17 +594,42 @@ 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) => {
|
||||||
if type_kind.is_known(state).is_err() {
|
match type_kind.is_known(state) {
|
||||||
let first_param = function_call
|
Ok(_) => {}
|
||||||
.parameters
|
Err(ErrorKind::NoSuchType(name, mod_id)) => return Err(ErrorKind::NoSuchType(name, mod_id)),
|
||||||
.get_mut(0)
|
Err(_) => {
|
||||||
.expect("Unknown-type associated function NEEDS to always have at least one parameter!");
|
let first_param = function_call
|
||||||
let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep();
|
.parameters
|
||||||
*type_kind = state.or_else(
|
.get_mut(0)
|
||||||
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
|
.expect("Unknown-type associated function NEEDS to always have at least one parameter!");
|
||||||
Void,
|
let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep();
|
||||||
first_param.1,
|
*type_kind = state
|
||||||
);
|
.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
|
||||||
@ -635,4 +659,21 @@ 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,6 +27,10 @@ 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