<commit_before>/*
 * Copyright (C) 2008-2010, <NAME>.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/finally.hh>

#include <ast/cloner.hxx>
#include <ast/new-clone.hh>
#include <ast/parametric-ast.hh>

#include <object/symbols.hh>

#include <ast/factory.hh>
#include <ast/event-match.hh>
#include <parser/parse.hh>

#include <rewrite/desugarer.hh>
#include <rewrite/pattern-binder.hh>

namespace rewrite
{
  Desugarer::Desugarer()
    : pattern_(false)
    , allow_decl_(false)
    , allow_subdecl_(false)
  {}


  template <typename T>
  libport::intrusive_ptr<typename boost::remove_const<T>::type>
  Desugarer::recurse_with_subdecl(T* s)
  {
    libport::Finally finally;
    finally << libport::scoped_set(allow_subdecl_, true);
    super_type::visit(s);
    passert(*s, result_);
    typedef typename boost::remove_const<T>::type T_no_const;
    return result_.unsafe_cast<T_no_const>();
  }

  void
  Desugarer::err(const ast::loc& loc, const std::string& msg)
  {
    errors_.err(loc, msg, "syntax error");
  }

  template <typename T>
  libport::intrusive_ptr<typename boost::remove_const<T>::type>
  Desugarer::recurse_with_subdecl(libport::intrusive_ptr<T> s)
  {
    libport::Finally finally;
    finally << libport::scoped_set(allow_subdecl_, true);
    aver(s);
    return recurse(s);
  }

  void Desugarer::visit(const ast::And* s)
  {
    recurse_with_subdecl(s);
  }

  void
  Desugarer::desugar_modifiers(const ast::Assign* assign)
  {
    ast::rLValue what = assign->what_get().unsafe_cast<ast::LValue>();
    if (!what)
      err(what->location_get(),
          "cannot use modifiers on pattern assignments");

    ast::rConstBinding binding = what.unsafe_cast<const ast::Binding>();
    if (binding)
      what = binding->what_get();

    const ast::loc& loc = assign->location_get();
    ast::rLValue tgt = factory_->make_lvalue_once(what);

    // Complete the dictionary with the base, getter and setter.
    // FIXME: There is a copy here that we would like to get rid of.
    ast::modifiers_type source = *assign->modifiers_get();
    source[SYMBOL(base)] = assign->value_get();
    source[SYMBOL(getter)] = factory_->make_closure(new_clone(tgt));
    PARAMETRIC_AST(setter, "closure (v) { %exp:1 }");
    source[SYMBOL(setter)] =
      exp(setter
          % new ast::Assign(loc, new_clone(tgt),
                            factory_->make_call(loc, SYMBOL(v)), 0));

    // Convert into a dictionary.  Sort it to improve determinism in
    // the desugared output.  The cost is neglectible.
    ast::rExp dict;
    {
      std::vector<libport::Symbol> keys;
      foreach (const ast::modifiers_type::value_type& i, source)
        keys << i.first;
      std::sort(keys.begin(), keys.end());

      ast::dictionary_elts_type d;
      foreach (libport::Symbol k, keys)
        d << ast::dictionary_elt_type(new ast::String(loc, k),
                                      recurse(source[k]));
      dict = new ast::Dictionary(loc, d);
    }
    PARAMETRIC_AST(traj, "TrajectoryGenerator.new(%exp:1).run");
    ast::rExp res(factory_->make_lvalue_wrap(what, exp(traj % dict).get()));

    if (binding)
    {
      PARAMETRIC_AST(declare, "var %lvalue:1 | %exp:2");
      res = exp(declare % what % res);
    }

    res->original_set(assign);
    result_ = recurse(res);<commit_msg>trajectories: fix exception.chk.<commit_after>/*
 * Copyright (C) 2008-2010, <NAME>.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/finally.hh>

#include <ast/cloner.hxx>
#include <ast/new-clone.hh>
#include <ast/parametric-ast.hh>

#include <object/symbols.hh>

#include <ast/factory.hh>
#include <ast/event-match.hh>
#include <parser/parse.hh>

#include <rewrite/desugarer.hh>
#include <rewrite/pattern-binder.hh>

namespace rewrite
{
  Desugarer::Desugarer()
    : pattern_(false)
    , allow_decl_(false)
    , allow_subdecl_(false)
  {}


  template <typename T>
  libport::intrusive_ptr<typename boost::remove_const<T>::type>
  Desugarer::recurse_with_subdecl(T* s)
  {
    libport::Finally finally;
    finally << libport::scoped_set(allow_subdecl_, true);
    super_type::visit(s);
    passert(*s, result_);
    typedef typename boost::remove_const<T>::type T_no_const;
    return result_.unsafe_cast<T_no_const>();
  }

  void
  Desugarer::err(const ast::loc& loc, const std::string& msg)
  {
    errors_.err(loc, msg, "syntax error");
  }

  template <typename T>
  libport::intrusive_ptr<typename boost::remove_const<T>::type>
  Desugarer::recurse_with_subdecl(libport::intrusive_ptr<T> s)
  {
    libport::Finally finally;
    finally << libport::scoped_set(allow_subdecl_, true);
    aver(s);
    return recurse(s);
  }

  void Desugarer::visit(const ast::And* s)
  {
    recurse_with_subdecl(s);
  }

  void
  Desugarer::desugar_modifiers(const ast::Assign* assign)
  {
    ast::rLValue what = assign->what_get().unsafe_cast<ast::LValue>();
    if (!what)
      err(what->location_get(),
          "cannot use modifiers on pattern assignments");

    ast::rConstBinding binding = what.unsafe_cast<const ast::Binding>();
    if (binding)
      what = binding->what_get();

    const ast::loc& loc = assign->location_get();
    ast::rLValue tgt = factory_->make_lvalue_once(what);

    // Complete the dictionary with the base, getter and setter.
    // FIXME: There is a copy here that we would like to get rid of.
    ast::modifiers_type source = *assign->modifiers_get();
    source[SYMBOL(base)] = assign->value_get();
    source[SYMBOL(getter)] = factory_->make_closure(new_clone(tgt));
    PARAMETRIC_AST(setter, "closure (v) { %exp:1 }");
    source[SYMBOL(setter)] =
      exp(setter
          % new ast::Assign(loc, new_clone(tgt),
                            factory_->make_call(loc, SYMBOL(v)), 0));

    // Convert into a dictionary.  Sort it to improve determinism in
    // the desugared output.  The cost is neglectible.
    ast::rExp dict;
    {
      std::vector<libport::Symbol> keys;
      foreach (const ast::modifiers_type::value_type& i, source)
        keys << i.first;
      std::sort(keys.begin(), keys.end());

      ast::dictionary_elts_type d;
      foreach (libport::Symbol k, keys)
        d << ast::dictionary_elt_type(new ast::String(loc, k),
                                      recurse(source[k]));
      dict = new ast::Dictionary(loc, d);
    }
    PARAMETRIC_AST(traj, "TrajectoryGenerator.new(%exp:1).run");
    ast::rExp res(factory_->make_lvalue_wrap(what, exp(traj % dict).get()));
    // Parametric ASTs forward the location of the user code to the
    // desugared code.  In the case of trajectories, this is a
    // nuisance, as it results in errors in "run" calls _not_ being
    // flagged as system errors.  So restore a location that really
    // means it's a system feature that should be hidden from the user
    // in the back traces.
    res->location_set(LOCATION_HERE);

    if (binding)
    {
      PARAMETRIC_AST(declare, "var %lvalue:1 | %exp:2");
      res = exp(declare % what % res);
    }

    res->original_set(assign);
    result_ = recurse(res);
{'fraction_non_alphanumeric': 0.1385316184351554, 'fraction_numerical': 0.0034833869239013935, 'mean_word_length': 3.4915764139590855, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7524364', 'n_tokens_mistral': 2525, 'n_tokens_neox': 2464, 'n_words': 574}