Expressions and macros

An expression is a document. The example builds an expression program once and evaluates it with an input document. The macro example expands an expression before compilation and evaluation.

Example

Build an expression and evaluate it

expressionText holds this document:

dust9B
[+ ?x 1]

inputText holds this document:

dust5B
x 41
go422B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

program, err := stardust.Build(expression, nil)
if err != nil {
	return err
}
defer program.Close()

result, err := program.Evaluate(input, nil)
if err != nil {
	return err
}
defer result.Close()
Result / 2B
42

Reusing programs

A program keeps the expression that you built, independently of any one evaluation.

  • You can evaluate one program concurrently with separate input documents.
  • Keep the program until its evaluations finish.
  • Then release it under the ownership rule of its operation.

Operations

OperationReturnsSummary
Buildprogrambuild(expression) borrows the expression document and returns an owned program.
BuildMacroprogrambuild_macro(title, authored, arguments) binds AST arguments into an unstored macro and returns an owned program.
ExpandMacrodocumentexpand_macro(title, authored, arguments) returns the expanded expression document without building it.
Program.Evaluatedocumentprogram.evaluate(input) returns an independent owned result document.
Program.ClosenoneRelease the program handle.

Build

build(expression) borrows the expression document and returns an owned program.

  • Programs belong to no runtime.
  • Concurrent calls can evaluate a program.
  • Each call leases an internal runtime.

Expression documents.

go73B
func Build(expression *Document, explain *BuildExplain) (*Program, error)
  • Concurrency: Other calls can overlap this call, except the release of a handle that this call uses.
  • Ownership: The caller owns the returned handle and releases it.

Parameters

ParameterTypeOwnershipDefaultMeaning
expression*DocumentBorrowed for the callRequiredThe native expression AST to compile. The call borrows this document.
explain*BuildExplainCaller-owned outputAbsent skips explain outputOptional explain output. This record contains explain output for build.

Errors

StatusWhen
StatusCompileFailedthe expression does not compile
StatusOutOfMemorynative memory is exhausted

Examples

Build an expression and evaluate its input

expressionText holds this document:

dust9B
[+ ?x 1]

inputText holds this document:

dust5B
x 41
go422B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

program, err := stardust.Build(expression, nil)
if err != nil {
	return err
}
defer program.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

result, err := program.Evaluate(input, nil)
if err != nil {
	return err
}
defer result.Close()
Result / 2B
42

Inspect one measured cost stage

expressionText holds this document:

dust9B
[+ ?x 1]
go284B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

var explain stardust.BuildExplain
program, err := stardust.Build(expression, &explain)
if err != nil {
	return err
}
defer program.Close()

result := explain.Total
Result / 47B
{cpu         15
 wall        16
 arena_bytes 0}

Explain expression compilation

expressionText holds this document:

dust9B
[+ ?x 1]
go278B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

var explain stardust.BuildExplain
program, err := stardust.Build(expression, &explain)
if err != nil {
	return err
}
defer program.Close()

result := explain
Result / 393B
{prepare_expression {cpu         2
                     wall        3
                     arena_bytes 0}
 compile            {cpu         6
                     wall        6
                     arena_bytes 0}
 total              {cpu         11
                     wall        11
                     arena_bytes 0}
 arena_capacity     65536
 stages_completed   2
 cache_hit          true}

C exports: stardust_expr_build, stardust_expr_program_error

BuildMacro

build_macro(title, authored, arguments) binds AST arguments into an unstored macro and returns an owned program. The call borrows input documents only until it returns.

Macro documents.

go78B
func BuildMacro(title string, authored, arguments *Document) (*Program, error)
  • Concurrency: Other calls can overlap this call, except the release of a handle that this call uses.
  • Ownership: The caller owns the returned handle and releases it.

Parameters

ParameterTypeOwnershipDefaultMeaning
titlestringValueRequiredThe diagnostic title of this unstored macro.
authored*DocumentBorrowed for the callRequiredThe native authored macro definition with its declared parameters and expression body.
arguments*DocumentBorrowed for the callRequiredNative AST arguments bound to the macro's declared parameters before expansion.

Errors

StatusWhen
StatusInvalidArgumentthe arguments include an undeclared macro parameter
StatusInvalidDefinitionthe macro is invalid or expands recursively
StatusNotFoundthe macro refers to an unknown macro
StatusCompileFailedthe expansion does not compile
StatusOutOfMemorynative memory is exhausted

Examples

Bind an unstored macro and evaluate it

macroText holds this document:

dust45B
params  [input]
expands [+ {insert input} 1]

argumentsText holds this document:

dust20B
input [* ?amount 2]

inputText holds this document:

dust10B
amount 10
go549B
macro, err := stardust.Parse(macroText, stardust.DUST)
if err != nil {
	return err
}
defer macro.Close()

arguments, err := stardust.Parse(argumentsText, stardust.DUST)
if err != nil {
	return err
}
defer arguments.Close()

