コード例 #1
0
ファイル: type.cpp プロジェクト: jahankhanna/hiphop-php
TypePtr Type::Coerce(AnalysisResultPtr ar, TypePtr type1, TypePtr type2) {
  if (SameType(type1, type2)) return type1;
  if (type1->m_kindOf == KindOfVariant ||
      type2->m_kindOf == KindOfVariant) return Type::Variant;
  if (type1->m_kindOf > type2->m_kindOf) {
    TypePtr tmp = type1;
    type1 = type2;
    type2 = tmp;
  }
  if (type2->m_kindOf == KindOfSome ||
      type2->m_kindOf == KindOfAny) return type1;

  if (type2->m_kindOf & KindOfAuto) {
    if (type1->mustBe(type2->m_kindOf & ~KindOfAuto)) {
      if (!(type1->m_kindOf & Type::KindOfString)) {
        return type1;
      }
      if (type2->m_kindOf == KindOfAutoSequence) {
        return Type::Sequence;
      }
      return TypePtr(new Type((KindOf)(type2->m_kindOf & ~KindOfAuto)));
    }
    return Type::Variant;
  }

  if (type1->mustBe(KindOfInteger)) {
    if (type2->mustBe(KindOfInteger)) {
      return type2;
    } else if (type2->mustBe(KindOfDouble)) {
      return Type::Numeric;
    }
  }

  if (type1->mustBe(Type::KindOfObject) &&
      type2->mustBe(Type::KindOfObject)) {
    if (type1->m_name.empty()) return type1;
    if (type2->m_name.empty()) return type2;
    ClassScopePtr cls1 = ar->findClass(type1->m_name);
    if (cls1 && !cls1->isRedeclaring() &&
        cls1->derivesFrom(ar, type2->m_name, true, false)) {
      return type2;
    }
    ClassScopePtr cls2 = ar->findClass(type2->m_name);
    if (cls2 && !cls2->isRedeclaring() &&
        cls2->derivesFrom(ar, type1->m_name, true, false)) {
      return type1;
    }
    return Type::Object;
  }

  if (type1->mustBe(type2->m_kindOf)) {
    return type2;
  }

  return Type::Variant;
}
コード例 #2
0
void FunctionScope::setParamSpecs(AnalysisResultPtr ar) {
  if (m_maxParam > 0 && m_stmt) {
    MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt);
    ExpressionListPtr params = stmt->getParams();

    for (int i = 0; i < m_maxParam; i++) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*params)[i]);
      TypePtr specType = param->getTypeSpec(ar, false);
      if (specType &&
          !specType->is(Type::KindOfSome) &&
          !specType->is(Type::KindOfVariant)) {
        m_paramTypeSpecs[i] = specType;
      }
      ExpressionPtr exp = param->defaultValue();
      if (exp) {
        m_paramDefaults[i] = exp->getText(false, false, ar);
      }
    }
  }
}
コード例 #3
0
void ObjectMethodExpression::outputCPPObject(CodeGenerator &cg,
    AnalysisResultPtr ar) {
  bool isThis = m_object->isThis();
  if (isThis && getFunctionScope()->isStatic()) {
    cg_printf("GET_THIS_ARROW()");
  }

  if (!isThis) {
    if (!m_object->getActualType() ||
        (directVariantProxy(ar) && !m_object->hasCPPTemp())) {
      TypePtr expectedType = m_object->getExpectedType();
      ASSERT(!expectedType || expectedType->is(Type::KindOfObject));
      // Clear m_expectedType to avoid type cast (toObject).
      m_object->setExpectedType(TypePtr());
      m_object->outputCPP(cg, ar);
      m_object->setExpectedType(expectedType);
    } else {
      m_object->outputCPP(cg, ar);
    }
  }
}
コード例 #4
0
void FunctionScope::setReturnType(AnalysisResultPtr ar, TypePtr type) {
  // no change can be made to virtual function's prototype
  if (m_overriding) return;

  if (m_returnType) {
    type = Type::Coerce(ar, m_returnType, type);
    if (type && !Type::SameType(m_returnType, type)) {
      ar->incNewlyInferred();
      if (!ar->isFirstPass()) {
        Logger::Verbose("Corrected function return type %s -> %s",
                        m_returnType->toString().c_str(),
                        type->toString().c_str());
      }
    }
  }
  if (!type->getName().empty()) {
    FileScopePtr fs = getFileScope();
    if (fs) fs->addClassDependency(ar, type->getName());
  }
  m_returnType = type;
}
コード例 #5
0
TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar,
                                           TypePtr type, bool coerce,
                                           FunctionScopePtr func,
                                           bool arrayParams) {
#ifdef HPHP_DETAILED_TYPE_INF_ASSERT
  assert(func->hasUser(getScope(), BlockScope::UseKindCaller));
#endif /* HPHP_DETAILED_TYPE_INF_ASSERT */
  ConstructPtr self = shared_from_this();
  TypePtr frt;
  {
    TRY_LOCK(func);
    func->getInferTypesMutex().assertOwnedBySelf();
    assert(!func->inVisitScopes() || getScope() == func);
    frt = func->getReturnType();
  }
  if (!frt) {
    m_voidReturn = true;
    setActualType(TypePtr());
    if (!isUnused() && !type->is(Type::KindOfAny)) {
      if (!hasContext(ReturnContext) &&
          !func->isFirstPass() && !func->isAbstract()) {
        if (Option::WholeProgram || !func->getContainingClass() ||
            func->isStatic() || func->isFinal() || func->isPrivate()) {
          Compiler::Error(Compiler::UseVoidReturn, self);
        }
      }
      if (!Type::IsMappedToVariant(type)) {
        setExpectedType(type);
      }
      m_voidWrapper = true;
    }
  } else {
    m_voidReturn = false;
    m_voidWrapper = false;
    type = checkTypesImpl(ar, type, frt, coerce);
    assert(m_actualType);
  }
  if (arrayParams) {
    m_extraArg = 0;
    (*m_params)[0]->inferAndCheck(ar, Type::Array, false);
  } else {
    m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid);
  }
  m_variableArgument = func->isVariableArgument();
  if (m_valid) {
    m_implementedType.reset();
  } else {
    m_implementedType = Type::Variant;
  }
  assert(type);

  return type;
}
コード例 #6
0
ファイル: declarationbuilder.cpp プロジェクト: KDE/kdev-ruby
void DeclarationBuilder::visitReturnStatement(Ast *node)
{
    AstVisitor::visitReturnStatement(node);

    if (node->tree->l != nullptr) {
        node->tree = node->tree->l;
        if (!hasCurrentType()) {
            appendProblem(node->tree, i18n("Return statement not within function declaration"));
            return;
        }
        TypePtr<FunctionType> t = currentType<FunctionType>();
        if (!t) { // the case of: a = -> { return 1 }
            return;
        }
        ExpressionVisitor ev(currentContext(), m_editor);
        ev.visitNode(node);
        AbstractType::Ptr rType = t->returnType();
        DUChainWriteLocker wlock;
        t->setReturnType(mergeTypes(ev.lastType(), rType));
    }
}
コード例 #7
0
ファイル: type.cpp プロジェクト: Bittarman/hiphop-php
TypePtr Type::Coerce(AnalysisResultPtr ar, TypePtr type1, TypePtr type2) {
  if (SameType(type1, type2)) return type1;
  if (type1->m_kindOf == KindOfVariant ||
      type2->m_kindOf == KindOfVariant) return Type::Variant;
  if (type1->m_kindOf > type2->m_kindOf) return Coerce(ar, type2, type1);
  if (type2->m_kindOf == KindOfSome ||
      type2->m_kindOf == KindOfAny) return type1;

  if (type1->mustBe(KindOfNumeric) && type2->mustBe(Type::KindOfDouble)) {
    return TypePtr(new Type(KindOfNumeric));
  } else if (type1->mustBe(KindOfNumeric) &&
             type2->mustBe(Type::KindOfNumeric)) {
    return type2;
  } else if (type1->mustBe(Type::KindOfObject) &&
             type2->mustBe(Type::KindOfObject)) {
    if (type1->m_name.empty()) return type1;
    if (type2->m_name.empty()) return type2;
    ClassScopePtr cls1 = ar->findClass(type1->m_name);
     if (cls1 && !cls1->isRedeclaring() &&
        cls1->derivesFrom(ar, type2->m_name, true, false)) {
      return type2;
    }
    ClassScopePtr cls2 = ar->findClass(type2->m_name);
    if (cls2 && !cls2->isRedeclaring() &&
        cls2->derivesFrom(ar, type1->m_name, true, false)) {
      return type1;
    }
  }

  return Type::Variant;
}
コード例 #8
0
void DeclarationAnalyzer::visitExtension(const ExtensionDefPtr& node)
{
    //if(parentNode && parentNode->getNodeType() != NodeType::Program)
    if(ctx->currentFunction || ctx->currentType)
    {
        error(node, Errors::E_A_MAY_ONLY_BE_DECLARED_AT_FILE_SCOPE_1, node->getIdentifier()->getName());
        return;
    }
    if(node->getGenericParametersDef())
    {
        error(node, Errors::E_GENERIC_ARGUMENTS_ARE_NOT_ALLOWED_ON_AN_EXTENSION);
        return;
    }
    TypePtr type = lookupType(node->getIdentifier());
    Type::Category category = type->getCategory();
    if(category == Type::Protocol)
    {
        error(node, Errors::E_PROTOCOL_A_CANNOT_BE_EXTENDED_1, type->getName());
        return;
    }
    if(category != Type::Struct && category != Type::Enum && category != Type::Class)
    {
        error(node, Errors::E_NON_NOMINAL_TYPE_A_CANNOT_BE_EXTENDED_1, node->getIdentifier()->getName());
        return;
    }

    SCOPED_SET(ctx->currentType, type);
    TypePtr extension = Type::newExtension(type);
    symbolRegistry->getFileScope()->addExtension(extension);
    SCOPED_SET(ctx->currentExtension, extension);
    for(const DeclarationPtr& decl : *node)
    {
        if(decl->getNodeType() == NodeType::ValueBindings)
        {
            error(node, Errors::E_EXTENSIONS_MAY_NOT_CONTAIN_STORED_PROPERTIES);
            continue;
        }
        decl->accept(semanticAnalyzer);
    }
}
コード例 #9
0
ファイル: loader.cpp プロジェクト: Blei/clay
static void installGlobals(ModulePtr m) {
    m->env = new Env(m);
    vector<TopLevelItemPtr>::iterator i, end;
    for (i = m->topLevelItems.begin(), end = m->topLevelItems.end();
         i != end; ++i) {
        TopLevelItem *x = i->ptr();
        x->env = m->env;
        switch (x->objKind) {
        case ENUM_DECL : {
            EnumDecl *enumer = (EnumDecl *)x;
            TypePtr t = enumType(enumer);
            addGlobal(m, enumer->name, enumer->visibility, t.ptr());
            for (unsigned i = 0 ; i < enumer->members.size(); ++i) {
                EnumMember *member = enumer->members[i].ptr();
                member->index = (int)i;
                member->type = t;
                addGlobal(m, member->name, enumer->visibility, member);
            }
            break;
        }
        case NEW_TYPE_DECL : {
            NewTypeDecl *nt = (NewTypeDecl *)x;
            TypePtr t = newType(nt);
            addGlobal(m, nt->name, nt->visibility, t.ptr());
            break;
        }
        case PROCEDURE : {
            Procedure *proc = (Procedure *)x;
            if (proc->interface != NULL)
                proc->interface->env = m->env;
            // fallthrough
        }
        default :
            if (x->name.ptr())
                addGlobal(m, x->name, x->visibility, x);
            break;
        }
    }
}
コード例 #10
0
void ForEachStatement::inferTypes(AnalysisResultPtr ar) {
  IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope());

  m_array->inferAndCheck(ar, m_ref ? Type::Variant : Type::Array, m_ref);
  if (m_name) {
    m_name->inferAndCheck(ar, Type::Primitive, true);
  }
  m_value->inferAndCheck(ar, Type::Variant, true);
  if (m_ref) {
    TypePtr actualType = m_array->getActualType();
    if (!actualType ||
        actualType->is(Type::KindOfVariant) ||
        actualType->is(Type::KindOfObject)) {
      ar->forceClassVariants(getClassScope(), false, true);
    }
  }
  if (m_stmt) {
    getScope()->incLoopNestedLevel();
    m_stmt->inferTypes(ar);
    getScope()->decLoopNestedLevel();
  }
}
コード例 #11
0
ファイル: function_container.cpp プロジェクト: 191919/hhvm
void FunctionContainer::countReturnTypes(
  std::map<std::string, int> &counts,
  const StringToFunctionScopePtrVecMap *redec) {
  for (StringToFunctionScopePtrMap::const_iterator iter =
         m_functions.begin(); iter != m_functions.end(); ++iter) {
    FunctionScopePtr f = iter->second;
    if (f->isLocalRedeclaring()) {
      always_assert(redec);
      for (FunctionScopePtr f: redec->find(iter->first)->second) {
        TypePtr type = f->getReturnType();
        if (type) {
          type->count(counts);
        }
      }
    } else {
      TypePtr type = f->getReturnType();
      if (type) {
        type->count(counts);
      }
    }
  }
}
コード例 #12
0
ファイル: expression.cpp プロジェクト: andyanx/hhvm
void Expression::setTypes(AnalysisResultConstPtr ar, TypePtr actualType,
                          TypePtr expectedType) {
  assert(actualType);
  assert(expectedType);

  m_actualType = actualType;
  if (!expectedType->is(Type::KindOfAny) &&
      !expectedType->is(Type::KindOfSome)) {
    // store the expected type if it is not Any nor Some,
    // regardless of the actual type
    m_expectedType = expectedType;
  } else {
    m_expectedType.reset();
  }

  // This is a special case where Type::KindOfObject means any object.
  if (m_expectedType && m_expectedType->is(Type::KindOfObject) &&
      !m_expectedType->isSpecificObject() &&
      m_actualType->isSpecificObject()) {
    m_expectedType.reset();
  }
}
コード例 #13
0
static bool checkCopyElision(FunctionScopePtr func, ExpressionPtr exp) {
  if (!exp->getType()->is(Type::KindOfVariant) || func->isRefReturn()) {
    return false;
  }

  TypePtr imp = exp->getImplementedType();
  if (!imp) imp = exp->getActualType();
  if (!imp || !imp->is(Type::KindOfVariant)) return false;

  if (func->getNRVOFix() && exp->is(Expression::KindOfSimpleVariable)) {
    return true;
  }

  if (FunctionCallPtr fc = dynamic_pointer_cast<FunctionCall>(exp)) {
    FunctionScopePtr fs = fc->getFuncScope();
    if (!fs || fs->isRefReturn()) {
      return true;
    }
  }

  return false;
}
コード例 #14
0
ファイル: expr_dict.cpp プロジェクト: CyaLiven/hiphop-php
TypePtr ExprDict::reduceToSingleAssertion(const TypePtrIdxPairVec &types)
  const {
  assert(m_available);
  TypePtr ret;
  for (TypePtrIdxPairVec::const_iterator it = types.begin();
       it != types.end(); ++it) {
    assert(it->first);
    if (!BitOps::get_bit(it->second, m_available)) continue;
    if (!ret) ret = it->first;
    else if (!Type::SameType(ret, it->first)) {
      if (ret->is(Type::KindOfObject) &&
          it->first->is(Type::KindOfObject)) {
        // reconcile
        ret = Type::InferredObject(
            m_am.getAnalysisResult(), ret, it->first);
      } else {
        return TypePtr();
      }
    }
  }
  return ret;
}
コード例 #15
0
bool ObjectPropertyExpression::outputCPPObject(CodeGenerator &cg,
                                               AnalysisResultPtr ar,
                                               bool noEvalOnError) {
  if (m_object->isThis()) {
    if (m_valid) {
      if (!m_object->getOriginalClass()) {
        m_valid = false;
      } else {
        FunctionScopeRawPtr fs = m_object->getOriginalFunction();
        if (!fs || fs->isStatic()) {
          m_valid = false;
        } else if (m_object->getOriginalClass() != getClassScope() &&
                   m_object->getOriginalClass()->isRedeclaring()) {
          m_valid = false;
        }
      }
    }
    if (!m_valid) {
      cg_printf("GET_THIS_DOT()");
    }
  } else if (m_valid) {
    TypePtr act;
    if (!m_object->hasCPPTemp() && m_object->getImplementedType() &&
        !Type::SameType(m_object->getImplementedType(),
                         m_object->getActualType())) {
      act = m_object->getActualType();
      m_object->setActualType(m_object->getImplementedType());
      ClassScopePtr cls = ar->findExactClass(shared_from_this(),
                                             act->getName());
      cg_printf("((%s%s*)", Option::ClassPrefix, cls->getId(cg).c_str());
    }
    m_object->outputCPP(cg, ar);
    if (act) {
      if (m_object->getImplementedType()->is(Type::KindOfObject)) {
        cg_printf(".get())");
      } else {
        cg_printf(".getObjectData())");
      }
      m_object->setActualType(act);
    }
    cg_printf("->");
  } else {
    TypePtr t = m_object->getType();
    bool ok = t && (t->is(Type::KindOfObject) || t->is(Type::KindOfVariant));
    if (noEvalOnError && !ok) {
      if (!t || !t->is(Type::KindOfArray)) {
        cg_printf("(");
        if (m_object->outputCPPUnneeded(cg, ar)) cg_printf(", ");
        return true;
      }
    }
    ok = ok || !t;
    if (!ok) cg_printf("Variant(");
    m_object->outputCPP(cg, ar);
    if (!ok) cg_printf(")");
    cg_printf(".");
  }
  return false;
}
コード例 #16
0
ファイル: printer.cpp プロジェクト: DawidvC/clay
static void printStaticOrTupleOfStatics(llvm::raw_ostream &out, TypePtr t) {
    switch (t->typeKind) {
    case STATIC_TYPE : {
        StaticType *st = (StaticType *)t.ptr();
        printName(out, st->obj);
        break;
    }
    case TUPLE_TYPE : {
        TupleType *tt = (TupleType *)t.ptr();
        out << "[";
        for (size_t i = 0; i < tt->elementTypes.size(); ++i) {
            if (i != 0)
                out << ", ";
            printStaticOrTupleOfStatics(out, tt->elementTypes[i]);
        }
        out << "]";
        break;
    }
    default :
        assert(false);
    }
}
コード例 #17
0
ファイル: Type.cpp プロジェクト: zhangjunlei26/swallow
bool Type::canAssignTo(const TypePtr &type) const
{
    if(type == nullptr)
        return false;
    TypePtr self = this->self();
    if(equals(self, type))
        return true;
    if(type->getCategory() == Protocol || type->getCategory() == Class)
    {
        if(this->category == Type::Specialized)
            self = innerType;
        if(self->parents.find(type) != parents.end())
        {
            return true;
        }
        return false;
    }
    /*
    if(type->getCategory() != category)
        return false;
    if(category == Tuple)
    {
        //In tuple type, each element type must can be assigned to corresponding element type in given argument
        if(elementTypes.size() != type->elementTypes.size())
            return false;
        auto iter1 = elementTypes.begin();
        auto iter2 = type->elementTypes.begin();
        for(; iter1 != elementTypes.end(); iter1++, iter2++)
        {
            if(!(*iter1)->canAssignTo(*iter2))
            {
                return false;
            }
        }
    }
    */
    return equals(self, type);
}
コード例 #18
0
void MethodStatement::outputCPPStaticMethodWrapper(CodeGenerator &cg,
                                                   AnalysisResultPtr ar,
                                                   const char *cls) {
  if (!m_modifiers->isStatic() || !m_stmt) return;
  FunctionScopePtr funcScope = m_funcScope.lock();
  ar->pushScope(funcScope);
  m_modifiers->outputCPP(cg, ar);
  TypePtr type = funcScope->getReturnType();
  if (type) {
    type->outputCPPDecl(cg, ar);
  } else {
    cg.printf("void");
  }
  cg.printf(" %s%s(", Option::MethodPrefix, m_name.c_str());
  CodeGenerator::Context old = cg.getContext();
  cg.setContext(CodeGenerator::CppStaticMethodWrapper);
  funcScope->outputCPPParamsDecl(cg, ar, m_params, true);
  cg.setContext(old);
  cg.printf(") { %s%s%s(\"%s\"", type ? "return " : "",
            Option::MethodImplPrefix, m_name.c_str(),
            cls);
  if (funcScope->isVariableArgument()) {
    cg.printf(", num_args");
  }
  if (m_params) {
    for (int i = 0; i < m_params->getCount(); i++) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*m_params)[i]);
      ASSERT(param);
      cg.printf(", %s%s", Option::VariablePrefix, param->getName().c_str());
    }
  }
  if (funcScope->isVariableArgument()) {
    cg.printf(", args");
  }
  cg.printf("); }\n");
  ar->popScope();
}
コード例 #19
0
ファイル: Type.cpp プロジェクト: zhangjunlei26/swallow
/*!
 * Gets the common parent class between current class and rhs with the minimum inheritance distance.
 */
