Skip to content
Snippets Groups Projects
Select Git revision
  • 42c12629a661ac8e81e0a8a437e8bf8b94ca6dad
  • master default protected
  • julia protected
  • 6.x protected
  • python-codegen
  • llvm-15
  • 5.x protected
  • 4.6 protected
  • uop
  • rework_pac
  • aux_vars_fix
  • julia-7.0.0
  • julia-6.4.0
  • julia-6.3.0
  • julia-6.2.0
15 results

Environment.cc

Blame
  • Environment.cc 4.68 KiB
    /*
     * Copyright © 2019-2024 Dynare Team
     *
     * This file is part of Dynare.
     *
     * Dynare is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * Dynare is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
     */
    
    #include <algorithm>
    #include <cassert>
    #include <ranges>
    
    #include "Environment.hh"
    #include "Expressions.hh"
    
    using namespace macro;
    
    void
    Environment::define(const VariablePtr& var, const ExpressionPtr& value)
    {
      string name = var->getName();
      if (functions.contains(name))
        throw StackTrace("Variable " + name + " was previously defined as a function");
      variables[move(name)] = value->eval(*this);
    }
    
    void
    Environment::define(FunctionPtr func, ExpressionPtr value)
    {
      string name = func->getName();
      if (variables.contains(name))
        throw StackTrace("Variable " + name + " was previously defined as a variable");
      functions[name] = {move(func), move(value)};
    }
    
    ExpressionPtr
    Environment::getVariable(const string& name) const
    {
      if (auto it = variables.find(name); it != variables.end())
        return it->second;
    
      if (!parent)
        throw StackTrace("Unknown variable " + name);
    
      return getGlobalEnv()->getVariable(name);
    }
    
    pair<FunctionPtr, ExpressionPtr>
    Environment::getFunction(const string& name) const
    {
      if (auto it = functions.find(name); it != functions.end())
        return it->second;
    
      if (!parent)
        throw StackTrace("Unknown function " + name);
    
      return parent->getFunction(name);
    }
    
    codes::BaseType
    Environment::getType(const string& name) const
    {
      return getVariable(name)->eval(const_cast<Environment&>(*this))->getType();
    }
    
    bool
    Environment::isVariableDefined(const string& name) const noexcept
    {
      try
        {
          getVariable(name);
          return true;
        }
      catch (StackTrace& ex)
        {
          return false;
        }
    }
    
    bool
    Environment::isFunctionDefined(const string& name) const noexcept
    {
      try
        {
          getFunction(name);
          return true;
        }
      catch (StackTrace& ex)
        {
          return false;
        }
    }
    
    void
    Environment::print(ostream& output, const vector<string>& vars, int line, bool save) const
    {
      if (!save && !variables.empty())
        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 lexicographical_compare(
            begin(a), end(a), begin(b), end(b),
            [](const char& c1, const char& c2) { return tolower(c1) < tolower(c2); });
      };
    
      if (vars.empty())
        {
          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 (at line " << line << "):" << endl;
    
      if (vars.empty())
        {
          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, it, line, save);
    
      if (parent)
        parent->print(output, vars, line, save);
    }
    
    void
    Environment::printVariable(ostream& output, const string& name, int line, bool save) const
    {
      output << (save ? "options_.macrovars_line_" + to_string(line) + "." : "  ") << name << " = ";
      getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save);
      if (save)
        output << ";";
      output << endl;
    }
    
    void
    Environment::printFunction(ostream& output, const string& name, int line, bool save) const
    {
      auto [func_signature, func_body] = getFunction(name);
      output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : "  ");
      if (save)
        {
          func_signature->printName(output);
          output << " = '";
        }
    
      func_signature->print(output);
      output << " = ";
      func_body->print(output);
    
      if (save)
        output << "';";
      output << endl;
    }