gleam-parser-morphir

    Optional Morphir target profile for moonrockz/gleam-parser

    gleam
    parser
    morphir
    Download zip
    Author
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    25 days ago
    Downloads
    55

    #Morphir target profile

    See the README with tested examples for installation, configuration, external functions and types, composition, and releases.

    Release history is in CHANGELOG.md.

    #Morphir target profile for gleam-parser

    This optional MoonBit module adds the morphir target to the core parser. It has its own release identity, moonrockz/gleam-parser-morphir@0.1.1, and requires core parser 0.5.0. Installing the core does not install this module.

    Install it with moon add moonrockz/gleam-parser-morphir. In moon.pkg, import:

    import { "moonrockz/gleam-parser-morphir" @morphir, }

    The profile re-exports the common core APIs used below. These functions keep standard Gleam as their default. If you need other core APIs, also run moon add moonrockz/gleam-parser@0.5.0 and import that package as @gleam.

    #Parse a Morphir external function

    Enable the profile explicitly. @external retains the target, module, symbol, and source location. It does not restrict the definition to Morphir.

    ///|
    test "mr: retain a Morphir function binding" {
    let dialect = @morphir.Dialect::gleam_1_19().with_profile(@morphir.profile())
    let config = { ..@morphir.Config::default(), dialect, }
    let source = "@external(morphir, \"morphir/sdk/list\", \"length\")\npub fn length(xs: List(a)) -> Int\n"
    let result = @morphir.parse_text(source, config~)
    assert_eq(result.has_errors(), false)
    guard result.module_.definitions[0].definition is Function(function) else {
    fail("expected a function")
    }
    let target = dialect.targets.resolve("morphir").unwrap()
    let binding = function.external_for(target).unwrap()
    assert_eq(binding.module_, "morphir/sdk/list")
    assert_eq(binding.function, "length")
    assert_eq(result.module_.definitions[0].target, None)
    assert_eq(@morphir.format_parsed(result), source)
    assert_eq(
    @morphir.decode_extended(@morphir.encode_extended(result)).parsed,
    result.parsed(),
    )
    }

    #Retain a target restriction and an external type

    Use @target(morphir) for a definition's target restriction. Parsing retains all definitions. A consumer decides which target to translate later.

    ///|
    test "mr: external types and restrictions stay distinct" {
    let dialect = @morphir.Dialect::gleam_1_19().with_profile(@morphir.profile())
    let config = { ..@morphir.Config::default(), dialect, }
    let result = @morphir.parse_text(
    "@target(morphir)\n@external(morphir, \"example/domain\", \"CustomerId\")\npub type CustomerId\n",
    config~,
    )
    assert_eq(result.has_errors(), false)
    assert_eq(
    result.module_.definitions[0].target.map(t => t.name()),
    Some("morphir"),
    )
    guard result.module_.definitions[0].definition is CustomType(type_) else {
    fail("expected an external type")
    }
    assert_eq(type_.externals.all()[0].external.function, "CustomerId")
    assert_eq(
    @morphir.parse_text("@target(morphir) pub const x = 1").has_errors(),
    true,
    )
    assert_eq(dialect.knows_target("go"), false)
    }

    #Compose with another provider

    Other modules use the same public APIs. Conflicting registrations raise ProfileError; no registration silently overrides another.

    ///|
    test "mr: compose a separately defined target" {
    let scala = @morphir.Profile(
    "example/scala@1",
    [@morphir.Target::extension("scala")][:],
    )
    let dialect = @morphir.Dialect::gleam_1_19()
    .with_profile(@morphir.profile())
    .with_profile(scala)
    assert_eq(dialect.knows_target("morphir"), true)
    assert_eq(dialect.knows_target("scala"), true)
    let available = @morphir.Profiles([@morphir.profile(), scala][:])
    let config = @morphir.Config::from_toml(
    "[parser]\nprofiles = [\"moonrockz/gleam-parser-morphir@0.1.1\", \"example/scala@1\"]\n",
    profiles=available,
    ).to_config(@morphir.Config::default())
    assert_eq(config.dialect, dialect)
    }

    This module supplies no Morphir backend, symbol resolution, or foreign-call execution. Module and symbol strings are opaque. Use extended JSON to retain Morphir metadata. Compiler-compatible export raises NonStandardTarget. See the core target profile cookbook and migration guide.

    #Release this module

    Publish the required core version first. Run the Release Morphir profile workflow on the commit to release. Verify the module version on mooncakes.io, then create the morphir-v0.1.1 GitHub release at the same commit. Future profile releases update this module's manifest, version(), profile identity, and notes independently of the core version.

    Config

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    Dialect

    Dialects: what the parser accepts (Dialect::gleam_1_19() is the default) and the deprecation Rules it warns about.

    Profile

    Named optional registrations and the application's available-profile registry.

    Profiles

    Named optional registrations and the application's available-profile registry.

    Target

    Standard and validated extension target identities.

    decode_extended

    Decode extended JSON with its embedded registry. No optional module is loaded. Reject unsupported versions, invalid registrations, unknown target references, and duplicate bindings with a source path in DecodeError.

    decode_parsed

    Decode a module with its trivia positions and parse-time warnings. Raise DecodeError with the field path for malformed JSON values.

    encode_extended

    Encode a parse result in the versioned extended JSON format. Record the dialect, profile identities, and registry used to parse the source. This preserves extension targets and bindings that compiler-compatible export rejects.

    test {
    let orbit = @gleam.Target::extension("orbit")
    let config = {
    ..@gleam.Config::default(),
    dialect: @gleam.Dialect::gleam_1_19().register_target(orbit),
    }
    let result = @gleam.parse_text("@target(orbit) const answer = 42", config~)
    let document = @gleam.decode_extended(@gleam.encode_extended(result))
    assert_eq(document.parsed, result.parsed())
    }

    encode_parsed

    Encode a module with its trivia positions and parse-time warnings. Raise ExportError for extension targets; use encode_extended to retain them. Use canonical to write the JSON in the oracle's key order.

    test {
    let parsed = @gleam.parse_text("const x = 1").parsed()
    assert_eq(@gleam.decode_parsed(@gleam.encode_parsed(parsed)), parsed)
    }

    format

    Format Gleam source as gleam format does (see @format.format): 80 columns, two spaces of indentation, comments and empty lines kept. Raises ParseFailed with the error diagnostics when the text has a syntax error.

    test {
    inspect(@gleam.format("const x = 1\n"), content="const x = 1\n")
    }

    format_parsed

    Format a parse result (see @format.format_parsed).

    parse_text

    Parse Gleam source text into a module, with recovery per definition. config sets the dialect and the fuel budget; see Config.

    test {
    let r = @gleam.parse_text("pub fn main() {\n io.println(\"hi\")\n}\n")
    inspect(r.module_.definitions.length(), content="1")
    inspect(r.has_errors(), content="false")
    }

    profile

    Construct the optional Morphir profile through the public core API. It registers only morphir. Standard targets stay available; other extension targets stay unregistered. Importing this module does not enable the profile. Pass it to Dialect::with_profile explicitly. The registration supplies syntax and AST metadata, not a Morphir backend. Module and symbol strings are opaque references interpreted by consumers.

    test {
    let dialect = @morphir.Dialect::gleam_1_19().with_profile(@morphir.profile())
    let config = { ..@morphir.Config::default(), dialect, }
    let result = @morphir.parse_text(
    "@target(morphir) pub const answer = 42",
    config~,
    )
    assert_eq(result.has_errors(), false)
    assert_eq(dialect.knows_target("scala"), false)
    }

    version

    fn version() -> String

    Return the Morphir profile's release version. It is independent of the core parser version. This module requires core parser 0.5.0 or later.

    Source Files