Add module id to CustomType, String to std

This commit is contained in:
Sofia 2025-07-22 16:15:10 +03:00
parent 1224c612c7
commit e9bca63f0d
12 changed files with 253 additions and 152 deletions

View File

@ -1,6 +1,7 @@
extern fn puts(message: *char) -> i32;
extern fn malloc(size: u64) -> *u8;
extern fn free(ptr: *u8);
extern fn div(numerator: i32, denominator: i32) -> div_t;
struct div_t {
@ -8,8 +9,8 @@ struct div_t {
remainder: i32,
}
pub fn print(message: *char) {
puts(message);
pub fn print(message: &String) {
puts(*message.inner);
}
pub fn int_div(numerator: i32, denominator: i32) -> div_t {
@ -20,6 +21,30 @@ pub fn allocate(size: u64) -> *u8 {
malloc(size)
}
fn main() -> u16 {
return 0;
struct String {
inner: *char,
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 {
free((*string).inner as *u8);
(*string).max_length = (*string).max_length + 4;
(*string).inner = allocate((*string).max_length) as *char;
}
(*string).inner[(*string).length] = c;
(*string).inner[((*string).length + 1)] = '\0';
(*string).length = (*string).length + 1;
}
pub fn free_string(string: &mut String) {
free((*string).inner as *u8);
}

View File

@ -2,7 +2,7 @@ use std::{path::PathBuf, process};
use crate::{
ast::{self},
mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType},
mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType, TypeKey},
};
impl mir::Context {
@ -31,13 +31,13 @@ impl ast::Module {
return_type: signature
.return_type
.clone()
.map(|r| r.0.into())
.map(|r| r.0.into_mir(module_id))
.unwrap_or(mir::TypeKind::Void),
parameters: signature
.args
.iter()
.cloned()
.map(|p| (p.0, p.1.into()))
.map(|p| (p.0, p.1 .0.into_mir(module_id)))
.collect(),
kind: mir::FunctionDefinitionKind::Local(
block.into_mir(module_id),
@ -54,13 +54,13 @@ impl ast::Module {
return_type: signature
.return_type
.clone()
.map(|r| r.0.into())
.map(|r| r.0.into_mir(module_id))
.unwrap_or(mir::TypeKind::Void),
parameters: signature
.args
.iter()
.cloned()
.map(|p| (p.0, p.1.into()))
.map(|p| (p.0, p.1 .0.into_mir(module_id)))
.collect(),
kind: mir::FunctionDefinitionKind::Extern(false),
};
@ -77,7 +77,7 @@ impl ast::Module {
.map(|s| {
StructField(
s.name.clone(),
s.ty.clone().into(),
s.ty.clone().0.into_mir(module_id),
s.range.as_meta(module_id),
)
})
@ -86,6 +86,7 @@ impl ast::Module {
}
},
meta: (*range).as_meta(module_id),
source_module: module_id,
};
typedefs.push(def);
}
@ -116,7 +117,7 @@ impl ast::Block {
s_let
.ty
.clone()
.map(|t| t.0.into())
.map(|t| t.0.into_mir(module_id))
.unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)),
s_let.name.clone(),
s_let.name_range.as_meta(module_id),
@ -256,9 +257,10 @@ impl ast::Expression {
Box::new(expr.process(module_id)),
),
},
ast::ExpressionKind::CastTo(expression, ty) => {
mir::ExprKind::CastTo(Box::new(expression.process(module_id)), ty.0.clone().into())
}
ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo(
Box::new(expression.process(module_id)),
ty.0.clone().into_mir(module_id),
),
};
mir::Expression(kind, self.1.as_meta(module_id))
@ -294,9 +296,9 @@ impl ast::Literal {
}
}
impl From<ast::TypeKind> for mir::TypeKind {
fn from(value: ast::TypeKind) -> Self {
match &value {
impl ast::TypeKind {
fn into_mir(&self, source_mod: SourceModuleId) -> mir::TypeKind {
match &self {
ast::TypeKind::Bool => mir::TypeKind::Bool,
ast::TypeKind::I8 => mir::TypeKind::I8,
ast::TypeKind::I16 => mir::TypeKind::I16,
@ -309,14 +311,16 @@ impl From<ast::TypeKind> for mir::TypeKind {
ast::TypeKind::U64 => mir::TypeKind::U64,
ast::TypeKind::U128 => mir::TypeKind::U128,
ast::TypeKind::Array(type_kind, length) => {
mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length)
mir::TypeKind::Array(Box::new(type_kind.clone().into_mir(source_mod)), *length)
}
ast::TypeKind::Custom(name) => {
mir::TypeKind::CustomType(TypeKey(name.clone(), source_mod))
}
ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()),
ast::TypeKind::Borrow(type_kind, mutable) => {
mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())), *mutable)
mir::TypeKind::Borrow(Box::new(type_kind.clone().into_mir(source_mod)), *mutable)
}
ast::TypeKind::Ptr(type_kind) => {
mir::TypeKind::UserPtr(Box::new(mir::TypeKind::from(*type_kind.clone())))
mir::TypeKind::UserPtr(Box::new(type_kind.clone().into_mir(source_mod)))
}
ast::TypeKind::F16 => mir::TypeKind::F16,
ast::TypeKind::F32B => mir::TypeKind::F32B,
@ -329,9 +333,3 @@ impl From<ast::TypeKind> for mir::TypeKind {
}
}
}
impl From<ast::Type> for mir::TypeKind {
fn from(value: ast::Type) -> Self {
value.0.into()
}
}

