Macro-processor: move environment out of node classes

This completes the separation of parse trees from their evaluation.

Closes: #32
issue#70
Sébastien Villemot 2020-12-07 17:28:29 +01:00
parent 638b4c7ac5
commit ec779235ea
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
9 changed files with 514 additions and 520 deletions

View File

@ -34,8 +34,8 @@ macroExpandModFile(const string &filename, const string &basename, const istream
// Do macro processing
stringstream macro_output;
macro::Environment env = macro::Environment();
macro::Driver m(env);
m.parse(filename, basename, modfile, debug, defines, paths, macro_output);
macro::Driver m;
m.parse(filename, basename, modfile, debug, defines, env, paths, macro_output);
if (save_macro)
{
if (save_macro_file.empty())

View File

@ -25,11 +25,11 @@
using namespace macro;
void
Eval::interpret(ostream &output, vector<filesystem::path> &paths)
Eval::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
try
{
output << expr->eval()->to_string();
output << expr->eval(env)->to_string();
}
catch (StackTrace &ex)
{
@ -43,12 +43,12 @@ Eval::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
Include::interpret(ostream &output, vector<filesystem::path> &paths)
Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
using namespace filesystem;
try
{
StringPtr msp = dynamic_pointer_cast<String>(expr->eval());
StringPtr msp = dynamic_pointer_cast<String>(expr->eval(env));
if (!msp)
throw StackTrace("File name does not evaluate to a string");
path filename = msp->to_string();
@ -71,11 +71,11 @@ Include::interpret(ostream &output, vector<filesystem::path> &paths)
+". The following directories were searched:\n" + errmsg.str(), location));
}
}
Driver m(env);
Driver m;
// Calling `string()` method on filename and filename.stem() because of bug in
// MinGW 8.3.0 that ignores implicit conversion to string from filename::path.
// Test if bug exists when version of MinGW is upgraded on Debian runners
m.parse(filename.string(), filename.stem().string(), incfile, false, {}, paths, output);
m.parse(filename.string(), filename.stem().string(), incfile, false, {}, env, paths, output);
}
catch (StackTrace &ex)
{
@ -90,12 +90,12 @@ Include::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
IncludePath::interpret(ostream &output, vector<filesystem::path> &paths)
IncludePath::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
using namespace filesystem;
try
{
StringPtr msp = dynamic_pointer_cast<String>(expr->eval());
StringPtr msp = dynamic_pointer_cast<String>(expr->eval(env));
if (!msp)
throw StackTrace("File name does not evaluate to a string");
path ip = static_cast<string>(*msp);
@ -117,7 +117,7 @@ IncludePath::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
Define::interpret(ostream &output, vector<filesystem::path> &paths)
Define::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
try
{
@ -140,11 +140,11 @@ Define::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
Echo::interpret(ostream &output, vector<filesystem::path> &paths)
Echo::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
try
{
cout << "@#echo (" << getLocation() << "): " << expr->eval()->to_string() << endl;
cout << "@#echo (" << getLocation() << "): " << expr->eval(env)->to_string() << endl;
}
catch (StackTrace &ex)
{
@ -159,11 +159,11 @@ Echo::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
Error::interpret(ostream &output, vector<filesystem::path> &paths)
Error::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
try
{
throw StackTrace(expr->eval()->to_string());
throw StackTrace(expr->eval(env)->to_string());
}
catch (StackTrace &ex)
{
@ -177,7 +177,7 @@ Error::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
EchoMacroVars::interpret(ostream &output, vector<filesystem::path> &paths)
EchoMacroVars::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
if (save)
env.print(output, vars, location.begin.line, true);
@ -187,12 +187,12 @@ EchoMacroVars::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
For::interpret(ostream &output, vector<filesystem::path> &paths)
For::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
ArrayPtr ap;
try
{
ap = dynamic_pointer_cast<Array>(index_vals->eval());
ap = dynamic_pointer_cast<Array>(index_vals->eval(env));
if (!ap)
throw StackTrace("The index must loop through an array");
}
@ -236,14 +236,14 @@ For::interpret(ostream &output, vector<filesystem::path> &paths)
statement->printLineInfo(output);
printLine = false;
}
statement->interpret(output, paths);
statement->interpret(output, env, paths);
}
}
printEndLineInfo(output);
}
void
If::interpret(ostream &output, vector<filesystem::path> &paths)
If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths)
{
bool first_clause = true;
for (const auto & [expr, body] : expr_and_body)
@ -257,13 +257,13 @@ If::interpret(ostream &output, vector<filesystem::path> &paths)
if ((ifdef && env.isVariableDefined(vp->getName()))
|| (ifndef && !env.isVariableDefined(vp->getName())))
{
interpretBody(body, output, paths);
interpretBody(body, output, env, paths);
break;
}
}
else
{
auto tmp = expr->eval();
auto tmp = expr->eval(env);
RealPtr dp = dynamic_pointer_cast<Real>(tmp);
BoolPtr bp = dynamic_pointer_cast<Bool>(tmp);
if (!bp && !dp)
@ -271,7 +271,7 @@ If::interpret(ostream &output, vector<filesystem::path> &paths)
"The condition must evaluate to a boolean or a double", location));
if ((bp && *bp) || (dp && *dp))
{
interpretBody(body, output, paths);
interpretBody(body, output, env, paths);
break;
}
}
@ -289,7 +289,7 @@ If::interpret(ostream &output, vector<filesystem::path> &paths)
}
void
If::interpretBody(const vector<DirectivePtr> &body, ostream &output, vector<filesystem::path> &paths)
If::interpretBody(const vector<DirectivePtr> &body, ostream &output, Environment &env, vector<filesystem::path> &paths)
{
bool printLine = true;
for (const auto &statement : body)
@ -299,6 +299,6 @@ If::interpretBody(const vector<DirectivePtr> &body, ostream &output, vector<file
statement->printLineInfo(output);
printLine = false;
}
statement->interpret(output, paths);
statement->interpret(output, env, paths);
}
}

View File

@ -30,10 +30,10 @@ namespace macro
{
// A Parent class just for clarity
public:
Directive(Environment &env_arg, Tokenizer::location location_arg) :
Node(env_arg, move(location_arg)) { }
explicit Directive(Tokenizer::location location_arg) :
Node(move(location_arg)) { }
// Directives can be interpreted
virtual void interpret(ostream &output, vector<filesystem::path> &paths) = 0;
virtual void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) = 0;
};
@ -45,9 +45,9 @@ namespace macro
private:
const string text;
public:
TextNode(string text_arg, Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), text{move(text_arg)} { }
inline void interpret(ostream &output, vector<filesystem::path> &paths) override { output << text; }
TextNode(string text_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), text{move(text_arg)} { }
inline void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override { output << text; }
};
@ -59,9 +59,9 @@ namespace macro
private:
const ExpressionPtr expr;
public:
Eval(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Eval(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -70,9 +70,9 @@ namespace macro
private:
const ExpressionPtr expr;
public:
Include(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Include(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -81,9 +81,9 @@ namespace macro
private:
const ExpressionPtr expr;
public:
IncludePath(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
IncludePath(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -96,13 +96,13 @@ namespace macro
public:
Define(VariablePtr var_arg,
ExpressionPtr value_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), var{move(var_arg)}, value{move(value_arg)} { }
Tokenizer::location location_arg) :
Directive(move(location_arg)), var{move(var_arg)}, value{move(value_arg)} { }
Define(FunctionPtr func_arg,
ExpressionPtr value_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Tokenizer::location location_arg) :
Directive(move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -112,9 +112,9 @@ namespace macro
const ExpressionPtr expr;
public:
Echo(ExpressionPtr expr_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -124,9 +124,9 @@ namespace macro
const ExpressionPtr expr;
public:
Error(ExpressionPtr expr_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -137,12 +137,12 @@ namespace macro
const vector<string> vars;
public:
EchoMacroVars(bool save_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), save{save_arg} { }
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg} { }
EchoMacroVars(bool save_arg, vector<string> vars_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), save{save_arg}, vars{move(vars_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg}, vars{move(vars_arg)} { }
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -156,10 +156,10 @@ namespace macro
For(vector<VariablePtr> index_vec_arg,
ExpressionPtr index_vals_arg,
vector<DirectivePtr> statements_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Directive(env_arg, move(location_arg)), index_vec{move(index_vec_arg)},
Tokenizer::location location_arg) :
Directive(move(location_arg)), index_vec{move(index_vec_arg)},
index_vals{move(index_vals_arg)}, statements{move(statements_arg)} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
};
@ -178,22 +178,22 @@ namespace macro
const bool ifdef, ifndef;
public:
If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg,
Tokenizer::location location_arg,
bool ifdef_arg = false, bool ifndef_arg = false) :
Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)},
Directive(move(location_arg)), expr_and_body{move(expr_and_body_arg)},
ifdef{ifdef_arg}, ifndef{ifndef_arg} { }
void interpret(ostream &output, vector<filesystem::path> &paths) override;
void interpret(ostream &output, Environment &env, vector<filesystem::path> &paths) override;
protected:
void interpretBody(const vector<DirectivePtr> &body, ostream &output,
vector<filesystem::path> &paths);
Environment &env, vector<filesystem::path> &paths);
};
class Ifdef : public If
{
public:
Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg) :
If(move(expr_and_body_arg), env_arg, move(location_arg), true, false) { }
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), true, false) { }
};
@ -201,8 +201,8 @@ namespace macro
{
public:
Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Environment &env_arg, Tokenizer::location location_arg) :
If(move(expr_and_body_arg), env_arg, move(location_arg), false, true) { }
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), false, true) { }
};
}
#endif

View File

@ -25,7 +25,7 @@ using namespace macro;
void
Driver::parse(const string &file_arg, const string &basename_arg, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, ostream &output)
Environment &env, vector<filesystem::path> &paths, ostream &output)
{
file = file_arg;
basename = basename_arg;
@ -35,9 +35,9 @@ Driver::parse(const string &file_arg, const string &basename_arg, const istream
stringstream command_line_defines_with_endl;
for (const auto & [var, val] : defines)
command_line_defines_with_endl << "@#define " << var << " = " << val << endl;
Driver m(env);
Driver m;
istream is(command_line_defines_with_endl.rdbuf());
m.parse("command_line_defines", "command_line_defines", is, debug, {}, paths, output);
m.parse("command_line_defines", "command_line_defines", is, debug, {}, env, paths, output);
}
// Handle empty files
@ -65,7 +65,7 @@ Driver::parse(const string &file_arg, const string &basename_arg, const istream
statement->printLineInfo(output);
printLine = false;
}
statement->interpret(output, paths);
statement->interpret(output, env, paths);
}
}

