TypePtr Parser::maybeType(bool se) { if(token == TIdent) { TypePtr t = resolveIdentType(tokenStr); if(t) next(se); return t; } else if(token == TTypeIdent) { IntrusiveRefCntPtr<TypeDataNamed> named( new TypeDataNamed(nextIdent(se))); if(test(TLParen)) { do { named->typeAssignment.push_back(typeName(false)); } while(test(TComma)); expect(TRParen); } return TypePtr(named); } parseError(); return TypePtr(); }
TypePtr getRepeatedType(const TypePtr& cur) { assert_true(isVariableSized(cur)) << "Only variable sized types contain repeated types."; NodeType type = cur->getNodeType(); switch(type) { case NT_ArrayType: return cur.as<ArrayTypePtr>()->getElementType(); case NT_StructType: { StructTypePtr structType = cur.as<StructTypePtr>(); return getRepeatedType(structType.back()->getType()); } case NT_TupleType: { TupleTypePtr tupleType = cur.as<TupleTypePtr>(); return getRepeatedType(tupleType.back()); } case NT_UnionType: { UnionTypePtr unionType = cur.as<UnionTypePtr>(); for(auto cur : unionType) { if (isVariableSized(cur->getType())) return getRepeatedType(cur->getType()); } break; } default: break; } assert_fail() << "Invalid classification as a variable sized type!"; return TypePtr(); }
TypePtr TypeData::fresh() { /* if(kind == TyVar) { IntrusiveRefCntPtr<TypeData> data( new TypeDataVar(*static_cast<TypeDataVar*>(data.getPtr()))); return TypeRef(TyVar, data); } else if(kind == TyNamed) { vector<TypeRef> newAssignment; auto& def = *static_cast<TypeDataDef*>(data.getPtr()); bool different = false; for(auto& t : def.typeAssignment) { TypeRef newT = t.fresh(); newAssignment.push_back(newT); different = different || !newT.isSame(t); } if(different) { } } assert(kind != TyDef); */ return TypePtr(this); }
TypePtr TypeData::commonWith(TypePtr const& other) { if(this != other.getPtr()) // TODO: TypeData may not be interned return tyUnit; return TypePtr(this); }
TypePtr Parser::parseType() { if (match(TokenType::Array)) { if (!match(TokenType::LBracket)) { reportError(ErrorCodes::ExpectedLBracket); panic(typeFollow, typeFollowSize); return TypePtr(); } NumberPtr from = parseNumber(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::Range)) { reportError(ErrorCodes::ExpectedRange); panic(typeFollow, typeFollowSize); return TypePtr(); } NumberPtr to = parseNumber(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::RBracket)) { reportError(ErrorCodes::ExpectedRBracket); panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::Of)) { reportError(ErrorCodes::ExpectedOf); panic(typeFollow, typeFollowSize); return TypePtr(); } TypePtr type = parseStandardType(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } TypePtr arrayType(new Type); arrayType->isArray = true; arrayType->startsAt = from; arrayType->endsAt = to; arrayType->standardType = type->standardType; return arrayType; } return parseStandardType(); }
Value *TacBuilder::createNot(Value *value) { TacValuePtr result = m_insertBlock->owner->createTemporary(TypePtr()); TacValue *valueValue = (TacValue *)value; m_insertBlock->code << "\t\t" << "NOT" << "\t" << valueValue->value() << "\t" << valueValue->value() << "\t" << result->value() << std::endl; return result.get(); }
Value *TacBuilder::createSub(Value *lhs, Value *rhs) { TacValuePtr result = m_insertBlock->owner->createTemporary(TypePtr()); TacValue *lhsValue = (TacValue *)lhs; TacValue *rhsValue = (TacValue *)rhs; m_insertBlock->code << "\t\t" << "SUB" << "\t" << lhsValue->value() << "\t" << rhsValue->value() << "\t" << result->value() << std::endl; return result.get(); }
TacBuilder::TacBuilder() : m_programFunction(new TacFunction("", DeclarationsPtr(), TypePtr())) , m_insertBlock() { TacValuePtr writelnPtr(new TacValue); IdentifierPtr writelnIdPtr(new Identifier); writelnIdPtr->id = Token("writeln", -1, -1); writelnPtr->id = writelnIdPtr; writelnPtr->isConstant = true; writelnPtr->isFunction = true; m_programFunction->symbols.push_back(writelnPtr); }
TypePtr deduceReturnType(const FunctionTypePtr& funType, const TypeList& argumentTypes, bool unitOnFail) { try { // try deducing the return type ... return tryDeduceReturnType(funType, argumentTypes); } catch (const ReturnTypeDeductionException&) { // didn't work => print a warning LOG(DEBUG) << "Unable to deduce return type for call to function of type " << toString(*funType) << " using arguments " << join(", ", argumentTypes, print<deref<TypePtr>>()); } // return null ptr return unitOnFail ? funType->getNodeManager().getLangBasic().getUnit() : TypePtr(); }
Value *TacBuilder::createCmpNe(Value *lhs, Value *rhs) { TacValuePtr result = m_insertBlock->owner->createTemporary(TypePtr()); std::string trueLabel = createLabel(); std::string doneLabel = createLabel(); TacValue *lhsValue = (TacValue *)lhs; TacValue *rhsValue = (TacValue *)rhs; m_insertBlock->code << "\t\t" << "NE" << "\t" << lhsValue->value() << "\t" << rhsValue->value() << "\t" << trueLabel << std::endl; m_insertBlock->code << "\t\t" << "ASSIGN" << "\t" << "0" << "\t" << result->value() << std::endl; m_insertBlock->code << "\t\t" << "GOTO" << "\t" << doneLabel << std::endl; m_insertBlock->code << trueLabel << ":"; m_insertBlock->code << "\t\t" << "ASSIGN" << "\t" << "1" << "\t" << result->value() << std::endl; m_insertBlock->code << doneLabel << ":"; return result.get(); }
TypePtr TypeDataDef::apply(vector<TypePtr> const& params) { assert(!params.empty()); IntrusiveRefCntPtr<TypeDataDef> newData(new TypeDataDef(*this)); newData->typeAssignment.insert( newData->typeAssignment.end(), params.begin(), params.end()); // Check "over-application" if(newData->typeAssignment.size() > def->typeParams.size()) throw CompileError(CEGeneralError, -1); return TypePtr(newData); }
TypePtr Parser::parseStandardType() { TypePtr type(new Type); if (m_curToken.tokenType() == TokenType::Integer) { match(TokenType::Integer); type->standardType = NumberType::Integer; return type; } else if (m_curToken.tokenType() == TokenType::Real) { match(TokenType::Real); type->standardType = NumberType::Real; return type; } reportError(ErrorCodes::ExpectedStandardType); return TypePtr(); }
IntrusiveRefCntPtr<PatternExpr> Parser::pattern(bool se) { // TODO: Proper pattern syntax if(token == TTypeIdent) { string const& ctorName = nextIdent(se); IntrusiveRefCntPtr<PatternNamedCtorExpr> pt( new PatternNamedCtorExpr()); pt->name = ctorName; if(test(TLParen)) { do { pt->subPatterns.push_back(pattern(false)); } while(test(TComma)); expect(TRParen); } return IntrusiveRefCntPtr<PatternExpr>(pt.getPtr()); } else if(token == TIdent) { string const& bindingName = nextIdent(se); auto varDecl = declVar(bindingName, TypePtr()); IntrusiveRefCntPtr<PatternBindingExpr> pt( new PatternBindingExpr()); pt->var = varDecl; return IntrusiveRefCntPtr<PatternExpr>(pt.getPtr()); } parseError(); return IntrusiveRefCntPtr<PatternExpr>(); }
TypePtr UserAttribute::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { assert(false); return TypePtr(); }
void TypeInference::inferTypes( ValueDef& valueDef, StaticContextPtr& pMemberCtx, const LogPtr& pLog) { switch (valueDef.getValueType()) { case OBJECT_INIT: { const ObjectInitValueDef& objectInitDef = static_cast<const ObjectInitValueDef&>(valueDef); TypePtr pType = TypePtr( new ReferenceType(OBJECT_REF_TYPE, objectInitDef.getClassName())); valueDef.setInferredType(pType); const map<const wstring, ActualParamDefPtr>& actualParamsMap = objectInitDef.getActualParamsMap(); map<const wstring, ActualParamDefPtr>::const_iterator it; for (it = actualParamsMap.begin(); it != actualParamsMap.end(); it++) { const ActualParamDefPtr& pActualParamDef = (*it).second; const ValueDefPtr& pParamValueDef = pActualParamDef->getValue(); inferTypes(*pParamValueDef, pMemberCtx, pLog); } } break; case ARRAY_INIT: { const ArrayInitValueDef& arrayInitDef = static_cast<const ArrayInitValueDef&>(valueDef); valueDef.setInferredType(arrayInitDef.getDeclaredType()); const list<ValueDefPtr>& arrayValues = arrayInitDef.getValues(); list<ValueDefPtr>::const_iterator it; for (it = arrayValues.begin(); it != arrayValues.end(); it++) { const ValueDefPtr& pArrayValue = *it; inferTypes(*pArrayValue, pMemberCtx, pLog); } } break; case LITERAL: { const LiteralValueDef& literalDef = static_cast<const LiteralValueDef&>(valueDef); switch (literalDef.getLiteralType()) { case INTEGER_LITERAL: valueDef.setInferredType(P_INTEGER_TYPE); break; case FLOAT_LITERAL: valueDef.setInferredType(P_FLOAT_TYPE); break; case STRING_LITERAL: valueDef.setInferredType(P_STRING_TYPE); break; default: assert(false); break; } } break; case REFERENCE_PATH: { const ReferencePathValueDef& referencePathDef = static_cast<const ReferencePathValueDef&>(valueDef); const list<const wstring>& path = referencePathDef.getReferencePath(); StaticContextEntryPtr pEntry; TypePtr pCurrentType; list<const wstring>::const_iterator it; wstring parentPath(L""); for (it = path.begin(); it != path.end(); it++) { const wstring& pathElement = *it; if (it == path.begin()) { CStaticContextEntryPtr pEntry; if (!pMemberCtx->lookup(pathElement, pEntry)) { boost::wformat f(L"Unable to resolve name %1%"); f % pathElement; pLog->log(referencePathDef, msg::ErrAnaTypeInfer_NameNotInContext, f.str()); return; } else { switch (pEntry->getStaticEntryType()) { case CLASS_DEF_CTX_ENTRY: { TypePtr pType(new ReferenceType(CLASS_REF_TYPE, pEntry->getName())); pCurrentType = pType; } break; case INTERFACE_DEF_CTX_ENTRY: { TypePtr pType(new ReferenceType(CLASS_REF_TYPE, pEntry->getName())); pCurrentType = pType; } break; case VARIABLE_DEF_CTX_ENTRY: { VariableDeclDefPtr pVariableDef; pEntry->getVariable(pVariableDef); if (pMemberCtx->isStatic() && !pVariableDef->isStatic()) { boost::wformat f(L"Cannot refer to a non static variable from an static context: %1%"); f % pathElement; pLog->log(referencePathDef, msg::ErrAnaTypeInfer_NonStaticVarRef, f.str()); return; } else { pCurrentType = pVariableDef->getDeclaredType(); } } break; case FORMAL_PARAM_DEF_CTX_ENTRY: { if (pMemberCtx->isStatic()) { boost::wformat f(L"Cannot refer to a class parameter from an static context: %1%"); f % pathElement; pLog->log(referencePathDef, msg::ErrAnaTypeInfer_NonStaticParamRef, f.str()); return; } FormalParamDefPtr pFormalParamDef; pEntry->getFormalParam(pFormalParamDef); pCurrentType = pFormalParamDef->getType(); } break; default: assert(false); return; } } } else { assert(pCurrentType.get() != NULL); StaticContextPtr pRootCtx; pMemberCtx->getRootContext(pRootCtx); if (!followPathElement( *pCurrentType, *pRootCtx, pathElement, pCurrentType)) { boost::wformat f(L"%1% is not a member of %2%"); f % pathElement % parentPath; pLog->log(referencePathDef, msg::ErrAnaTypeInfer_NotAMember, f.str()); return; } } if (parentPath.size()) { parentPath.append(L"."); } parentPath.append(pathElement); } assert(pCurrentType.get() != NULL); valueDef.setInferredType(pCurrentType); } break; default: assert(false); break; } }
TypePtr TypeDataDef::doResolve(ModuleBuilder& /*modBuilder*/) { def->doResolve(*modBuilder); TypeDataComposite::doResolve(); return TypePtr(this); }
TypePtr PointerType::create(const TypePtr& elementType, bool _const, bool _volatile) { assert_true(elementType); return PointerType(elementType, _const, _volatile).operator TypePtr(); }
TypePtr Parser::resolveIdentType(string const& name) { if (!currentTypeScope) return TypePtr(); return currentTypeScope->resolveIdent(name); }