Compile the expression into a tiny daslang program. Each variable becomes a global "var name = 0.0f". A single [export] function "eval" returns the expression result.
| 41 | // Each variable becomes a global "var name = 0.0f". |
| 42 | // A single [export] function "eval" returns the expression result. |
| 43 | ExprCalc::ExprCalc(const string & expr, const ExprVars & vars) { |
| 44 | TextWriter ss; |
| 45 | // gen2 syntax — use options gen2 and require math for trig/sqrt/etc. |
| 46 | ss << "options gen2\n"; |
| 47 | ss << "require math\n\n"; |
| 48 | // Declare each variable as a module-level global. |
| 49 | for (auto & v : vars) { |
| 50 | ss << "var " << v.first << " = 0.0f\n"; |
| 51 | } |
| 52 | // The evaluator function simply returns the expression. |
| 53 | ss << "\n[export]\n" |
| 54 | << "def eval() : float {\n" |
| 55 | << " return " << expr << "\n" |
| 56 | << "}\n" |
| 57 | << "\n"; |
| 58 | string text = ss.str(); |
| 59 | |
| 60 | // --- Register the source string as a virtual file --- |
| 61 | // |
| 62 | // TextFileInfo wraps a raw character buffer. setFileInfo tells the |
| 63 | // file-access layer that "expr.das" resolves to this buffer instead |
| 64 | // of a real file on disk. |
| 65 | TextPrinter tout; |
| 66 | auto fAccess = make_smart<FsFileAccess>(); |
| 67 | auto fileInfo = make_unique<TextFileInfo>(text.c_str(), |
| 68 | uint32_t(text.length()), false); |
| 69 | fAccess->setFileInfo("expr.das", das::move(fileInfo)); |
| 70 | |
| 71 | // --- Compile the virtual file --- |
| 72 | ModuleGroup dummyLibGroup; |
| 73 | auto program = compileDaScript("expr.das", fAccess, tout, dummyLibGroup); |
| 74 | if (program->failed()) { |
| 75 | tout << "Compilation failed:\n"; |
| 76 | for (auto & err : program->errors) { |
| 77 | tout << reportError(err.at, err.what, err.extra, |
| 78 | err.fixme, err.cerr); |
| 79 | } |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | // --- Simulate into a shared context --- |
| 84 | ctx = make_shared<Context>(program->getContextStackSize()); |
| 85 | if (!program->simulate(*ctx, tout)) { |
| 86 | tout << "Simulation failed:\n"; |
| 87 | for (auto & err : program->errors) { |
| 88 | tout << reportError(err.at, err.what, err.extra, |
| 89 | err.fixme, err.cerr); |
| 90 | } |
| 91 | return; |
| 92 | } |
| 93 | |
| 94 | // --- Look up the function --- |
| 95 | fni = ctx->findFunction("eval"); |
| 96 | |
| 97 | // --- Map each variable name to its address in context memory --- |
| 98 | // |
| 99 | // findVariable returns -1 if not found; getVariable returns a raw |
| 100 | // pointer into the context's global-variable segment. |
nothing calls this directly
no test coverage detected