END_TEST




START_TEST (test_element_selector)
{
  const char* s = wrapMathML
  (
    "  <apply>"
    "    <selector/>"
    "    <ci> A </ci>"
    "    <ci> i </ci>"
    "  </apply>"
  );



  N = readMathMLFromStringWithNamespaces(s, NS);

  fail_unless( N != NULL );
  fail_unless( N->getType() == AST_ORIGINATES_IN_PACKAGE);
  fail_unless( N->getExtendedType() == AST_LINEAR_ALGEBRA_SELECTOR);
  fail_unless( N->getNumChildren() == 2);
  fail_unless( N->getPackageName() == "arrays");

  ASTNode * child = N->getChild(0);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_NAME);
  fail_unless( child->getExtendedType() == AST_NAME);
  fail_unless( strcmp(child->getName(), "A") == 0);
  fail_unless( child->getNumChildren() == 0);
  fail_unless( child->getPackageName() == "core");

  child = N->getChild(1);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_NAME);
  fail_unless( child->getExtendedType() == AST_NAME);
  fail_unless( strcmp(child->getName(), "i") == 0);
  fail_unless( child->getNumChildren() == 0);

  ArraysASTPlugin* plugin = static_cast<ArraysASTPlugin*>(N->getPlugin("arrays"));
  
  fail_unless(plugin != NULL);
  fail_unless(plugin->getASTType() == AST_LINEAR_ALGEBRA_SELECTOR);

}
Example #2
0
/*
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
PieceBooleanMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_FUNCTION_PIECEWISE:

      checkPiece(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
Example #3
0
/**
 * Constructor that makes a ConverterASTNode from an ASTNode.
 */
