void FunctionAnalyzer::visitSubscript(const SubscriptDefPtr &node) { //TypeInference ParametersNodePtr parameters = node->getParameters(); TypePtr retType = declarationAnalyzer->resolveType(node->getReturnType(), true); TypePtr type = declarationAnalyzer->resolveType(node->getReturnType(), true); assert(type != nullptr); std::vector<Parameter> params; for (const ParameterNodePtr ¶m : *node->getParameters()) { wstring name = param->isShorthandExternalName() ? param->getLocalName() : param->getExternalName(); TypePtr paramType = declarationAnalyzer->resolveType(param->getDeclaredType(), true); params.push_back(Parameter(name, param->isInout(), paramType)); //verify index's access level declarationAnalyzer->verifyAccessLevel(node, paramType, DeclarationTypeSubscript, ComponentTypeIndex); } //verify element type's access level declarationAnalyzer->verifyAccessLevel(node, type, DeclarationTypeSubscript, ComponentTypeType); //process getter visitAccessor(node->getGetter(), parameters, nullptr, node->getModifiers()); //process setter wstring setterName = L"newValue"; if (!node->getSetterName().empty()) setterName = node->getSetterName(); SymbolPlaceHolderPtr setter(new SymbolPlaceHolder(setterName, retType, SymbolPlaceHolder::R_PARAMETER, SymbolFlagReadable | SymbolFlagInitialized)); visitAccessor(node->getSetter(), parameters, setter, node->getModifiers()); }
/* “GRAMMAR OF A SUBSCRIPT DECLARATION subscript-declaration → subscript-head subscript-result code-block subscript-declaration → subscript-head subscript-result getter-setter-block subscript-declaration → subscript-head subscript-result getter-setter-keyword-block subscript-head → attributes opt subscript parameter-clause subscript-result → ->attributes opt type ” */ DeclarationPtr Parser::parseSubscript(const std::vector<AttributePtr>& attrs) { Token token; expect(Keyword::Subscript, token); ParametersPtr params = parseParameterClause(); expect(L"->"); Attributes typeAttrs; parseAttributes(typeAttrs); TypeNodePtr retType = parseType(); SubscriptDefPtr ret = nodeFactory->createSubscript(token.state); ret->setAttributes(attrs); ret->setParameters(params); ret->setReturnType(retType); ret->setReturnTypeAttributes(typeAttrs); if(flags & UNDER_PROTOCOL) { expect(L"{"); std::pair<CodeBlockPtr, CodeBlockPtr> accessors = parseGetterSetterKeywordBlock(); expect(L"}"); ret->setGetter(accessors.first); ret->setSetter(accessors.second); } else { Token token; TokenizerState s = tokenizer->save(); expect(L"{"); expect_next(token); restore(token); if(token.getKeyword() == Keyword::Set || token.getKeyword() == Keyword::Get) { std::pair<CodeBlockPtr, std::pair<std::wstring, CodeBlockPtr> > accessors = parseGetterSetterBlock(); ret->setGetter(accessors.first); ret->setSetter(accessors.second.second); ret->setSetterName(accessors.second.first); expect(L"}"); } else { tokenizer->restore(s); CodeBlockPtr cb = parseCodeBlock(); ret->setGetter(cb); } } return ret; }
void NodeVisitor::visitSubscript(const SubscriptDefPtr& node) { ACCEPT(node->getGetter()); ACCEPT(node->getSetter()); }