mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
tmp
This commit is contained in:
parent
9120737f57
commit
f9b424418c
@ -158,7 +158,7 @@ bool ReferencesResolver::visit(Identifier const& _identifier)
|
||||
|
||||
bool ReferencesResolver::visit(FunctionDefinition const& _functionDefinition)
|
||||
{
|
||||
m_returnParameters.push_back(_functionDefinition.returnParameterList().get());
|
||||
m_functionDefinitions.push_back(&_functionDefinition);
|
||||
|
||||
if (_functionDefinition.documentation())
|
||||
resolveInheritDoc(*_functionDefinition.documentation(), _functionDefinition.annotation());
|
||||
@ -168,13 +168,13 @@ bool ReferencesResolver::visit(FunctionDefinition const& _functionDefinition)
|
||||
|
||||
void ReferencesResolver::endVisit(FunctionDefinition const&)
|
||||
{
|
||||
solAssert(!m_returnParameters.empty(), "");
|
||||
m_returnParameters.pop_back();
|
||||
solAssert(!m_functionDefinitions.empty(), "");
|
||||
m_functionDefinitions.pop_back();
|
||||
}
|
||||
|
||||
bool ReferencesResolver::visit(ModifierDefinition const& _modifierDefinition)
|
||||
{
|
||||
m_returnParameters.push_back(nullptr);
|
||||
m_functionDefinitions.push_back(nullptr);
|
||||
|
||||
if (_modifierDefinition.documentation())
|
||||
resolveInheritDoc(*_modifierDefinition.documentation(), _modifierDefinition.annotation());
|
||||
@ -184,8 +184,8 @@ bool ReferencesResolver::visit(ModifierDefinition const& _modifierDefinition)
|
||||
|
||||
void ReferencesResolver::endVisit(ModifierDefinition const&)
|
||||
{
|
||||
solAssert(!m_returnParameters.empty(), "");
|
||||
m_returnParameters.pop_back();
|
||||
solAssert(!m_functionDefinitions.empty(), "");
|
||||
m_functionDefinitions.pop_back();
|
||||
}
|
||||
|
||||
void ReferencesResolver::endVisit(IdentifierPath const& _path)
|
||||
@ -245,8 +245,9 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
|
||||
|
||||
bool ReferencesResolver::visit(Return const& _return)
|
||||
{
|
||||
solAssert(!m_returnParameters.empty(), "");
|
||||
_return.annotation().functionReturnParameters = m_returnParameters.back();
|
||||
solAssert(!m_functionDefinitions.empty(), "");
|
||||
_return.annotation().function = m_functionDefinitions.back();
|
||||
_return.annotation().functionReturnParameters = m_functionDefinitions.back() ? m_functionDefinitions.back()->returnParameterList().get() : nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,8 @@ private:
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
NameAndTypeResolver& m_resolver;
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
/// Stack of return parameters.
|
||||
std::vector<ParameterList const*> m_returnParameters;
|
||||
/// Stack of function definitions.
|
||||
std::vector<FunctionDefinition const*> m_functionDefinitions;
|
||||
bool const m_resolveInsideCode;
|
||||
|
||||
InlineAssemblyAnnotation* m_yulAnnotation = nullptr;
|
||||
|
@ -958,7 +958,8 @@ public:
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
std::vector<ASTPointer<ModifierInvocation>> _modifiers,
|
||||
ASTPointer<ParameterList> const& _returnParameters,
|
||||
ASTPointer<Block> const& _body
|
||||
ASTPointer<Block> const& _body,
|
||||
ASTPointer<Expression> const& _experimentalReturnExpression = {}
|
||||
):
|
||||
CallableDeclaration(_id, _location, _name, _nameLocation, _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
|
||||
StructurallyDocumented(_documentation),
|
||||
@ -967,10 +968,12 @@ public:
|
||||
m_free(_free),
|
||||
m_kind(_kind),
|
||||
m_functionModifiers(std::move(_modifiers)),
|
||||
m_body(_body)
|
||||
m_body(_body),
|
||||
m_experimentalReturnExpression(_experimentalReturnExpression)
|
||||
{
|
||||
solAssert(_kind == Token::Constructor || _kind == Token::Function || _kind == Token::Fallback || _kind == Token::Receive, "");
|
||||
solAssert(isOrdinary() == !name().empty(), "");
|
||||
// TODO: assert _returnParameters implies non-experimental _experimentalReturnExpression implies experimental
|
||||
}
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
@ -1028,12 +1031,15 @@ public:
|
||||
ContractDefinition const* _searchStart = nullptr
|
||||
) const override;
|
||||
|
||||
Expression const* experimentalReturnExpression() const { return m_experimentalReturnExpression.get(); }
|
||||
|
||||
private:
|
||||
StateMutability m_stateMutability;
|
||||
bool m_free;
|
||||
Token const m_kind;
|
||||
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
|
||||
ASTPointer<Block> m_body;
|
||||
ASTPointer<Expression> m_experimentalReturnExpression;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -244,6 +244,8 @@ struct ReturnAnnotation: StatementAnnotation
|
||||
{
|
||||
/// Reference to the return parameters of the function.
|
||||
ParameterList const* functionReturnParameters = nullptr;
|
||||
/// Reference to the function containing the return statement.
|
||||
FunctionDefinition const* function = nullptr;
|
||||
};
|
||||
|
||||
struct TypeNameAnnotation: ASTAnnotation
|
||||
|
@ -265,6 +265,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor)
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_returnParameters)
|
||||
m_returnParameters->accept(_visitor);
|
||||
if (m_experimentalReturnExpression)
|
||||
m_experimentalReturnExpression->accept(_visitor);
|
||||
listAccept(m_functionModifiers, _visitor);
|
||||
if (m_body)
|
||||
m_body->accept(_visitor);
|
||||
@ -283,6 +285,8 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_returnParameters)
|
||||
m_returnParameters->accept(_visitor);
|
||||
if (m_experimentalReturnExpression)
|
||||
m_experimentalReturnExpression->accept(_visitor);
|
||||
listAccept(m_functionModifiers, _visitor);
|
||||
if (m_body)
|
||||
m_body->accept(_visitor);
|
||||
|
@ -59,6 +59,7 @@ bool SyntaxRestrictor::visit(FunctionDefinition const& _functionDefinition)
|
||||
m_errorReporter.syntaxError(0000_error, _functionDefinition.location(), "Function may not have modifiers.");
|
||||
if (_functionDefinition.overrides())
|
||||
m_errorReporter.syntaxError(0000_error, _functionDefinition.location(), "Function may not have override specifiers.");
|
||||
solAssert(!_functionDefinition.returnParameterList());
|
||||
if (_functionDefinition.isFree())
|
||||
{
|
||||
if (_functionDefinition.stateMutability() != StateMutability::NonPayable)
|
||||
|
@ -68,13 +68,15 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
|
||||
ScopedSaveAndRestore signatureRestore(m_currentFunctionType, nullopt);
|
||||
|
||||
_functionDefinition.parameterList().accept(*this);
|
||||
if (_functionDefinition.returnParameterList())
|
||||
_functionDefinition.returnParameterList()->accept(*this);
|
||||
if (_functionDefinition.experimentalReturnExpression())
|
||||
{
|
||||
ScopedSaveAndRestore expressionContext{m_expressionContext, ExpressionContext::Type};
|
||||
_functionDefinition.experimentalReturnExpression()->accept(*this);
|
||||
}
|
||||
|
||||
auto getListType = [&](ParameterList const* _list) { return _list ? getType(*_list) : m_unitType; };
|
||||
Type functionType = TypeSystemHelpers{m_typeSystem}.functionType(
|
||||
getListType(&_functionDefinition.parameterList()),
|
||||
getListType(_functionDefinition.returnParameterList().get())
|
||||
getType(_functionDefinition.parameterList()),
|
||||
_functionDefinition.experimentalReturnExpression() ? getType(*_functionDefinition.experimentalReturnExpression()) : m_unitType
|
||||
);
|
||||
|
||||
m_currentFunctionType = functionType;
|
||||
|
@ -140,14 +140,15 @@ string IRGenerator::generate(FunctionDefinition const& _function, Type _type)
|
||||
if (!_function.parameters().empty())
|
||||
code << IRNames::localVariable(*_function.parameters().back());
|
||||
code << ")";
|
||||
if (_function.returnParameterList() && !_function.returnParameters().empty())
|
||||
if (_function.experimentalReturnExpression())
|
||||
{
|
||||
code << " -> ";
|
||||
if (_function.returnParameters().size() > 1)
|
||||
for (auto const& arg: _function.returnParameters() | ranges::views::drop_last(1))
|
||||
code << IRNames::localVariable(*arg) << ", ";
|
||||
if (!_function.returnParameters().empty())
|
||||
code << IRNames::localVariable(*_function.returnParameters().back());
|
||||
auto returnType = m_context.analysis.annotation<TypeInference>(*_function.experimentalReturnExpression()).type;
|
||||
solAssert(returnType);
|
||||
if (!m_env.typeEquals(*returnType, m_context.analysis.typeSystem().type(PrimitiveType::Unit, {})))
|
||||
{
|
||||
// TODO: destructure tuples.
|
||||
code << " -> " << IRNames::localVariable(*_function.experimentalReturnExpression()) << " ";
|
||||
}
|
||||
}
|
||||
code << "{\n";
|
||||
for (auto _statement: _function.body().statements())
|
||||
|
@ -161,11 +161,9 @@ 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";
|
||||
solAssert(_return.annotation().function, "Invalid return.");
|
||||
solAssert(_return.annotation().function->experimentalReturnExpression(), "Invalid return.");
|
||||
m_code << IRNames::localVariable(*_return.annotation().function->experimentalReturnExpression()) << " := " << IRNames::localVariable(*value) << "\n";
|
||||
}
|
||||
|
||||
m_code << "leave\n";
|
||||
|
@ -621,16 +621,25 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (
|
||||
m_scanner->currentToken() == (m_experimentalSolidityEnabledInCurrentSourceUnit ? Token::RightArrow : Token::Returns)
|
||||
)
|
||||
if (m_experimentalSolidityEnabledInCurrentSourceUnit)
|
||||
{
|
||||
bool const permitEmptyParameterList = m_experimentalSolidityEnabledInCurrentSourceUnit;
|
||||
advance();
|
||||
result.returnParameters = parseParameterList(options, permitEmptyParameterList);
|
||||
if (m_scanner->currentToken() == Token::RightArrow)
|
||||
{
|
||||
advance();
|
||||
result.experimentalReturnExpression = parseBinaryExpression();
|
||||
}
|
||||
}
|
||||
else
|
||||
result.returnParameters = createEmptyParameterList();
|
||||
{
|
||||
if (m_scanner->currentToken() == Token::Returns)
|
||||
{
|
||||
bool const permitEmptyParameterList = m_experimentalSolidityEnabledInCurrentSourceUnit;
|
||||
advance();
|
||||
result.returnParameters = parseParameterList(options, permitEmptyParameterList);
|
||||
}
|
||||
else
|
||||
result.returnParameters = createEmptyParameterList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -682,6 +691,11 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction, bool _al
|
||||
|
||||
FunctionHeaderParserResult header = parseFunctionHeader(false);
|
||||
|
||||
if (m_experimentalSolidityEnabledInCurrentSourceUnit)
|
||||
solAssert(!header.returnParameters);
|
||||
else
|
||||
solAssert(!header.experimentalReturnExpression);
|
||||
|
||||
ASTPointer<Block> block;
|
||||
nodeFactory.markEndPosition();
|
||||
if (!_allowBody)
|
||||
@ -706,7 +720,8 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction, bool _al
|
||||
header.parameters,
|
||||
header.modifiers,
|
||||
header.returnParameters,
|
||||
block
|
||||
block,
|
||||
header.experimentalReturnExpression
|
||||
);
|
||||
}
|
||||
|
||||
@ -1224,10 +1239,12 @@ ASTPointer<TypeName> Parser::parseTypeName()
|
||||
|
||||
ASTPointer<FunctionTypeName> Parser::parseFunctionType()
|
||||
{
|
||||
solAssert(!m_experimentalSolidityEnabledInCurrentSourceUnit);
|
||||
RecursionGuard recursionGuard(*this);
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
expectToken(Token::Function);
|
||||
FunctionHeaderParserResult header = parseFunctionHeader(true);
|
||||
solAssert(!header.experimentalReturnExpression);
|
||||
return nodeFactory.createNode<FunctionTypeName>(
|
||||
header.parameters,
|
||||
header.returnParameters,
|
||||
|
@ -77,6 +77,7 @@ private:
|
||||
Visibility visibility = Visibility::Default;
|
||||
StateMutability stateMutability = StateMutability::NonPayable;
|
||||
std::vector<ASTPointer<ModifierInvocation>> modifiers;
|
||||
ASTPointer<Expression> experimentalReturnExpression;
|
||||
};
|
||||
|
||||
/// Struct to share parsed function call arguments.
|
||||
|
@ -2,19 +2,8 @@ pragma experimental solidity;
|
||||
|
||||
type uint256 = word;
|
||||
|
||||
instantiation uint256: * {
|
||||
function mul(x, y) -> z {
|
||||
let a = uint256.rep(x);
|
||||
let b = uint256.rep(y);
|
||||
assembly {
|
||||
a := mul(a,b)
|
||||
}
|
||||
return uint256.abs(a);
|
||||
}
|
||||
}
|
||||
|
||||
instantiation uint256: + {
|
||||
function add(x, y) -> z {
|
||||
function add(x, y) -> uint256 {
|
||||
let a = uint256.rep(x);
|
||||
let b = uint256.rep(y);
|
||||
assembly {
|
||||
@ -24,27 +13,52 @@ instantiation uint256: + {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
instantiation uint256: * {
|
||||
function mul(x, y) -> uint256 {
|
||||
let a = uint256.rep(x);
|
||||
let b = uint256.rep(y);
|
||||
assembly {
|
||||
a := mul(a,b)
|
||||
}
|
||||
return uint256.abs(a);
|
||||
}
|
||||
}
|
||||
instantiation word: * {
|
||||
function mul(x, y) -> z {
|
||||
function mul(x, y) -> word {
|
||||
let z: word;
|
||||
assembly {
|
||||
z := mul(x,y)
|
||||
}
|
||||
return z;
|
||||
}
|
||||
}
|
||||
|
||||
instantiation word: integer {
|
||||
function fromInteger(x:integer) -> y:word {
|
||||
function fromInteger(x:integer) -> word {
|
||||
//x + x;
|
||||
}
|
||||
}
|
||||
|
||||
instantiation word: == {
|
||||
function eq(x, y) -> z:bool {
|
||||
function eq(x, y) -> bool {
|
||||
assembly {
|
||||
x := eq(x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function f(x:uint256->uint256,y:uint256) -> uint256
|
||||
{
|
||||
return x(y);
|
||||
}
|
||||
|
||||
function g(x:uint256) -> uint256
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
contract C {
|
||||
fallback() external {
|
||||
let x : word;
|
||||
@ -52,8 +66,10 @@ contract C {
|
||||
x := 0x10
|
||||
}
|
||||
let w = uint256.abs(x);
|
||||
// w = f(g, w);
|
||||
w = w * w + w;
|
||||
let y : word;
|
||||
let z : (uint256,uint256);
|
||||
assembly { y := 2 }
|
||||
y = uint256.rep(w) * y;
|
||||
assembly {
|
||||
|
Loading…
Reference in New Issue
Block a user