Packages
metastatic
0.26.0
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/cure.ex
defmodule Metastatic.Adapters.Cure do
@moduledoc """
Metastatic adapter for the Cure programming language.
Transforms Cure source code to/from MetaAST representation using
Cure's lexer and parser pipeline.
## Usage
{:ok, doc} = Metastatic.Adapter.abstract(Metastatic.Adapters.Cure, source, :cure)
{:ok, source} = Metastatic.Adapter.reify(Metastatic.Adapters.Cure, doc)
"""
# NOTE: Does not declare @behaviour Metastatic.Adapter because the Cure
# compiler modules live in a separate Mix project and are not available
# at Metastatic compile time. The adapter is used at runtime only.
alias Metastatic.{Adapters.Cure.FromMeta, Adapters.Cure.ToMeta, Document}
@doc "Parse Cure source code into a MetaAST Document."
@spec abstract(String.t(), atom(), keyword()) :: {:ok, Document.t()} | {:error, term()}
@dialyzer {:nowarn_function, abstract: 3}
def abstract(source, language \\ :cure, opts \\ [])
# credo:disable-for-lines:12
def abstract(source, _language, opts) when is_binary(source) and is_list(opts) do
# The `{:ok, ...}` branch is only reachable when the Cure compiler
# is linked in at runtime. Using apply/3 prevents the Elixir type
# system from statically resolving the return type of from_source/2
# and emitting a "pattern will never match" warning for the fallback
# clause compiled when the Cure compiler is absent.
with {:ok, ast, metadata} <- apply(ToMeta, :from_source, [source, opts]) do
{:ok, Document.new(ast, :cure, metadata, source)}
end
end
@doc "Convert a Cure MetaAST Document back to Cure source."
@spec reify(Document.t()) :: {:ok, String.t()} | {:error, term()}
def reify(%Document{ast: ast, language: :cure}) do
source = FromMeta.to_source(ast)
{:ok, source}
end
def reify(_), do: {:error, "Not a Cure document"}
@dialyzer {:nowarn_function, round_trip: 1}
@doc "Round-trip: parse source to MetaAST, then back to source."
@spec round_trip(String.t()) :: {:ok, String.t()} | {:error, term()}
def round_trip(source) do
with {:ok, doc} <- abstract(source, :cure), do: reify(doc)
end
end