Compare commits

..

No commits in common. "bbdfae081debfef2018cca3f9b56e3e6fb4cd574" and "1224c612c7032abb09465b04575f400cbc24f888" have entirely different histories.

23 changed files with 474 additions and 716 deletions

View File

@ -478,7 +478,7 @@ impl Builder {
Instr::SIToFP(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::SIToFP(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::BitCast(..) => Ok(()), Instr::BitCast(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
} }
} }
} }
@ -628,7 +628,7 @@ impl InstructionValue {
SIToFP(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), SIToFP(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
PtrToInt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), PtrToInt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
BitCast(_, ty) => Ok(ty.clone()), BitCast(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
} }
} }
} }

View File

@ -376,8 +376,8 @@ impl DebugLocationHolder {
unsafe { unsafe {
LLVMDIBuilderCreateDebugLocation( LLVMDIBuilderCreateDebugLocation(
context.context_ref, context.context_ref,
self.location.pos.line, self.location.line,
self.location.pos.column, self.location.column,
*debug.programs.get(&self.program).unwrap(), *debug.programs.get(&self.program).unwrap(),
null_mut(), null_mut(),
) )
@ -399,8 +399,8 @@ impl DebugScopeHolder {
di_builder, di_builder,
parent, parent,
file, file,
location.pos.line, location.line,
location.pos.column, location.column,
) )
} else { } else {
LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0)
@ -421,23 +421,23 @@ impl DebugMetadataHolder {
match &self.data { match &self.data {
DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable( DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable(
debug.builder, debug.builder,
*debug.programs.get(&self.location.scope).unwrap(), *debug.programs.get(&self.program).unwrap(),
into_cstring(param.name.clone()).as_ptr(), into_cstring(param.name.clone()).as_ptr(),
param.name.len(), param.name.len(),
param.arg_idx + 1, param.arg_idx + 1,
debug.file_ref, debug.file_ref,
self.location.pos.line, param.location.line,
*debug.types.get(&param.ty).unwrap(), *debug.types.get(&param.ty).unwrap(),
param.always_preserve as i32, param.always_preserve as i32,
param.flags.as_llvm(), param.flags.as_llvm(),
), ),
DebugMetadata::LocalVar(var) => LLVMDIBuilderCreateAutoVariable( DebugMetadata::LocalVar(var) => LLVMDIBuilderCreateAutoVariable(
debug.builder, debug.builder,
*debug.programs.get(&self.location.scope).unwrap(), *debug.programs.get(&self.program).unwrap(),
into_cstring(var.name.clone()).as_ptr(), into_cstring(var.name.clone()).as_ptr(),
var.name.len(), var.name.len(),
debug.file_ref, debug.file_ref,
self.location.pos.line, var.location.line,
*debug.types.get(&var.ty).unwrap(), *debug.types.get(&var.ty).unwrap(),
var.always_preserve as i32, var.always_preserve as i32,
var.flags.as_llvm(), var.flags.as_llvm(),
@ -508,7 +508,7 @@ impl DebugTypeHolder {
into_cstring(field.name.clone()).as_ptr(), into_cstring(field.name.clone()).as_ptr(),
field.name.len(), field.name.len(),
debug.file_ref, debug.file_ref,
field.pos.map(|p| p.line).unwrap_or(1), field.location.line,
field.size_bits, field.size_bits,
0, 0,
1, 1,
@ -523,7 +523,7 @@ impl DebugTypeHolder {
into_cstring(st.name.clone()).as_ptr(), into_cstring(st.name.clone()).as_ptr(),
st.name.len(), st.name.len(),
debug.file_ref, debug.file_ref,
st.pos.map(|p| p.line).unwrap_or(1), st.location.line,
st.size_bits, st.size_bits,
0, 0,
st.flags.as_llvm(), st.flags.as_llvm(),
@ -617,7 +617,7 @@ impl FunctionHolder {
mangled_name, mangled_name,
mangled_length, mangled_length,
debug.file_ref, debug.file_ref,
subprogram.location.pos.line, subprogram.location.line,
*debug.types.get(&subprogram.ty).unwrap(), *debug.types.get(&subprogram.ty).unwrap(),
subprogram.opts.is_local as i32, subprogram.opts.is_local as i32,
subprogram.opts.is_definition as i32, subprogram.opts.is_definition as i32,
@ -1027,8 +1027,8 @@ impl InstructionHolder {
let location = LLVMDIBuilderCreateDebugLocation( let location = LLVMDIBuilderCreateDebugLocation(
module.context_ref, module.context_ref,
record.location.pos.line, record.location.line,
record.location.pos.column, record.location.column,
*debug.programs.get(&record.scope).unwrap(), *debug.programs.get(&record.scope).unwrap(),
null_mut(), null_mut(),
); );

View File

@ -34,7 +34,7 @@ pub(crate) struct DebugScopeHolder {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DebugMetadataHolder { pub struct DebugMetadataHolder {
pub(crate) location: DebugLocation, pub(crate) program: DebugProgramValue,
pub(crate) value: DebugMetadataValue, pub(crate) value: DebugMetadataValue,
pub(crate) data: DebugMetadata, pub(crate) data: DebugMetadata,
} }
@ -140,11 +140,11 @@ impl DebugInformation {
value value
} }
pub fn metadata(&self, location: &DebugLocation, kind: DebugMetadata) -> DebugMetadataValue { pub fn metadata(&self, program: &DebugProgramValue, kind: DebugMetadata) -> DebugMetadataValue {
let mut metadata = self.metadata.borrow_mut(); let mut metadata = self.metadata.borrow_mut();
let value = DebugMetadataValue(metadata.len()); let value = DebugMetadataValue(metadata.len());
metadata.push(DebugMetadataHolder { metadata.push(DebugMetadataHolder {
location: *location, program: *program,
value: value.clone(), value: value.clone(),
data: kind, data: kind,
}); });
@ -165,10 +165,6 @@ impl DebugInformation {
unsafe { self.metadata.borrow().get_unchecked(value.0).data.clone() } unsafe { self.metadata.borrow().get_unchecked(value.0).data.clone() }
} }
pub fn get_metadata_location(&self, value: DebugMetadataValue) -> DebugLocation {
unsafe { self.metadata.borrow().get_unchecked(value.0).location }
}
pub fn get_subprogram_data(&self, value: DebugProgramValue) -> Option<DebugSubprogramData> { pub fn get_subprogram_data(&self, value: DebugProgramValue) -> Option<DebugSubprogramData> {
if value.0 == 0 { if value.0 == 0 {
None None
@ -222,14 +218,8 @@ impl DebugInformation {
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Default)]
pub struct DebugLocation { pub struct DebugLocation {
pub scope: DebugProgramValue,
pub pos: DebugPosition,
}
#[derive(Clone, Copy)]
pub struct DebugPosition {
pub line: u32, pub line: u32,
pub column: u32, pub column: u32,
} }
@ -248,6 +238,8 @@ pub struct DebugParamVariable {
/// parameters. arg_idx should not conflict with other parameters of the /// parameters. arg_idx should not conflict with other parameters of the
/// same subprogram. /// same subprogram.
pub arg_idx: u32, pub arg_idx: u32,
/// Used for line number
pub location: DebugLocation,
pub ty: DebugTypeValue, pub ty: DebugTypeValue,
/// If this variable will be referenced from its containing subprogram, and /// If this variable will be referenced from its containing subprogram, and
/// will survive some optimizations. /// will survive some optimizations.
@ -258,6 +250,7 @@ pub struct DebugParamVariable {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DebugLocalVariable { pub struct DebugLocalVariable {
pub name: String, pub name: String,
pub location: DebugLocation,
pub ty: DebugTypeValue, pub ty: DebugTypeValue,
pub always_preserve: bool, pub always_preserve: bool,
pub flags: DwarfFlags, pub flags: DwarfFlags,
@ -316,7 +309,7 @@ pub struct DebugPointerType {
pub struct DebugStructType { pub struct DebugStructType {
pub name: String, pub name: String,
pub scope: DebugProgramValue, pub scope: DebugProgramValue,
pub pos: Option<DebugPosition>, pub location: DebugLocation,
pub size_bits: u64, pub size_bits: u64,
pub flags: DwarfFlags, pub flags: DwarfFlags,
pub fields: Vec<DebugFieldType>, pub fields: Vec<DebugFieldType>,
@ -325,8 +318,7 @@ pub struct DebugStructType {
#[derive(Clone)] #[derive(Clone)]
pub struct DebugFieldType { pub struct DebugFieldType {
pub name: String, pub name: String,
pub scope: DebugProgramValue, pub location: DebugLocation,
pub pos: Option<DebugPosition>,
pub size_bits: u64, pub size_bits: u64,
pub offset: u64, pub offset: u64,
pub flags: DwarfFlags, pub flags: DwarfFlags,

View File

@ -11,8 +11,8 @@ use crate::{
debug_information::{ debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable,
DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable,
DebugPointerType, DebugPosition, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugPointerType, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugStructType,
DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue,
}, },
pad_adapter::PadAdapter, pad_adapter::PadAdapter,
}; };
@ -157,26 +157,26 @@ impl InstructionHolder {
impl DebugMetadataValue { impl DebugMetadataValue {
fn hr(&self, debug: &DebugInformation) -> String { fn hr(&self, debug: &DebugInformation) -> String {
let kind = match debug.get_metadata(*self) { match debug.get_metadata(*self) {
DebugMetadata::ParamVar(DebugParamVariable { DebugMetadata::ParamVar(DebugParamVariable {
name, arg_idx, ty, .. name,
}) => format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty), arg_idx,
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { location,
format!("var {} (type {:?}) ", name, ty) ty,
} ..
}) => format!(
"param {} (idx {}) (type {:?}) at {}",
name, arg_idx, ty, location
),
DebugMetadata::LocalVar(DebugLocalVariable {
name, location, ty, ..
}) => format!("var {} (type {:?}) at {}", name, ty, location),
DebugMetadata::VarAssignment => todo!(), DebugMetadata::VarAssignment => todo!(),
}; }
format!("{} at {}", kind, debug.get_metadata_location(*self))
} }
} }
impl Display for DebugLocation { impl Display for DebugLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?} on scope {:?}", self.pos, self.scope)
}
}
impl Display for DebugPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "line {}, col {}", self.line, self.column) write!(f, "line {}, col {}", self.line, self.column)
} }
@ -491,7 +491,7 @@ impl Debug for DebugStructType {
f.debug_struct("Struct") f.debug_struct("Struct")
.field("name", &self.name) .field("name", &self.name)
.field("scope", &self.scope) .field("scope", &self.scope)
.field("pos", &self.pos) .field("location", &self.location)
.field("size_bit", &self.size_bits) .field("size_bit", &self.size_bits)
.field("flags", &self.flags) .field("flags", &self.flags)
.field("elements", &self.fields) .field("elements", &self.fields)
@ -502,8 +502,7 @@ impl Debug for DebugStructType {
impl Debug for DebugFieldType { impl Debug for DebugFieldType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("Field({})", self.name)) f.debug_struct(&format!("Field({})", self.name))
.field("scope", &self.scope) .field("location", &self.location)
.field("pos", &self.pos)
.field("size_bits", &self.size_bits) .field("size_bits", &self.size_bits)
.field("offset", &self.offset) .field("offset", &self.offset)
.field("flags", &self.flags) .field("flags", &self.flags)
@ -577,12 +576,6 @@ impl Debug for DebugLocationValue {
} }
impl Debug for DebugLocation { impl Debug for DebugLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?} on scope {:?}", self.pos, self.scope)
}
}
impl Debug for DebugPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ln {}, col {}", self.line, self.column) write!(f, "ln {}, col {}", self.line, self.column)
} }

View File

@ -51,7 +51,6 @@ pub struct ModuleData {
is_main: bool, is_main: bool,
} }
#[derive(Clone)]
pub struct Module<'ctx> { pub struct Module<'ctx> {
phantom: PhantomData<&'ctx ()>, phantom: PhantomData<&'ctx ()>,
builder: Builder, builder: Builder,
@ -521,7 +520,7 @@ impl ConstValue {
ConstValue::U32(_) => U32, ConstValue::U32(_) => U32,
ConstValue::U64(_) => U64, ConstValue::U64(_) => U64,
ConstValue::U128(_) => U128, ConstValue::U128(_) => U128,
ConstValue::Str(_) => Type::Ptr(Box::new(U8)), ConstValue::Str(_) => Type::Ptr(Box::new(I8)),
ConstValue::Bool(_) => Bool, ConstValue::Bool(_) => Bool,
ConstValue::F16(_) => F16, ConstValue::F16(_) => F16,
ConstValue::F32B(_) => F32B, ConstValue::F32B(_) => F32B,

View File

@ -1,7 +1,6 @@
extern fn puts(message: *char) -> i32; extern fn puts(message: *char) -> i32;
extern fn malloc(size: u64) -> *u8; extern fn malloc(size: u64) -> *u8;
extern fn free(ptr: *u8);
extern fn div(numerator: i32, denominator: i32) -> div_t; extern fn div(numerator: i32, denominator: i32) -> div_t;
struct div_t { struct div_t {
@ -9,8 +8,8 @@ struct div_t {
remainder: i32, remainder: i32,
} }
pub fn print(message: &String) { pub fn print(message: *char) {
puts(*message.inner); puts(message);
} }
pub fn int_div(numerator: i32, denominator: i32) -> div_t { pub fn int_div(numerator: i32, denominator: i32) -> div_t {
@ -21,42 +20,6 @@ pub fn allocate(size: u64) -> *u8 {
malloc(size) malloc(size)
} }
struct String { fn main() -> u16 {
inner: *char, return 0;
length: u64,
max_length: u64,
}
pub fn new_string() -> String {
String {
inner: allocate(0),
length: 0,
}
}
pub fn add_char(string: &mut String, c: char) {
if ((*string).length + 1) >= (*string).max_length {
let new = allocate((*string).max_length + 4) as *char;
copy_bits((*string).inner, new, 0, (*string).max_length);
free((*string).inner as *u8);
(*string).max_length = (*string).max_length + 4;
(*string).inner = new;
}
(*string).inner[(*string).length] = c;
(((*string).inner) as *u8)[((*string).length + 1)] = 0;
(*string).length = (*string).length + 1;
}
fn copy_bits(from: *char, to: *char, pos: u64, max: u64) -> u8 {
if (pos >= max) {
return 0;
}
to[pos] = from[pos];
return copy_bits(from, to, pos + 1, max);
}
pub fn free_string(string: &mut String) {
free((*string).inner as *u8);
} }

View File

@ -3,7 +3,7 @@
//! used for unwrapping syntax sugar, and then be transformed into Reid MIR. //! used for unwrapping syntax sugar, and then be transformed into Reid MIR.
use std::path::PathBuf; use std::path::PathBuf;
use crate::{lexer::FullToken, token_stream::TokenRange}; use crate::token_stream::TokenRange;
pub mod parse; pub mod parse;
pub mod process; pub mod process;
@ -206,7 +206,6 @@ pub enum TopLevelStatement {
#[derive(Debug)] #[derive(Debug)]
pub struct Module { pub struct Module {
pub name: String, pub name: String,
pub tokens: Vec<FullToken>,
pub top_level_statements: Vec<TopLevelStatement>, pub top_level_statements: Vec<TopLevelStatement>,
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
pub is_main: bool, pub is_main: bool,

View File

@ -1,25 +1,18 @@
use std::path::PathBuf; use std::{path::PathBuf, process};
use crate::{ use crate::{
ast::{self}, ast::{self},
mir::{ mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType},
self, ModuleMap, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType,
CustomTypeKey,
},
}; };
impl mir::Context { impl mir::Context {
pub fn from(modules: Vec<mir::Module>, base: PathBuf) -> mir::Context { pub fn from(modules: Vec<mir::Module>, base: PathBuf) -> mir::Context {
let mut map = ModuleMap::new(); mir::Context { modules, base }
for module in modules {
map.insert(module.module_id, module);
}
mir::Context { modules: map, base }
} }
} }
impl ast::Module { impl ast::Module {
pub fn process(self, module_id: SourceModuleId) -> mir::Module { pub fn process(&self, module_id: SourceModuleId) -> mir::Module {
let mut imports = Vec::new(); let mut imports = Vec::new();
let mut functions = Vec::new(); let mut functions = Vec::new();
let mut typedefs = Vec::new(); let mut typedefs = Vec::new();
@ -38,13 +31,13 @@ impl ast::Module {
return_type: signature return_type: signature
.return_type .return_type
.clone() .clone()
.map(|r| r.0.into_mir(module_id)) .map(|r| r.0.into())
.unwrap_or(mir::TypeKind::Void), .unwrap_or(mir::TypeKind::Void),
parameters: signature parameters: signature
.args .args
.iter() .iter()
.cloned() .cloned()
.map(|p| (p.0, p.1 .0.into_mir(module_id))) .map(|p| (p.0, p.1.into()))
.collect(), .collect(),
kind: mir::FunctionDefinitionKind::Local( kind: mir::FunctionDefinitionKind::Local(
block.into_mir(module_id), block.into_mir(module_id),
@ -61,13 +54,13 @@ impl ast::Module {
return_type: signature return_type: signature
.return_type .return_type
.clone() .clone()
.map(|r| r.0.into_mir(module_id)) .map(|r| r.0.into())
.unwrap_or(mir::TypeKind::Void), .unwrap_or(mir::TypeKind::Void),
parameters: signature parameters: signature
.args .args
.iter() .iter()
.cloned() .cloned()
.map(|p| (p.0, p.1 .0.into_mir(module_id))) .map(|p| (p.0, p.1.into()))
.collect(), .collect(),
kind: mir::FunctionDefinitionKind::Extern(false), kind: mir::FunctionDefinitionKind::Extern(false),
}; };
@ -84,7 +77,7 @@ impl ast::Module {
.map(|s| { .map(|s| {
StructField( StructField(
s.name.clone(), s.name.clone(),
s.ty.clone().0.into_mir(module_id), s.ty.clone().into(),
s.range.as_meta(module_id), s.range.as_meta(module_id),
) )
}) })
@ -93,7 +86,6 @@ impl ast::Module {
} }
}, },
meta: (*range).as_meta(module_id), meta: (*range).as_meta(module_id),
source_module: module_id,
}; };
typedefs.push(def); typedefs.push(def);
} }
@ -107,7 +99,6 @@ impl ast::Module {
functions, functions,
path: self.path.clone(), path: self.path.clone(),
is_main: self.is_main, is_main: self.is_main,
tokens: self.tokens,
typedefs, typedefs,
} }
} }
@ -125,7 +116,7 @@ impl ast::Block {
s_let s_let
.ty .ty
.clone() .clone()
.map(|t| t.0.into_mir(module_id)) .map(|t| t.0.into())
.unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)), .unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)),
s_let.name.clone(), s_let.name.clone(),
s_let.name_range.as_meta(module_id), s_let.name_range.as_meta(module_id),
@ -265,10 +256,9 @@ impl ast::Expression {
Box::new(expr.process(module_id)), Box::new(expr.process(module_id)),
), ),
}, },
ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo( ast::ExpressionKind::CastTo(expression, ty) => {
Box::new(expression.process(module_id)), mir::ExprKind::CastTo(Box::new(expression.process(module_id)), ty.0.clone().into())
ty.0.clone().into_mir(module_id), }
),
}; };
mir::Expression(kind, self.1.as_meta(module_id)) mir::Expression(kind, self.1.as_meta(module_id))
@ -304,9 +294,9 @@ impl ast::Literal {
} }
} }
impl ast::TypeKind { impl From<ast::TypeKind> for mir::TypeKind {
fn into_mir(&self, source_mod: SourceModuleId) -> mir::TypeKind { fn from(value: ast::TypeKind) -> Self {
match &self { 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,
@ -319,16 +309,14 @@ impl ast::TypeKind {
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) => {
mir::TypeKind::Array(Box::new(type_kind.clone().into_mir(source_mod)), *length) mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length)
}
ast::TypeKind::Custom(name) => {
mir::TypeKind::CustomType(CustomTypeKey(name.clone(), source_mod))
} }
ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()),
ast::TypeKind::Borrow(type_kind, mutable) => { ast::TypeKind::Borrow(type_kind, mutable) => {
mir::TypeKind::Borrow(Box::new(type_kind.clone().into_mir(source_mod)), *mutable) mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())), *mutable)
} }
ast::TypeKind::Ptr(type_kind) => { ast::TypeKind::Ptr(type_kind) => {
mir::TypeKind::UserPtr(Box::new(type_kind.clone().into_mir(source_mod))) mir::TypeKind::UserPtr(Box::new(mir::TypeKind::from(*type_kind.clone())))
} }
ast::TypeKind::F16 => mir::TypeKind::F16, ast::TypeKind::F16 => mir::TypeKind::F16,
ast::TypeKind::F32B => mir::TypeKind::F32B, ast::TypeKind::F32B => mir::TypeKind::F32B,
@ -341,3 +329,9 @@ impl ast::TypeKind {
} }
} }
} }
impl From<ast::Type> for mir::TypeKind {
fn from(value: ast::Type) -> Self {
value.0.into()
}
}

