"""Tests for Signal codegen to LLVM IR.""" import textwrap def test_signal_llvm_ir_structure(): """Test that signal generates proper LLVM IR with memory allocation.""" from ritz.llvm_codegen import generate_llvm_ir from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) with P(): yield "test" """ ) ir = parse_component(source) llvm_ir = generate_llvm_ir(ir) # Should have global for signal value assert "@signal_count" in llvm_ir or "signal" in llvm_ir.lower() # Should have signal getter function assert "get_signal" in llvm_ir or "@get_count" in llvm_ir # Should have signal setter function assert "set_signal" in llvm_ir or "@set_count" in llvm_ir def test_signal_with_fstring(): """Test signal reference in f-string generates proper IR. NOTE: Full f-string interpolation is not yet implemented - this is a TODO. Currently generates a placeholder text node. """ from ritz.llvm_codegen import generate_llvm_ir from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) with P(): yield f"Count: {count}" """ ) ir = parse_component(source) llvm_ir = generate_llvm_ir(ir) # Should have signal storage assert "@signal_count" in llvm_ir # Should have getter function assert "get_count" in llvm_ir # TODO: Full f-string support - currently creates placeholder assert "js_create_text" in llvm_ir def test_event_handler_export(): """Test that event handler functions are exported for JS to call.""" from ritz.llvm_codegen import generate_llvm_ir from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) def increment(): count += 1 with Button(onclick=increment): yield "Click" """ ) ir = parse_component(source) llvm_ir = generate_llvm_ir(ir) # Event handler should be exported as separate function assert "define" in llvm_ir and "increment" in llvm_ir # Should update the signal assert "store" in llvm_ir or "set_count" in llvm_ir def test_signal_update_in_handler(): """Test that count += 1 generates proper signal update code.""" from ritz.llvm_codegen import generate_llvm_ir from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) def increment(): count += 1 """ ) ir = parse_component(source) llvm_ir = generate_llvm_ir(ir) # Should load current value, add 1, store back # This is the signal update pattern found_load = "load" in llvm_ir or "get_count" in llvm_ir found_add = "add" in llvm_ir found_store = "store" in llvm_ir or "set_count" in llvm_ir assert found_load, "Should load signal value" assert found_add, "Should add to value" assert found_store, "Should store updated value" def test_onclick_binding(): """Test that onclick prop generates event binding code.""" from ritz.llvm_codegen import generate_llvm_ir from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): def handleClick(): pass with Button(onclick=handleClick): yield "Click" """ ) ir = parse_component(source) llvm_ir = generate_llvm_ir(ir) # Should call js_bind_event or similar to register handler assert "js_bind_event" in llvm_ir or "onclick" in llvm_ir