ConverterASTNode::ConverterASTNode(const ASTNode &templ): ASTNode(templ.getType())
{
  if (this->getType() == AST_RATIONAL)
    {
      this->mDenominator = templ.getDenominator();
      this->mInteger = templ.getNumerator();
    }
  else if (this->getType() == AST_REAL || this->getType() == AST_REAL_E)
    {
      this->mExponent = templ.getExponent();
      this->mReal = templ.getMantissa();
    }
  if (this->getType() == AST_PLUS || this->getType() == AST_MINUS || this->getType() == AST_TIMES || this->getType() == AST_DIVIDE || this->getType() == AST_POWER)
    {
      this->mChar = templ.getCharacter();
    }
  else if (this->getType() == AST_INTEGER)
    {
      this->mInteger = templ.getInteger();
    }
  if ((!this->isOperator()) && (!this->isNumber()))
    {
      this->setName(templ.getName());
    }
  unsigned int counter;
  for (counter = 0; counter < templ.getNumChildren(); counter++)
    {
      this->addChild(new ConverterASTNode(*templ.getChild(counter)));
    }
};
Example #4
0
void addChildren(Association* association, const ASTNode* node, const ASTNode *current)
{

  if (node->getType() == AST_TIMES || node->getType() == AST_PLUS)
  {
  for (unsigned int i = 0; i < node->getNumChildren(); ++i)
  {
    ASTNode* astChild = node->getChild(i);
    if (astChild->getType() == current->getType())
    {
      addChildren(association, astChild, node);
      continue;
    }
    
    Association* child = toAssociation(astChild);
    if (child == NULL)
      continue;
    association->addAssociation(*child);
    delete child;
  }
  }
  else{
    Association* child = toAssociation(node);
    if (child == NULL)
      return;
    association->addAssociation(*child);
    
  }

  
}
unsigned int
ASTPiecewiseFunctionNode::getNumChildren() const
{
  /* HACK TO REPLICATE OLD AST */
  unsigned int numChildren = 0;
  
  for (unsigned int i = 0; i < getNumPiece(); i++)
  {
    ASTBase * base = ASTFunctionBase::getChild(i);
    ASTNode * piece = dynamic_cast<ASTNode*>(base);

    if (piece != NULL && piece->getType() == AST_CONSTRUCTOR_PIECE)
    {
      numChildren += piece->getNumChildren();
    }
    else
    {
      // fail safe - a piece should have 2 children
      numChildren += 2;
    }
  }
  if (getHasOtherwise() == true)
  {
    numChildren++;
  }

  return numChildren;
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
EqualityArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  ASTNodeType_t type = node.getType();

  /* check arguments of eq or neq */
  switch (type) 
  {
    case AST_RELATIONAL_EQ:
    case AST_RELATIONAL_NEQ:

      checkArgs(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/**
  * Checks that the units of the result of the assignment rule
  * are consistent with variable being assigned
  *
  * If an inconsistent variable is found, an error message is logged.
  */
void
PowerUnitsCheck::checkUnits (const Model& m, const ASTNode& node, const SBase & sb,
                                 bool inKL, int reactNo)
{
  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    //case AST_DIVIDE:
    //  checkForPowersBeingDivided(m, node, sb);
    //  break;
    case AST_POWER:
    case AST_FUNCTION_POWER:

      checkUnitsFromPower(m, node, sb, inKL, reactNo);
      break;

    case AST_FUNCTION:

      checkFunction(m, node, sb, inKL, reactNo);
      break;

    default:

      checkChildren(m, node, sb, inKL, reactNo);
      break;

  }
}
/*
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
LambdaMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  /* should not be here but why not catch it rather than crash*/
  if (&(node) == NULL)
  {
    return;
  }

  ASTNodeType_t type = node.getType();
    
  /* a lambda function outside a functionDefinition is a conflict */
  switch (type) 
  {
    case AST_LAMBDA:
    
      logMathConflict(node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/*
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
LogicalArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_LOGICAL_AND:
    case AST_LOGICAL_NOT:
    case AST_LOGICAL_OR:
    case AST_LOGICAL_XOR:

      checkMathFromLogical(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/*
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
LogicalArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  /* should not be here but why not catch it rather than crash*/
  if (&(node) == NULL)
  {
    return;
  }

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_LOGICAL_AND:
    case AST_LOGICAL_NOT:
    case AST_LOGICAL_OR:
    case AST_LOGICAL_XOR:

      checkMathFromLogical(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
void TestASTNode::testConstructor()
{
	ASTNode* node = new ASTNode("value", PROGRAM, 1);

	CPPUNIT_ASSERT("value" == node->getName());
	CPPUNIT_ASSERT_EQUAL(PROGRAM, node->getType());
	CPPUNIT_ASSERT_EQUAL(1, node->getStatementNumber());
}
Example #12
0
std::string AST::getCalledProcedure(int stmtNum)
{
    ASTNode* node = getStatementNode(stmtNum);

    if (node->getType() == CALL) {
        return node->getName();
    } else {
        return "";
    }
}
Example #13
0
/**
 * In MathML, &lt;plus/> and &lt;times/> are n-ary operators but the infix
 * FormulaParser represents them as binary operators.  To ensure a
 * consistent AST representation, this function is part of the n-ary to
 * binary reduction process.
 */
static void
reduceBinary (ASTNode& node)
{
  if (node.getNumChildren() == 2)
  {
    ASTNode* op = new ASTNode( node.getType() );
    node.swapChildren(op);
    node.prependChild(op);
  }
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
ValidCnUnitsValue::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  /* should not be here but why not catch it rather than crash*/
  if (&(node) == NULL)
  {
    return;
  }

  if (node.isNumber())
  {
    checkValidUnits(m, node, sb);
  }
  else
  {
    ASTNodeType_t type = node.getType();

    switch (type) 
    {
      case AST_FUNCTION:

        checkFunction(m, node, sb);
        break;

      default:

        checkChildren(m, node, sb);
        break;

    }
  }

  //switch (type) 
  //{
  //  case AST_LOGICAL_AND:
  //  case AST_LOGICAL_NOT:
  //  case AST_LOGICAL_OR:
  //  case AST_LOGICAL_XOR:

  //    checkMathFromLogical(m, node, sb);
  //    break;


  //  case AST_FUNCTION:

  //    checkFunction(m, node, sb);
  //    break;

  //  default:

  //    checkChildren(m, node, sb);
  //    break;

  //}
}
Example #15
0
/**
 * Ensures the given ASTNode has the appropriate number of arguments.  If
 * arguments are missing, appropriate defaults (per the MathML 2.0
 * specification) are added:
 *
 *   log (x) -> log (10, x)
 *   root(x) -> root( 2, x)
 */
static void
checkFunctionArgs (ASTNode& node)
{
  if (node.getNumChildren() == 1)
  {
    if (node.getType() == AST_FUNCTION_LOG)
    {
      ASTNode* child = new ASTNode;
      child->setValue(10);

      node.prependChild(child);
    }
    else if (node.getType() == AST_FUNCTION_ROOT)
    {
      ASTNode* child = new ASTNode;
      child->setValue(2);

      node.prependChild(child);
    }
  }
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
ValidCnUnitsValue::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{

  if (node.isNumber())
  {
    checkValidUnits(m, node, sb);
  }
  else
  {
    ASTNodeType_t type = node.getType();

    switch (type) 
    {
      case AST_FUNCTION:

        checkFunction(m, node, sb);
        break;

      default:

        checkChildren(m, node, sb);
        break;

    }
  }

  //switch (type) 
  //{
  //  case AST_LOGICAL_AND:
  //  case AST_LOGICAL_NOT:
  //  case AST_LOGICAL_OR:
  //  case AST_LOGICAL_XOR:

  //    checkMathFromLogical(m, node, sb);
  //    break;


  //  case AST_FUNCTION:

  //    checkFunction(m, node, sb);
  //    break;

  //  default:

  //    checkChildren(m, node, sb);
  //    break;

  //}
}
Example #17
0
ASTNode *XQContentSequence::staticTypingImpl(StaticContext *context)
{
    _src.clear();

    _src.copy(expr_->getStaticAnalysis());

    if(!expr_->getStaticAnalysis().getStaticType().containsType(StaticType::DOCUMENT_TYPE|StaticType::ANY_ATOMIC_TYPE)) {
        ASTNode *pChild = expr_;

        // Not needed if the wrapped expression is a DOM_CONSTRUCTOR
        if(pChild->getType() == ASTNode::DOM_CONSTRUCTOR ||
                (pChild->getType() == ASTNode::NAMESPACE_BINDING &&
                 ((XQNamespaceBinding*)pChild)->getExpression()->getType() == ASTNode::DOM_CONSTRUCTOR)) {
            return expr_;
        }
    }

    _src.getStaticType().substitute(StaticType::ANY_ATOMIC_TYPE, StaticType::TEXT_TYPE);
    _src.getStaticType().substitute(StaticType::DOCUMENT_TYPE, StaticType(StaticType::ELEMENT_TYPE | StaticType::TEXT_TYPE | StaticType::PI_TYPE |
                                    StaticType::COMMENT_TYPE, 0, StaticType::UNLIMITED));

    _src.creative(true);
    return this;
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
NumericReturnMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  //SBMLTypeCode_t type = sb.getTypeCode();
  int type = sb.getTypeCode();
  
  /* HACK: if the math is a lambda - this is invalid
   * and will be caught by constraint 2006
   * dont want to check it here as it will also fire this
   */
  if (!(node.getType() == AST_LAMBDA))
  {
    switch (type) 
    {
      case SBML_KINETIC_LAW:
      case SBML_INITIAL_ASSIGNMENT:
      case SBML_ASSIGNMENT_RULE:
      case SBML_RATE_RULE:
      case SBML_ALGEBRAIC_RULE:
      case SBML_SPECIES_CONCENTRATION_RULE:
      case SBML_COMPARTMENT_VOLUME_RULE:
      case SBML_PARAMETER_RULE:
      case SBML_EVENT_ASSIGNMENT:
      case SBML_SPECIES_REFERENCE:

        if (!returnsNumeric(m, &node))
        {
          logMathConflict(node, sb);
        }
        break;

      case SBML_EVENT:

        /* only want to check delay since trigger should return boolean */
        if (!mIsTrigger && !returnsNumeric(m , &node))
        {
          logMathConflict(node, sb);
        }
        break;

      default:

        break;

    }
  }
}
/*
  * Checks that the units of the result of the assignment rule
  * are consistent with variable being assigned
  *
  * If an inconsistent variable is found, an error message is logged.
  */
void
ArgumentsUnitsCheck::checkUnits (const Model& m, const ASTNode& node, const SBase & sb,
                                 bool inKL, int reactNo)
{
  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    /* functions that act on same units */
    case AST_PLUS:
    case AST_MINUS:
    case AST_FUNCTION_ABS:
    case AST_FUNCTION_CEILING:
    case AST_FUNCTION_FLOOR:
    case AST_RELATIONAL_EQ:
    case AST_RELATIONAL_GEQ:
    case AST_RELATIONAL_GT:
    case AST_RELATIONAL_LEQ:
    case AST_RELATIONAL_LT:
    case AST_RELATIONAL_NEQ:
  
      checkSameUnitsAsArgs(m, node, sb, inKL, reactNo);
      break;

    case AST_FUNCTION_DELAY:

      checkUnitsFromDelay(m, node, sb, inKL, reactNo);
      break;

    case AST_FUNCTION_PIECEWISE:
      
      checkUnitsFromPiecewise(m, node, sb, inKL, reactNo);
      break;

    case AST_FUNCTION:

      checkFunction(m, node, sb, inKL, reactNo);
      break;

    default:

      checkChildren(m, node, sb, inKL, reactNo);
      break;

  }
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
FunctionNoArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_FUNCTION:

      checkNumArgs(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
LambdaMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  ASTNodeType_t type = node.getType();
    
  /* a lambda function outside a functionDefinition is a conflict */
  switch (type) 
  {
    case AST_LAMBDA:
    
      logMathConflict(node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/**
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
CiElementMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  ASTNodeType_t type = node.getType();
    
  /* if the node is a <ci> element it will have type AST_NAME
   * check that this name is an appropriate component of the model */
  switch (type) 
  {
    case AST_NAME:

      checkCiElement(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
/**
 * Checks that all variables referenced in FunctionDefinition bodies are
 * bound variables (function arguments).
 */
void
FunctionDefinitionVars::check_ (const Model& m, const FunctionDefinition& fd)
{
  if ( fd.getLevel() == 1         ) return;
  if ( !fd.isSetMath()            ) return;
  if ( fd.getBody()  == NULL      ) return;
  if (  fd.getNumArguments() == 0 ) return;


  List* variables = fd.getBody()->getListOfNodes( ASTNode_isName );


  for (unsigned int n = 0; n < variables->getSize(); ++n)
  {
    ASTNode* node = static_cast<ASTNode*>( variables->get(n) );
    string   name = node->getName() ? node->getName() : "";

    if ( fd.getArgument(name) == NULL ) 
    {
      /* if this is the csymbol time - technically it is allowed 
       * in L2v1 and L2v2
       */
      if (node->getType() == AST_NAME_TIME)
      {
        if (fd.getLevel() > 2
          || (fd.getLevel() == 2 && fd.getVersion() > 2))
        {
          logUndefined(fd, name);
        }
      }
      else
      {
        logUndefined(fd, name);
      }
    }
  }
  
  delete variables;
}
Example #24
0
pair<string, list<string> >
MMOMath::_generateAlgebraic (pair<list<string>, ASTNode*> function,
			     list<string> args, ASTNode *node)
{
  ASTNode *repNode = new ASTNode (*function.second);
  _processNode (repNode);
  list<string>::iterator defArgs = function.first.begin ();
  list<string> variables;
  for (list<string>::iterator it = args.begin (); it != args.end (); it++)
    {
      repNode->renameSIdRefs (*defArgs, *it);
      defArgs++;
    }
  string ret = MMOUtils::getInstance ()->getExp (repNode);
  _getVariables (repNode, &variables);
  int childs = node->getNumChildren (), i;
  for (i = 0; i < childs; i++)
    {
      node->removeChild (0);
    }
  if (_type == MATH_ZERO_CROSSING)
    {
      node->setType (repNode->getType ());
      childs = repNode->getNumChildren ();
      for (i = 0; i < childs; i++)
	{
	  node->addChild (new ASTNode (*repNode->getChild (i)));
	}
    }
  else
    {
      node->setType (AST_NAME);
      node->setName (ret.c_str ());
      node->setId ("REPLACED_FUNCTION");
    }
  delete repNode;
  return (pair<string, list<string> > (ret, variables));
}
/*
  * Checks the MathML of the ASTnode 
  * is appropriate for the function being performed
  *
  * If an inconsistency is found, an error message is logged.
  */
void
PieceBooleanMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  // does not apply in L3V2 for general consistency checking
  // BUT we want to use it for telling a converter that this occurs in L3V2
  if (this->mValidator.getCategory() == LIBSBML_CAT_MATHML_CONSISTENCY)
  {
    if (m.getLevel() == 3 && m.getVersion() > 1) return;
  }
  else
  {
    if (m.getLevel() != 3) return;
    else if (m.getVersion() == 1) return;
  }

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_FUNCTION_PIECEWISE:

      checkPiece(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
bool
ASTNaryFunctionNode::isSqrt() const
{
  bool valid = false;

  if (getType() == AST_FUNCTION_ROOT)
  {
    // a sqrt can have either one child that is not the degree qualifier
    // or two where the first is the degree of 2
    if (getNumChildren() == 1)
    {
      /* HACK to replicate OLD AST whic says a sqrt must have two children*/
      valid = false;
      //ASTBase * base1 = getChild(0);
      //if (base1->isQualifier() == false)
      //{
      //  valid = true;
      //}
    }
    else if (getNumChildren() == 2)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      ASTFunction* fun = dynamic_cast<ASTFunction*>(base1);
      if (fun != NULL)
      {
        if (fun->getType() == AST_QUALIFIER_DEGREE 
          && fun->getNumChildren() == 1)
        {
          ASTBase *base2 = fun->getChild(0);
          if (base2->getType() == AST_INTEGER)
          {
            ASTNumber *child = static_cast<ASTNumber*>(base2);
            if (child->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
      }
      else
      {
        // here we are working the ASTNode so the casting
        // is more difficult

        ASTNode* newAST = dynamic_cast<ASTNode*>(base1);
        if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE
          && newAST->getNumChildren() == 1)
        {
          ASTNode* newAST1 = newAST->getChild(0);
          if (newAST1->getType() == AST_INTEGER)
          {
            if (newAST1->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
        else
        {
          if (newAST != NULL && newAST->getType() == AST_INTEGER)
          {
            if (newAST->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
      }
    }
  }

  return valid;
}
bool
ASTNaryFunctionNode::isLog10() const
{
  bool valid = false;

  if (getType() == AST_FUNCTION_LOG)
  {
    // a log can have either one child that is not the logbase qualifier
    // or two where the first is the logbase of 10
    if (getNumChildren() == 1)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      if (base1->isQualifier() == false)
      {
        valid = true;
      }
    }
    else if (getNumChildren() == 2)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      ASTFunction* fun = dynamic_cast<ASTFunction*>(base1);
      if (fun != NULL)
      {
        if (fun->getType() == AST_QUALIFIER_LOGBASE
          && fun->getNumChildren() == 1)
        {
          ASTBase *base2 = fun->getChild(0);
          if (base2->getType() == AST_INTEGER)
          {
            ASTNumber *child = static_cast<ASTNumber*>(base2);
            if (child->getInteger() == 10)
            {
              valid = true;
            }
          }
        }
      }
      else
      {
        // here we are working the ASTNode so the casting
        // is more difficult

        ASTNode* newAST = dynamic_cast<ASTNode*>(base1);
        if (newAST != NULL && newAST->getType() == AST_QUALIFIER_LOGBASE
          && newAST->getNumChildren() == 1 )
        {
          ASTNode* newAST1 = newAST->getChild(0);
          if (newAST1->getType() == AST_INTEGER)
          {
            if (newAST1->getInteger() == 10)
            {
              valid = true;
            }
          }
        }
        else
        {
          if (newAST != NULL && newAST->getType() == AST_INTEGER)
          {
            if (newAST->getInteger() == 10)
            {
              valid = true;
            }
          }
        }

      }
    }
  }

  return valid;
}
CK_CPPSTART


START_TEST (test_element_vector)
{
  const char* s = wrapMathML
  (
    "<vector>"
    "  <apply>"
    "    <cos/>"
    "    <cn type=\"integer\"> 5 </cn>"
    "  </apply>"
    "  <ci> y </ci>"
    "</vector>\n"
  );



  N = readMathMLFromStringWithNamespaces(s, NS);

  fail_unless( N != NULL );
  fail_unless( N->getType() == AST_ORIGINATES_IN_PACKAGE);
  fail_unless( N->getExtendedType() == AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR);
  fail_unless( N->getNumChildren() == 2);
  fail_unless( N->getPackageName() == "arrays");

  ASTNode * child = N->getChild(0);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_FUNCTION_COS);
  fail_unless( child->getExtendedType() == AST_FUNCTION_COS);
  fail_unless( child->getNumChildren() == 1);
  fail_unless( child->getPackageName() == "core");

  ASTNode *c1 = child->getChild(0);

  fail_unless( c1 != NULL );
  fail_unless( c1->getType() == AST_INTEGER);
  fail_unless( c1->getExtendedType() == AST_INTEGER);
  fail_unless( c1->getNumChildren() == 0);
  fail_unless( c1->getInteger() == 5);

  child = N->getChild(1);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_NAME);
  fail_unless( child->getExtendedType() == AST_NAME);
  fail_unless( strcmp(child->getName(), "y") == 0);
  fail_unless( child->getNumChildren() == 0);


  ArraysASTPlugin* plugin = static_cast<ArraysASTPlugin*>(N->getPlugin("arrays"));
  
  fail_unless(plugin != NULL);
  fail_unless(plugin->getASTType() == AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR);


  plugin = static_cast<ArraysASTPlugin*>(child->getPlugin("arrays"));
  
  fail_unless(plugin != NULL);
  fail_unless(plugin->getASTType() == AST_ARRAYS_UNKNOWN);

}
END_TEST




START_TEST (test_element_matrix)
{
  const char* s = wrapMathML
  (
    "<matrix>"
    "<matrixrow>"
    "<apply>"
    "<cos/>"
    "<cn type=\"integer\"> 5 </cn>"
    "</apply>"
    "<ci> y </ci>"
    "</matrixrow>"
    "<matrixrow>"
    "<cn type=\"integer\"> 2 </cn>"
    "<apply>"
    "<cos/>"
    "<cn type=\"integer\"> 5 </cn>"
    "</apply>"
    "</matrixrow>"
    "</matrix>\n"
  );



  N = readMathMLFromStringWithNamespaces(s, NS);

  fail_unless( N != NULL );
  fail_unless( N->getType() == AST_ORIGINATES_IN_PACKAGE);
  fail_unless( N->getExtendedType() == AST_LINEAR_ALGEBRA_MATRIX_CONSTRUCTOR);
  fail_unless( N->getNumChildren() == 2);
  fail_unless( N->getPackageName() == "arrays");

  ASTNode * child = N->getChild(0);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_ORIGINATES_IN_PACKAGE);
  fail_unless( child->getExtendedType() == AST_LINEAR_ALGEBRA_MATRIXROW_CONSTRUCTOR);
  fail_unless( child->getNumChildren() == 2);
  fail_unless( child->getPackageName() == "arrays");

  ASTNode *c1 = child->getChild(0);

  fail_unless( c1 != NULL );
  fail_unless( c1->getType() == AST_FUNCTION_COS);
  fail_unless( c1->getExtendedType() == AST_FUNCTION_COS);
  fail_unless( c1->getNumChildren() == 1);
  fail_unless( c1->getPackageName() == "core");

  child = N->getChild(1);

  fail_unless( child != NULL );
  fail_unless( child->getType() == AST_ORIGINATES_IN_PACKAGE);
  fail_unless( child->getExtendedType() == AST_LINEAR_ALGEBRA_MATRIXROW_CONSTRUCTOR);
  fail_unless( child->getNumChildren() == 2);
  fail_unless( child->getPackageName() == "arrays");

  c1 = child->getChild(0);

  fail_unless( c1 != NULL );
  fail_unless( c1->getType() == AST_INTEGER);
  fail_unless( c1->getExtendedType() == AST_INTEGER);
  fail_unless( c1->getNumChildren() == 0);
  fail_unless( c1->getInteger() == 2);
  
  ArraysASTPlugin* plugin = static_cast<ArraysASTPlugin*>(N->getPlugin("arrays"));
  
  fail_unless(plugin != NULL);
  fail_unless(plugin->getASTType() == AST_LINEAR_ALGEBRA_MATRIX_CONSTRUCTOR);

}
/*
 * Checks the MathML of the ASTnode 
 * is appropriate for the function being performed
 *
 * If an inconsistency is found, an error message is logged.
 */
void
NumericArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_PLUS:
    case AST_MINUS:
    case AST_TIMES:
    case AST_DIVIDE:
    case AST_POWER:
    case AST_FUNCTION_POWER:
    case AST_FUNCTION_ROOT:
    case AST_FUNCTION_ABS:
    case AST_FUNCTION_EXP:
    case AST_FUNCTION_LN:
    case AST_FUNCTION_LOG:
    case AST_FUNCTION_CEILING:
    case AST_FUNCTION_FLOOR:
    case AST_FUNCTION_FACTORIAL:
    case AST_FUNCTION_COS:
    case AST_FUNCTION_COT:
    case AST_FUNCTION_CSC:
    case AST_FUNCTION_SEC:
    case AST_FUNCTION_SIN:
    case AST_FUNCTION_TAN: 
    case AST_FUNCTION_COSH:
    case AST_FUNCTION_COTH:
    case AST_FUNCTION_CSCH:
    case AST_FUNCTION_SECH:
    case AST_FUNCTION_SINH:
    case AST_FUNCTION_TANH: 
    case AST_FUNCTION_ARCCOSH:
    case AST_FUNCTION_ARCCOTH:
    case AST_FUNCTION_ARCCSCH:
    case AST_FUNCTION_ARCSECH:
    case AST_FUNCTION_ARCSINH:
    case AST_FUNCTION_ARCTANH:
    case AST_FUNCTION_ARCCOS:
    case AST_FUNCTION_ARCCOT:
    case AST_FUNCTION_ARCCSC:
    case AST_FUNCTION_ARCSEC:
    case AST_FUNCTION_ARCSIN:
    case AST_FUNCTION_ARCTAN: 

      checkNumericArgs(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}