From 3286d1cec2728acd0a3bca940297fbe430d0dd80 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 21 Jun 2023 01:04:14 +0200 Subject: [PATCH] tmp --- liblangutil/Token.h | 3 +- libsolidity/analysis/SyntaxChecker.cpp | 14 ++- libsolidity/analysis/SyntaxChecker.h | 2 + .../experimental/SyntaxRestrictor.cpp | 3 +- .../analysis/experimental/TypeInference.cpp | 28 +++++- .../analysis/experimental/TypeInference.h | 3 + libsolidity/ast/AST.cpp | 8 ++ libsolidity/ast/AST.h | 41 +++++++++ libsolidity/ast/ASTAnnotations.h | 8 ++ libsolidity/ast/ASTJsonExporter.cpp | 9 ++ libsolidity/ast/ASTJsonExporter.h | 1 + libsolidity/ast/ASTVisitor.h | 16 ++++ libsolidity/ast/AST_accept.h | 27 ++++++ libsolidity/ast/experimental/TypeSystem.cpp | 88 ++++++++++++++++--- libsolidity/ast/experimental/TypeSystem.h | 10 ++- libsolidity/parsing/Parser.cpp | 65 +++++++++++++- libsolidity/parsing/Parser.h | 3 +- .../semanticTests/experimental/stub.sol | 10 +-- 18 files changed, 307 insertions(+), 32 deletions(-) diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 9753c45b4..2fc12efb2 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -273,6 +273,7 @@ namespace solidity::langutil K(Class, "class", 0) \ K(Instantiation, "instantiation", 0) \ K(Word, "word", 0) \ + K(Integer, "integer", 0) \ K(Void, "void", 0) \ K(StaticAssert, "static_assert", 0) \ T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \ @@ -301,7 +302,7 @@ namespace TokenTraits // Predicates constexpr bool isElementaryTypeName(Token tok) { - return (Token::Int <= tok && tok < Token::TypesEnd) || tok == Token::Word || tok == Token::Void; + return (Token::Int <= tok && tok < Token::TypesEnd) || tok == Token::Word || tok == Token::Void || tok == Token::Integer; } constexpr bool isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; } constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; } diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 4f99f67ac..ad1d6ca9d 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -451,7 +451,9 @@ bool SyntaxChecker::visit(UsingForDirective const& _usingFor) bool SyntaxChecker::visit(FunctionDefinition const& _function) { - solAssert(_function.isFree() == (m_currentContractKind == std::nullopt), ""); + if (m_sourceUnit && m_sourceUnit->experimentalSolidity()) + // Handled in experimental::SyntaxRestrictor instead. + return true; if (!_function.isFree() && !_function.isConstructor() && _function.noVisibilitySpecified()) { @@ -506,3 +508,13 @@ bool SyntaxChecker::visit(StructDefinition const& _struct) return true; } + +bool SyntaxChecker::visitNode(ASTNode const& _node) +{ + if (_node.experimentalSolidityOnly()) + { + solAssert(m_sourceUnit); + solAssert(m_sourceUnit->experimentalSolidity()); + } + return ASTConstVisitor::visitNode(_node); +} diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index f221df09f..69bda229f 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -97,6 +97,8 @@ private: bool visit(StructDefinition const& _struct) override; bool visit(Literal const& _literal) override; + bool visitNode(ASTNode const&) override; + langutil::ErrorReporter& m_errorReporter; bool m_useYulOptimizer = false; diff --git a/libsolidity/analysis/experimental/SyntaxRestrictor.cpp b/libsolidity/analysis/experimental/SyntaxRestrictor.cpp index 17c4cc629..f20fa6b41 100644 --- a/libsolidity/analysis/experimental/SyntaxRestrictor.cpp +++ b/libsolidity/analysis/experimental/SyntaxRestrictor.cpp @@ -32,7 +32,8 @@ bool SyntaxRestrictor::check(ASTNode const& _astRoot) bool SyntaxRestrictor::visitNode(ASTNode const& _node) { - m_errorReporter.syntaxError(0000_error, _node.location(), "Unsupported AST node."); + if (!_node.experimentalSolidityOnly()) + m_errorReporter.syntaxError(0000_error, _node.location(), "Unsupported AST node."); return false; } diff --git a/libsolidity/analysis/experimental/TypeInference.cpp b/libsolidity/analysis/experimental/TypeInference.cpp index d069e0887..a149d2c0c 100644 --- a/libsolidity/analysis/experimental/TypeInference.cpp +++ b/libsolidity/analysis/experimental/TypeInference.cpp @@ -41,11 +41,13 @@ m_errorReporter(_analysis.errorReporter()) {BuiltinType::Function, "fun", 2}, {BuiltinType::Unit, "unit", 0}, {BuiltinType::Pair, "pair", 2}, - {BuiltinType::Word, "word", 0} + {BuiltinType::Word, "word", 0}, + {BuiltinType::Integer, "integer", 0} }) m_typeSystem.declareBuiltinType(type, name, arity); m_voidType = m_typeSystem.builtinType(BuiltinType::Void, {}); m_wordType = m_typeSystem.builtinType(BuiltinType::Word, {}); + m_integerType = m_typeSystem.builtinType(BuiltinType::Integer, {}); m_typeAnnotations.resize(_analysis.maxAstId()); } @@ -84,7 +86,8 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition) m_currentFunctionType = functionType; - _functionDefinition.body().accept(*this); + if (_functionDefinition.isImplemented()) + _functionDefinition.body().accept(*this); functionAnnotation.type = m_typeSystem.fresh( functionType, @@ -143,13 +146,32 @@ experimental::Type TypeInference::fromTypeName(TypeName const& _typeName) return m_wordType; case Token::Void: return m_voidType; + case Token::Integer: + return m_integerType; default: m_errorReporter.typeError(0000_error, _typeName.location(), "Only elementary types are supported."); break; } } + else if (auto const* userDefinedTypeName = dynamic_cast(&_typeName)) + { + auto const* declaration = userDefinedTypeName->pathNode().annotation().referencedDeclaration; + solAssert(declaration); + if (auto const* variableDeclaration = dynamic_cast(declaration)) + { + if (auto const* typeClass = dynamic_cast(variableDeclaration->scope())) + { + (void)typeClass; + m_errorReporter.typeError(0000_error, _typeName.location(), "Using type class type variables not yet implemented."); + } + else + m_errorReporter.typeError(0000_error, _typeName.location(), "Type name referencing a variable declaration."); + } + else + m_errorReporter.typeError(0000_error, _typeName.location(), "Unsupported user defined type name."); + } else - m_errorReporter.typeError(0000_error, _typeName.location(), "Only elementary types are supported."); + m_errorReporter.typeError(0000_error, _typeName.location(), "Unsupported type name."); return m_typeSystem.freshTypeVariable(false); } diff --git a/libsolidity/analysis/experimental/TypeInference.h b/libsolidity/analysis/experimental/TypeInference.h index 2782236c1..4e54eb9e6 100644 --- a/libsolidity/analysis/experimental/TypeInference.h +++ b/libsolidity/analysis/experimental/TypeInference.h @@ -57,6 +57,8 @@ private: bool visit(Return const&) override { return true; } void endVisit(Return const& _return) override; + bool visit(TypeClassDefinition const&) override { return true; } + bool visitNode(ASTNode const& _node) override; Type fromTypeName(TypeName const& _typeName); @@ -65,6 +67,7 @@ private: TypeSystem m_typeSystem; Type m_voidType; Type m_wordType; + Type m_integerType; std::optional m_currentFunctionType; struct TypeAnnotation diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 833ba739e..cb5998d77 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -1058,3 +1058,11 @@ TryCatchClause const* TryStatement::errorClause() const { TryCatchClause const* TryStatement::fallbackClause() const { return findClause(m_clauses); } + +/// Experimental Solidity nodes +/// @{ +TypeClassDefinitionAnnotation& TypeClassDefinition::annotation() const +{ + return initAnnotation(); +} +/// @} \ No newline at end of file diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 07c9576fc..d9a1220f8 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -121,6 +121,8 @@ public: bool operator!=(ASTNode const& _other) const { return !operator==(_other); } ///@} + virtual bool experimentalSolidityOnly() const { return false; } + protected: size_t const m_id = 0; @@ -2447,4 +2449,43 @@ private: /// @} +/// Experimental Solidity nodes +/// @{ +class TypeClassDefinition: public Declaration, public StructurallyDocumented, public ScopeOpener +{ +public: + TypeClassDefinition( + int64_t _id, + SourceLocation const& _location, + ASTPointer _typeVariable, + ASTPointer const& _name, + SourceLocation _nameLocation, + ASTPointer const& _documentation, + std::vector> _subNodes + ): + Declaration(_id, _location, _name, std::move(_nameLocation)), + StructurallyDocumented(_documentation), + m_typeVariable(std::move(_typeVariable)), + m_subNodes(std::move(_subNodes)) + {} + + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; + + VariableDeclaration const& typeVariable() const { return *m_typeVariable; } + std::vector> const& subNodes() const { return m_subNodes; } + + TypeClassDefinitionAnnotation& annotation() const override; + + Type const* type() const override { solAssert(false, "Requested type of experimental solidity node."); } + + bool experimentalSolidityOnly() const override { return true; } + +private: + ASTPointer m_typeVariable; + std::vector> m_subNodes; +}; + +/// @} + } diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 2573015c2..fbd59508a 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -341,4 +341,12 @@ struct FunctionCallAnnotation: ExpressionAnnotation bool tryCall = false; }; +/// Experimental Solidity annotations. +/// Used to intergrate with name and type resolution. +/// @{ +struct TypeClassDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation +{ +}; +/// @} + } diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index da7f76936..41e791b00 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -1033,6 +1033,15 @@ void ASTJsonExporter::endVisit(EventDefinition const&) m_inEvent = false; } +bool ASTJsonExporter::visitNode(ASTNode const& _node) +{ + solAssert(false, _node.experimentalSolidityOnly() ? + "Attempt to export an AST of experimental solidity." : + "Attempt to export an AST that contains unexpected nodes." + ); + return false; +} + string ASTJsonExporter::location(VariableDeclaration::Location _location) { switch (_location) diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index 71d15ce0a..ff3b94fa2 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -130,6 +130,7 @@ public: void endVisit(EventDefinition const&) override; + bool visitNode(ASTNode const& _node) override; private: void setJsonNode( ASTNode const& _node, diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index ef03e6339..c38c270b8 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -109,6 +109,10 @@ public: virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); } virtual bool visit(Literal& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation& _node) { return visitNode(_node); } + /// Experimental Solidity nodes + /// @{ + virtual bool visit(TypeClassDefinition& _node) { return visitNode(_node); } + /// @} virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); } virtual void endVisit(PragmaDirective& _node) { endVisitNode(_node); } @@ -165,6 +169,10 @@ public: virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); } virtual void endVisit(Literal& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); } + /// Experimental Solidity nodes + /// @{ + virtual void endVisit(TypeClassDefinition& _node) { endVisitNode(_node); } + /// @} protected: /// Generic function called by default for each node, to be overridden by derived classes @@ -243,6 +251,10 @@ public: virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); } virtual bool visit(Literal const& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation const& _node) { return visitNode(_node); } + /// Experimental Solidity nodes + /// @{ + virtual bool visit(TypeClassDefinition const& _node) { return visitNode(_node); } + /// @} virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); } virtual void endVisit(PragmaDirective const& _node) { endVisitNode(_node); } @@ -299,6 +311,10 @@ public: virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); } virtual void endVisit(Literal const& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); } + /// Experimental Solidity nodes + /// @{ + virtual void endVisit(TypeClassDefinition const& _node) { endVisitNode(_node); } + /// @} protected: /// Generic function called by default for each node, to be overridden by derived classes diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index 78dc0e5dd..fb9f17896 100644 --- a/libsolidity/ast/AST_accept.h +++ b/libsolidity/ast/AST_accept.h @@ -1024,4 +1024,31 @@ void Literal::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } +/// Experimental Solidity nodes +/// @{ +void TypeClassDefinition::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + { + m_typeVariable->accept(_visitor); + if (m_documentation) + m_documentation->accept(_visitor); + listAccept(m_subNodes, _visitor); + } + _visitor.endVisit(*this); +} + +void TypeClassDefinition::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + { + m_typeVariable->accept(_visitor); + if (m_documentation) + m_documentation->accept(_visitor); + listAccept(m_subNodes, _visitor); + } + _visitor.endVisit(*this); +} +/// @} + } diff --git a/libsolidity/ast/experimental/TypeSystem.cpp b/libsolidity/ast/experimental/TypeSystem.cpp index 1ebe333ec..d911b03f8 100644 --- a/libsolidity/ast/experimental/TypeSystem.cpp +++ b/libsolidity/ast/experimental/TypeSystem.cpp @@ -40,26 +40,52 @@ std::string TypeSystem::typeToString(Type const& _type) const return std::visit(util::GenericVisitor{ [&](TypeExpression const& _type) { std::stringstream stream; - if (!_type.arguments.empty()) - { - stream << "("; - for (auto type: _type.arguments | ranges::views::drop_last(1)) - stream << typeToString(type) << ", "; - stream << typeToString(_type.arguments.back()); - stream << ") "; - } - stream << std::visit(util::GenericVisitor{ + auto printTypeArguments = [&]() { + if (!_type.arguments.empty()) + { + stream << "("; + for (auto type: _type.arguments | ranges::views::drop_last(1)) + stream << typeToString(type) << ", "; + stream << typeToString(_type.arguments.back()); + stream << ") "; + } + }; + std::visit(util::GenericVisitor{ [&](Declaration const* _declaration) { - return _declaration->name(); + printTypeArguments(); + stream << _declaration->name(); }, - [&](BuiltinType _builtinType) -> string { - return builtinTypeName(_builtinType); + [&](BuiltinType _builtinType) { + switch (_builtinType) + { + case BuiltinType::Function: + solAssert(_type.arguments.size() == 2); + stream << fmt::format("{} -> {}", typeToString(_type.arguments.front()), typeToString(_type.arguments.back())); + break; + case BuiltinType::Unit: + solAssert(_type.arguments.empty()); + stream << "()"; + break; + case BuiltinType::Pair: + { + auto tupleTypes = TypeSystemHelpers{*this}.destTupleType(_type); + stream << "("; + for (auto type: tupleTypes | ranges::view::drop_last(1)) + stream << typeToString(type) << ", "; + stream << typeToString(tupleTypes.back()) << ")"; + break; + } + default: + printTypeArguments(); + stream << builtinTypeName(_builtinType); + break; + } } }, _type.constructor); return stream.str(); }, [](TypeVariable const& _type) { - return fmt::format("var[{}]", _type.index()); + return fmt::format("{}var{}", _type.generic() ? '?' : '\'', _type.index()); }, }, resolve(_type)); } @@ -180,6 +206,41 @@ experimental::Type TypeSystemHelpers::tupleType(vector _elements) const return result; } +vector TypeSystemHelpers::destTupleType(Type _tupleType) const +{ + auto [constructor, arguments] = destTypeExpression(_tupleType); + if (auto const* builtinType = get_if(&constructor)) + { + if (*builtinType == BuiltinType::Unit) + return {}; + else if (*builtinType != BuiltinType::Pair) + return {_tupleType}; + } + else + return {_tupleType}; + solAssert(arguments.size() == 2); + + vector result; + result.emplace_back(arguments.front()); + Type tail = arguments.back(); + while(true) + { + auto const* tailTypeExpression = get_if(&tail); + if (!tailTypeExpression) + break; + + auto [tailConstructor, tailArguments] = destTypeExpression(tail); + auto const* builtinType = get_if(&tailConstructor); + if(!builtinType || *builtinType != BuiltinType::Pair) + break; + solAssert(tailArguments.size() == 2); + result.emplace_back(tailArguments.front()); + tail = tailArguments.back(); + } + result.emplace_back(tail); + return result; +} + experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType, experimental::Type _resultType) const { return typeSystem.builtinType(BuiltinType::Function, {_argType, _resultType}); @@ -198,7 +259,6 @@ tuple> TypeSystemHelpers }, _functionType); } - tuple TypeSystemHelpers::destFunctionType(Type _functionType) const { auto [constructor, arguments] = destTypeExpression(_functionType); diff --git a/libsolidity/ast/experimental/TypeSystem.h b/libsolidity/ast/experimental/TypeSystem.h index b61ec18ab..d56efcf6a 100644 --- a/libsolidity/ast/experimental/TypeSystem.h +++ b/libsolidity/ast/experimental/TypeSystem.h @@ -46,7 +46,8 @@ enum class BuiltinType Function, Unit, Pair, - Word + Word, + Integer }; struct TypeExpression @@ -104,10 +105,11 @@ private: struct TypeSystemHelpers { - TypeSystem& typeSystem; - Type tupleType(std::vector _elements) const; - Type functionType(Type _argType, Type _resultType) const; + TypeSystem const& typeSystem; std::tuple> destTypeExpression(Type _functionType) const; + Type tupleType(std::vector _elements) const; + std::vector destTupleType(Type _tupleType) const; + Type functionType(Type _argType, Type _resultType) const; std::tuple destFunctionType(Type _functionType) const; }; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 86c7ccc3d..3d0ddc662 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -134,6 +134,10 @@ ASTPointer Parser::parse(CharStream& _charStream) case Token::Function: nodes.push_back(parseFunctionDefinition(true)); break; + case Token::Class: + solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit); + nodes.push_back(parseTypeClassDefinition()); + break; default: if ( // Workaround because `error` is not a keyword. @@ -623,7 +627,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari return result; } -ASTPointer Parser::parseFunctionDefinition(bool _freeFunction) +ASTPointer Parser::parseFunctionDefinition(bool _freeFunction, bool _allowBody) { RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); @@ -673,7 +677,9 @@ ASTPointer Parser::parseFunctionDefinition(bool _freeFunction) ASTPointer block; nodeFactory.markEndPosition(); - if (m_scanner->currentToken() == Token::Semicolon) + if (!_allowBody) + expectToken(Token::Semicolon); + else if (m_scanner->currentToken() == Token::Semicolon) advance(); else { @@ -1270,6 +1276,13 @@ ASTPointer Parser::parseParameterList( vector> parameters; VarDeclParserOptions options(_options); options.allowEmptyName = true; + if (m_experimentalSolidityEnabledInCurrentSourceUnit && m_scanner->currentToken() == Token::Identifier) + { + // Parses unary parameter lists without parentheses. TODO: is this a good idea in all cases? Including arguments? + parameters = {parsePostfixVariableDeclaration()}; + nodeFactory.setEndPositionFromNode(parameters.front()); + return nodeFactory.createNode(parameters); + } expectToken(Token::LParen); auto parseSingleVariableDeclaration = [&]() { if (m_experimentalSolidityEnabledInCurrentSourceUnit) @@ -1717,6 +1730,54 @@ ASTPointer Parser::parsePostfixVariableDeclaration() ); } +ASTPointer Parser::parseTypeClassDefinition() +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + + vector> subNodes; + + ASTPointer const documentation = parseStructuredDocumentation(); + + expectToken(Token::Class); + // TODO: parseTypeVariable()? parseTypeVariableDeclaration()? + ASTPointer typeVariable; + { + ASTNodeFactory nodeFactory(*this); + nodeFactory.markEndPosition(); + auto [identifier, nameLocation] = expectIdentifierWithLocation(); + typeVariable = nodeFactory.createNode( + nullptr, + identifier, + nameLocation, + nullptr, + Visibility::Default, + nullptr + ); + } + expectToken(Token::Colon); + auto [name, nameLocation] = expectIdentifierWithLocation(); + expectToken(Token::LBrace); + while (true) + { + Token currentTokenValue = m_scanner->currentToken(); + if (currentTokenValue == Token::RBrace) + break; + expectToken(Token::Function, false); + subNodes.push_back(parseFunctionDefinition(false, false)); + } + nodeFactory.markEndPosition(); + expectToken(Token::RBrace); + + return nodeFactory.createNode( + typeVariable, + name, + nameLocation, + documentation, + subNodes + ); +} + ASTPointer Parser::parseSimpleStatement(ASTPointer const& _docString) { RecursionGuard recursionGuard(*this); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index f607bcbc0..cd5af9b3b 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -102,7 +102,7 @@ private: ASTPointer parseOverrideSpecifier(); StateMutability parseStateMutability(); FunctionHeaderParserResult parseFunctionHeader(bool _isStateVariable); - ASTPointer parseFunctionDefinition(bool _freeFunction = false); + ASTPointer parseFunctionDefinition(bool _freeFunction = false, bool _allowBody = true); ASTPointer parseStructDefinition(); ASTPointer parseEnumDefinition(); ASTPointer parseUserDefinedValueTypeDefinition(); @@ -176,6 +176,7 @@ private: ASTPointer const& _docString ); ASTPointer parsePostfixVariableDeclaration(); + ASTPointer parseTypeClassDefinition(); ///@} ///@{ diff --git a/test/libsolidity/semanticTests/experimental/stub.sol b/test/libsolidity/semanticTests/experimental/stub.sol index d94b9a420..3998fbf7c 100644 --- a/test/libsolidity/semanticTests/experimental/stub.sol +++ b/test/libsolidity/semanticTests/experimental/stub.sol @@ -1,10 +1,10 @@ pragma experimental solidity; -/* -class a:StackType { - function stackSize() -> (integer); -} +class a:StackType { + function stackSize() -> x:integer; +} +/* instantiate uint256 : StackType { function stackSize() -> (integer) { return 1; @@ -12,7 +12,7 @@ instantiate uint256 : StackType { } */ -function f(a) -> (b) { +function f(a) -> b { return a; }