View File

@ -61,14 +61,11 @@ namespace macro
//! Implements the macro expansion using a Flex scanner and a Bison parser
class Driver
{
public:
Environment &env;
private:
vector<DirectivePtr> statements;
stack<vector<DirectivePtr>> directive_stack;
public:
Driver(Environment &env_arg) :
env{env_arg} { }
Driver() = default;
Driver(const Driver &) = delete;
Driver(Driver &&) = delete;
Driver &operator=(const Driver &) = delete;
@ -84,12 +81,11 @@ namespace macro
}
};
//! Starts parsing a file, modifies `paths` and `output`
//! Both `paths` and `output` are passed as reference
//! Starts parsing a file, modifies `env`, `paths` and `output`
//! as they are modified by various macro directives
void parse(const string &file, const string &basename, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, ostream &output);
Environment &env, vector<filesystem::path> &paths, ostream &output);
//! Name of main file being parsed
string file;

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2019 Dynare Team
* Copyright © 2019-2020 Dynare Team
*
* This file is part of Dynare.
*
@ -28,7 +28,7 @@ Environment::define(VariablePtr var, ExpressionPtr value)
string name = var->getName();
if (functions.count(name))
throw StackTrace("Variable " + name + " was previously defined as a function");
variables[move(name)] = value->eval();
variables[move(name)] = value->eval(*this);
}
void
@ -67,7 +67,7 @@ Environment::getFunction(const string &name) const
codes::BaseType
Environment::getType(const string &name) const
{
return getVariable(name)->eval()->getType();
return getVariable(name)->eval(const_cast<Environment &>(*this))->getType();
}
bool
@ -132,7 +132,7 @@ Environment::printVariable(ostream &output, const string &name, int line, bool s
{
output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " ")
<< name << " = ";
getVariable(name)->eval()->print(output, save);
getVariable(name)->eval(const_cast<Environment &>(*this))->print(output, save);
if (save)
output << ";";
output << endl;

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2019 Dynare Team
* Copyright © 2019-2020 Dynare Team
*
* This file is part of Dynare.
*
@ -25,8 +25,8 @@ BoolPtr
BaseType::is_different(const BaseTypePtr &btp) const
{
if (*(this->is_equal(btp)))
return make_shared<Bool>(false, env);
return make_shared<Bool>(true, env);
return make_shared<Bool>(false);
return make_shared<Bool>(true);
}
BoolPtr
@ -34,38 +34,38 @@ Bool::is_equal(const BaseTypePtr &btp) const
{
auto btp2 = dynamic_pointer_cast<Bool>(btp);
if (!btp2)
return make_shared<Bool>(false, env);
return make_shared<Bool>(value == btp2->value, env);
return make_shared<Bool>(false);
return make_shared<Bool>(value == btp2->value);
}
BoolPtr
Bool::logical_and(const ExpressionPtr &ep) const
Bool::logical_and(const ExpressionPtr &ep, Environment &env) const
{
if (!value)
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
auto btp = ep->eval();
auto btp = ep->eval(env);
if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
throw StackTrace("Type mismatch for operands of && operator");
}
BoolPtr
Bool::logical_or(const ExpressionPtr &ep) const
Bool::logical_or(const ExpressionPtr &ep, Environment &env) const
{
if (value)
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
auto btp = ep->eval();
auto btp = ep->eval(env);
if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
throw StackTrace("Type mismatch for operands of || operator");
}
@ -73,7 +73,7 @@ Bool::logical_or(const ExpressionPtr &ep) const
BoolPtr
Bool::logical_not() const
{
return make_shared<Bool>(!value, env);
return make_shared<Bool>(!value);
}
BaseTypePtr
@ -82,7 +82,7 @@ Real::plus(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of + operator");
return make_shared<Real>(value + btp2->value, env);
return make_shared<Real>(value + btp2->value);
}
BaseTypePtr
@ -91,7 +91,7 @@ Real::minus(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of - operator");
return make_shared<Real>(value - btp2->value, env);
return make_shared<Real>(value - btp2->value);
}
BaseTypePtr
@ -100,7 +100,7 @@ Real::times(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of * operator");
return make_shared<Real>(value * btp2->value, env);
return make_shared<Real>(value * btp2->value);
}
BaseTypePtr
@ -109,7 +109,7 @@ Real::divide(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of / operator");
return make_shared<Real>(value / btp2->value, env);
return make_shared<Real>(value / btp2->value);
}
BaseTypePtr
@ -118,7 +118,7 @@ Real::power(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of ^ operator");
return make_shared<Real>(pow(value, btp2->value), env);
return make_shared<Real>(pow(value, btp2->value));
}
BoolPtr
@ -127,7 +127,7 @@ Real::is_less(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of < operator");
return make_shared<Bool>(isless(value, btp2->value), env);
return make_shared<Bool>(isless(value, btp2->value));
}
BoolPtr
@ -136,7 +136,7 @@ Real::is_greater(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of > operator");
return make_shared<Bool>(isgreater(value, btp2->value), env);
return make_shared<Bool>(isgreater(value, btp2->value));
}
BoolPtr
@ -145,7 +145,7 @@ Real::is_less_equal(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of <= operator");
return make_shared<Bool>(islessequal(value, btp2->value), env);
return make_shared<Bool>(islessequal(value, btp2->value));
}
BoolPtr
@ -154,7 +154,7 @@ Real::is_greater_equal(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of >= operator");
return make_shared<Bool>(isgreaterequal(value, btp2->value), env);
return make_shared<Bool>(isgreaterequal(value, btp2->value));
}
BoolPtr
@ -162,38 +162,38 @@ Real::is_equal(const BaseTypePtr &btp) const
{
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
return make_shared<Bool>(false, env);
return make_shared<Bool>(value == btp2->value, env);
return make_shared<Bool>(false);
return make_shared<Bool>(value == btp2->value);
}
BoolPtr
Real::logical_and(const ExpressionPtr &ep) const
Real::logical_and(const ExpressionPtr &ep, Environment &env) const
{
if (!value)
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
auto btp = ep->eval();
auto btp = ep->eval(env);
if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
throw StackTrace("Type mismatch for operands of && operator");
}
BoolPtr
Real::logical_or(const ExpressionPtr &ep) const
Real::logical_or(const ExpressionPtr &ep, Environment &env) const
{
if (value)
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
auto btp = ep->eval();
auto btp = ep->eval(env);
if (auto btp2 = dynamic_pointer_cast<Real>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
if (auto btp2 = dynamic_pointer_cast<Bool>(btp); btp2)
return make_shared<Bool>(*btp2, env);
return make_shared<Bool>(*btp2);
throw StackTrace("Type mismatch for operands of || operator");
}
@ -201,7 +201,7 @@ Real::logical_or(const ExpressionPtr &ep) const
BoolPtr
Real::logical_not() const
{
return make_shared<Bool>(!value, env);
return make_shared<Bool>(!value);
}
RealPtr
@ -210,7 +210,7 @@ Real::max(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of `max` operator");
return make_shared<Real>(std::max(value, btp2->value), env);
return make_shared<Real>(std::max(value, btp2->value));
}
RealPtr
@ -219,7 +219,7 @@ Real::min(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of `min` operator");
return make_shared<Real>(std::min(value, btp2->value), env);
return make_shared<Real>(std::min(value, btp2->value));
}
RealPtr
@ -228,7 +228,7 @@ Real::mod(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<Real>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of `mod` operator");
return make_shared<Real>(std::fmod(value, btp2->value), env);
return make_shared<Real>(std::fmod(value, btp2->value));
}
RealPtr
@ -238,7 +238,7 @@ Real::normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
auto btp22 = dynamic_pointer_cast<Real>(btp2);
if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>((1/(btp22->value*std::sqrt(2*M_PI)*std::exp(pow((value-btp12->value)/btp22->value, 2)/2))), env);
return make_shared<Real>((1/(btp22->value*std::sqrt(2*M_PI)*std::exp(pow((value-btp12->value)/btp22->value, 2)/2))));
}
RealPtr
@ -248,7 +248,7 @@ Real::normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const
auto btp22 = dynamic_pointer_cast<Real>(btp2);
if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>((0.5*(1+std::erf((value-btp12->value)/btp22->value/M_SQRT2))), env);
return make_shared<Real>((0.5*(1+std::erf((value-btp12->value)/btp22->value/M_SQRT2))));
}
BaseTypePtr
@ -257,7 +257,7 @@ String::plus(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of + operator");
return make_shared<String>(value + btp2->value, env);
return make_shared<String>(value + btp2->value);
}
BoolPtr
@ -266,7 +266,7 @@ String::is_less(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of < operator");
return make_shared<Bool>(value < btp2->value, env);
return make_shared<Bool>(value < btp2->value);
}
BoolPtr
@ -275,7 +275,7 @@ String::is_greater(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of > operator");
return make_shared<Bool>(value > btp2->value, env);
return make_shared<Bool>(value > btp2->value);
}
BoolPtr
@ -284,7 +284,7 @@ String::is_less_equal(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of <= operator");
return make_shared<Bool>(value <= btp2->value, env);
return make_shared<Bool>(value <= btp2->value);
}
BoolPtr
@ -293,7 +293,7 @@ String::is_greater_equal(const BaseTypePtr &btp) const
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
throw StackTrace("Type mismatch for operands of >= operator");
return make_shared<Bool>(value >= btp2->value, env);
return make_shared<Bool>(value >= btp2->value);
}
BoolPtr
@ -301,20 +301,20 @@ String::is_equal(const BaseTypePtr &btp) const
{
auto btp2 = dynamic_pointer_cast<String>(btp);
if (!btp2)
return make_shared<Bool>(false, env);
return make_shared<Bool>(value == btp2->value, env);
return make_shared<Bool>(false);
return make_shared<Bool>(value == btp2->value);
}
BoolPtr
String::cast_bool() const
String::cast_bool(Environment &env) const
{
auto f = [](const char &a, const char &b) { return (tolower(a) == tolower(b)); };
if (string tf = "true"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f))
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
if (string tf = "false"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f))
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
try
{
@ -322,7 +322,7 @@ String::cast_bool() const
double value_d = stod(value, &pos);
if (pos != value.length())
throw StackTrace("Entire string not converted");
return make_shared<Bool>(static_cast<bool>(value_d), env);
return make_shared<Bool>(static_cast<bool>(value_d));
}
catch (...)
{
@ -331,7 +331,7 @@ String::cast_bool() const
}
RealPtr
String::cast_real() const
String::cast_real(Environment &env) const
{
try
{
@ -339,7 +339,7 @@ String::cast_real() const
double value_d = stod(value, &pos);
if (pos != value.length())
throw StackTrace("Entire string not converted");
return make_shared<Real>(value_d, env);
return make_shared<Real>(value_d);
}
catch (...)
{
@ -356,7 +356,7 @@ Array::plus(const BaseTypePtr &btp) const
vector<ExpressionPtr> arr_copy{arr};
arr_copy.insert(arr_copy.end(), btp2->arr.begin(), btp2->arr.end());
return make_shared<Array>(arr_copy, env);
return make_shared<Array>(arr_copy);
}
BaseTypePtr
@ -379,7 +379,7 @@ Array::minus(const BaseTypePtr &btp) const
if (it2 == btp2->arr.cend())
arr_copy.emplace_back(itbtp);
}
return make_shared<Array>(arr_copy, env);
return make_shared<Array>(arr_copy);
}
BaseTypePtr
@ -409,10 +409,10 @@ Array::times(const BaseTypePtr &btp) const
else
throw StackTrace("Array::times: unsupported type on rhs");
values.emplace_back(make_shared<Tuple>(new_tuple, env));
values.emplace_back(make_shared<Tuple>(new_tuple));
}
return make_shared<Array>(values, env);
return make_shared<Array>(values);
}
BaseTypePtr
@ -422,11 +422,11 @@ Array::power(const BaseTypePtr &btp) const
if (!btp2 || !*(btp2->isinteger()))
throw StackTrace("The second argument of the power operator (^) must be an integer");
auto retval = make_shared<Array>(arr, env);
auto retval = make_shared<Array>(arr);
for (int i = 1; i < *btp2; i++)
{
auto btpv = retval->times(make_shared<Array>(arr, env));
retval = make_shared<Array>(dynamic_pointer_cast<Array>(btpv)->getValue(), env);
auto btpv = retval->times(make_shared<Array>(arr));
retval = make_shared<Array>(dynamic_pointer_cast<Array>(btpv)->getValue());
}
return retval;
}
@ -436,19 +436,19 @@ Array::is_equal(const BaseTypePtr &btp) const
{
auto btp2 = dynamic_pointer_cast<Array>(btp);
if (!btp2)
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
if (arr.size() != btp2->arr.size())
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
for (size_t i = 0; i < arr.size(); i++)
{
auto bt = dynamic_pointer_cast<BaseType>(arr[i]);
auto bt2 = dynamic_pointer_cast<BaseType>(btp2->arr[i]);
if (!*(bt->is_equal(bt2)))
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
}
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
}
ArrayPtr
@ -479,7 +479,7 @@ Array::set_union(const BaseTypePtr &btp) const
if (!found)
new_values.push_back(it);
}
return make_shared<Array>(new_values, env);
return make_shared<Array>(new_values);
}
ArrayPtr
@ -507,7 +507,7 @@ Array::set_intersection(const BaseTypePtr &btp) const
}
}
}
return make_shared<Array>(new_values, env);
return make_shared<Array>(new_values);
}
BoolPtr
@ -519,9 +519,9 @@ Array::contains(const BaseTypePtr &btp) const
if (!v2)
throw StackTrace("Type mismatch for operands of in operator");
if (*(v2->is_equal(btp)))
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
}
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
}
RealPtr
@ -535,23 +535,23 @@ Array::sum() const
throw StackTrace("Type mismatch for operands of in operator");
retval += *v2;
}
return make_shared<Real>(retval, env);
return make_shared<Real>(retval);
}
BoolPtr
Array::cast_bool() const
Array::cast_bool(Environment &env) const
{
if (arr.size() != 1)
throw StackTrace("Array must be of size 1 to be cast to a boolean");
return arr.at(0)->eval()->cast_bool();
return arr.at(0)->eval(env)->cast_bool(env);
}
RealPtr
Array::cast_real() const
Array::cast_real(Environment &env) const
{
if (arr.size() != 1)
throw StackTrace("Array must be of size 1 to be cast to a real");
return arr.at(0)->eval()->cast_real();
return arr.at(0)->eval(env)->cast_real(env);
}
BoolPtr
@ -559,19 +559,19 @@ Tuple::is_equal(const BaseTypePtr &btp) const
{
auto btp2 = dynamic_pointer_cast<Tuple>(btp);
if (!btp2)
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
if (tup.size() != btp2->tup.size())
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
for (size_t i = 0; i < tup.size(); i++)
{
auto bt = dynamic_pointer_cast<BaseType>(tup[i]);
auto bt2 = dynamic_pointer_cast<BaseType>(btp2->tup[i]);
if (!*(bt->is_equal(bt2)))
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
}
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
}
BoolPtr
@ -583,35 +583,35 @@ Tuple::contains(const BaseTypePtr &btp) const
if (!v2)
throw StackTrace("Type mismatch for operands of in operator");
if (*(v2->is_equal(btp)))
return make_shared<Bool>(true, env);
return make_shared<Bool>(true);
}
return make_shared<Bool>(false, env);
return make_shared<Bool>(false);
}
BoolPtr
Tuple::cast_bool() const
Tuple::cast_bool(Environment &env) const
{
if (tup.size() != 1)
throw StackTrace("Tuple must be of size 1 to be cast to a boolean");
return tup.at(0)->eval()->cast_bool();
return tup.at(0)->eval(env)->cast_bool(env);
}
RealPtr
Tuple::cast_real() const
Tuple::cast_real(Environment &env) const
{
if (tup.size() != 1)
throw StackTrace("Tuple must be of size 1 to be cast to a real");
return tup.at(0)->eval()->cast_real();
return tup.at(0)->eval(env)->cast_real(env);
}
BaseTypePtr
Range::eval()
Range::eval(Environment &env)
{
RealPtr incdbl = make_shared<Real>(1, env);
RealPtr incdbl = make_shared<Real>(1);
if (inc)
incdbl = dynamic_pointer_cast<Real>(inc->eval());
RealPtr startdbl = dynamic_pointer_cast<Real>(start->eval());
RealPtr enddbl = dynamic_pointer_cast<Real>(end->eval());
incdbl = dynamic_pointer_cast<Real>(inc->eval(env));
RealPtr startdbl = dynamic_pointer_cast<Real>(start->eval(env));
RealPtr enddbl = dynamic_pointer_cast<Real>(end->eval(env));
if (!startdbl || !enddbl || !incdbl)
throw StackTrace("To create an array from a range using the colon operator, "
"the arguments must evaluate to reals");
@ -619,38 +619,38 @@ Range::eval()
vector<ExpressionPtr> arr;
if (*incdbl > 0 && *startdbl <= *enddbl)
for (double i = *startdbl; i <= *enddbl; i += *incdbl)
arr.emplace_back(make_shared<Real>(i, env));
arr.emplace_back(make_shared<Real>(i));
else if (*startdbl >= *enddbl && *incdbl < 0)
for (double i = *startdbl; i >= *enddbl; i += *incdbl)
arr.emplace_back(make_shared<Real>(i, env));
arr.emplace_back(make_shared<Real>(i));
return make_shared<Array>(arr, env, location);
return make_shared<Array>(arr, location);
}
BaseTypePtr
Array::eval()
Array::eval(Environment &env)
{
vector<ExpressionPtr> retval;
for (const auto &it : arr)
retval.emplace_back(it->eval());
return make_shared<Array>(retval, env);
retval.emplace_back(it->eval(env));
return make_shared<Array>(retval);
}
BaseTypePtr
Tuple::eval()
Tuple::eval(Environment &env)
{
vector<ExpressionPtr> retval;
for (const auto &it : tup)
retval.emplace_back(it->eval());
return make_shared<Tuple>(retval, env);
retval.emplace_back(it->eval(env));
return make_shared<Tuple>(retval);
}
BaseTypePtr
Variable::eval()
Variable::eval(Environment &env)
{
if (indices && !indices->empty())
{
ArrayPtr map = dynamic_pointer_cast<Array>(indices->eval());
ArrayPtr map = dynamic_pointer_cast<Array>(indices->eval(env));
vector<ExpressionPtr> index = map->getValue();
vector<int> ind;
for (const auto &it : index)
@ -703,7 +703,7 @@ Variable::eval()
{
throw StackTrace("variable", "Index out of range", location);
}
return make_shared<String>(retvals, env);
return make_shared<String>(retvals);
}
case codes::BaseType::Array:
{
@ -712,7 +712,7 @@ Variable::eval()
for (auto it : ind)
try
{
retval.emplace_back(ap->at(it - 1)->eval());
retval.emplace_back(ap->at(it - 1)->eval(env));
}
catch (const out_of_range &ex)
{
@ -722,15 +722,15 @@ Variable::eval()
if (retval.size() == 1)
return retval.at(0);
vector<ExpressionPtr> retvala(retval.begin(), retval.end());
return make_shared<Array>(retvala, env);
return make_shared<Array>(retvala);
}
}
}
return env.getVariable(name)->eval();
return env.getVariable(name)->eval(env);
}
BaseTypePtr
Function::eval()
Function::eval(Environment &env)
{
FunctionPtr func;
ExpressionPtr body;
@ -755,9 +755,9 @@ Function::eval()
for (size_t i = 0; i < func->args.size(); i++)
{
VariablePtr mvp = dynamic_pointer_cast<Variable>(func->args.at(i));
env.define(mvp, args.at(i)->eval());
env.define(mvp, args.at(i)->eval(env));
}
auto retval = body->eval();
auto retval = body->eval(env);
env = env_orig;
return retval;
}
@ -769,90 +769,90 @@ Function::eval()
}
BaseTypePtr
UnaryOp::eval()
UnaryOp::eval(Environment &env)
{
try
{
switch (op_code)
{
case codes::UnaryOp::cast_bool:
return arg->eval()->cast_bool();
return arg->eval(env)->cast_bool(env);
case codes::UnaryOp::cast_real:
return arg->eval()->cast_real();
return arg->eval(env)->cast_real(env);
case codes::UnaryOp::cast_string:
return arg->eval()->cast_string();
return arg->eval(env)->cast_string();
case codes::UnaryOp::cast_tuple:
return arg->eval()->cast_tuple();
return arg->eval(env)->cast_tuple();
case codes::UnaryOp::cast_array:
return arg->eval()->cast_array();
return arg->eval(env)->cast_array();
case codes::UnaryOp::logical_not:
return arg->eval()->logical_not();
return arg->eval(env)->logical_not();
case codes::UnaryOp::unary_minus:
return arg->eval()->unary_minus();
return arg->eval(env)->unary_minus();
case codes::UnaryOp::unary_plus:
return arg->eval()->unary_plus();
return arg->eval(env)->unary_plus();
case codes::UnaryOp::length:
return arg->eval()->length();
return arg->eval(env)->length();
case codes::UnaryOp::isempty:
return arg->eval()->isempty();
return arg->eval(env)->isempty();
case codes::UnaryOp::isboolean:
return arg->eval()->isboolean();
return arg->eval(env)->isboolean();
case codes::UnaryOp::isreal:
return arg->eval()->isreal();
return arg->eval(env)->isreal();
case codes::UnaryOp::isstring:
return arg->eval()->isstring();
return arg->eval(env)->isstring();
case codes::UnaryOp::istuple:
return arg->eval()->istuple();
return arg->eval(env)->istuple();
case codes::UnaryOp::isarray:
return arg->eval()->isarray();
return arg->eval(env)->isarray();
case codes::UnaryOp::exp:
return arg->eval()->exp();
return arg->eval(env)->exp();
case codes::UnaryOp::ln:
return arg->eval()->ln();
return arg->eval(env)->ln();
case codes::UnaryOp::log10:
return arg->eval()->log10();
return arg->eval(env)->log10();
case codes::UnaryOp::sin:
return arg->eval()->sin();
return arg->eval(env)->sin();
case codes::UnaryOp::cos:
return arg->eval()->cos();
return arg->eval(env)->cos();
case codes::UnaryOp::tan:
return arg->eval()->tan();
return arg->eval(env)->tan();
case codes::UnaryOp::asin:
return arg->eval()->asin();
return arg->eval(env)->asin();
case codes::UnaryOp::acos:
return arg->eval()->acos();
return arg->eval(env)->acos();
case codes::UnaryOp::atan:
return arg->eval()->atan();
return arg->eval(env)->atan();
case codes::UnaryOp::sqrt:
return arg->eval()->sqrt();
return arg->eval(env)->sqrt();
case codes::UnaryOp::cbrt:
return arg->eval()->cbrt();
return arg->eval(env)->cbrt();
case codes::UnaryOp::sign:
return arg->eval()->sign();
return arg->eval(env)->sign();
case codes::UnaryOp::floor:
return arg->eval()->floor();
return arg->eval(env)->floor();
case codes::UnaryOp::ceil:
return arg->eval()->ceil();
return arg->eval(env)->ceil();
case codes::UnaryOp::trunc:
return arg->eval()->trunc();
return arg->eval(env)->trunc();
case codes::UnaryOp::sum:
return arg->eval()->sum();
return arg->eval(env)->sum();
case codes::UnaryOp::erf:
return arg->eval()->erf();
return arg->eval(env)->erf();
case codes::UnaryOp::erfc:
return arg->eval()->erfc();
return arg->eval(env)->erfc();
case codes::UnaryOp::gamma:
return arg->eval()->gamma();
return arg->eval(env)->gamma();
case codes::UnaryOp::lgamma:
return arg->eval()->lgamma();
return arg->eval(env)->lgamma();
case codes::UnaryOp::round:
return arg->eval()->round();
return arg->eval(env)->round();
case codes::UnaryOp::normpdf:
return arg->eval()->normpdf();
return arg->eval(env)->normpdf();
case codes::UnaryOp::normcdf:
return arg->eval()->normcdf();
return arg->eval(env)->normcdf();
case codes::UnaryOp::defined:
return arg->eval()->defined();
return arg->eval(env)->defined(env);
}
}
catch (StackTrace &ex)
@ -869,50 +869,50 @@ UnaryOp::eval()
}
BaseTypePtr
BinaryOp::eval()
BinaryOp::eval(Environment &env)
{
try
{
switch (op_code)
{
case codes::BinaryOp::plus:
return arg1->eval()->plus(arg2->eval());
return arg1->eval(env)->plus(arg2->eval(env));
case codes::BinaryOp::minus:
return arg1->eval()->minus(arg2->eval());
return arg1->eval(env)->minus(arg2->eval(env));
case codes::BinaryOp::times:
return arg1->eval()->times(arg2->eval());
return arg1->eval(env)->times(arg2->eval(env));
case codes::BinaryOp::divide:
return arg1->eval()->divide(arg2->eval());
return arg1->eval(env)->divide(arg2->eval(env));
case codes::BinaryOp::power:
return arg1->eval()->power(arg2->eval());
return arg1->eval(env)->power(arg2->eval(env));
case codes::BinaryOp::equal_equal:
return arg1->eval()->is_equal(arg2->eval());
return arg1->eval(env)->is_equal(arg2->eval(env));
case codes::BinaryOp::not_equal:
return arg1->eval()->is_different(arg2->eval());
return arg1->eval(env)->is_different(arg2->eval(env));
case codes::BinaryOp::less:
return arg1->eval()->is_less(arg2->eval());
return arg1->eval(env)->is_less(arg2->eval(env));
case codes::BinaryOp::greater:
return arg1->eval()->is_greater(arg2->eval());
return arg1->eval(env)->is_greater(arg2->eval(env));
case codes::BinaryOp::less_equal:
return arg1->eval()->is_less_equal(arg2->eval());
return arg1->eval(env)->is_less_equal(arg2->eval(env));
case codes::BinaryOp::greater_equal:
return arg1->eval()->is_greater_equal(arg2->eval());
return arg1->eval(env)->is_greater_equal(arg2->eval(env));
case codes::BinaryOp::logical_and:
return arg1->eval()->logical_and(arg2);
return arg1->eval(env)->logical_and(arg2, env);
case codes::BinaryOp::logical_or:
return arg1->eval()->logical_or(arg2);
return arg1->eval(env)->logical_or(arg2, env);
case codes::BinaryOp::in:
return arg2->eval()->contains(arg1->eval());
return arg2->eval(env)->contains(arg1->eval(env));
case codes::BinaryOp::set_union:
return arg1->eval()->set_union(arg2->eval());
return arg1->eval(env)->set_union(arg2->eval(env));
case codes::BinaryOp::set_intersection:
return arg1->eval()->set_intersection(arg2->eval());
return arg1->eval(env)->set_intersection(arg2->eval(env));
case codes::BinaryOp::max:
return arg1->eval()->max(arg2->eval());
return arg1->eval(env)->max(arg2->eval(env));
case codes::BinaryOp::min:
return arg1->eval()->min(arg2->eval());
return arg1->eval(env)->min(arg2->eval(env));
case codes::BinaryOp::mod:
return arg1->eval()->mod(arg2->eval());
return arg1->eval(env)->mod(arg2->eval(env));
}
}
catch (StackTrace &ex)
@ -929,16 +929,16 @@ BinaryOp::eval()
}
BaseTypePtr
TrinaryOp::eval()
TrinaryOp::eval(Environment &env)
{
try
{
switch (op_code)
{
case codes::TrinaryOp::normpdf:
return arg1->eval()->normpdf(arg2->eval(), arg3->eval());
return arg1->eval(env)->normpdf(arg2->eval(env), arg3->eval(env));
case codes::TrinaryOp::normcdf:
return arg1->eval()->normcdf(arg2->eval(), arg3->eval());
return arg1->eval(env)->normcdf(arg2->eval(env), arg3->eval(env));
}
}
catch (StackTrace &ex)
@ -955,14 +955,14 @@ TrinaryOp::eval()
}
BaseTypePtr
Comprehension::eval()
Comprehension::eval(Environment &env)
{
ArrayPtr input_set;
VariablePtr vp;
TuplePtr mt;
try
{
input_set = dynamic_pointer_cast<Array>(c_set->eval());
input_set = dynamic_pointer_cast<Array>(c_set->eval(env));
if (!input_set)
throw StackTrace("Comprehension", "The input set must evaluate to an array", location);
vp = dynamic_pointer_cast<Variable>(c_vars);
@ -1009,14 +1009,14 @@ Comprehension::eval()
if (!c_expr)
throw StackTrace("Comprehension", "Internal Error: Impossible case", location);
else
values.emplace_back(c_expr->clone()->eval());
values.emplace_back(c_expr->clone()->eval(env));
else
{
RealPtr dp;
BoolPtr bp;
try
{
auto tmp = c_when->eval();
auto tmp = c_when->eval(env);
dp = dynamic_pointer_cast<Real>(tmp);
bp = dynamic_pointer_cast<Bool>(tmp);
if (!bp && !dp)
@ -1029,12 +1029,12 @@ Comprehension::eval()
}
if ((bp && *bp) || (dp && *dp))
if (c_expr)
values.emplace_back(c_expr->clone()->eval());
values.emplace_back(c_expr->clone()->eval(env));
else
values.emplace_back(btp);
}
}
return make_shared<Array>(values, env);
return make_shared<Array>(values);
}
ExpressionPtr
@ -1043,7 +1043,7 @@ Tuple::clone() const noexcept
vector<ExpressionPtr> tup_copy;
for (const auto &it : tup)
tup_copy.emplace_back(it->clone());
return make_shared<Tuple>(tup_copy, env, location);
return make_shared<Tuple>(tup_copy, location);
}
ExpressionPtr
@ -1052,7 +1052,7 @@ Array::clone() const noexcept
vector<ExpressionPtr> arr_copy;
for (const auto &it : arr)
arr_copy.emplace_back(it->clone());
return make_shared<Array>(arr_copy, env, location);
return make_shared<Array>(arr_copy, location);
}
ExpressionPtr
@ -1061,18 +1061,18 @@ Function::clone() const noexcept
vector<ExpressionPtr> args_copy;
for (const auto &it : args)
args_copy.emplace_back(it->clone());
return make_shared<Function>(name, args_copy, env, location);
return make_shared<Function>(name, args_copy, location);
}
ExpressionPtr
Comprehension::clone() const noexcept
{
if (c_expr && c_when)
return make_shared<Comprehension>(c_expr->clone(), c_vars->clone(), c_set->clone(), c_when->clone(), env, location);
return make_shared<Comprehension>(c_expr->clone(), c_vars->clone(), c_set->clone(), c_when->clone(), location);
else if (c_expr)
return make_shared<Comprehension>(c_expr->clone(), c_vars->clone(), c_set->clone(), env, location);
return make_shared<Comprehension>(c_expr->clone(), c_vars->clone(), c_set->clone(), location);
else
return make_shared<Comprehension>(true, c_vars->clone(), c_set->clone(), c_when->clone(), env, location);
return make_shared<Comprehension>(true, c_vars->clone(), c_set->clone(), c_when->clone(), location);
}
string

