use rex::{BuiltinTypeId, Engine, GasMeter, Library, Parser, Token, Type, Value};
#[tokio::test]
async fn record_update_end_to_end() {
let code = r#"
type Foo = Bar { x: i32, y: i32, z: i32 }
type Sum = A { x: i32 } | B { x: i32 }
let
foo: Foo = Bar { x = 1, y = 2, z = 3 },
foo2 = { foo with { x = 6 } },
sum: Sum = A { x = 1 },
sum2 = match sum
when A {x} -> { sum with { x = x + 1 } }
when B {x} -> { sum with { x = x + 2 } }
in
(foo2.x, match sum2 when A {x} -> x when B {x} -> x)
"#;
let tokens = Token::tokenize(code).unwrap();
let mut parser = Parser::new(tokens);
let program = parser.parse_program(&mut GasMeter::default()).unwrap();
let mut engine = Engine::with_prelude(()).unwrap();
let mut library = Library::global();
library.add_decls(program.decls.clone());
engine.inject_library(library).unwrap();
let mut gas = GasMeter::default();
let (value_ptr, ty) = rex::Evaluator::new_with_compiler(
rex::RuntimeEnv::new(engine.clone()),
rex::Compiler::new(engine.clone()),
)
.eval(program.expr.as_ref(), &mut gas)
.await
.unwrap();
assert_eq!(
ty,
Type::tuple(vec![
Type::builtin(BuiltinTypeId::I32),
Type::builtin(BuiltinTypeId::I32)
])
);
let value = engine
.heap
.get(&value_ptr)
.map(|value| value.as_ref().clone())
.unwrap();
let Value::Tuple(items) = value else {
panic!(
"expected tuple, got {}",
engine.heap.type_name(&value_ptr).unwrap()
);
};
assert_eq!(items.len(), 2);
let a_ptr = &items[0];
let a_value = engine.heap.get(a_ptr).unwrap();
let Value::I32(a) = a_value.as_ref() else {
panic!(
"expected i32, got {}",
engine.heap.type_name(a_ptr).unwrap()
);
};
let b_ptr = &items[1];
let b_value = engine.heap.get(b_ptr).unwrap();
let Value::I32(b) = b_value.as_ref() else {
panic!(
"expected i32, got {}",
engine.heap.type_name(b_ptr).unwrap()
);
};
assert_eq!(*a, 6);
assert_eq!(*b, 2);
}