This commit is contained in:
Daniel Kirchner 2023-06-20 22:26:52 +02:00
parent 3249979969
commit 1c1110f734
7 changed files with 59 additions and 7 deletions

View File

@ -270,6 +270,8 @@ namespace solidity::langutil
\ \
T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \ T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \
/* Experimental Solidity specific keywords. */ \ /* Experimental Solidity specific keywords. */ \
K(Class, "class", 0) \
K(Instantiation, "instantiation", 0) \
K(Word, "word", 0) \ K(Word, "word", 0) \
K(Void, "void", 0) \ K(Void, "void", 0) \
K(StaticAssert, "static_assert", 0) \ K(StaticAssert, "static_assert", 0) \
@ -336,7 +338,7 @@ namespace TokenTraits
{ {
return tok == Token::Assembly || tok == Token::Contract || tok == Token::External || tok == Token::Fallback || return tok == Token::Assembly || tok == Token::Contract || tok == Token::External || tok == Token::Fallback ||
tok == Token::Pragma || tok == Token::Import || tok == Token::As || tok == Token::Function || tok == Token::Let || tok == Token::Pragma || tok == Token::Import || tok == Token::As || tok == Token::Function || tok == Token::Let ||
(tok > Token::NonExperimentalEnd && tok < Token::ExperimentalEnd); tok == Token::Return || (tok > Token::NonExperimentalEnd && tok < Token::ExperimentalEnd);
} }
constexpr bool isExperimentalSolidityOnlyKeyword(Token tok) constexpr bool isExperimentalSolidityOnlyKeyword(Token tok)
{ {

View File

@ -52,6 +52,7 @@ private:
bool visit(VariableDeclaration const&) override; bool visit(VariableDeclaration const&) override;
bool visit(ElementaryTypeName const&) override { return true; } bool visit(ElementaryTypeName const&) override { return true; }
bool visit(ParameterList const&) override { return true; } bool visit(ParameterList const&) override { return true; }
bool visit(Return const&) override { return true; }
langutil::ErrorReporter& m_errorReporter; langutil::ErrorReporter& m_errorReporter;
}; };

View File

@ -58,6 +58,7 @@ bool TypeInference::analyze(SourceUnit const& _sourceUnit)
bool TypeInference::visit(FunctionDefinition const& _functionDefinition) bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
{ {
ScopedSaveAndRestore signatureRestore(m_currentFunctionType, nullopt);
auto& functionAnnotation = annotation(_functionDefinition); auto& functionAnnotation = annotation(_functionDefinition);
if (functionAnnotation.type) if (functionAnnotation.type)
return false; return false;
@ -66,8 +67,6 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
if (_functionDefinition.returnParameterList()) if (_functionDefinition.returnParameterList())
_functionDefinition.returnParameterList()->accept(*this); _functionDefinition.returnParameterList()->accept(*this);
_functionDefinition.body().accept(*this);
auto typeFromParameterList = [&](ParameterList const* _list) { auto typeFromParameterList = [&](ParameterList const* _list) {
if (!_list) if (!_list)
return m_typeSystem.builtinType(BuiltinType::Unit, {}); return m_typeSystem.builtinType(BuiltinType::Unit, {});
@ -78,11 +77,17 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
}) | ranges::to<std::vector<Type>>); }) | ranges::to<std::vector<Type>>);
}; };
Type argType = typeFromParameterList(&_functionDefinition.parameterList()); Type functionType = TypeSystemHelpers{m_typeSystem}.functionType(
Type resultType = typeFromParameterList(_functionDefinition.returnParameterList().get()); typeFromParameterList(&_functionDefinition.parameterList()),
typeFromParameterList(_functionDefinition.returnParameterList().get())
);
m_currentFunctionType = functionType;
_functionDefinition.body().accept(*this);
functionAnnotation.type = m_typeSystem.fresh( functionAnnotation.type = m_typeSystem.fresh(
TypeSystemHelpers{m_typeSystem}.functionType(argType, resultType), functionType,
true true
); );
@ -91,6 +96,18 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
return false; return false;
} }
void TypeInference::endVisit(Return const& _return)
{
solAssert(m_currentFunctionType);
if (_return.expression())
{
auto& returnExpressionAnnotation = annotation(*_return.expression());
solAssert(returnExpressionAnnotation.type);
Type functionReturnType = get<1>(TypeSystemHelpers{m_typeSystem}.destFunctionType(*m_currentFunctionType));
unify(functionReturnType, *returnExpressionAnnotation.type);
}
}
bool TypeInference::visit(ParameterList const&) bool TypeInference::visit(ParameterList const&)
{ {
return true; return true;

View File

@ -54,6 +54,8 @@ private:
bool visit(Identifier const&) override; bool visit(Identifier const&) override;
bool visit(FunctionCall const& _functionCall) override; bool visit(FunctionCall const& _functionCall) override;
void endVisit(FunctionCall const& _functionCall) override; void endVisit(FunctionCall const& _functionCall) override;
bool visit(Return const&) override { return true; }
void endVisit(Return const& _return) override;
bool visitNode(ASTNode const& _node) override; bool visitNode(ASTNode const& _node) override;
@ -63,6 +65,7 @@ private:
TypeSystem m_typeSystem; TypeSystem m_typeSystem;
Type m_voidType; Type m_voidType;
Type m_wordType; Type m_wordType;
std::optional<Type> m_currentFunctionType;
struct TypeAnnotation struct TypeAnnotation
{ {

View File

@ -134,6 +134,21 @@ bool IRGeneratorForStatements::visit(Identifier const& _identifier)
return false; return false;
} }
void IRGeneratorForStatements::endVisit(Return const& _return)
{
if (Expression const* value = _return.expression())
{
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
_return.annotation().functionReturnParameters->parameters();
solAssert(returnParameters.size() == 1, "Returning tuples not yet supported.");
m_code << IRNames::localVariable(*returnParameters.front()) << " := " << IRNames::localVariable(*value) << "\n";
}
_return.annotation().functionReturnParameters;
m_code << "leave\n";
}
bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall) bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
{ {
for(auto arg: _functionCall.arguments()) for(auto arg: _functionCall.arguments())

View File

@ -41,6 +41,8 @@ private:
bool visit(FunctionCall const&) override; bool visit(FunctionCall const&) override;
bool visit(InlineAssembly const& _inlineAssembly) override; bool visit(InlineAssembly const& _inlineAssembly) override;
bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override; bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override;
bool visit(Return const&) override { return true; }
void endVisit(Return const& _return) override;
/// Default visit will reject all AST nodes that are not explicitly supported. /// Default visit will reject all AST nodes that are not explicitly supported.
bool visitNode(ASTNode const& _node) override; bool visitNode(ASTNode const& _node) override;
IRGenerationContext& m_context; IRGenerationContext& m_context;

View File

@ -1,7 +1,19 @@
pragma experimental solidity; pragma experimental solidity;
/*
class a:StackType {
function stackSize() -> (integer);
}
instantiate uint256 : StackType {
function stackSize() -> (integer) {
return 1;
}
}
*/
function f(a) -> (b) { function f(a) -> (b) {
b = a; return a;
} }
contract C { contract C {