Module: Kumi::Dev::PrettyPrinter
- Defined in:
- lib/kumi/dev/pretty_printer.rb
Constant Summary collapse
- IR_GRAPH_STAGES =
The IR-graph stages differ only in the pass to stop after and the state key to render — one row each instead of a copy-pasted method. :label is what the “Missing …” diagnostic prints.
{ dfir: { stop_after: "DFValidatePass", state_key: :df_module_unoptimized, label: "DFIR" }, dfir_optimized: { stop_after: "DFValidatePass", state_key: :df_module, label: "optimized DFIR" }, vecir: { stop_after: "VecValidatePass", state_key: :vec_module, label: "VecIR" }, loopir: { stop_after: "LoopValidatePass", state_key: :loop_module, label: "LoopIR" } }.freeze
- ANALYZED_STAGES =
Stages that run the full analyzer (side tables on) and render one state key. :render maps the state value to text.
{ schema_ruby: { state_key: :ruby_codegen_files, render: ->(v) { v["codegen.rb"] } }, schema_javascript: { state_key: :javascript_codegen_files, render: ->(v) { v["codegen.mjs"] } } }.freeze
Class Method Summary collapse
- .analyze_schema(path, stop_after: nil, **opts) ⇒ Object
- .format_node(name, node, indent) ⇒ Object
- .generate_analyzed(path, state_key:, render:) ⇒ Object
- .generate_ast(path) ⇒ Object
- .generate_input_plan(path) ⇒ Object
- .generate_ir(path) ⇒ Object
- .generate_ir_graph(path, stop_after:, state_key:, label:) ⇒ Object
- .generate_nast(path) ⇒ Object
-
.generate_runtime(path) ⇒ Object
Executes the generated Ruby + JS against the golden’s input.json and snapshots the outputs (also asserting Ruby == JS).
- .generate_snast(path) ⇒ Object
- .print_input_plan(metadata, indent = 0) ⇒ Object
- .print_ir_graph(graph) ⇒ Object
- .run(kind, path) ⇒ Object
- .with_stop_after(pass_name) ⇒ Object
Class Method Details
.analyze_schema(path, stop_after: nil, **opts) ⇒ Object
159 160 161 162 163 164 165 166 167 168 |
# File 'lib/kumi/dev/pretty_printer.rb', line 159 def analyze_schema(path, stop_after: nil, **opts) schema, = Kumi::Frontends.load(path: path) if stop_after with_stop_after(stop_after) do Kumi::Analyzer.analyze!(schema, **opts) end else Kumi::Analyzer.analyze!(schema, **opts) end end |
.format_node(name, node, indent) ⇒ Object
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 |
# File 'lib/kumi/dev/pretty_printer.rb', line 57 def format_node(name, node, indent) prefix = " " * indent result = [] # Node header with type and container header = "#{prefix}#{name}: #{node.type}" header += " (#{node.container})" if node.container != :scalar header += " access_mode=#{node.access_mode}" if node.access_mode result << header # Child steps if any if node.child_steps && !node.child_steps.empty? node.child_steps.each do |child_name, steps| steps_str = steps.map { |s| s[:kind] }.join(" → ") result << "#{prefix} └─> #{child_name}: #{steps_str}" end end # Recursively print children if node.children && !node.children.empty? node.children.each do |child_name, child_node| result << format_node(child_name, child_node, indent + 1) end end result.join("\n") end |
.generate_analyzed(path, state_key:, render:) ⇒ Object
138 139 140 141 142 143 |
# File 'lib/kumi/dev/pretty_printer.rb', line 138 def generate_analyzed(path, state_key:, render:) schema, = Kumi::Frontends.load(path: path) res = Kumi::Analyzer.analyze!(schema, side_tables: true) value = res.state[state_key] or return nil render.call(value) end |
.generate_ast(path) ⇒ Object
37 38 39 40 |
# File 'lib/kumi/dev/pretty_printer.rb', line 37 def generate_ast(path) schema, = Kumi::Frontends.load(path: path) Kumi::Support::SExpressionPrinter.print(schema) end |
.generate_input_plan(path) ⇒ Object
42 43 44 45 46 47 |
# File 'lib/kumi/dev/pretty_printer.rb', line 42 def generate_input_plan(path) res = analyze_schema(path, stop_after: "InputAccessPlannerPass") return nil unless res.state[:input_metadata] print_input_plan(res.state[:input_metadata]) end |
.generate_ir(path) ⇒ Object
85 86 87 88 89 90 91 |
# File 'lib/kumi/dev/pretty_printer.rb', line 85 def generate_ir(path) schema, = Kumi::Frontends.load(path: path) res = Kumi::Analyzer.analyze!(schema) return nil unless res.state[:ir_module] Kumi::Support::IRRender.to_text(res.state[:ir_module], analysis_state: res.state) end |
.generate_ir_graph(path, stop_after:, state_key:, label:) ⇒ Object
132 133 134 135 136 |
# File 'lib/kumi/dev/pretty_printer.rb', line 132 def generate_ir_graph(path, stop_after:, state_key:, label:) res = analyze_schema(path, stop_after: stop_after, side_tables: true) graph = res.state[state_key] or raise "Missing #{label} for #{path}" print_ir_graph(graph) end |
.generate_nast(path) ⇒ Object
93 94 95 96 97 |
# File 'lib/kumi/dev/pretty_printer.rb', line 93 def generate_nast(path) res = analyze_schema(path, stop_after: "NormalizeToNASTPass") mod = res.state[:nast_module] or raise "Missing NAST for #{path}" Kumi::Support::NASTPrinter.print(mod) end |
.generate_runtime(path) ⇒ Object
Executes the generated Ruby + JS against the golden’s input.json and snapshots the outputs (also asserting Ruby == JS). Returns nil when the golden has no input.json (text-only). See GoldenRuntime.
148 149 150 151 |
# File 'lib/kumi/dev/pretty_printer.rb', line 148 def generate_runtime(path) require_relative "golden_runtime" GoldenRuntime.snapshot(path) end |
.generate_snast(path) ⇒ Object
99 100 101 102 103 |
# File 'lib/kumi/dev/pretty_printer.rb', line 99 def generate_snast(path) res = analyze_schema(path, stop_after: "SNASTPass") mod = res.state[:snast_module] or raise "Missing SNAST for #{path}" Kumi::Support::SNASTPrinter.print(mod) end |
.print_input_plan(metadata, indent = 0) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/kumi/dev/pretty_printer.rb', line 49 def print_input_plan(, indent = 0) lines = [] .each do |name, node| lines << format_node(name, node, indent) end lines.join("\n") end |
.print_ir_graph(graph) ⇒ Object
153 154 155 156 157 |
# File 'lib/kumi/dev/pretty_printer.rb', line 153 def print_ir_graph(graph) io = StringIO.new Kumi::IR::Printer.print(graph, io: io) io.string end |
.run(kind, path) ⇒ Object
11 12 13 14 15 16 17 |
# File 'lib/kumi/dev/pretty_printer.rb', line 11 def run(kind, path) method_name = "generate_#{kind}" raise "Unknown pretty print kind: #{kind}" unless respond_to?(method_name) output = send(method_name, path) puts output if output end |
.with_stop_after(pass_name) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/kumi/dev/pretty_printer.rb', line 19 def with_stop_after(pass_name) saved = { "KUMI_STOP_AFTER" => ENV.fetch("KUMI_STOP_AFTER", nil), "KUMI_CHECKPOINT" => ENV.fetch("KUMI_CHECKPOINT", nil), "KUMI_RESUME_FROM" => ENV.fetch("KUMI_RESUME_FROM", nil), "KUMI_RESUME_AT" => ENV.fetch("KUMI_RESUME_AT", nil) } ENV["KUMI_STOP_AFTER"] = pass_name ENV["KUMI_CHECKPOINT"] = "0" ENV.delete("KUMI_RESUME_FROM") ENV.delete("KUMI_RESUME_AT") yield ensure saved.each { |k, v| v ? ENV[k] = v : ENV.delete(k) } end |