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

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin344 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.build(expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)
Result / 2 B
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.
build_macroprogrambuild_macro(title, authored, arguments) binds AST arguments into an unstored macro and returns an owned program.
expand_macrodocumentexpand_macro(title, authored, arguments) returns the expanded expression document without building it.
evaluatedocumentprogram.evaluate(input) returns an independent owned result document.
closenoneRelease the program handle.
expressionprogramBuild an owned program from a path or inline expression, expanding stored macros.

build

odin129 B
build :: proc(
	expression: Document,
	explain: ^Build_Explain = nil,
	allocator := context.allocator,
) -> (
	Program,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
expressionDocumentBorrowed for the callRequiredThe native expression AST to compile. The call borrows this document.
explain^Build_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for build.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Compile_Failedthe expression does not compile
.Out_Of_Memorynative memory is exhausted

Notes

Expression documents.

Examples

Build an expression and evaluate its input

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin344 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.build(expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)
Result / 2 B
42

Inspect one measured cost stage

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]
odin243 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

explain: stardust.Build_Explain
program := stardust.build(expression, &explain) or_return
defer stardust.close(&program)

result := explain.total
Result / 49 B
{
  "cpu": 20,
  "wall": 20,
  "arena_bytes": 0
}

Explain expression compilation

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]
odin237 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

explain: stardust.Build_Explain
program := stardust.build(expression, &explain) or_return
defer stardust.close(&program)

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

C exports: stardust_expr_build, stardust_expr_program_error

build_macro

odin128 B
build_macro :: proc(
	title: string,
	authored, arguments: Document,
	allocator := context.allocator,
) -> (
	Program,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
titlestringValueRequiredThe diagnostic title of this unstored macro.
authoredDocumentBorrowed for the callRequiredThe native authored macro definition with its declared parameters and expression body.
argumentsDocumentBorrowed for the callRequiredNative AST arguments bound to the macro's declared parameters before expansion.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentthe arguments include an undeclared macro parameter
.Invalid_Definitionthe macro is invalid or expands recursively
.Not_Foundthe macro refers to an unknown macro
.Compile_Failedthe expansion does not compile
.Out_Of_Memorynative memory is exhausted

Notes

Macro documents.

Examples

Bind an unstored macro and evaluate it

macro_text holds this document:

json106 B
{
  "params": [
    "input"
  ],
  "expands": [
    "+",
    {
      "insert": "input"
    },
    1
  ]
}

arguments_text holds this document:

json51 B
{
  "input": [
    "*",
    "?amount",
    2
  ]
}

input_text holds this document:

json19 B
{
  "amount": 10
}
odin463 B
authored := stardust.parse(macro_text, .JSON) or_return
defer stardust.close(&authored)

arguments := stardust.parse(arguments_text, .JSON) or_return
defer stardust.close(&arguments)

program := stardust.build_macro("twice-plus-one", authored, arguments) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)
Result / 2 B
21

C exports: stardust_macro_build, stardust_expr_program_error

expand_macro

odin130 B
expand_macro :: proc(
	title: string,
	authored, arguments: Document,
	allocator := context.allocator,
) -> (
	Document,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
titlestringValueRequiredThe diagnostic title of this unstored macro.
authoredDocumentBorrowed for the callRequiredThe native authored macro definition with its declared parameters and expression body.
argumentsDocumentBorrowed for the callRequiredNative AST arguments bound to the macro's declared parameters before expansion.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentthe arguments include an undeclared macro parameter
.Invalid_Definitionthe macro is invalid or expands recursively
.Not_Foundthe macro refers to an unknown macro
.Out_Of_Memorynative memory is exhausted

Notes

Macro documents.

Examples

Expand an unstored macro as a native document

macro_text holds this document:

json106 B
{
  "params": [
    "input"
  ],
  "expands": [
    "+",
    {
      "insert": "input"
    },
    1
  ]
}

arguments_text holds this document:

json51 B
{
  "input": [
    "*",
    "?amount",
    2
  ]
}
odin294 B
authored := stardust.parse(macro_text, .JSON) or_return
defer stardust.close(&authored)

arguments := stardust.parse(arguments_text, .JSON) or_return
defer stardust.close(&arguments)

result := stardust.expand_macro("twice-plus-one", authored, arguments) or_return
defer stardust.close(&result)
Result / 53 B
[
  "+",
  [
    "*",
    "?amount",
    2
  ],
  1
]

C exports: stardust_macro_expand, stardust_document_error

evaluate

odin151 B
evaluate :: proc(
	program: Program,
	input: Document = {},
	explain: ^Eval_Explain = nil,
	allocator := context.allocator,
) -> (
	Document,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
programProgramBorrowed for the callRequiredThe program owner for this operation. Keep it alive during the call.
inputDocumentBorrowed for the call{}Variables for evaluation. Absent input uses an empty object.
explain^Eval_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for evaluate.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Evaluation_Failedthe expression fails on the input
.Closedthe program is closed
.Out_Of_Memorynative memory is exhausted

Notes

Expression evaluation.

Examples

Build an expression and evaluate its input

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin344 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.build(expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)
Result / 2 B
42

Explain expression evaluation

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin404 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.build(expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

explain: stardust.Eval_Explain
output := stardust.evaluate(program, input, &explain) or_return
defer stardust.close(&output)

result := explain
Result / 378 B
{
  "prepare_variables": {
    "cpu": 4,
    "wall": 5,
    "arena_bytes": 0
  },
  "evaluate": {
    "cpu": 47,
    "wall": 47,
    "arena_bytes": 0
  },
  "adopt_document": {
    "cpu": 3,
    "wall": 3,
    "arena_bytes": 0
  },
  "total": {
    "cpu": 57,
    "wall": 59,
    "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

close

odin32 B
close :: proc(program: ^Program)

Consumes the receiver handle.

Parameters

ParameterTypeOwnershipDefaultMeaning
program^ProgramConsumed ownerRequiredThe program owner to release. Do not use it after this call.

Examples

Build an expression and evaluate its input

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin370 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.build(expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)

stardust.close(&program)
Result / 2 B
42

C exports: stardust_expr_program_release

expression

odin141 B
expression :: proc(
	db: Database,
	path: string,
	explain: ^Build_Explain = nil,
	allocator := context.allocator,
) -> (
	Program,
	Error,
)
odin149 B
expression :: proc(
	db: Database,
	definition: Document,
	explain: ^Build_Explain = nil,
	allocator := context.allocator,
) -> (
	Program,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
pathstringValueRequiredThe stored definition path selected at run time.
explain^Build_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for build.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.
definitionDocumentBorrowed for the callRequiredThe inline native definition copied into the opened handle.

Errors

StatusWhen
.Not_Foundno expression is stored at the path
.Invalid_Definitiona macro it calls is invalid or expands recursively
.Compile_Failedthe expanded expression does not compile
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

The program keeps the expression and macros selected at build time and survives database closure. Build again to use later definition changes.

Expression documents.

Examples

Build an expression with the database's macros and evaluate it

expression_text holds this document:

json23 B
[
  "+",
  "?x",
  1
]

input_text holds this document:

json14 B
{
  "x": 41
}
odin353 B
expression := stardust.parse(expression_text, .JSON) or_return
defer stardust.close(&expression)

program := stardust.expression(db, expression) or_return
defer stardust.close(&program)

input := stardust.parse(input_text, .JSON) or_return
defer stardust.close(&input)

result := stardust.evaluate(program, input) or_return
defer stardust.close(&result)
Result / 2 B
42

C exports: stardust_db_expression_build, stardust_expr_program_error