diff options
author | chriseth <c@ethdev.com> | 2017-02-02 04:20:21 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2017-02-16 17:15:22 +0800 |
commit | 49a919b3e012cfa0f7e0c93c29b93289740e9e44 (patch) | |
tree | 83bb619c3bd17f28a439c28f2a5df7b17895ad83 | |
parent | 5d584aded8bcabaafddf2f61692f8663913be603 (diff) | |
download | dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar.gz dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar.bz2 dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar.lz dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar.xz dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.tar.zst dexon-solidity-49a919b3e012cfa0f7e0c93c29b93289740e9e44.zip |
Parsing function calls.
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmData.h | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 91 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.h | 2 | ||||
-rw-r--r-- | test/libsolidity/InlineAssembly.cpp | 5 |
5 files changed, 69 insertions, 37 deletions
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 1eab5df0..faa7dabd 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -190,6 +190,10 @@ public: } (*this)(_instr.instruction); } + void operator()(assembly::FunctionCall const&) + { + solAssert(false, "Function call not removed during desugaring phase."); + } void operator()(Label const& _label) { m_state.assembly.setSourceLocation(_label.location); diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index 64dd7b8e..d61b5803 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -49,13 +49,15 @@ struct Assignment { SourceLocation location; Identifier variableName; }; struct FunctionalAssignment; struct VariableDeclaration; struct FunctionDefinition; +struct FunctionCall; struct Block; -using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>; +using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>; /// Functional assignment ("x := mload(20)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. struct FunctionalAssignment { SourceLocation location; Identifier variableName; std::shared_ptr<Statement> value; }; /// Functional instruction, e.g. "mul(mload(20), add(2, x))" struct FunctionalInstruction { SourceLocation location; Instruction instruction; std::vector<Statement> arguments; }; +struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; }; /// Block-scope variable declaration ("let x := mload(20)"), non-hoisted struct VariableDeclaration { SourceLocation location; std::string name; std::shared_ptr<Statement> value; }; /// Block that creates a scope (frees declared stack variables) diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 019ec1a3..0fc0a34f 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -257,46 +257,67 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -FunctionalInstruction Parser::parseFunctionalInstruction(assembly::Statement&& _instruction) +assembly::Statement Parser::parseFunctionalInstruction(assembly::Statement&& _instruction) { - if (_instruction.type() != typeid(Instruction)) - fatalParserError("Assembly instruction required in front of \"(\")"); - FunctionalInstruction ret; - ret.instruction = std::move(boost::get<Instruction>(_instruction)); - ret.location = ret.instruction.location; - solidity::Instruction instr = ret.instruction.instruction; - InstructionInfo instrInfo = instructionInfo(instr); - if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16) - fatalParserError("DUPi instructions not allowed for functional notation"); - if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16) - fatalParserError("SWAPi instructions not allowed for functional notation"); - - expectToken(Token::LParen); - unsigned args = unsigned(instrInfo.args); - for (unsigned i = 0; i < args; ++i) + if (_instruction.type() == typeid(Instruction)) { - ret.arguments.emplace_back(parseExpression()); - if (i != args - 1) + FunctionalInstruction ret; + ret.instruction = std::move(boost::get<Instruction>(_instruction)); + ret.location = ret.instruction.location; + solidity::Instruction instr = ret.instruction.instruction; + InstructionInfo instrInfo = instructionInfo(instr); + if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16) + fatalParserError("DUPi instructions not allowed for functional notation"); + if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16) + fatalParserError("SWAPi instructions not allowed for functional notation"); + expectToken(Token::LParen); + unsigned args = unsigned(instrInfo.args); + for (unsigned i = 0; i < args; ++i) { - if (m_scanner->currentToken() != Token::Comma) - fatalParserError(string( - "Expected comma (" + - instrInfo.name + - " expects " + - boost::lexical_cast<string>(args) + - " arguments)" - )); - else - m_scanner->next(); + ret.arguments.emplace_back(parseExpression()); + if (i != args - 1) + { + if (m_scanner->currentToken() != Token::Comma) + fatalParserError(string( + "Expected comma (" + + instrInfo.name + + " expects " + + boost::lexical_cast<string>(args) + + " arguments)" + )); + else + m_scanner->next(); + } } + ret.location.end = endPosition(); + if (m_scanner->currentToken() == Token::Comma) + fatalParserError( + string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)") + ); + expectToken(Token::RParen); + return ret; } - ret.location.end = endPosition(); - if (m_scanner->currentToken() == Token::Comma) - fatalParserError( - string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)") - ); - expectToken(Token::RParen); - return ret; + else if (_instruction.type() == typeid(Identifier)) + { + FunctionCall ret; + ret.functionName = std::move(boost::get<Identifier>(_instruction)); + ret.location = ret.functionName.location; + expectToken(Token::LParen); + while (m_scanner->currentToken() != Token::RParen) + { + ret.arguments.emplace_back(parseExpression()); + if (m_scanner->currentToken() == Token::RParen) + break; + expectToken(Token::Comma); + } + ret.location.end = endPosition(); + expectToken(Token::RParen); + return ret; + } + else + fatalParserError("Assembly instruction or function name required in front of \"(\")"); + + return {}; } string Parser::expectAsmIdentifier() diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h index 1da049f6..4b4a24ae 100644 --- a/libsolidity/inlineasm/AsmParser.h +++ b/libsolidity/inlineasm/AsmParser.h @@ -68,7 +68,7 @@ protected: Statement parseElementaryOperation(bool _onlySinglePusher = false); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - FunctionalInstruction parseFunctionalInstruction(Statement&& _instruction); + Statement parseFunctionalInstruction(Statement&& _instruction); std::string expectAsmIdentifier(); }; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 5216ac06..40135a06 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -169,6 +169,11 @@ BOOST_AUTO_TEST_CASE(function_definitions_multiple_args) BOOST_CHECK(successParse("{ function f(a, d) { } function g(a, d) -> (x, y) { } }")); } +BOOST_AUTO_TEST_CASE(function_calls) +{ + BOOST_CHECK(successParse("{ g(1, 2, f(mul(2, 3))) x() }")); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(Printing) |