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