View File

@ -81,11 +81,10 @@ namespace macro
class Node
{
protected:
Environment &env;
const Tokenizer::location location;
public:
Node(Environment &env_arg, Tokenizer::location location_arg) :
env{env_arg}, location{move(location_arg)} { }
explicit Node(Tokenizer::location location_arg) :
location{move(location_arg)} { }
virtual ~Node() = default;
public:
inline Tokenizer::location getLocation() const noexcept { return location; }
@ -113,11 +112,11 @@ namespace macro
class Expression : public Node
{
public:
Expression(Environment &env_arg, Tokenizer::location location_arg) :
Node(env_arg, move(location_arg)) { }
explicit Expression(Tokenizer::location location_arg) :
Node(move(location_arg)) { }
virtual string to_string() const noexcept = 0;
virtual void print(ostream &output, bool matlab_output = false) const noexcept = 0;
virtual BaseTypePtr eval() = 0;
virtual BaseTypePtr eval(Environment &env) = 0;
virtual ExpressionPtr clone() const noexcept = 0;
};
@ -125,10 +124,10 @@ namespace macro
class BaseType : public Expression, public enable_shared_from_this<BaseType>
{
public:
BaseType(Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
Expression(env_arg, move(location_arg)) { }
explicit BaseType(Tokenizer::location location_arg = Tokenizer::location()) :
Expression(move(location_arg)) { }
virtual codes::BaseType getType() const noexcept = 0;
inline BaseTypePtr eval() override { return shared_from_this(); }
inline BaseTypePtr eval(Environment &env) override { return shared_from_this(); }
public:
virtual BaseTypePtr plus(const BaseTypePtr &bt) const { throw StackTrace("Operator + does not exist for this type"); }
virtual BaseTypePtr unary_plus() const { throw StackTrace("Unary operator + does not exist for this type"); }
@ -143,20 +142,20 @@ namespace macro
virtual BoolPtr is_greater_equal(const BaseTypePtr &btp) const { throw StackTrace("Operator >= does not exist for this type"); }
virtual BoolPtr is_equal(const BaseTypePtr &btp) const = 0;
virtual BoolPtr is_different(const BaseTypePtr &btp) const final;
virtual BoolPtr logical_and(const ExpressionPtr &ep) const { throw StackTrace("Operator && does not exist for this type"); }
virtual BoolPtr logical_or(const ExpressionPtr &ep) const { throw StackTrace("Operator || does not exist for this type"); }
virtual BoolPtr logical_and(const ExpressionPtr &ep, Environment &env) const { throw StackTrace("Operator && does not exist for this type"); }
virtual BoolPtr logical_or(const ExpressionPtr &ep, Environment &env) const { throw StackTrace("Operator || does not exist for this type"); }
virtual BoolPtr logical_not() const { throw StackTrace("Operator ! does not exist for this type"); }
virtual ArrayPtr set_union(const BaseTypePtr &btp) const { throw StackTrace("Operator | does not exist for this type"); }
virtual ArrayPtr set_intersection(const BaseTypePtr &btp) const { throw StackTrace("Operator & does not exist for this type"); }
virtual BoolPtr contains(const BaseTypePtr &btp) const { throw StackTrace("Second argument of `in` operator must be an array"); }
virtual RealPtr length() const { throw StackTrace("Operator `length` does not exist for this type"); }
virtual BoolPtr isempty() const { throw StackTrace("Operator `isempty` does not exist for this type"); }
virtual BoolPtr isboolean() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr isreal() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr isinteger() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr isstring() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr istuple() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr isarray() const noexcept { return make_shared<Bool>(false, env, location); }
virtual BoolPtr isboolean() const noexcept { return make_shared<Bool>(false, location); }
virtual BoolPtr isreal() const noexcept { return make_shared<Bool>(false, location); }
virtual BoolPtr isinteger() const noexcept { return make_shared<Bool>(false, location); }
virtual BoolPtr isstring() const noexcept { return make_shared<Bool>(false, location); }
virtual BoolPtr istuple() const noexcept { return make_shared<Bool>(false, location); }
virtual BoolPtr isarray() const noexcept { return make_shared<Bool>(false, location); }
virtual RealPtr max(const BaseTypePtr &btp) const { throw StackTrace("Operator `max` does not exist for this type"); }
virtual RealPtr min(const BaseTypePtr &btp) const { throw StackTrace("Operator `min` does not exist for this type"); }
virtual RealPtr mod(const BaseTypePtr &btp) const { throw StackTrace("Operator `mod` does not exist for this type"); }
@ -189,12 +188,12 @@ namespace macro
virtual RealPtr normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const { throw StackTrace("Operator `normpdf` does not exist for this type"); }
virtual RealPtr normcdf() const { throw StackTrace("Operator `normcdf` does not exist for this type"); }
virtual RealPtr normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const { throw StackTrace("Operator `normcdf` does not exist for this type"); }
virtual BoolPtr cast_bool() const { throw StackTrace("This type cannot be cast to a boolean"); }
virtual RealPtr cast_real() const { throw StackTrace("This type cannot be cast to a real"); }
virtual BoolPtr cast_bool(Environment &env) const { throw StackTrace("This type cannot be cast to a boolean"); }
virtual RealPtr cast_real(Environment &env) const { throw StackTrace("This type cannot be cast to a real"); }
virtual StringPtr cast_string() const { throw StackTrace("This type cannot be cast to a string"); }
virtual TuplePtr cast_tuple() const { throw StackTrace("This type cannot be cast to a tuple"); }
virtual ArrayPtr cast_array() const { throw StackTrace("This type cannot be cast to an array"); }
virtual BoolPtr defined() const { throw StackTrace("Operator `defined` does not exist for this type"); }
virtual BoolPtr defined(const Environment &env) const { throw StackTrace("Operator `defined` does not exist for this type"); }
};
@ -204,30 +203,30 @@ namespace macro
const bool value;
public:
Bool(bool value_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{value_arg} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::Bool; }
inline string to_string() const noexcept override { return value ? "true" : "false"; }
inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); }
inline ExpressionPtr clone() const noexcept override { return make_shared<Bool>(value, env, location); }
inline ExpressionPtr clone() const noexcept override { return make_shared<Bool>(value, location); }
public:
operator bool() const { return value; }
BoolPtr is_equal(const BaseTypePtr &btp) const override;
BoolPtr logical_and(const ExpressionPtr &ep) const override;
BoolPtr logical_or(const ExpressionPtr &ep) const override;
BoolPtr logical_and(const ExpressionPtr &ep, Environment &env) const override;
BoolPtr logical_or(const ExpressionPtr &ep, Environment &env) const override;
BoolPtr logical_not() const override;
inline BoolPtr isboolean() const noexcept override { return make_shared<Bool>(true, env, location); }
inline BoolPtr cast_bool() const override { return make_shared<Bool>(value, env); }
inline RealPtr cast_real() const override { return value ? make_shared<Real>(1, env) : make_shared<Real>(0, env); }
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
inline BoolPtr isboolean() const noexcept override { return make_shared<Bool>(true, location); }
inline BoolPtr cast_bool(Environment &env) const override { return make_shared<Bool>(value); }
inline RealPtr cast_real(Environment &env) const override { return value ? make_shared<Real>(1) : make_shared<Real>(0); }
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
inline TuplePtr cast_tuple() const override
{
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Bool>(value, env)}, env);
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Bool>(value)});
}
inline ArrayPtr cast_array() const override
{
return make_shared<Array>(vector<ExpressionPtr>{make_shared<Bool>(value, env)}, env);
return make_shared<Array>(vector<ExpressionPtr>{make_shared<Bool>(value)});
}
};
@ -240,12 +239,12 @@ namespace macro
// Use strtod to handle extreme cases (e.g. 1e500, 1e-500), nan, inf
// See Note in NumericalConstants::AddNonNegativeConstant
Real(const string &value_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{strtod(value_arg.c_str(), nullptr)} { }
Real(double value_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{value_arg} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::Real; }
inline string to_string() const noexcept override
@ -255,13 +254,13 @@ namespace macro
return strs.str();
}
inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); }
inline ExpressionPtr clone() const noexcept override { return make_shared<Real>(value, env, location); }
inline ExpressionPtr clone() const noexcept override { return make_shared<Real>(value, location); }
public:
operator double() const { return value; }
BaseTypePtr plus(const BaseTypePtr &bt) const override;
inline BaseTypePtr unary_plus() const override { return make_shared<Real>(value, env); }
inline BaseTypePtr unary_plus() const override { return make_shared<Real>(value); }
BaseTypePtr minus(const BaseTypePtr &bt) const override;
inline BaseTypePtr unary_minus() const override { return make_shared<Real>(-value, env); }
inline BaseTypePtr unary_minus() const override { return make_shared<Real>(-value); }
BaseTypePtr times(const BaseTypePtr &bt) const override;
BaseTypePtr divide(const BaseTypePtr &bt) const override;
BaseTypePtr power(const BaseTypePtr &btp) const override;
@ -270,65 +269,65 @@ namespace macro
BoolPtr is_less_equal(const BaseTypePtr &btp) const override;
BoolPtr is_greater_equal(const BaseTypePtr &btp) const override;
BoolPtr is_equal(const BaseTypePtr &btp) const override;
inline BoolPtr isreal() const noexcept override { return make_shared<Bool>(true, env, location); }
inline BoolPtr isreal() const noexcept override { return make_shared<Bool>(true, location); }
inline BoolPtr isinteger() const noexcept override
{
double intpart;
return make_shared<Bool>(modf(value, &intpart) == 0.0, env, location);
return make_shared<Bool>(modf(value, &intpart) == 0.0, location);
}
BoolPtr logical_and(const ExpressionPtr &ep) const override;
BoolPtr logical_or(const ExpressionPtr &ep) const override;
BoolPtr logical_and(const ExpressionPtr &ep, Environment &env) const override;
BoolPtr logical_or(const ExpressionPtr &ep, Environment &env) const override;
BoolPtr logical_not() const override;
RealPtr max(const BaseTypePtr &btp) const override;
RealPtr min(const BaseTypePtr &btp) const override;
RealPtr mod(const BaseTypePtr &btp) const override;
inline RealPtr exp() const override { return make_shared<Real>(std::exp(value), env); }
inline RealPtr ln() const override { return make_shared<Real>(std::log(value), env); }
inline RealPtr log10() const override { return make_shared<Real>(std::log10(value), env); }
inline BoolPtr isinf() const override { return make_shared<Bool>(std::isinf(value), env); }
inline BoolPtr isnan() const override { return make_shared<Bool>(std::isnan(value), env); }
inline BoolPtr isfinite() const override { return make_shared<Bool>(std::isfinite(value), env); }
inline BoolPtr isnormal() const override { return make_shared<Bool>(std::isnormal(value), env); }
inline RealPtr sin() const override { return make_shared<Real>(std::sin(value), env); }
inline RealPtr cos() const override { return make_shared<Real>(std::cos(value), env); }
inline RealPtr tan() const override { return make_shared<Real>(std::tan(value), env); }
inline RealPtr asin() const override { return make_shared<Real>(std::asin(value), env); }
inline RealPtr acos() const override { return make_shared<Real>(std::acos(value), env); }
inline RealPtr atan() const override { return make_shared<Real>(std::atan(value), env); }
inline RealPtr sqrt() const override { return make_shared<Real>(std::sqrt(value), env); }
inline RealPtr cbrt() const override { return make_shared<Real>(std::cbrt(value), env); }
inline RealPtr exp() const override { return make_shared<Real>(std::exp(value)); }
inline RealPtr ln() const override { return make_shared<Real>(std::log(value)); }
inline RealPtr log10() const override { return make_shared<Real>(std::log10(value)); }
inline BoolPtr isinf() const override { return make_shared<Bool>(std::isinf(value)); }
inline BoolPtr isnan() const override { return make_shared<Bool>(std::isnan(value)); }
inline BoolPtr isfinite() const override { return make_shared<Bool>(std::isfinite(value)); }
inline BoolPtr isnormal() const override { return make_shared<Bool>(std::isnormal(value)); }
inline RealPtr sin() const override { return make_shared<Real>(std::sin(value)); }
inline RealPtr cos() const override { return make_shared<Real>(std::cos(value)); }
inline RealPtr tan() const override { return make_shared<Real>(std::tan(value)); }
inline RealPtr asin() const override { return make_shared<Real>(std::asin(value)); }
inline RealPtr acos() const override { return make_shared<Real>(std::acos(value)); }
inline RealPtr atan() const override { return make_shared<Real>(std::atan(value)); }
inline RealPtr sqrt() const override { return make_shared<Real>(std::sqrt(value)); }
inline RealPtr cbrt() const override { return make_shared<Real>(std::cbrt(value)); }
inline RealPtr sign() const override
{
return make_shared<Real>((value > 0) ? 1. : ((value < 0) ? -1. : 0.), env);
return make_shared<Real>((value > 0) ? 1. : ((value < 0) ? -1. : 0.));
}
inline RealPtr floor() const override { return make_shared<Real>(std::floor(value), env); }
inline RealPtr ceil() const override { return make_shared<Real>(std::ceil(value), env); }
inline RealPtr trunc() const override { return make_shared<Real>(std::trunc(value), env); }
inline RealPtr erf() const override { return make_shared<Real>(std::erf(value), env); }
inline RealPtr erfc() const override { return make_shared<Real>(std::erfc(value), env); }
inline RealPtr gamma() const override { return make_shared<Real>(std::tgamma(value), env); }
inline RealPtr lgamma() const override { return make_shared<Real>(std::lgamma(value), env); }
inline RealPtr round() const override { return make_shared<Real>(std::round(value), env); }
inline RealPtr floor() const override { return make_shared<Real>(std::floor(value)); }
inline RealPtr ceil() const override { return make_shared<Real>(std::ceil(value)); }
inline RealPtr trunc() const override { return make_shared<Real>(std::trunc(value)); }
inline RealPtr erf() const override { return make_shared<Real>(std::erf(value)); }
inline RealPtr erfc() const override { return make_shared<Real>(std::erfc(value)); }
inline RealPtr gamma() const override { return make_shared<Real>(std::tgamma(value)); }
inline RealPtr lgamma() const override { return make_shared<Real>(std::lgamma(value)); }
inline RealPtr round() const override { return make_shared<Real>(std::round(value)); }
inline RealPtr normpdf() const override
{
return normpdf(make_shared<Real>(0, env), make_shared<Real>(1, env));
return normpdf(make_shared<Real>(0), make_shared<Real>(1));
}
RealPtr normpdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const override;
inline RealPtr normcdf() const override
{
return normcdf(make_shared<Real>(0, env), make_shared<Real>(1, env));
return normcdf(make_shared<Real>(0), make_shared<Real>(1));
}
RealPtr normcdf(const BaseTypePtr &btp1, const BaseTypePtr &btp2) const override;
inline BoolPtr cast_bool() const override { return make_shared<Bool>(static_cast<bool>(value), env); }
inline RealPtr cast_real() const override { return make_shared<Real>(value, env); }
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
inline BoolPtr cast_bool(Environment &env) const override { return make_shared<Bool>(static_cast<bool>(value)); }
inline RealPtr cast_real(Environment &env) const override { return make_shared<Real>(value); }
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
inline TuplePtr cast_tuple() const override
{
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Real>(value, env)}, env);
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<Real>(value)});
}
inline ArrayPtr cast_array() const override
{
return make_shared<Array>(vector<ExpressionPtr>{make_shared<Real>(value, env)}, env);
return make_shared<Array>(vector<ExpressionPtr>{make_shared<Real>(value)});
}
};
@ -338,13 +337,13 @@ namespace macro
const string value;
public:
String(string value_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{move(value_arg)} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::String; }
inline string to_string() const noexcept override { return value; }
void print(ostream &output, bool matlab_output = false) const noexcept override;
inline ExpressionPtr clone() const noexcept override { return make_shared<String>(value, env, location); }
inline ExpressionPtr clone() const noexcept override { return make_shared<String>(value, location); }
public:
operator string() const { return value; }
BaseTypePtr plus(const BaseTypePtr &bt) const override;
@ -353,23 +352,23 @@ namespace macro
BoolPtr is_less_equal(const BaseTypePtr &btp) const override;
BoolPtr is_greater_equal(const BaseTypePtr &btp) const override;
BoolPtr is_equal(const BaseTypePtr &btp) const override;
inline BoolPtr isstring() const noexcept override { return make_shared<Bool>(true, env, location); }
inline RealPtr length() const override { return make_shared<Real>(value.size(), env); }
inline BoolPtr isempty() const override { return make_shared<Bool>(value.empty(), env); }
BoolPtr cast_bool() const override;
RealPtr cast_real() const override;
inline StringPtr cast_string() const override { return make_shared<String>(value, env); }
inline BoolPtr isstring() const noexcept override { return make_shared<Bool>(true, location); }
inline RealPtr length() const override { return make_shared<Real>(value.size()); }
inline BoolPtr isempty() const override { return make_shared<Bool>(value.empty()); }
BoolPtr cast_bool(Environment &env) const override;
RealPtr cast_real(Environment &env) const override;
inline StringPtr cast_string() const override { return make_shared<String>(value); }
inline TuplePtr cast_tuple() const override
{
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<String>(value, env)}, env);
return make_shared<Tuple>(vector<ExpressionPtr>{make_shared<String>(value)});
}
inline ArrayPtr cast_array() const override
{
return make_shared<Array>(vector<ExpressionPtr>{make_shared<String>(value, env)}, env);
return make_shared<Array>(vector<ExpressionPtr>{make_shared<String>(value)});
}
inline BoolPtr defined() const override
inline BoolPtr defined(const Environment &env) const override
{
return make_shared<Bool>(env.isSymbolDefined(value), env);
return make_shared<Bool>(env.isSymbolDefined(value));
}
};
@ -380,13 +379,13 @@ namespace macro
const vector<ExpressionPtr> tup;
public:
Tuple(vector<ExpressionPtr> tup_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
tup{move(tup_arg)} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::Tuple; }
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
ExpressionPtr clone() const noexcept override;
public:
inline size_t size() const { return tup.size(); }
@ -394,15 +393,15 @@ namespace macro
inline const vector<ExpressionPtr> &getValue() const { return tup; }
inline const ExpressionPtr &at(int i) const { return tup.at(i); }
BoolPtr is_equal(const BaseTypePtr &btp) const override;
inline BoolPtr istuple() const noexcept override { return make_shared<Bool>(true, env, location); }
inline BoolPtr istuple() const noexcept override { return make_shared<Bool>(true, location); }
BoolPtr contains(const BaseTypePtr &btp) const override;
inline RealPtr length() const override { return make_shared<Real>(tup.size(), env); }
inline BoolPtr isempty() const override { return make_shared<Bool>(empty(), env); }
BoolPtr cast_bool() const override;
RealPtr cast_real() const override;
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(tup, env); }
inline ArrayPtr cast_array() const override { return make_shared<Array>(tup, env); }
inline RealPtr length() const override { return make_shared<Real>(tup.size()); }
inline BoolPtr isempty() const override { return make_shared<Bool>(empty()); }
BoolPtr cast_bool(Environment &env) const override;
RealPtr cast_real(Environment &env) const override;
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(tup); }
inline ArrayPtr cast_array() const override { return make_shared<Array>(tup); }
};
@ -412,12 +411,12 @@ namespace macro
const vector<ExpressionPtr> arr;
public:
Array(vector<ExpressionPtr> arr_arg,
Environment &env_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(env_arg, move(location_arg)), arr{move(arr_arg)} { }
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), arr{move(arr_arg)} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::Array; }
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
ExpressionPtr clone() const noexcept override;
public:
inline size_t size() const { return arr.size(); }
@ -429,18 +428,18 @@ namespace macro
BaseTypePtr times(const BaseTypePtr &bt) const override;
BaseTypePtr power(const BaseTypePtr &btp) const override;
BoolPtr is_equal(const BaseTypePtr &btp) const override;
inline BoolPtr isarray() const noexcept override { return make_shared<Bool>(true, env, location); }
inline BoolPtr isarray() const noexcept override { return make_shared<Bool>(true, location); }
ArrayPtr set_union(const BaseTypePtr &btp) const override;
ArrayPtr set_intersection(const BaseTypePtr &btp) const override;
BoolPtr contains(const BaseTypePtr &btp) const override;
inline RealPtr length() const override { return make_shared<Real>(arr.size(), env); }
inline BoolPtr isempty() const override { return make_shared<Bool>(empty(), env); }
inline RealPtr length() const override { return make_shared<Real>(arr.size()); }
inline BoolPtr isempty() const override { return make_shared<Bool>(empty()); }
RealPtr sum() const override;
BoolPtr cast_bool() const override;
RealPtr cast_real() const override;
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string(), env); }
inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(arr, env); }
inline ArrayPtr cast_array() const override { return make_shared<Array>(arr, env); }
BoolPtr cast_bool(Environment &env) const override;
RealPtr cast_real(Environment &env) const override;
inline StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
inline TuplePtr cast_tuple() const override { return make_shared<Tuple>(arr); }
inline ArrayPtr cast_array() const override { return make_shared<Array>(arr); }
};
@ -450,11 +449,11 @@ namespace macro
const ExpressionPtr start, inc, end;
public:
Range(ExpressionPtr start_arg, ExpressionPtr end_arg,
Environment &env_arg, Tokenizer::location location_arg) :
BaseType(env_arg, move(location_arg)), start{move(start_arg)}, end{move(end_arg)} { }
Tokenizer::location location_arg) :
BaseType(move(location_arg)), start{move(start_arg)}, end{move(end_arg)} { }
Range(ExpressionPtr start_arg, ExpressionPtr inc_arg, ExpressionPtr end_arg,
Environment &env_arg, Tokenizer::location location_arg) :
BaseType(env_arg, move(location_arg)),
Tokenizer::location location_arg) :
BaseType(move(location_arg)),
start{move(start_arg)}, inc{move(inc_arg)}, end{move(end_arg)} { }
inline codes::BaseType getType() const noexcept override { return codes::BaseType::Range; }
inline string to_string() const noexcept override
@ -465,12 +464,12 @@ namespace macro
return retval + end->to_string() + "]";
}
inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); }
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
inline ExpressionPtr clone() const noexcept override
{
return inc ?
make_shared<Range>(start, inc, end, env, location)
: make_shared<Range>(start, end, env, location);
make_shared<Range>(start, inc, end, location)
: make_shared<Range>(start, end, location);
}
public:
inline BoolPtr is_equal(const BaseTypePtr &btp) const override
@ -487,22 +486,22 @@ namespace macro
const ArrayPtr indices; // for indexing strings/arrays
public:
Variable(string name_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), name{move(name_arg)} { }
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)} { }
Variable(string name_arg, ArrayPtr indices_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), name{move(name_arg)}, indices{move(indices_arg)} { }
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)}, indices{move(indices_arg)} { }
inline string to_string() const noexcept override { return name; }
inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << name; }
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
inline ExpressionPtr clone() const noexcept override
{
return indices ? make_shared<Variable>(name, indices, env, location) :
make_shared<Variable>(name, env, location);
return indices ? make_shared<Variable>(name, indices, location) :
make_shared<Variable>(name, location);
}
public:
inline const string &getName() const noexcept { return name; }
inline codes::BaseType getType() const { return env.getType(name); }
inline codes::BaseType getType(const Environment &env) const { return env.getType(name); }
};
@ -514,14 +513,14 @@ namespace macro
public:
Function(string name_arg,
vector<ExpressionPtr> args_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), name{move(name_arg)}, args{move(args_arg)} { }
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)}, args{move(args_arg)} { }
string to_string() const noexcept override;
inline void print(ostream &output, bool matlab_output = false) const noexcept override
{
printName(output); printArgs(output);
}
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
ExpressionPtr clone() const noexcept override;
public:
inline void printName(ostream &output) const noexcept { output << name; }
@ -539,14 +538,14 @@ namespace macro
public:
UnaryOp(codes::UnaryOp op_code_arg,
ExpressionPtr arg_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), op_code{move(op_code_arg)}, arg{move(arg_arg)} { }
Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code{move(op_code_arg)}, arg{move(arg_arg)} { }
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
inline ExpressionPtr clone() const noexcept override
{
return make_shared<UnaryOp>(op_code, arg->clone(), env, location);
return make_shared<UnaryOp>(op_code, arg->clone(), location);
}
};
@ -559,16 +558,16 @@ namespace macro
public:
BinaryOp(codes::BinaryOp op_code_arg,
ExpressionPtr arg1_arg, ExpressionPtr arg2_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), op_code{op_code_arg},
Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code{op_code_arg},
arg1{move(arg1_arg)}, arg2{move(arg2_arg)} { }
public:
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
inline ExpressionPtr clone() const noexcept override
{
return make_shared<BinaryOp>(op_code, arg1->clone(), arg2->clone(), env, location);
return make_shared<BinaryOp>(op_code, arg1->clone(), arg2->clone(), location);
}
};
@ -581,15 +580,15 @@ namespace macro
public:
TrinaryOp(codes::TrinaryOp op_code_arg,
ExpressionPtr arg1_arg, ExpressionPtr arg2_arg, ExpressionPtr arg3_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)), op_code{op_code_arg},
Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code{op_code_arg},
arg1{move(arg1_arg)}, arg2{move(arg2_arg)}, arg3{move(arg3_arg)} { }
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
inline ExpressionPtr clone() const noexcept override
{
return make_shared<TrinaryOp>(op_code, arg1->clone(), arg2->clone(), arg3->clone(), env, location);
return make_shared<TrinaryOp>(op_code, arg1->clone(), arg2->clone(), arg3->clone(), location);
}
};
@ -608,26 +607,26 @@ namespace macro
ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg,
ExpressionPtr c_when_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)),
Tokenizer::location location_arg) :
Expression(move(location_arg)),
c_expr{move(c_expr_arg)}, c_vars{move(c_vars_arg)},
c_set{move(c_set_arg)}, c_when{move(c_when_arg)} { }
Comprehension(ExpressionPtr c_expr_arg,
ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)),
Tokenizer::location location_arg) :
Expression(move(location_arg)),
c_expr{move(c_expr_arg)}, c_vars{move(c_vars_arg)}, c_set{move(c_set_arg)} { }
Comprehension(bool filter_only_arg,
ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg,
ExpressionPtr c_when_arg,
Environment &env_arg, Tokenizer::location location_arg) :
Expression(env_arg, move(location_arg)),
Tokenizer::location location_arg) :
Expression(move(location_arg)),
c_vars{move(c_vars_arg)}, c_set{move(c_set_arg)}, c_when{move(c_when_arg)} { }
string to_string() const noexcept override;
void print(ostream &output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval() override;
BaseTypePtr eval(Environment &env) override;
ExpressionPtr clone() const noexcept override;
};
}

