Compare commits
No commits in common. "b14a62bc34efef8c5d21e480f28ce7028d38d92c" and "bf8baa7cd48187bc26b3592c0c688b865b3e71d2" have entirely different histories.
b14a62bc34
...
bf8baa7cd4
@ -9,7 +9,7 @@ fn main() -> u16 {
|
|||||||
|
|
||||||
let mut list = array();
|
let mut list = array();
|
||||||
|
|
||||||
// list[1] = 5;
|
list[1] = 5;
|
||||||
|
|
||||||
return list[0];
|
return list[0];
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ fn main() {
|
|||||||
ExprKind::BinOp(
|
ExprKind::BinOp(
|
||||||
BinaryOperator::Cmp(CmpOperator::GT),
|
BinaryOperator::Cmp(CmpOperator::GT),
|
||||||
Box::new(Expression(
|
Box::new(Expression(
|
||||||
ExprKind::Variable(NamedVariableRef(
|
ExprKind::Variable(VariableReference(
|
||||||
TypeKind::I32,
|
TypeKind::I32,
|
||||||
"N".to_string(),
|
"N".to_string(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
@ -52,7 +52,7 @@ fn main() {
|
|||||||
BinaryOperator::Minus,
|
BinaryOperator::Minus,
|
||||||
Box::new(Expression(
|
Box::new(Expression(
|
||||||
ExprKind::Variable(
|
ExprKind::Variable(
|
||||||
NamedVariableRef(
|
VariableReference(
|
||||||
TypeKind::I32,
|
TypeKind::I32,
|
||||||
fibonacci_n.clone(),
|
fibonacci_n.clone(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
@ -80,7 +80,7 @@ fn main() {
|
|||||||
BinaryOperator::Minus,
|
BinaryOperator::Minus,
|
||||||
Box::new(Expression(
|
Box::new(Expression(
|
||||||
ExprKind::Variable(
|
ExprKind::Variable(
|
||||||
NamedVariableRef(
|
VariableReference(
|
||||||
TypeKind::I32,
|
TypeKind::I32,
|
||||||
fibonacci_n.clone(),
|
fibonacci_n.clone(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -133,11 +133,8 @@ pub struct Block(
|
|||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VariableReference(pub VariableReferenceKind, pub TokenRange);
|
pub enum VariableReference {
|
||||||
|
Name(String),
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum VariableReferenceKind {
|
|
||||||
Name(String, TokenRange),
|
|
||||||
Index(Box<VariableReference>, u64),
|
Index(Box<VariableReference>, u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ impl Parse for Block {
|
|||||||
stream.expect(Token::BraceOpen)?;
|
stream.expect(Token::BraceOpen)?;
|
||||||
|
|
||||||
while !matches!(stream.peek(), Some(Token::BraceClose)) {
|
while !matches!(stream.peek(), Some(Token::BraceClose)) {
|
||||||
if let Some((_, e)) = return_stmt.take() {
|
if let Some((r_type, e)) = return_stmt.take() {
|
||||||
// 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(_), _)) {
|
||||||
@ -383,18 +383,12 @@ impl Parse for Block {
|
|||||||
impl Parse for VariableReference {
|
impl Parse for VariableReference {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
if let Some(Token::Identifier(ident)) = stream.next() {
|
if let Some(Token::Identifier(ident)) = stream.next() {
|
||||||
let mut var_ref = VariableReference(
|
let mut var_ref = VariableReference::Name(ident);
|
||||||
VariableReferenceKind::Name(ident, stream.get_one_token_range()),
|
|
||||||
stream.get_range().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
dbg!(&var_ref);
|
dbg!(&var_ref);
|
||||||
while let Ok(ValueIndex(idx)) = stream.parse() {
|
while let Ok(ValueIndex(idx)) = stream.parse() {
|
||||||
dbg!(idx);
|
dbg!(idx);
|
||||||
var_ref = VariableReference(
|
var_ref = VariableReference::Index(Box::new(var_ref), idx);
|
||||||
VariableReferenceKind::Index(Box::new(var_ref), idx),
|
|
||||||
stream.get_range().unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(var_ref)
|
Ok(var_ref)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::{self},
|
ast::{self},
|
||||||
mir::{self, NamedVariableRef, StmtKind},
|
mir::{self, StmtKind, VariableReference},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl mir::Context {
|
impl mir::Context {
|
||||||
@ -61,7 +61,7 @@ impl ast::Block {
|
|||||||
let (kind, range) = match statement {
|
let (kind, range) = match statement {
|
||||||
ast::BlockLevelStatement::Let(s_let) => (
|
ast::BlockLevelStatement::Let(s_let) => (
|
||||||
mir::StmtKind::Let(
|
mir::StmtKind::Let(
|
||||||
mir::NamedVariableRef(
|
mir::VariableReference(
|
||||||
s_let
|
s_let
|
||||||
.1
|
.1
|
||||||
.clone()
|
.clone()
|
||||||
@ -75,8 +75,15 @@ impl ast::Block {
|
|||||||
),
|
),
|
||||||
s_let.4,
|
s_let.4,
|
||||||
),
|
),
|
||||||
ast::BlockLevelStatement::Set(var_ref, expression, range) => (
|
ast::BlockLevelStatement::Set(name, expression, range) => (
|
||||||
StmtKind::Set(var_ref.process(), expression.process()),
|
StmtKind::Set(
|
||||||
|
VariableReference(
|
||||||
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
|
todo!(), // was name.clone()
|
||||||
|
(*range).into(),
|
||||||
|
),
|
||||||
|
expression.process(),
|
||||||
|
),
|
||||||
*range,
|
*range,
|
||||||
),
|
),
|
||||||
ast::BlockLevelStatement::Import { _i } => todo!(),
|
ast::BlockLevelStatement::Import { _i } => todo!(),
|
||||||
@ -110,36 +117,10 @@ impl From<ast::ReturnType> for mir::ReturnKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::VariableReference {
|
|
||||||
fn process(&self) -> mir::IndexedVariableReference {
|
|
||||||
mir::IndexedVariableReference {
|
|
||||||
kind: self.0.process(),
|
|
||||||
meta: self.1.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::VariableReferenceKind {
|
|
||||||
fn process(&self) -> mir::IndexedVariableReferenceKind {
|
|
||||||
match &self {
|
|
||||||
ast::VariableReferenceKind::Name(name, range) => {
|
|
||||||
mir::IndexedVariableReferenceKind::Named(NamedVariableRef(
|
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
|
||||||
name.clone(),
|
|
||||||
(*range).into(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
ast::VariableReferenceKind::Index(var_ref, idx) => {
|
|
||||||
mir::IndexedVariableReferenceKind::Index(Box::new(var_ref.process()), *idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::Expression {
|
impl ast::Expression {
|
||||||
fn process(&self) -> mir::Expression {
|
fn process(&self) -> mir::Expression {
|
||||||
let kind = match &self.0 {
|
let kind = match &self.0 {
|
||||||
ast::ExpressionKind::VariableName(name) => mir::ExprKind::Variable(NamedVariableRef(
|
ast::ExpressionKind::VariableName(name) => mir::ExprKind::Variable(VariableReference(
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
self.1.into(),
|
self.1.into(),
|
||||||
@ -168,12 +149,8 @@ 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) => {
|
ast::ExpressionKind::Array(expressions) => todo!(),
|
||||||
mir::ExprKind::Array(expressions.iter().map(|e| e.process()).collect())
|
ast::ExpressionKind::Index(expression, _) => todo!(),
|
||||||
}
|
|
||||||
ast::ExpressionKind::Index(expression, idx) => {
|
|
||||||
mir::ExprKind::Index(Box::new(expression.process()), *idx)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mir::Expression(kind, self.1.into())
|
mir::Expression(kind, self.1.into())
|
||||||
@ -220,9 +197,7 @@ 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) => {
|
ast::TypeKind::Array(type_kind, length) => todo!(),
|
||||||
mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use reid_lib::{
|
|||||||
TerminatorKind as Term, Type,
|
TerminatorKind as Term, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::mir::{self, types::ReturnType, NamedVariableRef, TypeKind};
|
use crate::mir::{self, types::ReturnType, TypeKind, VariableReference};
|
||||||
|
|
||||||
/// Context that contains all of the given modules as complete codegenerated
|
/// Context that contains all of the given modules as complete codegenerated
|
||||||
/// LLIR that can then be finally compiled into LLVM IR.
|
/// LLIR that can then be finally compiled into LLVM IR.
|
||||||
@ -156,7 +156,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
impl mir::Statement {
|
impl mir::Statement {
|
||||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option<InstructionValue> {
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option<InstructionValue> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => {
|
mir::StmtKind::Let(VariableReference(ty, name, _), mutable, expression) => {
|
||||||
let value = expression.codegen(scope).unwrap();
|
let value = expression.codegen(scope).unwrap();
|
||||||
scope.stack_values.insert(
|
scope.stack_values.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
@ -178,20 +178,19 @@ impl mir::Statement {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
mir::StmtKind::Set(var, val) => {
|
mir::StmtKind::Set(var, val) => {
|
||||||
todo!("Re-think how set needs to work with arrays");
|
if let Some(StackValue(kind, _)) = scope.stack_values.get(&var.1).cloned() {
|
||||||
// if let Some(StackValue(kind, _)) = scope.stack_values.get(&var.1).cloned() {
|
match kind {
|
||||||
// match kind {
|
StackValueKind::Immutable(_) => {
|
||||||
// StackValueKind::Immutable(_) => {
|
panic!("Tried to mutate an immutable variable")
|
||||||
// panic!("Tried to mutate an immutable variable")
|
}
|
||||||
// }
|
StackValueKind::Mutable(ptr) => {
|
||||||
// StackValueKind::Mutable(ptr) => {
|
let expression = val.codegen(scope).unwrap();
|
||||||
// let expression = val.codegen(scope).unwrap();
|
Some(scope.block.build(Instr::Store(ptr, expression)).unwrap())
|
||||||
// Some(scope.block.build(Instr::Store(ptr, expression)).unwrap())
|
}
|
||||||
// }
|
}
|
||||||
// }
|
} else {
|
||||||
// } else {
|
panic!("")
|
||||||
// panic!("")
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
// mir::StmtKind::If(if_expression) => if_expression.codegen(scope),
|
// mir::StmtKind::If(if_expression) => if_expression.codegen(scope),
|
||||||
mir::StmtKind::Import(_) => todo!(),
|
mir::StmtKind::Import(_) => todo!(),
|
||||||
@ -334,8 +333,6 @@ impl mir::Expression {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Index(expression, _) => todo!("codegen for index expression"),
|
|
||||||
mir::ExprKind::Array(expressions) => todo!("codegen for array expression"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,7 +413,6 @@ impl TypeKind {
|
|||||||
TypeKind::Bool => Type::Bool,
|
TypeKind::Bool => Type::Bool,
|
||||||
TypeKind::Void => panic!("Void not a supported type"),
|
TypeKind::Void => panic!("Void not a supported type"),
|
||||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||||
TypeKind::Array(_, _) => todo!("codegen for array type"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,33 +122,12 @@ impl Display for Expression {
|
|||||||
impl Display for ExprKind {
|
impl Display for ExprKind {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ExprKind::Variable(var) => Display::fmt(var, f),
|
Self::Variable(var) => Display::fmt(var, f),
|
||||||
ExprKind::Literal(lit) => Display::fmt(lit, f),
|
Self::Literal(lit) => Display::fmt(lit, f),
|
||||||
ExprKind::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs),
|
Self::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs),
|
||||||
ExprKind::FunctionCall(fc) => Display::fmt(fc, f),
|
Self::FunctionCall(fc) => Display::fmt(fc, f),
|
||||||
ExprKind::If(if_exp) => Display::fmt(&if_exp, f),
|
Self::If(if_exp) => Display::fmt(&if_exp, f),
|
||||||
ExprKind::Block(block) => Display::fmt(block, f),
|
Self::Block(block) => Display::fmt(block, f),
|
||||||
ExprKind::Index(expression, idx) => {
|
|
||||||
Display::fmt(&expression, f)?;
|
|
||||||
write_index(f, *idx)
|
|
||||||
}
|
|
||||||
ExprKind::Array(expressions) => {
|
|
||||||
f.write_char('[')?;
|
|
||||||
|
|
||||||
let mut state = Default::default();
|
|
||||||
let mut inner_f = PadAdapter::wrap(f, &mut state);
|
|
||||||
|
|
||||||
let mut iter = expressions.iter();
|
|
||||||
if let Some(item) = iter.next() {
|
|
||||||
write!(inner_f, "\n{}", item)?;
|
|
||||||
while let Some(item) = iter.next() {
|
|
||||||
writeln!(inner_f, ",")?;
|
|
||||||
write!(inner_f, "{}", item)?;
|
|
||||||
}
|
|
||||||
writeln!(inner_f, "")?;
|
|
||||||
}
|
|
||||||
f.write_char(']')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,24 +156,12 @@ impl Display for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for NamedVariableRef {
|
impl Display for VariableReference {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "v(\"{}\", {})", &self.1, &self.0)
|
write!(f, "v(\"{}\", {})", &self.1, &self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IndexedVariableReference {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match &self.kind {
|
|
||||||
IndexedVariableReferenceKind::Named(name) => Display::fmt(name, f),
|
|
||||||
IndexedVariableReferenceKind::Index(variable_reference_kind, idx) => {
|
|
||||||
Display::fmt(&variable_reference_kind, f)?;
|
|
||||||
write_index(f, *idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Literal {
|
impl Display for Literal {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -244,9 +211,3 @@ impl Display for Metadata {
|
|||||||
write!(f, "{:?}", self.range)
|
write!(f, "{:?}", self.range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_index(f: &mut std::fmt::Formatter<'_>, idx: u64) -> std::fmt::Result {
|
|
||||||
f.write_char('[')?;
|
|
||||||
Display::fmt(&idx, f)?;
|
|
||||||
f.write_char(']')
|
|
||||||
}
|
|
||||||
|
@ -32,7 +32,7 @@ impl From<TokenRange> for Metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
#[error("bool")]
|
#[error("bool")]
|
||||||
Bool,
|
Bool,
|
||||||
@ -58,8 +58,6 @@ pub enum TypeKind {
|
|||||||
U128,
|
U128,
|
||||||
#[error("void")]
|
#[error("void")]
|
||||||
Void,
|
Void,
|
||||||
#[error("[{0}; {1}]")]
|
|
||||||
Array(Box<TypeKind>, u64),
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Vague(#[from] VagueType),
|
Vague(#[from] VagueType),
|
||||||
}
|
}
|
||||||
@ -79,7 +77,7 @@ impl TypeKind {
|
|||||||
if let TypeKind::Vague(vague) = self {
|
if let TypeKind::Vague(vague) = self {
|
||||||
Err(*vague)
|
Err(*vague)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.clone())
|
Ok(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +98,6 @@ impl TypeKind {
|
|||||||
TypeKind::U32 => false,
|
TypeKind::U32 => false,
|
||||||
TypeKind::U64 => false,
|
TypeKind::U64 => false,
|
||||||
TypeKind::U128 => false,
|
TypeKind::U128 => false,
|
||||||
TypeKind::Array(_, _) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +117,6 @@ impl TypeKind {
|
|||||||
Bool => true,
|
Bool => true,
|
||||||
Vague(_) => false,
|
Vague(_) => false,
|
||||||
Void => false,
|
Void => false,
|
||||||
Array(_, _) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,16 +196,14 @@ pub enum ReturnKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NamedVariableRef(pub TypeKind, pub String, pub Metadata);
|
pub struct VariableReference(pub TypeKind, pub String, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Import(pub String, pub Metadata);
|
pub struct Import(pub String, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
Variable(NamedVariableRef),
|
Variable(VariableReference),
|
||||||
Index(Box<Expression>, u64),
|
|
||||||
Array(Vec<Expression>),
|
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
BinOp(BinaryOperator, Box<Expression>, Box<Expression>),
|
BinOp(BinaryOperator, Box<Expression>, Box<Expression>),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
@ -273,23 +267,11 @@ pub struct Block {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Statement(pub StmtKind, pub Metadata);
|
pub struct Statement(pub StmtKind, pub Metadata);
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct IndexedVariableReference {
|
|
||||||
pub kind: IndexedVariableReferenceKind,
|
|
||||||
pub meta: Metadata,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum IndexedVariableReferenceKind {
|
|
||||||
Named(NamedVariableRef),
|
|
||||||
Index(Box<IndexedVariableReference>, u64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum StmtKind {
|
pub enum StmtKind {
|
||||||
/// Variable name++mutability+type, evaluation
|
/// Variable name++mutability+type, evaluation
|
||||||
Let(NamedVariableRef, bool, Expression),
|
Let(VariableReference, bool, Expression),
|
||||||
Set(IndexedVariableReference, Expression),
|
Set(VariableReference, Expression),
|
||||||
Import(Import),
|
Import(Import),
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
//! passes. Passes can be performed on Reid MIR to e.g. typecheck the code.
|
//! passes. Passes can be performed on Reid MIR to e.g. typecheck the code.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::Infallible;
|
|
||||||
use std::error::Error as STDError;
|
use std::error::Error as STDError;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -130,7 +129,7 @@ impl Scope {
|
|||||||
Scope {
|
Scope {
|
||||||
function_returns: self.function_returns.clone(),
|
function_returns: self.function_returns.clone(),
|
||||||
variables: self.variables.clone(),
|
variables: self.variables.clone(),
|
||||||
return_type_hint: self.return_type_hint.clone(),
|
return_type_hint: self.return_type_hint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,16 +166,6 @@ impl<'st, 'sc, TError: STDError + Clone> PassState<'st, 'sc, TError> {
|
|||||||
self.state.ok(result, meta)
|
self.state.ok(result, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn note_errors<TMeta: Into<Metadata> + Clone>(
|
|
||||||
&mut self,
|
|
||||||
errors: &Vec<TError>,
|
|
||||||
meta: TMeta,
|
|
||||||
) {
|
|
||||||
for error in errors {
|
|
||||||
self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inner(&mut self) -> PassState<TError> {
|
pub fn inner(&mut self) -> PassState<TError> {
|
||||||
self.inner.push(self.scope.inner());
|
self.inner.push(self.scope.inner());
|
||||||
let scope = self.inner.last_mut().unwrap();
|
let scope = self.inner.last_mut().unwrap();
|
||||||
@ -222,8 +211,8 @@ impl Module {
|
|||||||
.set(
|
.set(
|
||||||
function.name.clone(),
|
function.name.clone(),
|
||||||
ScopeFunction {
|
ScopeFunction {
|
||||||
ret: function.return_type.clone(),
|
ret: function.return_type,
|
||||||
params: function.parameters.iter().cloned().map(|v| v.1).collect(),
|
params: function.parameters.iter().map(|v| v.1).collect(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
@ -245,7 +234,7 @@ impl FunctionDefinition {
|
|||||||
.set(
|
.set(
|
||||||
param.0.clone(),
|
param.0.clone(),
|
||||||
ScopeVariable {
|
ScopeVariable {
|
||||||
ty: param.1.clone(),
|
ty: param.1,
|
||||||
mutable: false,
|
mutable: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -256,7 +245,7 @@ impl FunctionDefinition {
|
|||||||
|
|
||||||
match &mut self.kind {
|
match &mut self.kind {
|
||||||
FunctionDefinitionKind::Local(block, _) => {
|
FunctionDefinitionKind::Local(block, _) => {
|
||||||
scope.return_type_hint = Some(self.return_type.clone());
|
scope.return_type_hint = Some(self.return_type);
|
||||||
block.pass(pass, state, scope);
|
block.pass(pass, state, scope);
|
||||||
}
|
}
|
||||||
FunctionDefinitionKind::Extern => {}
|
FunctionDefinitionKind::Extern => {}
|
||||||
@ -300,7 +289,7 @@ impl Statement {
|
|||||||
.set(
|
.set(
|
||||||
variable_reference.1.clone(),
|
variable_reference.1.clone(),
|
||||||
ScopeVariable {
|
ScopeVariable {
|
||||||
ty: variable_reference.0.clone(),
|
ty: variable_reference.0,
|
||||||
mutable: *mutable,
|
mutable: *mutable,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -40,10 +40,6 @@ pub enum ErrorKind {
|
|||||||
TypeNotInferrable(TypeKind),
|
TypeNotInferrable(TypeKind),
|
||||||
#[error("Expected branch type to be {0}, found {1} instead")]
|
#[error("Expected branch type to be {0}, found {1} instead")]
|
||||||
BranchTypesDiffer(TypeKind, TypeKind),
|
BranchTypesDiffer(TypeKind, TypeKind),
|
||||||
#[error("Attempted to index a non-array type of {0}")]
|
|
||||||
TriedIndexingNonArray(TypeKind),
|
|
||||||
#[error("Index {0} out of bounds ({1})")]
|
|
||||||
IndexOutOfBounds(u64, u64),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
@ -88,8 +84,8 @@ impl FunctionDefinition {
|
|||||||
let return_type = self.return_type.clone();
|
let return_type = self.return_type.clone();
|
||||||
let inferred = match &mut self.kind {
|
let inferred = match &mut self.kind {
|
||||||
FunctionDefinitionKind::Local(block, _) => {
|
FunctionDefinitionKind::Local(block, _) => {
|
||||||
state.scope.return_type_hint = Some(self.return_type.clone());
|
state.scope.return_type_hint = Some(self.return_type);
|
||||||
block.typecheck(state, &hints, Some(&return_type))
|
block.typecheck(state, &hints, Some(return_type))
|
||||||
}
|
}
|
||||||
FunctionDefinitionKind::Extern => Ok(Vague(Unknown)),
|
FunctionDefinitionKind::Extern => Ok(Vague(Unknown)),
|
||||||
};
|
};
|
||||||
@ -108,7 +104,7 @@ impl Block {
|
|||||||
&mut self,
|
&mut self,
|
||||||
state: &mut PassState<ErrorKind>,
|
state: &mut PassState<ErrorKind>,
|
||||||
hints: &TypeRefs,
|
hints: &TypeRefs,
|
||||||
hint_t: Option<&TypeKind>,
|
hint_t: Option<TypeKind>,
|
||||||
) -> Result<TypeKind, ErrorKind> {
|
) -> Result<TypeKind, ErrorKind> {
|
||||||
let mut state = state.inner();
|
let mut state = state.inner();
|
||||||
|
|
||||||
@ -121,7 +117,7 @@ impl Block {
|
|||||||
let var_t_resolved = variable_reference.0.resolve_hinted(&hints);
|
let var_t_resolved = variable_reference.0.resolve_hinted(&hints);
|
||||||
|
|
||||||
// Typecheck (and coerce) expression with said type
|
// Typecheck (and coerce) expression with said type
|
||||||
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 and note error.
|
||||||
@ -140,7 +136,7 @@ impl Block {
|
|||||||
state.or_else(res_t.or_default(), Vague(Unknown), variable_reference.2);
|
state.or_else(res_t.or_default(), Vague(Unknown), variable_reference.2);
|
||||||
|
|
||||||
// Re-typecheck and coerce expression to default type
|
// Re-typecheck and coerce expression to default type
|
||||||
let expr_res = expression.typecheck(&mut state, &hints, Some(&res_t));
|
let expr_res = expression.typecheck(&mut state, &hints, Some(res_t));
|
||||||
state.ok(expr_res, expression.1);
|
state.ok(expr_res, expression.1);
|
||||||
|
|
||||||
res_t
|
res_t
|
||||||
@ -158,7 +154,7 @@ impl Block {
|
|||||||
.set(
|
.set(
|
||||||
variable_reference.1.clone(),
|
variable_reference.1.clone(),
|
||||||
ScopeVariable {
|
ScopeVariable {
|
||||||
ty: variable_reference.0.clone(),
|
ty: variable_reference.0,
|
||||||
mutable: *mutable,
|
mutable: *mutable,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -169,41 +165,40 @@ impl Block {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
StmtKind::Set(variable_reference, expression) => {
|
StmtKind::Set(variable_reference, expression) => {
|
||||||
todo!("Re-think how set needs to work with arrays")
|
if let Some(var) = state.scope.variables.get(&variable_reference.1).cloned() {
|
||||||
// if let Some(var) = state.scope.variables.get(&variable_reference.1).cloned() {
|
// Typecheck expression and coerce to variable type
|
||||||
// // Typecheck expression and coerce to variable type
|
let res = expression.typecheck(&mut state, &hints, Some(var.ty));
|
||||||
// let res = expression.typecheck(&mut state, &hints, Some(&var.ty));
|
|
||||||
|
|
||||||
// // If expression resolution itself was erronous, resolve as
|
// If expression resolution itself was erronous, resolve as
|
||||||
// // Unknown.
|
// Unknown.
|
||||||
// let expr_ty = state.or_else(res, Vague(Unknown), expression.1);
|
let expr_ty = state.or_else(res, Vague(Unknown), expression.1);
|
||||||
|
|
||||||
// // Make sure the expression and variable type to really
|
// Make sure the expression and variable type to really
|
||||||
// // be the same
|
// be the same
|
||||||
// let res_t = state.or_else(
|
let res_t = state.or_else(
|
||||||
// expr_ty.collapse_into(&variable_reference.0.resolve_hinted(&hints)),
|
expr_ty.collapse_into(&variable_reference.0.resolve_hinted(&hints)),
|
||||||
// Vague(Unknown),
|
Vague(Unknown),
|
||||||
// variable_reference.2 + expression.1,
|
variable_reference.2 + expression.1,
|
||||||
// );
|
);
|
||||||
|
|
||||||
// // Update typing to be more accurate
|
// Update typing to be more accurate
|
||||||
// variable_reference.0 = res_t;
|
variable_reference.0 = res_t;
|
||||||
|
|
||||||
// if !var.mutable {
|
if !var.mutable {
|
||||||
// state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
// Err(ErrorKind::VariableNotMutable(variable_reference.1.clone())),
|
Err(ErrorKind::VariableNotMutable(variable_reference.1.clone())),
|
||||||
// variable_reference.2,
|
variable_reference.2,
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// None
|
None
|
||||||
// } else {
|
} else {
|
||||||
// state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
// Err(ErrorKind::VariableNotDefined(variable_reference.1.clone())),
|
Err(ErrorKind::VariableNotDefined(variable_reference.1.clone())),
|
||||||
// variable_reference.2,
|
variable_reference.2,
|
||||||
// );
|
);
|
||||||
// None
|
None
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Import(_) => todo!(), // TODO
|
StmtKind::Import(_) => todo!(), // TODO
|
||||||
StmtKind::Expression(expression) => {
|
StmtKind::Expression(expression) => {
|
||||||
@ -226,18 +221,18 @@ impl Block {
|
|||||||
// as to not cause problems in codegen later (when unable to delete the
|
// as to not cause problems in codegen later (when unable to delete the
|
||||||
// block)
|
// block)
|
||||||
if let Some((ReturnKind::Hard, expr)) = early_return {
|
if let Some((ReturnKind::Hard, expr)) = early_return {
|
||||||
let hint = state.scope.return_type_hint.clone();
|
let hint = state.scope.return_type_hint;
|
||||||
let res = expr.typecheck(&mut state, &hints, hint.as_ref());
|
let res = expr.typecheck(&mut state, &hints, hint);
|
||||||
return Ok(state.or_else(res, Vague(Unknown), expr.1));
|
return Ok(state.or_else(res, Vague(Unknown), expr.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((return_kind, expr)) = &mut self.return_expression {
|
if let Some((return_kind, expr)) = &mut self.return_expression {
|
||||||
// Use function return type as hint if return is hard.
|
// Use function return type as hint if return is hard.
|
||||||
let ret_hint_t = match return_kind {
|
let ret_hint_t = match return_kind {
|
||||||
ReturnKind::Hard => state.scope.return_type_hint.clone(),
|
ReturnKind::Hard => state.scope.return_type_hint,
|
||||||
ReturnKind::Soft => hint_t.cloned(),
|
ReturnKind::Soft => hint_t,
|
||||||
};
|
};
|
||||||
let res = expr.typecheck(&mut state, &hints, ret_hint_t.as_ref());
|
let res = expr.typecheck(&mut state, &hints, ret_hint_t);
|
||||||
Ok(state.or_else(res, Vague(Unknown), expr.1))
|
Ok(state.or_else(res, Vague(Unknown), expr.1))
|
||||||
} else {
|
} else {
|
||||||
Ok(Void)
|
Ok(Void)
|
||||||
@ -250,7 +245,7 @@ impl Expression {
|
|||||||
&mut self,
|
&mut self,
|
||||||
state: &mut PassState<ErrorKind>,
|
state: &mut PassState<ErrorKind>,
|
||||||
hints: &TypeRefs,
|
hints: &TypeRefs,
|
||||||
hint_t: Option<&TypeKind>,
|
hint_t: Option<TypeKind>,
|
||||||
) -> Result<TypeKind, ErrorKind> {
|
) -> Result<TypeKind, ErrorKind> {
|
||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
ExprKind::Variable(var_ref) => {
|
ExprKind::Variable(var_ref) => {
|
||||||
@ -273,10 +268,10 @@ impl Expression {
|
|||||||
var_ref.2,
|
var_ref.2,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(var_ref.0.clone())
|
Ok(var_ref.0)
|
||||||
}
|
}
|
||||||
ExprKind::Literal(literal) => {
|
ExprKind::Literal(literal) => {
|
||||||
*literal = literal.try_coerce(hint_t.cloned())?;
|
*literal = literal.try_coerce(hint_t)?;
|
||||||
Ok(literal.as_type())
|
Ok(literal.as_type())
|
||||||
}
|
}
|
||||||
ExprKind::BinOp(op, lhs, rhs) => {
|
ExprKind::BinOp(op, lhs, rhs) => {
|
||||||
@ -284,13 +279,13 @@ impl Expression {
|
|||||||
// operation once relevant
|
// operation once relevant
|
||||||
let lhs_res = lhs.typecheck(state, &hints, None);
|
let lhs_res = lhs.typecheck(state, &hints, None);
|
||||||
let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.1);
|
let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.1);
|
||||||
let rhs_res = rhs.typecheck(state, &hints, Some(&lhs_type));
|
let rhs_res = rhs.typecheck(state, &hints, Some(lhs_type));
|
||||||
let rhs_type = state.or_else(rhs_res, Vague(Unknown), rhs.1);
|
let rhs_type = state.or_else(rhs_res, Vague(Unknown), rhs.1);
|
||||||
|
|
||||||
if let Some(collapsed) = state.ok(rhs_type.collapse_into(&rhs_type), self.1) {
|
if let Some(collapsed) = state.ok(rhs_type.collapse_into(&rhs_type), self.1) {
|
||||||
// Try to coerce both sides again with collapsed type
|
// Try to coerce both sides again with collapsed type
|
||||||
lhs.typecheck(state, &hints, Some(&collapsed)).ok();
|
lhs.typecheck(state, &hints, Some(collapsed)).ok();
|
||||||
rhs.typecheck(state, &hints, Some(&collapsed)).ok();
|
rhs.typecheck(state, &hints, Some(collapsed)).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let both_t = lhs_type.collapse_into(&rhs_type)?;
|
let both_t = lhs_type.collapse_into(&rhs_type)?;
|
||||||
@ -327,7 +322,7 @@ impl Expression {
|
|||||||
function_call.parameters.iter_mut().zip(true_params_iter)
|
function_call.parameters.iter_mut().zip(true_params_iter)
|
||||||
{
|
{
|
||||||
// Typecheck every param separately
|
// Typecheck every param separately
|
||||||
let param_res = param.typecheck(state, &hints, Some(&true_param_t));
|
let param_res = param.typecheck(state, &hints, Some(true_param_t));
|
||||||
let param_t = state.or_else(param_res, Vague(Unknown), param.1);
|
let param_t = state.or_else(param_res, Vague(Unknown), param.1);
|
||||||
state.ok(param_t.collapse_into(&true_param_t), param.1);
|
state.ok(param_t.collapse_into(&true_param_t), param.1);
|
||||||
}
|
}
|
||||||
@ -338,14 +333,14 @@ impl Expression {
|
|||||||
.ret
|
.ret
|
||||||
.collapse_into(&function_call.return_type.resolve_hinted(hints))?;
|
.collapse_into(&function_call.return_type.resolve_hinted(hints))?;
|
||||||
// Update typing to be more accurate
|
// Update typing to be more accurate
|
||||||
function_call.return_type = ret_t.clone();
|
function_call.return_type = ret_t;
|
||||||
Ok(ret_t)
|
Ok(ret_t)
|
||||||
} else {
|
} else {
|
||||||
Ok(function_call.return_type.clone())
|
Ok(function_call.return_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||||
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);
|
||||||
|
|
||||||
@ -369,8 +364,8 @@ impl Expression {
|
|||||||
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.
|
||||||
let lhs_res = lhs.typecheck(state, &hints, Some(&collapsed));
|
let lhs_res = lhs.typecheck(state, &hints, Some(collapsed));
|
||||||
let rhs_res = rhs.typecheck(state, &hints, Some(&collapsed));
|
let rhs_res = rhs.typecheck(state, &hints, Some(collapsed));
|
||||||
state.ok(lhs_res, lhs.meta);
|
state.ok(lhs_res, lhs.meta);
|
||||||
state.ok(rhs_res, rhs.meta);
|
state.ok(rhs_res, rhs.meta);
|
||||||
}
|
}
|
||||||
@ -378,42 +373,6 @@ impl Expression {
|
|||||||
Ok(collapsed)
|
Ok(collapsed)
|
||||||
}
|
}
|
||||||
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
|
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
|
||||||
ExprKind::Index(expression, idx) => {
|
|
||||||
let expr_t = expression.typecheck(state, hints, hint_t)?;
|
|
||||||
if let TypeKind::Array(elem_t, len) = expr_t {
|
|
||||||
if len >= *idx {
|
|
||||||
return Err(ErrorKind::IndexOutOfBounds(*idx, len));
|
|
||||||
}
|
|
||||||
Ok(*elem_t)
|
|
||||||
} else {
|
|
||||||
Err(ErrorKind::TriedIndexingNonArray(expr_t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Array(expressions) => {
|
|
||||||
let mut expr_result = try_all(
|
|
||||||
expressions
|
|
||||||
.iter_mut()
|
|
||||||
.map(|e| e.typecheck(state, hints, hint_t))
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
match &mut expr_result {
|
|
||||||
Ok(expr_types) => {
|
|
||||||
let mut iter = expr_types.iter_mut();
|
|
||||||
if let Some(first) = iter.next() {
|
|
||||||
for other in iter {
|
|
||||||
state.ok(first.collapse_into(other), self.1);
|
|
||||||
}
|
|
||||||
Ok(first.clone())
|
|
||||||
} else {
|
|
||||||
Ok(Array(Box::new(Void), 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(errors) => {
|
|
||||||
state.note_errors(errors, self.1);
|
|
||||||
Ok(Array(Box::new(Vague(Unknown)), expressions.len() as u64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,7 +381,7 @@ impl Literal {
|
|||||||
/// Try to coerce this literal, ie. convert it to a more specific type in
|
/// Try to coerce this literal, ie. convert it to a more specific type in
|
||||||
/// regards to the given hint if any.
|
/// regards to the given hint if any.
|
||||||
fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> {
|
fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> {
|
||||||
if let Some(hint) = &hint {
|
if let Some(hint) = hint {
|
||||||
use Literal as L;
|
use Literal as L;
|
||||||
use VagueLiteral as VagueL;
|
use VagueLiteral as VagueL;
|
||||||
Ok(match (self, hint) {
|
Ok(match (self, hint) {
|
||||||
@ -450,7 +409,7 @@ impl Literal {
|
|||||||
(L::Vague(VagueL::Number(v)), U64) => L::U64(v as u64),
|
(L::Vague(VagueL::Number(v)), U64) => L::U64(v as u64),
|
||||||
(L::Vague(VagueL::Number(v)), U128) => L::U128(v as u128),
|
(L::Vague(VagueL::Number(v)), U128) => L::U128(v as u128),
|
||||||
(_, Vague(_)) => self,
|
(_, Vague(_)) => self,
|
||||||
_ => Err(ErrorKind::LiteralIncompatible(self, hint.clone()))?,
|
_ => Err(ErrorKind::LiteralIncompatible(self, hint))?,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
@ -469,19 +428,19 @@ impl TypeKind {
|
|||||||
/// Error if not.
|
/// Error if not.
|
||||||
fn or_default(&self) -> Result<TypeKind, ErrorKind> {
|
fn or_default(&self) -> Result<TypeKind, ErrorKind> {
|
||||||
match self {
|
match self {
|
||||||
Vague(vague_type) => match &vague_type {
|
Vague(vague_type) => match vague_type {
|
||||||
Unknown => Err(ErrorKind::TypeIsVague(*vague_type)),
|
Unknown => Err(ErrorKind::TypeIsVague(*vague_type)),
|
||||||
Number => Ok(TypeKind::I32),
|
Number => Ok(TypeKind::I32),
|
||||||
TypeRef(_) => panic!("Hinted default!"),
|
TypeRef(_) => panic!("Hinted default!"),
|
||||||
},
|
},
|
||||||
_ => Ok(self.clone()),
|
_ => Ok(*self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(),
|
||||||
_ => self.clone(),
|
_ => *self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -502,11 +461,11 @@ impl Collapsable for TypeKind {
|
|||||||
(Vague(Number), other) | (other, Vague(Number)) => match other {
|
(Vague(Number), other) | (other, Vague(Number)) => match other {
|
||||||
Vague(Unknown) => Ok(Vague(Number)),
|
Vague(Unknown) => Ok(Vague(Number)),
|
||||||
Vague(Number) => Ok(Vague(Number)),
|
Vague(Number) => Ok(Vague(Number)),
|
||||||
I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => Ok(other.clone()),
|
I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => Ok(*other),
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
_ => Err(ErrorKind::TypesIncompatible(*self, *other)),
|
||||||
},
|
},
|
||||||
(Vague(Unknown), other) | (other, Vague(Unknown)) => Ok(other.clone()),
|
(Vague(Unknown), other) | (other, Vague(Unknown)) => Ok(other.clone()),
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
_ => Err(ErrorKind::TypesIncompatible(*self, *other)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@
|
|||||||
//! must then be passed through TypeCheck with the same [`TypeRefs`] in order to
|
//! must then be passed through TypeCheck with the same [`TypeRefs`] in order to
|
||||||
//! place the correct types from the IDs and check that there are no issues.
|
//! place the correct types from the IDs and check that there are no issues.
|
||||||
|
|
||||||
use std::{convert::Infallible, iter};
|
use std::iter;
|
||||||
|
|
||||||
use crate::{mir::TypeKind, util::try_all};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
pass::{Pass, PassState, ScopeVariable},
|
pass::{Pass, PassState, ScopeVariable},
|
||||||
@ -61,7 +59,7 @@ impl FunctionDefinition {
|
|||||||
|
|
||||||
match &mut self.kind {
|
match &mut self.kind {
|
||||||
FunctionDefinitionKind::Local(block, _) => {
|
FunctionDefinitionKind::Local(block, _) => {
|
||||||
state.scope.return_type_hint = Some(self.return_type.clone());
|
state.scope.return_type_hint = Some(self.return_type);
|
||||||
let scope_hints = ScopeTypeRefs::from(type_refs);
|
let scope_hints = ScopeTypeRefs::from(type_refs);
|
||||||
|
|
||||||
// Infer block return type
|
// Infer block return type
|
||||||
@ -93,7 +91,7 @@ impl Block {
|
|||||||
StmtKind::Let(var, mutable, expr) => {
|
StmtKind::Let(var, mutable, expr) => {
|
||||||
// Get the TypeRef for this variable declaration
|
// Get the TypeRef for this variable declaration
|
||||||
let mut var_ref =
|
let mut var_ref =
|
||||||
state.ok(inner_hints.new_var(var.1.clone(), *mutable, &var.0), var.2);
|
state.ok(inner_hints.new_var(var.1.clone(), *mutable, var.0), var.2);
|
||||||
|
|
||||||
// If ok, update the MIR type to this TypeRef
|
// If ok, update the MIR type to this TypeRef
|
||||||
if let Some(var_ref) = &var_ref {
|
if let Some(var_ref) = &var_ref {
|
||||||
@ -113,24 +111,23 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Set(var, expr) => {
|
StmtKind::Set(var, expr) => {
|
||||||
todo!("Re-think how set needs to work with arrays")
|
// Get the TypeRef for this variable declaration
|
||||||
// // Get the TypeRef for this variable declaration
|
let var_ref = inner_hints.find_hint(&var.1);
|
||||||
// let var_ref = inner_hints.find_hint(&var.1);
|
|
||||||
|
|
||||||
// // If ok, update the MIR type to this TypeRef
|
// If ok, update the MIR type to this TypeRef
|
||||||
// if let Some((_, var_ref)) = &var_ref {
|
if let Some((_, var_ref)) = &var_ref {
|
||||||
// var.0 = var_ref.as_type()
|
var.0 = var_ref.as_type()
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Infer hints for the expression itself
|
// Infer hints for the expression itself
|
||||||
// let inferred = expr.infer_types(&mut state, &inner_hints);
|
let inferred = expr.infer_types(&mut state, &inner_hints);
|
||||||
// let expr_ty_ref = state.ok(inferred, expr.1);
|
let expr_ty_ref = state.ok(inferred, expr.1);
|
||||||
|
|
||||||
// // Try to narrow the variable type declaration with the
|
// Try to narrow the variable type declaration with the
|
||||||
// // expression
|
// expression
|
||||||
// if let (Some((_, mut var_ref)), Some(expr_ty_ref)) = (var_ref, expr_ty_ref) {
|
if let (Some((_, mut var_ref)), Some(expr_ty_ref)) = (var_ref, expr_ty_ref) {
|
||||||
// var_ref.narrow(&expr_ty_ref);
|
var_ref.narrow(&expr_ty_ref);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Import(_) => todo!(),
|
StmtKind::Import(_) => todo!(),
|
||||||
StmtKind::Expression(expr) => {
|
StmtKind::Expression(expr) => {
|
||||||
@ -152,7 +149,7 @@ impl Block {
|
|||||||
|
|
||||||
// Narow return type to declared type if hard return
|
// Narow return type to declared type if hard return
|
||||||
if kind == ReturnKind::Hard {
|
if kind == ReturnKind::Hard {
|
||||||
if let Some(hint) = &state.scope.return_type_hint {
|
if let Some(hint) = state.scope.return_type_hint {
|
||||||
ret_type_ref.narrow(&mut outer_hints.from_type(&hint).unwrap());
|
ret_type_ref.narrow(&mut outer_hints.from_type(&hint).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,52 +260,6 @@ impl Expression {
|
|||||||
ReturnKind::Soft => Ok(block_ref.1),
|
ReturnKind::Soft => Ok(block_ref.1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Index(expression, _) => {
|
|
||||||
let expr_ty = expression.infer_types(state, type_refs)?;
|
|
||||||
let kind = unsafe { expr_ty.resolve_type() };
|
|
||||||
match kind {
|
|
||||||
Array(type_kind, _) => Ok(type_refs.from_type(&type_kind).unwrap()),
|
|
||||||
_ => Err(ErrorKind::TriedIndexingNonArray(kind)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Array(expressions) => {
|
|
||||||
let mut expr_types_result = try_all(
|
|
||||||
expressions
|
|
||||||
.iter_mut()
|
|
||||||
.map(|e| (*e).infer_types(state, type_refs))
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
match &mut expr_types_result {
|
|
||||||
Ok(expr_types) => {
|
|
||||||
let mut iter = expr_types.iter_mut();
|
|
||||||
if let Some(first) = iter.next() {
|
|
||||||
while let Some(other) = iter.next() {
|
|
||||||
first.narrow(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(type_refs
|
|
||||||
.from_type(&Array(
|
|
||||||
Box::new(first.as_type()),
|
|
||||||
expressions.len() as u64,
|
|
||||||
))
|
|
||||||
.unwrap())
|
|
||||||
} else {
|
|
||||||
Ok(type_refs
|
|
||||||
.from_type(&Array(Box::new(TypeKind::Void), 0))
|
|
||||||
.unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(errors) => {
|
|
||||||
state.note_errors(errors, self.1);
|
|
||||||
Ok(type_refs
|
|
||||||
.from_type(&TypeKind::Array(
|
|
||||||
Box::new(TypeKind::Vague(Unknown)),
|
|
||||||
expressions.len() as u64,
|
|
||||||
))
|
|
||||||
.unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,7 @@ pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
|
|||||||
|
|
||||||
impl<'scope> TypeRef<'scope> {
|
impl<'scope> TypeRef<'scope> {
|
||||||
pub unsafe fn resolve_type(&self) -> TypeKind {
|
pub unsafe fn resolve_type(&self) -> TypeKind {
|
||||||
unsafe {
|
unsafe { *self.1.types.hints.borrow().get_unchecked(*self.0.borrow()) }
|
||||||
self.1
|
|
||||||
.types
|
|
||||||
.hints
|
|
||||||
.borrow()
|
|
||||||
.get_unchecked(*self.0.borrow())
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn narrow(&mut self, other: &TypeRef) -> Option<TypeRef<'scope>> {
|
pub fn narrow(&mut self, other: &TypeRef) -> Option<TypeRef<'scope>> {
|
||||||
@ -53,15 +46,15 @@ pub struct TypeRefs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeRefs {
|
impl TypeRefs {
|
||||||
pub fn new(&self, ty: &TypeKind) -> TypeIdRef {
|
pub fn new(&self, ty: TypeKind) -> TypeIdRef {
|
||||||
let idx = self.hints.borrow().len();
|
let idx = self.hints.borrow().len();
|
||||||
let typecell = Rc::new(RefCell::new(idx));
|
let typecell = Rc::new(RefCell::new(idx));
|
||||||
self.type_refs.borrow_mut().push(typecell.clone());
|
self.type_refs.borrow_mut().push(typecell.clone());
|
||||||
self.hints.borrow_mut().push(ty.clone());
|
self.hints.borrow_mut().push(ty);
|
||||||
typecell
|
typecell
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find(&self, ty: &TypeKind) -> Option<TypeIdRef> {
|
pub fn find(&self, ty: TypeKind) -> Option<TypeIdRef> {
|
||||||
if ty.known().is_err() {
|
if ty.known().is_err() {
|
||||||
// Only do this for non-vague types that can not be further narrowed
|
// Only do this for non-vague types that can not be further narrowed
|
||||||
// down.
|
// down.
|
||||||
@ -73,7 +66,7 @@ impl TypeRefs {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, t)| *t == ty)
|
.find(|(_, t)| **t == ty)
|
||||||
.map(|(i, _)| i)
|
.map(|(i, _)| i)
|
||||||
{
|
{
|
||||||
Some(Rc::new(RefCell::new(idx)))
|
Some(Rc::new(RefCell::new(idx)))
|
||||||
@ -96,7 +89,7 @@ impl TypeRefs {
|
|||||||
|
|
||||||
pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> {
|
pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> {
|
||||||
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
|
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
|
||||||
self.hints.borrow().get(inner_idx).cloned()
|
self.hints.borrow().get(inner_idx).copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +114,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
&'outer self,
|
&'outer self,
|
||||||
name: String,
|
name: String,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
initial_ty: &TypeKind,
|
initial_ty: TypeKind,
|
||||||
) -> Result<TypeRef<'outer>, ErrorKind> {
|
) -> Result<TypeRef<'outer>, ErrorKind> {
|
||||||
if self.variables.borrow().contains_key(&name) {
|
if self.variables.borrow().contains_key(&name) {
|
||||||
return Err(ErrorKind::VariableAlreadyDefined(name));
|
return Err(ErrorKind::VariableAlreadyDefined(name));
|
||||||
@ -139,17 +132,12 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
let inner_idx = unsafe { *self.types.recurse_type_ref(*idx).borrow() };
|
let inner_idx = unsafe { *self.types.recurse_type_ref(*idx).borrow() };
|
||||||
self.types.type_refs.borrow().get(inner_idx).cloned()?
|
self.types.type_refs.borrow().get(inner_idx).cloned()?
|
||||||
}
|
}
|
||||||
TypeKind::Vague(_) => self.types.new(ty),
|
TypeKind::Vague(_) => self.types.new(*ty),
|
||||||
TypeKind::Array(elem_ty, length) => {
|
|
||||||
let elem_ty = self.from_type(elem_ty)?;
|
|
||||||
self.types
|
|
||||||
.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(ty_ref) = self.types.find(ty) {
|
if let Some(ty_ref) = self.types.find(*ty) {
|
||||||
ty_ref
|
ty_ref
|
||||||
} else {
|
} else {
|
||||||
self.types.new(ty)
|
self.types.new(*ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use crate::ast::VariableReference;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -9,7 +7,6 @@ pub enum ReturnTypeOther {
|
|||||||
Set(Metadata),
|
Set(Metadata),
|
||||||
EmptyBlock(Metadata),
|
EmptyBlock(Metadata),
|
||||||
NoBlockReturn(Metadata),
|
NoBlockReturn(Metadata),
|
||||||
IndexingNonArray(Metadata),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
@ -18,11 +15,10 @@ impl TypeKind {
|
|||||||
pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind {
|
pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind {
|
||||||
// TODO make some type of mechanism that allows to binop two values of
|
// TODO make some type of mechanism that allows to binop two values of
|
||||||
// differing types..
|
// differing types..
|
||||||
// TODO Return None for arrays later
|
|
||||||
match op {
|
match op {
|
||||||
BinaryOperator::Add => self.clone(),
|
BinaryOperator::Add => *self,
|
||||||
BinaryOperator::Minus => self.clone(),
|
BinaryOperator::Minus => *self,
|
||||||
BinaryOperator::Mult => self.clone(),
|
BinaryOperator::Mult => *self,
|
||||||
BinaryOperator::And => TypeKind::Bool,
|
BinaryOperator::And => TypeKind::Bool,
|
||||||
BinaryOperator::Cmp(_) => TypeKind::Bool,
|
BinaryOperator::Cmp(_) => TypeKind::Bool,
|
||||||
}
|
}
|
||||||
@ -66,7 +62,7 @@ impl ReturnType for Statement {
|
|||||||
),
|
),
|
||||||
Set(var, expr) => if_hard(
|
Set(var, expr) => if_hard(
|
||||||
expr.return_type()?,
|
expr.return_type()?,
|
||||||
Err(ReturnTypeOther::Set(var.meta + expr.1)),
|
Err(ReturnTypeOther::Set(var.2 + expr.1)),
|
||||||
),
|
),
|
||||||
Import(_) => todo!(),
|
Import(_) => todo!(),
|
||||||
Expression(expression) => expression.return_type(),
|
Expression(expression) => expression.return_type(),
|
||||||
@ -89,25 +85,6 @@ impl ReturnType for Expression {
|
|||||||
Block(block) => block.return_type(),
|
Block(block) => block.return_type(),
|
||||||
FunctionCall(fcall) => fcall.return_type(),
|
FunctionCall(fcall) => fcall.return_type(),
|
||||||
If(expr) => expr.return_type(),
|
If(expr) => expr.return_type(),
|
||||||
Index(expression, _) => {
|
|
||||||
let expr_type = expression.return_type()?;
|
|
||||||
if let (_, TypeKind::Array(elem_ty, _)) = expr_type {
|
|
||||||
Ok((ReturnKind::Soft, *elem_ty))
|
|
||||||
} else {
|
|
||||||
Err(ReturnTypeOther::IndexingNonArray(expression.1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Array(expressions) => {
|
|
||||||
let first = expressions
|
|
||||||
.iter()
|
|
||||||
.next()
|
|
||||||
.map(|e| e.return_type())
|
|
||||||
.unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?;
|
|
||||||
Ok((
|
|
||||||
ReturnKind::Soft,
|
|
||||||
TypeKind::Array(Box::new(first.1), expressions.len() as u64),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +107,7 @@ impl ReturnType for IfExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReturnType for NamedVariableRef {
|
impl ReturnType for VariableReference {
|
||||||
fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
|
fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
|
||||||
Ok((ReturnKind::Soft, self.0.clone()))
|
Ok((ReturnKind::Soft, self.0.clone()))
|
||||||
}
|
}
|
||||||
|
@ -153,13 +153,6 @@ impl<'a, 'b> TokenStream<'a, 'b> {
|
|||||||
end: self.position,
|
end: self.position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_one_token_range(&self) -> TokenRange {
|
|
||||||
TokenRange {
|
|
||||||
start: self.position - 1,
|
|
||||||
end: self.position,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TokenStream<'_, '_> {
|
impl Drop for TokenStream<'_, '_> {
|
||||||
|
Loading…
Reference in New Issue
Block a user