diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.cpp | 1 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 26 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 8 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 13 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.cpp | 2 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.h | 19 | ||||
-rw-r--r-- | libsolidity/interface/AssemblyStack.cpp | 16 | ||||
-rw-r--r-- | libsolidity/interface/AssemblyStack.h | 8 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 13 |
9 files changed, 67 insertions, 39 deletions
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 1de2e801..4ad1f962 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -252,6 +252,7 @@ bool ASTJsonConverter::visit(ContractDefinition const& _node) { setJsonNode(_node, "ContractDefinition", { make_pair("name", _node.name()), + make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue), make_pair("contractKind", contractKind(_node.contractKind())), make_pair("fullyImplemented", _node.annotation().isFullyImplemented), make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)), diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 36ac0e75..630e0abf 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -92,7 +92,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) if (m_currentScope->lookup(_identifier.name, Scope::Visitor( [&](Scope::Variable const& _var) { - if (!_var.active) + if (!m_activeVariables.count(&_var)) { m_errorReporter.declarationError( _identifier.location, @@ -187,7 +187,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) for (auto const& variable: _varDecl.variables) { expectValidType(variable.type, variable.location); - boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)).active = true; + m_activeVariables.insert(&boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name))); } m_info.stackHeightInfo[&_varDecl] = m_stackHeight; return success; @@ -201,7 +201,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) for (auto const& var: _funDef.arguments + _funDef.returns) { expectValidType(var.type, var.location); - boost::get<Scope::Variable>(varScope.identifiers.at(var.name)).active = true; + m_activeVariables.insert(&boost::get<Scope::Variable>(varScope.identifiers.at(var.name))); } int const stackHeight = m_stackHeight; @@ -384,7 +384,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t m_errorReporter.typeError(_variable.location, "Assignment requires variable."); success = false; } - else if (!boost::get<Scope::Variable>(*var).active) + else if (!m_activeVariables.count(&boost::get<Scope::Variable>(*var))) { m_errorReporter.declarationError( _variable.location, @@ -447,17 +447,25 @@ void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _loc void AsmAnalyzer::warnOnFutureInstruction(solidity::Instruction _instr, SourceLocation const& _location) { + string instr; switch (_instr) { + case solidity::Instruction::CREATE2: + instr = "create2"; + break; case solidity::Instruction::RETURNDATASIZE: + instr = "returndatasize"; + break; case solidity::Instruction::RETURNDATACOPY: - m_errorReporter.warning( - _location, - "The RETURNDATASIZE/RETURNDATACOPY instructions are only available after " - "the Metropolis hard fork. Before that they act as an invalid instruction." - ); + instr = "returndatacopy"; break; default: break; } + if (!instr.empty()) + m_errorReporter.warning( + _location, + "The \"" + instr + "\" instruction is only available after " + + "the Metropolis hard fork. Before that it acts as an invalid instruction." + ); } diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 55b409ba..2516722a 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -22,6 +22,8 @@ #include <libsolidity/interface/Exceptions.h> +#include <libsolidity/inlineasm/AsmScope.h> + #include <libjulia/backends/evm/AbstractAssembly.h> #include <boost/variant.hpp> @@ -51,9 +53,6 @@ struct FunctionCall; struct Switch; using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>; - -struct Scope; - struct AsmAnalysisInfo; /** @@ -102,6 +101,9 @@ private: int m_stackHeight = 0; julia::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; + /// Variables that are active at the current point in assembly (as opposed to + /// "part of the scope but not yet declared") + std::set<Scope::Variable const*> m_activeVariables; AsmAnalysisInfo& m_info; ErrorReporter& m_errorReporter; bool m_julia = false; diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 68a9cb03..f9b073ba 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -174,6 +174,19 @@ assembly::Case Parser::parseCase() assembly::Statement Parser::parseExpression() { Statement operation = parseElementaryOperation(true); + if (operation.type() == typeid(Instruction)) + { + Instruction const& instr = boost::get<Instruction>(operation); + int args = instructionInfo(instr.instruction).args; + if (args > 0 && currentToken() != Token::LParen) + fatalParserError(string( + "Expected token \"(\" (\"" + + instructionNames().at(instr.instruction) + + "\" expects " + + boost::lexical_cast<string>(args) + + " arguments)" + )); + } if (currentToken() == Token::LParen) return parseCall(std::move(operation)); else diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp index 7a086846..1db5ca41 100644 --- a/libsolidity/inlineasm/AsmScope.cpp +++ b/libsolidity/inlineasm/AsmScope.cpp @@ -46,7 +46,7 @@ bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const& { if (exists(_name)) return false; - identifiers[_name] = Function(_arguments, _returns); + identifiers[_name] = Function{_arguments, _returns}; return true; } diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index ad321f77..de9119e0 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -65,27 +65,12 @@ struct Scope using JuliaType = std::string; using LabelID = size_t; - struct Variable - { - /// Used during code generation to store the stack height. @todo move there. - int stackHeight = 0; - /// Used during analysis to check whether we already passed the declaration inside the block. - /// @todo move there. - bool active = false; - JuliaType type; - }; - - struct Label - { - boost::optional<LabelID> id; - }; - + struct Variable { JuliaType type; }; + struct Label { }; struct Function { - Function(std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns): arguments(_arguments), returns(_returns) {} std::vector<JuliaType> arguments; std::vector<JuliaType> returns; - boost::optional<LabelID> id; }; using Identifier = boost::variant<Variable, Label, Function>; diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 75877881..7dc1edc7 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -77,7 +77,7 @@ bool AssemblyStack::analyzeParsed() return m_analysisSuccessful; } -eth::LinkerObject AssemblyStack::assemble(Machine _machine) const +MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { solAssert(m_analysisSuccessful, ""); solAssert(m_parserResult, ""); @@ -87,21 +87,29 @@ eth::LinkerObject AssemblyStack::assemble(Machine _machine) const { case Machine::EVM: { + MachineAssemblyObject object; eth::Assembly assembly; assembly::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly); - return assembly.assemble(); + object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble()); + ostringstream tmp; + assembly.stream(tmp); + object.assembly = tmp.str(); + return object; } case Machine::EVM15: { + MachineAssemblyObject object; julia::EVMAssembly assembly(true); julia::CodeTransform(assembly, *m_analysisInfo, true).run(*m_parserResult); - return assembly.finalize(); + object.bytecode = make_shared<eth::LinkerObject>(assembly.finalize()); + /// TOOD: fill out text representation + return object; } case Machine::eWasm: solUnimplemented("eWasm backend is not yet implemented."); } // unreachable - return eth::LinkerObject(); + return MachineAssemblyObject(); } string AssemblyStack::print() const diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index ee2a334c..2ae596ed 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -38,6 +38,12 @@ struct AsmAnalysisInfo; struct Block; } +struct MachineAssemblyObject +{ + std::shared_ptr<eth::LinkerObject> bytecode; + std::string assembly; +}; + /* * Full assembly stack that can support EVM-assembly and JULIA as input and EVM, EVM1.5 and * eWasm as output. @@ -64,7 +70,7 @@ public: bool analyze(assembly::Block const& _block, Scanner const* _scanner = nullptr); /// Run the assembly step (should only be called after parseAndAnalyze). - eth::LinkerObject assemble(Machine _machine) const; + MachineAssemblyObject assemble(Machine _machine) const; /// @returns the errors generated during parsing, analysis (and potentially assembly). ErrorList const& errors() const { return m_errors; } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ec27f89b..7c439211 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1328,16 +1328,21 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars { // call({arg1 : 1, arg2 : 2 }) expectToken(Token::LBrace); + + bool first = true; while (m_scanner->currentToken() != Token::RBrace) { + if (!first) + expectToken(Token::Comma); + + if (m_scanner->currentToken() == Token::RBrace) + fatalParserError("Unexpected trailing comma."); + ret.second.push_back(expectIdentifierToken()); expectToken(Token::Colon); ret.first.push_back(parseExpression()); - if (m_scanner->currentToken() == Token::Comma) - expectToken(Token::Comma); - else - break; + first = false; } expectToken(Token::RBrace); } |