Packages
metastatic
0.20.1
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.3
0.20.2
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Cross-language code meta-model library using unified MetaAST representation. Parse, transform, and translate code across Python, Elixir, Ruby, Erlang, Haskell, and more via a shared three-tuple AST format.
Current section
Files
Jump to
Current section
Files
lib/metastatic/adapters/haskell/subprocess.ex
defmodule Metastatic.Adapters.Haskell.Subprocess do
@moduledoc """
Manages subprocess communication with the Haskell parser.
Uses Stack to execute the parser binary built from `priv/parsers/haskell/`.
"""
@parser_dir Path.expand("../../../../priv/parsers/haskell", __DIR__)
@doc """
Parse Haskell source code by invoking the Stack-based parser subprocess.
Returns `{:ok, ast}` on success or `{:error, reason}` on failure.
## Examples
iex> Metastatic.Adapters.Haskell.Subprocess.parse("1 + 2")
{:ok, %{"type" => "infix", ...}}
"""
@spec parse(String.t()) :: {:ok, map()} | {:error, String.t()}
def parse(source) when is_binary(source) do
parser_command =
"cd #{@parser_dir} && printf %s \"#{escape_source(source)}\" | stack exec parser"
case System.cmd("sh", ["-c", parser_command], stderr_to_stdout: true) do
{output, 0} ->
handle_parser_output(output)
{error_output, _exit_code} ->
{:error, "Haskell parser failed: #{inspect(error_output)}"}
end
end
# Handle parser JSON output
defp handle_parser_output(output) do
case Jason.decode(output) do
{:ok, %{"status" => "ok", "ast" => ast}} when not is_nil(ast) ->
{:ok, ast}
{:ok, %{"status" => "error", "errorMessage" => message}} ->
{:error, "Parse error: #{message}"}
{:ok, %{"status" => "ok", "ast" => nil}} ->
{:error, "Parse error: empty AST returned"}
{:error, _} = error ->
{:error, "Failed to decode parser output: #{inspect(error)}"}
end
end
# Escape source for shell command
defp escape_source(source) do
source
|> String.replace("\\", "\\\\")
|> String.replace("\"", "\\\"")
|> String.replace("$", "\\$")
|> String.replace("`", "\\`")
end
end