Example #1
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::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);
}