示例#1
0
void SymbolCheckVisitor::visit(ASTFunction& ast)
{
   ScopedScope scope(mScopeStack);
   ScopedValue<ASTFunction*> scopedfunction(&mpFunction, &ast, mpFunction);
   ASSERT_PTR(mpFunction);

   visitChildren(ast); // <-- arguments

   if ( ast.isConstructor() && ast.getName() != mpClass->getName() )
   {
      error(E0005, UTEXT("Function ") + ast.getName() + UTEXT(" must have a return type (or equal class name as constructor)."), ast);
   }

   if ( ast.hasBody() )
   {
      if ( ast.getModifiers().isAbstract() )
      {
         error(E0006, UTEXT("Abstract function ") + ast.getName() + UTEXT(" should not have a body."), ast);
      }
      else
      {
         checkReturn(ast);

         ast.getBody().accept(*this);
      }
   }
   else if ( !ast.getModifiers().isAbstract() && !ast.getModifiers().isPureNative() )
   {
      error(E0007, UTEXT("Function ") + ast.getName() + UTEXT(" requires a body."), ast);
   }

   mCurrentType.clear();
}
示例#2
0
/// Read-Eval-Print-Loop
static void repl(CEnv& cenv, ExecutionEngine* engine)
{
	while (1) {
		std::cout << "> ";
		std::cout.flush();
		SExp exp = readExpression(std::cin);

		try {
			AST* ast = parseExpression(exp);
			if (ast->evaluatable()) {
				ASTPrototype* proto = new ASTPrototype(false, "", vector<string>());
				ASTFunction*  func  = new ASTFunction(proto, ast);
				Function*     code  = func->Funcgen(cenv);
				void*         fp    = engine->getPointerToFunction(code);
				double (*f)() = (double (*)())fp;
				std::cout << f() << endl;
			} else {
				Value* code = ast->Codegen(cenv); 
				std::cout << "Generated code:" << endl;
				code->dump();
			}
		} catch (SyntaxError e) {
			std::cerr << "Syntax error: " << e.what() << endl;
		}
	}
}
示例#3
0
void ASTFunctionTable::reindex(int base)
{
   // skip the static and variable init blocks, as they are created in a later stage
   int resourceindex = base;

   for ( std::size_t index = 2; index < mFunctions.size(); ++index )
   {
      ASTFunction* pfunction = mFunctions[index];
      pfunction->setResourceIndex(resourceindex++);
   }
}
void ResourceCheckVisitor::visit(ASTFunction& ast)
{
   if ( !ast.getModifiers().isPureNative() && !ast.getModifiers().isAbstract() )
   {
      mOffset = 0;

      ast.getBody().accept(*this);
    
      ast.setLocalVariableCount(mOffset - ast.getArguments().size());
   }
}
示例#5
0
String DxBuilder::buildFunction(const ASTFunction& function)
{
   String code;

   const ASTAnnotation* panno = function.findAnnotation(UTEXT("maxvertexcount"));
   if ( panno != NULL )
   {
      code += UTEXT("[maxvertexcount({0})]").arg(0, panno->intvalue);
   }

   code += function.mpType->toDirectX() + ' ' + function.mName + '(';
   for ( std::size_t index = 0; index < function.mArguments.size(); ++index )
   {
      const ASTFunctionArgument* parg = function.mArguments[index];

      if ( index > 0 )
      {
         code += UTEXT(", ");
      }
      else
      {
         const ASTAnnotation* panno = function.findAnnotation(UTEXT("inputtype"));
         if ( panno != NULL )
         {
            code += panno->strvalue + L' ';
         }
      }

      if ( !parg->mpType->getTemplateClass().isEmpty() )
      {
         // hack!! maybe we should support for pre-argument values like in, inout, out
         code += UTEXT("inout ");
      }
      
      code += parg->mpType->toDirectX() + ' ' + parg->mName;
      if ( parg->mArraySize > -1 )
      {
         String conv;
         code += L'[';
         code += NumberConverter::getInstance().format(conv, parg->mArraySize) + L']'; 
      }
   }

   code += ')';

   if ( !function.mReturn.isEmpty() )
   {
      code += UTEXT(" : ") + function.mReturn;
   }
   
   code += UTEXT("\n{") + function.mBody + UTEXT("}\n");
   return code;
}
void
ASTNaryFunctionNode::reduceOperatorsToBinary()
{
  unsigned int numChildren = getNumChildren();
  /* number of children should be greater than 2 */
  if (numChildren < 3)
    return;

  /* only work with times and plus */
  int type = getType();
  if (type != AST_TIMES && type != AST_PLUS)
    return;


  ASTFunction* op = new ASTFunction( getExtendedType() );
  ASTFunction* op2 = new ASTFunction( getExtendedType() );

  // add the first two children to the first node
  op->addChild(getChild(0));
  op->addChild(getChild(1));

  op2->addChild(op);

  for (unsigned int n = 2; n < numChildren; n++)
  {
    op2->addChild(getChild(n));
  }

  swapChildren(op2);

  // valgrind says we are leaking a lot of memory here 
  // but we cannot delete op2 since its children are the children of the
  // current element
  // neither addChild not swapChildren make copies of things

  // we could remove the children and delete the object
  // removeChild does not destroy the object
  // merely removes it from the mChildren vector
  unsigned int i = op2->getNumChildren();
  while (i > 0)
  {
    op2->removeChild(i-1);
    i--;
  }

  delete op2;

  setReducedToBinary(true);

  reduceOperatorsToBinary();
}
示例#7
0
void OOCheckVisitor::visit(ASTFunction& ast)
{
   mpFunction = &ast;

   ScopedScope scope(mScopeStack);

   ast.getArgumentNodes().accept(*this);

   if ( ast.hasAnnotations() )
   {
      if ( ast.getAnnotations().contains(UTEXT("override")) )
      {
         // check if the base class still has this function
      }
   }

   if ( ast.isConstructor() )
   {
      // abstract classes can not have native constructors
      /*
      if ( ast.getModifiers().isNative() && mpClass->getModifiers().isAbstract() )
      {
         mContext.getLog().error("Abstract class " + mpClass->getFullName() + " can not have native constructors.");
      }
      */
   }
   else
   {
      if ( mpClass->hasBaseClass() )
      {
         ASTClass& baseclass = mpClass->getBaseClass();
         ASTFunction* pbasefunc = baseclass.findExactMatch(ast.getName(), ast.getSignature());
         if ( pbasefunc != NULL )
         {
            ast.setBaseFunction(*pbasefunc);
         }
      }
   }

   if ( ast.hasBody() )
   {
      mHasNativeCall = false;

      ast.getBody().accept(*this);

      if ( mHasNativeCall )
      {
         ast.getModifiers().setNative(true);
      }
   }
}
示例#8
0
void ASTFunctionTable::insert(ASTFunction& function)
{
   for ( std::size_t index = 2; index < mFunctions.size(); index++ )
   {
      ASTFunction* pfunction = mFunctions[index];

      if ( pfunction->getName() == function.getName()
        && pfunction->getSignature().exactMatch(function.getSignature()) ) // for now do not allow derived types
      {
         mFunctions[index] = &function;
         return;
      }
   }

   mFunctions.push_back(&function);
}
void
ASTNaryFunctionNode::writeNodeOfType(XMLOutputStream& stream, int type, 
                                     bool inChildNode) const
{
  if (inChildNode == false)
  {
    stream.startElement("apply");
      
    ASTBase::writeStartEndElement(stream);
  }
      

  unsigned int numChildren = getNumChildren();

  {
    for (unsigned int i = 0; i < numChildren; i++)
    {
      if (ASTFunctionBase::getChild(i)->getType() == type)
      {
        ASTFunction* fun = dynamic_cast<ASTFunction*>(ASTFunctionBase::getChild(i));
        if (fun != NULL)
        {
          fun->writeNodeOfType(stream, type, true);
        }
        else
        {
          ASTNode* newAST = dynamic_cast<ASTNode*>(ASTFunctionBase::getChild(i));
          if (newAST != NULL)
          {
            newAST->writeNodeOfType(stream, type, true);
          }
        }
      }
      else
      {
        ASTFunctionBase::getChild(i)->write(stream);
      }
    }
  }
  
  if (inChildNode == false)
  {
    stream.endElement("apply");
  }
}
int
ASTSemanticsNode::swapChildren(ASTFunction* that)
{
  int success = LIBSBML_OPERATION_FAILED;
  // the original ast nodes did not have a type for semantics
  // so we actually want to swap the children of the child
  // of this sematics node

  // catch case when this node has no children
  if (getNumChildren() == 0 || getNumChildren() > 1)
  {
    return LIBSBML_INVALID_OBJECT;
  }

  if (getChild(0)->isFunctionNode() == false)
  {
    return LIBSBML_INVALID_OBJECT;
  }


  ASTNode * child0 = dynamic_cast<ASTNode*>(getChild(0));
  if (child0 == NULL)
  {
    return LIBSBML_INVALID_OBJECT;
  }

  ASTFunction * childFunc = child0->getFunction();

  ASTFunction * child = new ASTFunction(child0->getExtendedType());
  child->syncMembersAndTypeFrom(childFunc, child0->getExtendedType());

  success = child->swapChildren(that);

  if (success == LIBSBML_OPERATION_SUCCESS)
  {
    this->removeChild(0);
    this->addChild(child);
  }

  return success;
}
示例#11
0
void SymbolCheckVisitor::checkReturn(const ASTFunction& function)
{
   checkUnknown(function.getType());

   if ( !function.getType().isVoid() )
   {
      // ensure that we have a return statement
      bool hasunreachablecode = false;
      if ( !function.getBody().hasReturn(hasunreachablecode) )
      {
         error(E0045, UTEXT("Function ") + function.getName() + UTEXT(" should return a value of type ") + function.getType().toString(), function.getPosition());
      }
      else if ( hasunreachablecode )
      {
         warning(W0003, UTEXT("Unreachable code in ") + function.getName(), function.getPosition());
      }
   }
}
bool
ASTNaryFunctionNode::read(XMLInputStream& stream, const std::string& reqd_prefix)
{
  bool read = false;
  ASTBase * child = NULL;
  const XMLToken element = stream.peek ();

  ASTBase::checkPrefix(stream, reqd_prefix, element);

  const char*      name = element.getName().c_str();

  int type = getTypeFromName(name);
  setType(type);
  ASTBase::read(stream, reqd_prefix);

  unsigned int numChildrenAdded = 0;

  if (getExpectedNumChildren() > 0)
  {
    while (stream.isGood() && numChildrenAdded < getExpectedNumChildren())
    {
      stream.skipText();

      name = stream.peek().getName().c_str();

      if (representsNumber(ASTBase::getTypeFromName(name)) == true)
      {
        child = new ASTNumber();
      }
      else 
      {
        child = new ASTFunction();
      }

      read = child->read(stream, reqd_prefix);

      stream.skipText();

      if (read == true && addChild(child) == LIBSBML_OPERATION_SUCCESS)
      {
        numChildrenAdded++;
      }
      else
      {
        delete child;
        child = NULL;
        read = false;
        break;
      }
    }
  }
  else
  {
    stream.skipPastEnd(element);
    read = true;
  }

  if (read == true && type == AST_FUNCTION_ROOT 
    && getExpectedNumChildren() == 1 
    && ASTFunctionBase::getChild(0)->getType() != AST_QUALIFIER_DEGREE)
  {
    /* HACK TO REPLICATE OLD BEHAVIOUR */
    /* we need to add the qualifier child for the degree 2 */
    ASTFunction * degree = new ASTFunction(AST_QUALIFIER_DEGREE);
    ASTNumber * int2 = new ASTNumber(AST_INTEGER);
    int2->setInteger(2);
    degree->addChild(int2->deepCopy());
    this->prependChild(degree->deepCopy());
    delete int2;
    delete degree;

  }

  //if (read == false)
  //{
  //  stream.skipPastEnd(element);
  //}

  return read;
}
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;
}
bool
ASTBinaryFunctionNode::isSqrt() const
{
  bool valid = false;

  ASTBase * base1 = NULL;

  if (getType() == AST_FUNCTION_ROOT)
  {
    if (getNumChildren() == 2)
    {
      base1 = 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;
}
void CodeGeneratorVisitor::visit(ASTFunction& ast)
{
   CIL::Function* pfunction = new CIL::Function();
   pfunction->setName(ast.getName());
   pfunction->setReturnType(toCilType(ast.getType()));
   pfunction->setModifiers(toCilModifiers(ast.getModifiers()));

   // copy the arguments
   const ASTNodes& nodes = ast.getArgumentNodes();
   for ( int index = 0; index < nodes.size(); ++index )
   {
      const ASTFunctionArgument& arg = static_cast<const ASTFunctionArgument&>(nodes[index]);
      pfunction->addArgument(toCilType(arg.getVariable().getType()));
   }

   if ( ast.hasAnnotations() )
   {
      const ASTAnnotations& annotations = ast.getAnnotations();
      for ( int index = 0; index < annotations.size(); ++index )
      {
         const ASTAnnotation& anno = annotations[index];
         pfunction->addAnnotation(anno.mName);
      }
   }
   
   if ( !ast.getModifiers().isPureNative() )
   {
      mCurrentType.clear();

      if ( ast.hasBody() )
      {
         mpFunction = &ast;

         mBuilder.start();

         ScopedScope scope(mScopeStack);
         const ASTBlock& block = ast.getBody();
         block.accept(*this);

         mBuilder.end();

         // set the generated content
         pfunction->setInstructions(mBuilder.getInstructions());
         pfunction->setGuards(mBuilder.getGuards());
         pfunction->setSwitchTables(mBuilder.getSwitchTables());
      }

      // copy the locals
      const ASTTypeList& locals = ast.getLocals();
      for ( int index = 0; index < locals.size(); ++index )
      {
         const ASTType& local = locals[index];
         yasc::Type* ptype = yasc::Type::fromString(local.toString());
         pfunction->addLocal(ptype);
      }
      
      // clean up the code body to save memory
      ast.cleanup();
   }

   mpClass->getCompiledClass().add(pfunction);
}