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:
[+ ?x 1]
inputText holds this document:
x 41
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()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
| Operation | Returns | Summary |
|---|---|---|
| Build | program | build(expression) borrows the expression document and returns an owned program. |
| BuildMacro | program | build_macro(title, authored, arguments) binds AST arguments into an unstored macro and returns an owned program. |
| ExpandMacro | document | expand_macro(title, authored, arguments) returns the expanded expression document without building it. |
| Program.Evaluate | document | program.evaluate(input) returns an independent owned result document. |
| Program.Close | none | Release 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.
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
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
expression | *Document | Borrowed for the call | Required | The native expression AST to compile. The call borrows this document. |
explain | *BuildExplain | Caller-owned output | Absent skips explain output | Optional explain output. This record contains explain output for build. |
Errors
| Status | When |
|---|---|
StatusCompileFailed | the expression does not compile |
StatusOutOfMemory | native memory is exhausted |
Examples
Build an expression and evaluate its input
expressionText holds this document:
[+ ?x 1]
inputText holds this document:
x 41
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()42
Inspect one measured cost stage
expressionText holds this document:
[+ ?x 1]
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{cpu 15
wall 16
arena_bytes 0}Explain expression compilation
expressionText holds this document:
[+ ?x 1]
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{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.
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
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
title | string | Value | Required | The diagnostic title of this unstored macro. |
authored | *Document | Borrowed for the call | Required | The native authored macro definition with its declared parameters and expression body. |
arguments | *Document | Borrowed for the call | Required | Native AST arguments bound to the macro's declared parameters before expansion. |
Errors
| Status | When |
|---|---|
StatusInvalidArgument | the arguments include an undeclared macro parameter |
StatusInvalidDefinition | the macro is invalid or expands recursively |
StatusNotFound | the macro refers to an unknown macro |
StatusCompileFailed | the expansion does not compile |
StatusOutOfMemory | native memory is exhausted |
Examples
Bind an unstored macro and evaluate it
macroText holds this document:
params [input]
expands [+ {insert input} 1]
argumentsText holds this document:
input [* ?amount 2]
inputText holds this document:
amount 10
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()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.
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
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
title | string | Value | Required | The diagnostic title of this unstored macro. |
authored | *Document | Borrowed for the call | Required | The native authored macro definition with its declared parameters and expression body. |
arguments | *Document | Borrowed for the call | Required | Native AST arguments bound to the macro's declared parameters before expansion. |
Errors
| Status | When |
|---|---|
StatusInvalidArgument | the arguments include an undeclared macro parameter |
StatusInvalidDefinition | the macro is invalid or expands recursively |
StatusNotFound | the macro refers to an unknown macro |
StatusOutOfMemory | native memory is exhausted |
Examples
Expand an unstored macro as a native document
macroText holds this document:
params [input]
expands [+ {insert input} 1]
argumentsText holds this document:
input [* ?amount 2]
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()[+ [* ?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.
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
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
input | *Document | Borrowed for the call | Absent | The native input document for evaluation. |
explain | *EvalExplain | Caller-owned output | Absent skips explain output | Optional explain output. This record contains explain output for evaluate. |
Errors
| Status | When |
|---|---|
StatusEvaluationFailed | the expression fails on the input |
StatusClosed | the program is closed |
StatusOutOfMemory | native memory is exhausted |
Examples
Build an expression and evaluate its input
expressionText holds this document:
[+ ?x 1]
inputText holds this document:
x 41
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()42
Explain expression evaluation
expressionText holds this document:
[+ ?x 1]
inputText holds this document:
x 41
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(){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.
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:
[+ ?x 1]
inputText holds this document:
x 41
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()42
C exports: stardust_expr_program_release