View File

@ -1,12 +1,12 @@
use std::{array, collections::HashMap, hash::Hash, mem}; use std::{array, collections::HashMap, mem};
use reid_lib::{ use reid_lib::{
builder::{InstructionValue, ModuleValue, TypeValue}, builder::{InstructionValue, TypeValue},
compile::CompiledModule, compile::CompiledModule,
debug_information::{ debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugFileData, DebugInformation, DebugArrayType, DebugBasicType, DebugFieldType, DebugFileData, DebugInformation,
DebugLocalVariable, DebugLocation, DebugMetadata, DebugParamVariable, DebugPointerType, DebugLocalVariable, DebugLocation, DebugMetadata, DebugParamVariable, DebugPointerType,
DebugPosition, DebugProgramValue, DebugRecordKind, DebugStructType, DebugSubprogramData, DebugProgramValue, DebugRecordKind, DebugStructType, DebugSubprogramData,
DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DebugTypeValue, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DebugTypeValue,
DwarfEncoding, DwarfFlags, InstructionDebugRecordData, DwarfEncoding, DwarfFlags, InstructionDebugRecordData,
}, },
@ -15,12 +15,11 @@ use reid_lib::{
}; };
use crate::{ use crate::{
error_raporting::ErrorModules, error_raporting::ModuleMap,
lexer::{FullToken, Position}, lexer::{FullToken, Position},
mir::{ mir::{
self, implement::TypeCategory, CustomTypeKey, Metadata, ModuleMap, NamedVariableRef, self, implement::TypeCategory, Metadata, NamedVariableRef, StructField, StructType,
SourceModuleId, StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral,
VagueLiteral,
}, },
}; };
@ -41,25 +40,31 @@ impl<'ctx> CodegenContext<'ctx> {
impl mir::Context { impl mir::Context {
/// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR. /// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR.
pub fn codegen<'ctx>(&self, context: &'ctx Context) -> CodegenContext<'ctx> { pub fn codegen<'ctx>(
let mut modules = HashMap::new(); &self,
let mut modules_sorted = self.modules.iter().map(|(_, m)| m).collect::<Vec<_>>(); context: &'ctx Context,
modules_sorted.sort_by(|m1, m2| m2.module_id.cmp(&m1.module_id)); mod_map: &ModuleMap,
) -> CodegenContext<'ctx> {
for module in &modules_sorted { let mut modules = Vec::new();
let codegen = module.codegen(context, modules.clone()); for module in &self.modules {
modules.insert(module.module_id, codegen); modules.push(
module.codegen(
context,
mod_map
.module(&module.module_id)
.unwrap()
.tokens
.as_ref()
.unwrap(),
),
);
} }
CodegenContext { context } CodegenContext { context }
} }
} }
#[derive(Clone)]
struct ModuleCodegen<'ctx> { struct ModuleCodegen<'ctx> {
module: Module<'ctx>, module: Module<'ctx>,
tokens: &'ctx Vec<FullToken>,
debug_types: Option<HashMap<TypeKind, DebugTypeValue>>,
type_values: HashMap<CustomTypeKey, TypeValue>,
} }
impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> { impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> {
@ -68,17 +73,15 @@ impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> {
} }
} }
pub struct Scope<'ctx, 'scope> { pub struct Scope<'ctx, 'a> {
context: &'ctx Context, context: &'ctx Context,
modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>,
tokens: &'ctx Vec<FullToken>, tokens: &'ctx Vec<FullToken>,
module: &'ctx Module<'ctx>, module: &'ctx Module<'ctx>,
module_id: SourceModuleId,
function: &'ctx StackFunction<'ctx>, function: &'ctx StackFunction<'ctx>,
block: Block<'ctx>, block: Block<'ctx>,
types: &'scope HashMap<TypeValue, TypeDefinition>, types: &'a HashMap<TypeValue, TypeDefinition>,
type_values: &'scope HashMap<CustomTypeKey, TypeValue>, type_values: &'a HashMap<String, TypeValue>,
functions: &'scope HashMap<String, StackFunction<'ctx>>, functions: &'a HashMap<String, StackFunction<'ctx>>,
stack_values: HashMap<String, StackValue>, stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>, debug: Option<Debug<'ctx>>,
} }
@ -147,12 +150,10 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> { fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> {
Scope { Scope {
block, block,
modules: self.modules,
tokens: self.tokens, tokens: self.tokens,
function: self.function, function: self.function,
context: self.context, context: self.context,
module: self.module, module: self.module,
module_id: self.module_id,
functions: self.functions, functions: self.functions,
types: self.types, types: self.types,
type_values: self.type_values, type_values: self.type_values,
@ -169,8 +170,8 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
old_block old_block
} }
fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> { fn get_typedef(&self, name: &String) -> Option<&TypeDefinition> {
self.type_values.get(key).and_then(|v| self.types.get(v)) self.type_values.get(name).and_then(|v| self.types.get(v))
} }
} }
@ -196,12 +197,11 @@ impl Default for State {
impl mir::Module { impl mir::Module {
fn codegen<'ctx>( fn codegen<'ctx>(
&'ctx self, &self,
context: &'ctx Context, context: &'ctx Context,
modules: HashMap<SourceModuleId, ModuleCodegen<'ctx>>, tokens: &Vec<FullToken>,
) -> ModuleCodegen<'ctx> { ) -> ModuleCodegen<'ctx> {
let mut module = context.module(&self.name, self.is_main); let mut module = context.module(&self.name, self.is_main);
let tokens = &self.tokens;
let (debug, compile_unit) = if let Some(path) = &self.path { let (debug, compile_unit) = if let Some(path) = &self.path {
module.create_debug_info(DebugFileData { module.create_debug_info(DebugFileData {
@ -229,9 +229,7 @@ impl mir::Module {
&debug_types, &debug_types,
&type_values, &type_values,
&types, &types,
self.module_id, tokens,
&self.tokens,
&modules,
), ),
) )
}; };
@ -251,11 +249,7 @@ impl mir::Module {
insert_debug!(&TypeKind::Void); insert_debug!(&TypeKind::Void);
insert_debug!(&TypeKind::Char); insert_debug!(&TypeKind::Char);
let mut typedefs = self.typedefs.clone(); for typedef in &self.typedefs {
typedefs.sort_by(|a, b| b.source_module.cmp(&a.source_module));
for typedef in typedefs {
let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module);
let type_value = match &typedef.kind { let type_value = match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => { TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
@ -271,8 +265,8 @@ impl mir::Module {
} }
}; };
types.insert(type_value, typedef.clone()); types.insert(type_value, typedef.clone());
type_values.insert(type_key.clone(), type_value); type_values.insert(typedef.name.clone(), type_value);
insert_debug!(&TypeKind::CustomType(type_key.clone())); insert_debug!(&TypeKind::CustomType(typedef.name.clone()));
} }
let mut functions = HashMap::new(); let mut functions = HashMap::new();
@ -314,126 +308,116 @@ impl mir::Module {
for mir_function in &self.functions { for mir_function in &self.functions {
let function = functions.get(&mir_function.name).unwrap(); let function = functions.get(&mir_function.name).unwrap();
let mut entry = function.ir.block("entry");
// Insert debug information
let debug_scope = if let Some(location) = mir_function.signature().into_debug(tokens) {
// let debug_scope = debug.inner_scope(&outer_scope, location);
let fn_param_ty = &mir_function.return_type.get_debug_type_hard(
compile_unit,
&debug,
&debug_types,
&type_values,
&types,
tokens,
);
let debug_ty = debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramType {
parameters: vec![*fn_param_ty],
flags: DwarfFlags,
}));
let subprogram = debug.subprogram(DebugSubprogramData {
name: mir_function.name.clone(),
outer_scope: compile_unit.clone(),
location,
ty: debug_ty,
opts: DebugSubprogramOptionals {
is_local: !mir_function.is_pub,
is_definition: true,
..DebugSubprogramOptionals::default()
},
});
function.ir.set_debug(subprogram);
Some(subprogram)
} else {
None
};
// Compile actual IR part
let mut stack_values = HashMap::new();
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
// Codegen actual parameters
let arg_name = format!("arg.{}", p_name);
let param = entry
.build_named(format!("{}.get", arg_name), Instr::Param(i))
.unwrap();
let alloca = entry
.build_named(
&arg_name,
Instr::Alloca(p_ty.get_type(&type_values, &types)),
)
.unwrap();
entry
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
.unwrap();
stack_values.insert(
p_name.clone(),
StackValue(
StackValueKind::mutable(p_ty.is_mutable(), alloca),
TypeKind::CodegenPtr(Box::new(p_ty.clone())),
),
);
// Generate debug info
if let (Some(debug_scope), Some(location)) =
(&debug_scope, mir_function.signature().into_debug(tokens))
{
debug.metadata(
&debug_scope,
DebugMetadata::ParamVar(DebugParamVariable {
name: p_name.clone(),
arg_idx: i as u32,
location,
ty: p_ty.get_debug_type_hard(
*debug_scope,
&debug,
&debug_types,
&type_values,
&types,
tokens,
),
always_preserve: true,
flags: DwarfFlags,
}),
);
}
}
let mut scope = Scope {
context,
tokens,
module: &module,
function,
block: entry,
functions: &functions,
types: &types,
type_values: &type_values,
stack_values,
debug: debug_scope.and_then(|scope| {
Some(Debug {
info: &debug,
scope,
types: &debug_types,
})
}),
};
match &mir_function.kind { match &mir_function.kind {
mir::FunctionDefinitionKind::Local(block, _) => { mir::FunctionDefinitionKind::Local(block, _) => {
let mut entry = function.ir.block("entry");
// Insert debug information
let debug_scope = if let Some(location) =
mir_function.signature().into_debug(tokens, compile_unit)
{
// let debug_scope = debug.inner_scope(&outer_scope, location);
let fn_param_ty = &mir_function.return_type.get_debug_type_hard(
compile_unit,
&debug,
&debug_types,
&type_values,
&types,
self.module_id,
&self.tokens,
&modules,
);
let debug_ty =
debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramType {
parameters: vec![*fn_param_ty],
flags: DwarfFlags,
}));
let subprogram = debug.subprogram(DebugSubprogramData {
name: mir_function.name.clone(),
outer_scope: compile_unit.clone(),
location,
ty: debug_ty,
opts: DebugSubprogramOptionals {
is_local: !mir_function.is_pub,
is_definition: true,
..DebugSubprogramOptionals::default()
},
});
function.ir.set_debug(subprogram);
Some(subprogram)
} else {
None
};
// Compile actual IR part
let mut stack_values = HashMap::new();
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
// Codegen actual parameters
let arg_name = format!("arg.{}", p_name);
let param = entry
.build_named(format!("{}.get", arg_name), Instr::Param(i))
.unwrap();
let alloca = entry
.build_named(
&arg_name,
Instr::Alloca(p_ty.get_type(&type_values, &types)),
)
.unwrap();
entry
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
.unwrap();
stack_values.insert(
p_name.clone(),
StackValue(
StackValueKind::mutable(p_ty.is_mutable(), alloca),
TypeKind::CodegenPtr(Box::new(p_ty.clone())),
),
);
// Generate debug info
if let (Some(debug_scope), Some(location)) = (
&debug_scope,
mir_function.signature().into_debug(tokens, compile_unit),
) {
// debug.metadata(
// &location,
// DebugMetadata::ParamVar(DebugParamVariable {
// name: p_name.clone(),
// arg_idx: i as u32,
// ty: p_ty.get_debug_type_hard(
// *debug_scope,
// &debug,
// &debug_types,
// &type_values,
// &types,
// self.module_id,
// &self.tokens,
// &modules,
// ),
// always_preserve: true,
// flags: DwarfFlags,
// }),
// );
}
}
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,
debug: debug_scope.and_then(|scope| {
Some(Debug {
info: &debug,
scope,
types: &debug_types,
})
}),
};
let state = State::default(); let state = State::default();
if let Some(ret) = block.codegen(&mut scope, &state) { if let Some(ret) = block.codegen(&mut scope, &state) {
scope.block.terminate(Term::Ret(ret.instr())).unwrap(); scope.block.terminate(Term::Ret(ret.instr())).unwrap();
@ -446,8 +430,7 @@ impl mir::Module {
} }
if let Some(debug) = scope.debug { if let Some(debug) = scope.debug {
let location = let location = &block.return_meta().into_debug(tokens).unwrap();
&block.return_meta().into_debug(tokens, debug.scope).unwrap();
let location = debug.info.location(&debug.scope, *location); let location = debug.info.location(&debug.scope, *location);
scope.block.set_terminator_location(location).unwrap(); scope.block.set_terminator_location(location).unwrap();
} }
@ -456,12 +439,7 @@ impl mir::Module {
} }
} }
ModuleCodegen { ModuleCodegen { module }
module,
debug_types: Some(debug_types),
type_values,
tokens: &self.tokens,
}
} }
} }
@ -474,7 +452,7 @@ impl mir::Block {
for stmt in &self.statements { for stmt in &self.statements {
stmt.codegen(&mut scope, state).map(|s| { stmt.codegen(&mut scope, state).map(|s| {
if let Some(debug) = &scope.debug { if let Some(debug) = &scope.debug {
let location = stmt.1.into_debug(scope.tokens, debug.scope).unwrap(); let location = stmt.1.into_debug(scope.tokens).unwrap();
let loc_val = debug.info.location(&debug.scope, location); let loc_val = debug.info.location(&debug.scope, location);
s.instr().with_location(&mut scope.block, loc_val); s.instr().with_location(&mut scope.block, loc_val);
} }
@ -498,10 +476,11 @@ impl mir::Block {
impl mir::Statement { impl mir::Statement {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> {
let location = scope.debug.clone().map(|d| { let location = self.1.into_debug(scope.tokens).unwrap();
let location = self.1.into_debug(scope.tokens, d.scope).unwrap(); let location = scope
d.info.location(&d.scope, location) .debug
}); .as_ref()
.map(|d| d.info.location(&d.scope, location));
match &self.0 { match &self.0 {
mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => { mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => {
@ -535,11 +514,12 @@ impl mir::Statement {
StackValue(stack_value, TypeKind::CodegenPtr(Box::new(value.clone().1))), StackValue(stack_value, TypeKind::CodegenPtr(Box::new(value.clone().1))),
); );
if let Some(debug) = &scope.debug { if let Some(debug) = &scope.debug {
let location = self.1.into_debug(scope.tokens, debug.scope).unwrap(); let location = self.1.into_debug(scope.tokens).unwrap();
let var = debug.info.metadata( let var = debug.info.metadata(
&location, &debug.scope,
DebugMetadata::LocalVar(DebugLocalVariable { DebugMetadata::LocalVar(DebugLocalVariable {
name: name.clone(), name: name.clone(),
location,
ty: ty.clone().get_debug_type(debug, scope), ty: ty.clone().get_debug_type(debug, scope),
always_preserve: true, always_preserve: true,
flags: DwarfFlags, flags: DwarfFlags,
@ -597,10 +577,11 @@ impl mir::Statement {
impl mir::Expression { impl mir::Expression {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> {
let location = if let Some(debug) = &scope.debug { let location = if let Some(debug) = &scope.debug {
Some(debug.info.location( Some(
&debug.scope, debug
self.1.into_debug(scope.tokens, debug.scope).unwrap(), .info
)) .location(&debug.scope, self.1.into_debug(scope.tokens).unwrap()),
)
} else { } else {
None None
}; };
@ -651,10 +632,7 @@ impl mir::Expression {
.codegen(scope, state) .codegen(scope, state)
.expect("rhs has no return value") .expect("rhs has no return value")
.instr(); .instr();
let lhs_type = lhs_exp let lhs_type = lhs_exp.return_type(&Default::default()).unwrap().1;
.return_type(&Default::default(), scope.module_id)
.unwrap()
.1;
let instr = match ( let instr = match (
binop, binop,
lhs_type.signed(), lhs_type.signed(),
@ -686,9 +664,8 @@ impl mir::Expression {
let params = call let params = call
.parameters .parameters
.iter() .iter()
.map(|e| e.codegen(scope, state).unwrap()) .map(|e| e.codegen(scope, &mut state.load(true)).unwrap().instr())
.collect::<Vec<_>>(); .collect();
let param_instrs = params.iter().map(|e| e.instr()).collect();
let callee = scope let callee = scope
.functions .functions
.get(&call.name) .get(&call.name)
@ -698,12 +675,12 @@ impl mir::Expression {
.block .block
.build_named( .build_named(
call.name.clone(), call.name.clone(),
Instr::FunctionCall(callee.ir.value(), param_instrs), Instr::FunctionCall(callee.ir.value(), params),
) )
.unwrap(); .unwrap();
if let Some(debug) = &scope.debug { if let Some(debug) = &scope.debug {
let location = call.meta.into_debug(scope.tokens, debug.scope).unwrap(); let location = call.meta.into_debug(scope.tokens).unwrap();
let location_val = debug.info.location(&debug.scope, location); let location_val = debug.info.location(&debug.scope, location);
val.with_location(&mut scope.block, location_val); val.with_location(&mut scope.block, location_val);
} }
@ -776,6 +753,7 @@ impl mir::Expression {
}; };
let (ptr, contained_ty) = if let TypeKind::UserPtr(further_inner) = *inner.clone() { let (ptr, contained_ty) = if let TypeKind::UserPtr(further_inner) = *inner.clone() {
dbg!(&further_inner, &val_t);
let loaded = scope let loaded = scope
.block .block
.build_named( .build_named(
@ -812,6 +790,7 @@ impl mir::Expression {
}; };
if state.should_load { if state.should_load {
dbg!(&contained_ty);
Some(StackValue( Some(StackValue(
kind.derive( kind.derive(
scope scope
@ -908,15 +887,15 @@ impl mir::Expression {
let TypeKind::CodegenPtr(inner) = &struct_val.1 else { let TypeKind::CodegenPtr(inner) = &struct_val.1 else {
panic!("tried accessing non-pointer"); panic!("tried accessing non-pointer");
}; };
let TypeKind::CustomType(key) = *inner.clone() else { let TypeKind::CustomType(name) = *inner.clone() else {
panic!("tried accessing non-custom-type"); panic!("tried accessing non-custom-type");
}; };
let TypeDefinitionKind::Struct(struct_ty) = let TypeDefinitionKind::Struct(struct_ty) =
scope.get_typedef(&key).unwrap().kind.clone(); scope.get_typedef(&name).unwrap().kind.clone();
let idx = struct_ty.find_index(field).unwrap(); let idx = struct_ty.find_index(field).unwrap();
let gep_n = format!("{}.{}.gep", key.0, field); let gep_n = format!("{}.{}.gep", name, field);
let load_n = format!("{}.{}.load", key.0, field); let load_n = format!("{}.{}.load", name, field);
let value = scope let value = scope
.block .block
@ -954,8 +933,7 @@ impl mir::Expression {
} }
} }
mir::ExprKind::Struct(name, items) => { mir::ExprKind::Struct(name, items) => {
let type_key = CustomTypeKey(name.clone(), scope.module_id); let struct_ty = Type::CustomType(*scope.type_values.get(name)?);
let struct_ty = Type::CustomType(*scope.type_values.get(&type_key)?);
let load_n = format!("{}.load", name); let load_n = format!("{}.load", name);
@ -990,7 +968,7 @@ impl mir::Expression {
Some(StackValue( Some(StackValue(
StackValueKind::Literal(struct_val), StackValueKind::Literal(struct_val),
TypeKind::CustomType(type_key), TypeKind::CustomType(name.clone()),
)) ))
} }
mir::ExprKind::Borrow(varref, mutable) => { mir::ExprKind::Borrow(varref, mutable) => {
@ -1048,69 +1026,30 @@ impl mir::Expression {
panic!("Variable was not a pointer?!?") panic!("Variable was not a pointer?!?")
} }
} else { } else {
let TypeKind::Borrow(borrow_inner, mutable) = *ptr_inner.clone() else { StackValue(v.0.derive(var_ptr_instr), *ptr_inner.clone())
panic!();
};
StackValue(
StackValueKind::mutable(mutable, var_ptr_instr),
TypeKind::CodegenPtr(borrow_inner.clone()),
)
} }
}) })
} }
mir::ExprKind::CastTo(expression, type_kind) => { mir::ExprKind::CastTo(expression, type_kind) => {
let val = expression.codegen(scope, state)?; let val = expression.codegen(scope, state)?;
if val.1 == *type_kind { if val.1 == *type_kind {
Some(val) Some(val)
} else if let (TypeKind::UserPtr(_), TypeKind::UserPtr(_)) = (&val.1, type_kind) {
Some(val)
} else { } else {
match (&val.1, type_kind) { let cast_instr = val
(TypeKind::CodegenPtr(inner), TypeKind::UserPtr(_)) => match *inner.clone() .1
{ .get_type(scope.type_values, scope.types)
TypeKind::UserPtr(_) => Some(StackValue( .cast_instruction(
val.0.derive( val.instr(),
scope &type_kind.get_type(scope.type_values, scope.types),
.block )
.build(Instr::BitCast( .unwrap();
val.instr(),
Type::Ptr(Box::new(
type_kind.get_type(scope.type_values, scope.types),
)),
))
.unwrap(),
),
TypeKind::CodegenPtr(Box::new(type_kind.clone())),
)),
_ => panic!(),
},
(TypeKind::UserPtr(_), TypeKind::UserPtr(_)) => Some(StackValue(
val.0.derive(
scope
.block
.build(Instr::BitCast(
val.instr(),
type_kind.get_type(scope.type_values, scope.types),
))
.unwrap(),
),
type_kind.clone(),
)),
_ => {
let cast_instr = val
.1
.get_type(scope.type_values, scope.types)
.cast_instruction(
val.instr(),
&type_kind.get_type(scope.type_values, scope.types),
)
.unwrap();
Some(StackValue( Some(StackValue(
val.0.derive(scope.block.build(cast_instr).unwrap()), val.0.derive(scope.block.build(cast_instr).unwrap()),
type_kind.clone(), type_kind.clone(),
)) ))
}
}
} }
} }
}; };
@ -1131,23 +1070,16 @@ impl mir::IfExpression {
let after_b = scope.function.ir.block("after"); let after_b = scope.function.ir.block("after");
if let Some(debug) = &scope.debug { if let Some(debug) = &scope.debug {
let before_location = self.0 .1.into_debug(scope.tokens, debug.scope).unwrap(); let before_location = self.0 .1.into_debug(scope.tokens).unwrap();
let before_v = debug.info.location(&debug.scope, before_location); let before_v = debug.info.location(&debug.scope, before_location);
scope.block.set_terminator_location(before_v).unwrap(); scope.block.set_terminator_location(before_v).unwrap();
let then_location = self let then_location = self.1.return_meta().into_debug(scope.tokens).unwrap();
.1
.return_meta()
.into_debug(scope.tokens, debug.scope)
.unwrap();
let then_v = debug.info.location(&debug.scope, then_location); let then_v = debug.info.location(&debug.scope, then_location);
then_b.set_terminator_location(then_v).unwrap(); then_b.set_terminator_location(then_v).unwrap();
let else_location = if let Some(else_block) = &self.2 { let else_location = if let Some(else_block) = &self.2 {
else_block else_block.return_meta().into_debug(scope.tokens).unwrap()
.return_meta()
.into_debug(scope.tokens, debug.scope)
.unwrap()
} else { } else {
then_location then_location
}; };
@ -1277,7 +1209,7 @@ impl mir::Literal {
impl TypeKind { impl TypeKind {
fn get_type( fn get_type(
&self, &self,
type_vals: &HashMap<CustomTypeKey, TypeValue>, type_vals: &HashMap<String, TypeValue>,
typedefs: &HashMap<TypeValue, TypeDefinition>, typedefs: &HashMap<TypeValue, TypeDefinition>,
) -> Type { ) -> Type {
match &self { match &self {
@ -1299,7 +1231,7 @@ impl TypeKind {
TypeKind::F128 => Type::F128, TypeKind::F128 => Type::F128,
TypeKind::F80 => Type::F80, TypeKind::F80 => Type::F80,
TypeKind::F128PPC => Type::F128PPC, TypeKind::F128PPC => Type::F128PPC,
TypeKind::Char => Type::U8, TypeKind::Char => Type::I8,
TypeKind::Array(elem_t, len) => { TypeKind::Array(elem_t, len) => {
Type::Array(Box::new(elem_t.get_type(type_vals, typedefs)), *len) Type::Array(Box::new(elem_t.get_type(type_vals, typedefs)), *len)
} }
@ -1330,9 +1262,7 @@ impl TypeKind {
debug.types, debug.types,
scope.type_values, scope.type_values,
scope.types, scope.types,
scope.module_id,
scope.tokens, scope.tokens,
scope.modules,
) )
} }
@ -1341,11 +1271,9 @@ impl TypeKind {
scope: DebugProgramValue, scope: DebugProgramValue,
debug_info: &DebugInformation, debug_info: &DebugInformation,
debug_types: &HashMap<TypeKind, DebugTypeValue>, debug_types: &HashMap<TypeKind, DebugTypeValue>,
type_values: &HashMap<CustomTypeKey, TypeValue>, type_values: &HashMap<String, TypeValue>,
types: &HashMap<TypeValue, TypeDefinition>, types: &HashMap<TypeValue, TypeDefinition>,
local_mod: SourceModuleId,
tokens: &Vec<FullToken>, tokens: &Vec<FullToken>,
modules: &HashMap<SourceModuleId, ModuleCodegen>,
) -> DebugTypeValue { ) -> DebugTypeValue {
if let Some(ty) = debug_types.get(self) { if let Some(ty) = debug_types.get(self) {
return *ty; return *ty;
@ -1363,9 +1291,7 @@ impl TypeKind {
debug_types, debug_types,
type_values, type_values,
types, types,
local_mod,
tokens, tokens,
modules,
), ),
size_bits: self.size_of(), size_bits: self.size_of(),
}) })
@ -1377,9 +1303,7 @@ impl TypeKind {
debug_types, debug_types,
type_values, type_values,
types, types,
local_mod,
tokens, tokens,
modules,
); );
DebugTypeData::Array(DebugArrayType { DebugTypeData::Array(DebugArrayType {
size_bits: self.size_of(), size_bits: self.size_of(),
@ -1388,23 +1312,17 @@ impl TypeKind {
length: *len, length: *len,
}) })
} }
TypeKind::CustomType(key) => { TypeKind::CustomType(name) => {
let typedef = types.get(type_values.get(key).unwrap()).unwrap(); let typedef = types.get(type_values.get(name).unwrap()).unwrap();
match &typedef.kind { match &typedef.kind {
TypeDefinitionKind::Struct(struct_type) => { TypeDefinitionKind::Struct(struct_type) => {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut size_bits = 0; let mut size_bits = 0;
for field in &struct_type.0 { for field in &struct_type.0 {
let location = if typedef.source_module != local_mod {
None
} else {
field.2.into_debug(&tokens, scope)
};
fields.push(DebugFieldType { fields.push(DebugFieldType {
name: field.0.clone(), name: field.0.clone(),
scope, location: field.2.into_debug(tokens).unwrap(),
pos: location.map(|l| l.pos),
size_bits: field.1.size_of(), size_bits: field.1.size_of(),
offset: size_bits, offset: size_bits,
flags: DwarfFlags, flags: DwarfFlags,
@ -1414,23 +1332,16 @@ impl TypeKind {
debug_types, debug_types,
type_values, type_values,
types, types,
local_mod,
tokens, tokens,
modules,
), ),
}); });
size_bits += field.1.size_of(); size_bits += field.1.size_of();
} }
{ {
let location = if typedef.source_module != local_mod {
None
} else {
typedef.meta.into_debug(&tokens, scope)
};
DebugTypeData::Struct(DebugStructType { DebugTypeData::Struct(DebugStructType {
name: key.0.clone(), name: name.clone(),
scope, scope,
pos: location.map(|l| l.pos), location: typedef.meta.into_debug(tokens).unwrap(),
size_bits, size_bits,
flags: DwarfFlags, flags: DwarfFlags,
fields, fields,
@ -1473,27 +1384,20 @@ impl TypeKind {
} }
impl Metadata { impl Metadata {
pub fn into_debug( pub fn into_debug(&self, tokens: &Vec<FullToken>) -> Option<DebugLocation> {
&self,
tokens: &Vec<FullToken>,
scope: DebugProgramValue,
) -> Option<DebugLocation> {
if let Some((start, _)) = self.into_positions(tokens) { if let Some((start, _)) = self.into_positions(tokens) {
Some(start.debug(scope)) Some(start.into())
} else { } else {
None None
} }
} }
} }
impl Position { impl Into<DebugLocation> for Position {
fn debug(self, scope: DebugProgramValue) -> DebugLocation { fn into(self) -> DebugLocation {
DebugLocation { DebugLocation {
pos: DebugPosition { line: self.1,
line: self.1, column: self.0,
column: self.0,
},
scope,
} }
} }
} }

View File

@ -63,24 +63,24 @@ impl PartialOrd for ErrorKind {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ErrorModule { pub struct Module {
pub name: String, pub name: String,
pub tokens: Option<Vec<FullToken>>, pub tokens: Option<Vec<FullToken>>,
pub source: Option<String>, pub source: Option<String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ErrorModules { pub struct ModuleMap {
module_map: HashMap<mir::SourceModuleId, ErrorModule>, module_map: HashMap<mir::SourceModuleId, Module>,
module_counter: mir::SourceModuleId, module_counter: mir::SourceModuleId,
} }
impl ErrorModules { impl ModuleMap {
pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> { pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> {
let id = self.module_counter.increment(); let id = self.module_counter.increment();
self.module_map.insert( self.module_map.insert(
id, id,
ErrorModule { Module {
name: name.into(), name: name.into(),
tokens: None, tokens: None,
source: None, source: None,
@ -101,21 +101,21 @@ impl ErrorModules {
} }
} }
pub fn module(&self, id: &mir::SourceModuleId) -> Option<&ErrorModule> { pub fn module(&self, id: &mir::SourceModuleId) -> Option<&Module> {
self.module_map.get(id) self.module_map.get(id)
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ReidError { pub struct ReidError {
map: ErrorModules, map: ModuleMap,
errors: Vec<ErrorKind>, errors: Vec<ErrorKind>,
} }
impl ReidError { impl ReidError {
pub fn from_lexer<U>( pub fn from_lexer<U>(
result: Result<U, lexer::Error>, result: Result<U, lexer::Error>,
map: ErrorModules, map: ModuleMap,
module: SourceModuleId, module: SourceModuleId,
) -> Result<U, ReidError> { ) -> Result<U, ReidError> {
result.map_err(|error| { result.map_err(|error| {
@ -136,7 +136,7 @@ impl ReidError {
pub fn from_parser<U>( pub fn from_parser<U>(
result: Result<U, token_stream::Error>, result: Result<U, token_stream::Error>,
map: ErrorModules, map: ModuleMap,
module: SourceModuleId, module: SourceModuleId,
) -> Result<U, ReidError> { ) -> Result<U, ReidError> {
result.map_err(|error| { result.map_err(|error| {
@ -155,7 +155,7 @@ impl ReidError {
}) })
} }
pub fn from_kind<U>(errors: Vec<ErrorKind>, map: ErrorModules) -> ReidError { pub fn from_kind<U>(errors: Vec<ErrorKind>, map: ModuleMap) -> ReidError {
ReidError { map, errors } ReidError { map, errors }
} }
} }

View File

@ -366,7 +366,6 @@ fn escape_char(c: &char) -> char {
't' => '\t', 't' => '\t',
'n' => '\n', 'n' => '\n',
'r' => '\r', 'r' => '\r',
'0' => '\0',
_ => *c, _ => *c,
} }
} }

View File

@ -43,7 +43,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use error_raporting::{ErrorKind as ErrorRapKind, ErrorModules, ReidError}; use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError};
use lexer::FullToken; use lexer::FullToken;
use mir::{ use mir::{
linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs, linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs,
@ -64,7 +64,7 @@ mod util;
pub fn parse_module<'map, T: Into<String>>( pub fn parse_module<'map, T: Into<String>>(
source: &str, source: &str,
name: T, name: T,
map: &'map mut ErrorModules, map: &'map mut ModuleMap,
) -> Result<(mir::SourceModuleId, Vec<FullToken>), ReidError> { ) -> Result<(mir::SourceModuleId, Vec<FullToken>), ReidError> {
let id = map.add_module(name.into()).unwrap(); let id = map.add_module(name.into()).unwrap();
map.set_source(id, source.to_owned()); map.set_source(id, source.to_owned());
@ -81,8 +81,8 @@ pub fn parse_module<'map, T: Into<String>>(
pub fn compile_module<'map>( pub fn compile_module<'map>(
module_id: mir::SourceModuleId, module_id: mir::SourceModuleId,
tokens: Vec<FullToken>, tokens: &Vec<FullToken>,
map: &'map mut ErrorModules, map: &'map mut ModuleMap,
path: Option<PathBuf>, path: Option<PathBuf>,
is_main: bool, is_main: bool,
) -> Result<mir::Module, ReidError> { ) -> Result<mir::Module, ReidError> {
@ -101,11 +101,8 @@ pub fn compile_module<'map>(
statements.push(statement); statements.push(statement);
} }
drop(token_stream);
let ast_module = ast::Module { let ast_module = ast::Module {
name: module.name, name: module.name,
tokens: tokens,
top_level_statements: statements, top_level_statements: statements,
path, path,
is_main, is_main,
@ -116,7 +113,7 @@ pub fn compile_module<'map>(
pub fn perform_all_passes<'map>( pub fn perform_all_passes<'map>(
context: &mut mir::Context, context: &mut mir::Context,
module_map: &'map mut ErrorModules, module_map: &'map mut ModuleMap,
) -> Result<(), ReidError> { ) -> Result<(), ReidError> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
dbg!(&context); dbg!(&context);
@ -150,7 +147,7 @@ pub fn perform_all_passes<'map>(
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{:-^100}", "TYPE INFERRER OUTPUT"); println!("{:-^100}", "TYPE INFERRER OUTPUT");
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &refs); dbg!(&refs);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &context); println!("{}", &context);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -196,13 +193,13 @@ pub fn perform_all_passes<'map>(
pub fn compile_and_pass<'map>( pub fn compile_and_pass<'map>(
source: &str, source: &str,
path: PathBuf, path: PathBuf,
module_map: &'map mut ErrorModules, module_map: &'map mut ModuleMap,
) -> Result<CompileOutput, ReidError> { ) -> Result<CompileOutput, ReidError> {
let path = path.canonicalize().unwrap(); let path = path.canonicalize().unwrap();
let name = path.file_name().unwrap().to_str().unwrap().to_owned(); let name = path.file_name().unwrap().to_str().unwrap().to_owned();
let (id, tokens) = parse_module(source, name, module_map)?; let (id, tokens) = parse_module(source, name, module_map)?;
let module = compile_module(id, tokens, module_map, Some(path.clone()), true)?; let module = compile_module(id, &tokens, module_map, Some(path.clone()), true)?;
let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned()); let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned());
@ -214,7 +211,7 @@ pub fn compile_and_pass<'map>(
println!("{}", &mir_context); println!("{}", &mir_context);
let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION")));
let codegen_modules = mir_context.codegen(&mut context); let codegen_modules = mir_context.codegen(&mut context, &module_map);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("{}", &codegen_modules.context); println!("{}", &codegen_modules.context);
@ -224,6 +221,6 @@ pub fn compile_and_pass<'map>(
} }
pub fn compile_simple(source: &str, path: PathBuf) -> Result<CompileOutput, ReidError> { pub fn compile_simple(source: &str, path: PathBuf) -> Result<CompileOutput, ReidError> {
let mut map = ErrorModules::default(); let mut map = ModuleMap::default();
compile_and_pass(source, path, &mut map) compile_and_pass(source, path, &mut map)
} }

View File

@ -2,31 +2,11 @@ use std::fmt::{Debug, Display, Write};
use crate::pad_adapter::PadAdapter; use crate::pad_adapter::PadAdapter;
use super::{ use super::*;
typerefs::{TypeRef, TypeRefs},
*,
};
impl Display for TypeRefs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (i, typeref) in self.type_refs.borrow().iter().enumerate() {
let idx = *typeref.borrow();
writeln!(
f,
"{:<3} = {:<3} = {:?} = {}",
i,
unsafe { *self.recurse_type_ref(idx).borrow() },
self.retrieve_type(idx),
TypeKind::Vague(VagueType::TypeRef(idx)).resolve_ref(self)
)?;
}
Ok(())
}
}
impl Display for Context { impl Display for Context {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (_, module) in &self.modules { for module in &self.modules {
Display::fmt(&module, f)?; Display::fmt(&module, f)?;
} }
Ok(()) Ok(())
@ -365,7 +345,7 @@ impl Display for TypeKind {
Display::fmt(len, f)?; Display::fmt(len, f)?;
f.write_char(']') f.write_char(']')
} }
TypeKind::CustomType(CustomTypeKey(name, mod_id)) => write!(f, "{}:{}", mod_id, name), TypeKind::CustomType(name) => write!(f, "{}", name),
TypeKind::Borrow(type_kind, false) => { TypeKind::Borrow(type_kind, false) => {
write!(f, "&")?; write!(f, "&")?;
Display::fmt(type_kind, f) Display::fmt(type_kind, f)

View File

@ -122,12 +122,12 @@ impl TypeKind {
TypeKind::U128 => false, TypeKind::U128 => false,
TypeKind::Void => false, TypeKind::Void => false,
TypeKind::Char => false, TypeKind::Char => false,
TypeKind::Array(..) => false, TypeKind::Array(_, _) => false,
TypeKind::CustomType(..) => false, TypeKind::CustomType(_) => false,
TypeKind::CodegenPtr(..) => false, TypeKind::CodegenPtr(_) => false,
TypeKind::Vague(..) => false, TypeKind::Vague(_) => false,
TypeKind::Borrow(..) => false, TypeKind::Borrow(_, _) => false,
TypeKind::UserPtr(..) => false, TypeKind::UserPtr(_) => false,
TypeKind::F16 => true, TypeKind::F16 => true,
TypeKind::F32B => true, TypeKind::F32B => true,
TypeKind::F32 => true, TypeKind::F32 => true,
@ -154,10 +154,10 @@ impl TypeKind {
TypeKind::Void => 0, TypeKind::Void => 0,
TypeKind::Char => 8, TypeKind::Char => 8,
TypeKind::Array(type_kind, len) => type_kind.size_of() * len, TypeKind::Array(type_kind, len) => type_kind.size_of() * len,
TypeKind::CustomType(..) => 32, TypeKind::CustomType(_) => 32,
TypeKind::CodegenPtr(_) => 64, TypeKind::CodegenPtr(_) => 64,
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
TypeKind::Borrow(..) => 64, TypeKind::Borrow(_, _) => 64,
TypeKind::UserPtr(_) => 64, TypeKind::UserPtr(_) => 64,
TypeKind::F16 => 16, TypeKind::F16 => 16,
TypeKind::F32B => 16, TypeKind::F32B => 16,
@ -185,7 +185,7 @@ impl TypeKind {
TypeKind::Void => 0, TypeKind::Void => 0,
TypeKind::Char => 8, TypeKind::Char => 8,
TypeKind::Array(type_kind, _) => type_kind.alignment(), TypeKind::Array(type_kind, _) => type_kind.alignment(),
TypeKind::CustomType(..) => 32, TypeKind::CustomType(_) => 32,
TypeKind::CodegenPtr(_) => 64, TypeKind::CodegenPtr(_) => 64,
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
TypeKind::Borrow(_, _) => 64, TypeKind::Borrow(_, _) => 64,
@ -230,7 +230,7 @@ impl TypeKind {
TypeKind::Void => TypeCategory::Other, TypeKind::Void => TypeCategory::Other,
TypeKind::Bool => TypeCategory::Other, TypeKind::Bool => TypeCategory::Other,
TypeKind::Array(_, _) => TypeCategory::Other, TypeKind::Array(_, _) => TypeCategory::Other,
TypeKind::CustomType(..) => TypeCategory::Other, TypeKind::CustomType(_) => TypeCategory::Other,
TypeKind::Borrow(_, _) => TypeCategory::Other, TypeKind::Borrow(_, _) => TypeCategory::Other,
TypeKind::UserPtr(_) => TypeCategory::Other, TypeKind::UserPtr(_) => TypeCategory::Other,
TypeKind::CodegenPtr(_) => TypeCategory::Other, TypeKind::CodegenPtr(_) => TypeCategory::Other,
@ -278,7 +278,7 @@ impl Block {
let mut early_return = None; let mut early_return = None;
for statement in &self.statements { for statement in &self.statements {
let ret = statement.return_type(&Default::default(), SourceModuleId(0)); let ret = statement.return_type(&Default::default());
if let Ok((ReturnKind::Hard, _)) = ret { if let Ok((ReturnKind::Hard, _)) = ret {
early_return = Some(statement); early_return = Some(statement);
} }
@ -302,15 +302,11 @@ impl Block {
.unwrap_or(self.meta) .unwrap_or(self.meta)
} }
pub fn return_type( pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
&self,
refs: &TypeRefs,
mod_id: SourceModuleId,
) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let mut early_return = None; let mut early_return = None;
for statement in &self.statements { for statement in &self.statements {
let ret = statement.return_type(refs, mod_id); let ret = statement.return_type(refs);
if let Ok((ReturnKind::Hard, _)) = ret { if let Ok((ReturnKind::Hard, _)) = ret {
early_return = early_return.or(ret.ok()); early_return = early_return.or(ret.ok());
} }
@ -323,7 +319,7 @@ impl Block {
self.return_expression self.return_expression
.as_ref() .as_ref()
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta)) .ok_or(ReturnTypeOther::NoBlockReturn(self.meta))
.and_then(|(kind, stmt)| Ok((*kind, stmt.return_type(refs, mod_id)?.1))) .and_then(|(kind, stmt)| Ok((*kind, stmt.return_type(refs)?.1)))
} }
pub fn backing_var(&self) -> Option<&NamedVariableRef> { pub fn backing_var(&self) -> Option<&NamedVariableRef> {
@ -341,23 +337,19 @@ impl Block {
} }
impl Statement { impl Statement {
pub fn return_type( pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
&self,
refs: &TypeRefs,
mod_id: SourceModuleId,
) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use StmtKind::*; use StmtKind::*;
match &self.0 { match &self.0 {
Let(var, _, expr) => if_hard( Let(var, _, expr) => if_hard(
expr.return_type(refs, mod_id)?, expr.return_type(refs)?,
Err(ReturnTypeOther::Let(var.2 + expr.1)), Err(ReturnTypeOther::Let(var.2 + expr.1)),
), ),
Set(lhs, rhs) => if_hard( Set(lhs, rhs) => if_hard(
rhs.return_type(refs, mod_id)?, rhs.return_type(refs)?,
Err(ReturnTypeOther::Set(lhs.1 + rhs.1)), Err(ReturnTypeOther::Set(lhs.1 + rhs.1)),
), ),
Import(_) => todo!(), Import(_) => todo!(),
Expression(expression) => expression.return_type(refs, mod_id), Expression(expression) => expression.return_type(refs),
} }
} }
@ -372,26 +364,22 @@ impl Statement {
} }
impl Expression { impl Expression {
pub fn return_type( pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
&self,
refs: &TypeRefs,
mod_id: SourceModuleId,
) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use ExprKind::*; use ExprKind::*;
match &self.0 { match &self.0 {
Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())), Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())),
Variable(var) => var.return_type(), Variable(var) => var.return_type(),
BinOp(_, then_e, else_e) => { BinOp(_, then_e, else_e) => {
let then_r = then_e.return_type(refs, mod_id)?; let then_r = then_e.return_type(refs)?;
let else_r = else_e.return_type(refs, mod_id)?; let else_r = else_e.return_type(refs)?;
Ok(pick_return(then_r, else_r)) Ok(pick_return(then_r, else_r))
} }
Block(block) => block.return_type(refs, mod_id), Block(block) => block.return_type(refs),
FunctionCall(fcall) => fcall.return_type(), FunctionCall(fcall) => fcall.return_type(),
If(expr) => expr.return_type(refs, mod_id), If(expr) => expr.return_type(refs),
Indexed(expression, _, _) => { Indexed(expression, _, _) => {
let expr_type = expression.return_type(refs, mod_id)?; let expr_type = expression.return_type(refs)?;
if let TypeKind::Array(elem_ty, _) = expr_type.1.resolve_weak(refs) { if let TypeKind::Array(elem_ty, _) = expr_type.1.resolve_weak(refs) {
Ok((ReturnKind::Soft, *elem_ty)) Ok((ReturnKind::Soft, *elem_ty))
} else { } else {
@ -402,7 +390,7 @@ impl Expression {
let first = expressions let first = expressions
.iter() .iter()
.next() .next()
.map(|e| e.return_type(refs, mod_id)) .map(|e| e.return_type(refs))
.unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?; .unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?;
Ok(( Ok((
ReturnKind::Soft, ReturnKind::Soft,
@ -410,10 +398,7 @@ impl Expression {
)) ))
} }
Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())), Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())),
Struct(name, _) => Ok(( Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))),
ReturnKind::Soft,
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
)),
Borrow(var, mutable) => { Borrow(var, mutable) => {
let ret_type = var.return_type()?; let ret_type = var.return_type()?;
Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable))) Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable)))
@ -425,7 +410,7 @@ impl Expression {
_ => Err(ReturnTypeOther::DerefNonBorrow(var.2)), _ => Err(ReturnTypeOther::DerefNonBorrow(var.2)),
} }
} }
CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) { CastTo(expr, type_kind) => match expr.return_type(refs) {
Ok(ret_type) => match ret_type { Ok(ret_type) => match ret_type {
(ReturnKind::Hard, ty) => Ok((ReturnKind::Hard, ty)), (ReturnKind::Hard, ty) => Ok((ReturnKind::Hard, ty)),
_ => Ok((ReturnKind::Soft, type_kind.clone())), _ => Ok((ReturnKind::Soft, type_kind.clone())),
@ -483,14 +468,10 @@ impl Expression {
} }
impl IfExpression { impl IfExpression {
pub fn return_type( pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
&self, let then_r = self.1.return_type(refs)?;
refs: &TypeRefs,
mod_id: SourceModuleId,
) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let then_r = self.1.return_type(refs, mod_id)?;
if let Some(else_b) = &self.2 { if let Some(else_b) = &self.2 {
let else_r = else_b.return_type(refs, mod_id)?; let else_r = else_b.return_type(refs)?;
let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard {
ReturnKind::Hard ReturnKind::Hard

View File

@ -9,8 +9,9 @@ use std::{
use crate::{ use crate::{
compile_module, compile_module,
error_raporting::{ErrorModules, ReidError}, error_raporting::{ModuleMap, ReidError},
mir::{SourceModuleId, TypeDefinition, CustomTypeKey, TypeKind}, lexer::FullToken,
mir::{TypeDefinition, TypeKind},
parse_module, parse_module,
}; };
@ -21,7 +22,6 @@ use super::{
}; };
pub static STD_SOURCE: &str = include_str!("../../lib/std.reid"); pub static STD_SOURCE: &str = include_str!("../../lib/std.reid");
pub static STD_NAME: &str = "std";
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ErrorKind { pub enum ErrorKind {
@ -47,21 +47,22 @@ pub enum ErrorKind {
FunctionIsPrivate(String, String), FunctionIsPrivate(String, String),
} }
pub fn compile_std(module_map: &mut ErrorModules) -> Result<Module, ReidError> { pub fn compile_std(
let (id, tokens) = parse_module(STD_SOURCE, STD_NAME, module_map)?; module_map: &mut ModuleMap,
let module = compile_module(id, tokens, module_map, None, false)?; ) -> Result<(super::Module, Vec<FullToken>), ReidError> {
let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map)?;
let module = compile_module(id, &tokens, module_map, None, false)?;
let module_id = module.module_id;
let mut mir_context = super::Context::from(vec![module], Default::default()); let mut mir_context = super::Context::from(vec![module], Default::default());
let std_compiled = mir_context.modules.remove(&module_id).unwrap(); let std_compiled = mir_context.modules.remove(0);
Ok(std_compiled) Ok((std_compiled, tokens))
} }
/// 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
/// MIR. /// MIR.
pub struct LinkerPass<'map> { pub struct LinkerPass<'map> {
pub module_map: &'map mut ErrorModules, pub module_map: &'map mut ModuleMap,
pub is_lib: bool, pub is_lib: bool,
} }
@ -74,13 +75,13 @@ impl<'map> Pass for LinkerPass<'map> {
let mains = context let mains = context
.modules .modules
.iter_mut() .iter_mut()
.filter(|(_, module)| module.is_main) .filter(|m| m.is_main)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if mains.len() > 1 { if mains.len() > 1 {
state.note_errors(&vec![ErrorKind::MultipleMainsAtStart], Metadata::default()); state.note_errors(&vec![ErrorKind::MultipleMainsAtStart], Metadata::default());
return Ok(()); return Ok(());
} }
if let Some((_, main)) = mains.first() { if let Some(main) = mains.first() {
if let None = main.functions.iter().find(|f| f.name == "main") { if let None = main.functions.iter().find(|f| f.name == "main") {
if !self.is_lib { if !self.is_lib {
state.note_errors(&vec![ErrorKind::NoMainFunction], Metadata::default()); state.note_errors(&vec![ErrorKind::NoMainFunction], Metadata::default());
@ -94,19 +95,26 @@ impl<'map> Pass for LinkerPass<'map> {
} }
}; };
let mut modules = HashMap::<SourceModuleId, Rc<RefCell<_>>>::new(); let mut modules = HashMap::<String, Rc<RefCell<_>>>::new();
let mut module_ids = HashMap::<String, SourceModuleId>::new();
for (mod_id, module) in context.modules.drain() { for module in context.modules.drain(..) {
modules.insert(mod_id, Rc::new(RefCell::new(module))); let tokens = self
.module_map
.module(&module.module_id)
.unwrap()
.tokens
.clone()
.unwrap();
modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens))));
} }
let mut modules_to_process: Vec<Rc<RefCell<_>>> = modules.values().cloned().collect(); let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> =
modules.values().cloned().collect();
while let Some(module) = modules_to_process.pop() { while let Some(module) = modules_to_process.pop() {
let mut importer_module = module.borrow_mut(); let mut importer_module = module.borrow_mut();
for import in importer_module.imports.clone() { for import in importer_module.0.imports.clone() {
let Import(path, _) = &import; let Import(path, _) = &import;
if path.len() != 2 { if path.len() != 2 {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(
@ -117,16 +125,14 @@ impl<'map> Pass for LinkerPass<'map> {
let module_name = unsafe { path.get_unchecked(0) }; let module_name = unsafe { path.get_unchecked(0) };
let mut imported = if let Some(mod_id) = module_ids.get(module_name) { let mut imported = if let Some(module) = modules.get_mut(module_name) {
modules.get(mod_id).unwrap() module
} else if module_name == STD_NAME { } else if module_name == "std" {
let std = compile_std(&mut self.module_map)?;
modules.insert( modules.insert(
std.module_id, "std".to_owned(),
Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), Rc::new(RefCell::new(compile_std(&mut self.module_map)?)),
); );
module_ids.insert(std.name, std.module_id); modules.get("std").unwrap()
modules.get(&std.module_id).unwrap()
} else { } else {
let file_path = let file_path =
PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid");
@ -154,7 +160,8 @@ impl<'map> Pass for LinkerPass<'map> {
} }
}; };
match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) { match compile_module(id, &tokens, &mut self.module_map, Some(file_path), false)
{
Ok(imported_module) => { Ok(imported_module) => {
if imported_module.is_main { if imported_module.is_main {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(
@ -163,11 +170,12 @@ impl<'map> Pass for LinkerPass<'map> {
); );
continue; continue;
} }
let module_id = imported_module.module_id; let module_name = imported_module.name.clone();
module_ids modules.insert(
.insert(imported_module.name.clone(), imported_module.module_id); module_name.clone(),
modules.insert(module_id, Rc::new(RefCell::new(imported_module))); Rc::new(RefCell::new((imported_module, tokens))),
let imported = modules.get_mut(&module_id).unwrap(); );
let imported = modules.get_mut(&module_name).unwrap();
modules_to_process.push(imported.clone()); modules_to_process.push(imported.clone());
imported imported
} }
@ -186,9 +194,14 @@ impl<'map> Pass for LinkerPass<'map> {
.borrow_mut(); .borrow_mut();
let func_name = unsafe { path.get_unchecked(1) }; let func_name = unsafe { path.get_unchecked(1) };
let imported_mod_name = imported.name.clone(); let imported_mod_name = imported.0.name.clone();
let imported_mod_typedefs = imported.0.typedefs.clone();
let Some(func) = imported.functions.iter_mut().find(|f| f.name == *func_name) let Some(func) = imported
.0
.functions
.iter_mut()
.find(|f| f.name == *func_name)
else { else {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(
Err(ErrorKind::NoSuchFunctionInModule( Err(ErrorKind::NoSuchFunctionInModule(
@ -200,8 +213,6 @@ impl<'map> Pass for LinkerPass<'map> {
continue; continue;
}; };
let func_name = func.name.clone();
if !func.is_pub { if !func.is_pub {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(
Err(ErrorKind::FunctionIsPrivate( Err(ErrorKind::FunctionIsPrivate(
@ -216,6 +227,7 @@ impl<'map> Pass for LinkerPass<'map> {
func.is_imported = true; func.is_imported = true;
if let Some(existing) = importer_module if let Some(existing) = importer_module
.0
.functions .functions
.iter() .iter()
.find(|f| f.name == *func_name) .find(|f| f.name == *func_name)
@ -232,12 +244,14 @@ impl<'map> Pass for LinkerPass<'map> {
} }
} }
fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<CustomTypeKey>) { fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<String>) {
let mut imported_types = Vec::new(); let mut imported_types = Vec::new();
let ty = match &ty { let ty = match &ty {
TypeKind::CustomType(key) => { TypeKind::CustomType(name) => {
imported_types.push(key.clone()); imported_types.push(name.clone());
TypeKind::CustomType(key.clone())
let name = format!("{}::{}", base, name);
TypeKind::CustomType(name)
} }
_ => ty.clone(), _ => ty.clone(),
}; };
@ -258,28 +272,27 @@ impl<'map> Pass for LinkerPass<'map> {
fn find_inner_types( fn find_inner_types(
typedef: &TypeDefinition, typedef: &TypeDefinition,
mut seen: HashSet<CustomTypeKey>, mut seen: HashSet<String>,
mod_id: SourceModuleId, ) -> Vec<String> {
) -> Vec<CustomTypeKey> {
match &typedef.kind { match &typedef.kind {
crate::mir::TypeDefinitionKind::Struct(struct_type) => { crate::mir::TypeDefinitionKind::Struct(struct_type) => {
let typenames = struct_type let typenames = struct_type
.0 .0
.iter() .iter()
.filter(|t| matches!(t.1, TypeKind::CustomType(..))) .filter(|t| matches!(t.1, TypeKind::CustomType(_)))
.map(|t| match &t.1 { .map(|t| match &t.1 {
TypeKind::CustomType(CustomTypeKey(t, _)) => t, TypeKind::CustomType(t) => t,
_ => panic!(), _ => panic!(),
}) })
.cloned() .cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for typename in typenames { for typename in typenames {
if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) { if seen.contains(&typename) {
continue; continue;
} }
let inner = find_inner_types(typedef, seen.clone(), mod_id); let inner = find_inner_types(typedef, seen.clone());
seen.insert(CustomTypeKey(typename, mod_id)); seen.insert(typename);
seen.extend(inner); seen.extend(inner);
} }
@ -291,30 +304,28 @@ impl<'map> Pass for LinkerPass<'map> {
let mut seen = HashSet::new(); let mut seen = HashSet::new();
seen.extend(imported_types.clone()); seen.extend(imported_types.clone());
let imported_mod_id = imported.module_id; for typename in imported_types.clone() {
let imported_mod_typedefs = &mut imported.typedefs;
for typekey in imported_types.clone() {
let typedef = imported_mod_typedefs let typedef = imported_mod_typedefs
.iter() .iter()
.find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) .find(|ty| ty.name == typename)
.unwrap(); .unwrap();
let inner = find_inner_types(typedef, seen.clone(), imported_mod_id); let inner = find_inner_types(typedef, seen.clone());
seen.extend(inner); seen.extend(inner);
} }
for typekey in seen.into_iter() { for typename in seen.into_iter() {
let typedef = imported_mod_typedefs let mut typedef = imported_mod_typedefs
.iter() .iter()
.find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) .find(|ty| ty.name == typename)
.unwrap() .unwrap()
.clone(); .clone();
importer_module.typedefs.push(typedef.clone()); typedef.name = format!("{}::{}", imported_mod_name, typedef.name);
importer_module.0.typedefs.push(typedef);
} }
importer_module.functions.push(FunctionDefinition { importer_module.0.functions.push(FunctionDefinition {
name: func_name, name: func.name.clone(),
is_pub: false, is_pub: false,
is_imported: false, is_imported: false,
return_type: return_type, return_type: return_type,
@ -324,15 +335,11 @@ impl<'map> Pass for LinkerPass<'map> {
} }
} }
let mut modules: Vec<Module> = modules context.modules = modules
.into_values() .into_values()
.map(|v| Rc::into_inner(v).unwrap().into_inner()) .map(|v| Rc::into_inner(v).unwrap().into_inner().0)
.collect(); .collect();
for module in modules.drain(..) {
context.modules.insert(module.module_id, module);
}
Ok(()) Ok(())
} }
} }

View File

@ -18,7 +18,7 @@ pub mod typeinference;
pub mod typerefs; pub mod typerefs;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
pub struct SourceModuleId(pub u32); pub struct SourceModuleId(u32);
impl SourceModuleId { impl SourceModuleId {
pub fn increment(&mut self) -> SourceModuleId { pub fn increment(&mut self) -> SourceModuleId {
@ -77,9 +77,6 @@ impl TokenRange {
} }
} }
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CustomTypeKey(pub String, pub SourceModuleId);
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TypeKind { pub enum TypeKind {
Bool, Bool,
@ -103,7 +100,7 @@ pub enum TypeKind {
F128PPC, F128PPC,
Char, Char,
Array(Box<TypeKind>, u64), Array(Box<TypeKind>, u64),
CustomType(CustomTypeKey), CustomType(String),
Borrow(Box<TypeKind>, bool), Borrow(Box<TypeKind>, bool),
UserPtr(Box<TypeKind>), UserPtr(Box<TypeKind>),
CodegenPtr(Box<TypeKind>), CodegenPtr(Box<TypeKind>),
@ -338,7 +335,6 @@ pub struct TypeDefinition {
pub name: String, pub name: String,
pub kind: TypeDefinitionKind, pub kind: TypeDefinitionKind,
pub meta: Metadata, pub meta: Metadata,
pub source_module: SourceModuleId,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -354,14 +350,11 @@ pub struct Module {
pub functions: Vec<FunctionDefinition>, pub functions: Vec<FunctionDefinition>,
pub typedefs: Vec<TypeDefinition>, pub typedefs: Vec<TypeDefinition>,
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
pub tokens: Vec<FullToken>,
pub is_main: bool, pub is_main: bool,
} }
pub type ModuleMap = HashMap<SourceModuleId, Module>;
#[derive(Debug)] #[derive(Debug)]
pub struct Context { pub struct Context {
pub modules: ModuleMap, pub modules: Vec<Module>,
pub base: PathBuf, pub base: PathBuf,
} }

View File

@ -90,16 +90,16 @@ impl<TErr: STDError> State<TErr> {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Storage<Key: std::hash::Hash, T: std::fmt::Debug>(HashMap<Key, T>); pub struct Storage<T: std::fmt::Debug>(HashMap<String, T>);
impl<Key: std::hash::Hash, T: std::fmt::Debug> Default for Storage<Key, T> { impl<T: std::fmt::Debug> Default for Storage<T> {
fn default() -> Self { fn default() -> Self {
Self(Default::default()) Self(Default::default())
} }
} }
impl<Key: std::hash::Hash + Eq, T: Clone + std::fmt::Debug> Storage<Key, T> { impl<T: Clone + std::fmt::Debug> Storage<T> {
pub fn set(&mut self, key: Key, value: T) -> Result<T, ()> { pub fn set(&mut self, key: String, value: T) -> Result<T, ()> {
if let Some(_) = self.0.get(&key) { if let Some(_) = self.0.get(&key) {
Err(()) Err(())
} else { } else {
@ -108,16 +108,16 @@ impl<Key: std::hash::Hash + Eq, T: Clone + std::fmt::Debug> Storage<Key, T> {
} }
} }
pub fn get(&self, key: &Key) -> Option<&T> { pub fn get(&self, key: &String) -> Option<&T> {
self.0.get(key) self.0.get(key)
} }
} }
#[derive(Clone, Default, Debug)] #[derive(Clone, Default, Debug)]
pub struct Scope<Data: Clone + Default> { pub struct Scope<Data: Clone + Default> {
pub function_returns: Storage<String, ScopeFunction>, pub function_returns: Storage<ScopeFunction>,
pub variables: Storage<String, ScopeVariable>, pub variables: Storage<ScopeVariable>,
pub types: Storage<CustomTypeKey, TypeDefinition>, pub types: Storage<TypeDefinitionKind>,
/// Hard Return type of this scope, if inside a function /// Hard Return type of this scope, if inside a function
pub return_type_hint: Option<TypeKind>, pub return_type_hint: Option<TypeKind>,
pub data: Data, pub data: Data,
@ -134,20 +134,12 @@ impl<Data: Clone + Default> Scope<Data> {
} }
} }
pub fn get_struct_type(&self, key: &CustomTypeKey) -> Option<&StructType> { pub fn get_struct_type(&self, name: &String) -> Option<&StructType> {
let ty = self.types.get(&key)?; let ty = self.types.get(&name)?;
match &ty.kind { match ty {
TypeDefinitionKind::Struct(struct_ty) => Some(struct_ty), TypeDefinitionKind::Struct(struct_ty) => Some(struct_ty),
} }
} }
pub fn find_type(&self, name: &String) -> Option<&CustomTypeKey> {
self.types
.0
.iter()
.find(|(CustomTypeKey(n, _), _)| n == name)
.map(|(key, _)| key)
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -166,20 +158,14 @@ pub struct PassState<'st, 'sc, Data: Clone + Default, TError: STDError + Clone>
state: &'st mut State<TError>, state: &'st mut State<TError>,
pub scope: &'sc mut Scope<Data>, pub scope: &'sc mut Scope<Data>,
inner: Vec<Scope<Data>>, inner: Vec<Scope<Data>>,
pub module_id: Option<SourceModuleId>,
} }
impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> { impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> {
fn from( fn from(state: &'st mut State<TError>, scope: &'sc mut Scope<Data>) -> Self {
state: &'st mut State<TError>,
scope: &'sc mut Scope<Data>,
module_id: Option<SourceModuleId>,
) -> Self {
PassState { PassState {
state, state,
scope, scope,
inner: Vec::new(), inner: Vec::new(),
module_id: module_id,
} }
} }
@ -217,7 +203,6 @@ impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, '
state: self.state, state: self.state,
scope, scope,
inner: Vec::new(), inner: Vec::new(),
module_id: self.module_id,
} }
} }
} }
@ -276,8 +261,8 @@ impl Context {
pub fn pass<T: Pass>(&mut self, pass: &mut T) -> Result<State<T::TError>, ReidError> { pub fn pass<T: Pass>(&mut self, pass: &mut T) -> Result<State<T::TError>, ReidError> {
let mut state = State::new(); let mut state = State::new();
let mut scope = Scope::default(); let mut scope = Scope::default();
pass.context(self, PassState::from(&mut state, &mut scope, None))?; pass.context(self, PassState::from(&mut state, &mut scope))?;
for (_, module) in &mut self.modules { for module in &mut self.modules {
module.pass(pass, &mut state, &mut scope.inner())?; module.pass(pass, &mut state, &mut scope.inner())?;
} }
Ok(state) Ok(state)
@ -292,13 +277,10 @@ impl Module {
scope: &mut Scope<T::Data>, scope: &mut Scope<T::Data>,
) -> PassResult { ) -> PassResult {
for typedef in &self.typedefs { for typedef in &self.typedefs {
scope let kind = match &typedef.kind {
.types TypeDefinitionKind::Struct(fields) => TypeDefinitionKind::Struct(fields.clone()),
.set( };
CustomTypeKey(typedef.name.clone(), self.module_id), scope.types.set(typedef.name.clone(), kind).ok();
typedef.clone(),
)
.ok();
} }
for function in &self.functions { for function in &self.functions {
@ -314,10 +296,10 @@ impl Module {
.ok(); .ok();
} }
pass.module(self, PassState::from(state, scope, Some(self.module_id)))?; pass.module(self, PassState::from(state, scope))?;
for function in &mut self.functions { for function in &mut self.functions {
function.pass(pass, state, &mut scope.inner(), self.module_id)?; function.pass(pass, state, &mut scope.inner())?;
} }
Ok(()) Ok(())
} }
@ -329,7 +311,6 @@ impl FunctionDefinition {
pass: &mut T, pass: &mut T,
state: &mut State<T::TError>, state: &mut State<T::TError>,
scope: &mut Scope<T::Data>, scope: &mut Scope<T::Data>,
mod_id: SourceModuleId,
) -> PassResult { ) -> PassResult {
for param in &self.parameters { for param in &self.parameters {
scope scope
@ -344,12 +325,12 @@ impl FunctionDefinition {
.ok(); .ok();
} }
pass.function(self, PassState::from(state, scope, Some(mod_id)))?; pass.function(self, PassState::from(state, scope))?;
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.clone());
block.pass(pass, state, scope, mod_id)?; block.pass(pass, state, scope)?;
} }
FunctionDefinitionKind::Extern(_) => {} FunctionDefinitionKind::Extern(_) => {}
}; };
@ -363,15 +344,14 @@ impl Block {
pass: &mut T, pass: &mut T,
state: &mut State<T::TError>, state: &mut State<T::TError>,
scope: &mut Scope<T::Data>, scope: &mut Scope<T::Data>,
mod_id: SourceModuleId,
) -> PassResult { ) -> PassResult {
let mut scope = scope.inner(); let mut scope = scope.inner();
for statement in &mut self.statements { for statement in &mut self.statements {
statement.pass(pass, state, &mut scope, mod_id)?; statement.pass(pass, state, &mut scope)?;
} }
pass.block(self, PassState::from(state, &mut scope, Some(mod_id))) pass.block(self, PassState::from(state, &mut scope))
} }
} }
@ -381,22 +361,21 @@ impl Statement {
pass: &mut T, pass: &mut T,
state: &mut State<T::TError>, state: &mut State<T::TError>,
scope: &mut Scope<T::Data>, scope: &mut Scope<T::Data>,
mod_id: SourceModuleId,
) -> PassResult { ) -> PassResult {
match &mut self.0 { match &mut self.0 {
StmtKind::Let(_, _, expression) => { StmtKind::Let(_, _, expression) => {
expression.pass(pass, state, scope, mod_id)?; expression.pass(pass, state, scope)?;
} }
StmtKind::Set(_, expression) => { StmtKind::Set(_, expression) => {
expression.pass(pass, state, scope, mod_id)?; expression.pass(pass, state, scope)?;
} }
StmtKind::Import(_) => {} // Never exists at this stage StmtKind::Import(_) => {} // Never exists at this stage
StmtKind::Expression(expression) => { StmtKind::Expression(expression) => {
expression.pass(pass, state, scope, mod_id)?; expression.pass(pass, state, scope)?;
} }
} }
pass.stmt(self, PassState::from(state, scope, Some(mod_id)))?; pass.stmt(self, PassState::from(state, scope))?;
match &mut self.0 { match &mut self.0 {
StmtKind::Let(variable_reference, mutable, _) => { StmtKind::Let(variable_reference, mutable, _) => {
@ -425,9 +404,8 @@ impl Expression {
pass: &mut T, pass: &mut T,
state: &mut State<T::TError>, state: &mut State<T::TError>,
scope: &mut Scope<T::Data>, scope: &mut Scope<T::Data>,
mod_id: SourceModuleId,
) -> PassResult { ) -> PassResult {
pass.expr(self, PassState::from(state, scope, Some(mod_id)))?; pass.expr(self, PassState::from(state, scope))?;
Ok(()) Ok(())
} }
} }

View File

@ -42,8 +42,8 @@ pub enum ErrorKind {
TriedIndexingNonIndexable(TypeKind), TriedIndexingNonIndexable(TypeKind),
#[error("Index {0} out of bounds ({1})")] #[error("Index {0} out of bounds ({1})")]
IndexOutOfBounds(u64, u64), IndexOutOfBounds(u64, u64),
#[error("No such type {0} could be found in module {1}")] #[error("No such type {0} could be found")]
NoSuchType(String, SourceModuleId), NoSuchType(String),
#[error("Attempted to access field of non-struct type of {0}")] #[error("Attempted to access field of non-struct type of {0}")]
TriedAccessingNonStruct(TypeKind), TriedAccessingNonStruct(TypeKind),
#[error("No such struct-field on type {0}")] #[error("No such struct-field on type {0}")]
@ -85,13 +85,7 @@ impl<'t> Pass for TypeCheck<'t> {
fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult {
let mut defmap = HashMap::new(); let mut defmap = HashMap::new();
for typedef in &module.typedefs { for typedef in &module.typedefs {
let TypeDefinition { let TypeDefinition { name, kind, meta } = &typedef;
name,
kind,
meta,
source_module,
} = &typedef;
match kind { match kind {
TypeDefinitionKind::Struct(StructType(fields)) => { TypeDefinitionKind::Struct(StructType(fields)) => {
let mut fieldmap = HashMap::new(); let mut fieldmap = HashMap::new();
@ -138,7 +132,7 @@ fn check_typedefs_for_recursion<'a, 'b>(
match &typedef.kind { match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => { TypeDefinitionKind::Struct(StructType(fields)) => {
for field_ty in fields.iter().map(|StructField(_, ty, _)| ty) { for field_ty in fields.iter().map(|StructField(_, ty, _)| ty) {
if let TypeKind::CustomType(CustomTypeKey(name, _)) = field_ty { if let TypeKind::CustomType(name) = field_ty {
if seen.contains(name) { if seen.contains(name) {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(
Err(ErrorKind::RecursiveTypeDefinition( Err(ErrorKind::RecursiveTypeDefinition(
@ -325,9 +319,7 @@ impl Block {
StmtKind::Expression(expression) => { StmtKind::Expression(expression) => {
let res = expression.typecheck(&mut state, &typerefs, None); let res = expression.typecheck(&mut state, &typerefs, None);
state.or_else(res, TypeKind::Void, expression.1); state.or_else(res, TypeKind::Void, expression.1);
if let Ok((kind, _)) = if let Ok((kind, _)) = expression.return_type(typerefs) {
expression.return_type(typerefs, state.module_id.unwrap())
{
Some((kind, expression)) Some((kind, expression))
} else { } else {
None None
@ -613,11 +605,11 @@ impl Expression {
let expr_ty = let expr_ty =
state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1);
if let TypeKind::CustomType(key) = expr_ty { if let TypeKind::CustomType(struct_name) = expr_ty {
let struct_type = state let struct_type = state
.scope .scope
.get_struct_type(&key) .get_struct_type(&struct_name)
.ok_or(ErrorKind::NoSuchType(key.0.clone(), key.1))?; .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?;
if let Some(expr_field_ty) = struct_type.get_field_ty(&field_name) { if let Some(expr_field_ty) = struct_type.get_field_ty(&field_name) {
// Make sure they are the same // Make sure they are the same
let true_ty = state.or_else( let true_ty = state.or_else(
@ -636,11 +628,10 @@ impl Expression {
} }
} }
ExprKind::Struct(struct_name, items) => { ExprKind::Struct(struct_name, items) => {
let type_key = CustomTypeKey(struct_name.clone(), state.module_id.unwrap());
let struct_def = state let struct_def = state
.scope .scope
.get_struct_type(&type_key) .get_struct_type(struct_name)
.ok_or(ErrorKind::NoSuchType(struct_name.clone(), type_key.1))? .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?
.clone(); .clone();
for (field_name, field_expr) in items { for (field_name, field_expr) in items {
// Get expected type, or error if field does not exist // Get expected type, or error if field does not exist
@ -663,7 +654,7 @@ impl Expression {
// Make sure both are the same type, report error if not // Make sure both are the same type, report error if not
state.ok(expr_ty.collapse_into(&expr_ty), field_expr.1); state.ok(expr_ty.collapse_into(&expr_ty), field_expr.1);
} }
Ok(TypeKind::CustomType(type_key)) Ok(TypeKind::CustomType(struct_name.clone()))
} }
ExprKind::Borrow(var_ref, mutable) => { ExprKind::Borrow(var_ref, mutable) => {
let scope_var = state.scope.variables.get(&var_ref.1).cloned(); let scope_var = state.scope.variables.get(&var_ref.1).cloned();

View File

@ -13,8 +13,8 @@ use super::{
pass::{Pass, PassResult, PassState}, pass::{Pass, PassResult, PassState},
typecheck::ErrorKind, typecheck::ErrorKind,
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression, Module,
IfExpression, Module, ReturnKind, StmtKind, ReturnKind, StmtKind,
TypeKind::*, TypeKind::*,
VagueType::*, VagueType::*,
}; };
@ -138,7 +138,7 @@ impl Block {
// Fetch the declared return type // Fetch the declared return type
let (kind, ty) = self let (kind, ty) = self
.return_type(inner_refs.types, state.module_id.unwrap()) .return_type(inner_refs.types)
.ok() .ok()
.unwrap_or((ReturnKind::Soft, Void)); .unwrap_or((ReturnKind::Soft, Void));
let mut ret_type_ref = outer_refs.from_type(&ty).unwrap(); let mut ret_type_ref = outer_refs.from_type(&ty).unwrap();
@ -183,8 +183,8 @@ impl Expression {
type_refs type_refs
.binop(op, &mut lhs_ref, &mut rhs_ref) .binop(op, &mut lhs_ref, &mut rhs_ref)
.ok_or(ErrorKind::TypesIncompatible( .ok_or(ErrorKind::TypesIncompatible(
lhs_ref.resolve_deep().unwrap(), lhs_ref.as_type(),
rhs_ref.resolve_deep().unwrap(), rhs_ref.as_type(),
)) ))
} }
ExprKind::FunctionCall(function_call) => { ExprKind::FunctionCall(function_call) => {
@ -320,11 +320,11 @@ impl Expression {
// need for further resolution. // need for further resolution.
let kind = expr_ty.resolve_weak().unwrap(); let kind = expr_ty.resolve_weak().unwrap();
match kind { match kind {
CustomType(key) => { CustomType(name) => {
let struct_ty = state let struct_ty = state
.scope .scope
.get_struct_type(&key) .get_struct_type(&name)
.ok_or(ErrorKind::NoSuchType(key.0.clone(), key.1))?; .ok_or(ErrorKind::NoSuchType(name.clone()))?;
match struct_ty.get_field_ty(&field_name) { match struct_ty.get_field_ty(&field_name) {
Some(field_ty) => { Some(field_ty) => {
let mut elem_ty = type_refs.from_type(&type_kind).unwrap(); let mut elem_ty = type_refs.from_type(&type_kind).unwrap();
@ -339,14 +339,10 @@ impl Expression {
} }
} }
ExprKind::Struct(struct_name, fields) => { ExprKind::Struct(struct_name, fields) => {
let type_key = CustomTypeKey(struct_name.clone(), state.module_id.unwrap());
let expected_struct_ty = state let expected_struct_ty = state
.scope .scope
.get_struct_type(&type_key) .get_struct_type(&struct_name)
.ok_or(ErrorKind::NoSuchType( .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?
struct_name.clone(),
state.module_id.unwrap(),
))?
.clone(); .clone();
for field in fields { for field in fields {
if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) {
@ -365,7 +361,7 @@ impl Expression {
} }
} }
Ok(type_refs Ok(type_refs
.from_type(&TypeKind::CustomType(type_key.clone())) .from_type(&TypeKind::CustomType(struct_name.clone()))
.unwrap()) .unwrap())
} }
ExprKind::Borrow(var, mutable) => { ExprKind::Borrow(var, mutable) => {

View File

@ -9,10 +9,7 @@ use crate::mir::VagueType;
use super::{typecheck::ErrorKind, BinaryOperator, TypeKind}; use super::{typecheck::ErrorKind, BinaryOperator, TypeKind};
#[derive(Clone)] #[derive(Clone)]
pub struct TypeRef<'scope>( pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
pub(super) TypeIdRef,
pub(super) &'scope ScopeTypeRefs<'scope>,
);
impl<'scope> TypeRef<'scope> { impl<'scope> TypeRef<'scope> {
/// Resolve current type in a weak manner, not resolving any Arrays or /// Resolve current type in a weak manner, not resolving any Arrays or
@ -57,9 +54,9 @@ type TypeIdRef = Rc<RefCell<usize>>;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct TypeRefs { pub struct TypeRefs {
/// Simple list of types that variables can refrence /// Simple list of types that variables can refrence
pub(super) hints: RefCell<Vec<TypeKind>>, hints: RefCell<Vec<TypeKind>>,
/// Indirect ID-references, referring to hints-vec /// Indirect ID-references, referring to hints-vec
pub(super) type_refs: RefCell<Vec<TypeIdRef>>, type_refs: RefCell<Vec<TypeIdRef>>,
} }
impl TypeRefs { impl TypeRefs {
@ -92,7 +89,7 @@ impl TypeRefs {
} }
} }
pub(super) unsafe fn recurse_type_ref(&self, mut idx: usize) -> TypeIdRef { unsafe fn recurse_type_ref(&self, mut idx: usize) -> TypeIdRef {
let refs = self.type_refs.borrow(); let refs = self.type_refs.borrow();
let mut inner_idx = refs.get_unchecked(idx); let mut inner_idx = refs.get_unchecked(idx);
let mut seen = HashSet::new(); let mut seen = HashSet::new();

View File

@ -10,10 +10,13 @@ mod util;
fn test(source: &str, name: &str) { fn test(source: &str, name: &str) {
let mut map = Default::default(); let mut map = Default::default();
let (id, tokens) = assert_err(parse_module(source, name, &mut map)); let (id, tokens) = assert_err(parse_module(source, name, &mut map));
let module = assert_err(compile_module(id, tokens, &mut map, None, true)); let module = assert_err(compile_module(id, &tokens, &mut map, None, true));
assert_err(perform_all_passes( assert_err(perform_all_passes(
&mut mir::Context::from(vec![module], Default::default()), &mut mir::Context {
modules: vec![module],
base: Default::default(),
},
&mut map, &mut map,
)); ));
} }

View File

@ -14,7 +14,7 @@ fn compiles() {
#[test] #[test]
fn passes_all_passes() { fn passes_all_passes() {
let mut map = Default::default(); let mut map = Default::default();
let Ok(mut std) = compile_std(&mut map) else { let Ok((mut std, _)) = compile_std(&mut map) else {
panic!() panic!()
}; };
@ -22,7 +22,10 @@ fn passes_all_passes() {
std.is_main = true; std.is_main = true;
assert_err(perform_all_passes( assert_err(perform_all_passes(
&mut mir::Context::from(vec![std], Default::default()), &mut mir::Context {
modules: vec![std],
base: Default::default(),
},
&mut map, &mut map,
)); ));
} }

View File

@ -1,19 +1,8 @@
import std::print; import std::print;
import std::new_string;
import std::add_char;
import std::free_string;
fn main() -> i32 { fn main() -> i32 {
let mut test = new_string(); let test = "hello world";
add_char(&mut test, 'h'); print(test);
add_char(&mut test, 'e');
add_char(&mut test, 'l');
add_char(&mut test, 'l');
add_char(&mut test, 'o');
print(&test);
free_string(&mut test);
return 0; return 0;
} }