Orasund / leaf-lang / Leaf

This is the main module for working with Leaf scripts.

Basic Evaluation

To run this script in Elm you need to call Leaf.run.

import Leaf exposing (Value(..))

"\"Hello World\""
    |> Leaf.run Dict.empty
    --> Ok (StringVal "Hello World",Dict.empty)


type alias Exp =
Internal.Language.Exp

A leaf script is internally translated into an Exp


type Value
    = NullVal
    | StringVal String
    | BoolVal Basics.Bool
    | FloatVal Basics.Float
    | IntVal Basics.Int
    | ListVal (List Value)
    | ObjectVal (Dict String Value)
    | FunctionVal (Maybe String) Exp
    | ExtensionVal (Value -> Result String Value)

Every Leaf script evaluates to a Value

run : Dict String Field -> String -> Result String ( Value, Dict String Field )

Evaluates a Leaf script. The dictionary may contain fields that can be called from inside the Leaf script.

import Leaf exposing (Value(..))
import Dict exposing (Dict)

context : Dict String Field
context =
    [ StringVal "World" |> Leaf.field "name"
    , (\s2 s1 -> StringVal (s1 ++ s2) )
        |> Leaf.binaryFun
            (Leaf.typed Leaf.asString)
            (Leaf.typed Leaf.asString)
        |> Leaf.field "append"
    ]
    |> Dict.fromList

"\"Hello \" .append name"
    |> Leaf.run context
    --> Ok (StringVal "Hello World",context)

Context-Sensitive Evaluation

You can also evaluate context sensitive Leaf scripts.

import Leaf exposing (Value(..))
import Dict exposing (Dict)
import Leaf.Core as Core

context : Dict String Field
context =
    [ StringVal "World" |> Leaf.field "name"
    , (\s2 s1 -> StringVal (s1 ++ s2))
        |> Leaf.binaryFun (Leaf.typed Leaf.asString)
            (Leaf.typed Leaf.asString)
        |> Leaf.field "append"
    ]
        |> Dict.fromList
        |> Leaf.addExposed Core.package

"\"Hello \" .append name"
    |> Leaf.run context
    --> Ok (StringVal "Hello World",context)


type alias Field =
Internal.Semantics.Field

Internal type for fields

field : String -> Value -> ( String, Field )

Constructs a context field. Use this in combination with Dict.fromList

mutField : String -> Value -> ( String, Field )

Constructs a mutable context field. Use this in combination with Dict.fromList

unaryFun : ((a -> Value) -> Value) -> (a -> Value) -> Value

Turns an Elm function with one argument into a Leaf extension

import Leaf.Core as Core

(Core.isNull >> BoolVal)
    |> Leaf.unaryFun Leaf.untyped
    |> Leaf.field "isNull"

binaryFun : ((a -> Value) -> Value) -> ((b -> Value) -> Value) -> (a -> b -> Value) -> Value

Turns an Elm function with two argument into a Leaf extension

import Leaf.Core as Core
import Leaf exposing (Field)

(\v1 v2 -> Core.equal v1 v2 |> BoolVal)
    |> Leaf.binaryFun Leaf.untyped Leaf.untyped
    |> Leaf.field "equal"

trinaryFun : ((a -> Value) -> Value) -> ((b -> Value) -> Value) -> ((c -> Value) -> Value) -> (a -> b -> c -> Value) -> Value

Turns an Elm function with three argument into a Leaf extension

import Leaf.Core as Core
import Leaf exposing (Field)

(\v1 v2 -> Core.equal v1 v2 |> BoolVal)
    |> Leaf.binaryFun Leaf.untyped Leaf.untyped
    |> Leaf.field "equal"

untyped : (Value -> Value) -> Value

States that an extension function takes an untyped value

import Leaf.Core as Core

(Core.isNull >> BoolVal)
    |> Leaf.unaryFun Leaf.untyped
    |> Leaf.field "isNull"

typed : (Value -> Result String a) -> (a -> Value) -> Value

States that an extension function takes a typed value

import Leaf.Core as Core

Core.if_
    |> Leaf.trinaryFun (Leaf.typed Leaf.asBool) Leaf.untyped Leaf.untyped
    |> Leaf.field "if"

asNull : Value -> Result String ()

Converts a Leaf null into an Elm unit

asBool : Value -> Result String Basics.Bool

Converts a Leaf bool into an Elm bool

asString : Value -> Result String String

Converts a Leaf string into an Elm string

asFloat : Value -> Result String Basics.Float

Converts a Leaf float into an Elm float

asInt : Value -> Result String Basics.Int

Converts a Leaf int into an Elm int

asNullable : (Value -> Result String a) -> Value -> Result String (Maybe a)

converts a Leaf value into an Elm maybe type

asAnyList : Value -> Result String (List Value)

converts a Leaf list into an Elm list of values

asList : (Value -> Result String a) -> Value -> Result String (List a)

converts a Leaf list into an Elm list type

asObject : Value -> Result String (Dict String Value)

converts a Leaf object into an Elm dict

asFunction : Value -> Result String ( Maybe String, Exp )

converts a Leaf functions into an Elm tuple

asExtension : Value -> Result String (Value -> Result String Value)

converts a Leaf extension into an Elm function

Utility Functions

toString : Value -> String

returns a readable string representation of a value

addPackage : String -> Dict String Field -> Dict String Field -> Dict String Field

Adds a package to a context and applies the naming convention Package::functionName.

addExposed : Dict String Field -> Dict String Field -> Dict String Field

Adds a package and exposes all function. This should only be used for essential packages.

import Dict

addExposed
    --> Dict.union