Skip to content

Commit

Permalink
fix: make bool values semantic
Browse files Browse the repository at this point in the history
  • Loading branch information
Gankra committed Jul 7, 2024
1 parent 10e4e98 commit f59d38f
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 3 deletions.
31 changes: 31 additions & 0 deletions src/harness/check.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use console::Style;
use harness::run::{FuncBuffer, ValBuffer};
use kdl_script::types::PrimitiveTy;
use kdl_script::types::Ty;
use tracing::{error, info};

Expand Down Expand Up @@ -150,6 +151,17 @@ impl TestHarness {
let callee = enum_variant_name(enum_ty, callee_tag);
return Err(tag_error(types, &expected_val, expected, caller, callee));
}
} else if let Ty::Primitive(PrimitiveTy::Bool) = types.realize_ty(expected_val.ty) {
let expected_tag = expected_val.generate_idx(2);
let caller_tag = load_tag(caller_val);
let callee_tag = load_tag(callee_val);

if caller_tag != expected_tag || callee_tag != expected_tag {
let expected = bool_variant_name(expected_tag, expected_tag);
let caller = bool_variant_name(expected_tag, caller_tag);
let callee = bool_variant_name(expected_tag, callee_tag);
return Err(tag_error(types, &expected_val, expected, caller, callee));
}
} else if caller_val.bytes != callee_val.bytes {
// General case, just get a pile of bytes to span both values
let func = expected_val.func();
Expand Down Expand Up @@ -201,6 +213,25 @@ fn enum_variant_name(enum_ty: &kdl_script::types::EnumTy, tag: usize) -> String
format!("{enum_name}::{variant_name}")
}

fn bool_variant_name(expected_tag: usize, tag: usize) -> String {
// Because we're using the tag variant machinery, this code is a bit weird,
// because we essentially get passed Option<bool> for `tag`, where we get
// None when the wrong path is taken.
//
// So to figure out what variant a bool is supposed to have, we work out
// what variant the expected_tag has, and then either say "the same or opposite"
let bools = ["false", "true"];
let expected_bool = bools[expected_tag];
let unexpected_bool = bools[1 - expected_tag];

let res = if tag == expected_tag {
expected_bool
} else {
unexpected_bool
};
res.to_owned()
}

fn tag_error(
types: &kdl_script::TypedProgram,
expected_val: &ValueRef,
Expand Down
2 changes: 1 addition & 1 deletion src/harness/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ impl TestHarness {
.or_insert_with(|| Arc::new(OnceCell::new()))
.clone();
// Either acquire the cached result, or make it
info!("generating {}", &src_path);
let _ = once
.get_or_try_init(|| {
let toolchain = self.toolchain_by_test_key(key, call_side);
let options = key.options.clone();
info!("generating {}", &src_path);
generate_src(
&src_path,
toolchain,
Expand Down
4 changes: 4 additions & 0 deletions src/harness/vals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,10 @@ impl ValueGenerator {
};
rng.gen_range(0..len)
}
pub fn generate_bool(&self) -> bool {
let idx = self.generate_idx(2);
idx == 1
}
pub fn generate_u8(&self) -> u8 {
let mut buf = [0; 1];
self.fill_bytes(&mut buf);
Expand Down
2 changes: 1 addition & 1 deletion src/toolchains/c/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl CcToolchain {
write!(f, "{val}")?
}
}
PrimitiveTy::Bool => write!(f, "true")?,
PrimitiveTy::Bool => write!(f, "{}", val.generate_bool())?,
PrimitiveTy::Ptr => {
if true {
write!(f, "(void*){:#X}ull", val.generate_u64())?
Expand Down
24 changes: 24 additions & 0 deletions src/toolchains/c/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@ impl CcToolchain {
vals: &mut ArgValuesIter,
) -> Result<(), GenerateError> {
match state.types.realize_ty(var_ty) {
Ty::Primitive(PrimitiveTy::Bool) => {
// bool is basically an enum with variants "false" (0) and "true" (1)
let tag_generator = vals.next_val();
let cond = tag_generator.generate_bool();
if tag_generator.should_write_val(&state.options) {
writeln!(f, "if ({from}) {{")?;
f.add_indent(1);
if cond {
self.write_tag_field(f, state, to, from, 1, &tag_generator)?;
} else {
self.write_error_tag_field(f, state, to, &tag_generator)?;
}
f.sub_indent(1);
writeln!(f, "}} else {{")?;
f.add_indent(1);
if !cond {
self.write_tag_field(f, state, to, from, 0, &tag_generator)?;
} else {
self.write_error_tag_field(f, state, to, &tag_generator)?;
}
f.sub_indent(1);
writeln!(f, "}}")?;
}
}
Ty::Primitive(_) => {
// Hey an actual leaf, report it (and burn a value)
let val = vals.next_val();
Expand Down
2 changes: 1 addition & 1 deletion src/toolchains/rust/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl RustcToolchain {

PrimitiveTy::F32 => write!(f, "f32::from_bits({})", val.generate_u32())?,
PrimitiveTy::F64 => write!(f, "f64::from_bits({})", val.generate_u64())?,
PrimitiveTy::Bool => write!(f, "true")?,
PrimitiveTy::Bool => write!(f, "{}", val.generate_bool())?,
PrimitiveTy::Ptr => {
if true {
write!(f, "{:#X}u64 as *mut ()", val.generate_u64())?
Expand Down
24 changes: 24 additions & 0 deletions src/toolchains/rust/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,30 @@ impl RustcToolchain {
vals: &mut ArgValuesIter,
) -> Result<(), GenerateError> {
match state.types.realize_ty(var_ty) {
Ty::Primitive(PrimitiveTy::Bool) => {
// bool is basically an enum with variants "false" (0) and "true" (1)
let tag_generator = vals.next_val();
let cond = tag_generator.generate_bool();
if tag_generator.should_write_val(&state.options) {
writeln!(f, "if {from} {{")?;
f.add_indent(1);
if cond {
self.write_tag_field(f, state, to, from, 1, &tag_generator)?;
} else {
self.write_error_tag_field(f, state, to, &tag_generator)?;
}
f.sub_indent(1);
writeln!(f, "}} else {{")?;
f.add_indent(1);
if !cond {
self.write_tag_field(f, state, to, from, 0, &tag_generator)?;
} else {
self.write_error_tag_field(f, state, to, &tag_generator)?;
}
f.sub_indent(1);
writeln!(f, "}}")?;
}
}
Ty::Primitive(_) => {
// Hey an actual leaf, report it (and burn a value)
let val = vals.next_val();
Expand Down

0 comments on commit f59d38f

Please sign in to comment.