View File

@ -18,8 +18,8 @@ use crate::{
error_raporting::ModuleMap,
lexer::{FullToken, Position},
mir::{
self, implement::TypeCategory, Metadata, NamedVariableRef, StructField, StructType,
TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral,
self, implement::TypeCategory, Metadata, NamedVariableRef, SourceModuleId, StructField,
StructType, TypeDefinition, TypeDefinitionKind, TypeKey, TypeKind, VagueLiteral,
},
};
@ -77,10 +77,11 @@ pub struct Scope<'ctx, 'a> {
context: &'ctx Context,
tokens: &'ctx Vec<FullToken>,
module: &'ctx Module<'ctx>,
module_id: SourceModuleId,
function: &'ctx StackFunction<'ctx>,
block: Block<'ctx>,
types: &'a HashMap<TypeValue, TypeDefinition>,
type_values: &'a HashMap<String, TypeValue>,
type_values: &'a HashMap<TypeKey, TypeValue>,
functions: &'a HashMap<String, StackFunction<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>,
@ -154,6 +155,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
function: self.function,
context: self.context,
module: self.module,
module_id: self.module_id,
functions: self.functions,
types: self.types,
type_values: self.type_values,
@ -170,8 +172,8 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
old_block
}
fn get_typedef(&self, name: &String) -> Option<&TypeDefinition> {
self.type_values.get(name).and_then(|v| self.types.get(v))
fn get_typedef(&self, key: &TypeKey) -> Option<&TypeDefinition> {
self.type_values.get(key).and_then(|v| self.types.get(v))
}
}
@ -250,6 +252,7 @@ impl mir::Module {
insert_debug!(&TypeKind::Char);
for typedef in &self.typedefs {
let type_key = TypeKey(typedef.name.clone(), self.module_id);
let type_value = match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
@ -265,8 +268,8 @@ impl mir::Module {
}
};
types.insert(type_value, typedef.clone());
type_values.insert(typedef.name.clone(), type_value);
insert_debug!(&TypeKind::CustomType(typedef.name.clone()));
type_values.insert(type_key.clone(), type_value);
insert_debug!(&TypeKind::CustomType(type_key.clone()));
}
let mut functions = HashMap::new();
@ -401,6 +404,7 @@ impl mir::Module {
context,
tokens,
module: &module,
module_id: self.module_id,
function,
block: entry,
functions: &functions,
@ -632,7 +636,10 @@ impl mir::Expression {
.codegen(scope, state)
.expect("rhs has no return value")
.instr();
let lhs_type = lhs_exp.return_type(&Default::default()).unwrap().1;
let lhs_type = lhs_exp
.return_type(&Default::default(), scope.module_id)
.unwrap()
.1;
let instr = match (
binop,
lhs_type.signed(),
@ -887,15 +894,15 @@ impl mir::Expression {
let TypeKind::CodegenPtr(inner) = &struct_val.1 else {
panic!("tried accessing non-pointer");
};
let TypeKind::CustomType(name) = *inner.clone() else {
let TypeKind::CustomType(key) = *inner.clone() else {
panic!("tried accessing non-custom-type");
};
let TypeDefinitionKind::Struct(struct_ty) =
scope.get_typedef(&name).unwrap().kind.clone();
scope.get_typedef(&key).unwrap().kind.clone();
let idx = struct_ty.find_index(field).unwrap();
let gep_n = format!("{}.{}.gep", name, field);
let load_n = format!("{}.{}.load", name, field);
let gep_n = format!("{}.{}.gep", key.0, field);
let load_n = format!("{}.{}.load", key.0, field);
let value = scope
.block
@ -933,7 +940,8 @@ impl mir::Expression {
}
}
mir::ExprKind::Struct(name, items) => {
let struct_ty = Type::CustomType(*scope.type_values.get(name)?);
let type_key = TypeKey(name.clone(), scope.module_id);
let struct_ty = Type::CustomType(*scope.type_values.get(&type_key)?);
let load_n = format!("{}.load", name);
@ -968,7 +976,7 @@ impl mir::Expression {
Some(StackValue(
StackValueKind::Literal(struct_val),
TypeKind::CustomType(name.clone()),
TypeKind::CustomType(type_key),
))
}
mir::ExprKind::Borrow(varref, mutable) => {
@ -1209,7 +1217,7 @@ impl mir::Literal {
impl TypeKind {
fn get_type(
&self,
type_vals: &HashMap<String, TypeValue>,
type_vals: &HashMap<TypeKey, TypeValue>,
typedefs: &HashMap<TypeValue, TypeDefinition>,
) -> Type {
match &self {
@ -1271,7 +1279,7 @@ impl TypeKind {
scope: DebugProgramValue,
debug_info: &DebugInformation,
debug_types: &HashMap<TypeKind, DebugTypeValue>,
type_values: &HashMap<String, TypeValue>,
type_values: &HashMap<TypeKey, TypeValue>,
types: &HashMap<TypeValue, TypeDefinition>,
tokens: &Vec<FullToken>,
) -> DebugTypeValue {
@ -1312,8 +1320,8 @@ impl TypeKind {
length: *len,
})
}
TypeKind::CustomType(name) => {
let typedef = types.get(type_values.get(name).unwrap()).unwrap();
TypeKind::CustomType(key) => {
let typedef = types.get(type_values.get(key).unwrap()).unwrap();
match &typedef.kind {
TypeDefinitionKind::Struct(struct_type) => {
@ -1339,7 +1347,7 @@ impl TypeKind {
}
{
DebugTypeData::Struct(DebugStructType {
name: name.clone(),
name: key.0.clone(),
scope,
location: typedef.meta.into_debug(tokens).unwrap(),
size_bits,

View File

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

View File

@ -345,7 +345,7 @@ impl Display for TypeKind {
Display::fmt(len, f)?;
f.write_char(']')
}
TypeKind::CustomType(name) => write!(f, "{}", name),
TypeKind::CustomType(TypeKey(name, mod_id)) => write!(f, "{}:{}", mod_id, name),
TypeKind::Borrow(type_kind, false) => {
write!(f, "&")?;
Display::fmt(type_kind, f)

View File

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

View File

@ -11,7 +11,7 @@ use crate::{
compile_module,
error_raporting::{ModuleMap, ReidError},
lexer::FullToken,
mir::{TypeDefinition, TypeKind},
mir::{SourceModuleId, TypeDefinition, TypeKey, TypeKind},
parse_module,
};
@ -195,7 +195,6 @@ impl<'map> Pass for LinkerPass<'map> {
let func_name = unsafe { path.get_unchecked(1) };
let imported_mod_name = imported.0.name.clone();
let imported_mod_typedefs = imported.0.typedefs.clone();
let Some(func) = imported
.0
@ -213,6 +212,8 @@ impl<'map> Pass for LinkerPass<'map> {
continue;
};
let func_name = func.name.clone();
if !func.is_pub {
state.ok::<_, Infallible>(
Err(ErrorKind::FunctionIsPrivate(
@ -244,14 +245,12 @@ impl<'map> Pass for LinkerPass<'map> {
}
}
fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<String>) {
fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<TypeKey>) {
let mut imported_types = Vec::new();
let ty = match &ty {
TypeKind::CustomType(name) => {
imported_types.push(name.clone());
let name = format!("{}::{}", base, name);
TypeKind::CustomType(name)
TypeKind::CustomType(key) => {
imported_types.push(key.clone());
TypeKind::CustomType(key.clone())
}
_ => ty.clone(),
};
@ -272,27 +271,28 @@ impl<'map> Pass for LinkerPass<'map> {
fn find_inner_types(
typedef: &TypeDefinition,
mut seen: HashSet<String>,
) -> Vec<String> {
mut seen: HashSet<TypeKey>,
mod_id: SourceModuleId,
) -> Vec<TypeKey> {
match &typedef.kind {
crate::mir::TypeDefinitionKind::Struct(struct_type) => {
let typenames = struct_type
.0
.iter()
.filter(|t| matches!(t.1, TypeKind::CustomType(_)))
.filter(|t| matches!(t.1, TypeKind::CustomType(..)))
.map(|t| match &t.1 {
TypeKind::CustomType(t) => t,
TypeKind::CustomType(TypeKey(t, _)) => t,
_ => panic!(),
})
.cloned()
.collect::<Vec<_>>();
for typename in typenames {
if seen.contains(&typename) {
if seen.contains(&TypeKey(typename.clone(), mod_id)) {
continue;
}
let inner = find_inner_types(typedef, seen.clone());
seen.insert(typename);
let inner = find_inner_types(typedef, seen.clone(), mod_id);
seen.insert(TypeKey(typename, mod_id));
seen.extend(inner);
}
@ -304,28 +304,30 @@ impl<'map> Pass for LinkerPass<'map> {
let mut seen = HashSet::new();
seen.extend(imported_types.clone());
for typename in imported_types.clone() {
let imported_mod_id = imported.0.module_id;
let imported_mod_typedefs = &mut imported.0.typedefs;
for typekey in imported_types.clone() {
let typedef = imported_mod_typedefs
.iter()
.find(|ty| ty.name == typename)
.find(|ty| TypeKey(ty.name.clone(), imported_mod_id) == typekey)
.unwrap();
let inner = find_inner_types(typedef, seen.clone());
let inner = find_inner_types(typedef, seen.clone(), imported_mod_id);
seen.extend(inner);
}
for typename in seen.into_iter() {
let mut typedef = imported_mod_typedefs
for typekey in seen.into_iter() {
let typedef = imported_mod_typedefs
.iter()
.find(|ty| ty.name == typename)
.find(|ty| TypeKey(ty.name.clone(), imported_mod_id) == typekey)
.unwrap()
.clone();
typedef.name = format!("{}::{}", imported_mod_name, typedef.name);
importer_module.0.typedefs.push(typedef);
importer_module.0.typedefs.push(typedef.clone());
}
importer_module.0.functions.push(FunctionDefinition {
name: func.name.clone(),
name: func_name,
is_pub: false,
is_imported: false,
return_type: return_type,

View File

@ -18,7 +18,7 @@ pub mod typeinference;
pub mod typerefs;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
pub struct SourceModuleId(u32);
pub struct SourceModuleId(pub u32);
impl SourceModuleId {
pub fn increment(&mut self) -> SourceModuleId {
@ -77,6 +77,9 @@ impl TokenRange {
}
}
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct TypeKey(pub String, pub SourceModuleId);
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TypeKind {
Bool,
@ -100,7 +103,7 @@ pub enum TypeKind {
F128PPC,
Char,
Array(Box<TypeKind>, u64),
CustomType(String),
CustomType(TypeKey),
Borrow(Box<TypeKind>, bool),
UserPtr(Box<TypeKind>),
CodegenPtr(Box<TypeKind>),
@ -335,6 +338,7 @@ pub struct TypeDefinition {
pub name: String,
pub kind: TypeDefinitionKind,
pub meta: Metadata,
pub source_module: SourceModuleId,
}
#[derive(Debug, Clone)]

View File

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

View File

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

View File

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

View File

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