Compare commits
No commits in common. "1c3386bc9afee246b4a43c35524fc1f804957027" and "b93b7aa52b0960926e4a9e0e2c3fc4cd7976fd8b" have entirely different histories.
1c3386bc9a
...
b93b7aa52b
@ -1,6 +0,0 @@
|
|||||||
import foreign_struct::Vec2;
|
|
||||||
|
|
||||||
fn main() -> u32 {
|
|
||||||
let a = Vec2 {x: 16, y: 32};
|
|
||||||
return a.x;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
struct Vec2 { x: u32, y: u32 }
|
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
import triple_import_vec2::Vec2;
|
|
||||||
import triple_import_ship::Ship;
|
|
||||||
|
|
||||||
fn main() -> i32 { return 0; }
|
|
@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
import triple_import_vec2::Vec2;
|
|
||||||
struct Ship { position: Vec2 }
|
|
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
struct Vec2 { x: f32, y: f32 }
|
|
@ -743,6 +743,7 @@ pub fn analyze_block(
|
|||||||
analyze_expr(context, source_module, expression, scope);
|
analyze_expr(context, source_module, expression, scope);
|
||||||
}
|
}
|
||||||
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
|
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
|
||||||
|
dbg!(condition);
|
||||||
analyze_expr(context, source_module, condition, scope);
|
analyze_expr(context, source_module, condition, scope);
|
||||||
analyze_block(context, source_module, block, scope);
|
analyze_block(context, source_module, block, scope);
|
||||||
}
|
}
|
||||||
@ -851,8 +852,8 @@ pub fn analyze_expr(
|
|||||||
analyze_expr(context, source_module, expr, scope);
|
analyze_expr(context, source_module, expr, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Struct(key, items) => {
|
mir::ExprKind::Struct(struct_name, items) => {
|
||||||
let struct_type = TypeKind::CustomType(key.clone());
|
let struct_type = TypeKind::CustomType(CustomTypeKey(struct_name.clone(), source_module.module_id));
|
||||||
let struct_idx = scope
|
let struct_idx = scope
|
||||||
.token_idx(&expr.1, |t| matches!(t, Token::Identifier(_)))
|
.token_idx(&expr.1, |t| matches!(t, Token::Identifier(_)))
|
||||||
.unwrap_or(expr.1.range.end);
|
.unwrap_or(expr.1.range.end);
|
||||||
|
@ -381,7 +381,7 @@ impl ast::Expression {
|
|||||||
Box::new(idx_expr.process(module_id)),
|
Box::new(idx_expr.process(module_id)),
|
||||||
),
|
),
|
||||||
ast::ExpressionKind::StructExpression(struct_init) => mir::ExprKind::Struct(
|
ast::ExpressionKind::StructExpression(struct_init) => mir::ExprKind::Struct(
|
||||||
CustomTypeKey(struct_init.name.clone(), module_id),
|
struct_init.name.clone(),
|
||||||
struct_init
|
struct_init
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -151,11 +151,11 @@ impl mir::Expression {
|
|||||||
allocated.extend(expression.allocate(scope));
|
allocated.extend(expression.allocate(scope));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Struct(key, items) => {
|
mir::ExprKind::Struct(name, items) => {
|
||||||
let (_, ty) = self.return_type(&Default::default(), scope.mod_id).unwrap();
|
let (_, ty) = self.return_type(&Default::default(), scope.mod_id).unwrap();
|
||||||
let allocation = scope
|
let allocation = scope
|
||||||
.block
|
.block
|
||||||
.build_named(key.0.clone(), Instr::Alloca(ty.get_type(scope.type_values)))
|
.build_named(name, Instr::Alloca(ty.get_type(scope.type_values)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
allocated.push(Allocation(self.1, ty, allocation));
|
allocated.push(Allocation(self.1, ty, allocation));
|
||||||
|
|
||||||
|
@ -703,6 +703,7 @@ impl IntrinsicFunction for IntrinsicMemcpy {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let bytes = scope.block.build(Instr::Mul(sizeof, length.instr())).unwrap();
|
let bytes = scope.block.build(Instr::Mul(sizeof, length.instr())).unwrap();
|
||||||
|
|
||||||
|
dbg!(self.0.size_of(&scope.type_map) / 8);
|
||||||
let params = vec![
|
let params = vec![
|
||||||
dest.instr(),
|
dest.instr(),
|
||||||
src.instr(),
|
src.instr(),
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
use std::{
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
cell::RefCell,
|
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use allocator::{Allocator, AllocatorScope};
|
use allocator::{Allocator, AllocatorScope};
|
||||||
use intrinsics::*;
|
use intrinsics::*;
|
||||||
@ -184,40 +180,7 @@ impl mir::Module {
|
|||||||
let mut typedefs = self.typedefs.clone();
|
let mut typedefs = self.typedefs.clone();
|
||||||
typedefs.sort_by(|a, b| b.source_module.cmp(&a.source_module));
|
typedefs.sort_by(|a, b| b.source_module.cmp(&a.source_module));
|
||||||
|
|
||||||
// Since we know by this point that no types are recursive, we can
|
for typedef in typedefs {
|
||||||
// somewhat easily sort the type-definitions such that we can process
|
|
||||||
// the ones with no depencencies first, and later the ones that depend
|
|
||||||
// on the earlier ones.
|
|
||||||
let mut typekeys_seen = HashSet::new();
|
|
||||||
let mut typedefs_sorted = Vec::new();
|
|
||||||
let mut typedefs_left = typedefs.clone();
|
|
||||||
typedefs_left.reverse();
|
|
||||||
while let Some(typedef) = typedefs_left.pop() {
|
|
||||||
match &typedef.kind {
|
|
||||||
TypeDefinitionKind::Struct(StructType(fields)) => {
|
|
||||||
let mut is_ok = true;
|
|
||||||
for field in fields {
|
|
||||||
match &field.1 {
|
|
||||||
TypeKind::CustomType(type_key) => {
|
|
||||||
if !typekeys_seen.contains(type_key) {
|
|
||||||
is_ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_ok {
|
|
||||||
typekeys_seen.insert(CustomTypeKey(typedef.name.clone(), typedef.source_module));
|
|
||||||
typedefs_sorted.push(typedef);
|
|
||||||
} else {
|
|
||||||
typedefs_left.insert(0, typedef.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for typedef in typedefs_sorted {
|
|
||||||
let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module);
|
let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module);
|
||||||
type_map.insert(type_key.clone(), typedef.clone());
|
type_map.insert(type_key.clone(), typedef.clone());
|
||||||
|
|
||||||
@ -227,6 +190,9 @@ impl mir::Module {
|
|||||||
typedef.name.clone(),
|
typedef.name.clone(),
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
|
// TODO: Reorder custom-type definitions such that
|
||||||
|
// inner types get evaluated first. Otherwise this
|
||||||
|
// will cause a panic!
|
||||||
.map(|StructField(_, t, _)| t.get_type(&type_values))
|
.map(|StructField(_, t, _)| t.get_type(&type_values))
|
||||||
.collect(),
|
.collect(),
|
||||||
)))
|
)))
|
||||||
@ -1242,9 +1208,10 @@ impl mir::Expression {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Struct(key, items) => {
|
mir::ExprKind::Struct(name, items) => {
|
||||||
|
let type_key = CustomTypeKey(name.clone(), scope.module_id);
|
||||||
let ty = Type::CustomType({
|
let ty = Type::CustomType({
|
||||||
let Some(a) = scope.type_values.get(&key) else {
|
let Some(a) = scope.type_values.get(&type_key) else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
*a
|
*a
|
||||||
@ -1253,20 +1220,20 @@ impl mir::Expression {
|
|||||||
let TypeDefinition {
|
let TypeDefinition {
|
||||||
kind: TypeDefinitionKind::Struct(struct_ty),
|
kind: TypeDefinitionKind::Struct(struct_ty),
|
||||||
..
|
..
|
||||||
} = scope.types.get(scope.type_values.get(&key).unwrap()).unwrap();
|
} = scope.types.get(scope.type_values.get(&type_key).unwrap()).unwrap();
|
||||||
|
|
||||||
let indices = struct_ty.0.iter().enumerate();
|
let indices = struct_ty.0.iter().enumerate();
|
||||||
|
|
||||||
let load_n = format!("{:?}.load", key);
|
let load_n = format!("{}.load", name);
|
||||||
|
|
||||||
let struct_ptr = scope
|
let struct_ptr = scope
|
||||||
.allocate(&self.1, &TypeKind::CustomType(key.clone()))
|
.allocate(&self.1, &TypeKind::CustomType(type_key.clone()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location.clone());
|
.maybe_location(&mut scope.block, location.clone());
|
||||||
|
|
||||||
for (field_n, exp, _) in items {
|
for (field_n, exp, _) in items {
|
||||||
let gep_n = format!("{:?}.{}.gep", key, field_n);
|
let gep_n = format!("{}.{}.gep", name, field_n);
|
||||||
let store_n = format!("{:?}.{}.store", key, field_n);
|
let store_n = format!("{}.{}.store", name, field_n);
|
||||||
let i = indices.clone().find(|(_, f)| f.0 == *field_n).unwrap().0;
|
let i = indices.clone().find(|(_, f)| f.0 == *field_n).unwrap().0;
|
||||||
|
|
||||||
let elem_ptr = scope
|
let elem_ptr = scope
|
||||||
@ -1287,7 +1254,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
Some(StackValue(
|
Some(StackValue(
|
||||||
StackValueKind::Literal(struct_val),
|
StackValueKind::Literal(struct_val),
|
||||||
TypeKind::CustomType(key.clone()),
|
TypeKind::CustomType(type_key),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Borrow(expr, mutable) => {
|
mir::ExprKind::Borrow(expr, mutable) => {
|
||||||
|
@ -276,8 +276,8 @@ impl Display for ExprKind {
|
|||||||
}
|
}
|
||||||
f.write_char(']')
|
f.write_char(']')
|
||||||
}
|
}
|
||||||
ExprKind::Struct(key, items) => {
|
ExprKind::Struct(name, items) => {
|
||||||
write!(f, "{:?} ", key)?;
|
write!(f, "{} ", name)?;
|
||||||
|
|
||||||
f.write_char('{')?;
|
f.write_char('{')?;
|
||||||
let mut state = Default::default();
|
let mut state = Default::default();
|
||||||
|
@ -416,7 +416,10 @@ impl Expression {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
Accessed(_, type_kind, ..) => Ok((ReturnKind::Soft, type_kind.clone())),
|
Accessed(_, type_kind, ..) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||||
Struct(key, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(key.clone()))),
|
Struct(name, _) => Ok((
|
||||||
|
ReturnKind::Soft,
|
||||||
|
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
||||||
|
)),
|
||||||
Borrow(expr, mutable) => {
|
Borrow(expr, mutable) => {
|
||||||
let ret_type = expr.return_type(refs, mod_id)?;
|
let ret_type = expr.return_type(refs, mod_id)?;
|
||||||
Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable)))
|
Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable)))
|
||||||
|
@ -111,12 +111,11 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
|
|
||||||
let mut modules_to_process: Vec<Rc<RefCell<_>>> = modules.values().cloned().collect();
|
let mut modules_to_process: Vec<Rc<RefCell<_>>> = modules.values().cloned().collect();
|
||||||
|
|
||||||
let mut still_required_types = HashSet::<CustomTypeKey>::new();
|
let mut already_imported_types = HashSet::<CustomTypeKey>::new();
|
||||||
|
let mut already_imported_binops = HashSet::<BinopKey>::new();
|
||||||
|
|
||||||
while let Some(module) = modules_to_process.pop() {
|
while let Some(module) = modules_to_process.pop() {
|
||||||
let mut extern_types = HashMap::new();
|
let mut extern_types = HashMap::new();
|
||||||
let mut already_imported_binops = HashSet::<BinopKey>::new();
|
|
||||||
let mut already_imported_types = HashSet::<CustomTypeKey>::new();
|
|
||||||
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.imports.clone() {
|
||||||
@ -209,7 +208,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
let Some((import_name, _)) = path.get(1) else {
|
let Some((import_name, _)) = path.get(1) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let imported_id = imported.module_id;
|
let import_id = imported.module_id;
|
||||||
|
|
||||||
let mut imported_types = Vec::new();
|
let mut imported_types = Vec::new();
|
||||||
|
|
||||||
@ -352,7 +351,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
return_type,
|
return_type,
|
||||||
parameters: param_tys,
|
parameters: param_tys,
|
||||||
kind: super::FunctionDefinitionKind::Extern(true),
|
kind: super::FunctionDefinitionKind::Extern(true),
|
||||||
source: Some(imported_id),
|
source: Some(import_id),
|
||||||
signature_meta: func.signature_meta,
|
signature_meta: func.signature_meta,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -368,13 +367,6 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
let mut current_extern_types = HashSet::new();
|
let mut current_extern_types = HashSet::new();
|
||||||
seen.extend(imported_types.clone().iter().map(|t| t.0.clone()));
|
seen.extend(imported_types.clone().iter().map(|t| t.0.clone()));
|
||||||
|
|
||||||
for ty in still_required_types.clone() {
|
|
||||||
if ty.1 == imported_id && !seen.contains(&ty) {
|
|
||||||
imported_types.push((ty, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
current_extern_types.extend(imported_types.clone().iter().filter(|t| t.1).map(|t| t.0.clone()));
|
current_extern_types.extend(imported_types.clone().iter().filter(|t| t.1).map(|t| t.0.clone()));
|
||||||
for extern_type in ¤t_extern_types {
|
for extern_type in ¤t_extern_types {
|
||||||
extern_types.insert(extern_type.0.clone(), extern_type.1);
|
extern_types.insert(extern_type.0.clone(), extern_type.1);
|
||||||
@ -386,16 +378,10 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
for typekey in imported_types.clone() {
|
for typekey in imported_types.clone() {
|
||||||
let typedef = imported_mod_typedefs
|
let typedef = imported_mod_typedefs
|
||||||
.iter()
|
.iter()
|
||||||
.find(|ty| CustomTypeKey(ty.name.clone(), ty.source_module) == typekey.0)
|
.find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey.0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let inner = find_inner_types(typedef, seen.clone(), imported_mod_typedefs);
|
let inner = find_inner_types(typedef, seen.clone(), imported_mod_id);
|
||||||
for ty in inner {
|
seen.extend(inner.iter().cloned());
|
||||||
if ty.1 == imported_id && imported_mod_typedefs.iter().find(|t| t.name == ty.0).is_some() {
|
|
||||||
seen.insert(ty);
|
|
||||||
} else {
|
|
||||||
still_required_types.insert(ty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Unable to import same-named type from multiple places..
|
// TODO: Unable to import same-named type from multiple places..
|
||||||
@ -455,7 +441,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module(&mut self, module: &mut Module, state: PassState<Self::Data, Self::TError>) -> PassResult {
|
fn module(&mut self, module: &mut Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
let extern_types = &state.scope.data.extern_imported_types.get(&module.module_id);
|
let extern_types = &state.scope.data.extern_imported_types.get(&module.module_id);
|
||||||
if let Some(extern_types) = extern_types {
|
if let Some(extern_types) = extern_types {
|
||||||
for ty in &mut module.typedefs {
|
for ty in &mut module.typedefs {
|
||||||
@ -525,13 +511,6 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
super::ExprKind::AssociatedFunctionCall(type_kind, _) => {
|
super::ExprKind::AssociatedFunctionCall(type_kind, _) => {
|
||||||
*type_kind = type_kind.update_imported(extern_types, mod_id)
|
*type_kind = type_kind.update_imported(extern_types, mod_id)
|
||||||
}
|
}
|
||||||
super::ExprKind::Struct(key, _) => {
|
|
||||||
*key = if let Some(mod_id) = extern_types.get(&key.0) {
|
|
||||||
CustomTypeKey(key.0.clone(), *mod_id)
|
|
||||||
} else {
|
|
||||||
key.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -587,31 +566,28 @@ fn import_type(ty: &TypeKind, usable_import: bool) -> Vec<(CustomTypeKey, bool)>
|
|||||||
fn find_inner_types(
|
fn find_inner_types(
|
||||||
typedef: &TypeDefinition,
|
typedef: &TypeDefinition,
|
||||||
mut seen: HashSet<CustomTypeKey>,
|
mut seen: HashSet<CustomTypeKey>,
|
||||||
typedefs: &Vec<TypeDefinition>,
|
mod_id: SourceModuleId,
|
||||||
) -> Vec<CustomTypeKey> {
|
) -> Vec<CustomTypeKey> {
|
||||||
match &typedef.kind {
|
match &typedef.kind {
|
||||||
crate::mir::TypeDefinitionKind::Struct(struct_type) => {
|
crate::mir::TypeDefinitionKind::Struct(struct_type) => {
|
||||||
let typekeys = struct_type
|
let typenames = struct_type
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|t| match &t.1 {
|
.filter(|t| matches!(t.1, TypeKind::CustomType(..)))
|
||||||
TypeKind::CustomType(key) => Some(key),
|
.map(|t| match &t.1 {
|
||||||
_ => None,
|
TypeKind::CustomType(CustomTypeKey(t, _)) => t,
|
||||||
|
_ => panic!(),
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for typekey in typekeys {
|
for typename in typenames {
|
||||||
if seen.contains(&typekey) {
|
if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
seen.insert(typekey.clone());
|
let inner = find_inner_types(typedef, seen.clone(), mod_id);
|
||||||
if typekey.1 == typedef.source_module {
|
seen.insert(CustomTypeKey(typename, mod_id));
|
||||||
if let Some(inner) = typedefs.iter().find(|t| t.name == typekey.0) {
|
seen.extend(inner);
|
||||||
let ret = find_inner_types(inner, seen.clone(), typedefs);
|
|
||||||
seen.extend(ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
seen.into_iter().collect()
|
seen.into_iter().collect()
|
||||||
|
@ -264,7 +264,7 @@ pub enum ExprKind {
|
|||||||
Indexed(Box<Expression>, TypeKind, Box<Expression>),
|
Indexed(Box<Expression>, TypeKind, Box<Expression>),
|
||||||
Accessed(Box<Expression>, TypeKind, String, Metadata),
|
Accessed(Box<Expression>, TypeKind, String, Metadata),
|
||||||
Array(Vec<Expression>),
|
Array(Vec<Expression>),
|
||||||
Struct(CustomTypeKey, Vec<(String, Expression, Metadata)>),
|
Struct(String, Vec<(String, Expression, Metadata)>),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
BinOp(BinaryOperator, Box<Expression>, Box<Expression>, TypeKind),
|
BinOp(BinaryOperator, Box<Expression>, Box<Expression>, TypeKind),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
|
@ -627,14 +627,15 @@ impl Expression {
|
|||||||
Err(ErrorKind::TriedAccessingNonStruct(expr_ty))
|
Err(ErrorKind::TriedAccessingNonStruct(expr_ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Struct(struct_key, 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(&struct_key)
|
.get_struct_type(&type_key)
|
||||||
.ok_or(ErrorKind::NoSuchType(struct_key.0.clone(), struct_key.1))?
|
.ok_or(ErrorKind::NoSuchType(struct_name.clone(), type_key.1))?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let mut expected_fields = if let Some(struct_ty) = state.scope.get_struct_type(&struct_key) {
|
let mut expected_fields = if let Some(struct_ty) = state.scope.get_struct_type(&type_key) {
|
||||||
struct_ty.0.iter().map(|f| f.0.clone()).collect()
|
struct_ty.0.iter().map(|f| f.0.clone()).collect()
|
||||||
} else {
|
} else {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
@ -645,7 +646,7 @@ impl Expression {
|
|||||||
let expected_ty = state.or_else(
|
let expected_ty = state.or_else(
|
||||||
struct_def
|
struct_def
|
||||||
.get_field_ty(field_name)
|
.get_field_ty(field_name)
|
||||||
.ok_or(ErrorKind::NoSuchField(format!("{:?}.{}", struct_key, field_name))),
|
.ok_or(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field_name))),
|
||||||
&TypeKind::Vague(VagueType::Unknown),
|
&TypeKind::Vague(VagueType::Unknown),
|
||||||
field_expr.1,
|
field_expr.1,
|
||||||
);
|
);
|
||||||
@ -667,7 +668,7 @@ impl Expression {
|
|||||||
self.1,
|
self.1,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(TypeKind::CustomType(struct_key.clone()))
|
Ok(TypeKind::CustomType(type_key))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(expr, mutable) => {
|
ExprKind::Borrow(expr, mutable) => {
|
||||||
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
let hint_t = if let HintKind::Coerce(hint_t) = hint_t {
|
||||||
|
@ -553,11 +553,12 @@ impl Expression {
|
|||||||
_ => Ok(type_refs.from_type(&TypeKind::Vague(VagueType::Unknown)).unwrap()),
|
_ => Ok(type_refs.from_type(&TypeKind::Vague(VagueType::Unknown)).unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Struct(struct_key, 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(&struct_key)
|
.get_struct_type(&type_key)
|
||||||
.ok_or(ErrorKind::NoSuchType(struct_key.0.clone(), state.module_id.unwrap()))?
|
.ok_or(ErrorKind::NoSuchType(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) {
|
||||||
@ -567,12 +568,12 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
Err(ErrorKind::NoSuchField(format!("{:?}.{}", struct_key, field.0))),
|
Err(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field.0))),
|
||||||
field.1 .1,
|
field.1 .1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(type_refs.from_type(&TypeKind::CustomType(struct_key.clone())).unwrap())
|
Ok(type_refs.from_type(&TypeKind::CustomType(type_key.clone())).unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(expr, mutable) => {
|
ExprKind::Borrow(expr, mutable) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
|
@ -0,0 +1,171 @@
|
|||||||
|
use std::{path::PathBuf, process::Command, time::SystemTime};
|
||||||
|
|
||||||
|
use reid::{
|
||||||
|
compile_module,
|
||||||
|
ld::LDRunner,
|
||||||
|
mir::{self},
|
||||||
|
parse_module, perform_all_passes,
|
||||||
|
};
|
||||||
|
use reid_lib::{compile::CompileOutput, Context};
|
||||||
|
use util::assert_err;
|
||||||
|
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
fn test_compile(source: &str, name: &str) -> CompileOutput {
|
||||||
|
assert_err(assert_err(std::panic::catch_unwind(|| {
|
||||||
|
let mut map = Default::default();
|
||||||
|
let (id, tokens) = assert_err(parse_module(source, name, None, &mut map, None));
|
||||||
|
|
||||||
|
let module = assert_err(assert_err(compile_module(id, tokens, &mut map, None, true)).map_err(|(_, e)| e));
|
||||||
|
let mut mir_context = mir::Context::from(vec![module], Default::default());
|
||||||
|
assert_err(perform_all_passes(&mut mir_context, &mut map));
|
||||||
|
|
||||||
|
let context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION")));
|
||||||
|
|
||||||
|
let codegen = assert_err(mir_context.codegen(&context));
|
||||||
|
|
||||||
|
Ok::<_, ()>(codegen.compile(None, Vec::new()).output())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(source: &str, name: &str, expected_exit_code: Option<i32>) {
|
||||||
|
assert_err(assert_err(std::panic::catch_unwind(|| {
|
||||||
|
let output = test_compile(source, name);
|
||||||
|
|
||||||
|
let time = SystemTime::now();
|
||||||
|
let in_path = PathBuf::from(format!(
|
||||||
|
"/tmp/temp-{}.o",
|
||||||
|
time.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos()
|
||||||
|
));
|
||||||
|
|
||||||
|
std::fs::write(&in_path, &output.obj_buffer).expect("Could not write OBJ-file!");
|
||||||
|
|
||||||
|
let out_path = in_path.with_extension("out");
|
||||||
|
LDRunner::from_command("ld")
|
||||||
|
.with_library("c")
|
||||||
|
.invoke(&in_path, &out_path);
|
||||||
|
std::fs::remove_file(in_path).unwrap();
|
||||||
|
|
||||||
|
let executed = Command::new(&out_path).output();
|
||||||
|
std::fs::remove_file(out_path).unwrap();
|
||||||
|
|
||||||
|
if let Some(expected_exit_code) = expected_exit_code {
|
||||||
|
assert_eq!(expected_exit_code, executed.unwrap().status.code().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok::<(), ()>(())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arithmetic_compiles_well() {
|
||||||
|
test(include_str!("../../examples/arithmetic.reid"), "test", Some(48));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn array_structs_compiles_well() {
|
||||||
|
test(include_str!("../../examples/array_structs.reid"), "test", Some(5));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn array_compiles_well() {
|
||||||
|
test(include_str!("../../examples/array.reid"), "test", Some(3));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn borrow_compiles_well() {
|
||||||
|
test(include_str!("../../examples/borrow.reid"), "test", Some(17));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn borrow_hard_compiles_well() {
|
||||||
|
test(include_str!("../../examples/borrow_hard.reid"), "test", Some(17));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn cast_compiles_well() {
|
||||||
|
test(include_str!("../../examples/cast.reid"), "test", Some(6));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn char_compiles_well() {
|
||||||
|
test(include_str!("../../examples/char.reid"), "test", Some(98));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn div_mod_compiles_well() {
|
||||||
|
test(include_str!("../../examples/div_mod.reid"), "test", Some(12));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fibonacci_compiles_well() {
|
||||||
|
test(include_str!("../../examples/fibonacci.reid"), "test", Some(1));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn float_compiles_well() {
|
||||||
|
test(include_str!("../../examples/float.reid"), "test", Some(1));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn hello_world_compiles_well() {
|
||||||
|
test(include_str!("../../examples/hello_world.reid"), "test", None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn hello_world_harder_compiles_well() {
|
||||||
|
test(include_str!("../../examples/hello_world_harder.reid"), "test", None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn mutable_compiles_well() {
|
||||||
|
test(include_str!("../../examples/mutable.reid"), "test", Some(21));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn ptr_compiles_well() {
|
||||||
|
test(include_str!("../../examples/ptr.reid"), "test", Some(5));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn std_test_compiles_well() {
|
||||||
|
test(include_str!("../../examples/std_test.reid"), "test", Some(3));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn strings_compiles_well() {
|
||||||
|
test(include_str!("../../examples/strings.reid"), "test", Some(5));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn struct_compiles_well() {
|
||||||
|
test(include_str!("../../examples/struct.reid"), "test", Some(17));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn loops_compiles_well() {
|
||||||
|
test(include_str!("../../examples/loops.reid"), "test", Some(10));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn ptr_hard_compiles_well() {
|
||||||
|
test(include_str!("../../examples/ptr_hard.reid"), "test", Some(0));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn loop_hard_compiles_well() {
|
||||||
|
test(include_str!("../../examples/loop_hard.reid"), "test", Some(0));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn custom_binop_compiles_well() {
|
||||||
|
test(include_str!("../../examples/custom_binop.reid"), "test", Some(21));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn array_short_compiles_well() {
|
||||||
|
test(include_str!("../../examples/array_short.reid"), "test", Some(5));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn imported_type_compiles_well() {
|
||||||
|
test(include_str!("../../examples/imported_type.reid"), "test", Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn associated_functions() {
|
||||||
|
test(
|
||||||
|
include_str!("../../examples/associated_functions.reid"),
|
||||||
|
"test",
|
||||||
|
Some(4),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mutable_inner_functions() {
|
||||||
|
test(include_str!("../../examples/mutable_inner.reid"), "test", Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cpu_raytracer_compiles() {
|
||||||
|
test_compile(include_str!("../../examples/cpu_raytracer.reid"), "test");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user