program, err := stardust.BuildMacro("twice-plus-one", macro, arguments)
if err != nil {
	return err
}
defer program.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

result, err := program.Evaluate(input, nil)
if err != nil {
	return err
}
defer result.Close()
Result / 2B
21

C exports: stardust_macro_build, stardust_expr_program_error

ExpandMacro

expand_macro(title, authored, arguments) returns the expanded expression document without building it. Arguments preserve member order and duplicate keys.

Macro documents.

go80B
func ExpandMacro(title string, authored, arguments *Document) (*Document, error)
  • Concurrency: Other calls can overlap this call, except the release of a handle that this call uses.
  • Ownership: The caller owns the returned handle and releases it.

Parameters

ParameterTypeOwnershipDefaultMeaning
titlestringValueRequiredThe diagnostic title of this unstored macro.
authored*DocumentBorrowed for the callRequiredThe native authored macro definition with its declared parameters and expression body.
arguments*DocumentBorrowed for the callRequiredNative AST arguments bound to the macro's declared parameters before expansion.

Errors

StatusWhen
StatusInvalidArgumentthe arguments include an undeclared macro parameter
StatusInvalidDefinitionthe macro is invalid or expands recursively
StatusNotFoundthe macro refers to an unknown macro
StatusOutOfMemorynative memory is exhausted

Examples

Expand an unstored macro as a native document

macroText holds this document:

dust45B
params  [input]
expands [+ {insert input} 1]

argumentsText holds this document:

dust20B
input [* ?amount 2]
go346B
macro, err := stardust.Parse(macroText, stardust.DUST)
if err != nil {
	return err
}
defer macro.Close()

arguments, err := stardust.Parse(argumentsText, stardust.DUST)
if err != nil {
	return err
}
defer arguments.Close()

result, err := stardust.ExpandMacro("twice-plus-one", macro, arguments)
if err != nil {
	return err
}
defer result.Close()
Result / 19B
[+ [* ?amount 2] 1]

C exports: stardust_macro_expand, stardust_document_error

Program.Evaluate

program.evaluate(input) returns an independent owned result document.

  • An absent input selects an empty object of variables.
  • Concurrent calls can share programs and input documents.

Expression evaluation.

go84B
func (p *Program) Evaluate(input *Document, explain *EvalExplain) (*Document, error)
  • Concurrency: Other calls can overlap this call, except the release of a handle that this call uses.
  • Ownership: The caller owns the returned handle and releases it.

Parameters

ParameterTypeOwnershipDefaultMeaning
input*DocumentBorrowed for the callAbsentThe native input document for evaluation.
explain*EvalExplainCaller-owned outputAbsent skips explain outputOptional explain output. This record contains explain output for evaluate.

Errors

StatusWhen
StatusEvaluationFailedthe expression fails on the input
StatusClosedthe program is closed
StatusOutOfMemorynative memory is exhausted

Examples

Build an expression and evaluate its input

expressionText holds this document:

dust9B
[+ ?x 1]

inputText holds this document:

dust5B
x 41
go422B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

program, err := stardust.Build(expression, nil)
if err != nil {
	return err
}
defer program.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

result, err := program.Evaluate(input, nil)
if err != nil {
	return err
}
defer result.Close()
Result / 2B
42

Explain expression evaluation

expressionText holds this document:

dust9B
[+ ?x 1]

inputText holds this document:

dust5B
x 41
go458B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

program, err := stardust.Build(expression, nil)
if err != nil {
	return err
}
defer program.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

var result stardust.EvalExplain
output, err := program.Evaluate(input, &result)
if err != nil {
	return err
}
defer output.Close()
Result / 484B
{prepare_variables {cpu         4
                    wall        6
                    arena_bytes 0}
 evaluate          {cpu         22
                    wall        23
                    arena_bytes 0}
 adopt_document    {cpu         2
                    wall        2
                    arena_bytes 0}
 total             {cpu         32
                    wall        34
                    arena_bytes 0}
 arena_capacity    65536
 document_bytes    42
 stages_completed  3}

C exports: stardust_expr_evaluate, stardust_result_take_document, stardust_result_error, stardust_result_release

Program.Close

Release the program handle.

close(handle) releases the handle.

  • Do not use it after closure.
  • Result documents remain usable after the handle that produces them closes.
go25B
func (p *Program) Close()
  • Concurrency: This call is the last use of the receiver and ends its ownership.

Examples

Build an expression and evaluate its input

expressionText holds this document:

dust9B
[+ ?x 1]

inputText holds this document:

dust5B
x 41
go439B
expression, err := stardust.Parse(expressionText, stardust.DUST)
if err != nil {
	return err
}
defer expression.Close()

program, err := stardust.Build(expression, nil)
if err != nil {
	return err
}
defer program.Close()

input, err := stardust.Parse(inputText, stardust.DUST)
if err != nil {
	return err
}
defer input.Close()

result, err := program.Evaluate(input, nil)
if err != nil {
	return err
}
defer result.Close()

program.Close()
Result / 2B
42

C exports: stardust_expr_program_release