View File

@ -126,35 +126,35 @@ directive : directive_one_line EOL
;
directive_one_line : INCLUDE expr
{ $$ = make_shared<Include>($2, driver.env, @$); }
{ $$ = make_shared<Include>($2, @$); }
| INCLUDEPATH expr
{ $$ = make_shared<IncludePath>($2, driver.env, @$); }
{ $$ = make_shared<IncludePath>($2, @$); }
| DEFINE symbol
{
auto tmp = make_shared<Real>("1", driver.env, @$);
$$ = make_shared<Define>($2, tmp, driver.env, @$);
auto tmp = make_shared<Real>("1", @$);
$$ = make_shared<Define>($2, tmp, @$);
}
| DEFINE symbol EQUAL expr
{ $$ = make_shared<Define>($2, $4, driver.env, @$); }
{ $$ = make_shared<Define>($2, $4, @$); }
| DEFINE function EQUAL expr
{ $$ = make_shared<Define>($2, $4, driver.env, @$); }
{ $$ = make_shared<Define>($2, $4, @$); }
| D_ECHO expr
{ $$ = make_shared<Echo>($2, driver.env, @$); }
{ $$ = make_shared<Echo>($2, @$); }
| ERROR expr
{ $$ = make_shared<Error>($2, driver.env, @$); }
{ $$ = make_shared<Error>($2, @$); }
| ECHOMACROVARS
{ $$ = make_shared<EchoMacroVars>(false, driver.env, @$); }
{ $$ = make_shared<EchoMacroVars>(false, @$); }
| ECHOMACROVARS name_list
{ $$ = make_shared<EchoMacroVars>(false, $2, driver.env, @$); }
{ $$ = make_shared<EchoMacroVars>(false, $2, @$); }
| ECHOMACROVARS LPAREN SAVE RPAREN
{ $$ = make_shared<EchoMacroVars>(true, driver.env, @$); }
{ $$ = make_shared<EchoMacroVars>(true, @$); }
| ECHOMACROVARS LPAREN SAVE RPAREN name_list
{ $$ = make_shared<EchoMacroVars>(true, $5, driver.env, @$); }
{ $$ = make_shared<EchoMacroVars>(true, $5, @$); }
| LINE QUOTED_STRING NUMBER
{
// `@#line` is ignored; adjust newlines in output to accord
auto l = static_cast<Tokenizer::parser::location_type>(@$);
$$ = make_shared<TextNode>(string(l.end.line - l.begin.line + 1, '\n'), driver.env, @$);
$$ = make_shared<TextNode>(string(l.end.line - l.begin.line + 1, '\n'), @$);
}
;
@ -198,28 +198,28 @@ for : FOR { driver.pushContext(); } expr IN expr for_when EOL statements ENDFOR
error(@1, "For loop indices must be a variable or a tuple");
auto vdp = driver.popContext();
vdp.emplace_back(make_shared<TextNode>("\n", driver.env, @9));
vdp.emplace_back(make_shared<TextNode>("\n", @9));
if (!$6)
$$ = make_shared<For>(vvnp, $5, vdp, driver.env, @$);
$$ = make_shared<For>(vvnp, $5, vdp, @$);
else
{
auto tmpc = make_shared<Comprehension>(true, $3, $5, $6, driver.env, @6);
$$ = make_shared<For>(vvnp, tmpc, vdp, driver.env, @$);
auto tmpc = make_shared<Comprehension>(true, $3, $5, $6, @6);
$$ = make_shared<For>(vvnp, tmpc, vdp, @$);
}
}
;
if : IF { driver.pushContext(); } if_list ENDIF
{ $$ = make_shared<If>($3, driver.env, @$); }
{ $$ = make_shared<If>($3, @$); }
;
ifdef : IFDEF { driver.pushContext(); } if_list ENDIF
{ $$ = make_shared<Ifdef>($3, driver.env, @$); }
{ $$ = make_shared<Ifdef>($3, @$); }
;
ifndef : IFNDEF { driver.pushContext(); } if_list ENDIF
{ $$ = make_shared<Ifndef>($3, driver.env, @$); }
{ $$ = make_shared<Ifndef>($3, @$); }
;
if_list : if_list1
@ -233,13 +233,13 @@ if_list : if_list1
if_list1 : expr EOL
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @2));
context.emplace_back(make_shared<TextNode>("\n", @2));
$$ = {{$1, context}};
}
| expr EOL statements
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @3));
context.emplace_back(make_shared<TextNode>("\n", @3));
$$ = {{$1, context}};
}
| if_list1 elseif
@ -254,13 +254,13 @@ elseif_begin : ELSEIF { driver.pushContext(); } ;
elseif : elseif_begin expr EOL
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @3));
context.emplace_back(make_shared<TextNode>("\n", @3));
$$ = {$2, context};
}
| elseif_begin expr EOL statements
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @4));
context.emplace_back(make_shared<TextNode>("\n", @4));
$$ = {$2, context};
}
;
@ -270,35 +270,35 @@ else_begin : ELSE { driver.pushContext(); } ;
else : else_begin EOL
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @2));
$$ = {make_shared<Bool>(true, driver.env, @1), context};
context.emplace_back(make_shared<TextNode>("\n", @2));
$$ = {make_shared<Bool>(true, @1), context};
}
| else_begin EOL statements
{
auto context = driver.popContext();
context.emplace_back(make_shared<TextNode>("\n", driver.env, @3));
$$ = {make_shared<Bool>(true, driver.env, @1), context};
context.emplace_back(make_shared<TextNode>("\n", @3));
$$ = {make_shared<Bool>(true, @1), context};
}
;
text : TEXT
{ $$ = make_shared<TextNode>($1, driver.env, @$); }
{ $$ = make_shared<TextNode>($1, @$); }
| EOL
{ $$ = make_shared<TextNode>($1, driver.env, @$); }
{ $$ = make_shared<TextNode>($1, @$); }
;
eval : BEGIN_EVAL expr END_EVAL
{ $$ = make_shared<Eval>($2, driver.env, @$); }
{ $$ = make_shared<Eval>($2, @$); }
;
symbol : NAME
{ $$ = make_shared<Variable>($1, driver.env, @$); }
{ $$ = make_shared<Variable>($1, @$); }
;
function : NAME LPAREN RPAREN
{ $$ = make_shared<Function>($1, vector<ExpressionPtr>(), driver.env, @$); }
{ $$ = make_shared<Function>($1, vector<ExpressionPtr>(), @$); }
| NAME LPAREN function_args RPAREN
{ $$ = make_shared<Function>($1, $3, driver.env, @$); }
{ $$ = make_shared<Function>($1, $3, @$); }
;
function_args : symbol
@ -331,164 +331,163 @@ primary_expr : LPAREN expr RPAREN
{ $$ = $1; } // Explicit rule needed for type conversion
| NAME LBRACKET comma_expr RBRACKET
{
$$ = make_shared<Variable>($1, make_shared<Array>($3, driver.env, @3),
driver.env, @$);
$$ = make_shared<Variable>($1, make_shared<Array>($3, @3), @$);
}
| NAME LPAREN comma_expr RPAREN
{ $$ = make_shared<Function>($1, $3, driver.env, @$); }
{ $$ = make_shared<Function>($1, $3, @$); }
| TRUE
{ $$ = make_shared<Bool>(true, driver.env, @$); }
{ $$ = make_shared<Bool>(true, @$); }
| FALSE
{ $$ = make_shared<Bool>(false, driver.env, @$); }
{ $$ = make_shared<Bool>(false, @$); }
| NUMBER
{ $$ = make_shared<Real>($1, driver.env, @$); }
{ $$ = make_shared<Real>($1, @$); }
| QUOTED_STRING
{ $$ = make_shared<String>($1, driver.env, @$); }
{ $$ = make_shared<String>($1, @$); }
| LBRACKET comma_expr RBRACKET
{ $$ = make_shared<Array>($2, driver.env, @$); }
{ $$ = make_shared<Array>($2, @$); }
| LPAREN tuple_comma_expr RPAREN
{ $$ = make_shared<Tuple>($2, driver.env, @$); }
{ $$ = make_shared<Tuple>($2, @$); }
| LBRACKET expr IN expr WHEN expr RBRACKET
{ $$ = make_shared<Comprehension>(true, $2, $4, $6, driver.env, @$); }
{ $$ = make_shared<Comprehension>(true, $2, $4, $6, @$); }
| LBRACKET expr FOR expr IN expr RBRACKET
{ $$ = make_shared<Comprehension>($2, $4, $6, driver.env, @$); }
{ $$ = make_shared<Comprehension>($2, $4, $6, @$); }
| LBRACKET expr FOR expr IN expr WHEN expr RBRACKET
{ $$ = make_shared<Comprehension>($2, $4, $6, $8, driver.env, @$); }
{ $$ = make_shared<Comprehension>($2, $4, $6, $8, @$); }
| LENGTH LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::length, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::length, $3, @$); }
| ISEMPTY LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isempty, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isempty, $3, @$); }
| ISBOOLEAN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isboolean, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isboolean, $3, @$); }
| ISREAL LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isreal, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isreal, $3, @$); }
| ISSTRING LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isstring, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isstring, $3, @$); }
| ISTUPLE LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::istuple, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::istuple, $3, @$); }
| ISARRAY LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isarray, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::isarray, $3, @$); }
| EXP LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::exp, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::exp, $3, @$); }
| LOG LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ln, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ln, $3, @$); }
| LN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ln, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ln, $3, @$); }
| LOG10 LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::log10, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::log10, $3, @$); }
| SIN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sin, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sin, $3, @$); }
| COS LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cos, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cos, $3, @$); }
| TAN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::tan, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::tan, $3, @$); }
| ASIN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::asin, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::asin, $3, @$); }
| ACOS LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::acos, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::acos, $3, @$); }
| ATAN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::atan, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::atan, $3, @$); }
| SQRT LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sqrt, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sqrt, $3, @$); }
| CBRT LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cbrt, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cbrt, $3, @$); }
| SIGN LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sign, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sign, $3, @$); }
| FLOOR LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::floor, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::floor, $3, @$); }
| CEIL LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ceil, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::ceil, $3, @$); }
| TRUNC LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::trunc, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::trunc, $3, @$); }
| SUM LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sum, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::sum, $3, @$); }
| ERF LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::erf, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::erf, $3, @$); }
| ERFC LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::erfc, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::erfc, $3, @$); }
| GAMMA LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::gamma, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::gamma, $3, @$); }
| LGAMMA LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::lgamma, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::lgamma, $3, @$); }
| ROUND LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::round, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::round, $3, @$); }
| NORMPDF LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::normpdf, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::normpdf, $3, @$); }
| NORMCDF LPAREN expr RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::normcdf, $3, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::normcdf, $3, @$); }
| MAX LPAREN expr COMMA expr RPAREN
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::max, $3, $5, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::max, $3, $5, @$); }
| MIN LPAREN expr COMMA expr RPAREN
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::min, $3, $5, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::min, $3, $5, @$); }
| MOD LPAREN expr COMMA expr RPAREN
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::mod, $3, $5, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::mod, $3, $5, @$); }
| NORMPDF LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normpdf, $3, $5, $7, driver.env, @$); }
{ $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normpdf, $3, $5, $7, @$); }
| NORMCDF LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normcdf, $3, $5, $7, driver.env, @$); }
{ $$ = make_shared<TrinaryOp>(codes::TrinaryOp::normcdf, $3, $5, $7, @$); }
| DEFINED LPAREN NAME RPAREN
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::defined, make_shared<String>($3, driver.env, @3), driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::defined, make_shared<String>($3, @3), @$); }
;
oper_expr : primary_expr
| LPAREN BOOL RPAREN oper_expr %prec CAST
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_bool, $4, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_bool, $4, @$); }
| LPAREN REAL RPAREN oper_expr %prec CAST
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_real, $4, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_real, $4, @$); }
| LPAREN STRING RPAREN oper_expr %prec CAST
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_string, $4, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_string, $4, @$); }
| LPAREN TUPLE RPAREN oper_expr %prec CAST
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_tuple, $4, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_tuple, $4, @$); }
| LPAREN ARRAY RPAREN oper_expr %prec CAST
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_array, $4, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::cast_array, $4, @$); }
| NOT oper_expr
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::logical_not, $2, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::logical_not, $2, @$); }
| MINUS oper_expr %prec UNARY
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::unary_minus, $2, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::unary_minus, $2, @$); }
| PLUS oper_expr %prec UNARY
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::unary_plus, $2, driver.env, @$); }
{ $$ = make_shared<UnaryOp>(codes::UnaryOp::unary_plus, $2, @$); }
| oper_expr PLUS oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::plus, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::plus, $1, $3, @$); }
| oper_expr MINUS oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::minus, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::minus, $1, $3, @$); }
| oper_expr TIMES oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::times, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::times, $1, $3, @$); }
| oper_expr DIVIDE oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::divide, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::divide, $1, $3, @$); }
| oper_expr POWER oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::power, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::power, $1, $3, @$); }
| oper_expr UNION oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::set_union, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::set_union, $1, $3, @$); }
| oper_expr INTERSECTION oper_expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::set_intersection, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::set_intersection, $1, $3, @$); }
;
colon_expr : oper_expr COLON oper_expr
{ $$ = make_shared<Range>($1, $3, driver.env, @$); }
{ $$ = make_shared<Range>($1, $3, @$); }
| oper_expr COLON oper_expr COLON oper_expr
{ $$ = make_shared<Range>($1, $3, $5, driver.env, @$); }
{ $$ = make_shared<Range>($1, $3, $5, @$); }
;
expr : oper_expr
| colon_expr
| expr EQUAL_EQUAL expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::equal_equal, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::equal_equal, $1, $3, @$); }
| expr NOT_EQUAL expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::not_equal, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::not_equal, $1, $3, @$); }
| expr LESS expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::less, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::less, $1, $3, @$); }
| expr GREATER expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::greater, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::greater, $1, $3, @$); }
| expr LESS_EQUAL expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::less_equal, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::less_equal, $1, $3, @$); }
| expr GREATER_EQUAL expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::greater_equal, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::greater_equal, $1, $3, @$); }
| expr AND expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::logical_and, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::logical_and, $1, $3, @$); }
| expr OR expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::logical_or, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::logical_or, $1, $3, @$); }
| expr IN expr
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::in, $1, $3, driver.env, @$); }
{ $$ = make_shared<BinaryOp>(codes::BinaryOp::in, $1, $3, @$); }
;
%%