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:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_expr_build(expression, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}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 |
|---|---|---|
| stardust_expr_build | Status. program through output | build(expression) borrows the expression document and returns an owned program. |
| stardust_macro_build | Status. program through output | build_macro(title, authored, arguments) binds AST arguments into an unstored macro and returns an owned program. |
| stardust_macro_expand | Status. document through output | expand_macro(title, authored, arguments) returns the expanded expression document without building it. |
| stardust_expr_evaluate | Status. document through output | program.evaluate(input) returns an independent owned result document. |
| stardust_expr_program_release | void | Release the program handle. |
| stardust_db_expression_build | Status. program through output | Build an owned program from a path or inline expression, expanding stored macros. |
stardust_expr_build
uint32_t stardust_expr_build(const stardust_document *source, stardust_expr_build_explain *explain, stardust_expr_program **output);uint32_t stardust_expr_program_error(const stardust_expr_program *program, stardust_diagnostic_view *output);Parameters
stardust_expr_build
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
source | const stardust_document * | Borrowed handle | Required | Keep the handle alive until the call returns. |
explain | stardust_expr_build_explain * | Caller-owned output | NULL | Receives a record. Its pointer fields follow the record's ownership contract. |
output | stardust_expr_program ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_expr_program_error
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
program | const stardust_expr_program * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_diagnostic_view * | Caller-owned output | Required | Receives a record. Its pointer fields follow the record's ownership contract. |
Errors
| Status | When |
|---|---|
STARDUST_COMPILE_FAILED | the expression does not compile |
STARDUST_OUT_OF_MEMORY | native memory is exhausted |
STARDUST_INVALID_ARGUMENT | a required input or output pointer is NULL, or an input owner is not ready |
Notes
Examples
Build an expression and evaluate its input
expression_text holds this document:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_expr_build(expression, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}42
Inspect one measured cost stage
expression_text holds this document:
[
"+",
"?x",
1
]
stardust_document *expression = NULL;
stardust_expr_build_explain explain = {0};
stardust_expr_program *program = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_expr_build(expression, &explain, &program);
stardust_expr_program_release(program);
stardust_document_release(expression);
if (status != STARDUST_OK) return status;
stardust_cost result = explain.total;{
"cpu": 13,
"wall": 14,
"arena_bytes": 0
}Explain expression compilation
expression_text holds this document:
[
"+",
"?x",
1
]
stardust_document *expression = NULL;
stardust_expr_build_explain explain = {0};
stardust_expr_program *program = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_expr_build(expression, &explain, &program);
stardust_expr_program_release(program);
stardust_document_release(expression);
if (status != STARDUST_OK) return status;
stardust_expr_build_explain result = explain;{
"prepare_expression": {
"cpu": 4,
"wall": 4,
"arena_bytes": 0
},
"compile": {
"cpu": 8,
"wall": 8,
"arena_bytes": 0
},
"total": {
"cpu": 15,
"wall": 15,
"arena_bytes": 0
},
"arena_capacity": 65536,
"stages_completed": 2,
"cache_hit": true
}Also calls: stardust_expr_program_error
stardust_macro_build
uint32_t stardust_macro_build(stardust_bytes title, const stardust_document *authored, const stardust_document *arguments, stardust_expr_program **output);uint32_t stardust_expr_program_error(const stardust_expr_program *program, stardust_diagnostic_view *output);Parameters
stardust_macro_build
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
title | stardust_bytes | Value | Required | The diagnostic title of this unstored macro. |
authored | const stardust_document * | Borrowed handle | Required | The native authored macro definition with its declared parameters and expression body. |
arguments | const stardust_document * | Borrowed handle | Required | Native AST arguments bound to the macro's declared parameters before expansion. |
output | stardust_expr_program ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_expr_program_error
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
program | const stardust_expr_program * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_diagnostic_view * | Caller-owned output | Required | Receives a record. Its pointer fields follow the record's ownership contract. |
Errors
| Status | When |
|---|---|
STARDUST_INVALID_ARGUMENT | the arguments include an undeclared macro parameter |
STARDUST_INVALID_DEFINITION | the macro is invalid or expands recursively |
STARDUST_NOT_FOUND | the macro refers to an unknown macro |
STARDUST_COMPILE_FAILED | the expansion does not compile |
STARDUST_OUT_OF_MEMORY | native memory is exhausted |
Notes
Examples
Bind an unstored macro and evaluate it
macro_text holds this document:
{
"params": [
"input"
],
"expands": [
"+",
{
"insert": "input"
},
1
]
}
arguments_text holds this document:
{
"input": [
"*",
"?amount",
2
]
}
input_text holds this document:
{
"amount": 10
}
stardust_document *authored = NULL;
stardust_document *arguments = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
stardust_bytes title = {(const uint8_t *)"twice-plus-one", 14};
uint32_t status = stardust_parse(macro_text, STARDUST_JSON, &authored);
if (status == STARDUST_OK) status = stardust_parse(arguments_text, STARDUST_JSON, &arguments);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_macro_build(title, authored, arguments, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(arguments);
stardust_document_release(authored);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}21
Also calls: stardust_expr_program_error
stardust_macro_expand
uint32_t stardust_macro_expand(stardust_bytes title, const stardust_document *authored, const stardust_document *arguments, stardust_document **output);uint32_t stardust_document_error(const stardust_document *doc, stardust_diagnostic_view *output);Parameters
stardust_macro_expand
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
title | stardust_bytes | Value | Required | The diagnostic title of this unstored macro. |
authored | const stardust_document * | Borrowed handle | Required | The native authored macro definition with its declared parameters and expression body. |
arguments | const stardust_document * | Borrowed handle | Required | Native AST arguments bound to the macro's declared parameters before expansion. |
output | stardust_document ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_document_error
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
doc | const stardust_document * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_diagnostic_view * | Caller-owned output | Required | Receives a record. Its pointer fields follow the record's ownership contract. |
Errors
| Status | When |
|---|---|
STARDUST_INVALID_ARGUMENT | the arguments include an undeclared macro parameter |
STARDUST_INVALID_DEFINITION | the macro is invalid or expands recursively |
STARDUST_NOT_FOUND | the macro refers to an unknown macro |
STARDUST_OUT_OF_MEMORY | native memory is exhausted |
Notes
Examples
Expand an unstored macro as a native document
macro_text holds this document:
{
"params": [
"input"
],
"expands": [
"+",
{
"insert": "input"
},
1
]
}
arguments_text holds this document:
{
"input": [
"*",
"?amount",
2
]
}
stardust_document *authored = NULL;
stardust_document *arguments = NULL;
stardust_document *result = NULL;
stardust_bytes title = {(const uint8_t *)"twice-plus-one", 14};
uint32_t status = stardust_parse(macro_text, STARDUST_JSON, &authored);
if (status == STARDUST_OK) status = stardust_parse(arguments_text, STARDUST_JSON, &arguments);
if (status == STARDUST_OK) status = stardust_macro_expand(title, authored, arguments, &result);
stardust_document_release(arguments);
stardust_document_release(authored);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}[
"+",
[
"*",
"?amount",
2
],
1
]Also calls: stardust_document_error
stardust_expr_evaluate
uint32_t stardust_expr_evaluate(stardust_expr_program *program, const stardust_document *variables, stardust_expr_eval_explain *explain, stardust_result **output);uint32_t stardust_result_take_document(stardust_result *result, stardust_document **output);uint32_t stardust_result_error(const stardust_result *result, stardust_diagnostic_view *output);void stardust_result_release(stardust_result *result);Parameters
stardust_expr_evaluate
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
program | stardust_expr_program * | Borrowed handle | Required | Keep the handle alive until the call returns. |
variables | const stardust_document * | Borrowed handle | NULL | Keep the handle alive until the call returns. |
explain | stardust_expr_eval_explain * | Caller-owned output | NULL | Receives a record. Its pointer fields follow the record's ownership contract. |
output | stardust_result ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_result_take_document
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
result | stardust_result * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_document ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_result_error
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
result | const stardust_result * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_diagnostic_view * | Caller-owned output | Required | Receives a record. Its pointer fields follow the record's ownership contract. |
stardust_result_release
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
result | stardust_result * | Consumed handle | NULL | Ends ownership. Do not use the handle after this call. |
Errors
| Status | When |
|---|---|
STARDUST_EVALUATION_FAILED | the expression fails on the input |
STARDUST_OUT_OF_MEMORY | native memory is exhausted |
STARDUST_INVALID_ARGUMENT | a required input or output pointer is NULL, or an input owner is not ready |
Notes
Examples
Build an expression and evaluate its input
expression_text holds this document:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_expr_build(expression, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}42
Explain expression evaluation
expression_text holds this document:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *output = NULL;
stardust_expr_eval_explain explain = {0};
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_expr_build(expression, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, &explain, &output);
stardust_result_release(output);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) return status;
stardust_expr_eval_explain result = explain;{
"prepare_variables": {
"cpu": 6,
"wall": 7,
"arena_bytes": 0
},
"evaluate": {
"cpu": 24,
"wall": 24,
"arena_bytes": 0
},
"adopt_document": {
"cpu": 2,
"wall": 2,
"arena_bytes": 0
},
"total": {
"cpu": 36,
"wall": 36,
"arena_bytes": 0
},
"arena_capacity": 65536,
"document_bytes": 42,
"stages_completed": 3
}Also calls: stardust_result_take_document, stardust_result_error, stardust_result_release
stardust_expr_program_release
void stardust_expr_program_release(stardust_expr_program *program);Consumes the receiver handle.
Parameters
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
program | stardust_expr_program * | Consumed handle | NULL | Ends ownership. Do not use the handle after this call. |
Examples
Build an expression and evaluate its input
expression_text holds this document:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_expr_build(expression, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}42
stardust_db_expression_build
uint32_t stardust_db_expression_build(stardust_db *db, const stardust_db_source *source, stardust_expr_build_explain *explain, stardust_expr_program **output);uint32_t stardust_expr_program_error(const stardust_expr_program *program, stardust_diagnostic_view *output);Parameters
stardust_db_expression_build
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
db | stardust_db * | Borrowed handle | Required | Keep the handle alive until the call returns. |
source | const stardust_db_source * | Borrowed input | Required | An inline native definition or a stored definition path. |
explain | stardust_expr_build_explain * | Caller-owned output | NULL | Receives a record. Its pointer fields follow the record's ownership contract. |
output | stardust_expr_program ** | Owned output | Required | Receives a library-owned handle. Release it after use. |
stardust_expr_program_error
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
program | const stardust_expr_program * | Borrowed handle | Required | Keep the handle alive until the call returns. |
output | stardust_diagnostic_view * | Caller-owned output | Required | Receives a record. Its pointer fields follow the record's ownership contract. |
Errors
| Status | When |
|---|---|
STARDUST_NOT_FOUND | no expression is stored at the path |
STARDUST_INVALID_DEFINITION | a macro it calls is invalid or expands recursively |
STARDUST_COMPILE_FAILED | the expanded expression does not compile |
STARDUST_CLOSED | the database is closed |
STARDUST_OUT_OF_MEMORY | native memory is exhausted |
STARDUST_INVALID_ARGUMENT | a required input or output pointer is NULL, or an input owner is not ready |
Notes
The program keeps the expression and macros selected at build time and survives database closure. Build again to use later definition changes.
Examples
Build an expression with the database's macros and evaluate it
expression_text holds this document:
[
"+",
"?x",
1
]
input_text holds this document:
{
"x": 41
}
stardust_document *expression = NULL;
stardust_document *input = NULL;
stardust_expr_program *program = NULL;
stardust_result *evaluated = NULL;
stardust_document *result = NULL;
uint32_t status = stardust_parse(expression_text, STARDUST_JSON, &expression);
stardust_db_source source = {.kind = STARDUST_SOURCE_DOCUMENT, .document = expression};
if (status == STARDUST_OK) status = stardust_parse(input_text, STARDUST_JSON, &input);
if (status == STARDUST_OK) status = stardust_db_expression_build(db, &source, NULL, &program);
if (status == STARDUST_OK) status = stardust_expr_evaluate(program, input, NULL, &evaluated);
if (status == STARDUST_OK) status = stardust_result_take_document(evaluated, &result);
stardust_result_release(evaluated);
stardust_expr_program_release(program);
stardust_document_release(input);
stardust_document_release(expression);
if (status != STARDUST_OK) {stardust_document_release(result); return status;}42
Also calls: stardust_expr_program_error