use crate::*;
use shape_runtime::engine::{ProgramExecutor, ShapeEngine};
use shape_wire::WireValue;
fn execute_repl_command(
engine: &mut ShapeEngine,
source: &str,
) -> shape_runtime::error::Result<WireValue> {
let program = shape_ast::parser::parse_program(source)?;
let default_data = shape_runtime::data::DataFrame::default();
engine
.get_runtime_mut()
.load_program(&program, &default_data)?;
let mut executor = BytecodeExecutor::new();
let result = executor.execute_program(engine, &program)?;
Ok(result.wire_value)
}
#[test]
fn test_variable_persistence_across_executions() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
let result1 = execute_repl_command(&mut engine, "let a = 42");
assert!(
result1.is_ok(),
"first execution should succeed: {:?}",
result1
);
let result2 = execute_repl_command(&mut engine, "a");
assert!(
result2.is_ok(),
"second execution should succeed: {:?}",
result2
);
let wire_val = result2.unwrap();
assert_eq!(
wire_val.as_number(),
Some(42.0),
"variable 'a' should be 42"
);
}
#[test]
fn test_variable_update_persistence() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
execute_repl_command(&mut engine, "let x = 10").expect("should execute");
execute_repl_command(&mut engine, "x = 20").expect("should execute");
let wire_val = execute_repl_command(&mut engine, "x").expect("should execute");
assert_eq!(
wire_val.as_number(),
Some(20.0),
"variable 'x' should be updated to 20"
);
}
#[test]
fn test_variable_persistence_with_stdlib_executor() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
let mut executor = BytecodeExecutor::new();
let program1 = shape_ast::parser::parse_program("let x = 42").expect("parse");
let result1 = executor.execute_program(&mut engine, &program1);
assert!(
result1.is_ok(),
"cell 1 should succeed: {:?}",
result1.err()
);
let program2 = shape_ast::parser::parse_program("x + 8").expect("parse");
let result2 = executor.execute_program(&mut engine, &program2);
assert!(
result2.is_ok(),
"cell 2 should succeed: {:?}",
result2.err()
);
let wire_val = result2.unwrap().wire_value;
assert_eq!(
wire_val.as_number(),
Some(50.0),
"x + 8 should be 50"
);
}
#[test]
fn test_multiple_variables_persist() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
execute_repl_command(&mut engine, "let a = 1").expect("should execute");
execute_repl_command(&mut engine, "let b = 2").expect("should execute");
let wire_val = execute_repl_command(&mut engine, "a + b").expect("should execute");
assert_eq!(wire_val.as_number(), Some(3.0), "a + b should be 3");
}
#[test]
fn test_repl_with_stdlib_constants() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
let result1 = execute_repl_command(&mut engine, "let x = abs(-42)\nx");
assert!(
result1.is_ok(),
"cell 1 should execute: {:?}",
result1.err()
);
assert_eq!(
result1.unwrap().as_number(),
Some(42.0),
"abs should work via prelude injection"
);
let result2 = execute_repl_command(&mut engine, "x + 1");
assert!(
result2.is_ok(),
"cell 2 should execute: {:?}",
result2.err()
);
assert_eq!(
result2.unwrap().as_number(),
Some(43.0),
"cross-cell reference should work"
);
}
#[test]
fn test_type_definition_persistence_across_executions() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
let result1 = execute_repl_command(&mut engine, "type Point { x: int, y: int }");
assert!(
result1.is_ok(),
"type definition should succeed: {:?}",
result1.err()
);
let result2 = execute_repl_command(
&mut engine,
"let p = Point { x: 10, y: 20 }\np.x + p.y",
);
assert!(
result2.is_ok(),
"using type from previous cell should succeed: {:?}",
result2.err()
);
let wire_val = result2.unwrap();
assert_eq!(
wire_val.as_number(),
Some(30.0),
"p.x + p.y should be 30"
);
}
#[test]
fn test_multiple_type_definitions_persist() {
let mut engine = ShapeEngine::new().expect("engine should create");
engine.load_stdlib().expect("stdlib should load");
engine.init_repl();
execute_repl_command(&mut engine, "type Vec2 { x: number, y: number }")
.expect("first type def should succeed");
execute_repl_command(&mut engine, "type Circle { center: Vec2, radius: number }")
.expect("second type def should succeed");
let result = execute_repl_command(
&mut engine,
"let c = Circle { center: Vec2 { x: 1.0, y: 2.0 }, radius: 5.0 }\nc.radius",
);
assert!(
result.is_ok(),
"using both types should succeed: {:?}",
result.err()
);
let wire_val = result.unwrap();
assert_eq!(
wire_val.as_number(),
Some(5.0),
"c.radius should be 5.0"
);
}