diff --git a/src/protocol/tests/utils.rs b/src/protocol/tests/utils.rs index 45faf494e2d692b358c0d91f5692c431d103d1b8..8ffe0c7bbd8e44ccc3b99c90b49944e2fb786530 100644 --- a/src/protocol/tests/utils.rs +++ b/src/protocol/tests/utils.rs @@ -297,8 +297,8 @@ impl<'a> StructTester<'a> { self = self.assert_has_monomorph(monomorph); let (mono_idx, _) = has_monomorph(self.ctx, self.ast_def.this.upcast(), monomorph); let mono_idx = mono_idx.unwrap(); + let mono = self.ctx.types.get_monomorph(mono_idx); - let mono = &self.type_def.monomorphs[mono_idx]; assert!( mono.size == size && mono.alignment == alignment, "[{}] Expected (size,alignment) of ({}, {}), but got ({}, {}) for {}", @@ -403,6 +403,20 @@ impl<'a> EnumTester<'a> { self } + pub(crate) fn assert_size_alignment(mut self, serialized_monomorph: &str, size: usize, alignment: usize) -> Self { + self = self.assert_has_monomorph(serialized_monomorph); + let (has_monomorph, serialized) = has_monomorph(self.ctx, self.def.this.upcast(), serialized_monomorph); + let mono_index = has_monomorph.unwrap(); + let mono = self.ctx.types.get_monomorph(mono_index); + + assert!( + mono.size == size && mono.alignment == alignment, + "[{}] Expected (size,alignment) of ({}, {}), but got ({}, {}) for {}", + self.ctx.test_name, size, alignment, mono.size, mono.alignment, self.assert_postfix() + ); + self + } + pub(crate) fn assert_postfix(&self) -> String { let mut v = String::new(); v.push_str("Enum{ name: "); @@ -462,14 +476,16 @@ impl<'a> UnionTester<'a> { self = self.assert_has_monomorph(serialized_monomorph); let (mono_idx, _) = has_monomorph(self.ctx, self.ast_def.this.upcast(), serialized_monomorph); let mono_idx = mono_idx.unwrap(); - let mono = &self.type_def.monomorphs[mono_idx]; + let mono_base = self.ctx.types.get_monomorph(mono_idx); + let mono_union = mono_base.variant.as_union(); + assert!( - stack_size == mono.stack_size && stack_alignment == mono.stack_alignment && - heap_size == mono.heap_size && heap_alignment == mono.heap_alignment, + stack_size == mono_base.size && stack_alignment == mono_base.alignment && + heap_size == mono_union.heap_size && heap_alignment == mono_union.heap_alignment, "[{}] Expected (stack | heap) (size, alignment) of ({}, {} | {}, {}), but got ({}, {} | {}, {}) for {}", self.ctx.test_name, stack_size, stack_alignment, heap_size, heap_alignment, - mono.stack_size, mono.stack_alignment, mono.heap_size, mono.heap_alignment, + mono_base.size, mono_base.alignment, mono_union.heap_size, mono_union.heap_alignment, self.assert_postfix() ); self @@ -684,7 +700,12 @@ impl<'a> FunctionTester<'a> { fn eval_until_end(&self) -> (Prompt, Result) { use crate::protocol::*; - let mut prompt = Prompt::new(&self.ctx.types, &self.ctx.heap, self.def.this.upcast(), 0, ValueGroup::new_stack(Vec::new())); + // Assuming the function is not polymorphic + let definition_id = self.def.this.upcast(); + let func_type = [ConcreteTypePart::Function(definition_id, 0)]; + let mono_index = self.ctx.types.get_procedure_monomorph_index(&definition_id, &func_type).unwrap(); + + let mut prompt = Prompt::new(&self.ctx.types, &self.ctx.heap, self.def.this.upcast(), mono_index, ValueGroup::new_stack(Vec::new())); let mut call_context = FakeRunContext{}; loop { let result = prompt.step(&self.ctx.types, &self.ctx.heap, &self.ctx.modules, &mut call_context); @@ -728,7 +749,7 @@ impl<'a> VariableTester<'a> { pub(crate) fn assert_concrete_type(self, expected: &str) -> Self { // Lookup concrete type in type table - let mono_data = self.ctx.types.get_procedure_expression_data(&self.definition_id, 0); + let mono_data = get_procedure_monomorph(&self.ctx.heap, &self.ctx.types, self.definition_id); let concrete_type = &mono_data.expr_data[self.var_expr.unique_id_in_definition as usize].expr_type; // Serialize and check @@ -762,7 +783,7 @@ impl<'a> ExpressionTester<'a> { pub(crate) fn assert_concrete_type(self, expected: &str) -> Self { // Lookup concrete type - let mono_data = self.ctx.types.get_procedure_expression_data(&self.definition_id, 0); + let mono_data = get_procedure_monomorph(&self.ctx.heap, &self.ctx.types, self.definition_id); let expr_index = self.expr.get_unique_id_in_definition(); let concrete_type = &mono_data.expr_data[expr_index as usize].expr_type; @@ -785,6 +806,23 @@ impl<'a> ExpressionTester<'a> { } } +fn get_procedure_monomorph<'a>(heap: &Heap, types: &'a TypeTable, definition_id: DefinitionId) -> &'a ProcedureMonomorph { + let ast_definition = &heap[definition_id]; + let func_type = if ast_definition.is_function() { + [ConcreteTypePart::Function(definition_id, 0)] + } else if ast_definition.is_component() { + [ConcreteTypePart::Component(definition_id, 0)] + } else { + assert!(false); + unreachable!() + }; + + let mono_index = types.get_procedure_monomorph_index(&definition_id, &func_type).unwrap(); + let mono_data = types.get_procedure_monomorph(mono_index); + + mono_data +} + //------------------------------------------------------------------------------ // Interface for failed compilation //------------------------------------------------------------------------------ @@ -888,19 +926,27 @@ impl<'a> ErrorTester<'a> { fn has_equal_num_monomorphs(ctx: TestCtx, num: usize, definition_id: DefinitionId) -> (bool, usize) { use DefinedTypeVariant::*; + // Again: inefficient, but its testing code let type_def = ctx.types.get_base_definition(&definition_id).unwrap(); - let num_on_type = match &type_def.definition { - Struct(v) => v.monomorphs.len(), - Enum(v) => v.monomorphs.len(), - Union(v) => v.monomorphs.len(), - Function(v) => v.monomorphs.len(), - Component(v) => v.monomorphs.len(), - }; + let mut num_on_type = 0; + + for mono in &ctx.types.mono_lookup.monomorphs { + match &mono.concrete_type.parts[0] { + ConcreteTypePart::Instance(def_id, _) | + ConcreteTypePart::Function(def_id, _) | + ConcreteTypePart::Component(def_id, _) => { + if *def_id == definition_id { + num_on_type += 1; + } + }, + _ => {}, + }; + } (num_on_type == num, num_on_type) } -fn has_monomorph(ctx: TestCtx, definition_id: DefinitionId, serialized_monomorph: &str) -> (Option, String) { +fn has_monomorph(ctx: TestCtx, definition_id: DefinitionId, serialized_monomorph: &str) -> (Option, String) { use DefinedTypeVariant::*; let type_def = ctx.types.get_base_definition(&definition_id).unwrap(); @@ -919,34 +965,15 @@ fn has_monomorph(ctx: TestCtx, definition_id: DefinitionId, serialized_monomorph let first_idx = full_buffer.len(); full_buffer.push_str(concrete_type.display_name(ctx.heap).as_str()); if &full_buffer[first_idx..] == serialized_monomorph { - has_match = Some(mono_idx); + has_match = Some(mono_idx as i32); } full_buffer.push('"'); }; - match &type_def.definition { - Enum(definition) => { - for (mono_idx, mono) in definition.monomorphs.iter().enumerate() { - append_to_full_buffer(&mono.concrete_type, mono_idx); - } - }, - Union(definition) => { - for (mono_idx, mono) in definition.monomorphs.iter().enumerate() { - append_to_full_buffer(&mono.concrete_type, mono_idx); - } - }, - Struct(definition) => { - for (mono_idx, mono) in definition.monomorphs.iter().enumerate() { - append_to_full_buffer(&mono.concrete_type, mono_idx); - } - }, - Function(_) | Component(_) => { - let monomorphs = type_def.definition.procedure_monomorphs(); - for (mono_idx, mono) in monomorphs.iter().enumerate() { - append_to_full_buffer(&mono.concrete_type, mono_idx); - } - } + // Bit wasteful, but this is (temporary?) testing code: + for (mono_idx, mono) in ctx.types.mono_lookup.monomorphs.iter().enumerate() { + append_to_full_buffer(&mono.concrete_type, mono_idx); } full_buffer.push(']');