Skip to content

Commit ac1ef52

Browse files
authored
Update README.md
Add examples for how it's used
1 parent 4ddd023 commit ac1ef52

File tree

1 file changed

+136
-6
lines changed

1 file changed

+136
-6
lines changed

README.md

Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* any value once captured is const
1616
* any redefinition of a value shadows the previous value
1717
* 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
1919
* Any script can be executed at compile time.
2020
* Why execute script at compile time?
2121
* I don't know your other use cases
@@ -32,21 +32,151 @@
3232
* For C++23
3333
* Currently only known to work with GCC 13.1.
3434

35-
* WebAssembly build support with automatic GitHub Pages deployment
35+
## Examples
3636

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
3838

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).
41167

42-
The `main` branch deploys to the root, `develop` to `/develop/`, and tags to `/tagname/`.
43168

44169
## Command Line Inspection Tool
45170

46171
`ccons_expr` can be used to execute scripts and inspect the state of the runtime system live
47172

48173
[![asciicast](https://asciinema.org/a/ZJWpwSjkFqt7Fl750HpeiT3Eg.svg)](https://asciinema.org/a/ZJWpwSjkFqt7Fl750HpeiT3Eg)
49174

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+
50180

51181
## Important Notes
52182

0 commit comments

Comments
 (0)