TypePtr Type::getCommonParent(const TypePtr& rhs)
{
    if(rhs == nullptr || this == rhs.get())
        return rhs;
    TypePtr a;
    if(parentType)
        a = parentType->getCommonParent(rhs);

    TypePtr pthis = self();
    TypePtr b = rhs->getCommonParent(parentType);
    if(a && b)
    {
        if(a->inheritantDepth > b->inheritantDepth)
            return a;
        else
            return b;
    }
    if(a)
        return a;
    if(b)
        return b;
    return nullptr;
}
コード例 #20
0
void ObjectMethodExpression::outputCPPObjectCall(CodeGenerator &cg,
                                                 AnalysisResultPtr ar) {
  outputCPPObject(cg, ar);
  bool isThis = m_object->isThis();
  if (!isThis) {
    string objType;
    TypePtr type = m_object->getType();
    if (type->isSpecificObject() && !m_name.empty() && m_valid) {
      objType = type->getName();
      ClassScopePtr cls = ar->findClass(objType);
      objType = cls->getId();
    } else {
      objType = "ObjectData";
    }
    if (m_bindClass) {
      cg_printf("-> BIND_CLASS_ARROW(%s) ", objType.c_str());
    } else {
      cg_printf("->");
    }
  } else if (m_bindClass && m_classScope) {
    cg_printf(" BIND_CLASS_ARROW(%s) ", m_classScope->getId().c_str());
  }
}
コード例 #21
0
ファイル: type.cpp プロジェクト: hashaash/hiphop-php
bool Type::HasFastCastMethod(TypePtr t) {
  switch (t->getKindOf()) {
  case Type::KindOfBoolean:
  case Type::KindOfInt32:
  case Type::KindOfInt64:
  case Type::KindOfDouble:
  case Type::KindOfString:
  case Type::KindOfArray:
  case Type::KindOfObject:
    return true;
  default: break;
  }
  return false;
}
コード例 #22
0
/*!
 * Verify if the specified type conform to the given protocol
 */
