-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathconftest.py
More file actions
164 lines (127 loc) · 4.63 KB
/
conftest.py
File metadata and controls
164 lines (127 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""
Root-level pytest configuration for Factompiler tests.
Provides shared fixtures and path configuration.
"""
from pathlib import Path
from typing import Any
import pytest
from draftsman.blueprintable import Blueprint
from dsl_compiler.src.ast.statements import Program
from dsl_compiler.src.common.diagnostics import ProgramDiagnostics
from dsl_compiler.src.emission.emitter import BlueprintEmitter
from dsl_compiler.src.ir.nodes import IRNode
from dsl_compiler.src.layout.planner import LayoutPlanner
from dsl_compiler.src.lowering.lowerer import ASTLowerer
from dsl_compiler.src.parsing.parser import DSLParser
from dsl_compiler.src.semantic.analyzer import SemanticAnalyzer
# Path fixtures
@pytest.fixture
def project_root():
"""Return the project root directory."""
return Path(__file__).parent
@pytest.fixture
def example_programs_dir(project_root):
"""Return the example programs directory."""
return project_root / "example_programs"
# Common component fixtures
@pytest.fixture
def parser():
"""Create a new DSL parser."""
return DSLParser()
@pytest.fixture
def diagnostics():
"""Create a new ProgramDiagnostics instance."""
return ProgramDiagnostics()
@pytest.fixture
def analyzer(diagnostics):
"""Create a new SemanticAnalyzer instance."""
return SemanticAnalyzer(diagnostics)
# Helper functions available to all tests
def lower_program(
program: Program, semantic_analyzer: SemanticAnalyzer
) -> tuple[list[IRNode], ProgramDiagnostics, dict[str, Any]]:
"""Lower a semantic-analyzed program to IR.
Args:
program: The AST program node to lower
semantic_analyzer: Semantic analyzer containing type information and signal registry
Returns:
Tuple of (IR operations list, diagnostics, signal type map)
"""
diagnostics = ProgramDiagnostics()
lowerer = ASTLowerer(semantic_analyzer, diagnostics)
ir_operations = lowerer.lower_program(program)
return ir_operations, lowerer.diagnostics, lowerer.ir_builder.signal_type_map
def emit_blueprint(
ir_operations: list[IRNode],
label: str = "DSL Generated",
signal_type_map: dict[str, Any] | None = None,
*,
power_pole_type: str | None = None,
) -> tuple[Blueprint, ProgramDiagnostics]:
"""Convert IR operations to Factorio blueprint.
Args:
ir_operations: List of IR nodes to emit
label: Label for the blueprint
signal_type_map: Signal type mappings
power_pole_type: Optional power pole type to add
Returns:
Tuple of (Blueprint, diagnostics)
"""
signal_type_map = signal_type_map or {}
emitter_diagnostics = ProgramDiagnostics()
emitter = BlueprintEmitter(emitter_diagnostics, signal_type_map)
planner_diagnostics = ProgramDiagnostics()
planner = LayoutPlanner(
signal_type_map,
diagnostics=planner_diagnostics,
power_pole_type=power_pole_type,
max_wire_span=9.0,
)
layout_plan = planner.plan_layout(
ir_operations,
blueprint_label=label,
blueprint_description="",
)
combined_diagnostics = ProgramDiagnostics()
combined_diagnostics.diagnostics.extend(planner.diagnostics.diagnostics)
if planner.diagnostics.has_errors():
return Blueprint(), combined_diagnostics
blueprint = emitter.emit_from_plan(layout_plan)
combined_diagnostics.diagnostics.extend(emitter.diagnostics.diagnostics)
return blueprint, combined_diagnostics
def emit_blueprint_string(
ir_operations: list[IRNode],
label: str = "DSL Generated",
signal_type_map: dict[str, Any] | None = None,
*,
power_pole_type: str | None = None,
) -> tuple[str, ProgramDiagnostics]:
"""Convert IR operations to Factorio blueprint string.
Args:
ir_operations: List of IR nodes to emit
label: Label for the blueprint
signal_type_map: Signal type mappings
power_pole_type: Optional power pole type to add
Returns:
Tuple of (blueprint string, diagnostics)
"""
blueprint, diagnostics = emit_blueprint(
ir_operations,
label,
signal_type_map,
power_pole_type=power_pole_type,
)
try:
blueprint_string = blueprint.to_string()
return blueprint_string, diagnostics
except Exception as e:
diagnostics.error(f"Blueprint string generation failed: {e}")
return "", diagnostics
def analyze_program(ast, analyzer=None, diagnostics=None):
"""Helper to analyze a program AST."""
if diagnostics is None:
diagnostics = ProgramDiagnostics()
if analyzer is None:
analyzer = SemanticAnalyzer(diagnostics)
analyzer.visit(ast)
return diagnostics