Compare commits
7 Commits
3404f0fb6e
...
89002f34e4
Author | SHA1 | Date | |
---|---|---|---|
89002f34e4 | |||
954f3438d3 | |||
b793ef7526 | |||
5ff5651f5f | |||
4f1dc5e59d | |||
9ba091973a | |||
4bef1c2379 |
@ -47,7 +47,7 @@ Currently missing big features (TODOs) are:
|
||||
- Debug Information (PARTIALLY DONE)
|
||||
- Ability to specify types in literals and variable definitions
|
||||
- Intrinsic functions
|
||||
- Not-Unary
|
||||
- Not-Unary and NEQ-binary
|
||||
|
||||
Big features that I want later but are not necessary:
|
||||
- Associated functions
|
||||
|
@ -7,7 +7,7 @@ import std::new_string;
|
||||
import std::add_num_to_str;
|
||||
import std::concat_strings;
|
||||
|
||||
fn main() -> i32 {
|
||||
fn main() -> u8 {
|
||||
let mut test = from_str("hello");
|
||||
|
||||
concat_strings(&mut test, from_str(" world"));
|
||||
@ -21,5 +21,5 @@ fn main() -> i32 {
|
||||
|
||||
free_string(&test);
|
||||
|
||||
return 0;
|
||||
return addition(5, 3);
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ impl Default for FunctionFlags {
|
||||
FunctionFlags {
|
||||
is_extern: false,
|
||||
is_main: false,
|
||||
is_pub: true,
|
||||
is_pub: false,
|
||||
is_imported: false,
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,16 @@ pub struct Allocator {
|
||||
pub struct AllocatorScope<'ctx, 'a> {
|
||||
pub(super) block: &'a mut Block<'ctx>,
|
||||
pub(super) module_id: SourceModuleId,
|
||||
pub(super) types: &'a HashMap<TypeValue, TypeDefinition>,
|
||||
pub(super) type_values: &'a HashMap<CustomTypeKey, TypeValue>,
|
||||
}
|
||||
|
||||
impl Allocator {
|
||||
pub fn empty() -> Allocator {
|
||||
Allocator {
|
||||
allocations: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(func: &FunctionDefinition, scope: &mut AllocatorScope) -> Allocator {
|
||||
func.allocate(scope)
|
||||
}
|
||||
@ -44,22 +49,21 @@ impl mir::FunctionDefinition {
|
||||
fn allocate<'ctx, 'a>(&self, scope: &mut AllocatorScope<'ctx, 'a>) -> Allocator {
|
||||
let mut allocated = Vec::new();
|
||||
match &self.kind {
|
||||
crate::mir::FunctionDefinitionKind::Local(block, _) => {
|
||||
mir::FunctionDefinitionKind::Local(block, _) => {
|
||||
for param in &self.parameters {
|
||||
let allocation = scope
|
||||
.block
|
||||
.build_named(
|
||||
param.0.clone(),
|
||||
reid_lib::Instr::Alloca(
|
||||
param.1.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
reid_lib::Instr::Alloca(param.1.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap();
|
||||
allocated.push(Allocation(param.0.clone(), param.1.clone(), allocation));
|
||||
}
|
||||
allocated.extend(block.allocate(scope));
|
||||
}
|
||||
crate::mir::FunctionDefinitionKind::Extern(_) => {}
|
||||
mir::FunctionDefinitionKind::Extern(_) => {}
|
||||
mir::FunctionDefinitionKind::Intrinsic(_) => {}
|
||||
}
|
||||
|
||||
Allocator {
|
||||
@ -95,11 +99,7 @@ impl mir::Statement {
|
||||
.block
|
||||
.build_named(
|
||||
named_variable_ref.1.clone(),
|
||||
reid_lib::Instr::Alloca(
|
||||
named_variable_ref
|
||||
.0
|
||||
.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
reid_lib::Instr::Alloca(named_variable_ref.0.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap();
|
||||
allocated.push(Allocation(
|
||||
|
@ -50,7 +50,6 @@ impl ast::Module {
|
||||
block.into_mir(module_id),
|
||||
(*range).as_meta(module_id),
|
||||
),
|
||||
source: module_id,
|
||||
};
|
||||
functions.push(def);
|
||||
}
|
||||
@ -71,7 +70,6 @@ impl ast::Module {
|
||||
.map(|p| (p.0, p.1 .0.into_mir(module_id)))
|
||||
.collect(),
|
||||
kind: mir::FunctionDefinitionKind::Extern(false),
|
||||
source: module_id,
|
||||
};
|
||||
functions.push(def);
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ impl mir::Module {
|
||||
// TODO: Reorder custom-type definitions such that
|
||||
// inner types get evaluated first. Otherwise this
|
||||
// will cause a panic!
|
||||
.map(|StructField(_, t, _)| t.get_type(&type_values, &types))
|
||||
.map(|StructField(_, t, _)| t.get_type(&type_values))
|
||||
.collect(),
|
||||
)))
|
||||
}
|
||||
@ -291,14 +291,14 @@ impl mir::Module {
|
||||
let param_types: Vec<Type> = function
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|(_, p)| p.get_type(&type_values, &types))
|
||||
.map(|(_, p)| p.get_type(&type_values))
|
||||
.collect();
|
||||
|
||||
let is_main = self.is_main && function.name == "main";
|
||||
let func = match &function.kind {
|
||||
mir::FunctionDefinitionKind::Local(_, _) => module.function(
|
||||
&function.name,
|
||||
function.return_type.get_type(&type_values, &types),
|
||||
function.return_type.get_type(&type_values),
|
||||
param_types,
|
||||
FunctionFlags {
|
||||
is_pub: function.is_pub || is_main,
|
||||
@ -309,7 +309,7 @@ impl mir::Module {
|
||||
),
|
||||
mir::FunctionDefinitionKind::Extern(imported) => module.function(
|
||||
&function.name,
|
||||
function.return_type.get_type(&type_values, &types),
|
||||
function.return_type.get_type(&type_values),
|
||||
param_types,
|
||||
FunctionFlags {
|
||||
is_extern: true,
|
||||
@ -317,6 +317,14 @@ impl mir::Module {
|
||||
..FunctionFlags::default()
|
||||
},
|
||||
),
|
||||
mir::FunctionDefinitionKind::Intrinsic(_) => module.function(
|
||||
&function.name,
|
||||
function.return_type.get_type(&type_values),
|
||||
param_types,
|
||||
FunctionFlags {
|
||||
..FunctionFlags::default()
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
functions.insert(function.name.clone(), StackFunction { ir: func });
|
||||
@ -333,7 +341,6 @@ impl mir::Module {
|
||||
&mut AllocatorScope {
|
||||
block: &mut entry,
|
||||
module_id: self.module_id,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
},
|
||||
);
|
||||
@ -470,6 +477,26 @@ impl mir::Module {
|
||||
}
|
||||
}
|
||||
mir::FunctionDefinitionKind::Extern(_) => {}
|
||||
mir::FunctionDefinitionKind::Intrinsic(kind) => {
|
||||
let entry = function.ir.block("entry");
|
||||
let mut scope = Scope {
|
||||
context,
|
||||
modules: &modules,
|
||||
tokens,
|
||||
module: &module,
|
||||
module_id: self.module_id,
|
||||
function,
|
||||
block: entry,
|
||||
functions: &functions,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
stack_values: Default::default(),
|
||||
debug: None,
|
||||
allocator: Rc::new(RefCell::new(Allocator::empty())),
|
||||
};
|
||||
|
||||
kind.codegen(&mut scope)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,7 +721,7 @@ impl mir::Expression {
|
||||
format!("{}", varref.1),
|
||||
Instr::Load(
|
||||
v.0.instr(),
|
||||
inner.get_type(scope.type_values, scope.types),
|
||||
inner.get_type(scope.type_values),
|
||||
),
|
||||
)
|
||||
.unwrap(),
|
||||
@ -800,7 +827,7 @@ impl mir::Expression {
|
||||
.known()
|
||||
.expect("function return type unknown");
|
||||
|
||||
let ret_type = ret_type_kind.get_type(scope.type_values, scope.types);
|
||||
let ret_type = ret_type_kind.get_type(scope.type_values);
|
||||
|
||||
let params = try_all(
|
||||
call.parameters
|
||||
@ -903,10 +930,7 @@ impl mir::Expression {
|
||||
.block
|
||||
.build_named(
|
||||
"load",
|
||||
Instr::Load(
|
||||
kind.instr(),
|
||||
inner.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
Instr::Load(kind.instr(), inner.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap();
|
||||
(
|
||||
@ -962,10 +986,7 @@ impl mir::Expression {
|
||||
.block
|
||||
.build_named(
|
||||
"array.load",
|
||||
Instr::Load(
|
||||
ptr,
|
||||
contained_ty.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
Instr::Load(ptr, contained_ty.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap()
|
||||
.maybe_location(&mut scope.block, location),
|
||||
@ -1003,7 +1024,7 @@ impl mir::Expression {
|
||||
.unwrap_or(TypeKind::Void);
|
||||
|
||||
let array_ty = Type::Array(
|
||||
Box::new(elem_ty_kind.get_type(scope.type_values, scope.types)),
|
||||
Box::new(elem_ty_kind.get_type(scope.type_values)),
|
||||
instr_list.len() as u64,
|
||||
);
|
||||
let array_name = format!("{}.{}", elem_ty_kind, instr_list.len());
|
||||
@ -1086,10 +1107,7 @@ impl mir::Expression {
|
||||
.block
|
||||
.build_named(
|
||||
load_n,
|
||||
Instr::Load(
|
||||
value,
|
||||
type_kind.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
Instr::Load(value, type_kind.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
@ -1180,10 +1198,7 @@ impl mir::Expression {
|
||||
.block
|
||||
.build_named(
|
||||
format!("{}.deref", varref.1),
|
||||
Instr::Load(
|
||||
v.0.instr(),
|
||||
ptr_inner.get_type(scope.type_values, scope.types),
|
||||
),
|
||||
Instr::Load(v.0.instr(), ptr_inner.get_type(scope.type_values)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -1198,7 +1213,7 @@ impl mir::Expression {
|
||||
format!("{}.deref.inner", varref.1),
|
||||
Instr::Load(
|
||||
var_ptr_instr,
|
||||
inner.get_type(scope.type_values, scope.types),
|
||||
inner.get_type(scope.type_values),
|
||||
),
|
||||
)
|
||||
.unwrap(),
|
||||
@ -1236,7 +1251,7 @@ impl mir::Expression {
|
||||
.build(Instr::BitCast(
|
||||
val.instr(),
|
||||
Type::Ptr(Box::new(
|
||||
type_kind.get_type(scope.type_values, scope.types),
|
||||
type_kind.get_type(scope.type_values),
|
||||
)),
|
||||
))
|
||||
.unwrap(),
|
||||
@ -1254,7 +1269,7 @@ impl mir::Expression {
|
||||
.block
|
||||
.build(Instr::BitCast(
|
||||
val.instr(),
|
||||
type_kind.get_type(scope.type_values, scope.types),
|
||||
type_kind.get_type(scope.type_values),
|
||||
))
|
||||
.unwrap(),
|
||||
),
|
||||
@ -1263,10 +1278,10 @@ impl mir::Expression {
|
||||
_ => {
|
||||
let cast_instr = val
|
||||
.1
|
||||
.get_type(scope.type_values, scope.types)
|
||||
.get_type(scope.type_values)
|
||||
.cast_instruction(
|
||||
val.instr(),
|
||||
&type_kind.get_type(scope.type_values, scope.types),
|
||||
&type_kind.get_type(scope.type_values),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -1438,11 +1453,7 @@ impl mir::Literal {
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
pub(super) fn get_type(
|
||||
&self,
|
||||
type_vals: &HashMap<CustomTypeKey, TypeValue>,
|
||||
typedefs: &HashMap<TypeValue, TypeDefinition>,
|
||||
) -> Type {
|
||||
pub(super) fn get_type(&self, type_vals: &HashMap<CustomTypeKey, TypeValue>) -> Type {
|
||||
match &self {
|
||||
TypeKind::I8 => Type::I8,
|
||||
TypeKind::I16 => Type::I16,
|
||||
@ -1463,24 +1474,16 @@ impl TypeKind {
|
||||
TypeKind::F80 => Type::F80,
|
||||
TypeKind::F128PPC => Type::F128PPC,
|
||||
TypeKind::Char => Type::U8,
|
||||
TypeKind::Array(elem_t, len) => {
|
||||
Type::Array(Box::new(elem_t.get_type(type_vals, typedefs)), *len)
|
||||
}
|
||||
TypeKind::Array(elem_t, len) => Type::Array(Box::new(elem_t.get_type(type_vals)), *len),
|
||||
TypeKind::Void => Type::Void,
|
||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||
TypeKind::CustomType(n) => {
|
||||
let type_val = type_vals.get(n).unwrap().clone();
|
||||
Type::CustomType(type_val)
|
||||
}
|
||||
TypeKind::UserPtr(type_kind) => {
|
||||
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
|
||||
}
|
||||
TypeKind::CodegenPtr(type_kind) => {
|
||||
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
|
||||
}
|
||||
TypeKind::Borrow(type_kind, _) => {
|
||||
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
|
||||
}
|
||||
TypeKind::UserPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))),
|
||||
TypeKind::CodegenPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))),
|
||||
TypeKind::Borrow(type_kind, _) => Type::Ptr(Box::new(type_kind.get_type(type_vals))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
57
reid/src/intrinsics.rs
Normal file
57
reid/src/intrinsics.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use reid_lib::Instr;
|
||||
|
||||
use crate::{
|
||||
codegen::{ErrorKind, Scope},
|
||||
mir::{FunctionDefinition, FunctionDefinitionKind, TypeKind},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum InstrinsicKind {
|
||||
IAdd,
|
||||
}
|
||||
|
||||
fn intrinsic(
|
||||
name: &str,
|
||||
ret_ty: TypeKind,
|
||||
params: Vec<(&str, TypeKind)>,
|
||||
kind: InstrinsicKind,
|
||||
) -> FunctionDefinition {
|
||||
FunctionDefinition {
|
||||
name: name.into(),
|
||||
is_pub: false,
|
||||
is_imported: false,
|
||||
return_type: ret_ty,
|
||||
parameters: params.into_iter().map(|(n, ty)| (n.into(), ty)).collect(),
|
||||
kind: FunctionDefinitionKind::Intrinsic(kind),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn form_intrinsics() -> Vec<FunctionDefinition> {
|
||||
let mut intrinsics = Vec::new();
|
||||
|
||||
intrinsics.push(intrinsic(
|
||||
"addition",
|
||||
TypeKind::U8,
|
||||
vec![("lhs".into(), TypeKind::U8), ("rhs".into(), TypeKind::U8)],
|
||||
InstrinsicKind::IAdd,
|
||||
));
|
||||
|
||||
intrinsics
|
||||
}
|
||||
|
||||
impl InstrinsicKind {
|
||||
pub fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Result<(), ErrorKind> {
|
||||
match self {
|
||||
InstrinsicKind::IAdd => {
|
||||
let lhs = scope.block.build(Instr::Param(0)).unwrap();
|
||||
let rhs = scope.block.build(Instr::Param(1)).unwrap();
|
||||
let add = scope.block.build(Instr::Add(lhs, rhs)).unwrap();
|
||||
scope
|
||||
.block
|
||||
.terminate(reid_lib::TerminatorKind::Ret(add))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use error_raporting::{ErrorKind as ErrorRapKind, ErrorModules, ReidError};
|
||||
use intrinsics::form_intrinsics;
|
||||
use lexer::FullToken;
|
||||
use mir::{
|
||||
linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs,
|
||||
@ -56,6 +57,7 @@ mod allocator;
|
||||
mod ast;
|
||||
mod codegen;
|
||||
pub mod error_raporting;
|
||||
pub mod intrinsics;
|
||||
pub mod ld;
|
||||
mod lexer;
|
||||
pub mod mir;
|
||||
@ -126,6 +128,12 @@ pub fn perform_all_passes<'map>(
|
||||
#[cfg(debug_assertions)]
|
||||
dbg!(&context);
|
||||
|
||||
for module in &mut context.modules {
|
||||
for intrinsic in form_intrinsics() {
|
||||
module.1.functions.insert(0, intrinsic);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
println!("{}", &context);
|
||||
|
||||
|
@ -108,12 +108,13 @@ impl Display for FunctionDefinition {
|
||||
impl Display for FunctionDefinitionKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Local(block, _) => {
|
||||
FunctionDefinitionKind::Local(block, _) => {
|
||||
write!(f, "{}", block)?;
|
||||
Ok(())
|
||||
}
|
||||
Self::Extern(true) => write!(f, "<Imported Extern>"),
|
||||
Self::Extern(false) => write!(f, "<Linked Extern>"),
|
||||
FunctionDefinitionKind::Extern(true) => write!(f, "<Imported Extern>"),
|
||||
FunctionDefinitionKind::Extern(false) => write!(f, "<Linked Extern>"),
|
||||
FunctionDefinitionKind::Intrinsic(_) => write!(f, "<Intrinsic>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -675,6 +675,8 @@ pub enum EqualsIssue {
|
||||
AlreadyExtern(String, Metadata),
|
||||
#[error("Function {0} is already imported from another module")]
|
||||
ConflictWithImport(String),
|
||||
#[error("Function is defined as an intrinsic")]
|
||||
ExistsAsIntrinsic,
|
||||
}
|
||||
|
||||
impl FunctionDefinition {
|
||||
@ -701,6 +703,7 @@ impl FunctionDefinition {
|
||||
}
|
||||
}
|
||||
}
|
||||
FunctionDefinitionKind::Intrinsic(_) => Err(EqualsIssue::ExistsAsIntrinsic),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +331,6 @@ impl<'map> Pass for LinkerPass<'map> {
|
||||
return_type,
|
||||
parameters: param_tys,
|
||||
kind: super::FunctionDefinitionKind::Extern(true),
|
||||
source: imported_mod_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::{
|
||||
intrinsics::InstrinsicKind,
|
||||
lexer::{FullToken, Position},
|
||||
token_stream::TokenRange,
|
||||
};
|
||||
@ -293,7 +294,6 @@ pub struct FunctionDefinition {
|
||||
pub return_type: TypeKind,
|
||||
pub parameters: Vec<(String, TypeKind)>,
|
||||
pub kind: FunctionDefinitionKind,
|
||||
pub source: SourceModuleId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -302,6 +302,8 @@ pub enum FunctionDefinitionKind {
|
||||
Local(Block, Metadata),
|
||||
/// True = imported from other module, False = Is user defined extern
|
||||
Extern(bool),
|
||||
/// Intrinsic definition, defined within the compiler
|
||||
Intrinsic(InstrinsicKind),
|
||||
}
|
||||
|
||||
impl FunctionDefinition {
|
||||
@ -309,6 +311,7 @@ impl FunctionDefinition {
|
||||
match &self.kind {
|
||||
FunctionDefinitionKind::Local(block, _) => block.meta.clone(),
|
||||
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
||||
FunctionDefinitionKind::Intrinsic(_) => Metadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,6 +319,7 @@ impl FunctionDefinition {
|
||||
match &self.kind {
|
||||
FunctionDefinitionKind::Local(_, metadata) => metadata.clone(),
|
||||
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
||||
FunctionDefinitionKind::Intrinsic(_) => Metadata::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -352,6 +352,7 @@ impl FunctionDefinition {
|
||||
block.pass(pass, state, scope, mod_id)?;
|
||||
}
|
||||
FunctionDefinitionKind::Extern(_) => {}
|
||||
FunctionDefinitionKind::Intrinsic(..) => {}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ pub enum ErrorKind {
|
||||
FunctionNotDefined(String),
|
||||
#[error("Expected a return type of {0}, got {1} instead")]
|
||||
ReturnTypeMismatch(TypeKind, TypeKind),
|
||||
#[error("Function already defined: {0}")]
|
||||
FunctionAlreadyDefined(String),
|
||||
#[error("Function {0} already defined {1}")]
|
||||
FunctionAlreadyDefined(String, ErrorTypedefKind),
|
||||
#[error("Variable already defined: {0}")]
|
||||
VariableAlreadyDefined(String),
|
||||
#[error("Variable {0} is not declared as mutable")]
|
||||
@ -80,6 +80,16 @@ pub struct TypeCheck<'t> {
|
||||
|
||||
type TypecheckPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>;
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ErrorTypedefKind {
|
||||
#[error("locally")]
|
||||
Local,
|
||||
#[error("as an extern")]
|
||||
Extern,
|
||||
#[error("as an intrinsic")]
|
||||
Intrinsic,
|
||||
}
|
||||
|
||||
impl<'t> Pass for TypeCheck<'t> {
|
||||
type Data = ();
|
||||
type TError = ErrorKind;
|
||||
@ -116,10 +126,9 @@ impl<'t> Pass for TypeCheck<'t> {
|
||||
}
|
||||
}
|
||||
|
||||
let seen = HashSet::new();
|
||||
for typedef in defmap.values() {
|
||||
let mut curr = seen.clone();
|
||||
curr.insert(typedef.name.clone());
|
||||
let mut seen_types = HashSet::new();
|
||||
seen_types.insert(typedef.name.clone());
|
||||
check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state);
|
||||
}
|
||||
|
||||
@ -196,6 +205,9 @@ impl FunctionDefinition {
|
||||
FunctionDefinitionKind::Extern(_) => {
|
||||
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
|
||||
}
|
||||
FunctionDefinitionKind::Intrinsic(..) => {
|
||||
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
|
||||
}
|
||||
};
|
||||
|
||||
match inferred {
|
||||
|
@ -4,13 +4,13 @@
|
||||
//! 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.
|
||||
|
||||
use std::{convert::Infallible, iter};
|
||||
use std::{collections::HashMap, convert::Infallible, iter};
|
||||
|
||||
use crate::{mir::TypeKind, util::try_all};
|
||||
|
||||
use super::{
|
||||
pass::{Pass, PassResult, PassState},
|
||||
typecheck::ErrorKind,
|
||||
typecheck::{ErrorKind, ErrorTypedefKind},
|
||||
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
||||
Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind,
|
||||
IfExpression, Module, ReturnKind, StmtKind,
|
||||
@ -33,6 +33,28 @@ impl<'t> Pass for TypeInference<'t> {
|
||||
type TError = ErrorKind;
|
||||
|
||||
fn module(&mut self, module: &mut Module, mut state: TypeInferencePassState) -> PassResult {
|
||||
let mut seen_functions = HashMap::new();
|
||||
for function in &mut module.functions {
|
||||
if let Some(kind) = seen_functions.get(&function.name) {
|
||||
state.note_errors(
|
||||
&vec![ErrorKind::FunctionAlreadyDefined(
|
||||
function.name.clone(),
|
||||
*kind,
|
||||
)],
|
||||
function.signature(),
|
||||
);
|
||||
} else {
|
||||
seen_functions.insert(
|
||||
function.name.clone(),
|
||||
match function.kind {
|
||||
FunctionDefinitionKind::Local(..) => ErrorTypedefKind::Local,
|
||||
FunctionDefinitionKind::Extern(..) => ErrorTypedefKind::Extern,
|
||||
FunctionDefinitionKind::Intrinsic(..) => ErrorTypedefKind::Intrinsic,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for function in &mut module.functions {
|
||||
let res = function.infer_types(&self.refs, &mut state.inner());
|
||||
state.ok(res, function.block_meta());
|
||||
@ -69,6 +91,7 @@ impl FunctionDefinition {
|
||||
}
|
||||
}
|
||||
FunctionDefinitionKind::Extern(_) => {}
|
||||
FunctionDefinitionKind::Intrinsic(_) => {}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
@ -98,7 +98,7 @@ fn float_compiles_well() {
|
||||
}
|
||||
#[test]
|
||||
fn hello_world_compiles_well() {
|
||||
test(include_str!("../../examples/hello_world.reid"), "test", 0);
|
||||
test(include_str!("../../examples/hello_world.reid"), "test", 8);
|
||||
}
|
||||
#[test]
|
||||
fn mutable_compiles_well() {
|
||||
|
Loading…
Reference in New Issue
Block a user