mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
tmp
This commit is contained in:
parent
1c1110f734
commit
3286d1cec2
@ -273,6 +273,7 @@ namespace solidity::langutil
|
|||||||
K(Class, "class", 0) \
|
K(Class, "class", 0) \
|
||||||
K(Instantiation, "instantiation", 0) \
|
K(Instantiation, "instantiation", 0) \
|
||||||
K(Word, "word", 0) \
|
K(Word, "word", 0) \
|
||||||
|
K(Integer, "integer", 0) \
|
||||||
K(Void, "void", 0) \
|
K(Void, "void", 0) \
|
||||||
K(StaticAssert, "static_assert", 0) \
|
K(StaticAssert, "static_assert", 0) \
|
||||||
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
|
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
|
||||||
@ -301,7 +302,7 @@ namespace TokenTraits
|
|||||||
// Predicates
|
// Predicates
|
||||||
constexpr bool isElementaryTypeName(Token tok)
|
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 isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; }
|
||||||
constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; }
|
constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; }
|
||||||
|
@ -451,7 +451,9 @@ bool SyntaxChecker::visit(UsingForDirective const& _usingFor)
|
|||||||
|
|
||||||
bool SyntaxChecker::visit(FunctionDefinition const& _function)
|
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())
|
if (!_function.isFree() && !_function.isConstructor() && _function.noVisibilitySpecified())
|
||||||
{
|
{
|
||||||
@ -506,3 +508,13 @@ bool SyntaxChecker::visit(StructDefinition const& _struct)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SyntaxChecker::visitNode(ASTNode const& _node)
|
||||||
|
{
|
||||||
|
if (_node.experimentalSolidityOnly())
|
||||||
|
{
|
||||||
|
solAssert(m_sourceUnit);
|
||||||
|
solAssert(m_sourceUnit->experimentalSolidity());
|
||||||
|
}
|
||||||
|
return ASTConstVisitor::visitNode(_node);
|
||||||
|
}
|
||||||
|
@ -97,6 +97,8 @@ private:
|
|||||||
bool visit(StructDefinition const& _struct) override;
|
bool visit(StructDefinition const& _struct) override;
|
||||||
bool visit(Literal const& _literal) override;
|
bool visit(Literal const& _literal) override;
|
||||||
|
|
||||||
|
bool visitNode(ASTNode const&) override;
|
||||||
|
|
||||||
langutil::ErrorReporter& m_errorReporter;
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
|
|
||||||
bool m_useYulOptimizer = false;
|
bool m_useYulOptimizer = false;
|
||||||
|
@ -32,6 +32,7 @@ bool SyntaxRestrictor::check(ASTNode const& _astRoot)
|
|||||||
|
|
||||||
bool SyntaxRestrictor::visitNode(ASTNode const& _node)
|
bool SyntaxRestrictor::visitNode(ASTNode const& _node)
|
||||||
{
|
{
|
||||||
|
if (!_node.experimentalSolidityOnly())
|
||||||
m_errorReporter.syntaxError(0000_error, _node.location(), "Unsupported AST node.");
|
m_errorReporter.syntaxError(0000_error, _node.location(), "Unsupported AST node.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,13 @@ m_errorReporter(_analysis.errorReporter())
|
|||||||
{BuiltinType::Function, "fun", 2},
|
{BuiltinType::Function, "fun", 2},
|
||||||
{BuiltinType::Unit, "unit", 0},
|
{BuiltinType::Unit, "unit", 0},
|
||||||
{BuiltinType::Pair, "pair", 2},
|
{BuiltinType::Pair, "pair", 2},
|
||||||
{BuiltinType::Word, "word", 0}
|
{BuiltinType::Word, "word", 0},
|
||||||
|
{BuiltinType::Integer, "integer", 0}
|
||||||
})
|
})
|
||||||
m_typeSystem.declareBuiltinType(type, name, arity);
|
m_typeSystem.declareBuiltinType(type, name, arity);
|
||||||
m_voidType = m_typeSystem.builtinType(BuiltinType::Void, {});
|
m_voidType = m_typeSystem.builtinType(BuiltinType::Void, {});
|
||||||
m_wordType = m_typeSystem.builtinType(BuiltinType::Word, {});
|
m_wordType = m_typeSystem.builtinType(BuiltinType::Word, {});
|
||||||
|
m_integerType = m_typeSystem.builtinType(BuiltinType::Integer, {});
|
||||||
|
|
||||||
m_typeAnnotations.resize(_analysis.maxAstId());
|
m_typeAnnotations.resize(_analysis.maxAstId());
|
||||||
}
|
}
|
||||||
@ -84,6 +86,7 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
|
|||||||
|
|
||||||
m_currentFunctionType = functionType;
|
m_currentFunctionType = functionType;
|
||||||
|
|
||||||
|
if (_functionDefinition.isImplemented())
|
||||||
_functionDefinition.body().accept(*this);
|
_functionDefinition.body().accept(*this);
|
||||||
|
|
||||||
functionAnnotation.type = m_typeSystem.fresh(
|
functionAnnotation.type = m_typeSystem.fresh(
|
||||||
@ -143,13 +146,32 @@ experimental::Type TypeInference::fromTypeName(TypeName const& _typeName)
|
|||||||
return m_wordType;
|
return m_wordType;
|
||||||
case Token::Void:
|
case Token::Void:
|
||||||
return m_voidType;
|
return m_voidType;
|
||||||
|
case Token::Integer:
|
||||||
|
return m_integerType;
|
||||||
default:
|
default:
|
||||||
m_errorReporter.typeError(0000_error, _typeName.location(), "Only elementary types are supported.");
|
m_errorReporter.typeError(0000_error, _typeName.location(), "Only elementary types are supported.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (auto const* userDefinedTypeName = dynamic_cast<UserDefinedTypeName const*>(&_typeName))
|
||||||
|
{
|
||||||
|
auto const* declaration = userDefinedTypeName->pathNode().annotation().referencedDeclaration;
|
||||||
|
solAssert(declaration);
|
||||||
|
if (auto const* variableDeclaration = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||||
|
{
|
||||||
|
if (auto const* typeClass = dynamic_cast<TypeClassDefinition const*>(variableDeclaration->scope()))
|
||||||
|
{
|
||||||
|
(void)typeClass;
|
||||||
|
m_errorReporter.typeError(0000_error, _typeName.location(), "Using type class type variables not yet implemented.");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_errorReporter.typeError(0000_error, _typeName.location(), "Only elementary types are supported.");
|
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(), "Unsupported type name.");
|
||||||
return m_typeSystem.freshTypeVariable(false);
|
return m_typeSystem.freshTypeVariable(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,8 @@ private:
|
|||||||
bool visit(Return const&) override { return true; }
|
bool visit(Return const&) override { return true; }
|
||||||
void endVisit(Return const& _return) override;
|
void endVisit(Return const& _return) override;
|
||||||
|
|
||||||
|
bool visit(TypeClassDefinition const&) override { return true; }
|
||||||
|
|
||||||
bool visitNode(ASTNode const& _node) override;
|
bool visitNode(ASTNode const& _node) override;
|
||||||
|
|
||||||
Type fromTypeName(TypeName const& _typeName);
|
Type fromTypeName(TypeName const& _typeName);
|
||||||
@ -65,6 +67,7 @@ private:
|
|||||||
TypeSystem m_typeSystem;
|
TypeSystem m_typeSystem;
|
||||||
Type m_voidType;
|
Type m_voidType;
|
||||||
Type m_wordType;
|
Type m_wordType;
|
||||||
|
Type m_integerType;
|
||||||
std::optional<Type> m_currentFunctionType;
|
std::optional<Type> m_currentFunctionType;
|
||||||
|
|
||||||
struct TypeAnnotation
|
struct TypeAnnotation
|
||||||
|
@ -1058,3 +1058,11 @@ TryCatchClause const* TryStatement::errorClause() const {
|
|||||||
TryCatchClause const* TryStatement::fallbackClause() const {
|
TryCatchClause const* TryStatement::fallbackClause() const {
|
||||||
return findClause(m_clauses);
|
return findClause(m_clauses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Experimental Solidity nodes
|
||||||
|
/// @{
|
||||||
|
TypeClassDefinitionAnnotation& TypeClassDefinition::annotation() const
|
||||||
|
{
|
||||||
|
return initAnnotation<TypeClassDefinitionAnnotation>();
|
||||||
|
}
|
||||||
|
/// @}
|
@ -121,6 +121,8 @@ public:
|
|||||||
bool operator!=(ASTNode const& _other) const { return !operator==(_other); }
|
bool operator!=(ASTNode const& _other) const { return !operator==(_other); }
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
virtual bool experimentalSolidityOnly() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t const m_id = 0;
|
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<VariableDeclaration> _typeVariable,
|
||||||
|
ASTPointer<ASTString> const& _name,
|
||||||
|
SourceLocation _nameLocation,
|
||||||
|
ASTPointer<StructuredDocumentation> const& _documentation,
|
||||||
|
std::vector<ASTPointer<ASTNode>> _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<ASTPointer<ASTNode>> 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<VariableDeclaration> m_typeVariable;
|
||||||
|
std::vector<ASTPointer<ASTNode>> m_subNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -341,4 +341,12 @@ struct FunctionCallAnnotation: ExpressionAnnotation
|
|||||||
bool tryCall = false;
|
bool tryCall = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Experimental Solidity annotations.
|
||||||
|
/// Used to intergrate with name and type resolution.
|
||||||
|
/// @{
|
||||||
|
struct TypeClassDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
|
{
|
||||||
|
};
|
||||||
|
/// @}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1033,6 +1033,15 @@ void ASTJsonExporter::endVisit(EventDefinition const&)
|
|||||||
m_inEvent = false;
|
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)
|
string ASTJsonExporter::location(VariableDeclaration::Location _location)
|
||||||
{
|
{
|
||||||
switch (_location)
|
switch (_location)
|
||||||
|
@ -130,6 +130,7 @@ public:
|
|||||||
|
|
||||||
void endVisit(EventDefinition const&) override;
|
void endVisit(EventDefinition const&) override;
|
||||||
|
|
||||||
|
bool visitNode(ASTNode const& _node) override;
|
||||||
private:
|
private:
|
||||||
void setJsonNode(
|
void setJsonNode(
|
||||||
ASTNode const& _node,
|
ASTNode const& _node,
|
||||||
|
@ -109,6 +109,10 @@ public:
|
|||||||
virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); }
|
virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Literal& _node) { return visitNode(_node); }
|
virtual bool visit(Literal& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(StructuredDocumentation& _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(SourceUnit& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(PragmaDirective& _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(ElementaryTypeNameExpression& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Literal& _node) { endVisitNode(_node); }
|
virtual void endVisit(Literal& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); }
|
virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); }
|
||||||
|
/// Experimental Solidity nodes
|
||||||
|
/// @{
|
||||||
|
virtual void endVisit(TypeClassDefinition& _node) { endVisitNode(_node); }
|
||||||
|
/// @}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Generic function called by default for each node, to be overridden by derived classes
|
/// 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(ElementaryTypeNameExpression const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Literal const& _node) { return visitNode(_node); }
|
virtual bool visit(Literal const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(StructuredDocumentation 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(SourceUnit const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(PragmaDirective 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(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Literal const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Literal const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); }
|
virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); }
|
||||||
|
/// Experimental Solidity nodes
|
||||||
|
/// @{
|
||||||
|
virtual void endVisit(TypeClassDefinition const& _node) { endVisitNode(_node); }
|
||||||
|
/// @}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Generic function called by default for each node, to be overridden by derived classes
|
/// Generic function called by default for each node, to be overridden by derived classes
|
||||||
|
@ -1024,4 +1024,31 @@ void Literal::accept(ASTConstVisitor& _visitor) const
|
|||||||
_visitor.endVisit(*this);
|
_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);
|
||||||
|
}
|
||||||
|
/// @}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ std::string TypeSystem::typeToString(Type const& _type) const
|
|||||||
return std::visit(util::GenericVisitor{
|
return std::visit(util::GenericVisitor{
|
||||||
[&](TypeExpression const& _type) {
|
[&](TypeExpression const& _type) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
auto printTypeArguments = [&]() {
|
||||||
if (!_type.arguments.empty())
|
if (!_type.arguments.empty())
|
||||||
{
|
{
|
||||||
stream << "(";
|
stream << "(";
|
||||||
@ -48,18 +49,43 @@ std::string TypeSystem::typeToString(Type const& _type) const
|
|||||||
stream << typeToString(_type.arguments.back());
|
stream << typeToString(_type.arguments.back());
|
||||||
stream << ") ";
|
stream << ") ";
|
||||||
}
|
}
|
||||||
stream << std::visit(util::GenericVisitor{
|
};
|
||||||
|
std::visit(util::GenericVisitor{
|
||||||
[&](Declaration const* _declaration) {
|
[&](Declaration const* _declaration) {
|
||||||
return _declaration->name();
|
printTypeArguments();
|
||||||
|
stream << _declaration->name();
|
||||||
},
|
},
|
||||||
[&](BuiltinType _builtinType) -> string {
|
[&](BuiltinType _builtinType) {
|
||||||
return builtinTypeName(_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);
|
}, _type.constructor);
|
||||||
return stream.str();
|
return stream.str();
|
||||||
},
|
},
|
||||||
[](TypeVariable const& _type) {
|
[](TypeVariable const& _type) {
|
||||||
return fmt::format("var[{}]", _type.index());
|
return fmt::format("{}var{}", _type.generic() ? '?' : '\'', _type.index());
|
||||||
},
|
},
|
||||||
}, resolve(_type));
|
}, resolve(_type));
|
||||||
}
|
}
|
||||||
@ -180,6 +206,41 @@ experimental::Type TypeSystemHelpers::tupleType(vector<Type> _elements) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) const
|
||||||
|
{
|
||||||
|
auto [constructor, arguments] = destTypeExpression(_tupleType);
|
||||||
|
if (auto const* builtinType = get_if<BuiltinType>(&constructor))
|
||||||
|
{
|
||||||
|
if (*builtinType == BuiltinType::Unit)
|
||||||
|
return {};
|
||||||
|
else if (*builtinType != BuiltinType::Pair)
|
||||||
|
return {_tupleType};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return {_tupleType};
|
||||||
|
solAssert(arguments.size() == 2);
|
||||||
|
|
||||||
|
vector<Type> result;
|
||||||
|
result.emplace_back(arguments.front());
|
||||||
|
Type tail = arguments.back();
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
auto const* tailTypeExpression = get_if<TypeExpression>(&tail);
|
||||||
|
if (!tailTypeExpression)
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto [tailConstructor, tailArguments] = destTypeExpression(tail);
|
||||||
|
auto const* builtinType = get_if<BuiltinType>(&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
|
experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType, experimental::Type _resultType) const
|
||||||
{
|
{
|
||||||
return typeSystem.builtinType(BuiltinType::Function, {_argType, _resultType});
|
return typeSystem.builtinType(BuiltinType::Function, {_argType, _resultType});
|
||||||
@ -198,7 +259,6 @@ tuple<TypeExpression::Constructor, vector<experimental::Type>> TypeSystemHelpers
|
|||||||
}, _functionType);
|
}, _functionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionType(Type _functionType) const
|
tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionType(Type _functionType) const
|
||||||
{
|
{
|
||||||
auto [constructor, arguments] = destTypeExpression(_functionType);
|
auto [constructor, arguments] = destTypeExpression(_functionType);
|
||||||
|
@ -46,7 +46,8 @@ enum class BuiltinType
|
|||||||
Function,
|
Function,
|
||||||
Unit,
|
Unit,
|
||||||
Pair,
|
Pair,
|
||||||
Word
|
Word,
|
||||||
|
Integer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeExpression
|
struct TypeExpression
|
||||||
@ -104,10 +105,11 @@ private:
|
|||||||
|
|
||||||
struct TypeSystemHelpers
|
struct TypeSystemHelpers
|
||||||
{
|
{
|
||||||
TypeSystem& typeSystem;
|
TypeSystem const& typeSystem;
|
||||||
Type tupleType(std::vector<Type> _elements) const;
|
|
||||||
Type functionType(Type _argType, Type _resultType) const;
|
|
||||||
std::tuple<TypeExpression::Constructor, std::vector<Type>> destTypeExpression(Type _functionType) const;
|
std::tuple<TypeExpression::Constructor, std::vector<Type>> destTypeExpression(Type _functionType) const;
|
||||||
|
Type tupleType(std::vector<Type> _elements) const;
|
||||||
|
std::vector<Type> destTupleType(Type _tupleType) const;
|
||||||
|
Type functionType(Type _argType, Type _resultType) const;
|
||||||
std::tuple<Type, Type> destFunctionType(Type _functionType) const;
|
std::tuple<Type, Type> destFunctionType(Type _functionType) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -134,6 +134,10 @@ ASTPointer<SourceUnit> Parser::parse(CharStream& _charStream)
|
|||||||
case Token::Function:
|
case Token::Function:
|
||||||
nodes.push_back(parseFunctionDefinition(true));
|
nodes.push_back(parseFunctionDefinition(true));
|
||||||
break;
|
break;
|
||||||
|
case Token::Class:
|
||||||
|
solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
|
||||||
|
nodes.push_back(parseTypeClassDefinition());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (
|
if (
|
||||||
// Workaround because `error` is not a keyword.
|
// Workaround because `error` is not a keyword.
|
||||||
@ -623,7 +627,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction)
|
ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction, bool _allowBody)
|
||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
@ -673,7 +677,9 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction)
|
|||||||
|
|
||||||
ASTPointer<Block> block;
|
ASTPointer<Block> block;
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
if (m_scanner->currentToken() == Token::Semicolon)
|
if (!_allowBody)
|
||||||
|
expectToken(Token::Semicolon);
|
||||||
|
else if (m_scanner->currentToken() == Token::Semicolon)
|
||||||
advance();
|
advance();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1270,6 +1276,13 @@ ASTPointer<ParameterList> Parser::parseParameterList(
|
|||||||
vector<ASTPointer<VariableDeclaration>> parameters;
|
vector<ASTPointer<VariableDeclaration>> parameters;
|
||||||
VarDeclParserOptions options(_options);
|
VarDeclParserOptions options(_options);
|
||||||
options.allowEmptyName = true;
|
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<ParameterList>(parameters);
|
||||||
|
}
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
auto parseSingleVariableDeclaration = [&]() {
|
auto parseSingleVariableDeclaration = [&]() {
|
||||||
if (m_experimentalSolidityEnabledInCurrentSourceUnit)
|
if (m_experimentalSolidityEnabledInCurrentSourceUnit)
|
||||||
@ -1717,6 +1730,54 @@ ASTPointer<VariableDeclaration> Parser::parsePostfixVariableDeclaration()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPointer<TypeClassDefinition> Parser::parseTypeClassDefinition()
|
||||||
|
{
|
||||||
|
RecursionGuard recursionGuard(*this);
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
|
||||||
|
vector<ASTPointer<ASTNode>> subNodes;
|
||||||
|
|
||||||
|
ASTPointer<StructuredDocumentation> const documentation = parseStructuredDocumentation();
|
||||||
|
|
||||||
|
expectToken(Token::Class);
|
||||||
|
// TODO: parseTypeVariable()? parseTypeVariableDeclaration()?
|
||||||
|
ASTPointer<VariableDeclaration> typeVariable;
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
auto [identifier, nameLocation] = expectIdentifierWithLocation();
|
||||||
|
typeVariable = nodeFactory.createNode<VariableDeclaration>(
|
||||||
|
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<TypeClassDefinition>(
|
||||||
|
typeVariable,
|
||||||
|
name,
|
||||||
|
nameLocation,
|
||||||
|
documentation,
|
||||||
|
subNodes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
|
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
|
||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
|
@ -102,7 +102,7 @@ private:
|
|||||||
ASTPointer<OverrideSpecifier> parseOverrideSpecifier();
|
ASTPointer<OverrideSpecifier> parseOverrideSpecifier();
|
||||||
StateMutability parseStateMutability();
|
StateMutability parseStateMutability();
|
||||||
FunctionHeaderParserResult parseFunctionHeader(bool _isStateVariable);
|
FunctionHeaderParserResult parseFunctionHeader(bool _isStateVariable);
|
||||||
ASTPointer<ASTNode> parseFunctionDefinition(bool _freeFunction = false);
|
ASTPointer<ASTNode> parseFunctionDefinition(bool _freeFunction = false, bool _allowBody = true);
|
||||||
ASTPointer<StructDefinition> parseStructDefinition();
|
ASTPointer<StructDefinition> parseStructDefinition();
|
||||||
ASTPointer<EnumDefinition> parseEnumDefinition();
|
ASTPointer<EnumDefinition> parseEnumDefinition();
|
||||||
ASTPointer<UserDefinedValueTypeDefinition> parseUserDefinedValueTypeDefinition();
|
ASTPointer<UserDefinedValueTypeDefinition> parseUserDefinedValueTypeDefinition();
|
||||||
@ -176,6 +176,7 @@ private:
|
|||||||
ASTPointer<ASTString> const& _docString
|
ASTPointer<ASTString> const& _docString
|
||||||
);
|
);
|
||||||
ASTPointer<VariableDeclaration> parsePostfixVariableDeclaration();
|
ASTPointer<VariableDeclaration> parsePostfixVariableDeclaration();
|
||||||
|
ASTPointer<TypeClassDefinition> parseTypeClassDefinition();
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
///@{
|
///@{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
pragma experimental solidity;
|
pragma experimental solidity;
|
||||||
|
|
||||||
/*
|
|
||||||
class a:StackType {
|
|
||||||
function stackSize() -> (integer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
class a:StackType {
|
||||||
|
function stackSize() -> x:integer;
|
||||||
|
}
|
||||||
|
/*
|
||||||
instantiate uint256 : StackType {
|
instantiate uint256 : StackType {
|
||||||
function stackSize() -> (integer) {
|
function stackSize() -> (integer) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -12,7 +12,7 @@ instantiate uint256 : StackType {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function f(a) -> (b) {
|
function f(a) -> b {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user