bool DeclarationAnalyzer::verifyProtocolConform(const TypePtr& type, bool supressError)
{
    if(type->getCategory() == Type::Protocol)
        return true;//do not perform protocol conform on protocol type
    int idx = 0;
    TypeBuilderPtr type2 = static_pointer_cast<TypeBuilder>(type);
    vector<int>& protocolFlags = type2->getProtocolFlags();
    for(const TypePtr& protocol : type->getProtocols())
    {
        //TODO check if the protocol is checked
        if(protocolFlags[idx] == 0)
        {
            bool success = verifyProtocolConform(type, protocol, supressError);
            if(success)
            {
                //TODO: mark the protocol is checked
                protocolFlags[idx] = 1;
            }
        }
        idx++;
    }
    return true;
}
コード例 #23
0
bool ObjectPropertyExpression::directVariantProxy(AnalysisResultPtr ar) {
  TypePtr actualType = m_object->getActualType();
  if (actualType && actualType->is(Type::KindOfVariant)) {
    if (m_object->is(KindOfSimpleVariable)) {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(m_object);
      const std::string &name = var->getName();
      FunctionScopePtr func =
        dynamic_pointer_cast<FunctionScope>(ar->getScope());
      VariableTablePtr variables = func->getVariables();
      if (!variables->isParameter(name) || variables->isLvalParam(name)) {
        return true;
      }
      if (variables->getAttribute(VariableTable::ContainsDynamicVariable) ||
          variables->getAttribute(VariableTable::ContainsExtract)) {
        return true;
      }
    } else {
      return true;
    }
  }
  return false;
}
コード例 #24
0
ファイル: types.cpp プロジェクト: ceninan/clay
TypePtr pointerType(TypePtr pointeeType) {
    int h = pointerHash(pointeeType.ptr());
    h &= pointerTypes.size() - 1;
    vector<PointerTypePtr>::iterator i, end;
    for (i = pointerTypes[h].begin(), end = pointerTypes[h].end();
         i != end; ++i) {
        PointerType *t = i->ptr();
        if (t->pointeeType == pointeeType)
            return t;
    }
    PointerTypePtr t = new PointerType(pointeeType);
    pointerTypes[h].push_back(t);
    return t.ptr();
}
コード例 #25
0
ファイル: types.cpp プロジェクト: ceninan/clay
TypePtr vecType(TypePtr elementType, int size) {
    int h = pointerHash(elementType.ptr()) + size;
    h &= vecTypes.size() - 1;
    vector<VecTypePtr>::iterator i, end;
    for (i = vecTypes[h].begin(), end = vecTypes[h].end();
         i != end; ++i) {
        VecType *t = i->ptr();
        if ((t->elementType == elementType) && (t->size == size))
            return t;
    }
    VecTypePtr t = new VecType(elementType, size);
    vecTypes[h].push_back(t);
    return t.ptr();
}
コード例 #26
0
ファイル: loader.cpp プロジェクト: Blei/clay
static ModulePtr typeModule(TypePtr t) {
    switch (t->typeKind) {
    case BOOL_TYPE :
    case INTEGER_TYPE :
    case FLOAT_TYPE :
    case COMPLEX_TYPE :
    case POINTER_TYPE :
    case CODE_POINTER_TYPE :
    case CCODE_POINTER_TYPE :
    case ARRAY_TYPE :
    case VEC_TYPE :
    case TUPLE_TYPE :
    case UNION_TYPE :
    case STATIC_TYPE :
        return primitivesModule();
    case RECORD_TYPE : {
        RecordType *rt = (RecordType *)t.ptr();
        return envModule(rt->record->env);
    }
    case VARIANT_TYPE : {
        VariantType *vt = (VariantType *)t.ptr();
        return envModule(vt->variant->env);
    }
    case ENUM_TYPE : {
        EnumType *et = (EnumType *)t.ptr();
        return envModule(et->enumeration->env);
    }
    case NEW_TYPE : {
        NewType *et = (NewType *)t.ptr();
        return envModule(et->newtype->env);
    }
    default :
        assert(false);
        return NULL;
    }
}
コード例 #27
0
void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func =
    dynamic_pointer_cast<FunctionScope>(ar->getScope());
  VariableTablePtr variables = func->getVariables();
  TypePtr paramType = func->getParamType(cg.getItemIndex());
  bool isCVarRef = false;
  if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper ||
      (!variables->isLvalParam(m_name) &&
       !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
       !variables->getAttribute(VariableTable::ContainsExtract) &&
       !m_ref)) {
    if (paramType->is(Type::KindOfVariant) ||
        paramType->is(Type::KindOfSome)) {
      cg_printf("CVarRef");
      isCVarRef = true;
    }
    else if (paramType->is(Type::KindOfArray)) cg_printf("CArrRef");
    else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef");
    else paramType->outputCPPDecl(cg, ar);
  } else {
    paramType->outputCPPDecl(cg, ar);
  }

  cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str());
  if (m_defaultValue) {
    CodeGenerator::Context context = cg.getContext();
    bool comment =  context == CodeGenerator::CppImplementation ||
      (context == CodeGenerator::CppDeclaration && func->isInlined());
    if (comment) {
      cg_printf(" // ");
    }
    cg_printf(" = ");
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_defaultValue);
    if (isCVarRef && con && con->isNull()) {
      cg_printf("null_variant");
    } else {
      if (comment) {
        cg.setContext(CodeGenerator::CppParameterDefaultValueImpl);
      } else {
        cg.setContext(CodeGenerator::CppParameterDefaultValueDecl);
      }
      m_defaultValue->outputCPP(cg, ar);
      cg.setContext(context);
    }
    if (comment) {
      cg_printf("\n");
    }
  }
}
コード例 #28
0
void AssignmentExpression::onParseRecur(AnalysisResultConstPtr ar,
                                        ClassScopePtr scope) {
  // This is that much we can do during parse phase.
  TypePtr type;
  if (m_value->is(Expression::KindOfScalarExpression)) {
    type = static_pointer_cast<ScalarExpression>(m_value)->inferenceImpl(
      ar, Type::Some, false);
  } else if (m_value->is(Expression::KindOfUnaryOpExpression)) {
    UnaryOpExpressionPtr uexp =
      dynamic_pointer_cast<UnaryOpExpression>(m_value);
    if (uexp->getOp() == T_ARRAY) {
      type = Type::Array;
    }
  }
  if (!type) type = Type::Some;

  if (m_variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    // We are handling this one here, not in ClassConstant, purely because
    // we need "value" to store in constant table.
    if (type->is(Type::KindOfArray)) {
      parseTimeFatal(Compiler::NoError,
                     "Arrays are not allowed in class constants");
    }
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_variable);
    scope->getConstants()->add(exp->getName(), type, m_value, ar, m_variable);
  } else if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable);
    scope->getVariables()->add(var->getName(), type, true, ar,
                               shared_from_this(), scope->getModifiers());
    var->clearContext(Declaration); // to avoid wrong CodeError
  } else {
    assert(false); // parse phase shouldn't handle anything else
  }
}
コード例 #29
0
ファイル: types.cpp プロジェクト: ceninan/clay
bool isStaticOrTupleOfStatics(TypePtr t) {
    switch (t->typeKind) {
    case STATIC_TYPE :
        return true;
    case TUPLE_TYPE : {
        TupleType *tt = (TupleType *)t.ptr();
        for (unsigned i = 0; i < tt->elementTypes.size(); ++i) {
            if (!isStaticOrTupleOfStatics(tt->elementTypes[i]))
                return false;
        }
        return true;
    }
    default :
        return false;
    }
}
コード例 #30
0
void SemanticAnalyzer::checkTupleDefinition(const TuplePtr& tuple, const ExpressionPtr& initializer)
{
    //this is a tuple definition, the corresponding declared type must be a tuple type
    TypeNodePtr declaredType = tuple->getDeclaredType();
    TypePtr type = lookupType(declaredType);
    if(!type)
    {
        error(tuple, Errors::E_USE_OF_UNDECLARED_TYPE_1, toString(declaredType));
        return;
    }
    if(!(type->getCategory() == Type::Tuple))
    {
        //tuple definition must have a tuple type definition
        error(tuple, Errors::E_TUPLE_PATTERN_MUST_MATCH_TUPLE_TYPE_1, toString(declaredType));
        return;
    }
    if(tuple->numElements() != type->numElementTypes())
    {
        //tuple pattern has the wrong length for tuple type '%'
        error(tuple, Errors::E_TUPLE_PATTERN_MUST_MATCH_TUPLE_TYPE_1, toString(declaredType));
        return;
    }
    //check if initializer has the same type with the declared type
    if(initializer)
    {
        TypePtr valueType = evaluateType(initializer);
        if(valueType && !Type::equals(valueType, type))
        {
            //tuple pattern has the wrong length for tuple type '%'
            //tuple types '%0' and '%1' have a different number of elements (%2 vs. %3)
            wstring expectedType = type->toString();
            wstring got = toString(valueType->numElementTypes());
            wstring expected = toString(type->numElementTypes());
            error(initializer, Errors::E_TUPLE_TYPES_HAVE_A_DIFFERENT_NUMBER_OF_ELEMENT_4, toString(declaredType), expectedType, got, expected);
            return;
        }
    }


    for(const PatternPtr& p : *tuple)
    {
        NodeType nodeType = p->getNodeType();
        if(nodeType != NodeType::Identifier)
        {

        }

    }
}