Parser: Support multiple components in one file, change args to params with defaults
This commit is contained in:
1 parent
635d466874
commit
81d51d5617
38 files changed
+2151
-455
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,120 @@
|
||||
"""Tests for conditional rendering (if statements)."""
|
||||
|
||||
import pytest
|
||||
from ritz.parser import parse_component
|
||||
|
||||
|
||||
def test_if_statement():
|
||||
"""Test parsing if statement for conditional rendering."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Toggle():
|
||||
visible = signal(True)
|
||||
|
||||
if visible:
|
||||
with P():
|
||||
yield "I am visible!"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find the if statement
|
||||
if_stmt = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "if":
|
||||
if_stmt = stmt
|
||||
break
|
||||
|
||||
assert if_stmt is not None
|
||||
assert if_stmt["test"]["type"] == "name"
|
||||
assert if_stmt["test"]["id"] == "visible"
|
||||
assert len(if_stmt["body"]) == 1
|
||||
assert if_stmt["body"][0]["type"] == "with"
|
||||
|
||||
|
||||
def test_if_else_statement():
|
||||
"""Test parsing if/else for conditional rendering."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Toggle():
|
||||
visible = signal(True)
|
||||
|
||||
if visible:
|
||||
with P():
|
||||
yield "Shown"
|
||||
else:
|
||||
with P():
|
||||
yield "Hidden"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find the if statement
|
||||
if_stmt = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "if":
|
||||
if_stmt = stmt
|
||||
break
|
||||
|
||||
assert if_stmt is not None
|
||||
assert len(if_stmt["body"]) == 1
|
||||
assert len(if_stmt["orelse"]) == 1
|
||||
assert if_stmt["body"][0]["element"]["tag"] == "P"
|
||||
assert if_stmt["orelse"][0]["element"]["tag"] == "P"
|
||||
|
||||
|
||||
def test_if_comparison():
|
||||
"""Test parsing if statement with comparison."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Counter():
|
||||
count = signal(0)
|
||||
|
||||
if count > 5:
|
||||
with P():
|
||||
yield "High count!"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find the if statement
|
||||
if_stmt = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "if":
|
||||
if_stmt = stmt
|
||||
break
|
||||
|
||||
assert if_stmt is not None
|
||||
assert if_stmt["test"]["type"] == "compare"
|
||||
assert if_stmt["test"]["op"] == "Gt"
|
||||
|
||||
|
||||
def test_nested_if():
|
||||
"""Test parsing nested if statements."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Nested():
|
||||
a = signal(True)
|
||||
b = signal(False)
|
||||
|
||||
if a:
|
||||
if b:
|
||||
with P():
|
||||
yield "Both true"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find outer if
|
||||
outer_if = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "if":
|
||||
outer_if = stmt
|
||||
break
|
||||
|
||||
assert outer_if is not None
|
||||
assert outer_if["body"][0]["type"] == "if"
|
||||
@@ -0,0 +1,82 @@
|
||||
"""Tests for LLVM IR code generation with conditional rendering."""
|
||||
|
||||
import pytest
|
||||
from ritz.parser import parse_component
|
||||
from ritz.llvm_codegen_signals import generate_llvm_ir
|
||||
|
||||
|
||||
def test_if_statement_codegen():
|
||||
"""Test LLVM IR generation for if statement."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Toggle():
|
||||
visible = signal(1)
|
||||
|
||||
if visible:
|
||||
with P():
|
||||
yield "I am visible!"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
llvm_ir = generate_llvm_ir(ir)
|
||||
|
||||
# Should have signal global
|
||||
assert "@signal_visible = global i32 1" in llvm_ir
|
||||
|
||||
# Should have conditional branch
|
||||
assert "br i1" in llvm_ir
|
||||
|
||||
# Should have basic blocks for then/else/merge
|
||||
assert "if.then." in llvm_ir
|
||||
assert "if.end." in llvm_ir
|
||||
|
||||
|
||||
def test_if_else_codegen():
|
||||
"""Test LLVM IR generation for if/else."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Toggle():
|
||||
visible = signal(1)
|
||||
|
||||
if visible:
|
||||
with P():
|
||||
yield "Shown"
|
||||
else:
|
||||
with P():
|
||||
yield "Hidden"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
llvm_ir = generate_llvm_ir(ir)
|
||||
|
||||
# Should have conditional branch
|
||||
assert "br i1" in llvm_ir
|
||||
|
||||
# Should have both then and else blocks
|
||||
assert "if.then." in llvm_ir
|
||||
assert "if.else." in llvm_ir
|
||||
|
||||
|
||||
def test_if_comparison_codegen():
|
||||
"""Test LLVM IR generation for if with comparison."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Counter():
|
||||
count = signal(0)
|
||||
|
||||
if count > 5:
|
||||
with P():
|
||||
yield "High count!"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
llvm_ir = generate_llvm_ir(ir)
|
||||
|
||||
# Should have icmp instruction for comparison
|
||||
assert "icmp" in llvm_ir
|
||||
|
||||
# Should have greater-than comparison (sgt = signed greater than)
|
||||
assert "sgt" in llvm_ir or ">" in llvm_ir
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Tests for match/case statement parsing."""
|
||||
|
||||
import pytest
|
||||
from ritz.parser import parse_component
|
||||
|
||||
|
||||
def test_match_statement():
|
||||
"""Test parsing match statement."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Tabs():
|
||||
tab = signal(0)
|
||||
|
||||
match tab:
|
||||
case 0:
|
||||
with P():
|
||||
yield "First"
|
||||
case 1:
|
||||
with P():
|
||||
yield "Second"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find the match statement
|
||||
match_stmt = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "match":
|
||||
match_stmt = stmt
|
||||
break
|
||||
|
||||
assert match_stmt is not None
|
||||
assert match_stmt["subject"]["type"] == "name"
|
||||
assert match_stmt["subject"]["id"] == "tab"
|
||||
assert len(match_stmt["cases"]) == 2
|
||||
|
||||
|
||||
def test_match_with_wildcard():
|
||||
"""Test match with wildcard case."""
|
||||
source = """
|
||||
from ritz.syntax import *
|
||||
|
||||
@component
|
||||
def Tabs():
|
||||
tab = signal(0)
|
||||
|
||||
match tab:
|
||||
case 0:
|
||||
with P():
|
||||
yield "Home"
|
||||
case _:
|
||||
with P():
|
||||
yield "Other"
|
||||
"""
|
||||
ir = parse_component(source)
|
||||
|
||||
# Find the match statement
|
||||
match_stmt = None
|
||||
for stmt in ir["body"]:
|
||||
if stmt["type"] == "match":
|
||||
match_stmt = stmt
|
||||
break
|
||||
|
||||
assert match_stmt is not None
|
||||
assert len(match_stmt["cases"]) == 2
|
||||
# Wildcard should be the last case
|
||||
assert match_stmt["cases"][1]["pattern"]["type"] == "wildcard"
|
||||
@@ -33,7 +33,11 @@ def test_signal_llvm_ir_structure():
|
||||
|
||||
|
||||
def test_signal_with_fstring():
|
||||
"""Test signal reference in f-string generates proper IR."""
|
||||
"""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
|
||||
|
||||
@@ -51,11 +55,14 @@ def test_signal_with_fstring():
|
||||
ir = parse_component(source)
|
||||
llvm_ir = generate_llvm_ir(ir)
|
||||
|
||||
# Should call signal getter
|
||||
assert "get_count" in llvm_ir or "load" in llvm_ir # Loading signal value
|
||||
# Should have signal storage
|
||||
assert "@signal_count" in llvm_ir
|
||||
|
||||
# Should have string formatting/concatenation
|
||||
assert "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():
|
||||
|
||||
Reference in new issue
Block a user