From a36db1f2412d700cc8b32f8331be103c73ea90cb Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 30 Oct 2014 22:52:15 +0100 Subject: [PATCH] Actual contract creator and add solidity to AlethZero interface. --- Compiler.cpp | 13 +++++++++++++ Compiler.h | 2 ++ CompilerContext.h | 4 ++++ CompilerStack.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++ CompilerStack.h | 43 +++++++++++++++++++++++++++++++++++++++++ Scanner.cpp | 5 ----- Scanner.h | 3 ++- 7 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 CompilerStack.cpp create mode 100644 CompilerStack.h diff --git a/Compiler.cpp b/Compiler.cpp index 7e40db15f..b1e3c3da3 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -46,9 +46,22 @@ void Compiler::compileContract(ContractDefinition& _contract) for (ASTPointer const& function: _contract.getDefinedFunctions()) m_context.addFunction(*function); + appendFunctionSelector(_contract.getDefinedFunctions()); for (ASTPointer const& function: _contract.getDefinedFunctions()) function->accept(*this); + + packIntoContractCreator(); +} + +void Compiler::packIntoContractCreator() +{ + CompilerContext creatorContext; + eth::AssemblyItem sub = creatorContext.addSubroutine(m_context.getAssembly()); + // stack contains sub size + creatorContext << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY; + creatorContext << u256(0) << eth::Instruction::RETURN; + swap(m_context, creatorContext); } void Compiler::appendFunctionSelector(vector> const& _functions) diff --git a/Compiler.h b/Compiler.h index ebd786658..d10374a9b 100644 --- a/Compiler.h +++ b/Compiler.h @@ -40,6 +40,8 @@ public: static bytes compile(ContractDefinition& _contract); private: + /// Creates a new compiler context / assembly and packs the current code into the data part. + void packIntoContractCreator(); void appendFunctionSelector(std::vector > const& _functions); void appendFunctionCallSection(FunctionDefinition const& _function); void appendCalldataUnpacker(FunctionDefinition const& _function); diff --git a/CompilerContext.h b/CompilerContext.h index cce5838ef..46c4c72ab 100644 --- a/CompilerContext.h +++ b/CompilerContext.h @@ -63,6 +63,9 @@ public: eth::AssemblyItem pushNewTag() { return m_asm.append(m_asm.newPushTag()).tag(); } /// @returns a new tag without pushing any opcodes or data eth::AssemblyItem newTag() { return m_asm.newTag(); } + /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) + /// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset. + eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); } /// Append elements to the current instruction list and adjust @a m_stackOffset. CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; } @@ -70,6 +73,7 @@ public: CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; } CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; } + eth::Assembly const& getAssembly() const { return m_asm; } void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } bytes getAssembledBytecode() const { return m_asm.assemble(); } private: diff --git a/CompilerStack.cpp b/CompilerStack.cpp new file mode 100644 index 000000000..bbd693ae5 --- /dev/null +++ b/CompilerStack.cpp @@ -0,0 +1,49 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Full-stack compiler that converts a source code string to bytecode. + */ + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ + +bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr _scanner) +{ + if (!_scanner) + _scanner = make_shared(); + _scanner->reset(CharStream(_sourceCode)); + + ASTPointer contract = Parser().parse(_scanner); + NameAndTypeResolver().resolveNamesAndTypes(*contract); + return Compiler::compile(*contract); +} + +} +} diff --git a/CompilerStack.h b/CompilerStack.h new file mode 100644 index 000000000..9f3f81c04 --- /dev/null +++ b/CompilerStack.h @@ -0,0 +1,43 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Full-stack compiler that converts a source code string to bytecode. + */ + +#pragma once + +#include +#include +#include + +namespace dev { +namespace solidity { + +class Scanner; // forward + +class CompilerStack +{ +public: + /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for + /// scanning the source code - this is useful for printing exception information. + static bytes compile(std::string const& _sourceCode, std::shared_ptr _scanner = std::shared_ptr()); +}; + +} +} diff --git a/Scanner.cpp b/Scanner.cpp index 3148de52e..d8defb50a 100644 --- a/Scanner.cpp +++ b/Scanner.cpp @@ -103,11 +103,6 @@ int HexValue(char c) } } // end anonymous namespace -Scanner::Scanner(CharStream const& _source) -{ - reset(_source); -} - void Scanner::reset(CharStream const& _source) { m_source = _source; diff --git a/Scanner.h b/Scanner.h index fbaba9ed6..7754d71b4 100644 --- a/Scanner.h +++ b/Scanner.h @@ -110,7 +110,8 @@ public: bool complete_; }; - explicit Scanner(CharStream const& _source); + Scanner() { reset(CharStream()); } + explicit Scanner(CharStream const& _source) { reset(_source); } /// Resets the scanner as if newly constructed with _input as input. void reset(CharStream const& _source);