Current section
Files
Jump to
Current section
Files
lib/mix/tasks/firebird.analyze.ex
defmodule Mix.Tasks.Firebird.Analyze do
@moduledoc """
Analyze Elixir source files for WASM compilability.
Shows which functions can be compiled, estimates complexity,
and provides optimization suggestions.
## Usage
mix firebird.analyze lib/wasm_modules/math.ex
mix firebird.analyze lib/wasm_modules/
## Output
For each file, shows:
- Module name
- Function list with compilability status
- Recursion analysis (tail-recursive, exponential, etc.)
- Optimization suggestions
"""
use Mix.Task
@shortdoc "Analyze Elixir files for WASM compilability"
@impl Mix.Task
def run(args) do
{_opts, paths, _} = OptionParser.parse(args, switches: [], aliases: [])
if Enum.empty?(paths) do
Mix.raise("No input files specified. Usage: mix firebird.analyze <file_or_dir> [...]")
end
files = resolve_files(paths)
if Enum.empty?(files) do
Mix.raise("No .ex or .exs files found in the specified paths")
end
Mix.shell().info("π Firebird WASM Analyzer")
Mix.shell().info("")
Enum.each(files, fn file ->
analyze_file(file)
end)
end
defp resolve_files(paths) do
Enum.flat_map(paths, fn path ->
cond do
File.dir?(path) -> Path.wildcard(Path.join(path, "**/*.{ex,exs}"))
File.regular?(path) -> [path]
true -> []
end
end)
|> Enum.sort()
|> Enum.uniq()
end
defp analyze_file(path) do
Mix.shell().info("π #{path}")
case Firebird.Compiler.Analyzer.analyze_file(path) do
{:ok, analysis} ->
print_analysis(analysis)
{:error, reason} ->
Mix.shell().error(" β Cannot analyze: #{inspect(reason)}")
end
Mix.shell().info("")
end
defp print_analysis(analysis) do
status = if analysis.compilable, do: "β
Compilable", else: "β Partial"
Mix.shell().info(" Module: #{analysis.module} (#{status})")
for func <- analysis.functions do
icon = if func.compilable, do: "β
", else: "β"
rec_info =
cond do
func.tail_recursive -> " [tail-recursive]"
func.recursive -> " [recursive]"
true -> ""
end
Mix.shell().info(
" #{icon} #{func.name}/#{func.arity} #{func.estimated_complexity}#{rec_info}"
)
for issue <- func.issues do
Mix.shell().info(" β #{issue}")
end
end
if Enum.any?(analysis.suggestions) do
Mix.shell().info("")
Mix.shell().info(" π‘ Suggestions:")
for sug <- analysis.suggestions do
Mix.shell().info(" β’ #{sug}")
end
end
end
end