#include "expressions.h"

namespace xreate{

Expression
getVariantData(const Expression &variantE, ExpandedType variantT){
  Expression result(Operator::LIST, {});
  TypeAnnotation variantDataT(variantT->__operands.at(variantE.getValueDouble()));
  if(!variantDataT.isValid()) return Expression();

  assert(variantDataT.__operator == TypeOperator::RECORD);
  result.operands = variantE.operands;
  result.bindings = variantDataT.fields;
  result.type = variantDataT;
  return result;
}

ListDictionary
reprListAsDict(const Expression &e){
  ListDictionary result;
  assert(e.__state == Expression::COMPOUND);

  switch(e.op){
    case Operator::LIST:{
      Expression keyE;
      int lastPos = 0;
      for(size_t i = 0; i < e.operands.size(); ++i){
        const Expression &valueE = e.operands.at(i);
        const std::string &keyS = e.bindings.at(i);

        if(keyS.empty()){
          keyE = Expression(Atom<Number_t>(lastPos++));
        } else{
          keyE = Expression(Atom<String_t>(std::string(keyS)));
        }

        result.emplace(keyE, valueE);
      }
      break;
    }

    case Operator::LIST_INDEX:{
      auto opI = e.operands.cbegin();
      while(opI != e.operands.cend()){
        const Expression &keysListE = *(opI++);
        const Expression &valueE = *(opI++);
        assert(keysListE.operands.size() == 1);

        result.emplace(keysListE.operands.at(0), valueE);
      }
      break;
    }
    default:
      assert(false);
  }

  return result;
}

std::list<Expression>
getAnnotations(const Expression& e){
  std::list<Expression> result;
  for(const auto& tag: e.tags){result.push_back(tag.second);}

  return result;
}
}