use super::*;
use crate::frontend::ast::{Expr, ExprKind, Literal};
use crate::frontend::parser::Parser;
#[test]
fn test_emitter_creates() {
let _emitter = WasmEmitter::new();
}
#[test]
fn test_empty_program_emits() {
let mut parser = Parser::new("");
let expr = parser.parse().unwrap_or_else(|_| {
Expr::new(ExprKind::Block(vec![]), Default::default())
});
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(!bytes.is_empty());
assert_eq!(&bytes[0..4], b"\0asm");
assert_eq!(&bytes[4..8], &[1, 0, 0, 0]);
}
#[test]
fn test_integer_literal() {
let mut parser = Parser::new("42");
let expr = parser.parse().expect("Should parse integer");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x41));
}
#[test]
fn test_binary_operations() {
let mut parser = Parser::new("1 + 2");
let expr = parser.parse().expect("Should parse addition");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x6a));
let mut parser = Parser::new("5 - 3");
let expr = parser.parse().expect("Should parse subtraction");
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x6b));
let mut parser = Parser::new("3 * 4");
let expr = parser.parse().expect("Should parse multiplication");
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x6c));
}
#[test]
fn test_function_definition() {
let mut parser = Parser::new("fun add(x, y) { x + y }");
let expr = parser.parse().expect("Should parse function");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert_eq!(&bytes[0..4], b"\0asm");
assert!(bytes.windows(2).any(|w| w == [0x03, 0x02])); }
#[test]
fn test_if_expression() {
let mut parser = Parser::new("if true { 1 } else { 2 }");
let expr = parser.parse().expect("Should parse if expression");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x04));
}
#[test]
fn test_local_variables() {
let mut parser = Parser::new("let x = 5; x");
let expr = parser.parse().expect("Should parse let binding");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.iter().any(|&b| b == 0x20 || b == 0x21));
}
#[test]
fn test_comparison_operations() {
let mut parser = Parser::new("3 > 2");
let expr = parser.parse().expect("Should parse comparison");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x4a));
}
#[test]
fn test_boolean_literals() {
let mut parser = Parser::new("true");
let expr = parser.parse().expect("Should parse boolean");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.windows(2).any(|w| w == [0x41, 0x01]));
let mut parser = Parser::new("false");
let expr = parser.parse().expect("Should parse boolean");
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.windows(2).any(|w| w == [0x41, 0x00]));
}
#[test]
fn test_block_expression() {
let mut parser = Parser::new("{ 1; 2; 3 }");
let expr = parser.parse().expect("Should parse block");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x02));
}
#[test]
fn test_while_loop() {
let mut parser = Parser::new("while false { }");
let expr = parser.parse().expect("Should parse while loop");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x03));
}
#[test]
fn test_break_statement() {
let mut parser = Parser::new("while true { break }");
let expr = parser.parse().expect("Should parse break");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x0c));
}
#[test]
fn test_continue_statement() {
let mut parser = Parser::new("while true { continue }");
let expr = parser.parse().expect("Should parse continue");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x0c));
}
#[test]
fn test_return_statement() {
let mut parser = Parser::new("fun test() { return 42 }");
let expr = parser.parse().expect("Should parse return");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x0f));
}
#[test]
fn test_nested_expressions() {
let mut parser = Parser::new("(1 + 2) * (3 - 4)");
let expr = parser.parse().expect("Should parse nested expr");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x6a)); assert!(bytes.contains(&0x6b)); assert!(bytes.contains(&0x6c)); }
#[test]
fn test_logical_operations() {
let mut parser = Parser::new("true && false");
let expr = parser.parse().expect("Should parse logical and");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(!bytes.is_empty());
let mut parser = Parser::new("true || false");
let expr = parser.parse().expect("Should parse logical or");
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(!bytes.is_empty());
}
#[test]
fn test_unary_operations() {
let mut parser = Parser::new("!true");
let expr = parser.parse().expect("Should parse not");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x45));
let mut parser = Parser::new("-5");
let expr = parser.parse().expect("Should parse negate");
let result = emitter.emit(&expr);
assert!(result.is_ok());
}
#[test]
fn test_complex_function() {
let mut parser = Parser::new(
r"
fun factorial(n) {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
",
);
let expr = parser.parse().expect("Should parse complex function");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert_eq!(&bytes[0..4], b"\0asm");
assert!(!bytes.is_empty());
}
#[test]
fn test_needs_memory_check() {
let _emitter = WasmEmitter::new();
let expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
);
assert!(!utils::needs_memory(&expr));
let list_expr = Expr::new(ExprKind::List(vec![]), Default::default());
assert!(utils::needs_memory(&list_expr));
}
#[test]
fn test_collect_functions() {
let emitter = WasmEmitter::new();
let func_expr = Expr::new(
ExprKind::Function {
name: "test".to_string(),
type_params: vec![],
params: vec![],
body: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
)),
return_type: None,
is_async: false,
is_pub: false,
},
Default::default(),
);
let funcs = emitter.collect_functions(&func_expr);
assert_eq!(funcs.len(), 1);
assert_eq!(funcs[0].0, "test");
}
#[test]
fn test_division_operation() {
let mut parser = Parser::new("10 / 2");
let expr = parser.parse().expect("Should parse division");
let emitter = WasmEmitter::new();
let result = emitter.emit(&expr);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed in test");
assert!(bytes.contains(&0x6d));
}
#[test]
#[cfg(feature = "notebook")]
fn test_wasm_has_import_section_for_println() {
let mut parser = Parser::new(r#"println("Hello")"#);
let ast = parser.parse().expect("operation should succeed in test");
let emitter = WasmEmitter::new();
let wasm_bytes = emitter
.emit(&ast)
.expect("operation should succeed in test");
let parser = wasmparser::Parser::new(0);
let mut has_import = false;
for payload in parser.parse_all(&wasm_bytes) {
if let Ok(wasmparser::Payload::ImportSection(_)) = payload {
has_import = true;
break;
}
}
assert!(
has_import,
"WASM module must have import section for println"
);
}
#[test]
#[cfg(feature = "notebook")]
fn test_wasm_fstring_simple() {
let mut parser = Parser::new(r#"let x = 10; println(f"Value: {x}")"#);
let ast = parser.parse().expect("operation should succeed in test");
let emitter = WasmEmitter::new();
let wasm_bytes = emitter.emit(&ast);
assert!(
wasm_bytes.is_ok(),
"F-strings must compile to valid WASM: {:?}",
wasm_bytes.err()
);
let bytes = wasm_bytes.expect("operation should succeed in test");
let validation = wasmparser::validate(&bytes);
assert!(
validation.is_ok(),
"F-string WASM must pass validation: {:?}",
validation.err()
);
}
#[test]
#[cfg(feature = "notebook")]
fn test_wasm_match_simple_literal() {
let code = r#"
let number = 2
let description = match number {
1 => "one",
2 => "two",
_ => "other"
}
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("operation should succeed in test");
let emitter = WasmEmitter::new();
let wasm_bytes = emitter.emit(&ast);
assert!(
wasm_bytes.is_ok(),
"Match expressions must compile to valid WASM: {:?}",
wasm_bytes.err()
);
let bytes = wasm_bytes.expect("operation should succeed in test");
let validation = wasmparser::validate(&bytes);
assert!(
validation.is_ok(),
"Match expression WASM must pass validation: {:?}",
validation.err()
);
}
#[test]
fn test_while_loop_with_assignment() {
let code = "let x = 0; while x < 10 { x = x + 1 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_list_literal() {
let code = "[1, 2, 3]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_tuple_literal() {
let code = "(1, 2, 3)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_struct_definition_and_literal() {
let code = r#"
struct Point { x: i32, y: i32 }
let p = Point { x: 10, y: 20 }
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_index_access() {
let code = "let arr = [1, 2, 3]; arr[0]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_assignment() {
let code = "let x = 1; x = 2; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_return_expression() {
let code = "fun foo() { return 42 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_float_literal() {
let code = "3.14";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.unwrap();
assert!(bytes.contains(&0x43));
}
#[test]
fn test_float_operations() {
let code = "3.14 + 2.71";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_nested_function_calls() {
let code = r#"
fun add(a, b) { a + b }
fun double(x) { add(x, x) }
double(5)
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_comparison_lt() {
let code = "1 < 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.unwrap();
assert!(bytes.contains(&0x48));
}
#[test]
fn test_comparison_eq() {
let code = "1 == 1";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.unwrap();
assert!(bytes.contains(&0x46));
}
#[test]
fn test_logical_and() {
let code = "true && false";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_logical_or() {
let code = "true || false";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_unary_negate() {
let code = "-5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_unary_not() {
let code = "!true";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_nested_blocks() {
let code = "{ { 1 } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_if_without_else() {
let code = "if true { 1 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_multiple_let_bindings() {
let code = "let a = 1; let b = 2; let c = a + b; c";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_division() {
let code = "10 / 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.unwrap();
assert!(bytes.contains(&0x6d));
}
#[test]
fn test_modulo() {
let code = "10 % 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_wasm_type_to_valtype() {
let emitter = WasmEmitter::new();
assert_eq!(
emitter.wasm_type_to_valtype(WasmType::I32),
wasm_encoder::ValType::I32
);
assert_eq!(
emitter.wasm_type_to_valtype(WasmType::I64),
wasm_encoder::ValType::I64
);
assert_eq!(
emitter.wasm_type_to_valtype(WasmType::F32),
wasm_encoder::ValType::F32
);
assert_eq!(
emitter.wasm_type_to_valtype(WasmType::F64),
wasm_encoder::ValType::F64
);
}
#[test]
fn test_infer_element_type_literals() {
let emitter = WasmEmitter::new();
let int_expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
);
assert_eq!(emitter.infer_element_type(&int_expr), WasmType::I32);
let float_expr = Expr::new(ExprKind::Literal(Literal::Float(3.14)), Default::default());
assert_eq!(emitter.infer_element_type(&float_expr), WasmType::F32);
let bool_expr = Expr::new(ExprKind::Literal(Literal::Bool(true)), Default::default());
assert_eq!(emitter.infer_element_type(&bool_expr), WasmType::I32);
}
#[test]
fn test_uses_builtins_println() {
let code = "println(42)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
assert!(utils::uses_builtins(&ast));
}
#[test]
fn test_uses_builtins_no_builtins() {
let code = "1 + 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
assert!(!utils::uses_builtins(&ast));
}
#[test]
fn test_needs_memory_with_list() {
let code = "[1, 2, 3]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
assert!(utils::needs_memory(&ast));
}
#[test]
fn test_needs_memory_with_string() {
let code = r#""hello""#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
assert!(utils::needs_memory(&ast));
}
#[test]
fn test_needs_memory_simple_int() {
let code = "42";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
assert!(!utils::needs_memory(&ast));
}
#[test]
fn test_emitter_default() {
let emitter = WasmEmitter::default();
let code = "1 + 1";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_infer_element_type_float() {
let emitter = WasmEmitter::new();
let expr = Expr::new(ExprKind::Literal(Literal::Float(3.14)), Default::default());
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::F32);
}
#[test]
fn test_infer_element_type_integer() {
let emitter = WasmEmitter::new();
let expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
);
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::I32);
}
#[test]
fn test_infer_element_type_bool() {
let emitter = WasmEmitter::new();
let expr = Expr::new(ExprKind::Literal(Literal::Bool(true)), Default::default());
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::I32);
}
#[test]
fn test_infer_element_type_string() {
let emitter = WasmEmitter::new();
let expr = Expr::new(
ExprKind::Literal(Literal::String("hello".to_string())),
Default::default(),
);
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::I32); }
#[test]
fn test_infer_element_type_binary_comparison() {
use crate::frontend::ast::BinaryOp;
let emitter = WasmEmitter::new();
let left = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Default::default(),
));
let right = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Default::default(),
));
let expr = Expr::new(
ExprKind::Binary {
op: BinaryOp::Less,
left,
right,
},
Default::default(),
);
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::I32); }
#[test]
fn test_infer_element_type_binary_arithmetic() {
use crate::frontend::ast::BinaryOp;
let emitter = WasmEmitter::new();
let left = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Default::default(),
));
let right = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Default::default(),
));
let expr = Expr::new(
ExprKind::Binary {
op: BinaryOp::Add,
left,
right,
},
Default::default(),
);
let result = emitter.infer_element_type(&expr);
assert_eq!(result, super::types::WasmType::F32); }
#[test]
fn test_wasm_type_to_valtype_i32() {
let emitter = WasmEmitter::new();
let result = emitter.wasm_type_to_valtype(super::types::WasmType::I32);
assert_eq!(result, wasm_encoder::ValType::I32);
}
#[test]
fn test_wasm_type_to_valtype_f32() {
let emitter = WasmEmitter::new();
let result = emitter.wasm_type_to_valtype(super::types::WasmType::F32);
assert_eq!(result, wasm_encoder::ValType::F32);
}
#[test]
fn test_wasm_type_to_valtype_i64() {
let emitter = WasmEmitter::new();
let result = emitter.wasm_type_to_valtype(super::types::WasmType::I64);
assert_eq!(result, wasm_encoder::ValType::I64);
}
#[test]
fn test_wasm_type_to_valtype_f64() {
let emitter = WasmEmitter::new();
let result = emitter.wasm_type_to_valtype(super::types::WasmType::F64);
assert_eq!(result, wasm_encoder::ValType::F64);
}
#[test]
fn test_emit_with_nested_function_calls() {
let code = r#"
fun square(x) { x * x }
fun cube(x) { x * square(x) }
cube(3)
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_tuple_literal() {
let code = "let t = (1, 2, 3); t";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_mixed_type_tuple() {
let code = "let t = (1, 3.14); t";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_nested_blocks() {
let code = r#"
{
let x = 1;
{
let y = 2;
x + y
}
}
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_multiple_functions() {
let code = r#"
fun foo() { 1 }
fun bar() { 2 }
fun baz() { 3 }
foo() + bar() + baz()
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_recursive_function() {
let code = r#"
fun factorial(n) {
if n <= 1 { 1 } else { n * factorial(n - 1) }
}
factorial(5)
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_comparison_chain() {
let code = "1 < 2 && 2 < 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_while_loop() {
let code = r#"
let mut x = 0;
while x < 10 {
x = x + 1
}
x
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_with_for_range() {
let code = r#"
let mut sum = 0;
for i in 0..5 {
sum = sum + i
}
sum
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_modulo_operation() {
let code = "10 % 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x6f));
}
#[test]
fn test_emit_bitwise_and_operation() {
let code = "5 & 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
let _ = result; }
#[test]
fn test_emit_negative_integer() {
let code = "-42";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_float_literal() {
let code = "3.14159";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x43));
}
#[test]
fn test_emit_float_arithmetic() {
let code = "1.5 + 2.5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_equality_comparison() {
let code = "5 == 5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x46));
}
#[test]
fn test_emit_inequality_comparison() {
let code = "5 != 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x47));
}
#[test]
fn test_emit_greater_or_equal() {
let code = "5 >= 5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x4e));
}
#[test]
fn test_emit_less_or_equal() {
let code = "5 <= 5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x4c));
}
#[test]
fn test_emit_division() {
let code = "10 / 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x6d));
}
#[test]
fn test_emit_modulo() {
let code = "10 % 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x6f));
}
#[test]
fn test_emit_logical_and() {
let code = "true && false";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_logical_or() {
let code = "true || false";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_unary_negate() {
let code = "-42";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_unary_not() {
let code = "!true";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_greater_than() {
let code = "10 > 5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x4a));
}
#[test]
fn test_emit_less_than() {
let code = "5 < 10";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("operation should succeed");
assert!(bytes.contains(&0x48));
}
#[test]
fn test_emit_nested_function_calls() {
let code = "fun f(x) { x + 1 }; f(f(1))";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_multiple_functions() {
let code = "fun a() { 1 }; fun b() { 2 }; a() + b()";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_empty_block() {
let code = "{ }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_block_with_expressions() {
let code = "{ 1; 2; 3 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_comparison_equal() {
let code = "1 == 1";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("should succeed");
assert!(!bytes.is_empty());
}
#[test]
fn test_emit_comparison_not_equal() {
let code = "1 != 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_float_literal_r124() {
let code = "3.14159";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_float_addition() {
let code = "1.5 + 2.5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_bool_true() {
let code = "true";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_bool_false() {
let code = "false";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_unary_negate_r124() {
let code = "-42";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_unary_not_r124() {
let code = "!true";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_parenthesized_expr() {
let code = "(1 + 2) * 3";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_nested_function_calls_r124() {
let code = "fun f(x) { x + 1 }; f(f(1))";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_multiple_params() {
let code = "fun triple(a, b, c) { a + b + c }; triple(1, 2, 3)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_if_expression() {
let code = "if true { 1 } else { 0 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_large_integer_r124() {
let code = "999999999";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_negative_integer_r124() {
let code = "-999";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[cfg(test)]
mod property_tests_mod {
use proptest::proptest;
proptest! {
#[test]
fn test_new_never_panics(input: String) {
let _input = if input.len() > 100 { &input[..100] } else { &input[..] };
let _ = std::panic::catch_unwind(|| {
});
}
}
}
#[cfg(test)]
mod round_157_wasm_tests {
use super::*;
use crate::frontend::parser::Parser;
#[test]
fn test_emit_large_integer() {
let code = "2147483647";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_negative_integer() {
let code = "-2147483647";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_zero() {
let code = "0";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_small_float() {
let code = "0.001";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_large_float() {
let code = "1e38";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_negative_float() {
let code = "-3.14";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_simple_let_chain() {
let code = "let a = 1; let b = 2; let c = 3; a + b + c";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_let_with_computation() {
let code = "let x = 10 * 5; let y = x + 3; y * 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_nested_if() {
let code = "if true { if false { 1 } else { 2 } } else { 3 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_if_with_comparison() {
let code = "if 5 > 3 { 100 } else { 200 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_if_with_logical_and() {
let code = "if true && false { 1 } else { 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_if_with_logical_or() {
let code = "if true || false { 1 } else { 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_no_params() {
let code = "fun answer() { 42 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_one_param() {
let code = "fun double(x) { x * 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_two_params() {
let code = "fun add(a, b) { a + b }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_call() {
let code = "fun id(x) { x }; id(42)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_with_local_var() {
let code = "fun compute() { let x = 10; x * 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_while_break() {
let code = "while true { break }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_while_with_counter() {
let code = "let mut i = 0; while i < 10 { i = i + 1 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_block_single_expr() {
let code = "{ 42 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_block_multiple_expr() {
let code = "{ 1; 2; 3; 4; 5 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_deeply_nested_blocks() {
let code = "{ { { { 42 } } } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_subtraction() {
let code = "100 - 57";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
let bytes = result.expect("should succeed");
assert!(bytes.contains(&0x6b));
}
#[test]
fn test_emit_complex_arithmetic() {
let code = "(1 + 2) * (3 - 4) / 5";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_chained_comparisons() {
let code = "1 < 2 && 2 < 3 && 3 < 4";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_list_integers() {
let code = "[1, 2, 3, 4, 5]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_list_empty() {
let code = "[]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_tuple_integers() {
let code = "(1, 2, 3)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_tuple_mixed() {
let code = "(1, true, 3.14)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_collect_functions_multiple() {
let emitter = WasmEmitter::new();
let code = r#"
fun foo() { 1 }
fun bar() { 2 }
fun baz() { 3 }
"#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let funcs = emitter.collect_functions(&ast);
assert_eq!(funcs.len(), 3);
}
#[test]
fn test_collect_functions_none() {
let emitter = WasmEmitter::new();
let code = "1 + 2";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let funcs = emitter.collect_functions(&ast);
assert!(funcs.is_empty());
}
#[test]
fn test_emit_mutable_assignment() {
let code = "let mut x = 1; x = 2; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
#[test]
fn test_emit_function_with_if() {
let code = "fun max(a, b) { if a > b { a } else { b } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("should parse");
let emitter = WasmEmitter::new();
let result = emitter.emit(&ast);
assert!(result.is_ok());
}
}