Print elm-syntax declarations as moonbit code.
To try it out, you can
run this script.
import Elm.Parser
import ElmSyntaxToMoonbit
"""module Sample exposing (..)
plus2 : Float -> Float
plus2 n =
n + ([ 2.0 ] |> List.sum)
"""
|> Elm.Parser.parseToFile
|> Result.mapError (\_ -> "failed to parse elm source code")
|> Result.map
(\syntaxModule ->
[ syntaxModule ]
|> ElmSyntaxToMoonbit.modules
|> .declarations
|> ElmSyntaxToMoonbit.moonbitDeclarationsToModuleString
)
-->
Ok """...
pub fn sample_plus2(n: Double) -> Double {
basics_add(n, list_sum_float(@list.of([2.0])))
}
"""- not supported are
- ports that use non-json values like
port sendMessage : String -> Cmd msg, glsl, phantom types,==on a generic value elm/file,elm/http,elm/browser,elm-explorations/markdown,elm-explorations/webgl,elm-explorations/benchmark,elm/regex(because no support inmoonbitlang/core),elm-explorations/linear-algebra(because no support inmoonbitlang/core)Task,Process,Platform.Task,Platform.ProcessId,Platform.Router,Platform.sendToApp,Platform.sendToSelf,Random.generate,Time.now,Time.every,Time.here,Time.getZoneName,Bytes.getHostEndianness- extensible record types outside of module-level value/function declarations. For example, these declarations might not work:
Allowed is only record extension in module-level value/functions, annotated or not:
-- in variant value type Named rec = Named { rec | name : String } -- in let type, annotated or not let getName : { r | name : name } -> name
In the non-allowed cases listed above, we assume that you intended to use a regular record type with only the extension fields which can lead to moonbit compile errors if you actually pass in additional fields.userId : { u | name : String, server : Domain } -> String
- The transpiled list type is not yet comparable (unlike elm lists), it is implemented but not yet published, see moonbitlang/core#2757
- elm's
Char.toLocale[Case]functions will just behave likeChar.to[Case] - elm's
VirtualDom/Html/Svg.lazyNfunctions will still exist for compatibility but they will behave just like constructing them eagerly
- ports that use non-json values like
- dependencies cannot internally use the same module names as the transpiled project
- the resulting code might not be readable or even conventionally formatted and comments are not preserved
Please report any issues you notice <3
- it has first-class support for wasm (and native)
- it feels like a superset of elm which makes transpiling and "ffi" easier
- it supposedly has fast compile times (I have yet to verify this claim)
- the language is bloated
- the language is very young and tooling like the build CLI are fragile
- the language's promotion has made overly big claims and has the classic AI bullshit
- the ecosystem is tiny so you will likely need to write your own FFI wrappers and similar
An example can be found in example-hello-world/.
In your elm project, add moon.pkg.json
{"is-main": true}and moon.mod.json
{"name": "your_project_name"}(If you know of a simpler setup, please open an issue)
and a file main.mbt that uses elm.mbt:
mod elm
print(your_module_your_function("yourInput"))where your_module_your_function(firstArgument, secondArgument) is the transpiled elm function Your.Module.yourFunction firstArgument secondArgument. (If the value/function contains extensible records, search for your_module_your_function_ with the underscore to see the different specialized options)
Run with
cargo runIf something unexpected happened, please report an issue.
In the transpiled code, you will find these types:
- elm
Bool(TrueorFalse) → moonbitBool(trueorfalse),Char('a') →Char('a'),( Bool, Char )→( Bool, Char ) - elm
Ints will be of typeInt64. Create and match by appendingLto any number literal or usingInt::to_int64/Int64::from_int - elm
Floats will be of typef64. Create and match by using any number literal with a decimal point - elm
Strings (like"a") will be of the custom typeStringString. Create from literals or other string slices with (StringString::One("a")). Match withyour_string if string_string_string_equals_stringing(your_string, "some string") - elm records like
{ y : Float, x : Float }will be of typeGeneratedXY<f64, f64>with the fields sorted and can be constructed and matched with{ x: _, y: _ }.record.xaccess also works - elm
Lists will be of type@list.List. Create and match with the help of@list/List:: - elm
Arrays will be of type@immut/array.Array. Create and match with the helpers in@immut/array - elm
Sets will be of type@immut/sorted_set.SortedSet. Create and match with the helpers in@immut/sorted_set - elm
Dicts will be of type@immut/sorted_map.SortedMap. Create and match with the helpers in@immut/sorted_map - elm
Json.Encode.Value/Json.Decode.Values will be of typeJson. Create and match with the help of@json./Json:: - elm
Bytes.Byteswill be of typeBytes. Create and match with the help of@bytes/Bytes:: - a transpiled elm app does not run itself.
An elm main
Platform.workerprogram type will literally just consist of fieldsinit,updateandsubscriptionswhere subscriptions/commands are returned as a list ofPlatformSubSingle/PlatformCmdSinglewith possible elm subscriptions/commands in a choice type. It's then your responsibility as "the platform" to perform effects, create events and manage the state. For an example see example-worker-blocking/ & example-worker-concurrent/
- try and benchmark switching
Stringrepresentation fromOne &str | Append String Stringto(StringBuilder) -> StringBuilder - if lambda is called with a function, always inline that function
- your idea 👀