Example #1
0
// Resolve build-in operations for non-map types, e.g.: 'str'.len()
packToken TypeSpecificFunction(const packToken& p_left, const packToken& p_right, evaluationData* data) {
  if (p_left->type == MAP) throw Operation::Reject();

  TokenMap& attr_map = calculator::type_attribute_map()[p_left->type];
  std::string& key = p_right.asString();

  packToken* attr = attr_map.find(key);
  if (attr) {
    // Note: If attr is a function, it will receive have
    // scope["this"] == source, so it can make changes on this object.
    // Or just read some information for example: its length.
    return RefToken(key, (*attr), p_left);
  } else {
    throw undefined_operation(data->op, p_left, p_right);
  }
}
Example #2
0
TokenBase* calculator::calculate(const TokenQueue_t& rpn, TokenMap scope,
                                 const opMap_t& opMap) {
  evaluationData data(rpn, scope, opMap);

  // Evaluate the expression in RPN form.
  std::stack<TokenBase*> evaluation;
  while (!data.rpn.empty()) {
    TokenBase* base = data.rpn.front()->clone();
    data.rpn.pop();

    // Operator:
    if (base->type == OP) {
      data.op = static_cast<Token<std::string>*>(base)->val;
      delete base;

      /* * * * * Resolve operands Values and References: * * * * */

      if (evaluation.size() < 2) {
        cleanStack(evaluation);
        throw std::domain_error("Invalid equation.");
      }
      TokenBase* b_right = evaluation.top(); evaluation.pop();
      TokenBase* b_left  = evaluation.top(); evaluation.pop();

      if (b_right->type == VAR) {
        std::string var_name = static_cast<Token<std::string>*>(b_right)->val;
        delete b_right;
        delete resolve_reference(b_left);
        cleanStack(evaluation);
        throw std::domain_error("Unable to find the variable '" + var_name + "'.");
      } else {
        b_right = resolve_reference(b_right, &data.scope);
      }

      packToken r_left;
      packToken m_left;
      if (b_left->type & REF) {
        RefToken* left = static_cast<RefToken*>(b_left);
        r_left = left->key;
        m_left = left->source;
        b_left = resolve_reference(left, &data.scope);
      } else if (b_left->type == VAR) {
        r_left = static_cast<Token<std::string>*>(b_left)->val;
      }

      /* * * * * Resolve Asign Operation * * * * */

      if (!data.op.compare("=")) {
        delete b_left;

        // If the left operand has a variable name:
        if (r_left->type == STR) {
          if (m_left->type == MAP) {
            TokenMap& map = m_left.asMap();
            std::string& key = r_left.asString();
            map[key] = packToken(b_right->clone());
          } else {
            TokenMap* map = data.scope.findMap(r_left.asString());
            if (!map || *map == TokenMap::default_global()) {
              // Assign on the local scope.
              // The user should not be able to implicitly overwrite
              // variables he did not declare, since it's error prone.
              data.scope[r_left.asString()] = packToken(b_right->clone());
            } else {
              (*map)[r_left.asString()] = packToken(b_right->clone());
            }
          }

          evaluation.push(b_right);
        // If the left operand has an index number:
        } else if (r_left->type & NUM) {
          if (m_left->type == LIST) {
            TokenList& list = m_left.asList();
            size_t index = r_left.asInt();
            list[index] = packToken(b_right->clone());
          } else {
            delete b_right;
            cleanStack(evaluation);
            throw std::domain_error("Left operand of assignment is not a list!");
          }

          evaluation.push(b_right);
        } else {
          packToken p_right(b_right->clone());
          delete b_right;

          cleanStack(evaluation);
          throw undefined_operation(data.op, r_left, p_right);
        }
      } else if (b_left->type == FUNC && data.op == "()") {
        Function* f_left = static_cast<Function*>(b_left);

        if (!data.op.compare("()")) {
          // Collect the parameter tuple:
          Tuple right;
          if (b_right->type == TUPLE) {
            right = *static_cast<Tuple*>(b_right);
          } else {
            right = Tuple(b_right);
          }
          delete b_right;

          packToken _this;
          if (m_left->type != NONE) {
            _this = m_left;
          } else {
            _this = data.scope;
          }

          // Execute the function:
          packToken ret;
          try {
            ret = Function::call(_this, f_left, &right, data.scope);
          } catch (...) {
            cleanStack(evaluation);
            delete f_left;
            throw;
          }

          delete f_left;

          evaluation.push(ret->clone());
        } else {
          packToken p_right(b_right->clone());
          packToken p_left(b_left->clone());
          delete b_right;

          cleanStack(evaluation);
          throw undefined_operation(data.op, p_left, p_right);
        }
      } else {
        data.opID = Operation::build_mask(b_left->type, b_right->type);
        packToken p_left(b_left);
        packToken p_right(b_right);
        TokenBase* result = 0;

        try {
          // Resolve the operation:
          result = exec_operation(p_left, p_right, &data, data.op);
          if (!result) {
            result = exec_operation(p_left, p_right, &data, ANY_OP);
          }
        } catch (...) {
          cleanStack(evaluation);
          throw;
        }

        if (result) {
          evaluation.push(result);
        } else {
          cleanStack(evaluation);
          throw undefined_operation(data.op, p_left, p_right);
        }
      }
    } else if (base->type == VAR) {  // Variable
      packToken* value = NULL;
      std::string key = static_cast<Token<std::string>*>(base)->val;

      value = data.scope.find(key);

      if (value) {
        TokenBase* copy = (*value)->clone();
        evaluation.push(new RefToken(key, copy));
        delete base;
      } else {
        evaluation.push(base);
      }
    } else {
      evaluation.push(base);
    }
  }

  return evaluation.top();
}
Example #3
0
File: seen.c Project: mpw/p2
void
have_all_operations_been_seen (void)
{
  char missing_list[MAX_IDENT_LEN * MAX_NUM_OPS];
  char unneeded_list[MAX_IDENT_LEN * MAX_NUM_OPS];
  SPECIAL_OP op;
  int q;
  
  missing_list[0] = '\0';
  unneeded_list[0] = '\0';

  FOREACH_OPERATION_INDEX(q) {
    op = op_tab[q].op_num;
    if (op_exists_in_realm(op, layer_realm) && !seen[op]) {
      if (op == DDLHINT_OP) { 
        if (!annotations) { 
          /* The "no annotation" remark is enough to call gen_ddl */
          gen_ddl();
        }
        else { 
          /* There's no other notion of default for this procedure */
          strcat(missing_list, op_tab[q].name);
          strcat(missing_list, " ");
        }
        continue;
      }

      if (retrieval_op(op) && !retrieval) { 
        /* Okay.  We don't expect them here (BJG). */
        continue;
      }

      if (!call_below(op, 0)) { 
        /* Then what happens is that this is the last layer that the 
           operation can exist in (since it can't be called below). 
           We generate a warning & some notion of a default. 
           The default depends on if the operation can be an expression
           or not. (BJG) */ 

        out(op_tab[q].proc, layer_name);
        if (op == REF_OP || op == IREF_OP) { 
          out("{ NODE *P2_r, *P2_result = NULL;");
          do_action((op == REF_OP) ? "ref" : "iref", "cursor0", "field");
          out("if (!P2_result)"
              "P2_result = terminal_string1(\" \");"
              "return(P2_result); }");
        }
        else { 
          out("{ return(");
          undefined_operation(op_tab[q].name, op);
          out("); }");
        }
        seen[op] = TRUE;
        continue;
      }

      if (retrieval_op(op)) { 
        switch (retrieval) { 
        case 0:
          /* NEVER */
          /* ok. don't need retrieval ops */
          break;
        case 1:
        case 2:
          /* SOMETIMES */
          /* ALWAYS */
          warning(3, "retrieval operation %s not defined for layer %s",
                  op_tab[q].name, layer_name);
          break;
        default:
          error("Error in retrieval value");
        }
        continue;
      }
    }
    if (!(op_exists_in_realm(op, layer_realm)) && seen[op]) {
      strcat(unneeded_list, op_tab[q].name);
      strcat(unneeded_list, "  ");
    }
  }

  if (missing_list[0] != '\0')
    error("missing operations: %s", missing_list);
  if (unneeded_list[0] != '\0')
    error("unneeded operations: %s", unneeded_list);
}