Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 4.6
  • 5.x
  • 6.x
  • aux_vars_fix
  • julia
  • llvm-15
  • master
  • python-codegen
  • rework_pac
  • uop
  • julia-6.2.0
  • julia-6.3.0
  • julia-6.4.0
  • julia-7.0.0
14 results

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
  • 4.6
  • 5.x
  • aux_vars_fix
  • dynare_lite
  • julia
  • master
  • pylib
  • rework_pac
  • uop
  • wasm
  • created_preprocessor_repo
  • julia-6.2.0
12 results
Show changes
/*
* Copyright © 2012-2022 Dynare Team
* Copyright © 2012-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -18,41 +18,33 @@
*/
#include "WarningConsolidation.hh"
#include <ostream>
WarningConsolidation &
operator<<(WarningConsolidation &wcc, const string &warning)
ostream&
operator<<(ostream& stream, const Dynare::location& l)
{
if (wcc.no_warn)
return wcc;
stream << *l.begin.filename << ": line " << l.begin.line;
if (l.begin.line == l.end.line)
if (l.begin.column == l.end.column - 1)
stream << ", col " << l.begin.column;
else
stream << ", cols " << l.begin.column << "-" << l.end.column - 1;
else
stream << ", col " << l.begin.column << " -"
<< " line " << l.end.line << ", col " << l.end.column - 1;
cerr << warning;
wcc.addWarning(warning);
return wcc;
};
return stream;
}
WarningConsolidation &
operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
void
WarningConsolidation::incrementWarnings(const string& msg)
{
if (wcc.no_warn)
return wcc;
stringstream ostr;
Dynare::position last = loc.end - 1;
ostr << loc.begin;
if (last.filename
&& (!loc.begin.filename
|| *loc.begin.filename != *last.filename))
ostr << '-' << last;
else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column;
else if (loc.begin.column != last.column)
ostr << '-' << last.column;
cerr << ostr.str();
wcc.addWarning(ostr.str());
return wcc;
};
size_t p {0};
while ((p = msg.find('\n', p)) != string::npos)
{
p++;
num_warnings++;
}
}
WarningConsolidation&
operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&))
......@@ -60,49 +52,12 @@ operator<<(WarningConsolidation &wcc, ostream &(*pf)(ostream &))
if (wcc.no_warn)
return wcc;
cerr << pf;
wcc.addWarning(pf);
return wcc;
}
ostringstream ostr;
ostr << pf;
void
WarningConsolidation::writeOutput(ostream &output) const
{
if (warnings.str().empty())
return;
output << "disp([char(10) 'Dynare Preprocessor Warning(s) Encountered:']);" << endl;
cerr << ostr.str();
bool writedisp = true;
string warningsstr = warnings.str();
for (size_t i = 0; i < warningsstr.length(); i++)
{
if (writedisp)
{
output << "disp(' ";
writedisp = false;
}
wcc.incrementWarnings(ostr.str());
if (warningsstr[i] != '\n')
output << warningsstr[i];
else
{
output << "');" << endl;
if (i+1 < warningsstr.length())
writedisp = true;
}
}
}
int
WarningConsolidation::countWarnings() const
{
size_t p = 0;
int n = 0;
while ((p = warnings.str().find('\n', p)) != string::npos)
{
p++;
n++;
}
return n;
return wcc;
}
/*
* Copyright © 2012-2017 Dynare Team
* Copyright © 2012-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,49 +17,68 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _WARNINGCONSOLIDATION_HH
#define _WARNINGCONSOLIDATION_HH
#ifndef WARNING_CONSOLIDATION_HH
#define WARNING_CONSOLIDATION_HH
#include "DynareBisonLocation.hh"
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include "DynareBisonLocation.hh"
using namespace std;
//! Stores Warnings issued by the Preprocessor
/* Provide our implementation of operator<< with locations in DynareBison.hh. Note that the
following is a template specialization of the version provided in DynareBisonLocation.hh.
Ideally it should go into DynareBisonLocation.hh, but there does not seem to be a way to achieve
that. */
ostream& operator<<(ostream& stream, const Dynare::location& l);
class WarningConsolidation
{
private:
stringstream warnings;
bool no_warn;
const bool no_warn;
int num_warnings {0};
// Increases the warning counter by as many newlines as there are in the message
void incrementWarnings(const string& msg);
public:
explicit WarningConsolidation(bool no_warn_arg) : no_warn {no_warn_arg}
{
};
}
//! Add A Warning to the StringStream
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const string &warning);
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const Dynare::location &loc);
// Generic function to print something to the warning stream
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, auto&& warning);
/* Print std::endl to the warning stream. Unfortunately, since std::endl is a template of
functions, it cannot be bound to the universal reference of the generic function, hence the
need for this specialization. */
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&));
void
addWarning(const string &w)
int
numWarnings() const
{
warnings << w;
return num_warnings;
}
};
void
addWarning(ostream &(*pf)(ostream &))
WarningConsolidation&
operator<<(WarningConsolidation& wcc, auto&& warning)
{
warnings << pf;
};
if (wcc.no_warn)
return wcc;
//! Write Warnings to m file
void writeOutput(ostream &output) const;
//! Count warnings
/*! This is done in a very lousy way, by counting newlines in the
stringstream... */
int countWarnings() const;
};
ostringstream ostr;
ostr << warning;
cerr << ostr.str();
wcc.incrementWarnings(ostr.str());
return wcc;
}
#endif
......@@ -68,15 +68,17 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
errmsg << " * " << current_path().string() << endl;
for (const auto& dir : paths)
errmsg << " * " << absolute(dir).string() << endl;
error(StackTrace("@#include", "Could not open " + filename.string()
+". The following directories were searched:\n" + errmsg.str(), location));
error(StackTrace("@#include",
"Could not open " + filename.string()
+ ". The following directories were searched:\n" + errmsg.str(),
location));
}
}
Driver m;
/* Calling `string()` method on filename and filename.stem() because of
bug in GCC/MinGW 10.2 (shipped in Debian “Bullseye” 11), that fails
to accept implicit conversion to string from filename::path. See
https://en.cppreference.com/w/cpp/filesystem/path/native. */
/* Calling string() method on filename: not necessary on GNU/Linux and macOS because there is
an implicit conversion from from filesystem:path to string (i.e. basic_string<char>), but
needed on Windows because the implicit conversion is only to wstring (i.e.
basic_string<wchar_t>). */
m.parse(filename.string(), incfile, false, {}, env, paths, output);
}
catch (StackTrace& ex)
......@@ -92,7 +94,8 @@ Include::interpret(ostream &output, Environment &env, vector<filesystem::path> &
}
void
IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vector<filesystem::path> &paths)
IncludePath::interpret([[maybe_unused]] ostream& output, Environment& env,
vector<filesystem::path>& paths)
{
using namespace filesystem;
try
......@@ -100,20 +103,7 @@ IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vecto
StringPtr msp = dynamic_pointer_cast<String>(expr->eval(env));
if (!msp)
throw StackTrace("File name does not evaluate to a string");
#ifdef _WIN32
/* Trim trailing slashes and backslashes in the path. This is a
workaround for a GCC/MinGW bug present in version 10.2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88881, that affects
gcc-mingw-w64 in Debian “Bullseye” 11. It is fixed in GCC 10.3, and
thus should be fixed in Debian “Bookworm” 12.
See Madysson/estimation-codes#11. */
string ipstr = static_cast<string>(*msp);
while (ipstr.size() > 1 && (ipstr.back() == '/' || ipstr.back() == '\\'))
ipstr.pop_back();
path ip{ipstr};
#else
path ip = static_cast<string>(*msp);
#endif
if (!is_directory(ip))
throw StackTrace(ip.string() + " does not evaluate to a valid directory");
if (!exists(ip))
......@@ -133,7 +123,8 @@ IncludePath::interpret([[maybe_unused]] ostream &output, Environment &env, vecto
}
void
Define::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Define::interpret([[maybe_unused]] ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
......@@ -176,7 +167,8 @@ Echo::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<files
}
void
Error::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
Error::interpret([[maybe_unused]] ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
try
{
......@@ -194,12 +186,10 @@ Error::interpret([[maybe_unused]] ostream &output, Environment &env, [[maybe_unu
}
void
EchoMacroVars::interpret(ostream &output, Environment &env, [[maybe_unused]] vector<filesystem::path> &paths)
EchoMacroVars::interpret(ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths)
{
if (save)
env.print(output, vars, location.begin.line, true);
else
env.print(cout, vars);
env.print(save ? output : cout, vars, location.begin.line, save);
printEndLineInfo(output);
}
......@@ -237,8 +227,11 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
{
TuplePtr mtp = dynamic_pointer_cast<Tuple>(btp);
if (index_vec.size() != mtp->size())
error(StackTrace("@#for", "Encountered tuple of size " + to_string(mtp->size())
+ " but only have " + to_string(index_vec.size()) + " index variables", location));
error(StackTrace("@#for",
"Encountered tuple of size " + to_string(mtp->size())
+ " but only have " + to_string(index_vec.size())
+ " index variables",
location));
else
for (size_t j = 0; j < index_vec.size(); j++)
env.define(index_vec.at(j), mtp->at(j));
......@@ -262,8 +255,7 @@ For::interpret(ostream &output, Environment &env, vector<filesystem::path> &path
void
If::interpret(ostream& output, Environment& env, vector<filesystem::path>& paths)
{
for (bool first_clause{true};
const auto &[expr, body] : expr_and_body)
for (bool first_clause {true}; const auto& [expr, body] : expr_and_body)
try
{
if ((ifdef || ifndef) && exchange(first_clause, false))
......@@ -285,8 +277,8 @@ If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths
RealPtr dp = dynamic_pointer_cast<Real>(tmp);
BoolPtr bp = dynamic_pointer_cast<Bool>(tmp);
if (!bp && !dp)
error(StackTrace("@#if",
"The condition must evaluate to a boolean or a double", location));
error(StackTrace("@#if", "The condition must evaluate to a boolean or a double",
location));
if ((bp && *bp) || (dp && *dp))
{
interpretBody(body, output, env, paths);
......@@ -307,10 +299,10 @@ If::interpret(ostream &output, Environment &env, vector<filesystem::path> &paths
}
void
If::interpretBody(const vector<DirectivePtr> &body, ostream &output, Environment &env, vector<filesystem::path> &paths)
If::interpretBody(const vector<DirectivePtr>& body, ostream& output, Environment& env,
vector<filesystem::path>& paths)
{
for (bool printLine{true};
const auto &statement : body)
for (bool printLine {true}; const auto& statement : body)
{
if (exchange(printLine, false))
statement->printLineInfo(output);
......
/*
* Copyright © 2019-2020 Dynare Team
* Copyright © 2019-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DIRECTIVES_HH
#define _DIRECTIVES_HH
#ifndef DIRECTIVES_HH
#define DIRECTIVES_HH
#include "Expressions.hh"
......@@ -30,13 +30,13 @@ namespace macro
{
// A Parent class just for clarity
public:
explicit Directive(Tokenizer::location location_arg) :
Node(move(location_arg)) { }
explicit Directive(Tokenizer::location location_arg) : Node(move(location_arg))
{
}
// Directives can be interpreted
virtual void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) = 0;
};
class TextNode : public Directive
{
// Class for text not interpreted by macroprocessor
......@@ -44,17 +44,20 @@ namespace macro
// Treated as such as the output is only to be interpreted
private:
const string text;
public:
TextNode(string text_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), text{move(text_arg)} { }
Directive(move(location_arg)), text {move(text_arg)}
{
}
void
interpret(ostream &output, [[maybe_unused]] Environment &env, [[maybe_unused]] vector<filesystem::path> &paths) override
interpret(ostream& output, [[maybe_unused]] Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths) override
{
output << text;
}
};
class Eval : public Directive
{
// Class for @{} statements
......@@ -62,111 +65,123 @@ namespace macro
// Treated as such as the output is only to be interpreted
private:
const ExpressionPtr expr;
public:
Eval(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Include : public Directive
{
private:
const ExpressionPtr expr;
public:
Include(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class IncludePath : public Directive
{
private:
const ExpressionPtr expr;
public:
IncludePath(ExpressionPtr expr_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Directive(move(location_arg)), expr {move(expr_arg)}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
};
class Define : public Directive
{
private:
const VariablePtr var;
const FunctionPtr func;
const ExpressionPtr value;
public:
Define(VariablePtr var_arg,
ExpressionPtr 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,
Tokenizer::location location_arg) :
Directive(move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { }
Define(VariablePtr var_arg, ExpressionPtr 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, 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;
};
class Echo : public Directive
{
private:
const ExpressionPtr expr;
public:
Echo(ExpressionPtr expr_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Echo(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;
};
class Error : public Directive
{
private:
const ExpressionPtr expr;
public:
Error(ExpressionPtr expr_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), expr{move(expr_arg)} { }
Error(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;
};
class EchoMacroVars : public Directive
{
private:
const bool save;
const vector<string> vars;
public:
EchoMacroVars(bool save_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg} { }
EchoMacroVars(bool save_arg, vector<string> vars_arg,
Tokenizer::location location_arg) :
Directive(move(location_arg)), save{save_arg}, vars{move(vars_arg)} { }
EchoMacroVars(bool save_arg, Tokenizer::location location_arg) :
Directive(move(location_arg)), save {save_arg}
{
}
EchoMacroVars(bool save_arg, vector<string> vars_arg, 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;
};
class For : public Directive
{
private:
const vector<VariablePtr> index_vec;
const ExpressionPtr index_vals;
const vector<DirectivePtr> statements;
public:
For(vector<VariablePtr> index_vec_arg,
ExpressionPtr index_vals_arg,
vector<DirectivePtr> statements_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)} { }
For(vector<VariablePtr> index_vec_arg, ExpressionPtr index_vals_arg,
vector<DirectivePtr> statements_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, Environment& env, vector<filesystem::path>& paths) override;
};
class If : public Directive
{
protected:
......@@ -180,16 +195,21 @@ namespace macro
*/
const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body;
const bool ifdef, ifndef;
public:
If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg,
bool ifdef_arg = false, bool ifndef_arg = false) :
Directive(move(location_arg)), expr_and_body{move(expr_and_body_arg)},
ifdef{ifdef_arg}, ifndef{ifndef_arg} { }
Tokenizer::location location_arg, bool ifdef_arg = false, bool ifndef_arg = false) :
Directive(move(location_arg)),
expr_and_body {move(expr_and_body_arg)},
ifdef {ifdef_arg},
ifndef {ifndef_arg}
{
}
void interpret(ostream& output, Environment& env, vector<filesystem::path>& paths) override;
protected:
void interpretBody(const vector<DirectivePtr> &body, ostream &output,
Environment &env, vector<filesystem::path> &paths);
void interpretBody(const vector<DirectivePtr>& body, ostream& output, Environment& env,
vector<filesystem::path>& paths);
};
class Ifdef : public If
......@@ -197,16 +217,19 @@ namespace macro
public:
Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), true, false) { }
If(move(expr_and_body_arg), move(location_arg), true, false)
{
}
};
class Ifndef : public If
{
public:
Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
Tokenizer::location location_arg) :
If(move(expr_and_body_arg), move(location_arg), false, true) { }
If(move(expr_and_body_arg), move(location_arg), false, true)
{
}
};
}
#endif
......@@ -25,9 +25,9 @@
using namespace macro;
void
Driver::parse(const string &file_arg, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
Environment &env, vector<filesystem::path> &paths, ostream &output)
Driver::parse(const string& file_arg, const istream& modfile, bool debug,
const vector<pair<string, string>>& defines, Environment& env,
vector<filesystem::path>& paths, ostream& output)
{
file = file_arg;
......@@ -54,8 +54,7 @@ Driver::parse(const string &file_arg, const istream &modfile,
parser.parse();
// Interpret parsed statements
for (bool printLine{true};
const auto &statement : statements)
for (bool printLine {true}; const auto& statement : statements)
{
if (exchange(printLine, false))
statement->printLineInfo(output);
......
......@@ -17,16 +17,16 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _MACRO_DRIVER_HH
#define _MACRO_DRIVER_HH
#ifndef MACRO_DRIVER_HH
#define MACRO_DRIVER_HH
#ifdef _PARSING_DRIVER_HH
#ifdef PARSING_DRIVER_HH
# error Impossible to include both ../ParsingDriver.hh and Driver.hh
#endif
#include "Parser.hh"
#include "Environment.hh"
#include "Expressions.hh"
#include "Parser.hh"
#include <stack>
......@@ -46,7 +46,9 @@ namespace macro
class TokenizerFlex : public TokenizerFlexLexer
{
public:
TokenizerFlex(istream *in) : TokenizerFlexLexer{in} { }
TokenizerFlex(istream* in) : TokenizerFlexLexer {in}
{
}
TokenizerFlex(const TokenizerFlex&) = delete;
TokenizerFlex& operator=(const TokenizerFlex&) = delete;
......@@ -63,6 +65,7 @@ namespace macro
private:
vector<DirectivePtr> statements;
stack<vector<DirectivePtr>> directive_stack;
public:
Driver() = default;
Driver(const Driver&) = delete;
......@@ -76,9 +79,9 @@ namespace macro
//! Starts parsing a file, modifies `env`, `paths` and `output`
//! as they are modified by various macro directives
void parse(const string &file, const istream &modfile,
bool debug, const vector<pair<string, string>> &defines,
Environment &env, vector<filesystem::path> &paths, ostream &output);
void parse(const string& file, const istream& modfile, bool debug,
const vector<pair<string, string>>& defines, Environment& env,
vector<filesystem::path>& paths, ostream& output);
//! Name of main file being parsed (for error reporting purposes)
string file;
......@@ -89,7 +92,7 @@ namespace macro
//! Error handler
void error(const Tokenizer::parser::location_type& location, const string& message) const;
bool
[[nodiscard]] bool
inContext() const
{
return !directive_stack.empty();
......@@ -98,7 +101,7 @@ namespace macro
void
pushContext()
{
directive_stack.emplace(vector<DirectivePtr>());
directive_stack.emplace();
}
void
......
/*
* Copyright © 2019-2022 Dynare Team
* Copyright © 2019-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,7 +17,9 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cassert>
#include <ranges>
#include "Environment.hh"
#include "Expressions.hh"
......@@ -25,7 +27,7 @@
using namespace macro;
void
Environment::define(VariablePtr var, ExpressionPtr value)
Environment::define(const VariablePtr& var, const ExpressionPtr& value)
{
string name = var->getName();
if (functions.contains(name))
......@@ -54,7 +56,7 @@ Environment::getVariable(const string &name) const
return getGlobalEnv()->getVariable(name);
}
tuple<FunctionPtr, ExpressionPtr>
pair<FunctionPtr, ExpressionPtr>
Environment::getFunction(const string& name) const
{
if (auto it = functions.find(name); it != functions.end())
......@@ -101,40 +103,54 @@ Environment::isFunctionDefined(const string &name) const noexcept
}
void
Environment::print(ostream &output, const vector<string> &vars, const optional<int> &line, bool save) const
Environment::print(ostream& output, const vector<string>& vars, int line, bool save) const
{
if (!save && !variables.empty())
output << "Macro Variables:" << endl;
output << "Macro Variables (at line " << line << "):" << endl;
// For sorting the symbols in a case-insensitive way, see #128
auto case_insensitive_string_less = [](const string& a, const string& b) {
return ranges::lexicographical_compare(
a, b, [](char c1, char c2) { return tolower(c1) < tolower(c2); });
};
if (vars.empty())
for (const auto &it : variables)
printVariable(output, it.first, line, save);
{
vector<string> variables_sorted;
ranges::copy(views::keys(variables), back_inserter(variables_sorted));
ranges::sort(variables_sorted, case_insensitive_string_less);
for (const auto& it : variables_sorted)
printVariable(output, it, line, save);
}
else
for (const auto& it : vars)
if (isVariableDefined(it))
printVariable(output, it, line, save);
if (!save && !functions.empty())
output << "Macro Functions:" << endl;
output << "Macro Functions (at line " << line << "):" << endl;
if (vars.empty())
for (const auto &it : functions)
printFunction(output, it.second, line, save);
{
vector<string> functions_sorted;
ranges::copy(views::keys(functions), back_inserter(functions_sorted));
ranges::sort(functions_sorted, case_insensitive_string_less);
for (const auto& it : functions_sorted)
printFunction(output, it, line, save);
}
else
for (const auto& it : vars)
if (isFunctionDefined(it))
printFunction(output, functions.at(it), line, save);
printFunction(output, it, line, save);
if (parent)
parent->print(output, vars, line, save);
}
void
Environment::printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const
Environment::printVariable(ostream& output, const string& name, int line, bool save) const
{
assert(!save || line);
output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ")
<< name << " = ";
output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " ") << name << " = ";
getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save);
if (save)
output << ";";
......@@ -142,19 +158,19 @@ Environment::printVariable(ostream &output, const string &name, const optional<i
}
void
Environment::printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const
Environment::printFunction(ostream& output, const string& name, int line, bool save) const
{
assert(!save || line);
output << (save ? "options_.macrovars_line_" + to_string(*line) + ".function." : " ");
auto [func_signature, func_body] = getFunction(name);
output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " ");
if (save)
{
get<0>(function)->printName(output);
func_signature->printName(output);
output << " = '";
}
get<0>(function)->print(output);
func_signature->print(output);
output << " = ";
get<1>(function)->print(output);
func_body->print(output);
if (save)
output << "';";
......
/*
* Copyright © 2019-2022 Dynare Team
* Copyright © 2019-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,14 +17,14 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ENVIRONMENT_HH
#define _ENVIRONMENT_HH
#ifndef ENVIRONMENT_HH
#define ENVIRONMENT_HH
#include "ForwardDeclarationsAndEnums.hh"
#include <map>
#include <vector>
#include <optional>
#include <vector>
namespace macro
{
......@@ -33,30 +33,37 @@ namespace macro
private:
const Environment* parent {nullptr};
map<string, ExpressionPtr> variables;
map<string, tuple<FunctionPtr, ExpressionPtr>> functions;
map<string, pair<FunctionPtr, ExpressionPtr>> functions;
public:
Environment() = default;
Environment(const Environment *parent_arg) : parent{parent_arg} { }
void define(VariablePtr var, ExpressionPtr value);
Environment(const Environment* parent_arg) : parent {parent_arg}
{
}
void define(const VariablePtr& var, const ExpressionPtr& value);
void define(FunctionPtr func, ExpressionPtr value);
ExpressionPtr getVariable(const string &name) const;
tuple<FunctionPtr, ExpressionPtr> getFunction(const string &name) const;
codes::BaseType getType(const string &name) const;
bool isVariableDefined(const string &name) const noexcept;
bool isFunctionDefined(const string &name) const noexcept;
bool isSymbolDefined(const string &name) const noexcept
/* The following two functions are not marked [[nodiscard]], because they are used without output
to check whether they return an exception or not. */
ExpressionPtr getVariable(const string& name) const; // NOLINT(modernize-use-nodiscard)
pair<FunctionPtr, ExpressionPtr> // NOLINT(modernize-use-nodiscard)
getFunction(const string& name) const;
[[nodiscard]] codes::BaseType getType(const string& name) const;
[[nodiscard]] bool isVariableDefined(const string& name) const noexcept;
[[nodiscard]] bool isFunctionDefined(const string& name) const noexcept;
[[nodiscard]] bool
isSymbolDefined(const string& name) const noexcept
{
return isVariableDefined(name) || isFunctionDefined(name);
}
void print(ostream &output, const vector<string> &vars, const optional<int> &line = nullopt, bool save = false) const;
void printVariable(ostream &output, const string &name, const optional<int> &line, bool save) const;
void printFunction(ostream &output, const tuple<FunctionPtr, ExpressionPtr> &function, const optional<int> &line, bool save) const;
size_t
void print(ostream& output, const vector<string>& vars, int line, bool save) const;
void printVariable(ostream& output, const string& name, int line, bool save) const;
void printFunction(ostream& output, const string& name, int line, bool save) const;
[[nodiscard]] size_t
size() const noexcept
{
return variables.size() + functions.size();
}
const Environment *
[[nodiscard]] const Environment*
getGlobalEnv() const noexcept
{
return parent == nullptr ? this : parent->getGlobalEnv();
......
/*
* Copyright © 2019-2023 Dynare Team
* Copyright © 2019-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <utility>
#include <numbers>
#include <utility>
#include "Expressions.hh"
......@@ -241,7 +241,9 @@ 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*numbers::pi)*std::exp(pow((value-btp12->value)/btp22->value, 2)/2))));
return make_shared<Real>(1
/ (btp22->value * std::sqrt(2 * numbers::pi)
* std::exp(pow((value - btp12->value) / btp22->value, 2) / 2)));
}
RealPtr
......@@ -251,7 +253,8 @@ 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/numbers::sqrt2))));
return make_shared<Real>(
0.5 * (1 + std::erf((value - btp12->value) / btp22->value / numbers::sqrt2)));
}
BaseTypePtr
......@@ -311,12 +314,12 @@ String::is_equal(const BaseTypePtr &btp) const
BoolPtr
String::cast_bool([[maybe_unused]] Environment& env) const
{
auto f = [](const char &a, const char &b) { return (tolower(a) == tolower(b)); };
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))
if (ranges::equal(value, "true"s, f))
return make_shared<Bool>(true);
if (string tf = "false"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f))
if (ranges::equal(value, "false"s, f))
return make_shared<Bool>(false);
try
......@@ -620,12 +623,15 @@ Range::eval(Environment &env) const
"the arguments must evaluate to reals");
vector<ExpressionPtr> arr;
// We do want a float counter, because that’s the macro-language semantics
// NOLINTBEGIN(clang-analyzer-security.FloatLoopCounter)
if (*incdbl > 0 && *startdbl <= *enddbl)
for (double i = *startdbl; i <= *enddbl; i += *incdbl)
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));
// NOLINTEND(clang-analyzer-security.FloatLoopCounter)
return make_shared<Array>(arr, location);
}
......@@ -634,6 +640,7 @@ BaseTypePtr
Array::eval(Environment& env) const
{
vector<ExpressionPtr> retval;
retval.reserve(arr.size());
for (const auto& it : arr)
retval.emplace_back(it->eval(env));
return make_shared<Array>(retval);
......@@ -643,6 +650,7 @@ BaseTypePtr
Tuple::eval(Environment& env) const
{
vector<ExpressionPtr> retval;
retval.reserve(tup.size());
for (const auto& it : tup)
retval.emplace_back(it->eval(env));
return make_shared<Tuple>(retval);
......@@ -657,12 +665,15 @@ Variable::eval(Environment &env) const
vector<int> ind;
for (const auto& it : map->getValue())
// Necessary to handle indexes like: y[1:2,2]
// In general this evaluates to [[1:2],2] but when subscripting we want to expand it to [1,2,2]
// In general this evaluates to [[1:2],2] but when subscripting we want to expand it to
// [1,2,2]
if (auto db = dynamic_pointer_cast<Real>(it); db)
{
if (!*(db->isinteger()))
throw StackTrace("variable", "When indexing a variable you must pass "
"an int or an int array", location);
throw StackTrace("variable",
"When indexing a variable you must pass "
"an int or an int array",
location);
ind.emplace_back(*db);
}
else if (dynamic_pointer_cast<Array>(it))
......@@ -670,16 +681,22 @@ Variable::eval(Environment &env) const
if (db = dynamic_pointer_cast<Real>(it1); db)
{
if (!*(db->isinteger()))
throw StackTrace("variable", "When indexing a variable you must pass "
"an int or an int array", location);
throw StackTrace("variable",
"When indexing a variable you must pass "
"an int or an int array",
location);
ind.emplace_back(*db);
}
else
throw StackTrace("variable", "You cannot index a variable with a "
"nested array", location);
throw StackTrace("variable",
"You cannot index a variable with a "
"nested array",
location);
else
throw StackTrace("variable", "You can only index a variable with an int or "
"an int array", location);
throw StackTrace("variable",
"You can only index a variable with an int or "
"an int array",
location);
switch (env.getType(name))
{
......@@ -693,8 +710,7 @@ Variable::eval(Environment &env) const
throw StackTrace("variable", "Internal Error: Range: should not arrive here", location);
case codes::BaseType::String:
{
string orig_string
= dynamic_pointer_cast<String>(env.getVariable(name))->to_string();
string orig_string = dynamic_pointer_cast<String>(env.getVariable(name))->to_string();
string retvals;
for (auto it : ind)
try
......@@ -749,8 +765,10 @@ Function::eval(Environment &env) const
}
if (func->args.size() != args.size())
throw StackTrace("Function", "The number of arguments used to call " + name
+" does not match the number used in its definition", location);
throw StackTrace("Function",
"The number of arguments used to call " + name
+ " does not match the number used in its definition",
location);
try
{
......@@ -970,8 +988,10 @@ Comprehension::eval(Environment &env) const
vp = dynamic_pointer_cast<Variable>(c_vars);
mt = dynamic_pointer_cast<Tuple>(c_vars);
if ((!vp && !mt) || (vp && mt))
throw StackTrace("Comprehension", "the loop variables must be either "
"a tuple or a variable", location);
throw StackTrace("Comprehension",
"the loop variables must be either "
"a tuple or a variable",
location);
}
catch (StackTrace& ex)
{
......@@ -985,27 +1005,32 @@ Comprehension::eval(Environment &env) const
auto btp = dynamic_pointer_cast<BaseType>(input_set->at(i));
if (vp)
env.define(vp, btp);
else
if (btp->getType() == codes::BaseType::Tuple)
else if (btp->getType() == codes::BaseType::Tuple)
{
auto mt2 = dynamic_pointer_cast<Tuple>(btp);
if (mt->size() != mt2->size())
throw StackTrace("Comprehension", "The number of elements in the input "
throw StackTrace("Comprehension",
"The number of elements in the input "
" set tuple are not the same as the number of elements in "
"the output expression tuple", location);
"the output expression tuple",
location);
for (size_t j = 0; j < mt->size(); j++)
{
auto vp2 = dynamic_pointer_cast<Variable>(mt->at(j));
if (!vp2)
throw StackTrace("Comprehension", "Output expression tuple must be "
"comprised of variable names", location);
throw StackTrace("Comprehension",
"Output expression tuple must be "
"comprised of variable names",
location);
env.define(vp2, mt2->at(j));
}
}
else
throw StackTrace("Comprehension", "assigning to tuple in output expression "
"but input expression does not contain tuples", location);
throw StackTrace("Comprehension",
"assigning to tuple in output expression "
"but input expression does not contain tuples",
location);
if (!c_when)
if (!c_expr)
......@@ -1227,9 +1252,11 @@ TrinaryOp::to_string() const noexcept
switch (op_code)
{
case codes::TrinaryOp::normpdf:
return "normpdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string() + ")";
return "normpdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string()
+ ")";
case codes::TrinaryOp::normcdf:
return "normcdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string() + ")";
return "normcdf(" + arg1->to_string() + ", " + arg2->to_string() + ", " + arg3->to_string()
+ ")";
}
// Suppress GCC warning
exit(EXIT_FAILURE);
......@@ -1250,17 +1277,14 @@ Comprehension::to_string() const noexcept
void
String::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "'" : R"(")")
<< value
<< (matlab_output ? "'" : R"(")");
output << (matlab_output ? "'" : R"(")") << value << (matlab_output ? "'" : R"(")");
}
void
Array::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "{" : "[");
for (bool printed_something{false};
auto e : arr)
for (bool printed_something {false}; const auto& e : arr)
{
if (exchange(printed_something, true))
output << ", ";
......@@ -1273,8 +1297,7 @@ void
Tuple::print(ostream& output, bool matlab_output) const noexcept
{
output << (matlab_output ? "{" : "(");
for (bool printed_something{false};
auto e : tup)
for (bool printed_something {false}; const auto& e : tup)
{
if (exchange(printed_something, true))
output << ", ";
......@@ -1287,8 +1310,7 @@ void
Function::printArgs(ostream& output) const noexcept
{
output << "(";
for (bool printed_something{false};
auto e : args)
for (bool printed_something {false}; const auto& e : args)
{
if (exchange(printed_something, true))
output << ", ";
......@@ -1423,24 +1445,18 @@ UnaryOp::print(ostream &output, bool matlab_output) const noexcept
arg->print(output, matlab_output);
if (op_code != codes::UnaryOp::cast_bool
&& op_code != codes::UnaryOp::cast_real
&& op_code != codes::UnaryOp::cast_string
&& op_code != codes::UnaryOp::cast_tuple
&& op_code != codes::UnaryOp::cast_array
&& op_code != codes::UnaryOp::logical_not
&& op_code != codes::UnaryOp::unary_plus
&& op_code != codes::UnaryOp::unary_minus)
if (op_code != codes::UnaryOp::cast_bool && op_code != codes::UnaryOp::cast_real
&& op_code != codes::UnaryOp::cast_string && op_code != codes::UnaryOp::cast_tuple
&& op_code != codes::UnaryOp::cast_array && op_code != codes::UnaryOp::logical_not
&& op_code != codes::UnaryOp::unary_plus && op_code != codes::UnaryOp::unary_minus)
output << ")";
}
void
BinaryOp::print(ostream& output, bool matlab_output) const noexcept
{
if (op_code == codes::BinaryOp::set_union
|| op_code == codes::BinaryOp::set_intersection
|| op_code == codes::BinaryOp::max
|| op_code == codes::BinaryOp::min
if (op_code == codes::BinaryOp::set_union || op_code == codes::BinaryOp::set_intersection
|| op_code == codes::BinaryOp::max || op_code == codes::BinaryOp::min
|| op_code == codes::BinaryOp::mod)
{
switch (op_code)
......
......@@ -17,17 +17,17 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXPRESSIONS_HH
#define _EXPRESSIONS_HH
#ifndef EXPRESSIONS_HH
#define EXPRESSIONS_HH
#include "ForwardDeclarationsAndEnums.hh"
#include "Environment.hh"
#include "ForwardDeclarationsAndEnums.hh"
#include "ParserLocation.hh"
#include <cmath>
#include <vector>
#include <sstream>
#include <iomanip>
#include <sstream>
#include <vector>
namespace macro
{
......@@ -35,9 +35,13 @@ namespace macro
{
private:
vector<string> message;
public:
StackTrace (string message_arg) : message{move(message_arg)} { }
StackTrace (const string &prefix, const char *standard_exception_message, const Tokenizer::location &location)
StackTrace(string message_arg) : message {move(message_arg)}
{
}
StackTrace(const string& prefix, const char* standard_exception_message,
const Tokenizer::location& location)
{
stringstream ss;
ss << prefix << ": " << location << " " << standard_exception_message;
......@@ -49,26 +53,27 @@ namespace macro
ss << prefix << ": " << location << " " << msg;
message = {ss.str()};
}
void push(const string &prefix, const Tokenizer::location &location)
void
push(const string& prefix, const Tokenizer::location& location)
{
stringstream ss;
auto end_col = 0 < location.end.column ? location.end.column - 1 : 0;
ss << prefix << ": "
<< R"(")" << *location.begin.filename << R"(" line )" << location.begin.line
<< ", col " << location.begin.column;
<< R"(")" << *location.begin.filename << R"(" line )" << location.begin.line << ", col "
<< location.begin.column;
if (location.end.filename
&& (!location.begin.filename
|| *location.begin.filename != *location.end.filename))
ss << R"( to ")" << location.end.filename << R"(")" << " line " << location.end.line
<< ", col " << end_col;
&& (!location.begin.filename || *location.begin.filename != *location.end.filename))
ss << R"( to ")" << location.end.filename << R"(")"
<< " line " << location.end.line << ", col " << end_col;
else if (location.begin.line < location.end.line)
ss << " to line " << location.end.line << ", col " << end_col;
else if (location.begin.column < end_col)
ss << "-" << end_col;
message.emplace_back(ss.str());
}
string trace() const
[[nodiscard]] string
trace() const
{
stringstream ss;
for (auto& msg : message)
......@@ -77,17 +82,23 @@ namespace macro
}
};
class Node
{
protected:
const Tokenizer::location location;
public:
explicit Node(Tokenizer::location location_arg) :
location{move(location_arg)} { }
explicit Node(Tokenizer::location location_arg) : location {move(location_arg)}
{
}
virtual ~Node() = default;
public:
Tokenizer::location getLocation() const noexcept { return location; }
[[nodiscard]] Tokenizer::location
getLocation() const noexcept
{
return location;
}
void
error(const StackTrace& e) const noexcept
{
......@@ -107,121 +118,413 @@ namespace macro
void
printEndLineInfo(ostream& output) const noexcept
{
// Add one to end line because we want to print the line number of the line *following* the end statement
output << R"(@#line ")" << *(location.begin.filename) << R"(" )" << location.end.line + 1 << endl;
// Add one to end line because we want to print the line number of the line *following* the end
// statement
output << R"(@#line ")" << *(location.begin.filename) << R"(" )" << location.end.line + 1
<< endl;
}
};
class Expression : public Node
{
public:
explicit Expression(Tokenizer::location location_arg) :
Node(move(location_arg)) { }
virtual string to_string() const noexcept = 0;
explicit Expression(Tokenizer::location location_arg) : Node(move(location_arg))
{
}
[[nodiscard]] virtual string to_string() const noexcept = 0;
virtual void print(ostream& output, bool matlab_output = false) const noexcept = 0;
virtual BaseTypePtr eval(Environment& env) const = 0;
};
class BaseType : public Expression, public enable_shared_from_this<BaseType>
{
public:
explicit BaseType(Tokenizer::location location_arg = Tokenizer::location()) :
Expression(move(location_arg)) { }
Expression(move(location_arg))
{
}
virtual codes::BaseType getType() const noexcept = 0;
BaseTypePtr eval([[maybe_unused]] Environment &env) const override { return const_pointer_cast<BaseType>(shared_from_this()); }
BaseTypePtr
eval([[maybe_unused]] Environment& env) const override
{
return const_pointer_cast<BaseType>(shared_from_this());
}
public:
virtual BaseTypePtr plus([[maybe_unused]] 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"); }
virtual BaseTypePtr minus([[maybe_unused]] const BaseTypePtr &bt) const { throw StackTrace("Operator - does not exist for this type"); }
virtual BaseTypePtr unary_minus() const { throw StackTrace("Unary operator - does not exist for this type"); }
virtual BaseTypePtr times([[maybe_unused]] const BaseTypePtr &bt) const { throw StackTrace("Operator * does not exist for this type"); }
virtual BaseTypePtr divide([[maybe_unused]] const BaseTypePtr &bt) const { throw StackTrace("Operator / does not exist for this type"); }
virtual BaseTypePtr power([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator ^ does not exist for this type"); }
virtual BoolPtr is_less([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator < does not exist for this type"); }
virtual BoolPtr is_greater([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator > does not exist for this type"); }
virtual BoolPtr is_less_equal([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator <= does not exist for this type"); }
virtual BoolPtr is_greater_equal([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator >= does not exist for this type"); }
virtual BaseTypePtr
plus([[maybe_unused]] 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");
}
virtual BaseTypePtr
minus([[maybe_unused]] const BaseTypePtr& bt) const
{
throw StackTrace("Operator - does not exist for this type");
}
virtual BaseTypePtr
unary_minus() const
{
throw StackTrace("Unary operator - does not exist for this type");
}
virtual BaseTypePtr
times([[maybe_unused]] const BaseTypePtr& bt) const
{
throw StackTrace("Operator * does not exist for this type");
}
virtual BaseTypePtr
divide([[maybe_unused]] const BaseTypePtr& bt) const
{
throw StackTrace("Operator / does not exist for this type");
}
virtual BaseTypePtr
power([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator ^ does not exist for this type");
}
virtual BoolPtr
is_less([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator < does not exist for this type");
}
virtual BoolPtr
is_greater([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator > does not exist for this type");
}
virtual BoolPtr
is_less_equal([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator <= does not exist for this type");
}
virtual BoolPtr
is_greater_equal([[maybe_unused]] 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([[maybe_unused]] const ExpressionPtr &ep, [[maybe_unused]] Environment &env) const { throw StackTrace("Operator && does not exist for this type"); }
virtual BoolPtr logical_or([[maybe_unused]] const ExpressionPtr &ep, [[maybe_unused]] 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([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator | does not exist for this type"); }
virtual ArrayPtr set_intersection([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator & does not exist for this type"); }
virtual BoolPtr contains([[maybe_unused]] 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, 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([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator `max` does not exist for this type"); }
virtual RealPtr min([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator `min` does not exist for this type"); }
virtual RealPtr mod([[maybe_unused]] const BaseTypePtr &btp) const { throw StackTrace("Operator `mod` does not exist for this type"); }
virtual RealPtr exp() const { throw StackTrace("Operator `exp` does not exist for this type"); }
virtual RealPtr ln() const { throw StackTrace("Operator `ln` does not exist for this type"); }
virtual RealPtr log10() const { throw StackTrace("Operator `log10` does not exist for this type"); }
virtual BoolPtr isinf() const { throw StackTrace("Operator `isinf` does not exist for this type"); }
virtual BoolPtr isnan() const { throw StackTrace("Operator `isnan` does not exist for this type"); }
virtual BoolPtr isfinite() const { throw StackTrace("Operator `isfinite` does not exist for this type"); }
virtual BoolPtr isnormal() const { throw StackTrace("Operator `isnormal` does not exist for this type"); }
virtual RealPtr sin() const { throw StackTrace("Operator `sin` does not exist for this type"); }
virtual RealPtr cos() const { throw StackTrace("Operator `cos` does not exist for this type"); }
virtual RealPtr tan() const { throw StackTrace("Operator `tan` does not exist for this type"); }
virtual RealPtr asin() const { throw StackTrace("Operator `asin` does not exist for this type"); }
virtual RealPtr acos() const { throw StackTrace("Operator `acos` does not exist for this type"); }
virtual RealPtr atan() const { throw StackTrace("Operator `atan` does not exist for this type"); }
virtual RealPtr sqrt() const { throw StackTrace("Operator `sqrt` does not exist for this type"); }
virtual RealPtr cbrt() const { throw StackTrace("Operator `cbrt` does not exist for this type"); }
virtual RealPtr sign() const { throw StackTrace("Operator `sign` does not exist for this type"); }
virtual RealPtr floor() const { throw StackTrace("Operator `floor` does not exist for this type"); }
virtual RealPtr ceil() const { throw StackTrace("Operator `ceil` does not exist for this type"); }
virtual RealPtr trunc() const { throw StackTrace("Operator `trunc` does not exist for this type"); }
virtual RealPtr sum() const { throw StackTrace("Operator `sum` does not exist for this type"); }
virtual RealPtr erf() const { throw StackTrace("Operator `erf` does not exist for this type"); }
virtual RealPtr erfc() const { throw StackTrace("Operator `erfc` does not exist for this type"); }
virtual RealPtr gamma() const { throw StackTrace("Operator `gamma` does not exist for this type"); }
virtual RealPtr lgamma() const { throw StackTrace("Operator `lgamma` does not exist for this type"); }
virtual RealPtr round() const { throw StackTrace("Operator `round` does not exist for this type"); }
virtual RealPtr normpdf() const { throw StackTrace("Operator `normpdf` does not exist for this type"); }
virtual RealPtr normpdf([[maybe_unused]] const BaseTypePtr &btp1, [[maybe_unused]] 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([[maybe_unused]] const BaseTypePtr &btp1, [[maybe_unused]] const BaseTypePtr &btp2) const { throw StackTrace("Operator `normcdf` does not exist for this type"); }
virtual BoolPtr cast_bool([[maybe_unused]] Environment &env) const { throw StackTrace("This type cannot be cast to a boolean"); }
virtual RealPtr cast_real([[maybe_unused]] 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([[maybe_unused]] const Environment &env) const { throw StackTrace("Operator `defined` does not exist for this type"); }
virtual BoolPtr
logical_and([[maybe_unused]] const ExpressionPtr& ep, [[maybe_unused]] Environment& env) const
{
throw StackTrace("Operator && does not exist for this type");
}
virtual BoolPtr
logical_or([[maybe_unused]] const ExpressionPtr& ep, [[maybe_unused]] 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([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator | does not exist for this type");
}
virtual ArrayPtr
set_intersection([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator & does not exist for this type");
}
virtual BoolPtr
contains([[maybe_unused]] 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, 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([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator `max` does not exist for this type");
}
virtual RealPtr
min([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator `min` does not exist for this type");
}
virtual RealPtr
mod([[maybe_unused]] const BaseTypePtr& btp) const
{
throw StackTrace("Operator `mod` does not exist for this type");
}
virtual RealPtr
exp() const
{
throw StackTrace("Operator `exp` does not exist for this type");
}
virtual RealPtr
ln() const
{
throw StackTrace("Operator `ln` does not exist for this type");
}
virtual RealPtr
log10() const
{
throw StackTrace("Operator `log10` does not exist for this type");
}
virtual BoolPtr
isinf() const
{
throw StackTrace("Operator `isinf` does not exist for this type");
}
virtual BoolPtr
isnan() const
{
throw StackTrace("Operator `isnan` does not exist for this type");
}
virtual BoolPtr
isfinite() const
{
throw StackTrace("Operator `isfinite` does not exist for this type");
}
virtual BoolPtr
isnormal() const
{
throw StackTrace("Operator `isnormal` does not exist for this type");
}
virtual RealPtr
sin() const
{
throw StackTrace("Operator `sin` does not exist for this type");
}
virtual RealPtr
cos() const
{
throw StackTrace("Operator `cos` does not exist for this type");
}
virtual RealPtr
tan() const
{
throw StackTrace("Operator `tan` does not exist for this type");
}
virtual RealPtr
asin() const
{
throw StackTrace("Operator `asin` does not exist for this type");
}
virtual RealPtr
acos() const
{
throw StackTrace("Operator `acos` does not exist for this type");
}
virtual RealPtr
atan() const
{
throw StackTrace("Operator `atan` does not exist for this type");
}
virtual RealPtr
sqrt() const
{
throw StackTrace("Operator `sqrt` does not exist for this type");
}
virtual RealPtr
cbrt() const
{
throw StackTrace("Operator `cbrt` does not exist for this type");
}
virtual RealPtr
sign() const
{
throw StackTrace("Operator `sign` does not exist for this type");
}
virtual RealPtr
floor() const
{
throw StackTrace("Operator `floor` does not exist for this type");
}
virtual RealPtr
ceil() const
{
throw StackTrace("Operator `ceil` does not exist for this type");
}
virtual RealPtr
trunc() const
{
throw StackTrace("Operator `trunc` does not exist for this type");
}
virtual RealPtr
sum() const
{
throw StackTrace("Operator `sum` does not exist for this type");
}
virtual RealPtr
erf() const
{
throw StackTrace("Operator `erf` does not exist for this type");
}
virtual RealPtr
erfc() const
{
throw StackTrace("Operator `erfc` does not exist for this type");
}
virtual RealPtr
gamma() const
{
throw StackTrace("Operator `gamma` does not exist for this type");
}
virtual RealPtr
lgamma() const
{
throw StackTrace("Operator `lgamma` does not exist for this type");
}
virtual RealPtr
round() const
{
throw StackTrace("Operator `round` does not exist for this type");
}
virtual RealPtr
normpdf() const
{
throw StackTrace("Operator `normpdf` does not exist for this type");
}
virtual RealPtr
normpdf([[maybe_unused]] const BaseTypePtr& btp1, [[maybe_unused]] 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([[maybe_unused]] const BaseTypePtr& btp1, [[maybe_unused]] const BaseTypePtr& btp2) const
{
throw StackTrace("Operator `normcdf` does not exist for this type");
}
virtual BoolPtr
cast_bool([[maybe_unused]] Environment& env) const
{
throw StackTrace("This type cannot be cast to a boolean");
}
virtual RealPtr
cast_real([[maybe_unused]] 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([[maybe_unused]] const Environment& env) const
{
throw StackTrace("Operator `defined` does not exist for this type");
}
};
class Bool final : public BaseType
{
private:
const bool value;
public:
Bool(bool value_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{value_arg} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::Bool; }
string to_string() const noexcept override { return value ? "true" : "false"; }
void print(ostream &output, [[maybe_unused]] bool matlab_output = false) const noexcept override { output << to_string(); }
Bool(bool value_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), value {value_arg}
{
}
codes::BaseType
getType() const noexcept override
{
return codes::BaseType::Bool;
}
string
to_string() const noexcept override
{
return value ? "true" : "false";
}
void
print(ostream& output, [[maybe_unused]] bool matlab_output = false) const noexcept override
{
output << to_string();
}
public:
operator bool() const { return value; }
operator bool() const
{
return value;
}
BoolPtr is_equal(const BaseTypePtr& btp) 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;
BoolPtr isboolean() const noexcept override { return make_shared<Bool>(true, location); }
BoolPtr cast_bool([[maybe_unused]] Environment &env) const override { return make_shared<Bool>(value); }
RealPtr cast_real([[maybe_unused]] Environment &env) const override { return value ? make_shared<Real>(1) : make_shared<Real>(0); }
StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
BoolPtr
isboolean() const noexcept override
{
return make_shared<Bool>(true, location);
}
BoolPtr
cast_bool([[maybe_unused]] Environment& env) const override
{
return make_shared<Bool>(value);
}
RealPtr
cast_real([[maybe_unused]] Environment& env) const override
{
return value ? make_shared<Real>(1) : make_shared<Real>(0);
}
StringPtr
cast_string() const override
{
return make_shared<String>(this->to_string());
}
TuplePtr
cast_tuple() const override
{
......@@ -234,23 +537,27 @@ namespace macro
}
};
class Real final : public BaseType
{
private:
const double value;
public:
// Use strtod to handle extreme cases (e.g. 1e500, 1e-500), nan, inf
// See Note in NumericalConstants::AddNonNegativeConstant
Real(const string &value_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{strtod(value_arg.c_str(), nullptr)} { }
Real(double value_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{value_arg} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::Real; }
Real(const string& value_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), value {strtod(value_arg.c_str(), nullptr)}
{
}
Real(double value_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), value {value_arg}
{
}
codes::BaseType
getType() const noexcept override
{
return codes::BaseType::Real;
}
string
to_string() const noexcept override
{
......@@ -258,13 +565,29 @@ namespace macro
strs << setprecision(15) << value;
return strs.str();
}
void print(ostream &output, [[maybe_unused]] bool matlab_output = false) const noexcept override { output << to_string(); }
void
print(ostream& output, [[maybe_unused]] bool matlab_output = false) const noexcept override
{
output << to_string();
}
public:
operator double() const { return value; }
operator double() const
{
return value;
}
BaseTypePtr plus(const BaseTypePtr& bt) const override;
BaseTypePtr unary_plus() const override { return make_shared<Real>(value); }
BaseTypePtr
unary_plus() const override
{
return make_shared<Real>(value);
}
BaseTypePtr minus(const BaseTypePtr& bt) const override;
BaseTypePtr unary_minus() const override { return make_shared<Real>(-value); }
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;
......@@ -273,8 +596,13 @@ 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;
BoolPtr isreal() const noexcept override { return make_shared<Bool>(true, location); }
BoolPtr isinteger() const noexcept override
BoolPtr
isreal() const noexcept override
{
return make_shared<Bool>(true, location);
}
BoolPtr
isinteger() const noexcept override
{
double intpart;
return make_shared<Bool>(modf(value, &intpart) == 0.0, location);
......@@ -285,34 +613,126 @@ namespace macro
RealPtr max(const BaseTypePtr& btp) const override;
RealPtr min(const BaseTypePtr& btp) const override;
RealPtr mod(const BaseTypePtr& btp) const override;
RealPtr exp() const override { return make_shared<Real>(std::exp(value)); }
RealPtr ln() const override { return make_shared<Real>(std::log(value)); }
RealPtr log10() const override { return make_shared<Real>(std::log10(value)); }
BoolPtr isinf() const override { return make_shared<Bool>(std::isinf(value)); }
BoolPtr isnan() const override { return make_shared<Bool>(std::isnan(value)); }
BoolPtr isfinite() const override { return make_shared<Bool>(std::isfinite(value)); }
BoolPtr isnormal() const override { return make_shared<Bool>(std::isnormal(value)); }
RealPtr sin() const override { return make_shared<Real>(std::sin(value)); }
RealPtr cos() const override { return make_shared<Real>(std::cos(value)); }
RealPtr tan() const override { return make_shared<Real>(std::tan(value)); }
RealPtr asin() const override { return make_shared<Real>(std::asin(value)); }
RealPtr acos() const override { return make_shared<Real>(std::acos(value)); }
RealPtr atan() const override { return make_shared<Real>(std::atan(value)); }
RealPtr sqrt() const override { return make_shared<Real>(std::sqrt(value)); }
RealPtr cbrt() const override { return make_shared<Real>(std::cbrt(value)); }
RealPtr
exp() const override
{
return make_shared<Real>(std::exp(value));
}
RealPtr
ln() const override
{
return make_shared<Real>(std::log(value));
}
RealPtr
log10() const override
{
return make_shared<Real>(std::log10(value));
}
BoolPtr
isinf() const override
{
return make_shared<Bool>(std::isinf(value));
}
BoolPtr
isnan() const override
{
return make_shared<Bool>(std::isnan(value));
}
BoolPtr
isfinite() const override
{
return make_shared<Bool>(std::isfinite(value));
}
BoolPtr
isnormal() const override
{
return make_shared<Bool>(std::isnormal(value));
}
RealPtr
sin() const override
{
return make_shared<Real>(std::sin(value));
}
RealPtr
cos() const override
{
return make_shared<Real>(std::cos(value));
}
RealPtr
tan() const override
{
return make_shared<Real>(std::tan(value));
}
RealPtr
asin() const override
{
return make_shared<Real>(std::asin(value));
}
RealPtr
acos() const override
{
return make_shared<Real>(std::acos(value));
}
RealPtr
atan() const override
{
return make_shared<Real>(std::atan(value));
}
RealPtr
sqrt() const override
{
return make_shared<Real>(std::sqrt(value));
}
RealPtr
cbrt() const override
{
return make_shared<Real>(std::cbrt(value));
}
RealPtr
sign() const override
{
return make_shared<Real>((value > 0) ? 1. : ((value < 0) ? -1. : 0.));
}
RealPtr floor() const override { return make_shared<Real>(std::floor(value)); }
RealPtr ceil() const override { return make_shared<Real>(std::ceil(value)); }
RealPtr trunc() const override { return make_shared<Real>(std::trunc(value)); }
RealPtr erf() const override { return make_shared<Real>(std::erf(value)); }
RealPtr erfc() const override { return make_shared<Real>(std::erfc(value)); }
RealPtr gamma() const override { return make_shared<Real>(std::tgamma(value)); }
RealPtr lgamma() const override { return make_shared<Real>(std::lgamma(value)); }
RealPtr round() const override { return make_shared<Real>(std::round(value)); }
RealPtr
floor() const override
{
return make_shared<Real>(std::floor(value));
}
RealPtr
ceil() const override
{
return make_shared<Real>(std::ceil(value));
}
RealPtr
trunc() const override
{
return make_shared<Real>(std::trunc(value));
}
RealPtr
erf() const override
{
return make_shared<Real>(std::erf(value));
}
RealPtr
erfc() const override
{
return make_shared<Real>(std::erfc(value));
}
RealPtr
gamma() const override
{
return make_shared<Real>(std::tgamma(value));
}
RealPtr
lgamma() const override
{
return make_shared<Real>(std::lgamma(value));
}
RealPtr
round() const override
{
return make_shared<Real>(std::round(value));
}
RealPtr
normpdf() const override
{
......@@ -325,9 +745,21 @@ namespace macro
return normcdf(make_shared<Real>(0), make_shared<Real>(1));
}
RealPtr normcdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const override;
BoolPtr cast_bool([[maybe_unused]] Environment &env) const override { return make_shared<Bool>(static_cast<bool>(value)); }
RealPtr cast_real([[maybe_unused]] Environment &env) const override { return make_shared<Real>(value); }
StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
BoolPtr
cast_bool([[maybe_unused]] Environment& env) const override
{
return make_shared<Bool>(static_cast<bool>(value));
}
RealPtr
cast_real([[maybe_unused]] Environment& env) const override
{
return make_shared<Real>(value);
}
StringPtr
cast_string() const override
{
return make_shared<String>(this->to_string());
}
TuplePtr
cast_tuple() const override
{
......@@ -344,28 +776,57 @@ namespace macro
{
private:
const string value;
public:
String(string value_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
value{move(value_arg)} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::String; }
string to_string() const noexcept override { return value; }
String(string value_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), value {move(value_arg)}
{
}
codes::BaseType
getType() const noexcept override
{
return codes::BaseType::String;
}
string
to_string() const noexcept override
{
return value;
}
void print(ostream& output, bool matlab_output = false) const noexcept override;
public:
operator string() const { return value; }
operator string() const
{
return value;
}
BaseTypePtr plus(const BaseTypePtr& bt) const override;
BoolPtr is_less(const BaseTypePtr& btp) const override;
BoolPtr is_greater(const BaseTypePtr& btp) const override;
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;
BoolPtr isstring() const noexcept override { return make_shared<Bool>(true, location); }
RealPtr length() const override { return make_shared<Real>(value.size()); }
BoolPtr isempty() const override { return make_shared<Bool>(value.empty()); }
BoolPtr
isstring() const noexcept override
{
return make_shared<Bool>(true, location);
}
RealPtr
length() const override
{
return make_shared<Real>(value.size());
}
BoolPtr
isempty() const override
{
return make_shared<Bool>(value.empty());
}
BoolPtr cast_bool(Environment& env) const override;
RealPtr cast_real(Environment& env) const override;
StringPtr cast_string() const override { return make_shared<String>(value); }
StringPtr
cast_string() const override
{
return make_shared<String>(value);
}
TuplePtr
cast_tuple() const override
{
......@@ -383,88 +844,188 @@ namespace macro
}
};
class Tuple final : public BaseType
{
private:
const vector<ExpressionPtr> tup;
public:
Tuple(vector<ExpressionPtr> tup_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)),
tup{move(tup_arg)} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::Tuple; }
Tuple(vector<ExpressionPtr> tup_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), tup {move(tup_arg)}
{
}
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(Environment& env) const override;
public:
size_t size() const { return tup.size(); }
bool empty() const { return tup.empty(); }
const vector<ExpressionPtr> &getValue() const { return tup; }
const ExpressionPtr &at(int i) const { return tup.at(i); }
size_t
size() const
{
return tup.size();
}
bool
empty() const
{
return tup.empty();
}
const vector<ExpressionPtr>&
getValue() const
{
return tup;
}
const ExpressionPtr&
at(int i) const
{
return tup.at(i);
}
BoolPtr is_equal(const BaseTypePtr& btp) const override;
BoolPtr istuple() const noexcept override { return make_shared<Bool>(true, location); }
BoolPtr
istuple() const noexcept override
{
return make_shared<Bool>(true, location);
}
BoolPtr contains(const BaseTypePtr& btp) const override;
RealPtr length() const override { return make_shared<Real>(tup.size()); }
BoolPtr isempty() const override { return make_shared<Bool>(empty()); }
RealPtr
length() const override
{
return make_shared<Real>(tup.size());
}
BoolPtr
isempty() const override
{
return make_shared<Bool>(empty());
}
BoolPtr cast_bool(Environment& env) const override;
RealPtr cast_real(Environment& env) const override;
StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
TuplePtr cast_tuple() const override { return make_shared<Tuple>(tup); }
ArrayPtr cast_array() const override { return make_shared<Array>(tup); }
StringPtr
cast_string() const override
{
return make_shared<String>(this->to_string());
}
TuplePtr
cast_tuple() const override
{
return make_shared<Tuple>(tup);
}
ArrayPtr
cast_array() const override
{
return make_shared<Array>(tup);
}
};
class Array final : public BaseType
{
private:
const vector<ExpressionPtr> arr;
public:
Array(vector<ExpressionPtr> arr_arg,
Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), arr{move(arr_arg)} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::Array; }
Array(vector<ExpressionPtr> arr_arg, Tokenizer::location location_arg = Tokenizer::location()) :
BaseType(move(location_arg)), arr {move(arr_arg)}
{
}
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(Environment& env) const override;
public:
size_t size() const { return arr.size(); }
const vector<ExpressionPtr> &getValue() const { return arr; }
const ExpressionPtr &at(int i) const { return arr.at(i); }
bool empty() const { return arr.empty(); }
size_t
size() const
{
return arr.size();
}
const vector<ExpressionPtr>&
getValue() const
{
return arr;
}
const ExpressionPtr&
at(int i) const
{
return arr.at(i);
}
bool
empty() const
{
return arr.empty();
}
BaseTypePtr plus(const BaseTypePtr& bt) const override;
BaseTypePtr minus(const BaseTypePtr& bt) const override;
BaseTypePtr times(const BaseTypePtr& bt) const override;
BaseTypePtr power(const BaseTypePtr& btp) const override;
BoolPtr is_equal(const BaseTypePtr& btp) const override;
BoolPtr isarray() const noexcept override { return make_shared<Bool>(true, location); }
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;
RealPtr length() const override { return make_shared<Real>(arr.size()); }
BoolPtr isempty() const override { return make_shared<Bool>(empty()); }
RealPtr
length() const override
{
return make_shared<Real>(arr.size());
}
BoolPtr
isempty() const override
{
return make_shared<Bool>(empty());
}
RealPtr sum() const override;
BoolPtr cast_bool(Environment& env) const override;
RealPtr cast_real(Environment& env) const override;
StringPtr cast_string() const override { return make_shared<String>(this->to_string()); }
TuplePtr cast_tuple() const override { return make_shared<Tuple>(arr); }
ArrayPtr cast_array() const override { return make_shared<Array>(arr); }
StringPtr
cast_string() const override
{
return make_shared<String>(this->to_string());
}
TuplePtr
cast_tuple() const override
{
return make_shared<Tuple>(arr);
}
ArrayPtr
cast_array() const override
{
return make_shared<Array>(arr);
}
};
class Range final : public BaseType
{
private:
const ExpressionPtr start, inc, end;
public:
Range(ExpressionPtr start_arg, ExpressionPtr end_arg,
Tokenizer::location location_arg) :
BaseType(move(location_arg)), start{move(start_arg)}, end{move(end_arg)} { }
Range(ExpressionPtr start_arg, ExpressionPtr 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,
Tokenizer::location location_arg) :
BaseType(move(location_arg)),
start{move(start_arg)}, inc{move(inc_arg)}, end{move(end_arg)} { }
codes::BaseType getType() const noexcept override { return codes::BaseType::Range; }
start {move(start_arg)},
inc {move(inc_arg)},
end {move(end_arg)}
{
}
codes::BaseType
getType() const noexcept override
{
return codes::BaseType::Range;
}
string
to_string() const noexcept override
{
......@@ -473,8 +1034,13 @@ namespace macro
retval += inc->to_string() + ":";
return retval + end->to_string() + "]";
}
void print(ostream &output, [[maybe_unused]] bool matlab_output = false) const noexcept override { output << to_string(); }
void
print(ostream& output, [[maybe_unused]] bool matlab_output = false) const noexcept override
{
output << to_string();
}
BaseTypePtr eval(Environment& env) const override;
public:
BoolPtr
is_equal([[maybe_unused]] const BaseTypePtr& btp) const override
......@@ -483,104 +1049,143 @@ namespace macro
}
};
class Variable final : public Expression
{
private:
const string name;
const ArrayPtr indices; // for indexing strings/arrays
public:
Variable(string name_arg,
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)} { }
Variable(string name_arg, ArrayPtr indices_arg,
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)}, indices{move(indices_arg)} { }
string to_string() const noexcept override { return name; }
void print(ostream &output, [[maybe_unused]] bool matlab_output = false) const noexcept override { output << name; }
Variable(string name_arg, Tokenizer::location location_arg) :
Expression(move(location_arg)), name {move(name_arg)}
{
}
Variable(string name_arg, ArrayPtr indices_arg, Tokenizer::location location_arg) :
Expression(move(location_arg)), name {move(name_arg)}, indices {move(indices_arg)}
{
}
[[nodiscard]] string
to_string() const noexcept override
{
return name;
}
void
print(ostream& output, [[maybe_unused]] bool matlab_output = false) const noexcept override
{
output << name;
}
BaseTypePtr eval(Environment& env) const override;
public:
const string &getName() const noexcept { return name; }
codes::BaseType getType(const Environment &env) const { return env.getType(name); }
[[nodiscard]] const string&
getName() const noexcept
{
return name;
}
[[nodiscard]] codes::BaseType
getType(const Environment& env) const
{
return env.getType(name);
}
};
class Function final : public Expression
{
private:
const string name;
const vector<ExpressionPtr> args;
public:
Function(string name_arg,
vector<ExpressionPtr> args_arg,
Tokenizer::location location_arg) :
Expression(move(location_arg)), name{move(name_arg)}, args{move(args_arg)} { }
string to_string() const noexcept override;
Function(string name_arg, vector<ExpressionPtr> args_arg, Tokenizer::location location_arg) :
Expression(move(location_arg)), name {move(name_arg)}, args {move(args_arg)}
{
}
[[nodiscard]] string to_string() const noexcept override;
void
print(ostream& output, [[maybe_unused]] bool matlab_output = false) const noexcept override
{
printName(output); printArgs(output);
printName(output);
printArgs(output);
}
BaseTypePtr eval(Environment& env) const override;
public:
void printName(ostream &output) const noexcept { output << name; }
void
printName(ostream& output) const noexcept
{
output << name;
}
void printArgs(ostream& output) const noexcept;
const string &getName() const { return name; }
const vector<ExpressionPtr> &getArgs() const { return args; }
[[nodiscard]] const string&
getName() const
{
return name;
}
[[nodiscard]] const vector<ExpressionPtr>&
getArgs() const
{
return args;
}
};
class UnaryOp final : public Expression
{
private:
const codes::UnaryOp op_code;
const ExpressionPtr arg;
public:
UnaryOp(codes::UnaryOp op_code_arg,
ExpressionPtr 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;
UnaryOp(codes::UnaryOp op_code_arg, ExpressionPtr arg_arg, Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code {op_code_arg}, arg {move(arg_arg)}
{
}
[[nodiscard]] string to_string() const noexcept override;
void print(ostream& output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval(Environment& env) const override;
};
class BinaryOp final : public Expression
{
private:
const codes::BinaryOp op_code;
const ExpressionPtr arg1, arg2;
public:
BinaryOp(codes::BinaryOp op_code_arg,
ExpressionPtr arg1_arg, ExpressionPtr arg2_arg,
BinaryOp(codes::BinaryOp op_code_arg, ExpressionPtr arg1_arg, ExpressionPtr arg2_arg,
Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code{op_code_arg},
arg1{move(arg1_arg)}, arg2{move(arg2_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;
[[nodiscard]] string to_string() const noexcept override;
void print(ostream& output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval(Environment& env) const override;
};
class TrinaryOp final : public Expression
{
private:
const codes::TrinaryOp op_code;
const ExpressionPtr arg1, arg2, arg3;
public:
TrinaryOp(codes::TrinaryOp op_code_arg,
ExpressionPtr arg1_arg, ExpressionPtr arg2_arg, ExpressionPtr arg3_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;
TrinaryOp(codes::TrinaryOp op_code_arg, ExpressionPtr arg1_arg, ExpressionPtr arg2_arg,
ExpressionPtr arg3_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)}
{
}
[[nodiscard]] string to_string() const noexcept override;
void print(ostream& output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval(Environment& env) const override;
};
class Comprehension final : public Expression
{
/*
......@@ -590,29 +1195,35 @@ namespace macro
*/
private:
const ExpressionPtr c_expr, c_vars, c_set, c_when;
public:
Comprehension(ExpressionPtr c_expr_arg,
ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg,
ExpressionPtr c_when_arg,
Tokenizer::location location_arg) :
Comprehension(ExpressionPtr c_expr_arg, ExpressionPtr c_vars_arg, ExpressionPtr c_set_arg,
ExpressionPtr c_when_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,
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,
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([[maybe_unused]] bool filter_only_arg,
ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg,
ExpressionPtr c_when_arg,
c_expr {move(c_expr_arg)},
c_vars {move(c_vars_arg)},
c_set {move(c_set_arg)}
{
}
Comprehension([[maybe_unused]] bool filter_only_arg, ExpressionPtr c_vars_arg,
ExpressionPtr c_set_arg, ExpressionPtr c_when_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;
c_vars {move(c_vars_arg)},
c_set {move(c_set_arg)},
c_when {move(c_when_arg)}
{
}
[[nodiscard]] string to_string() const noexcept override;
void print(ostream& output, bool matlab_output = false) const noexcept override;
BaseTypePtr eval(Environment& env) const override;
};
......
/*
* Copyright © 2019 Dynare Team
* Copyright © 2019-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _FORWARDDECLARATIONSANDENUMS_HH
#define _FORWARDDECLARATIONSANDENUMS_HH
#ifndef FORWARD_DECLARATIONS_AND_ENUMS_HH
#define FORWARD_DECLARATIONS_AND_ENUMS_HH
#include <memory>
......
// -*- C++ -*-
/*
* Copyright © 2019-2022 Dynare Team
* Copyright © 2019-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -28,10 +28,6 @@
%define parse.error verbose
%define parse.trace
%code requires {
namespace macro { class Driver; }
}
%param { macro::Driver& driver }
%locations
......@@ -43,6 +39,9 @@ namespace macro { class Driver; }
%code requires {
#include "Directives.hh"
namespace macro { class Driver; }
using namespace macro;
}
......@@ -307,7 +306,10 @@ function : NAME LPAREN RPAREN
function_args : symbol
{ $$ = {$1}; }
| function_args COMMA symbol
{ $1.emplace_back($3); $$ = $1; }
{
$1.emplace_back($3);
$$ = $1;
}
;
comma_expr : %empty
......@@ -315,7 +317,10 @@ comma_expr : %empty
| expr
{ $$ = {$1}; }
| comma_expr COMMA expr
{ $1.emplace_back($3); $$ = $1; }
{
$1.emplace_back($3);
$$ = $1;
}
;
tuple_comma_expr : %empty
......@@ -325,7 +330,10 @@ tuple_comma_expr : %empty
| expr COMMA expr
{ $$ = {$1, $3}; }
| tuple_comma_expr COMMA expr
{ $1.emplace_back($3); $$ = $1; }
{
$1.emplace_back($3);
$$ = $1;
}
;
primary_expr : LPAREN expr RPAREN
......@@ -333,9 +341,7 @@ primary_expr : LPAREN expr RPAREN
| symbol
{ $$ = $1; } // Explicit rule needed for type conversion
| NAME LBRACKET comma_expr RBRACKET
{
$$ = make_shared<Variable>($1, make_shared<Array>($3, @3), @$);
}
{ $$ = make_shared<Variable>($1, make_shared<Array>($3, @3), @$); }
| NAME LPAREN comma_expr RPAREN
{ $$ = make_shared<Function>($1, $3, @$); }
| TRUE
......
......@@ -42,7 +42,7 @@ preprocessor_src = [ 'ComputingTasks.cc',
'ParsingDriver.cc',
'DataTree.cc',
'ModFile.cc',
'ConfigFile.cc',
'Configuration.cc',
'Statement.cc',
'ExprNode.cc',
'VariableDependencyGraph.cc',
......@@ -53,6 +53,8 @@ preprocessor_src = [ 'ComputingTasks.cc',
'ModelEquationBlock.cc',
'WarningConsolidation.cc',
'SubModel.cc',
'HeterogeneityTable.cc',
'HeterogeneousModel.cc',
'macro/Driver.cc',
'macro/Environment.cc',
'macro/Expressions.cc',
......