machine-dialect 0.1.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- machine_dialect/__main__.py +667 -0
- machine_dialect/agent/__init__.py +5 -0
- machine_dialect/agent/agent.py +360 -0
- machine_dialect/ast/__init__.py +95 -0
- machine_dialect/ast/ast_node.py +35 -0
- machine_dialect/ast/call_expression.py +82 -0
- machine_dialect/ast/dict_extraction.py +60 -0
- machine_dialect/ast/expressions.py +439 -0
- machine_dialect/ast/literals.py +309 -0
- machine_dialect/ast/program.py +35 -0
- machine_dialect/ast/statements.py +1433 -0
- machine_dialect/ast/tests/test_ast_string_representation.py +62 -0
- machine_dialect/ast/tests/test_boolean_literal.py +29 -0
- machine_dialect/ast/tests/test_collection_hir.py +138 -0
- machine_dialect/ast/tests/test_define_statement.py +142 -0
- machine_dialect/ast/tests/test_desugar.py +541 -0
- machine_dialect/ast/tests/test_foreach_desugar.py +245 -0
- machine_dialect/cfg/__init__.py +6 -0
- machine_dialect/cfg/config.py +156 -0
- machine_dialect/cfg/examples.py +221 -0
- machine_dialect/cfg/generate_with_ai.py +187 -0
- machine_dialect/cfg/openai_generation.py +200 -0
- machine_dialect/cfg/parser.py +94 -0
- machine_dialect/cfg/tests/__init__.py +1 -0
- machine_dialect/cfg/tests/test_cfg_parser.py +252 -0
- machine_dialect/cfg/tests/test_config.py +188 -0
- machine_dialect/cfg/tests/test_examples.py +391 -0
- machine_dialect/cfg/tests/test_generate_with_ai.py +354 -0
- machine_dialect/cfg/tests/test_openai_generation.py +256 -0
- machine_dialect/codegen/__init__.py +5 -0
- machine_dialect/codegen/bytecode_module.py +89 -0
- machine_dialect/codegen/bytecode_serializer.py +300 -0
- machine_dialect/codegen/opcodes.py +101 -0
- machine_dialect/codegen/register_codegen.py +1996 -0
- machine_dialect/codegen/symtab.py +208 -0
- machine_dialect/codegen/tests/__init__.py +1 -0
- machine_dialect/codegen/tests/test_array_operations_codegen.py +295 -0
- machine_dialect/codegen/tests/test_bytecode_serializer.py +185 -0
- machine_dialect/codegen/tests/test_register_codegen_ssa.py +324 -0
- machine_dialect/codegen/tests/test_symtab.py +418 -0
- machine_dialect/codegen/vm_serializer.py +621 -0
- machine_dialect/compiler/__init__.py +18 -0
- machine_dialect/compiler/compiler.py +197 -0
- machine_dialect/compiler/config.py +149 -0
- machine_dialect/compiler/context.py +149 -0
- machine_dialect/compiler/phases/__init__.py +19 -0
- machine_dialect/compiler/phases/bytecode_optimization.py +90 -0
- machine_dialect/compiler/phases/codegen.py +40 -0
- machine_dialect/compiler/phases/hir_generation.py +39 -0
- machine_dialect/compiler/phases/mir_generation.py +86 -0
- machine_dialect/compiler/phases/optimization.py +110 -0
- machine_dialect/compiler/phases/parsing.py +39 -0
- machine_dialect/compiler/pipeline.py +143 -0
- machine_dialect/compiler/tests/__init__.py +1 -0
- machine_dialect/compiler/tests/test_compiler.py +568 -0
- machine_dialect/compiler/vm_runner.py +173 -0
- machine_dialect/errors/__init__.py +32 -0
- machine_dialect/errors/exceptions.py +369 -0
- machine_dialect/errors/messages.py +82 -0
- machine_dialect/errors/tests/__init__.py +0 -0
- machine_dialect/errors/tests/test_expected_token_errors.py +188 -0
- machine_dialect/errors/tests/test_name_errors.py +118 -0
- machine_dialect/helpers/__init__.py +0 -0
- machine_dialect/helpers/stopwords.py +225 -0
- machine_dialect/helpers/validators.py +30 -0
- machine_dialect/lexer/__init__.py +9 -0
- machine_dialect/lexer/constants.py +23 -0
- machine_dialect/lexer/lexer.py +907 -0
- machine_dialect/lexer/tests/__init__.py +0 -0
- machine_dialect/lexer/tests/helpers.py +86 -0
- machine_dialect/lexer/tests/test_apostrophe_identifiers.py +122 -0
- machine_dialect/lexer/tests/test_backtick_identifiers.py +140 -0
- machine_dialect/lexer/tests/test_boolean_literals.py +108 -0
- machine_dialect/lexer/tests/test_case_insensitive_keywords.py +188 -0
- machine_dialect/lexer/tests/test_comments.py +200 -0
- machine_dialect/lexer/tests/test_double_asterisk_keywords.py +127 -0
- machine_dialect/lexer/tests/test_lexer_position.py +113 -0
- machine_dialect/lexer/tests/test_list_tokens.py +282 -0
- machine_dialect/lexer/tests/test_stopwords.py +80 -0
- machine_dialect/lexer/tests/test_strict_equality.py +129 -0
- machine_dialect/lexer/tests/test_token.py +41 -0
- machine_dialect/lexer/tests/test_tokenization.py +294 -0
- machine_dialect/lexer/tests/test_underscore_literals.py +343 -0
- machine_dialect/lexer/tests/test_url_literals.py +169 -0
- machine_dialect/lexer/tokens.py +487 -0
- machine_dialect/linter/__init__.py +10 -0
- machine_dialect/linter/__main__.py +144 -0
- machine_dialect/linter/linter.py +154 -0
- machine_dialect/linter/rules/__init__.py +8 -0
- machine_dialect/linter/rules/base.py +112 -0
- machine_dialect/linter/rules/statement_termination.py +99 -0
- machine_dialect/linter/tests/__init__.py +1 -0
- machine_dialect/linter/tests/mdrules/__init__.py +0 -0
- machine_dialect/linter/tests/mdrules/test_md101_statement_termination.py +181 -0
- machine_dialect/linter/tests/test_linter.py +81 -0
- machine_dialect/linter/tests/test_rules.py +110 -0
- machine_dialect/linter/tests/test_violations.py +71 -0
- machine_dialect/linter/violations.py +51 -0
- machine_dialect/mir/__init__.py +69 -0
- machine_dialect/mir/analyses/__init__.py +20 -0
- machine_dialect/mir/analyses/alias_analysis.py +315 -0
- machine_dialect/mir/analyses/dominance_analysis.py +49 -0
- machine_dialect/mir/analyses/escape_analysis.py +286 -0
- machine_dialect/mir/analyses/loop_analysis.py +272 -0
- machine_dialect/mir/analyses/tests/test_type_analysis.py +736 -0
- machine_dialect/mir/analyses/type_analysis.py +448 -0
- machine_dialect/mir/analyses/use_def_chains.py +232 -0
- machine_dialect/mir/basic_block.py +385 -0
- machine_dialect/mir/dataflow.py +445 -0
- machine_dialect/mir/debug_info.py +208 -0
- machine_dialect/mir/hir_to_mir.py +1738 -0
- machine_dialect/mir/mir_dumper.py +366 -0
- machine_dialect/mir/mir_function.py +167 -0
- machine_dialect/mir/mir_instructions.py +1877 -0
- machine_dialect/mir/mir_interpreter.py +556 -0
- machine_dialect/mir/mir_module.py +225 -0
- machine_dialect/mir/mir_printer.py +480 -0
- machine_dialect/mir/mir_transformer.py +410 -0
- machine_dialect/mir/mir_types.py +367 -0
- machine_dialect/mir/mir_validation.py +455 -0
- machine_dialect/mir/mir_values.py +268 -0
- machine_dialect/mir/optimization_config.py +233 -0
- machine_dialect/mir/optimization_pass.py +251 -0
- machine_dialect/mir/optimization_pipeline.py +355 -0
- machine_dialect/mir/optimizations/__init__.py +84 -0
- machine_dialect/mir/optimizations/algebraic_simplification.py +733 -0
- machine_dialect/mir/optimizations/branch_prediction.py +372 -0
- machine_dialect/mir/optimizations/constant_propagation.py +634 -0
- machine_dialect/mir/optimizations/cse.py +398 -0
- machine_dialect/mir/optimizations/dce.py +288 -0
- machine_dialect/mir/optimizations/inlining.py +551 -0
- machine_dialect/mir/optimizations/jump_threading.py +487 -0
- machine_dialect/mir/optimizations/licm.py +405 -0
- machine_dialect/mir/optimizations/loop_unrolling.py +366 -0
- machine_dialect/mir/optimizations/strength_reduction.py +422 -0
- machine_dialect/mir/optimizations/tail_call.py +207 -0
- machine_dialect/mir/optimizations/tests/test_loop_unrolling.py +483 -0
- machine_dialect/mir/optimizations/type_narrowing.py +397 -0
- machine_dialect/mir/optimizations/type_specialization.py +447 -0
- machine_dialect/mir/optimizations/type_specific.py +906 -0
- machine_dialect/mir/optimize_mir.py +89 -0
- machine_dialect/mir/pass_manager.py +391 -0
- machine_dialect/mir/profiling/__init__.py +26 -0
- machine_dialect/mir/profiling/profile_collector.py +318 -0
- machine_dialect/mir/profiling/profile_data.py +372 -0
- machine_dialect/mir/profiling/profile_reader.py +272 -0
- machine_dialect/mir/profiling/profile_writer.py +226 -0
- machine_dialect/mir/register_allocation.py +302 -0
- machine_dialect/mir/reporting/__init__.py +17 -0
- machine_dialect/mir/reporting/optimization_reporter.py +314 -0
- machine_dialect/mir/reporting/report_formatter.py +289 -0
- machine_dialect/mir/ssa_construction.py +342 -0
- machine_dialect/mir/tests/__init__.py +1 -0
- machine_dialect/mir/tests/test_algebraic_associativity.py +204 -0
- machine_dialect/mir/tests/test_algebraic_complex_patterns.py +221 -0
- machine_dialect/mir/tests/test_algebraic_division.py +126 -0
- machine_dialect/mir/tests/test_algebraic_simplification.py +863 -0
- machine_dialect/mir/tests/test_basic_block.py +425 -0
- machine_dialect/mir/tests/test_branch_prediction.py +459 -0
- machine_dialect/mir/tests/test_call_lowering.py +168 -0
- machine_dialect/mir/tests/test_collection_lowering.py +604 -0
- machine_dialect/mir/tests/test_cross_block_constant_propagation.py +255 -0
- machine_dialect/mir/tests/test_custom_passes.py +166 -0
- machine_dialect/mir/tests/test_debug_info.py +285 -0
- machine_dialect/mir/tests/test_dict_extraction_lowering.py +192 -0
- machine_dialect/mir/tests/test_dictionary_lowering.py +299 -0
- machine_dialect/mir/tests/test_double_negation.py +231 -0
- machine_dialect/mir/tests/test_escape_analysis.py +233 -0
- machine_dialect/mir/tests/test_hir_to_mir.py +465 -0
- machine_dialect/mir/tests/test_hir_to_mir_complete.py +389 -0
- machine_dialect/mir/tests/test_hir_to_mir_simple.py +130 -0
- machine_dialect/mir/tests/test_inlining.py +435 -0
- machine_dialect/mir/tests/test_licm.py +472 -0
- machine_dialect/mir/tests/test_mir_dumper.py +313 -0
- machine_dialect/mir/tests/test_mir_instructions.py +445 -0
- machine_dialect/mir/tests/test_mir_module.py +860 -0
- machine_dialect/mir/tests/test_mir_printer.py +387 -0
- machine_dialect/mir/tests/test_mir_types.py +123 -0
- machine_dialect/mir/tests/test_mir_types_enhanced.py +132 -0
- machine_dialect/mir/tests/test_mir_validation.py +378 -0
- machine_dialect/mir/tests/test_mir_values.py +168 -0
- machine_dialect/mir/tests/test_one_based_indexing.py +202 -0
- machine_dialect/mir/tests/test_optimization_helpers.py +60 -0
- machine_dialect/mir/tests/test_optimization_pipeline.py +554 -0
- machine_dialect/mir/tests/test_optimization_reporter.py +318 -0
- machine_dialect/mir/tests/test_pass_manager.py +294 -0
- machine_dialect/mir/tests/test_pass_registration.py +64 -0
- machine_dialect/mir/tests/test_profiling.py +356 -0
- machine_dialect/mir/tests/test_register_allocation.py +307 -0
- machine_dialect/mir/tests/test_report_formatters.py +372 -0
- machine_dialect/mir/tests/test_ssa_construction.py +433 -0
- machine_dialect/mir/tests/test_tail_call.py +236 -0
- machine_dialect/mir/tests/test_type_annotated_instructions.py +192 -0
- machine_dialect/mir/tests/test_type_narrowing.py +277 -0
- machine_dialect/mir/tests/test_type_specialization.py +421 -0
- machine_dialect/mir/tests/test_type_specific_optimization.py +545 -0
- machine_dialect/mir/tests/test_type_specific_optimization_advanced.py +382 -0
- machine_dialect/mir/type_inference.py +368 -0
- machine_dialect/parser/__init__.py +12 -0
- machine_dialect/parser/enums.py +45 -0
- machine_dialect/parser/parser.py +3655 -0
- machine_dialect/parser/protocols.py +11 -0
- machine_dialect/parser/symbol_table.py +169 -0
- machine_dialect/parser/tests/__init__.py +0 -0
- machine_dialect/parser/tests/helper_functions.py +193 -0
- machine_dialect/parser/tests/test_action_statements.py +334 -0
- machine_dialect/parser/tests/test_boolean_literal_expressions.py +152 -0
- machine_dialect/parser/tests/test_call_statements.py +154 -0
- machine_dialect/parser/tests/test_call_statements_errors.py +187 -0
- machine_dialect/parser/tests/test_collection_mutations.py +264 -0
- machine_dialect/parser/tests/test_conditional_expressions.py +343 -0
- machine_dialect/parser/tests/test_define_integration.py +468 -0
- machine_dialect/parser/tests/test_define_statements.py +311 -0
- machine_dialect/parser/tests/test_dict_extraction.py +115 -0
- machine_dialect/parser/tests/test_empty_literal.py +155 -0
- machine_dialect/parser/tests/test_float_literal_expressions.py +163 -0
- machine_dialect/parser/tests/test_identifier_expressions.py +57 -0
- machine_dialect/parser/tests/test_if_empty_block.py +61 -0
- machine_dialect/parser/tests/test_if_statements.py +299 -0
- machine_dialect/parser/tests/test_illegal_tokens.py +86 -0
- machine_dialect/parser/tests/test_infix_expressions.py +680 -0
- machine_dialect/parser/tests/test_integer_literal_expressions.py +137 -0
- machine_dialect/parser/tests/test_interaction_statements.py +269 -0
- machine_dialect/parser/tests/test_list_literals.py +277 -0
- machine_dialect/parser/tests/test_no_none_in_ast.py +94 -0
- machine_dialect/parser/tests/test_panic_mode_recovery.py +171 -0
- machine_dialect/parser/tests/test_parse_errors.py +114 -0
- machine_dialect/parser/tests/test_possessive_syntax.py +182 -0
- machine_dialect/parser/tests/test_prefix_expressions.py +415 -0
- machine_dialect/parser/tests/test_program.py +13 -0
- machine_dialect/parser/tests/test_return_statements.py +89 -0
- machine_dialect/parser/tests/test_set_statements.py +152 -0
- machine_dialect/parser/tests/test_strict_equality.py +258 -0
- machine_dialect/parser/tests/test_symbol_table.py +217 -0
- machine_dialect/parser/tests/test_url_literal_expressions.py +209 -0
- machine_dialect/parser/tests/test_utility_statements.py +423 -0
- machine_dialect/parser/token_buffer.py +159 -0
- machine_dialect/repl/__init__.py +3 -0
- machine_dialect/repl/repl.py +426 -0
- machine_dialect/repl/tests/__init__.py +0 -0
- machine_dialect/repl/tests/test_repl.py +606 -0
- machine_dialect/semantic/__init__.py +12 -0
- machine_dialect/semantic/analyzer.py +906 -0
- machine_dialect/semantic/error_messages.py +189 -0
- machine_dialect/semantic/tests/__init__.py +1 -0
- machine_dialect/semantic/tests/test_analyzer.py +364 -0
- machine_dialect/semantic/tests/test_error_messages.py +104 -0
- machine_dialect/tests/edge_cases/__init__.py +10 -0
- machine_dialect/tests/edge_cases/test_boundary_access.py +256 -0
- machine_dialect/tests/edge_cases/test_empty_collections.py +166 -0
- machine_dialect/tests/edge_cases/test_invalid_operations.py +243 -0
- machine_dialect/tests/edge_cases/test_named_list_edge_cases.py +295 -0
- machine_dialect/tests/edge_cases/test_nested_structures.py +313 -0
- machine_dialect/tests/edge_cases/test_type_mixing.py +277 -0
- machine_dialect/tests/integration/test_array_operations_emulation.py +248 -0
- machine_dialect/tests/integration/test_list_compilation.py +395 -0
- machine_dialect/tests/integration/test_lists_and_dictionaries.py +322 -0
- machine_dialect/type_checking/__init__.py +21 -0
- machine_dialect/type_checking/tests/__init__.py +1 -0
- machine_dialect/type_checking/tests/test_type_system.py +230 -0
- machine_dialect/type_checking/type_system.py +270 -0
- machine_dialect-0.1.0a1.dist-info/METADATA +128 -0
- machine_dialect-0.1.0a1.dist-info/RECORD +268 -0
- machine_dialect-0.1.0a1.dist-info/WHEEL +5 -0
- machine_dialect-0.1.0a1.dist-info/entry_points.txt +3 -0
- machine_dialect-0.1.0a1.dist-info/licenses/LICENSE +201 -0
- machine_dialect-0.1.0a1.dist-info/top_level.txt +2 -0
- machine_dialect_vm/__init__.pyi +15 -0
@@ -0,0 +1,372 @@
|
|
1
|
+
"""Tests for report formatters."""
|
2
|
+
|
3
|
+
import json
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
|
7
|
+
from machine_dialect.mir.reporting.optimization_reporter import (
|
8
|
+
ModuleMetrics,
|
9
|
+
PassMetrics,
|
10
|
+
)
|
11
|
+
from machine_dialect.mir.reporting.report_formatter import (
|
12
|
+
HTMLReportFormatter,
|
13
|
+
JSONReportFormatter,
|
14
|
+
TextReportFormatter,
|
15
|
+
)
|
16
|
+
|
17
|
+
|
18
|
+
def create_test_metrics() -> ModuleMetrics:
|
19
|
+
"""Create test module metrics."""
|
20
|
+
metrics = ModuleMetrics(
|
21
|
+
module_name="test_module",
|
22
|
+
optimization_level=2,
|
23
|
+
)
|
24
|
+
|
25
|
+
# Add pass metrics
|
26
|
+
pass1 = PassMetrics(
|
27
|
+
pass_name="constant-propagation",
|
28
|
+
phase="early",
|
29
|
+
metrics={"constants_propagated": 15, "expressions_folded": 5},
|
30
|
+
before_stats={"instructions": 100, "blocks": 10},
|
31
|
+
after_stats={"instructions": 85, "blocks": 8},
|
32
|
+
time_ms=3.5,
|
33
|
+
)
|
34
|
+
|
35
|
+
pass2 = PassMetrics(
|
36
|
+
pass_name="dead-code-elimination",
|
37
|
+
phase="main",
|
38
|
+
metrics={"dead_removed": 10, "blocks_removed": 2},
|
39
|
+
before_stats={"instructions": 85, "blocks": 8},
|
40
|
+
after_stats={"instructions": 75, "blocks": 6},
|
41
|
+
time_ms=2.0,
|
42
|
+
)
|
43
|
+
|
44
|
+
metrics.add_pass_metrics(pass1)
|
45
|
+
metrics.add_pass_metrics(pass2)
|
46
|
+
|
47
|
+
# Add function metrics
|
48
|
+
metrics.function_metrics["main"] = {
|
49
|
+
"instructions": 50,
|
50
|
+
"blocks": 4,
|
51
|
+
"loops": 1,
|
52
|
+
}
|
53
|
+
|
54
|
+
metrics.function_metrics["helper"] = {
|
55
|
+
"instructions": 25,
|
56
|
+
"blocks": 2,
|
57
|
+
"loops": 0,
|
58
|
+
}
|
59
|
+
|
60
|
+
return metrics
|
61
|
+
|
62
|
+
|
63
|
+
class TestTextReportFormatter:
|
64
|
+
"""Test text report formatter."""
|
65
|
+
|
66
|
+
def test_basic_formatting(self) -> None:
|
67
|
+
"""Test basic text formatting."""
|
68
|
+
formatter = TextReportFormatter(detailed=False)
|
69
|
+
metrics = create_test_metrics()
|
70
|
+
|
71
|
+
report = formatter.format(metrics)
|
72
|
+
|
73
|
+
assert "OPTIMIZATION REPORT - test_module" in report
|
74
|
+
assert "Optimization Level: 2" in report
|
75
|
+
assert "Total Passes Run: 2" in report
|
76
|
+
assert "Total Time: 5.50ms" in report
|
77
|
+
assert "constant-propagation" in report
|
78
|
+
assert "dead-code-elimination" in report
|
79
|
+
|
80
|
+
def test_detailed_formatting(self) -> None:
|
81
|
+
"""Test detailed text formatting."""
|
82
|
+
formatter = TextReportFormatter(detailed=True)
|
83
|
+
metrics = create_test_metrics()
|
84
|
+
|
85
|
+
report = formatter.format(metrics)
|
86
|
+
|
87
|
+
assert "DETAILED PASS STATISTICS" in report
|
88
|
+
assert "[1] constant-propagation" in report
|
89
|
+
assert "[2] dead-code-elimination" in report
|
90
|
+
assert "Phase: early" in report
|
91
|
+
assert "Phase: main" in report
|
92
|
+
assert "Time: 3.50ms" in report
|
93
|
+
assert "Time: 2.00ms" in report
|
94
|
+
|
95
|
+
def test_improvements_section(self) -> None:
|
96
|
+
"""Test that improvements are calculated and shown."""
|
97
|
+
formatter = TextReportFormatter(detailed=True)
|
98
|
+
metrics = create_test_metrics()
|
99
|
+
|
100
|
+
report = formatter.format(metrics)
|
101
|
+
|
102
|
+
assert "OVERALL IMPROVEMENTS" in report
|
103
|
+
# Instructions reduced from 100 to 75 (25% reduction)
|
104
|
+
assert "instructions" in report
|
105
|
+
assert "reduction" in report
|
106
|
+
|
107
|
+
def test_total_optimizations(self) -> None:
|
108
|
+
"""Test total optimizations section."""
|
109
|
+
formatter = TextReportFormatter()
|
110
|
+
metrics = create_test_metrics()
|
111
|
+
|
112
|
+
report = formatter.format(metrics)
|
113
|
+
|
114
|
+
assert "TOTAL OPTIMIZATIONS" in report
|
115
|
+
assert "constants_propagated" in report
|
116
|
+
assert "15" in report
|
117
|
+
assert "dead_removed" in report
|
118
|
+
assert "10" in report
|
119
|
+
|
120
|
+
def test_function_metrics_section(self) -> None:
|
121
|
+
"""Test function-level statistics."""
|
122
|
+
formatter = TextReportFormatter(detailed=True)
|
123
|
+
metrics = create_test_metrics()
|
124
|
+
|
125
|
+
report = formatter.format(metrics)
|
126
|
+
|
127
|
+
assert "FUNCTION-LEVEL STATISTICS" in report
|
128
|
+
assert "Function: main" in report
|
129
|
+
assert "Function: helper" in report
|
130
|
+
assert "instructions" in report
|
131
|
+
assert "blocks" in report
|
132
|
+
assert "loops" in report
|
133
|
+
|
134
|
+
def test_empty_metrics(self) -> None:
|
135
|
+
"""Test formatting empty metrics."""
|
136
|
+
formatter = TextReportFormatter()
|
137
|
+
metrics = ModuleMetrics("empty", optimization_level=0)
|
138
|
+
|
139
|
+
report = formatter.format(metrics)
|
140
|
+
|
141
|
+
assert "OPTIMIZATION REPORT - empty" in report
|
142
|
+
assert "Total Passes Run: 0" in report
|
143
|
+
assert "Total Time: 0.00ms" in report
|
144
|
+
|
145
|
+
def test_passes_applied_list(self) -> None:
|
146
|
+
"""Test passes applied list formatting."""
|
147
|
+
formatter = TextReportFormatter()
|
148
|
+
metrics = create_test_metrics()
|
149
|
+
|
150
|
+
report = formatter.format(metrics)
|
151
|
+
|
152
|
+
assert "PASSES APPLIED" in report
|
153
|
+
assert "1. constant-propagation" in report
|
154
|
+
assert "2. dead-code-elimination" in report
|
155
|
+
|
156
|
+
def test_average_pass_time(self) -> None:
|
157
|
+
"""Test average pass time calculation."""
|
158
|
+
formatter = TextReportFormatter()
|
159
|
+
metrics = create_test_metrics()
|
160
|
+
|
161
|
+
report = formatter.format(metrics)
|
162
|
+
|
163
|
+
assert "Average Pass Time:" in report
|
164
|
+
# (3.5 + 2.0) / 2 = 2.75ms
|
165
|
+
assert "2.75ms" in report
|
166
|
+
|
167
|
+
|
168
|
+
class TestHTMLReportFormatter:
|
169
|
+
"""Test HTML report formatter."""
|
170
|
+
|
171
|
+
def test_basic_html_structure(self) -> None:
|
172
|
+
"""Test basic HTML structure."""
|
173
|
+
formatter = HTMLReportFormatter()
|
174
|
+
metrics = create_test_metrics()
|
175
|
+
|
176
|
+
report = formatter.format(metrics)
|
177
|
+
|
178
|
+
assert "<!DOCTYPE html>" in report
|
179
|
+
assert "<html>" in report
|
180
|
+
assert "</html>" in report
|
181
|
+
assert "<head>" in report
|
182
|
+
assert "<body>" in report
|
183
|
+
assert "<title>Optimization Report</title>" in report
|
184
|
+
|
185
|
+
def test_html_content(self) -> None:
|
186
|
+
"""Test HTML content."""
|
187
|
+
formatter = HTMLReportFormatter()
|
188
|
+
metrics = create_test_metrics()
|
189
|
+
|
190
|
+
report = formatter.format(metrics)
|
191
|
+
|
192
|
+
assert "<h1>Optimization Report - test_module</h1>" in report
|
193
|
+
assert "<h2>Summary</h2>" in report
|
194
|
+
assert "Optimization Level" in report
|
195
|
+
assert "Total Passes" in report
|
196
|
+
assert "constant-propagation" in report
|
197
|
+
assert "dead-code-elimination" in report
|
198
|
+
|
199
|
+
def test_html_tables(self) -> None:
|
200
|
+
"""Test HTML tables."""
|
201
|
+
formatter = HTMLReportFormatter()
|
202
|
+
metrics = create_test_metrics()
|
203
|
+
|
204
|
+
report = formatter.format(metrics)
|
205
|
+
|
206
|
+
assert "<table>" in report
|
207
|
+
assert "<tr>" in report
|
208
|
+
assert "<td>" in report
|
209
|
+
assert "<th>" in report
|
210
|
+
|
211
|
+
def test_html_styling(self) -> None:
|
212
|
+
"""Test HTML styling."""
|
213
|
+
formatter = HTMLReportFormatter()
|
214
|
+
metrics = create_test_metrics()
|
215
|
+
|
216
|
+
report = formatter.format(metrics)
|
217
|
+
|
218
|
+
assert "<style>" in report
|
219
|
+
assert "font-family: monospace" in report
|
220
|
+
assert ".improvement" in report
|
221
|
+
assert ".regression" in report
|
222
|
+
|
223
|
+
def test_html_improvements(self) -> None:
|
224
|
+
"""Test HTML improvements section."""
|
225
|
+
formatter = HTMLReportFormatter()
|
226
|
+
metrics = create_test_metrics()
|
227
|
+
|
228
|
+
report = formatter.format(metrics)
|
229
|
+
|
230
|
+
assert "<h2>Overall Improvements</h2>" in report
|
231
|
+
assert "class='improvement'" in report
|
232
|
+
|
233
|
+
def test_html_detailed_stats(self) -> None:
|
234
|
+
"""Test HTML detailed statistics."""
|
235
|
+
formatter = HTMLReportFormatter()
|
236
|
+
metrics = create_test_metrics()
|
237
|
+
|
238
|
+
report = formatter.format(metrics)
|
239
|
+
|
240
|
+
assert "<h2>Detailed Pass Statistics</h2>" in report
|
241
|
+
assert "constant-propagation" in report
|
242
|
+
assert "3.50" in report # Time
|
243
|
+
|
244
|
+
def test_empty_html_report(self) -> None:
|
245
|
+
"""Test empty HTML report."""
|
246
|
+
formatter = HTMLReportFormatter()
|
247
|
+
metrics = ModuleMetrics("empty")
|
248
|
+
|
249
|
+
report = formatter.format(metrics)
|
250
|
+
|
251
|
+
assert "<!DOCTYPE html>" in report
|
252
|
+
assert "Optimization Report - empty" in report
|
253
|
+
|
254
|
+
|
255
|
+
class TestJSONReportFormatter:
|
256
|
+
"""Test JSON report formatter."""
|
257
|
+
|
258
|
+
def test_json_structure(self) -> None:
|
259
|
+
"""Test JSON structure."""
|
260
|
+
formatter = JSONReportFormatter()
|
261
|
+
metrics = create_test_metrics()
|
262
|
+
|
263
|
+
report = formatter.format(metrics)
|
264
|
+
data = json.loads(report)
|
265
|
+
|
266
|
+
assert data["module_name"] == "test_module"
|
267
|
+
assert data["optimization_level"] == 2
|
268
|
+
assert data["total_time_ms"] == 5.5
|
269
|
+
assert "summary" in data
|
270
|
+
assert "passes" in data
|
271
|
+
assert "functions" in data
|
272
|
+
|
273
|
+
def test_json_passes(self) -> None:
|
274
|
+
"""Test JSON passes data."""
|
275
|
+
formatter = JSONReportFormatter()
|
276
|
+
metrics = create_test_metrics()
|
277
|
+
|
278
|
+
report = formatter.format(metrics)
|
279
|
+
data = json.loads(report)
|
280
|
+
|
281
|
+
assert len(data["passes"]) == 2
|
282
|
+
|
283
|
+
pass1 = data["passes"][0]
|
284
|
+
assert pass1["name"] == "constant-propagation"
|
285
|
+
assert pass1["phase"] == "early"
|
286
|
+
assert pass1["time_ms"] == 3.5
|
287
|
+
assert pass1["metrics"]["constants_propagated"] == 15
|
288
|
+
|
289
|
+
def test_json_improvements(self) -> None:
|
290
|
+
"""Test JSON improvements calculation."""
|
291
|
+
formatter = JSONReportFormatter()
|
292
|
+
metrics = create_test_metrics()
|
293
|
+
|
294
|
+
report = formatter.format(metrics)
|
295
|
+
data = json.loads(report)
|
296
|
+
|
297
|
+
pass1 = data["passes"][0]
|
298
|
+
assert "improvements" in pass1
|
299
|
+
assert "instructions" in pass1["improvements"]
|
300
|
+
# 100 -> 85 is 15% improvement
|
301
|
+
assert pass1["improvements"]["instructions"] == 15.0
|
302
|
+
|
303
|
+
def test_json_function_metrics(self) -> None:
|
304
|
+
"""Test JSON function metrics."""
|
305
|
+
formatter = JSONReportFormatter()
|
306
|
+
metrics = create_test_metrics()
|
307
|
+
|
308
|
+
report = formatter.format(metrics)
|
309
|
+
data = json.loads(report)
|
310
|
+
|
311
|
+
assert "main" in data["functions"]
|
312
|
+
assert data["functions"]["main"]["instructions"] == 50
|
313
|
+
assert data["functions"]["main"]["loops"] == 1
|
314
|
+
|
315
|
+
assert "helper" in data["functions"]
|
316
|
+
assert data["functions"]["helper"]["instructions"] == 25
|
317
|
+
|
318
|
+
def test_json_summary(self) -> None:
|
319
|
+
"""Test JSON summary data."""
|
320
|
+
formatter = JSONReportFormatter()
|
321
|
+
metrics = create_test_metrics()
|
322
|
+
|
323
|
+
report = formatter.format(metrics)
|
324
|
+
data = json.loads(report)
|
325
|
+
|
326
|
+
summary = data["summary"]
|
327
|
+
assert summary["module_name"] == "test_module"
|
328
|
+
assert summary["total_passes"] == 2
|
329
|
+
assert "passes_applied" in summary
|
330
|
+
assert len(summary["passes_applied"]) == 2
|
331
|
+
|
332
|
+
def test_json_formatting(self) -> None:
|
333
|
+
"""Test JSON is properly formatted."""
|
334
|
+
formatter = JSONReportFormatter()
|
335
|
+
metrics = create_test_metrics()
|
336
|
+
|
337
|
+
report = formatter.format(metrics)
|
338
|
+
|
339
|
+
# Should be indented
|
340
|
+
assert "\n " in report
|
341
|
+
|
342
|
+
# Should be valid JSON
|
343
|
+
try:
|
344
|
+
json.loads(report)
|
345
|
+
except json.JSONDecodeError:
|
346
|
+
pytest.fail("Invalid JSON generated")
|
347
|
+
|
348
|
+
def test_empty_json_report(self) -> None:
|
349
|
+
"""Test empty JSON report."""
|
350
|
+
formatter = JSONReportFormatter()
|
351
|
+
metrics = ModuleMetrics("empty")
|
352
|
+
|
353
|
+
report = formatter.format(metrics)
|
354
|
+
data = json.loads(report)
|
355
|
+
|
356
|
+
assert data["module_name"] == "empty"
|
357
|
+
assert len(data["passes"]) == 0
|
358
|
+
assert len(data["functions"]) == 0
|
359
|
+
|
360
|
+
def test_json_before_after_stats(self) -> None:
|
361
|
+
"""Test JSON before/after statistics."""
|
362
|
+
formatter = JSONReportFormatter()
|
363
|
+
metrics = create_test_metrics()
|
364
|
+
|
365
|
+
report = formatter.format(metrics)
|
366
|
+
data = json.loads(report)
|
367
|
+
|
368
|
+
pass1 = data["passes"][0]
|
369
|
+
assert pass1["before_stats"]["instructions"] == 100
|
370
|
+
assert pass1["after_stats"]["instructions"] == 85
|
371
|
+
assert pass1["before_stats"]["blocks"] == 10
|
372
|
+
assert pass1["after_stats"]["blocks"] == 8
|