-
Notifications
You must be signed in to change notification settings - Fork 4
/
expression_parser.h
81 lines (67 loc) · 2.54 KB
/
expression_parser.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
* Parser/evaluator for the analytic expressions given by the user:
* the initial magnetization M(x, y, z), the applied field (B(t) or B(x, y, z))
* and a time-dependent scalar field amplitude.
*/
#ifndef expression_parser_h
#define expression_parser_h
#include <duktape.h>
#include <string>
#include <eigen3/Eigen/Dense>
/**
* This class handles a JavaScript function that computes either a scalar or a 3D vector,
* which depends on either a single parameter t or on (x, y, z).
*/
class ExpressionParser
{
public:
ExpressionParser();
ExpressionParser(const ExpressionParser &) = delete;
ExpressionParser &operator=(const ExpressionParser &) = delete;
~ExpressionParser();
/**
* Use the provided JavaScript function expression for subsequent computations. The provided
* function should take either one or three numeric parameters, and return either a number or an
* array of three numbers.
*/
void set_function(const std::string &js_function) const;
/**
* Use the provided expressions for the x, y and z components for subsequent computations of
* vectors. `parameters` should be a comma-separated list of parameter names, typically "t" or
* "x,y,z".
*/
void set_expressions(const std::string ¶meters, const std::string &expr_x,
const std::string &expr_y, const std::string &expr_z);
/**
* Compute a scalar from the given scalar argument.
*/
double get_scalar(double arg) const;
/**
* Compute a vector from the given scalar argument.
*/
Eigen::Vector3d get_vector(double arg) const;
/**
* Compute a vector from the given vector argument.
*/
Eigen::Vector3d get_vector(const Eigen::Ref<Eigen::Vector3d> arg) const;
private:
/**
* Abort with an suitable error message if `err` is an actual error, in which case the top of
* the stack is assumed to hold the corresponding Error object.
*/
void die_if_error(duk_int_t err) const;
/**
* Get the given component from the array at the top of the stack. Preserve the stack state.
*/
double get_vector_component(int idx) const;
/**
* Compute a vector. This must be called after duk_dup(ctx, -1) and one or more calls to
* duk_push_number(). `argument_count` should match the number of arguments pushed.
*/
Eigen::Vector3d compute_vector(int argument_count) const;
/**
* Ducktape context holding the internal state of the interpreter.
*/
duk_context *ctx;
};
#endif /* expression_parser_h */