Current section
Files
Jump to
Current section
Files
lib/mix/tasks/firebird.target.inspect.ex
defmodule Mix.Tasks.Firebird.Target.Inspect do
@moduledoc """
Inspect the compilation pipeline for a specific source file.
Shows the output of each pipeline stage, useful for debugging
compilation issues.
## Usage
# Inspect all stages for a file
mix firebird.target.inspect lib/math.ex
# Inspect a specific stage
mix firebird.target.inspect lib/math.ex --stage ir
mix firebird.target.inspect lib/math.ex --stage wat
mix firebird.target.inspect lib/math.ex --stage type_infer
# Run with optimizations
mix firebird.target.inspect lib/math.ex --optimize --tco
## Stages
- `parse` - Elixir AST
- `ir` - Firebird IR
- `optimize` - Optimized IR
- `type_infer` - Typed IR
- `validate` - Validation result
- `wat` - WebAssembly Text Format
- `wasm` - WASM binary info
"""
use Mix.Task
@shortdoc "Inspect WASM compilation pipeline stages"
@switches [
stage: :string,
optimize: :boolean,
tco: :boolean,
inline: :boolean
]
@aliases [
s: :stage
]
@impl Mix.Task
def run(args) do
{opts, paths, _} = OptionParser.parse(args, switches: @switches, aliases: @aliases)
if Enum.empty?(paths) do
Mix.raise("Usage: mix firebird.target.inspect <file.ex> [--stage <stage>]")
end
file = hd(paths)
unless File.regular?(file) do
Mix.raise("File not found: #{file}")
end
source = File.read!(file)
stage = Keyword.get(opts, :stage)
pipeline_opts = Keyword.take(opts, [:optimize, :tco, :inline])
Mix.shell().info("π Firebird Pipeline Inspector")
Mix.shell().info(" File: #{file}")
Mix.shell().info("")
if stage do
stage_atom = String.to_atom(stage)
output = Firebird.Target.Pipeline.inspect_stage(stage_atom, source, pipeline_opts)
Mix.shell().info(output)
else
# Show all stages
case Firebird.Target.Pipeline.run_all(source, pipeline_opts) do
{:ok, results} ->
Mix.shell().info(" β
Parse: AST generated")
Mix.shell().info(
" β
IR: #{results.ir.name} (#{length(results.ir.functions)} functions)"
)
Mix.shell().info(" β
Validated")
Enum.each(results.typed_ir.functions, fn f ->
params =
if f.type, do: Enum.map(f.type.params, &to_string/1) |> Enum.join(", "), else: "?"
ret = if f.type, do: to_string(f.type.return), else: "?"
Mix.shell().info(" #{f.name}(#{params}) -> #{ret}")
end)
Mix.shell().info(" β
WAT: #{byte_size(results.wat)} bytes")
Mix.shell().info(" β
WASM: #{byte_size(results.wasm)} bytes")
{:error, reason} ->
Mix.shell().error(" β Pipeline failed: #{inspect(reason)}")
end
end
:ok
end
end