|
15 | 15 | * any value once captured is const |
16 | 16 | * any redefinition of a value shadows the previous value |
17 | 17 | * Constexpr-capable |
18 | | - * `cons_expr::cons_expr` is `constinit` meaning that it is *always* 0-cost to construct a cons_expr interpreter |
| 18 | + * `cons_expr::cons_expr` is `consteval` meaning that it is *always* 0-cost to construct a cons_expr interpreter |
19 | 19 | * Any script can be executed at compile time. |
20 | 20 | * Why execute script at compile time? |
21 | 21 | * I don't know your other use cases |
|
32 | 32 | * For C++23 |
33 | 33 | * Currently only known to work with GCC 13.1. |
34 | 34 |
|
35 | | -* WebAssembly build support with automatic GitHub Pages deployment |
| 35 | +## Examples |
36 | 36 |
|
37 | | -**Live Demo:** If you enable GitHub Pages in your project created from this template, you'll have a working example like this: |
| 37 | +### Basic Example |
38 | 38 |
|
39 | | -- Main: [https://lefticus.github.io/cons_expr/](https://lefticus.github.io/cons_expr/) |
40 | | -- Develop: [https://lefticus.github.io/cons_expr/develop/](https://lefticus.github.io/cons_expr/develop/) |
| 39 | +It can be as simple as: |
| 40 | + |
| 41 | +```cpp |
| 42 | +#include <cons_expr/cons_expr.hpp> |
| 43 | +#include <print> |
| 44 | + |
| 45 | +void greet(std::string_view name) { std::println("Hello {}!", name); } |
| 46 | + |
| 47 | +int main() { |
| 48 | + lefticus::cons_expr<> evaluator; |
| 49 | + |
| 50 | + // add C++ function |
| 51 | + evaluator.add<greet>("greet"); |
| 52 | + |
| 53 | + // call C++ function from script |
| 54 | + const auto _ = evaluator.evaluate(R"( |
| 55 | + (greet "Jason") |
| 56 | + )"); |
| 57 | +} |
| 58 | +``` |
| 59 | +
|
| 60 | +Play with this in [Compiler Explorer](https://compiler-explorer.com/z/MvvqTdvMK). |
| 61 | +
|
| 62 | +### Calling Script Functions from C++ |
| 63 | +
|
| 64 | +```cpp |
| 65 | +#include <cons_expr/cons_expr.hpp> |
| 66 | +#include <iostream> |
| 67 | +
|
| 68 | +int main() { |
| 69 | + lefticus::cons_expr<> evaluator; |
| 70 | +
|
| 71 | + // you should check this for errors |
| 72 | + [[maybe_unused]] const auto result = evaluator.evaluate(R"( |
| 73 | + (define math |
| 74 | + (lambda (x y) |
| 75 | + (- (* x y) (+ x y)) |
| 76 | + ) |
| 77 | + ) |
| 78 | + )"); |
| 79 | +
|
| 80 | + // we can treat script functions as C++ functions |
| 81 | + auto func = evaluator.make_callable<int (int, int)>("math"); |
| 82 | +
|
| 83 | + std::cout << func(evaluator, 5, 4).value(); |
| 84 | +
|
| 85 | + // or bind them and make them more natural |
| 86 | + auto math = std::bind_front(func, std::ref(evaluator)); |
| 87 | +
|
| 88 | + std::cout << math(5, 4).value(); |
| 89 | +
|
| 90 | + // or bind them *by value* and make them self contained |
| 91 | + auto math2 = std::bind_front(func, evaluator); |
| 92 | +
|
| 93 | + std::cout << math2(5, 4).value(); |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +Play with this example in [Compiler Explorer](https://compiler-explorer.com/z/WGa54G9Ee). |
| 98 | + |
| 99 | +### More Complete Bi-Directional Example |
| 100 | + |
| 101 | +```cpp |
| 102 | +#include <cmath> |
| 103 | +#include <cons_expr/cons_expr.hpp> |
| 104 | +#include <cons_expr/utility.hpp> |
| 105 | +#include <numbers> |
| 106 | + |
| 107 | +namespace lefticus { |
| 108 | +constexpr double cos(double input) { return std::cos(input); } |
| 109 | +} // namespace lefticus |
| 110 | + |
| 111 | +int main() { |
| 112 | + lefticus::cons_expr<> evaluator; |
| 113 | + // adding a function |
| 114 | + evaluator.add<lefticus::cos>("cos"); |
| 115 | + |
| 116 | + // adding a lambda, not the + to force it into a |
| 117 | + // function pointer |
| 118 | + evaluator.add<+[](double input) { return std::sin(input); }>("sin"); |
| 119 | + |
| 120 | + // adding a global |
| 121 | + evaluator.add("pi", std::numbers::pi_v<double>); |
| 122 | + |
| 123 | + // calling the functions I just added |
| 124 | + // (floating point isn't exact :D) |
| 125 | + const auto result = evaluator.evaluate("(+ (cos pi) (sin pi))"); |
| 126 | + |
| 127 | + // if the above had an error then we'd get a pretty-print |
| 128 | + // of it with this helper function |
| 129 | + |
| 130 | + // using the to_string helper from the utility.hpp |
| 131 | + std::puts(lefticus::to_string(evaluator, true, result).c_str()); |
| 132 | +} |
| 133 | +``` |
| 134 | +
|
| 135 | +Play with this example in [Compiler Explorer](https://compiler-explorer.com/z/dGYbG88YE). |
| 136 | +
|
| 137 | +### And Remember: Everything is `constexpr` Capable |
| 138 | +
|
| 139 | +```cpp |
| 140 | +#include <https://raw.githubusercontent.com/lefticus/cons_expr/refs/heads/develop/include/cons_expr/cons_expr.hpp> |
| 141 | +
|
| 142 | +// the entire system is constexpr capable |
| 143 | +consteval int do_math(int x, int y) { |
| 144 | + lefticus::cons_expr<> evaluator; |
| 145 | +
|
| 146 | + // you should check this for errors |
| 147 | + [[maybe_unused]] const auto result = evaluator.evaluate(R"( |
| 148 | + (define math |
| 149 | + (lambda (x y) |
| 150 | + (- (* x y) (+ x y)) |
| 151 | + ) |
| 152 | + ) |
| 153 | + )"); |
| 154 | +
|
| 155 | + auto func = evaluator.make_callable<int (int, int)>("math"); |
| 156 | + return func(evaluator, x, y).value(); |
| 157 | +} |
| 158 | +
|
| 159 | +int main() { |
| 160 | + // doing this in a consteval function above guarantees this is done |
| 161 | + // at compile time. |
| 162 | + return do_math(4, 2); |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +Play with this example in [Compiler Explorer](https://compiler-explorer.com/z/jr51cYYv7). |
41 | 167 |
|
42 | | -The `main` branch deploys to the root, `develop` to `/develop/`, and tags to `/tagname/`. |
43 | 168 |
|
44 | 169 | ## Command Line Inspection Tool |
45 | 170 |
|
46 | 171 | `ccons_expr` can be used to execute scripts and inspect the state of the runtime system live |
47 | 172 |
|
48 | 173 | [](https://asciinema.org/a/ZJWpwSjkFqt7Fl750HpeiT3Eg) |
49 | 174 |
|
| 175 | +## Online Builds To Play With The Syntax |
| 176 | + |
| 177 | +- Main: [https://lefticus.github.io/cons_expr/](https://lefticus.github.io/cons_expr/) |
| 178 | +- Develop: [https://lefticus.github.io/cons_expr/develop/](https://lefticus.github.io/cons_expr/develop/) |
| 179 | + |
50 | 180 |
|
51 | 181 | ## Important Notes |
52 | 182 |
|
|
0 commit comments