Blame src/cssize.cpp

Packit bfcc33
#include "sass.hpp"
Packit bfcc33
#include <iostream>
Packit bfcc33
#include <typeinfo>
Packit bfcc33
#include <vector>
Packit bfcc33
Packit bfcc33
#include "cssize.hpp"
Packit bfcc33
#include "context.hpp"
Packit bfcc33
#include "backtrace.hpp"
Packit bfcc33
Packit bfcc33
namespace Sass {
Packit bfcc33
Packit bfcc33
  Cssize::Cssize(Context& ctx, Backtrace* bt)
Packit bfcc33
  : ctx(ctx),
Packit bfcc33
    block_stack(std::vector<Block_Ptr>()),
Packit bfcc33
    p_stack(std::vector<Statement_Ptr>()),
Packit bfcc33
    backtrace(bt)
Packit bfcc33
  { }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::parent()
Packit bfcc33
  {
Packit bfcc33
    return p_stack.size() ? p_stack.back() : block_stack.front();
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Block_Ptr Cssize::operator()(Block_Ptr b)
Packit bfcc33
  {
Packit bfcc33
    Block_Ptr bb = SASS_MEMORY_NEW(Block, b->pstate(), b->length(), b->is_root());
Packit bfcc33
    // bb->tabs(b->tabs());
Packit bfcc33
    block_stack.push_back(bb);
Packit bfcc33
    append_block(b, bb);
Packit bfcc33
    block_stack.pop_back();
Packit bfcc33
    return bb;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Trace_Ptr t)
Packit bfcc33
  {
Packit bfcc33
    return t->block()->perform(this);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Declaration_Ptr d)
Packit bfcc33
  {
Packit bfcc33
    String_Obj property = Cast<String>(d->property());
Packit bfcc33
Packit bfcc33
    if (Declaration_Ptr dd = Cast<Declaration>(parent())) {
Packit bfcc33
      String_Obj parent_property = Cast<String>(dd->property());
Packit bfcc33
      property = SASS_MEMORY_NEW(String_Constant,
Packit bfcc33
                                 d->property()->pstate(),
Packit bfcc33
                                 parent_property->to_string() + "-" + property->to_string());
Packit bfcc33
      if (!dd->value()) {
Packit bfcc33
        d->tabs(dd->tabs() + 1);
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Declaration_Obj dd = SASS_MEMORY_NEW(Declaration,
Packit bfcc33
                                      d->pstate(),
Packit bfcc33
                                      property,
Packit bfcc33
                                      d->value(),
Packit bfcc33
                                      d->is_important());
Packit bfcc33
    dd->is_indented(d->is_indented());
Packit bfcc33
    dd->tabs(d->tabs());
Packit bfcc33
Packit bfcc33
    p_stack.push_back(dd);
Packit bfcc33
    Block_Obj bb = d->block() ? operator()(d->block()) : NULL;
Packit bfcc33
    p_stack.pop_back();
Packit bfcc33
Packit bfcc33
    if (bb && bb->length()) {
Packit bfcc33
      if (dd->value() && !dd->value()->is_invisible()) {
Packit bfcc33
        bb->unshift(dd);
Packit bfcc33
      }
Packit bfcc33
      return bb.detach();
Packit bfcc33
    }
Packit bfcc33
    else if (dd->value() && !dd->value()->is_invisible()) {
Packit bfcc33
      return dd.detach();
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    return 0;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Directive_Ptr r)
Packit bfcc33
  {
Packit bfcc33
    if (!r->block() || !r->block()->length()) return r;
Packit bfcc33
Packit bfcc33
    if (parent()->statement_type() == Statement::RULESET)
Packit bfcc33
    {
Packit bfcc33
      return (r->is_keyframes()) ? SASS_MEMORY_NEW(Bubble, r->pstate(), r) : bubble(r);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    p_stack.push_back(r);
Packit bfcc33
    Directive_Obj rr = SASS_MEMORY_NEW(Directive,
Packit bfcc33
                                  r->pstate(),
Packit bfcc33
                                  r->keyword(),
Packit bfcc33
                                  r->selector(),
Packit bfcc33
                                  r->block() ? operator()(r->block()) : 0);
Packit bfcc33
    if (r->value()) rr->value(r->value());
Packit bfcc33
    p_stack.pop_back();
Packit bfcc33
Packit bfcc33
    bool directive_exists = false;
Packit bfcc33
    size_t L = rr->block() ? rr->block()->length() : 0;
Packit bfcc33
    for (size_t i = 0; i < L && !directive_exists; ++i) {
Packit bfcc33
      Statement_Obj s = r->block()->at(i);
Packit bfcc33
      if (s->statement_type() != Statement::BUBBLE) directive_exists = true;
Packit bfcc33
      else {
Packit bfcc33
        Bubble_Obj s_obj = Cast<Bubble>(s);
Packit bfcc33
        s = s_obj->node();
Packit bfcc33
        if (s->statement_type() != Statement::DIRECTIVE) directive_exists = false;
Packit bfcc33
        else directive_exists = (Cast<Directive>(s)->keyword() == rr->keyword());
Packit bfcc33
      }
Packit bfcc33
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Block_Ptr result = SASS_MEMORY_NEW(Block, rr->pstate());
Packit bfcc33
    if (!(directive_exists || rr->is_keyframes()))
Packit bfcc33
    {
Packit bfcc33
      Directive_Ptr empty_node = Cast<Directive>(rr);
Packit bfcc33
      empty_node->block(SASS_MEMORY_NEW(Block, rr->block() ? rr->block()->pstate() : rr->pstate()));
Packit bfcc33
      result->append(empty_node);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Block_Obj db = rr->block();
Packit bfcc33
    if (db.isNull()) db = SASS_MEMORY_NEW(Block, rr->pstate());
Packit bfcc33
    Block_Obj ss = debubble(db, rr);
Packit bfcc33
    for (size_t i = 0, L = ss->length(); i < L; ++i) {
Packit bfcc33
      result->append(ss->at(i));
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    return result;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Keyframe_Rule_Ptr r)
Packit bfcc33
  {
Packit bfcc33
    if (!r->block() || !r->block()->length()) return r;
Packit bfcc33
Packit bfcc33
    Keyframe_Rule_Obj rr = SASS_MEMORY_NEW(Keyframe_Rule,
Packit bfcc33
                                        r->pstate(),
Packit bfcc33
                                        operator()(r->block()));
Packit bfcc33
    if (!r->name().isNull()) rr->name(r->name());
Packit bfcc33
Packit bfcc33
    return debubble(rr->block(), rr);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Ruleset_Ptr r)
Packit bfcc33
  {
Packit bfcc33
    p_stack.push_back(r);
Packit bfcc33
    // this can return a string schema
Packit bfcc33
    // string schema is not a statement!
Packit bfcc33
    // r->block() is already a string schema
Packit bfcc33
    // and that is comming from propset expand
Packit bfcc33
    Block_Ptr bb = operator()(r->block());
Packit bfcc33
    // this should protect us (at least a bit) from our mess
Packit bfcc33
    // fixing this properly is harder that it should be ...
Packit bfcc33
    if (Cast<Statement>(bb) == NULL) {
Packit bfcc33
      error("Illegal nesting: Only properties may be nested beneath properties.", r->block()->pstate());
Packit bfcc33
    }
Packit bfcc33
    Ruleset_Obj rr = SASS_MEMORY_NEW(Ruleset,
Packit bfcc33
                                  r->pstate(),
Packit bfcc33
                                  r->selector(),
Packit bfcc33
                                  bb);
Packit bfcc33
Packit bfcc33
    rr->is_root(r->is_root());
Packit bfcc33
    // rr->tabs(r->block()->tabs());
Packit bfcc33
    p_stack.pop_back();
Packit bfcc33
Packit bfcc33
    if (!rr->block()) {
Packit bfcc33
      error("Illegal nesting: Only properties may be nested beneath properties.", r->block()->pstate());
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Block_Obj props = SASS_MEMORY_NEW(Block, rr->block()->pstate());
Packit bfcc33
    Block_Ptr rules = SASS_MEMORY_NEW(Block, rr->block()->pstate());
Packit bfcc33
    for (size_t i = 0, L = rr->block()->length(); i < L; i++)
Packit bfcc33
    {
Packit bfcc33
      Statement_Ptr s = rr->block()->at(i);
Packit bfcc33
      if (bubblable(s)) rules->append(s);
Packit bfcc33
      if (!bubblable(s)) props->append(s);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    if (props->length())
Packit bfcc33
    {
Packit bfcc33
      Block_Obj pb = SASS_MEMORY_NEW(Block, rr->block()->pstate());
Packit bfcc33
      pb->concat(props);
Packit bfcc33
      rr->block(pb);
Packit bfcc33
Packit bfcc33
      for (size_t i = 0, L = rules->length(); i < L; i++)
Packit bfcc33
      {
Packit bfcc33
        Statement_Ptr stm = rules->at(i);
Packit bfcc33
        stm->tabs(stm->tabs() + 1);
Packit bfcc33
      }
Packit bfcc33
Packit bfcc33
      rules->unshift(rr);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Block_Ptr ptr = rules;
Packit bfcc33
    rules = debubble(rules);
Packit bfcc33
    void* lp = ptr;
Packit bfcc33
    void* rp = rules;
Packit bfcc33
    if (lp != rp) {
Packit bfcc33
      Block_Obj obj = ptr;
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    if (!(!rules->length() ||
Packit bfcc33
          !bubblable(rules->last()) ||
Packit bfcc33
          parent()->statement_type() == Statement::RULESET))
Packit bfcc33
    {
Packit bfcc33
      rules->last()->group_end(true);
Packit bfcc33
    }
Packit bfcc33
    return rules;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Null_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    return 0;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Media_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    if (parent()->statement_type() == Statement::RULESET)
Packit bfcc33
    { return bubble(m); }
Packit bfcc33
Packit bfcc33
    if (parent()->statement_type() == Statement::MEDIA)
Packit bfcc33
    { return SASS_MEMORY_NEW(Bubble, m->pstate(), m); }
Packit bfcc33
Packit bfcc33
    p_stack.push_back(m);
Packit bfcc33
Packit bfcc33
    Media_Block_Obj mm = SASS_MEMORY_NEW(Media_Block,
Packit bfcc33
                                      m->pstate(),
Packit bfcc33
                                      m->media_queries(),
Packit bfcc33
                                      operator()(m->block()));
Packit bfcc33
    mm->tabs(m->tabs());
Packit bfcc33
Packit bfcc33
    p_stack.pop_back();
Packit bfcc33
Packit bfcc33
    return debubble(mm->block(), mm);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(Supports_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    if (!m->block()->length())
Packit bfcc33
    { return m; }
Packit bfcc33
Packit bfcc33
    if (parent()->statement_type() == Statement::RULESET)
Packit bfcc33
    { return bubble(m); }
Packit bfcc33
Packit bfcc33
    p_stack.push_back(m);
Packit bfcc33
Packit bfcc33
    Supports_Block_Obj mm = SASS_MEMORY_NEW(Supports_Block,
Packit bfcc33
                                       m->pstate(),
Packit bfcc33
                                       m->condition(),
Packit bfcc33
                                       operator()(m->block()));
Packit bfcc33
    mm->tabs(m->tabs());
Packit bfcc33
Packit bfcc33
    p_stack.pop_back();
Packit bfcc33
Packit bfcc33
    return debubble(mm->block(), mm);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::operator()(At_Root_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    bool tmp = false;
Packit bfcc33
    for (size_t i = 0, L = p_stack.size(); i < L; ++i) {
Packit bfcc33
      Statement_Ptr s = p_stack[i];
Packit bfcc33
      tmp |= m->exclude_node(s);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    if (!tmp)
Packit bfcc33
    {
Packit bfcc33
      Block_Ptr bb = operator()(m->block());
Packit bfcc33
      for (size_t i = 0, L = bb->length(); i < L; ++i) {
Packit bfcc33
        // (bb->elements())[i]->tabs(m->tabs());
Packit bfcc33
        Statement_Obj stm = bb->at(i);
Packit bfcc33
        if (bubblable(stm)) stm->tabs(stm->tabs() + m->tabs());
Packit bfcc33
      }
Packit bfcc33
      if (bb->length() && bubblable(bb->last())) bb->last()->group_end(m->group_end());
Packit bfcc33
      return bb;
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    if (m->exclude_node(parent()))
Packit bfcc33
    {
Packit bfcc33
      return SASS_MEMORY_NEW(Bubble, m->pstate(), m);
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    return bubble(m);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::bubble(Directive_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    Block_Ptr bb = SASS_MEMORY_NEW(Block, this->parent()->pstate());
Packit bfcc33
    Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent()));
Packit bfcc33
    new_rule->block(bb);
Packit bfcc33
    new_rule->tabs(this->parent()->tabs());
Packit bfcc33
    new_rule->block()->concat(m->block());
Packit bfcc33
Packit bfcc33
    Block_Obj wrapper_block = SASS_MEMORY_NEW(Block, m->block() ? m->block()->pstate() : m->pstate());
Packit bfcc33
    wrapper_block->append(new_rule);
Packit bfcc33
    Directive_Obj mm = SASS_MEMORY_NEW(Directive,
Packit bfcc33
                                  m->pstate(),
Packit bfcc33
                                  m->keyword(),
Packit bfcc33
                                  m->selector(),
Packit bfcc33
                                  wrapper_block);
Packit bfcc33
    if (m->value()) mm->value(m->value());
Packit bfcc33
Packit bfcc33
    Bubble_Ptr bubble = SASS_MEMORY_NEW(Bubble, mm->pstate(), mm);
Packit bfcc33
    return bubble;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::bubble(At_Root_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    Block_Ptr bb = SASS_MEMORY_NEW(Block, this->parent()->pstate());
Packit bfcc33
    Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent()));
Packit bfcc33
    new_rule->block(bb);
Packit bfcc33
    new_rule->tabs(this->parent()->tabs());
Packit bfcc33
    new_rule->block()->concat(m->block());
Packit bfcc33
Packit bfcc33
    Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
Packit bfcc33
    wrapper_block->append(new_rule);
Packit bfcc33
    At_Root_Block_Ptr mm = SASS_MEMORY_NEW(At_Root_Block,
Packit bfcc33
                                        m->pstate(),
Packit bfcc33
                                        wrapper_block,
Packit bfcc33
                                        m->expression());
Packit bfcc33
    Bubble_Ptr bubble = SASS_MEMORY_NEW(Bubble, mm->pstate(), mm);
Packit bfcc33
    return bubble;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::bubble(Supports_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    Ruleset_Obj parent = Cast<Ruleset>(SASS_MEMORY_COPY(this->parent()));
Packit bfcc33
Packit bfcc33
    Block_Ptr bb = SASS_MEMORY_NEW(Block, parent->block()->pstate());
Packit bfcc33
    Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset,
Packit bfcc33
                                        parent->pstate(),
Packit bfcc33
                                        parent->selector(),
Packit bfcc33
                                        bb);
Packit bfcc33
    new_rule->tabs(parent->tabs());
Packit bfcc33
    new_rule->block()->concat(m->block());
Packit bfcc33
Packit bfcc33
    Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
Packit bfcc33
    wrapper_block->append(new_rule);
Packit bfcc33
    Supports_Block_Ptr mm = SASS_MEMORY_NEW(Supports_Block,
Packit bfcc33
                                       m->pstate(),
Packit bfcc33
                                       m->condition(),
Packit bfcc33
                                       wrapper_block);
Packit bfcc33
Packit bfcc33
    mm->tabs(m->tabs());
Packit bfcc33
Packit bfcc33
    Bubble_Ptr bubble = SASS_MEMORY_NEW(Bubble, mm->pstate(), mm);
Packit bfcc33
    return bubble;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::bubble(Media_Block_Ptr m)
Packit bfcc33
  {
Packit bfcc33
    Ruleset_Obj parent = Cast<Ruleset>(SASS_MEMORY_COPY(this->parent()));
Packit bfcc33
Packit bfcc33
    Block_Ptr bb = SASS_MEMORY_NEW(Block, parent->block()->pstate());
Packit bfcc33
    Ruleset_Ptr new_rule = SASS_MEMORY_NEW(Ruleset,
Packit bfcc33
                                        parent->pstate(),
Packit bfcc33
                                        parent->selector(),
Packit bfcc33
                                        bb);
Packit bfcc33
    new_rule->tabs(parent->tabs());
Packit bfcc33
    new_rule->block()->concat(m->block());
Packit bfcc33
Packit bfcc33
    Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
Packit bfcc33
    wrapper_block->append(new_rule);
Packit bfcc33
    Media_Block_Obj mm = SASS_MEMORY_NEW(Media_Block,
Packit bfcc33
                                      m->pstate(),
Packit bfcc33
                                      m->media_queries(),
Packit bfcc33
                                      wrapper_block);
Packit bfcc33
Packit bfcc33
    mm->tabs(m->tabs());
Packit bfcc33
Packit bfcc33
    return SASS_MEMORY_NEW(Bubble, mm->pstate(), mm);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  bool Cssize::bubblable(Statement_Ptr s)
Packit bfcc33
  {
Packit bfcc33
    return Cast<Ruleset>(s) || s->bubbles();
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Block_Ptr Cssize::flatten(Block_Ptr b)
Packit bfcc33
  {
Packit bfcc33
    Block_Ptr result = SASS_MEMORY_NEW(Block, b->pstate(), 0, b->is_root());
Packit bfcc33
    for (size_t i = 0, L = b->length(); i < L; ++i) {
Packit bfcc33
      Statement_Ptr ss = b->at(i);
Packit bfcc33
      if (Block_Ptr bb = Cast<Block>(ss)) {
Packit bfcc33
        Block_Obj bs = flatten(bb);
Packit bfcc33
        for (size_t j = 0, K = bs->length(); j < K; ++j) {
Packit bfcc33
          result->append(bs->at(j));
Packit bfcc33
        }
Packit bfcc33
      }
Packit bfcc33
      else {
Packit bfcc33
        result->append(ss);
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
    return result;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  std::vector<std::pair<bool, Block_Obj>> Cssize::slice_by_bubble(Block_Ptr b)
Packit bfcc33
  {
Packit bfcc33
    std::vector<std::pair<bool, Block_Obj>> results;
Packit bfcc33
Packit bfcc33
    for (size_t i = 0, L = b->length(); i < L; ++i) {
Packit bfcc33
      Statement_Obj value = b->at(i);
Packit bfcc33
      bool key = Cast<Bubble>(value) != NULL;
Packit bfcc33
Packit bfcc33
      if (!results.empty() && results.back().first == key)
Packit bfcc33
      {
Packit bfcc33
        Block_Obj wrapper_block = results.back().second;
Packit bfcc33
        wrapper_block->append(value);
Packit bfcc33
      }
Packit bfcc33
      else
Packit bfcc33
      {
Packit bfcc33
        Block_Ptr wrapper_block = SASS_MEMORY_NEW(Block, value->pstate());
Packit bfcc33
        wrapper_block->append(value);
Packit bfcc33
        results.push_back(std::make_pair(key, wrapper_block));
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
    return results;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Block_Ptr Cssize::debubble(Block_Ptr children, Statement_Ptr parent)
Packit bfcc33
  {
Packit bfcc33
    Has_Block_Obj previous_parent = 0;
Packit bfcc33
    std::vector<std::pair<bool, Block_Obj>> baz = slice_by_bubble(children);
Packit bfcc33
    Block_Obj result = SASS_MEMORY_NEW(Block, children->pstate());
Packit bfcc33
Packit bfcc33
    for (size_t i = 0, L = baz.size(); i < L; ++i) {
Packit bfcc33
      bool is_bubble = baz[i].first;
Packit bfcc33
      Block_Obj slice = baz[i].second;
Packit bfcc33
Packit bfcc33
      if (!is_bubble) {
Packit bfcc33
        if (!parent) {
Packit bfcc33
          result->append(slice);
Packit bfcc33
        }
Packit bfcc33
        else if (previous_parent) {
Packit bfcc33
          previous_parent->block()->concat(slice);
Packit bfcc33
        }
Packit bfcc33
        else {
Packit bfcc33
          previous_parent = Cast<Has_Block>(SASS_MEMORY_COPY(parent));
Packit bfcc33
          previous_parent->block(slice);
Packit bfcc33
          previous_parent->tabs(parent->tabs());
Packit bfcc33
Packit bfcc33
          result->append(previous_parent);
Packit bfcc33
        }
Packit bfcc33
        continue;
Packit bfcc33
      }
Packit bfcc33
Packit bfcc33
      for (size_t j = 0, K = slice->length(); j < K; ++j)
Packit bfcc33
      {
Packit bfcc33
        Statement_Ptr ss;
Packit bfcc33
        Statement_Obj stm = slice->at(j);
Packit bfcc33
        // this has to go now here (too bad)
Packit bfcc33
        Bubble_Obj node = Cast<Bubble>(stm);
Packit bfcc33
        Media_Block_Ptr m1 = NULL;
Packit bfcc33
        Media_Block_Ptr m2 = NULL;
Packit bfcc33
        if (parent) m1 = Cast<Media_Block>(parent);
Packit bfcc33
        if (node) m2 = Cast<Media_Block>(node->node());
Packit bfcc33
        if (!parent ||
Packit bfcc33
            parent->statement_type() != Statement::MEDIA ||
Packit bfcc33
            node->node()->statement_type() != Statement::MEDIA ||
Packit bfcc33
            (m1 && m2 && *m1->media_queries() == *m2->media_queries())
Packit bfcc33
          )
Packit bfcc33
        {
Packit bfcc33
          ss = node->node();
Packit bfcc33
        }
Packit bfcc33
        else
Packit bfcc33
        {
Packit bfcc33
          List_Obj mq = merge_media_queries(
Packit bfcc33
            Cast<Media_Block>(node->node()),
Packit bfcc33
            Cast<Media_Block>(parent)
Packit bfcc33
          );
Packit bfcc33
          if (!mq->length()) continue;
Packit bfcc33
          if (Media_Block* b = Cast<Media_Block>(node->node())) {
Packit bfcc33
            b->media_queries(mq);
Packit bfcc33
          }
Packit bfcc33
          ss = node->node();
Packit bfcc33
        }
Packit bfcc33
Packit bfcc33
        if (!ss) continue;
Packit bfcc33
Packit bfcc33
        ss->tabs(ss->tabs() + node->tabs());
Packit bfcc33
        ss->group_end(node->group_end());
Packit bfcc33
Packit bfcc33
        Block_Obj bb = SASS_MEMORY_NEW(Block,
Packit bfcc33
                                    children->pstate(),
Packit bfcc33
                                    children->length(),
Packit bfcc33
                                    children->is_root());
Packit bfcc33
        bb->append(ss->perform(this));
Packit bfcc33
Packit bfcc33
        Block_Obj wrapper_block = SASS_MEMORY_NEW(Block,
Packit bfcc33
                                              children->pstate(),
Packit bfcc33
                                              children->length(),
Packit bfcc33
                                              children->is_root());
Packit bfcc33
Packit bfcc33
        Block_Ptr wrapper = flatten(bb);
Packit bfcc33
        wrapper_block->append(wrapper);
Packit bfcc33
Packit bfcc33
        if (wrapper->length()) {
Packit bfcc33
          previous_parent = NULL;
Packit bfcc33
        }
Packit bfcc33
Packit bfcc33
        if (wrapper_block) {
Packit bfcc33
          result->append(wrapper_block);
Packit bfcc33
        }
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    return flatten(result);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  Statement_Ptr Cssize::fallback_impl(AST_Node_Ptr n)
Packit bfcc33
  {
Packit bfcc33
    return static_cast<Statement_Ptr>(n);
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  void Cssize::append_block(Block_Ptr b, Block_Ptr cur)
Packit bfcc33
  {
Packit bfcc33
    for (size_t i = 0, L = b->length(); i < L; ++i) {
Packit bfcc33
      Statement_Obj ith = b->at(i)->perform(this);
Packit bfcc33
      if (Block_Ptr bb = Cast<Block>(ith)) {
Packit bfcc33
        for (size_t j = 0, K = bb->length(); j < K; ++j) {
Packit bfcc33
          cur->append(bb->at(j));
Packit bfcc33
        }
Packit bfcc33
      }
Packit bfcc33
      else if (ith) {
Packit bfcc33
        cur->append(ith);
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
  List_Ptr Cssize::merge_media_queries(Media_Block_Ptr m1, Media_Block_Ptr m2)
Packit bfcc33
  {
Packit bfcc33
    List_Ptr qq = SASS_MEMORY_NEW(List,
Packit bfcc33
                               m1->media_queries()->pstate(),
Packit bfcc33
                               m1->media_queries()->length(),
Packit bfcc33
                               SASS_COMMA);
Packit bfcc33
Packit bfcc33
    for (size_t i = 0, L = m1->media_queries()->length(); i < L; i++) {
Packit bfcc33
      for (size_t j = 0, K = m2->media_queries()->length(); j < K; j++) {
Packit bfcc33
        Expression_Obj l1 = m1->media_queries()->at(i);
Packit bfcc33
        Expression_Obj l2 = m2->media_queries()->at(j);
Packit bfcc33
        Media_Query_Ptr mq1 = Cast<Media_Query>(l1);
Packit bfcc33
        Media_Query_Ptr mq2 = Cast<Media_Query>(l2);
Packit bfcc33
        Media_Query_Ptr mq = merge_media_query(mq1, mq2);
Packit bfcc33
        if (mq) qq->append(mq);
Packit bfcc33
      }
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    return qq;
Packit bfcc33
  }
Packit bfcc33
Packit bfcc33
Packit bfcc33
  Media_Query_Ptr Cssize::merge_media_query(Media_Query_Ptr mq1, Media_Query_Ptr mq2)
Packit bfcc33
  {
Packit bfcc33
Packit bfcc33
    std::string type;
Packit bfcc33
    std::string mod;
Packit bfcc33
Packit bfcc33
    std::string m1 = std::string(mq1->is_restricted() ? "only" : mq1->is_negated() ? "not" : "");
Packit bfcc33
    std::string t1 = mq1->media_type() ? mq1->media_type()->to_string(ctx.c_options) : "";
Packit bfcc33
    std::string m2 = std::string(mq2->is_restricted() ? "only" : mq1->is_negated() ? "not" : "");
Packit bfcc33
    std::string t2 = mq2->media_type() ? mq2->media_type()->to_string(ctx.c_options) : "";
Packit bfcc33
Packit bfcc33
Packit bfcc33
    if (t1.empty()) t1 = t2;
Packit bfcc33
    if (t2.empty()) t2 = t1;
Packit bfcc33
Packit bfcc33
    if ((m1 == "not") ^ (m2 == "not")) {
Packit bfcc33
      if (t1 == t2) {
Packit bfcc33
        return 0;
Packit bfcc33
      }
Packit bfcc33
      type = m1 == "not" ? t2 : t1;
Packit bfcc33
      mod = m1 == "not" ? m2 : m1;
Packit bfcc33
    }
Packit bfcc33
    else if (m1 == "not" && m2 == "not") {
Packit bfcc33
      if (t1 != t2) {
Packit bfcc33
        return 0;
Packit bfcc33
      }
Packit bfcc33
      type = t1;
Packit bfcc33
      mod = "not";
Packit bfcc33
    }
Packit bfcc33
    else if (t1 != t2) {
Packit bfcc33
      return 0;
Packit bfcc33
    } else {
Packit bfcc33
      type = t1;
Packit bfcc33
      mod = m1.empty() ? m2 : m1;
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    Media_Query_Ptr mm = SASS_MEMORY_NEW(Media_Query,
Packit bfcc33
                                         mq1->pstate(),
Packit bfcc33
                                         0,
Packit bfcc33
                                         mq1->length() + mq2->length(),
Packit bfcc33
                                         mod == "not",
Packit bfcc33
                                         mod == "only");
Packit bfcc33
Packit bfcc33
    if (!type.empty()) {
Packit bfcc33
      mm->media_type(SASS_MEMORY_NEW(String_Quoted, mq1->pstate(), type));
Packit bfcc33
    }
Packit bfcc33
Packit bfcc33
    mm->concat(mq2);
Packit bfcc33
    mm->concat(mq1);
Packit bfcc33
Packit bfcc33
    return mm;
Packit bfcc33
  }
Packit bfcc33
}