diff --git a/src/collections/scoped_buffer.rs b/src/collections/scoped_buffer.rs index 7f519743775cad7b393f2e328eab987b96fb8fdf..5c8fe0837176db8c1e6a6788f815df2db806a58f 100644 --- a/src/collections/scoped_buffer.rs +++ b/src/collections/scoped_buffer.rs @@ -35,7 +35,7 @@ impl ScopedBuffer { ScopedSection { inner: &mut self.inner, start_size, - cur_size: start_size + #[cfg(debug_assertions)] cur_size: start_size } } } @@ -48,7 +48,7 @@ impl ScopedBuffer { ScopedSection{ inner: &mut self.inner, start_size, - cur_size: start_size + data_size, + #[cfg(debug_assertions)] cur_size: start_size + data_size, } } } @@ -65,21 +65,21 @@ impl ScopedSection { #[inline] pub(crate) fn push(&mut self, value: T) { let vec = unsafe{&mut *self.inner}; - debug_assert_eq!(vec.len(), self.cur_size as usize, "trying to push onto section, but size is larger than expected"); + #[cfg(debug_assertions)] debug_assert_eq!(vec.len(), self.cur_size as usize, "trying to push onto section, but size is larger than expected"); vec.push(value); - if cfg!(debug_assertions) { self.cur_size += 1; } + #[cfg(debug_assertions)] { self.cur_size += 1; } } pub(crate) fn len(&self) -> usize { let vec = unsafe{&mut *self.inner}; - debug_assert_eq!(vec.len(), self.cur_size as usize, "trying to get section length, but size is larger than expected"); + #[cfg(debug_assertions)] debug_assert_eq!(vec.len(), self.cur_size as usize, "trying to get section length, but size is larger than expected"); return vec.len() - self.start_size as usize; } #[inline] pub(crate) fn forget(mut self) { let vec = unsafe{&mut *self.inner}; - if cfg!(debug_assertions) { + #[cfg(debug_assertions)] { debug_assert_eq!( vec.len(), self.cur_size as usize, "trying to forget section, but size is larger than expected" @@ -92,7 +92,7 @@ impl ScopedSection { #[inline] pub(crate) fn into_vec(mut self) -> Vec { let vec = unsafe{&mut *self.inner}; - if cfg!(debug_assertions) { + #[cfg(debug_assertions)] { debug_assert_eq!( vec.len(), self.cur_size as usize, "trying to turn section into vec, but size is larger than expected" @@ -117,7 +117,7 @@ impl std::ops::Index for ScopedSection { impl Drop for ScopedSection { fn drop(&mut self) { let vec = unsafe{&mut *self.inner}; - debug_assert_eq!(vec.len(), self.cur_size as usize); + #[cfg(debug_assertions)] debug_assert_eq!(vec.len(), self.cur_size as usize); vec.truncate(self.start_size as usize); } } \ No newline at end of file diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index d2178fc7c6b01753c66f524f0e57f0f9174e8c46..46f86751474def60f6ca98baf04347136ca27d46 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -8,13 +8,13 @@ use crate::protocol::*; use crate::protocol::ast::*; use crate::protocol::type_table::*; -macro_rules! debug_enabled { () => { true }; } +macro_rules! debug_enabled { () => { false }; } macro_rules! debug_log { ($format:literal) => { - enabled_debug_print!(true, "exec", $format); + enabled_debug_print!(false, "exec", $format); }; ($format:literal, $($args:expr),*) => { - enabled_debug_print!(true, "exec", $format, $($args),*); + enabled_debug_print!(false, "exec", $format, $($args),*); }; } @@ -122,10 +122,21 @@ impl Frame { // No subexpressions }, Literal::Struct(literal) => { - for field in &literal.fields { - self.expr_stack.push_back(ExprInstruction::PushValToFront); - self.serialize_expression(heap, field.value); + // Note: fields expressions are evaluated in programmer- + // specified order. But struct construction expects them + // in type-defined order. I might want to come back to + // this. + let mut _num_pushed = 0; + for want_field_idx in 0..literal.fields.len() { + for field in &literal.fields { + if field.field_idx == want_field_idx { + _num_pushed += 1; + self.expr_stack.push_back(ExprInstruction::PushValToFront); + self.serialize_expression(heap, field.value); + } + } } + debug_assert_eq!(_num_pushed, literal.fields.len()) }, Literal::Union(literal) => { for value_expr_id in &literal.values { diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 102a9c2964506143a252ecff933439558a77573b..3ca4bc1da522d162038b1a21aa4e5cfa66642190 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -227,9 +227,9 @@ impl Parser { } } - let mut writer = ASTWriter::new(); - let mut file = std::fs::File::create(std::path::Path::new("ast.txt")).unwrap(); - writer.write_ast(&mut file, &self.heap); + // let mut writer = ASTWriter::new(); + // let mut file = std::fs::File::create(std::path::Path::new("ast.txt")).unwrap(); + // writer.write_ast(&mut file, &self.heap); Ok(()) } diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index 2bfe03822957446486b6547415f5fedccf1c9d0c..32eea7db518c49688743324867849fc39fedb058 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -46,15 +46,15 @@ /// maybe there is a better way then flattened trees + markers? macro_rules! debug_log_enabled { - () => { true }; + () => { false }; } macro_rules! debug_log { ($format:literal) => { - enabled_debug_print!(true, "types", $format); + enabled_debug_print!(false, "types", $format); }; ($format:literal, $($args:expr),*) => { - enabled_debug_print!(true, "types", $format, $($args),*); + enabled_debug_print!(false, "types", $format, $($args),*); }; } @@ -1487,7 +1487,7 @@ impl PassTyping { let target = ctx.types.get_procedure_expression_data_mut(&definition_id, self.reserved_idx); debug_assert!(target.poly_args == self.poly_vars); - debug_assert!(target.expr_data.is_empty()); + debug_assert!(target.expr_data.is_empty()); // makes sure we never queue something twice target.expr_data.reserve(self.expr_types.len()); for infer_expr in self.expr_types.iter() { @@ -2083,7 +2083,10 @@ impl PassTyping { // For all field expressions for field_idx in 0..extra.embedded.len() { - debug_assert_eq!(field_idx, data.fields[field_idx].field_idx, "confusing, innit?"); + // Note: fields in extra.embedded are in the same order as + // they are specified in the literal. Whereas + // `data.fields[...].field_idx` points to the field in the + // struct definition. let signature_type: *mut _ = &mut extra.embedded[field_idx]; let field_expr_id = data.fields[field_idx].value; let field_expr_idx = ctx.heap[field_expr_id].get_unique_id_in_definition(); diff --git a/src/protocol/tests/eval_silly.rs b/src/protocol/tests/eval_silly.rs index 3e3e4ddcba74959c366c307c1f648aa0b0261ae0..004afb78eb4b7d1568271f57a7d2e7c4754716d9 100644 --- a/src/protocol/tests/eval_silly.rs +++ b/src/protocol/tests/eval_silly.rs @@ -96,18 +96,53 @@ fn test_slicing_magic() { return left[0..1] @ right[0..1]; } - func foo() -> u32 { - // left array will be [0, 1, 2, ...] and right array will be [2, 3, 4, ...] - auto created = create_holder(0, 5, 2, 8); - - // in a convoluted fashion select the value 3 from the lhs and the value 3 from the rhs - auto result = slicing_magic(created, 3, 2, 1, 2); - - // and return 3 + 3 - return result[0] + result[1]; + func foo() -> bool { + // Preliminaries: + // 1. construct a holder, where: + // - left array will be [0, 1, 2, ...] + // - right array will be [2, 3, 4, ...] + // 2. Perform slicing magic, always returning an array [3, 3] + // 3. Make sure result is 6 + + // But ofcourse, because we want to be silly, we will check this for + // any possible integer type. + auto created_u08 = create_holder (0, 5, 2, 8); + auto created_u16 = create_holder(0, 5, 2, 8); + auto created_u32 = create_holder(0, 5, 2, 8); + auto created_u64 = create_holder(0, 5, 2, 8); + + auto result_u08 = slicing_magic(created_u08, 3, 2, 1, 2); + auto result_u16 = slicing_magic(created_u16, 3, 2, 1, 2); + auto result_u32 = slicing_magic(created_u32, 3, 2, 1, 2); + auto result_u64 = slicing_magic(created_u64, 3, 2, 1, 2); + + auto result_s08 = slicing_magic(create_holder (0, 5, 2, 8), 3, 2, 1, 2); + auto result_s16 = slicing_magic(create_holder(0, 5, 2, 8), 3, 2, 1, 2); + auto result_s32 = slicing_magic(create_holder(0, 5, 2, 8), 3, 2, 1, 2); + auto result_s64 = slicing_magic(create_holder(0, 5, 2, 8), 3, 2, 1, 2); + + return + result_u08[0] + result_u08[1] == 6 && + result_u16[0] + result_u16[1] == 6 && + result_u32[0] + result_u32[1] == 6 && + result_u64[0] + result_u64[1] == 6 && + result_s08[0] + result_s08[1] == 6 && + result_s16[0] + result_s16[1] == 6 && + result_s32[0] + result_s32[1] == 6 && + result_s64[0] + result_s64[1] == 6; } ").for_function("foo", |f| { - f.call_ok(Some(Value::UInt32(6))); + f.call_ok(Some(Value::Bool(true))); + }).for_struct("Holder", |s| { s + .assert_num_monomorphs(8) + .assert_has_monomorph("u8") + .assert_has_monomorph("u16") + .assert_has_monomorph("u32") + .assert_has_monomorph("u64") + .assert_has_monomorph("s8") + .assert_has_monomorph("s16") + .assert_has_monomorph("s32") + .assert_has_monomorph("s64"); }); } @@ -145,6 +180,40 @@ fn test_struct_fields() { }); } +#[test] +fn test_field_selection_polymorphism() { + // Bit silly, but just to be sure + Tester::new_single_source_expect_ok("struct field shuffles", " +struct VecXYZ { T x, T y, T z } +struct VecYZX { T y, T z, T x } +struct VecZXY { T z, T x, T y } +func modify_x(T input) -> T { + input.x = 1337; + return input; +} + +func foo() -> bool { + auto xyz = VecXYZ{ x: 1, y: 2, z: 3 }; + auto yzx = VecYZX{ y: 2, z: 3, x: 1 }; + auto zxy = VecZXY{ x: 1, y: 2, z: 3 }; + + auto mod_xyz = modify_x(xyz); + auto mod_yzx = modify_x(yzx); + auto mod_zxy = modify_x(zxy); + + return + xyz.x == 1 && xyz.y == 2 && xyz.z == 3 && + yzx.x == 1 && yzx.y == 2 && yzx.z == 3 && + zxy.x == 1 && zxy.y == 2 && zxy.z == 3 && + mod_xyz.x == 1337 && mod_xyz.y == 2 && mod_xyz.z == 3 && + mod_yzx.x == 1337 && mod_yzx.y == 2 && mod_yzx.z == 3 && + mod_zxy.x == 1337 && mod_zxy.y == 2 && mod_zxy.z == 3; +} +").for_function("foo", |f| { + f.call_ok(Some(Value::Bool(true))); + }); +} + #[test] fn test_index_error() { Tester::new_single_source_expect_ok("indexing error", " diff --git a/src/protocol/tests/utils.rs b/src/protocol/tests/utils.rs index 5dc895e2375c035bc85e36c53d9a2968a2f44ae8..4fcdf8f1ccf5bed0b8548b4590d393395a6194af 100644 --- a/src/protocol/tests/utils.rs +++ b/src/protocol/tests/utils.rs @@ -906,7 +906,7 @@ fn has_monomorph(ctx: TestCtx, definition_id: DefinitionId, serialized_monomorph full_buffer.push('['); let mut append_to_full_buffer = |buffer: String| { - if buffer.len() == 1 { + if full_buffer.len() != 1 { full_buffer.push_str(", "); } full_buffer.push('"');