Reqlang Expression Language
A small (tiny) WIP expression language for reqlang's templating engine.
Install
[]
= "0.1.1"
Syntax
The syntax is s-expression like. There are only builtin functions, identifiers and string literals.
| Syntax | Description |
|---|---|
:a |
Reference to the variable a |
?b |
Reference to the prompt b |
!c |
Reference to the secret c |
id |
Reference to the builtin id |
(id :a) |
Call to builtin id with arguments: :a |
`foo` |
String literal |
true |
Literal boolean value true |
false |
Literal boolean value false |
Why Backticks For Strings?
These expressions will be embedded in places where double quotes are common (e.g. JSON). Single quotes weren't chosen due to their use in prose e.g. weren't
Builtin Functions
| Name | Arity | Description | Usage |
|---|---|---|---|
id |
1 | Returns the string arugment passed to it | (id (noop)) |
noop |
0 | Returns the string "noop" | (noop) |
is_empty |
1 | Checks if the given string is empty | (is_empty ``) |
not |
1 | Logical NOT operation on a boolean value | (not true) |
and |
2 | Logical AND operation between two booleans | (and true false) |
or |
2 | Logical OR operation between two booleans | (or true false) |
cond |
3 | If condition, returns second arg if true, else third | (cond true `foo` `bar`) |
to_str |
1 | Converts a value to its string representation | (to_str true) |
concat |
up to 10 | Concatenates a list of values in to a string | (concat `foo` `bar`) |
contains |
2 | Checks for a substring match | (contains `foo` `foobar`) |
Project
- Lexer
- Parser, AST
- Bytecode Compiler
- VM interpreter
- Disassembler
- CLI
- REPL
- Example Usage
- Specification Examples
- Tests
A more detailed technical breakdown can be found here.
Built With
Running Examples
Lexer
Lex an expression in to a list of tokens.
stderr
[
Ok(
(
0,
LParan,
1,
),
),
Ok(
(
1,
Identifier(
"id",
),
3,
),
),
Ok(
(
4,
LParan,
5,
),
),
Ok(
(
5,
Identifier(
"id",
),
7,
),
),
Ok(
(
8,
Identifier(
":a",
),
10,
),
),
Ok(
(
10,
RParan,
11,
),
),
Ok(
(
11,
RParan,
12,
),
),
]
Parser
Parse an expression into an AST.
stderr
Call(
ExprCall {
callee: (
Identifier(
ExprIdentifier(
"id",
),
),
1..3,
),
args: [
(
Call(
ExprCall {
callee: (
Identifier(
ExprIdentifier(
"id",
),
),
5..7,
),
args: [
(
Identifier(
ExprIdentifier(
":a",
),
),
8..10,
),
],
},
),
4..11,
),
],
},
)
Compiler
Compile an expression into bytecode to stdout.
stderr
ExprByteCode {
codes: [
1,
0,
0,
1,
0,
0,
1,
1,
0,
0,
1,
0,
1,
],
}
stdout
...BYTECODE...
Disassembler
Compile expression and disassemble it.
stderr
0000 GET BUILTIN 0 == 'id'
0003 GET BUILTIN 0 == 'id'
0006 GET BUILTIN 1 == 'noop'
0009 CALL (0 args)
0011 CALL (1 args)
0013 CALL (1 args)
Interpreter
Interpret an expression.
stdout
`b_value`
REPL
A simple REPL to interpret expressions.
Repl Mode
The REPL works in different modes:
- Interpret: Fully interpret an expression using the VM. This is the default.
- Compile: Compile an expression into its bytecode
- Disassemble: Compile and disassemble an expression
- Parse: Parse an expression into an AST
- Lex: Lex an expression into tokens
interpret > /mode
Current Mode: Interpret
interpret > /mode compile
compile > /mode disassemble
disassemble > /mode parse
parse > /mode lex
lex > /mode interpret
interpret > /mode
Current Mode: Interpret
Reference Last String Value
The last returned string value can be referenced using %.
interpret > %
No expression has been interpeted yet.
interpret > `value`
interpret > %
`value`
interpret > (id %)
`value`
Set Variable
interpret > /set var key = value
interpret > :key
`value`
Set Prompt
interpret > /set prompt key = value
interpret > ?key
`value`
Set Secret
interpret > /set secret key = value
interpret > !key
`value`
Print Current Environment
interpret > /env
Env {
builtins: [
BuiltinFn {
name: "id",
arity: 1,
},
BuiltinFn {
name: "noop",
arity: 0,
},
],
vars: [],
prompts: [],
secrets: [],
}
> /set var isActive = true
> /env
Env {
builtins: [
BuiltinFn {
name: "id",
arity: 1,
},
BuiltinFn {
name: "noop",
arity: 0,
},
],
vars: ["isActive"],
prompts: [],
secrets: [],
}
Exit
interpret > /exit
Example
interpret > (id :foo)
`bar`