From fab5a230f1ac5f12e2727c41054cf015d12aff38 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Tue, 2 Apr 2024 21:00:05 -0700 Subject: [PATCH] move towards structure construction / deconstruction --- src/backend/into_crane.rs | 26 ++++++++++++++++++++++++-- src/ir/ast.rs | 6 +++--- src/ir/eval.rs | 2 +- src/ir/fields.rs | 14 ++++++++++++++ src/ir/pretty.rs | 2 +- src/type_infer/convert.rs | 1 + src/type_infer/finalize.rs | 3 ++- 7 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/backend/into_crane.rs b/src/backend/into_crane.rs index 644af63..a3aa10f 100644 --- a/src/backend/into_crane.rs +++ b/src/backend/into_crane.rs @@ -406,8 +406,30 @@ impl Backend { } } - Expression::Construct(_, _, _, _) => unimplemented!(), - Expression::FieldRef(_, _, _, _) => unimplemented!(), + Expression::Construct(_, ty, name, fields) => { + let Type::Structure(fields) = ty else { + panic!("Got to backend with non-structure type in structure construction?!"); + }; + + unimplemented!() + } + + Expression::FieldRef(_, _, struct_type, val, field) => { + let (structure, _) = self.compile_value_or_ref(val, variables, builder)?; + + let Type::Structure(fields) = struct_type else { + panic!("Got to backend with non-structure type in field reference?!"); + }; + + let Some((field_type, offset)) = fields.field_type_and_offset(&field) else { + panic!("Got to backend with invalid field for structure type?!"); + }; + + let field_cranelift_type = self.translate_type(field_type).value_type; + + let value = builder.ins().load(field_cranelift_type, MemFlags::new(), structure, offset); + Ok((value, field_cranelift_type)) + } Expression::Block(_, _, mut exprs) => match exprs.pop() { None => Ok((builder.ins().iconst(types::I64, 0), VOID_REPR_TYPE)), diff --git a/src/ir/ast.rs b/src/ir/ast.rs index 456aa91..0e58076 100644 --- a/src/ir/ast.rs +++ b/src/ir/ast.rs @@ -113,7 +113,7 @@ pub enum Expression { ArcIntern, HashMap, ValueOrRef>, ), - FieldRef(Location, Type, ValueOrRef, ArcIntern), + FieldRef(Location, Type, Type, ValueOrRef, ArcIntern), Block(Location, Type, Vec>), Print(Location, ValueOrRef), Call(Location, Type, Box>, Vec>), @@ -129,7 +129,7 @@ impl Expression { Expression::Cast(_, t, _) => t.clone(), Expression::Primitive(_, t, _, _) => t.clone(), Expression::Construct(_, t, _, _) => t.clone(), - Expression::FieldRef(_, t, _, _) => t.clone(), + Expression::FieldRef(_, t, _, _, _) => t.clone(), Expression::Block(_, t, _) => t.clone(), Expression::Print(_, _) => Type::void(), Expression::Call(_, t, _, _) => t.clone(), @@ -145,7 +145,7 @@ impl Expression { Expression::Cast(l, _, _) => l, Expression::Primitive(l, _, _, _) => l, Expression::Construct(l, _, _, _) => l, - Expression::FieldRef(l, _, _, _) => l, + Expression::FieldRef(l, _, _, _, _) => l, Expression::Block(l, _, _) => l, Expression::Print(l, _) => l, Expression::Call(l, _, _, _) => l, diff --git a/src/ir/eval.rs b/src/ir/eval.rs index 6c8b01c..d7462ee 100644 --- a/src/ir/eval.rs +++ b/src/ir/eval.rs @@ -91,7 +91,7 @@ where Ok(Value::Structure(Some(name.clone()), result_fields)) } - Expression::FieldRef(loc, _, valref, field) => match valref.eval(env)? { + Expression::FieldRef(loc, _, _, valref, field) => match valref.eval(env)? { Value::Structure(oname, mut fields) => match fields.remove(field) { None => Err(EvalError::NoFieldForValue( loc.clone(), diff --git a/src/ir/fields.rs b/src/ir/fields.rs index 0c1b689..adc624d 100644 --- a/src/ir/fields.rs +++ b/src/ir/fields.rs @@ -119,6 +119,20 @@ impl Fields { cranelift_description }) } + + pub fn field_type_and_offset(&self, field: &ArcIntern) -> Option<(&T, i32)> { + let mut offset = 0; + + for (current, ty) in self.fields.iter() { + if current == field { + return Some((ty, offset)); + } + + offset += 8; + } + + None + } } impl IntoIterator for Fields { diff --git a/src/ir/pretty.rs b/src/ir/pretty.rs index b407059..129d8f9 100644 --- a/src/ir/pretty.rs +++ b/src/ir/pretty.rs @@ -73,7 +73,7 @@ impl Expression { .braces(); allocator.text(name.to_string()).append(inner) } - Expression::FieldRef(_, _, val, field) => val.pretty(allocator).append( + Expression::FieldRef(_, _, _, val, field) => val.pretty(allocator).append( allocator .text(".") .append(allocator.text(field.to_string())), diff --git a/src/type_infer/convert.rs b/src/type_infer/convert.rs index c6c9a88..0658d95 100644 --- a/src/type_infer/convert.rs +++ b/src/type_infer/convert.rs @@ -338,6 +338,7 @@ fn convert_expression( let result = ir::Expression::FieldRef( loc.clone(), result_type.clone(), + etype.clone(), val_or_ref, field.clone().intern(), ); diff --git a/src/type_infer/finalize.rs b/src/type_infer/finalize.rs index 03edec2..8949c26 100644 --- a/src/type_infer/finalize.rs +++ b/src/type_infer/finalize.rs @@ -73,9 +73,10 @@ fn finalize_expression( .collect(), ), - Expression::FieldRef(loc, ty, valref, field) => Expression::FieldRef( + Expression::FieldRef(loc, ty, struct_type, valref, field) => Expression::FieldRef( loc, finalize_type(ty, resolutions), + finalize_type(struct_type, resolutions), finalize_val_or_ref(valref, resolutions), field, ),