trick
Code generated using trick is built up by combining expressions and
statements into a module.
The trick API is designed to make it as hard as possible to make mistakes
in your generation.
A trick code generator will look something like this:
use pi <- trick.constant("pi", trick.Private, trick.float(3.14))
use circle_area <- trick.function("circle_area", trick.Public, {
use radius <- trick.parameter("radius", trick.float_type())
trick.function_body({
use radius_squared <- trick.variable(
"radius_squared",
trick.multiply_float(radius, radius),
)
trick.expression(trick.multiply_float(radius_squared, pi))
})
})
trick.end_module()
The above code, when passed to to_string, will produce the
following code:
const pi = 3.14
pub fn circle_area(radius: Float) -> Float {
let radius_squared = radius *. radius
radius_squared *. pi
}
The called functions more or less mimic the structure of the resulting code, with the exception for a few boilerplate functions needed to convert between types to appease the Gleam type system.
Expression generation is pretty intuitive and straightforward, but some of the functions for creating custom types and top-level functions can get a bit complicated due to type system limitations. See the documentation of individual functions for full explanations of how they are used.
Table of contents
Definitions
Statements
Expressions
Expressionintfloatstringboolniladdadd_floatsubtractsubtract_floatmultiplymultiply_floatdividedivide_floatremainderconcatenateandorequalnot_equalless_thanless_than_floatless_than_or_equalless_than_or_equal_floatgreater_thangreater_than_floatgreater_than_or_equalgreater_than_or_equal_floatnegate_intnegate_boollistprependtupletuple_indexpanic_todo_echo_anonymouscall
Types
TypeConcreteTypeFieldMapErrorint_typefloat_typestring_typebool_typenil_typebit_array_typeutf_codepoint_typelist_typetuple_typefunction_typegeneric
Best practises
To avoid confusion, it’s usually best if you name any variables after their names in the generated code. For example, if you’re defining a variable, assign it to a variable of the same name in your generator code:
// DO:
use my_variable <- trick.variable("my_variable", trick.int(1))
// DON'T:
use number_one <- trick.variable("my_variable", trick.int(1))
The same applies to functions, constants, and types (although you may need to change these a little as your variable will be in the same scope as values). This helps to avoid cases where you (accidentally or intentionally) shadow a variable in the generated code, but don’t shadow it in your generator code, allowing out-of-scope values to be referenced.
Break up your code generators into multiple functions. While the API is designed to be as ergonomic as possible, due to limitations of the Gleam type system, generators can get quite verbose. Splitting separate parts of the code into different functions can make it easier to read and modify. After all, that’s the benefit of having code generators just be plain old Gleam code.
Types
A function argument with an optional label.
pub type Argument {
Argument(
label: option.Option(String),
value: Expression(Variable),
)
}
Constructors
-
Argument( label: option.Option(String), value: Expression(Variable), )
A known type for an expression. Unlike Type, this exists after
type-checking and contains the full information about each type.
pub type ConcreteType {
Custom(
module: String,
name: String,
generics: List(ConcreteType),
)
Generic(id: Int)
Unbound(id: Int)
Tuple(elements: List(ConcreteType))
Function(
parameters: List(ConcreteType),
return: ConcreteType,
field_map: option.Option(FieldMap),
)
}
Constructors
-
Custom( module: String, name: String, generics: List(ConcreteType), ) -
Generic(id: Int) -
Unbound(id: Int) -
Tuple(elements: List(ConcreteType)) -
Function( parameters: List(ConcreteType), return: ConcreteType, field_map: option.Option(FieldMap), )
Indicates that an expression is constant and can be assigned to a const.
pub type Constant
CustomType
opaqueInformation about a custom type.
pub opaque type CustomType(a)
A type error.
pub type Error {
TypeMismatch(expected: ConcreteType, got: ConcreteType)
TupleIndexOutOfBounds(length: Int, index: Int)
InvalidTupleAccess(type_: ConcreteType)
InvalidCall(type_: ConcreteType)
InvalidListPrepend(type_: ConcreteType)
IncorrectNumberOfArguments(expected: Int, got: Int)
UnlabelledParameterAfterLabelledParameter(name: String)
UnexpectedLabelledArgument(label: String)
UnknownLabel(label: String, available_labels: List(String))
DuplicateLabel(label: String)
NoCaptureHole
DuplicateCaptureHole
InvalidName(name: String, expected: NameCase)
}
Constructors
-
TypeMismatch(expected: ConcreteType, got: ConcreteType) -
TupleIndexOutOfBounds(length: Int, index: Int)Attempting to access a non-existent tuple field
-
InvalidTupleAccess(type_: ConcreteType)Attempting to perform tuple access on a value which is not a tuple
-
InvalidCall(type_: ConcreteType)Attempting to call a value which is not a function
-
InvalidListPrepend(type_: ConcreteType)Attempting to prepend to a value which is not a list
-
IncorrectNumberOfArguments(expected: Int, got: Int)Calling a function with the incorrect number of arguments
-
UnlabelledParameterAfterLabelledParameter(name: String)Attempting to define an unlabelled function parameter after a labelled parameter
-
UnexpectedLabelledArgument(label: String)Using a label in a call to a function with no labels
-
UnknownLabel(label: String, available_labels: List(String))Using a label which is not defined in the called function
-
DuplicateLabel(label: String)Attempting to define parameters with duplicate labels
-
NoCaptureHoleNo capture hole is provided to a
function_capture_altcall -
DuplicateCaptureHoleMore than one capture hole is provided to a
function_capture_altcall -
InvalidName(name: String, expected: NameCase)The name of a value does not match what is expected.
Expression
opaqueThe field of a custom type variant.
pub type Field {
Field(label: option.Option(String), type_: Type)
}
Constructors
-
Field(label: option.Option(String), type_: Type)
FunctionBuilder
opaqueInformation about a function which can either be turned into a function definition or an anonymous function.
Marked as either Labelled or Unlabelled.
pub opaque type FunctionBuilder(labelling)
An argument to a function capture.
pub type FunctionCaptureArgument {
CaptureArgument(value: Expression(Variable))
CaptureHole
}
Constructors
-
CaptureArgument(value: Expression(Variable)) -
CaptureHole
Indicates that a custom type has one or more type parameters.
pub type HasParameters
Indicates that a function has one or more labelled arguments can cannot be turned into an anonymous function as anonymous functions do not support labels.
pub type Labelled
Module
opaqueA module containing one or more definitions.
pub opaque type Module
pub type NameCase {
SnakeCase
PascalCase
}
Constructors
-
SnakeCase -
PascalCase
Indicates that a custom type has no type parameters.
pub type NoParameters
The publicity of a top-level definition.
pub type Publicity {
Public
Internal
Private
}
Constructors
-
Public -
Internal -
Private
Statement
opaqueOne or more statements that can be used in a block or function body.
pub opaque type Statement
Type
opaqueThe type of a value. This is different to ConcreteType
in that it exists before type-checking and does not contain complete
information yet.
pub opaque type Type
Indicates that a function does not have labelled arguments and can be turned into an anonymous function.
pub type Unlabelled
Indicates that an expression includes a runtime computation can cannot be
assigned to a const.
pub type Variable
Values
pub fn add(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a + operation.
Examples
trick.add(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 + 2")
pub fn add_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a +. operation.
Examples
trick.add_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 +. 2.0")
pub fn and(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a && operation.
Examples
trick.and(trick.bool(True), trick.bool(False))
|> trick.expression_to_string
// -> Ok("True && False")
pub fn anonymous(
function: FunctionBuilder(Unlabelled),
) -> Expression(Variable)
Generates an anonymous function.
Examples
trick.anonymous({
use a <- trick.parameter("a", trick.int_type())
use b <- trick.parameter("b", trick.int_type())
trick.add(a, b) |> trick.expression |> trick.function_body
})
|> trick.expression_to_string
// -> Ok("fn(a: Int, b: Int) { a + b }")
pub fn assert_(
condition: Expression(a),
message: option.Option(Expression(a)),
) -> Statement
Generates an assert statement with an optional message. The condition must
be of type Bool, and the message, if present, must be of type String.
Like expression, assert by default terminates the block
and doesn’t expect a continuation. To place statements after an assert,
use discard.
Examples
trick.assert_(trick.bool(True), None)
|> trick.block
|> trick.expression_to_string
Will generate:
{
assert True
}
trick.assert_(trick.bool(False), Some(trick.string("This will panic")))
|> trick.block
|> trick.expression_to_string
Will generate:
{
assert False as \"This will panic\"
}
trick.assert_(trick.int(1), None)
|> trick.block
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Bool, got: Int))
trick.assert_(trick.bool(True), Some(trick.bool(True)))
|> trick.block
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: String, got: Bool))
pub fn block(inner: Statement) -> Expression(Variable)
Generates a block wrapping one or more statements.
Examples
trick.int(1)
|> trick.add(trick.int(2))
|> trick.expression
|> trick.block
|> trick.expression_to_string
// -> Ok("{ 1 + 2 }")
trick.block({
use x <- trick.variable("x", trick.int(1))
use y <- trick.variable("y", trick.int(2))
trick.expression(trick.add(x, y))
})
|> trick.expression_to_string
Will generate:
{
let x = 1
let y = 2
x + y
}
pub fn bool(value: Bool) -> Expression(a)
Generates a Bool.
Examples
trick.bool(True) |> trick.expression_to_string
// -> Ok("True")
pub fn call(
function: Expression(a),
arguments: List(Expression(a)),
) -> Expression(Variable)
Generates a function call with unlabelled arguments. To use labels in the
call, see labelled_call.
Example
The following examples assume a function called add defined as the following:
pub fn add(a: Int, b: Int) -> Int {
a + b
}
The definition has been omitted for brevity. See function for
examples of how to create functions.
trick.call(add, [trick.int(1), trick.int(2)]) |> trick.expression_to_string
// -> Ok("add(1, 2)")
trick.call(add, [trick.float(1.0), trick.float(2.0)])
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
trick.call(add, [trick.int(1), trick.int(2), trick.int(3)])
|> trick.expression_to_string
// -> Error(IncorrectNumberOfArguments(expected: 2, got: 3))
trick.call(trick.int(1), [trick.int(2), trick.int(3)])
|> trick.expression_to_string
// -> Error(InvalidCall(type_: int))
pub fn comment(
comment: String,
continue: fn() -> Statement,
) -> Statement
Generates a comment.
Examples
trick.block({
use <- trick.comment("Pi to 2 decimal places")
trick.expression(trick.float(3.14))
})
|> trick.expression_to_string
Will generate:
{
// Pi to 2 decimal places
3.14
}
pub fn concatenate(
left: Expression(a),
right: Expression(a),
) -> Expression(a)
Generates a <> operation.
Examples
trick.concatenate(trick.string("Hello"), trick.string("world"))
|> trick.expression_to_string
// -> Ok("\"Hello\" <> \"world\"")
pub fn constant(
name: String,
publicity: Publicity,
value: Expression(Constant),
continue: fn(Expression(Constant)) -> Module,
) -> Module
Generates a top-level constant from a constant expression, passing the name of the constant to the continuing function allowing it to be used.
Examples
{
use hello <- trick.constant("hello", trick.Private, trick.string("Hello,"))
use world <- trick.constant("world", trick.Private, trick.string(" world!"))
use hello_world <- trick.constant(
"hello_world",
trick.Public,
trick.concatenate(hello, world),
)
trick.end_module()
}
|> trick.to_string
Will generate:
const hello = "Hello,"
const world = " world!"
pub const hello_world = hello <> world
pub fn constructor(
name: String,
fields: List(Field),
continue: fn(Expression(Constant)) -> CustomType(NoParameters),
) -> CustomType(NoParameters)
Generates a constructor for a custom types.
Examples
{
use wibble_type <- trick.custom_type("Wibble", trick.Public)
use wibble <- trick.constructor("Wibble", [
trick.Field(None, trick.int_type()),
trick.Field(None, trick.float_type()),
trick.Field(Some("a_label"), trick.string_type()),
trick.Field(Some("another_label"), trick.bool_type()),
])
use <- trick.end_custom_type
trick.end_module()
}
|> trick.to_string
Will generate:
pub type Wibble {
Wibble(Int, Float, a_label: String, another_label: Bool)
}
pub fn custom_type(
name: String,
publicity: Publicity,
continue: fn(Type) -> CustomType(a),
) -> Module
Begins a custom type declaration, passing the type to the continuing function so it can be used in constructors as a recursive definition, or in later functions and types.
Examples
{
use list <- trick.custom_type("List", trick.Public)
use a <- trick.type_parameter("a")
use empty <- trick.constructor("Empty", [])
use non_empty <- trick.constructor("NonEmpty", [
trick.Field(Some("head"), a),
trick.Field(Some("tail"), list),
])
use <- trick.end_custom_type
trick.end_module()
}
|> trick.to_string
Will generate:
pub type List(a) {
Empty
NonEmpty(head: a, tail: List(a))
}
pub fn discard(
discarded: Statement,
continue: fn() -> Statement,
) -> Statement
Discards a terminating statement and allows continuation.
trick.block({
use <- trick.discard(trick.expression(trick.int(1)))
trick.expression(trick.int(2))
})
|> trick.expression_to_string
Will generate:
{
1
2
}
trick.block({
use <- trick.discard(trick.assert(trick.bool(True), None))
trick.assert(trick.bool(False), None)
})
|> trick.expression_to_string
Will generate:
{
assert True
assert False
}
pub fn divide(
divide left: Expression(a),
by right: Expression(a),
) -> Expression(Variable)
Generates a / operation.
Examples
trick.divide(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 / 2")
pub fn divide_float(
divide left: Expression(a),
by right: Expression(a),
) -> Expression(Variable)
Generates a /. operation.
Examples
trick.divide_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 /. 2.0")
pub fn doc_comment(
comment: String,
continue: fn() -> Module,
) -> Module
Generates a doc comment in a module.
Examples
{ use <- trick.doc_comment( “The ultimate answer to life, the universe, and everything.” ) use _ <- trick.constant(“the_answer”, trick.Public, trick.int(42)) trick.end_module() }
pub fn echo_(
value: Expression(a),
message: option.Option(Expression(a)),
) -> Expression(Variable)
Generates an echo expression, with an optional message. If present, the
message must be of type String.
Examples
trick.echo_(trick.int(42), None) |> trick.expression_to_string
// -> Ok("echo 42")
trick.echo_(trick.int(42), Some(trick.string("the answer")))
|> trick.expression_to_string
// -> Ok("echo 42 as \"the answer\"")
trick.echo_(trick.int(42), Some(trick.int(42)))
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: String, got: Int))
pub fn end_custom_type(continue: fn() -> Module) -> CustomType(a)
Marks the end of a custom type definition.
Examples
{
use box_type <- trick.custom_type("Box", trick.Public)
use value <- trick.type_parameter("value")
use box <- trick.constructor("Box", [trick.Field(None, value)])
use <- trick.end_custom_type
trick.end_module()
}
|> trick.to_string
Will generate:
pub type Box(value) {
Box(value)
}
pub fn end_module() -> Module
Marks the end of a module.
Examples
{
use _ <- trick.constant("pi", trick.Public, trick.float(3.14))
trick.end_module()
}
|> trick.to_string
// -> Ok("pub const pi = 3.14")
pub fn equal(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a == operation. The two values must be of the same type.
Examples
trick.equal(trick.int(1), trick.int(1)) |> trick.expression_to_string
// -> Ok("1 == 1")
trick.equal(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 == 2.0")
trick.equal(trick.int(1), trick.float(2.0))
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
pub fn expression(expression: Expression(a)) -> Statement
Turns an Expression into a Statement so it can be used in statement
position.
By default, an expression statement ends the block and doesn’t allow being
followed by another statement. Use discard to include a
continuation.
pub fn expression_to_string(
expression: Expression(a),
) -> Result(String, Error)
Turns an Expression into a string of Gleam code.
Examples
trick.int(1) |> trick.add(trick.int(2)) |> trick.expression_to_string
// -> Ok("1 + 2")
trick.int(1) |> trick.add(trick.float(2.0)) |> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
pub fn float(value: Float) -> Expression(a)
Generates a Float.
Examples
trick.float(3.14) |> trick.expression_to_string
// -> Ok("3.14")
pub fn function(
name: String,
publicity: Publicity,
function: FunctionBuilder(a),
continue: fn(Expression(Constant)) -> Module,
) -> Module
Generates a top-level function definition, passing the function name to the continuing function so it can be called later.
Examples
{
use square <- trick.function("square", trick.Private, {
use value <- trick.parameter("value", trick.float_type())
trick.multiply_float(value, value)
|> trick.expression
|> trick.function_body
})
use circle_area <- trick.function("circle_area", trick.Public, {
use radius <- trick.parameter("radius", trick.float_type())
trick.call(square, [radius])
|> trick.multiple_float(trick.float(3.14))
|> trick.expression
|> trick.function_body
})
use main <- trick.function("main", trick.Public, trick.function_body(
trick.expression(
trick.echo_(trick.call(circle_area, [trick.float(5.0)]), None)
)
))
}
|> trick.to_string
Will generate:
fn square(value: Float) -> Float {
value *. value
}
pub fn circle_area(radius: Float) -> Float {
square(radius) *. 3.14
}
pub fn main() -> Float {
echo circle_area(5.0)
}
pub fn function_body(
body: Statement,
) -> FunctionBuilder(Unlabelled)
Marks a statement as the body of a function, concluding the definition.
Examples
trick.nil()
|> trick.expression
|> trick.function_body
|> trick.anonymous
|> trick.expression_to_string
// -> Ok("fn() { Nil }")
pub fn function_capture(
function: Expression(a),
before_hole: List(Expression(a)),
after_hole: List(Expression(a)),
) -> Expression(Variable)
Generates a function capture expression, receiving two lists of arguments. The function hole goes between the two lists.
See also: function_capture_alt for an alternative API.
Examples
{
use add_5_numbers <- trick.function("add_5_numbers", trick.Private, {
use a <- trick.parameter("a", int_type())
use b <- trick.parameter("b", int_type())
use c <- trick.parameter("c", int_type())
use d <- trick.parameter("d", int_type())
use e <- trick.parameter("e", int_type())
a
|> trick.add(b)
|> trick.add(c)
|> trick.add(d)
|> trick.add(e)
|> trick.expression
|> trick.function_body
})
use main <- trick.function("main", trick.Public, trick.function_body(
trick.expression(trick.function_capture(
add_5_numbers,
[trick.int(1), trick.int(2)],
[trick.int(4), trick.int(5)],
))
))
trick.end_module()
}
Will generate:
fn add_5_numbers(a: Int, b: Int, c: Int, d: Int, e: Int) -> Int {
a + b + c + d + e
}
pub fn main() -> fn(Int) -> Int {
add_5_numbers(1, 2, _, 4, 5)
}
pub fn function_capture_alt(
function: Expression(a),
arguments: List(FunctionCaptureArgument),
) -> Expression(Variable)
An alternative experimental API to function_capture,
structured more like a regular call.
The downside to this approach is that the type system doesn’t guarantee that there’s exactly one type hole, so we need to report errors for that too.
Examples
{
use add_5_numbers <- trick.function("add_5_numbers", trick.Private, {
use a <- trick.parameter("a", int_type())
use b <- trick.parameter("b", int_type())
use c <- trick.parameter("c", int_type())
use d <- trick.parameter("d", int_type())
use e <- trick.parameter("e", int_type())
a
|> trick.add(b)
|> trick.add(c)
|> trick.add(d)
|> trick.add(e)
|> trick.expression
|> trick.function_body
})
use main <- trick.function("main", trick.Public, trick.function_body(
trick.expression(trick.function_capture_alt(add_5_numbers, [
CaptureArgument(trick.int(1)),
CaptureArgument(trick.int(2)),
CaptureHole,
CaptureArgument(trick.int(4)),
CaptureArgument(trick.int(5)),
]))
))
trick.end_module()
}
Will generate:
fn add_5_numbers(a: Int, b: Int, c: Int, d: Int, e: Int) -> Int {
a + b + c + d + e
}
pub fn main() -> fn(Int) -> Int {
add_5_numbers(1, 2, _, 4, 5)
}
pub fn function_type(
parameters: List(Type),
return: Type,
) -> Type
Returns a function type with the specified parameters and return type.
pub fn greater_than(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a > operation.
Examples
trick.greater_than(trick.int(1), trick.int(2))
|> trick.expression_to_string
// -> Ok("1 > 2")
pub fn greater_than_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a >. operation.
Examples
trick.greater_than_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 >. 2.0")
pub fn greater_than_or_equal(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a >= operation.
Examples
trick.greater_than_or_equal(trick.int(1), trick.int(2))
|> trick.expression_to_string
// -> Ok("1 >= 2")
pub fn greater_than_or_equal_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a >=. operation.
Examples
trick.greater_than_or_equal_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 >=. 2.0")
pub fn int(value: Int) -> Expression(a)
Generates an Int.
Examples
trick.int(42) |> trick.expression_to_string
// -> Ok("42")
pub fn int_base16(value: Int) -> Expression(a)
Generates an Int using hexadecimal syntax.
Examples
trick.int_base16(42) |> trick.expression_to_string
// -> Ok("0x2a")
pub fn int_base2(value: Int) -> Expression(a)
Generates an Int using binary syntax.
Examples
trick.int_base2(42) |> trick.expression_to_string
// -> Ok("0b101010")
pub fn int_base8(value: Int) -> Expression(a)
Generates an Int using octal syntax.
Examples
trick.int_base8(42) |> trick.expression_to_string
// -> Ok("0o52")
pub fn labelled_call(
function: Expression(a),
arguments: List(Argument),
) -> Expression(Variable)
Generates a function call, allowing you to specify labelled arguments. For
a call with no labelled arguments, it’s more convenient to simply use
call.
Examples
{
use function_with_labels <- trick.function(
"function_with_labels",
trick.Private,
{
use _ <- trick.parameter("unlabelled", trick.int_type())
use _ <- trick.labelled_parameter("label", "name", trick.float_type())
use _ <- trick.labelled_parameter(
"other_label",
"different_name",
trick.bool_type(),
)
trick.todo_(None) |> trick.expression |> trick.function_body
},
)
use main <- trick.function("main", trick.Public, trick.function_body(
trick.expression(trick.labelled_call(function_with_labels, [
trick.Argument(None, trick.int(42)),
trick.Argument(Some("other_label"), trick.bool(False)),
trick.Argument(Some("label"), trick.float(3.14)),
]))
))
trick.end_module()
}
|> trick.to_string
Will generate:
fn function_with_labels(
unlabelled: Int,
label name: Float,
other_label different_name: Bool,
) -> a {
todo
}
pub fn main() -> a {
function_with_labels(42, other_label: False, label: 3.14)
}
pub fn labelled_parameter(
label: String,
name: String,
type_: Type,
continue: fn(Expression(a)) -> FunctionBuilder(a),
) -> FunctionBuilder(Labelled)
Adds a labelled parameter to a function definition.
Examples
trick.function("subtract", trick.Public, {
use left <- trick.labelled_parameter("from", "left", trick.type_int())
use right <- trick.labelled_parameter("subtract", "right", trick.type_int())
trick.subtract(left, right) |> trick.expression |> trick.function_body
}, fn(_) { trick.end_module() })
|> trick.to_string
Will generate:
pub fn subtract(from left: Int, subtract right: Int) -> Int {
left - right
}
pub fn less_than(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a < operation.
Examples
trick.less_than(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 < 2")
pub fn less_than_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a <. operation.
Examples
trick.less_than_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 <. 2.0")
pub fn less_than_or_equal(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a <= operation.
Examples
trick.less_than_or_equal(trick.int(1), trick.int(2))
|> trick.expression_to_string
// -> Ok("1 <= 2")
pub fn less_than_or_equal_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a <=. operation.
Examples
trick.less_than_or_equal_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 <=. 2.0")
pub fn list(values: List(Expression(a))) -> Expression(a)
Generates a list of values. The values must all be of the same type.
Examples
trick.list([trick.int(1), trick.int(2), trick.int(3)])
|> trick.expression_to_string
// -> Ok("[1, 2, 3]")
trick.list([trick.float(1.0), trick.float(2.0), trick.float(3.0)])
|> trick.expression_to_string
// -> Ok("[1.0, 2.0, 3.0]")
trick.list([trick.int(1), trick.float(2.0), trick.float(3.0)])
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
pub fn list_type(of element_type: Type) -> Type
Returns a List type with the specified element type.
pub fn multiply(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a * operation.
Examples
trick.multiply(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 * 2")
pub fn multiply_float(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a *. operation.
Examples
trick.multiply_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 *. 2.0")
pub fn negate_bool(value: Expression(a)) -> Expression(Variable)
Generates a unary ! operation.
Examples
trick.negate_bool(trick.bool(True))
|> trick.expression_to_string
// -> Ok("!True")
pub fn negate_int(value: Expression(a)) -> Expression(Variable)
Generates a unary - operation.
Examples
trick.negate_int(trick.int(1))
|> trick.expression_to_string
// -> Ok("-1")
trick.negate_int(trick.float(1.0))
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
pub fn nil() -> Expression(a)
Generates Nil.
Examples
trick.nil() |> trick.expression_to_string
// -> Ok("Nil")
pub fn not_equal(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a != operation. The two values must be of the same type.
Examples
trick.not_equal(trick.int(1), trick.int(1)) |> trick.expression_to_string
// -> Ok("1 != 1")
trick.not_equal(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 != 2.0")
trick.not_equal(trick.int(1), trick.float(2.0))
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
pub fn or(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a || operation.
Examples
trick.or(trick.bool(False), trick.bool(False))
|> trick.expression_to_string
// -> Ok("False || False")
pub fn panic_(
message: option.Option(Expression(a)),
) -> Expression(Variable)
Generates a panic expression, with an optional message. If present, the
message must be of type String.
Examples
trick.panic_(None) |> trick.expression_to_string
// -> Ok("panic")
trick.panic_(Some(trick.string("uh oh"))) |> trick.expression_to_string
// -> Ok("panic as \"uh oh\"")
trick.panic_(Some(trick.int(42))) |> trick.expression_to_string
// -> Error(TypeMismatch(expected: String, got: Int))
pub fn parameter(
name: String,
type_: Type,
continue: fn(Expression(a)) -> FunctionBuilder(a),
) -> FunctionBuilder(a)
Adds an unlabelled parameter to a function definition.
Examples
trick.anonymous({
use parameter <- trick.parameter("parameter", trick.type_int())
trick.todo_(None) |> trick.expression |> trick.function_body
})
|> trick.expression_to_string
// -> Ok("fn(parameter: Int) { todo }")
pub fn prepend(
to list: Expression(a),
prepend elements: List(Expression(a)),
) -> Expression(a)
Generates a list prepend expression, prepending one or more items.
Examples
trick.list([trick.int(2), trick.int(3)])
|> trick.prepend([trick.int(0), trick.int(1)])
|> trick.expression_to_string
// -> Ok("[0, 1, ..[2, 3]]")
trick.list([trick.int(2), trick.int(3)])
|> trick.prepend([trick.float(0.0), trick.float(1.0)])
|> trick.expression_to_string
// -> Error(TypeMismatch(expected: Int, got: Float))
trick.int(2)
|> trick.prepend([trick.int(0), trick.int(1)])
|> trick.expression_to_string
// -> InvalidListPrepend(type_: Int)
pub fn recursive(
continue: fn(Expression(Constant)) -> Statement,
) -> FunctionBuilder(Labelled)
Creates a recursive function by passing in the function name to the body.
Once a function is declared as recursive, no more parameters can be added.
Examples
trick.function("infinity", trick.Private, {
use parameter <- trick.parameter("parameter", trick.generic("a"))
use infinity <- trick.recursive
trick.call(infinity, parameter)
}, fn(_) { trick.end_module() })
|> trick.to_string
Will generate:
fn infinity(parameter: a) -> b {
infinity(parameter)
}
pub fn remainder(
left: Expression(a),
right: Expression(a),
) -> Expression(Variable)
Generates a % operation.
Examples
trick.remainder(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 % 2")
pub fn string(value: String) -> Expression(a)
Generates a String.
Examples
trick.string("Hello, world!") |> trick.expression_to_string
// -> Ok("\"Hello, world!\"")
pub fn subtract(
from left: Expression(a),
subtract right: Expression(a),
) -> Expression(Variable)
Generates a - operation.
Examples
trick.subtract(trick.int(1), trick.int(2)) |> trick.expression_to_string
// -> Ok("1 - 2")
pub fn subtract_float(
from left: Expression(a),
subtract right: Expression(a),
) -> Expression(Variable)
Generates a -. operation.
Examples
trick.subtract_float(trick.float(1.0), trick.float(2.0))
|> trick.expression_to_string
// -> Ok("1.0 -. 2.0")
pub fn to_string(module: Module) -> Result(String, Error)
Turns a Module into a string of Gleam code.
Examples
{
use _pi <- trick.constant("pi", trick.Public, trick.float(3.14))
trick.end_module()
}
|> trick.to_string
// -> Ok("pub const pi = 3.14")
pub fn todo_(
message: option.Option(Expression(a)),
) -> Expression(Variable)
Generates a todo expression, with an optional message. If present, the
message must be of type String.
Examples
trick.todo_(None) |> trick.expression_to_string
// -> Ok("todo")
trick.todo_(Some(trick.string("uh oh"))) |> trick.expression_to_string
// -> Ok("todo as \"uh oh\"")
trick.todo_(Some(trick.int(42))) |> trick.expression_to_string
// -> Error(TypeMismatch(expected: String, got: Int))
pub fn tuple(values: List(Expression(a))) -> Expression(a)
Generates a tuple from the specified values. The values can be of different types.
Examples
trick.tuple([trick.int(1), trick.float(2.0), trick.string("three")])
|> trick.expression_to_string
// -> Ok("#(1, 2.0, \"three\")")
pub fn tuple_index(
tuple: Expression(a),
index: Int,
) -> Expression(Variable)
Generates a tuple access expression.
Examples
trick.tuple([trick.int(1), trick.float(2.0), trick.string("three")])
|> trick.tuple_index(2)
|> trick.expression_to_string
// -> Ok("#(1, 2.0, \"three\").2")
trick.tuple([trick.int(1), trick.float(2.0), trick.string("three")])
|> trick.tuple_index(4)
|> trick.expression_to_string
// -> Error(TupleIndexOutOfBounds(length: 3, index: 4))
trick.list([trick.int(1), trick.int(2)])
|> trick.tuple_index(0)
|> trick.expression_to_string
// -> Error(InvalidTupleAccess(type_: List(Int)))
pub fn tuple_type(containing elements: List(Type)) -> Type
Returns a tuple type containing the specified elements.
pub fn type_parameter(
name: String,
continue: fn(Type) -> CustomType(a),
) -> CustomType(HasParameters)
Adds a type parameter to a custom type.
Examples
{
use dict <- trick.custom_type("Dict", trick.Public)
use key <- trick.type_parameter("key")
use value <- trick.type_parameter("value")
use <- trick.end_custom_type
trick.end_module()
}
|> trick.to_string
// -> Ok("pub type Dict(key, value)")
{
use box_type <- trick.custom_type("Box", trick.Public)
use value <- trick.type_parameter("value")
use box <- trick.constructor("Box", [trick.Field(None, value)])
use <- trick.end_custom_type
trick.end_module()
}
|> trick.to_string
Will generate:
pub type Box(value) {
Box(value)
}
pub fn variable(
name: String,
value: Expression(a),
continue: fn(Expression(Variable)) -> Statement,
) -> Statement
Declares a variable in the current scope. Calls the continuing function with an expression representing the variable name.
Examples
trick.block({
use x <- trick.variable("x", trick.int(1))
trick.expression(trick.add(x, trick.int(1)))
})
|> trick.expression_to_string
Will generate:
{
let x = 1
x + 1
}