Compare commits
No commits in common. "bf8baa7cd48187bc26b3592c0c688b865b3e71d2" and "a8ed7577a8233035c481014a591b74b0c5aaa2f6" have entirely different histories.
bf8baa7cd4
...
a8ed7577a8
@ -1,11 +0,0 @@
|
|||||||
use reid::compile;
|
|
||||||
|
|
||||||
pub static ARRAY: &str = include_str!("./reid/array.reid");
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let text = match compile(ARRAY) {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(e) => panic!("{}", e),
|
|
||||||
};
|
|
||||||
println!("{}", text);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
// Arithmetic, function calls and imports!
|
|
||||||
|
|
||||||
fn array() -> [u16; 4] {
|
|
||||||
return [1, 2, 3, 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> u16 {
|
|
||||||
let heehoo = 10;
|
|
||||||
|
|
||||||
let mut list = array();
|
|
||||||
|
|
||||||
list[1] = 5;
|
|
||||||
|
|
||||||
return list[0];
|
|
||||||
}
|
|
12
reid/examples/reid/medium.reid
Normal file
12
reid/examples/reid/medium.reid
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// if-statements, functions
|
||||||
|
|
||||||
|
import std::print;
|
||||||
|
|
||||||
|
fn fibonacci(value: i32) -> i32 {
|
||||||
|
if value < 3 {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return fibonacci(value - 1) + fibonacci(value - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fibonacci(15));
|
@ -6,10 +6,10 @@ use crate::token_stream::TokenRange;
|
|||||||
pub mod parse;
|
pub mod parse;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Type(pub TypeKind, pub TokenRange);
|
pub struct Type(pub TypeKind, pub TokenRange);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
Bool,
|
Bool,
|
||||||
I8,
|
I8,
|
||||||
@ -22,7 +22,6 @@ pub enum TypeKind {
|
|||||||
U32,
|
U32,
|
||||||
U64,
|
U64,
|
||||||
U128,
|
U128,
|
||||||
Array(Box<TypeKind>, u64),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -38,8 +37,6 @@ pub struct Expression(pub ExpressionKind, pub TokenRange);
|
|||||||
pub enum ExpressionKind {
|
pub enum ExpressionKind {
|
||||||
VariableName(String),
|
VariableName(String),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Array(Vec<Expression>),
|
|
||||||
Index(Box<Expression>, u64),
|
|
||||||
Binop(BinaryOperator, Box<Expression>, Box<Expression>),
|
Binop(BinaryOperator, Box<Expression>, Box<Expression>),
|
||||||
FunctionCall(Box<FunctionCallExpression>),
|
FunctionCall(Box<FunctionCallExpression>),
|
||||||
BlockExpr(Box<Block>),
|
BlockExpr(Box<Block>),
|
||||||
@ -132,17 +129,11 @@ pub struct Block(
|
|||||||
pub TokenRange,
|
pub TokenRange,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum VariableReference {
|
|
||||||
Name(String),
|
|
||||||
Index(Box<VariableReference>, u64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum BlockLevelStatement {
|
pub enum BlockLevelStatement {
|
||||||
Let(LetStatement),
|
Let(LetStatement),
|
||||||
/// Try to set a variable to a specified expression value
|
/// Try to set a variable to a specified expression value
|
||||||
Set(VariableReference, Expression, TokenRange),
|
Set(String, Expression, TokenRange),
|
||||||
Import {
|
Import {
|
||||||
_i: ImportStatement,
|
_i: ImportStatement,
|
||||||
},
|
},
|
||||||
|
@ -13,37 +13,24 @@ where
|
|||||||
|
|
||||||
impl Parse for Type {
|
impl Parse for Type {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
let kind = if let Some(Token::BracketOpen) = stream.peek() {
|
let kind = if let Some(Token::Identifier(ident)) = stream.next() {
|
||||||
stream.expect(Token::BracketOpen)?;
|
Ok(match &*ident {
|
||||||
let inner = stream.parse::<Type>()?;
|
"bool" => TypeKind::Bool,
|
||||||
stream.expect(Token::Semi)?;
|
"i8" => TypeKind::I8,
|
||||||
let length = if let Some(Token::DecimalValue(length)) = stream.next() {
|
"i16" => TypeKind::I16,
|
||||||
length
|
"i32" => TypeKind::I32,
|
||||||
} else {
|
"i64" => TypeKind::I64,
|
||||||
return Err(stream.expected_err("array length (number)")?);
|
"i128" => TypeKind::I128,
|
||||||
};
|
"u8" => TypeKind::U8,
|
||||||
stream.expect(Token::BracketClose)?;
|
"u16" => TypeKind::U16,
|
||||||
TypeKind::Array(Box::new(inner.0), length)
|
"u32" => TypeKind::U32,
|
||||||
|
"u64" => TypeKind::U64,
|
||||||
|
"u128" => TypeKind::U128,
|
||||||
|
_ => panic!("asd"),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
if let Some(Token::Identifier(ident)) = stream.next() {
|
Err(stream.expected_err("type identifier")?)
|
||||||
match &*ident {
|
}?;
|
||||||
"bool" => TypeKind::Bool,
|
|
||||||
"i8" => TypeKind::I8,
|
|
||||||
"i16" => TypeKind::I16,
|
|
||||||
"i32" => TypeKind::I32,
|
|
||||||
"i64" => TypeKind::I64,
|
|
||||||
"i128" => TypeKind::I128,
|
|
||||||
"u8" => TypeKind::U8,
|
|
||||||
"u16" => TypeKind::U16,
|
|
||||||
"u32" => TypeKind::U32,
|
|
||||||
"u64" => TypeKind::U64,
|
|
||||||
"u128" => TypeKind::U128,
|
|
||||||
_ => Err(stream.expected_err("known type identifier")?)?,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(stream.expected_err("type identifier")?)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Type(kind, stream.get_range().unwrap()))
|
Ok(Type(kind, stream.get_range().unwrap()))
|
||||||
}
|
}
|
||||||
@ -63,7 +50,7 @@ impl Parse for PrimaryExpression {
|
|||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
use ExpressionKind as Kind;
|
use ExpressionKind as Kind;
|
||||||
|
|
||||||
let mut expr = if let Ok(exp) = stream.parse() {
|
let expr = if let Ok(exp) = stream.parse() {
|
||||||
Expression(
|
Expression(
|
||||||
Kind::FunctionCall(Box::new(exp)),
|
Kind::FunctionCall(Box::new(exp)),
|
||||||
stream.get_range().unwrap(),
|
stream.get_range().unwrap(),
|
||||||
@ -81,7 +68,7 @@ impl Parse for PrimaryExpression {
|
|||||||
Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap())
|
Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap())
|
||||||
}
|
}
|
||||||
Token::DecimalValue(v) => Expression(
|
Token::DecimalValue(v) => Expression(
|
||||||
Kind::Literal(Literal::Number(*v)),
|
Kind::Literal(Literal::Number(v.parse().unwrap())),
|
||||||
stream.get_range().unwrap(),
|
stream.get_range().unwrap(),
|
||||||
),
|
),
|
||||||
Token::True => Expression(
|
Token::True => Expression(
|
||||||
@ -97,31 +84,11 @@ impl Parse for PrimaryExpression {
|
|||||||
stream.expect(Token::ParenClose)?;
|
stream.expect(Token::ParenClose)?;
|
||||||
exp
|
exp
|
||||||
}
|
}
|
||||||
Token::BracketOpen => {
|
_ => Err(stream.expected_err("identifier, constant or parentheses")?)?,
|
||||||
let mut expressions = Vec::new();
|
|
||||||
if let Ok(exp) = stream.parse() {
|
|
||||||
expressions.push(exp);
|
|
||||||
while let Some(Token::Comma) = stream.peek() {
|
|
||||||
stream.next(); // Consume comma
|
|
||||||
expressions.push(stream.parse()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stream.expect(Token::BracketClose)?;
|
|
||||||
Expression(Kind::Array(expressions), stream.get_range().unwrap())
|
|
||||||
}
|
|
||||||
_ => Err(stream.expected_err("identifier, constant, parentheses or brackets")?)?,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(stream.expected_err("expression")?)?
|
Err(stream.expected_err("expression")?)?
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Ok(ValueIndex(idx)) = stream.parse() {
|
|
||||||
expr = Expression(
|
|
||||||
ExpressionKind::Index(Box::new(expr), idx),
|
|
||||||
stream.get_range().unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(PrimaryExpression(expr))
|
Ok(PrimaryExpression(expr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,6 +321,7 @@ impl Parse for Block {
|
|||||||
// Special list of expressions that are simply not warned about,
|
// Special list of expressions that are simply not warned about,
|
||||||
// if semicolon is missing.
|
// if semicolon is missing.
|
||||||
if !matches!(e, Expression(ExpressionKind::IfExpr(_), _)) {
|
if !matches!(e, Expression(ExpressionKind::IfExpr(_), _)) {
|
||||||
|
dbg!(r_type, &e);
|
||||||
println!("Oh no, does this statement lack ;");
|
println!("Oh no, does this statement lack ;");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,39 +348,6 @@ impl Parse for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for VariableReference {
|
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
|
||||||
if let Some(Token::Identifier(ident)) = stream.next() {
|
|
||||||
let mut var_ref = VariableReference::Name(ident);
|
|
||||||
|
|
||||||
dbg!(&var_ref);
|
|
||||||
while let Ok(ValueIndex(idx)) = stream.parse() {
|
|
||||||
dbg!(idx);
|
|
||||||
var_ref = VariableReference::Index(Box::new(var_ref), idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(var_ref)
|
|
||||||
} else {
|
|
||||||
Err(stream.expected_err("identifier")?)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct ValueIndex(u64);
|
|
||||||
|
|
||||||
impl Parse for ValueIndex {
|
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
|
||||||
stream.expect(Token::BracketOpen)?;
|
|
||||||
if let Some(Token::DecimalValue(idx)) = stream.next() {
|
|
||||||
stream.expect(Token::BracketClose)?;
|
|
||||||
Ok(ValueIndex(idx))
|
|
||||||
} else {
|
|
||||||
return Err(stream.expected_err("array index (number)")?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for BlockLevelStatement {
|
impl Parse for BlockLevelStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
use BlockLevelStatement as Stmt;
|
use BlockLevelStatement as Stmt;
|
||||||
@ -447,15 +382,18 @@ impl Parse for BlockLevelStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SetStatement(VariableReference, Expression, TokenRange);
|
pub struct SetStatement(String, Expression, TokenRange);
|
||||||
|
|
||||||
impl Parse for SetStatement {
|
impl Parse for SetStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
let var_ref = stream.parse()?;
|
if let Some(Token::Identifier(ident)) = stream.next() {
|
||||||
stream.expect(Token::Equals)?;
|
stream.expect(Token::Equals)?;
|
||||||
let expr = stream.parse()?;
|
let expr = stream.parse()?;
|
||||||
stream.expect(Token::Semi)?;
|
stream.expect(Token::Semi)?;
|
||||||
Ok(SetStatement(var_ref, expr, stream.get_range().unwrap()))
|
Ok(Self(ident, expr, stream.get_range().unwrap()))
|
||||||
|
} else {
|
||||||
|
Err(stream.expected_err("identifier")?)?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ impl ast::Module {
|
|||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
return_type: signature
|
return_type: signature
|
||||||
.return_type
|
.return_type
|
||||||
.clone()
|
|
||||||
.map(|r| r.0.into())
|
.map(|r| r.0.into())
|
||||||
.unwrap_or(mir::TypeKind::Void),
|
.unwrap_or(mir::TypeKind::Void),
|
||||||
parameters: signature
|
parameters: signature
|
||||||
@ -45,6 +44,8 @@ impl ast::Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO do something with state here
|
||||||
|
|
||||||
mir::Module {
|
mir::Module {
|
||||||
name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
imports,
|
imports,
|
||||||
@ -64,7 +65,6 @@ impl ast::Block {
|
|||||||
mir::VariableReference(
|
mir::VariableReference(
|
||||||
s_let
|
s_let
|
||||||
.1
|
.1
|
||||||
.clone()
|
|
||||||
.map(|t| t.0.into())
|
.map(|t| t.0.into())
|
||||||
.unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)),
|
.unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)),
|
||||||
s_let.0.clone(),
|
s_let.0.clone(),
|
||||||
@ -79,7 +79,7 @@ impl ast::Block {
|
|||||||
StmtKind::Set(
|
StmtKind::Set(
|
||||||
VariableReference(
|
VariableReference(
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
todo!(), // was name.clone()
|
name.clone(),
|
||||||
(*range).into(),
|
(*range).into(),
|
||||||
),
|
),
|
||||||
expression.process(),
|
expression.process(),
|
||||||
@ -149,8 +149,6 @@ impl ast::Expression {
|
|||||||
};
|
};
|
||||||
mir::ExprKind::If(mir::IfExpression(Box::new(cond), then_block, else_block))
|
mir::ExprKind::If(mir::IfExpression(Box::new(cond), then_block, else_block))
|
||||||
}
|
}
|
||||||
ast::ExpressionKind::Array(expressions) => todo!(),
|
|
||||||
ast::ExpressionKind::Index(expression, _) => todo!(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mir::Expression(kind, self.1.into())
|
mir::Expression(kind, self.1.into())
|
||||||
@ -185,7 +183,7 @@ impl ast::Literal {
|
|||||||
|
|
||||||
impl From<ast::TypeKind> for mir::TypeKind {
|
impl From<ast::TypeKind> for mir::TypeKind {
|
||||||
fn from(value: ast::TypeKind) -> Self {
|
fn from(value: ast::TypeKind) -> Self {
|
||||||
match &value {
|
match value {
|
||||||
ast::TypeKind::Bool => mir::TypeKind::Bool,
|
ast::TypeKind::Bool => mir::TypeKind::Bool,
|
||||||
ast::TypeKind::I8 => mir::TypeKind::I8,
|
ast::TypeKind::I8 => mir::TypeKind::I8,
|
||||||
ast::TypeKind::I16 => mir::TypeKind::I16,
|
ast::TypeKind::I16 => mir::TypeKind::I16,
|
||||||
@ -197,7 +195,6 @@ impl From<ast::TypeKind> for mir::TypeKind {
|
|||||||
ast::TypeKind::U32 => mir::TypeKind::U32,
|
ast::TypeKind::U32 => mir::TypeKind::U32,
|
||||||
ast::TypeKind::U64 => mir::TypeKind::U64,
|
ast::TypeKind::U64 => mir::TypeKind::U64,
|
||||||
ast::TypeKind::U128 => mir::TypeKind::U128,
|
ast::TypeKind::U128 => mir::TypeKind::U128,
|
||||||
ast::TypeKind::Array(type_kind, length) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ pub enum Token {
|
|||||||
// Values
|
// Values
|
||||||
Identifier(String),
|
Identifier(String),
|
||||||
/// Number with at most one decimal point
|
/// Number with at most one decimal point
|
||||||
DecimalValue(u64),
|
DecimalValue(String),
|
||||||
|
|
||||||
// Keywords
|
// Keywords
|
||||||
/// `let`
|
/// `let`
|
||||||
@ -62,10 +62,6 @@ pub enum Token {
|
|||||||
BraceOpen,
|
BraceOpen,
|
||||||
/// `}`
|
/// `}`
|
||||||
BraceClose,
|
BraceClose,
|
||||||
/// `[`
|
|
||||||
BracketOpen,
|
|
||||||
/// `]`
|
|
||||||
BracketClose,
|
|
||||||
/// `,`
|
/// `,`
|
||||||
Comma,
|
Comma,
|
||||||
|
|
||||||
@ -198,7 +194,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
|||||||
value += &c.to_string();
|
value += &c.to_string();
|
||||||
cursor.next();
|
cursor.next();
|
||||||
}
|
}
|
||||||
Token::DecimalValue(value.parse().expect("Decimal not parseable to u64"))
|
Token::DecimalValue(value)
|
||||||
}
|
}
|
||||||
'-' if cursor.first() == Some('>') => {
|
'-' if cursor.first() == Some('>') => {
|
||||||
cursor.next(); // Eat `>`
|
cursor.next(); // Eat `>`
|
||||||
@ -217,8 +213,6 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
|||||||
'!' => Token::Exclamation,
|
'!' => Token::Exclamation,
|
||||||
'(' => Token::ParenOpen,
|
'(' => Token::ParenOpen,
|
||||||
')' => Token::ParenClose,
|
')' => Token::ParenClose,
|
||||||
'[' => Token::BracketOpen,
|
|
||||||
']' => Token::BracketClose,
|
|
||||||
'{' => Token::BraceOpen,
|
'{' => Token::BraceOpen,
|
||||||
'}' => Token::BraceClose,
|
'}' => Token::BraceClose,
|
||||||
',' => Token::Comma,
|
',' => Token::Comma,
|
||||||
|
@ -38,8 +38,6 @@ pub enum ErrorKind {
|
|||||||
InvalidAmountParameters(String, usize, usize),
|
InvalidAmountParameters(String, usize, usize),
|
||||||
#[error("Unable to infer type {0}")]
|
#[error("Unable to infer type {0}")]
|
||||||
TypeNotInferrable(TypeKind),
|
TypeNotInferrable(TypeKind),
|
||||||
#[error("Expected branch type to be {0}, found {1} instead")]
|
|
||||||
BranchTypesDiffer(TypeKind, TypeKind),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Struct used to implement a type-checking pass that can be performed on the
|
/// Struct used to implement a type-checking pass that can be performed on the
|
||||||
@ -120,7 +118,7 @@ impl Block {
|
|||||||
let res = expression.typecheck(&mut state, &hints, Some(var_t_resolved));
|
let res = expression.typecheck(&mut state, &hints, Some(var_t_resolved));
|
||||||
|
|
||||||
// If expression resolution itself was erronous, resolve as
|
// If expression resolution itself was erronous, resolve as
|
||||||
// Unknown and note error.
|
// Unknown.
|
||||||
let res = state.or_else(res, Vague(Unknown), expression.1);
|
let res = state.or_else(res, Vague(Unknown), expression.1);
|
||||||
|
|
||||||
// Make sure the expression and variable type really is the same
|
// Make sure the expression and variable type really is the same
|
||||||
@ -288,8 +286,8 @@ impl Expression {
|
|||||||
rhs.typecheck(state, &hints, Some(collapsed)).ok();
|
rhs.typecheck(state, &hints, Some(collapsed)).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let both_t = lhs_type.collapse_into(&rhs_type)?;
|
let res = lhs_type.binop_type(&op, &rhs_type)?;
|
||||||
Ok(both_t.binop_type(op))
|
Ok(res)
|
||||||
}
|
}
|
||||||
ExprKind::FunctionCall(function_call) => {
|
ExprKind::FunctionCall(function_call) => {
|
||||||
let true_function = state
|
let true_function = state
|
||||||
@ -340,6 +338,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||||
|
// TODO make sure cond_res is Boolean here
|
||||||
let cond_res = cond.typecheck(state, &hints, Some(Bool));
|
let cond_res = cond.typecheck(state, &hints, Some(Bool));
|
||||||
let cond_t = state.or_else(cond_res, Vague(Unknown), cond.1);
|
let cond_t = state.or_else(cond_res, Vague(Unknown), cond.1);
|
||||||
state.ok(cond_t.collapse_into(&Bool), cond.1);
|
state.ok(cond_t.collapse_into(&Bool), cond.1);
|
||||||
@ -352,15 +351,11 @@ impl Expression {
|
|||||||
let res = else_block.typecheck(state, &hints, hint_t);
|
let res = else_block.typecheck(state, &hints, hint_t);
|
||||||
state.or_else(res, Vague(Unknown), else_block.meta)
|
state.or_else(res, Vague(Unknown), else_block.meta)
|
||||||
} else {
|
} else {
|
||||||
// Else return type is Void if it does not exist
|
// TODO assert that then_ret_t is Void
|
||||||
Void
|
Vague(Unknown)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure then and else -blocks have the same return type
|
let collapsed = then_ret_t.collapse_into(&else_ret_t)?;
|
||||||
let collapsed = then_ret_t
|
|
||||||
.collapse_into(&else_ret_t)
|
|
||||||
.or(Err(ErrorKind::BranchTypesDiffer(then_ret_t, else_ret_t)))?;
|
|
||||||
|
|
||||||
if let Some(rhs) = rhs {
|
if let Some(rhs) = rhs {
|
||||||
// If rhs existed, typecheck both sides to perform type
|
// If rhs existed, typecheck both sides to perform type
|
||||||
// coercion.
|
// coercion.
|
||||||
@ -396,8 +391,6 @@ impl Literal {
|
|||||||
(L::U64(_), U64) => self,
|
(L::U64(_), U64) => self,
|
||||||
(L::U128(_), U128) => self,
|
(L::U128(_), U128) => self,
|
||||||
(L::Bool(_), Bool) => self,
|
(L::Bool(_), Bool) => self,
|
||||||
// TODO make sure that v is actually able to fit in the
|
|
||||||
// requested type
|
|
||||||
(L::Vague(VagueL::Number(v)), I8) => L::I8(v as i8),
|
(L::Vague(VagueL::Number(v)), I8) => L::I8(v as i8),
|
||||||
(L::Vague(VagueL::Number(v)), I16) => L::I16(v as i16),
|
(L::Vague(VagueL::Number(v)), I16) => L::I16(v as i16),
|
||||||
(L::Vague(VagueL::Number(v)), I32) => L::I32(v as i32),
|
(L::Vague(VagueL::Number(v)), I32) => L::I32(v as i32),
|
||||||
@ -437,6 +430,17 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn binop_type(&self, op: &BinaryOperator, other: &TypeKind) -> Result<TypeKind, ErrorKind> {
|
||||||
|
let res = self.collapse_into(other)?;
|
||||||
|
Ok(match op {
|
||||||
|
BinaryOperator::Add => res,
|
||||||
|
BinaryOperator::Minus => res,
|
||||||
|
BinaryOperator::Mult => res,
|
||||||
|
BinaryOperator::And => res,
|
||||||
|
BinaryOperator::Cmp(_) => Bool,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
|
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
|
||||||
match self {
|
match self {
|
||||||
Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
|
Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
|
||||||
|
@ -194,6 +194,12 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
rhs: &mut TypeRef<'outer>,
|
rhs: &mut TypeRef<'outer>,
|
||||||
) -> Option<TypeRef<'outer>> {
|
) -> Option<TypeRef<'outer>> {
|
||||||
let ty = lhs.narrow(rhs)?;
|
let ty = lhs.narrow(rhs)?;
|
||||||
self.from_type(&ty.as_type().binop_type(op))
|
Some(match op {
|
||||||
|
BinaryOperator::Add => ty,
|
||||||
|
BinaryOperator::Minus => ty,
|
||||||
|
BinaryOperator::Mult => ty,
|
||||||
|
BinaryOperator::And => self.from_type(&TypeKind::Bool).unwrap(),
|
||||||
|
BinaryOperator::Cmp(_) => self.from_type(&TypeKind::Bool).unwrap(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,24 +9,7 @@ pub enum ReturnTypeOther {
|
|||||||
NoBlockReturn(Metadata),
|
NoBlockReturn(Metadata),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
|
||||||
/// Return the type that is the result of a binary operator between two
|
|
||||||
/// values of this type
|
|
||||||
pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind {
|
|
||||||
// TODO make some type of mechanism that allows to binop two values of
|
|
||||||
// differing types..
|
|
||||||
match op {
|
|
||||||
BinaryOperator::Add => *self,
|
|
||||||
BinaryOperator::Minus => *self,
|
|
||||||
BinaryOperator::Mult => *self,
|
|
||||||
BinaryOperator::And => TypeKind::Bool,
|
|
||||||
BinaryOperator::Cmp(_) => TypeKind::Bool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ReturnType {
|
pub trait ReturnType {
|
||||||
/// Return the return type of this node
|
|
||||||
fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther>;
|
fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +24,9 @@ impl ReturnType for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO should actually probably prune all instructions after this one
|
||||||
|
// as to not cause problems in codegen later (when unable to delete the
|
||||||
|
// block)
|
||||||
if let Some((ReturnKind::Hard, ret_ty)) = early_return {
|
if let Some((ReturnKind::Hard, ret_ty)) = early_return {
|
||||||
return Ok((ReturnKind::Hard, ret_ty));
|
return Ok((ReturnKind::Hard, ret_ty));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user