aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/introduction-to-smart-contracts.rst24
-rw-r--r--docs/units-and-global-variables.rst2
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp9
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp2
-rw-r--r--libsolidity/inlineasm/AsmData.h17
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp34
-rw-r--r--libsolidity/inlineasm/AsmParser.h1
-rw-r--r--libsolidity/inlineasm/AsmPrinter.cpp33
-rw-r--r--libsolidity/inlineasm/AsmPrinter.h2
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp8
-rw-r--r--libsolidity/inlineasm/AsmScope.h17
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp16
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.h3
-rw-r--r--libsolidity/interface/CompilerStack.cpp17
-rw-r--r--test/libjulia/Parser.cpp31
15 files changed, 150 insertions, 66 deletions
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index 9001a08c..d6c30db8 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -33,9 +33,11 @@ Storage
The first line simply tells that the source code is written for
Solidity version 0.4.0 or anything newer that does not break functionality
(up to, but not including, version 0.5.0). This is to ensure that the
-contract does not suddenly behave differently with a new compiler version.
+contract does not suddenly behave differently with a new compiler version. The keyword ``pragma`` is called that way because, in general,
+pragmas are instructions for the compiler about how to treat the
+source code (e.g. [pragma once](https://en.wikipedia.org/wiki/Pragma_once)). .
-A contract in the sense of Solidity is a collection of code (its functions) and
+A contract in the sense of Solidity is a collection of code (its *functions*) and
data (its *state*) that resides at a specific address on the Ethereum
blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of
type ``uint`` (unsigned integer of 256 bits). You can think of it as a single slot
@@ -47,9 +49,9 @@ or retrieve the value of the variable.
To access a state variable, you do not need the prefix ``this.`` as is common in
other languages.
-This contract does not yet do much apart from (due to the infrastructure
-built by Ethereum) allowing anyone to store a single number that is accessible by
-anyone in the world without (feasible) a way to prevent you from publishing
+This contract does not do much yet (due to the infrastructure
+built by Ethereum) apart from allowing anyone to store a single number that is accessible by
+anyone in the world without a (feasible) way to prevent you from publishing
this number. Of course, anyone could just call ``set`` again with a different value
and overwrite your number, but the number will still be stored in the history
of the blockchain. Later, we will see how you can impose access restrictions
@@ -124,7 +126,7 @@ get the idea - the compiler figures that out for you.
The next line, ``mapping (address => uint) public balances;`` also
creates a public state variable, but it is a more complex datatype.
The type maps addresses to unsigned integers.
-Mappings can be seen as hashtables which are
+Mappings can be seen as [hash tables](https://en.wikipedia.org/wiki/Hash_table) which are
virtually initialized such that every possible key exists and is mapped to a
value whose byte-representation is all zeros. This analogy does not go
too far, though, as it is neither possible to obtain a list of all keys of
@@ -193,7 +195,7 @@ Blockchain Basics
*****************
Blockchains as a concept are not too hard to understand for programmers. The reason is that
-most of the complications (mining, hashing, elliptic-curve cryptography, peer-to-peer networks, ...)
+most of the complications (mining, [hashing](https://en.wikipedia.org/wiki/Cryptographic_hash_function), [elliptic-curve cryptography](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography), [peer-to-peer networks](https://en.wikipedia.org/wiki/Peer-to-peer), etc.)
are just there to provide a certain set of features and promises. Once you accept these
features as given, you do not have to worry about the underlying technology - or do you have
to know how Amazon's AWS works internally in order to use it?
@@ -402,7 +404,7 @@ such situations, so that exceptions "bubble up" the call stack.
As already said, the called contract (which can be the same as the caller)
will receive a freshly cleared instance of memory and has access to the
call payload - which will be provided in a separate area called the **calldata**.
-After it finished execution, it can return data which will be stored at
+After it has finished execution, it can return data which will be stored at
a location in the caller's memory preallocated by the caller.
Calls are **limited** to a depth of 1024, which means that for more complex
@@ -423,8 +425,8 @@ address at runtime. Storage, current address and balance still
refer to the calling contract, only the code is taken from the called address.
This makes it possible to implement the "library" feature in Solidity:
-Reusable library code that can be applied to a contract's storage in
-order to e.g. implement a complex data structure.
+Reusable library code that can be applied to a contract's storage, e.g. in
+order to implement a complex data structure.
.. index:: log
@@ -436,7 +438,7 @@ that maps all the way up to the block level. This feature called **logs**
is used by Solidity in order to implement **events**.
Contracts cannot access log data after it has been created, but they
can be efficiently accessed from outside the blockchain.
-Since some part of the log data is stored in bloom filters, it is
+Since some part of the log data is stored in [bloom filters](https://en.wikipedia.org/wiki/Bloom_filter), it is
possible to search for this data in an efficient and cryptographically
secure way, so network peers that do not download the whole blockchain
("light clients") can still find these logs.
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index 246cc564..779e3819 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -55,7 +55,7 @@ Block and Transaction Properties
- ``block.difficulty`` (``uint``): current block difficulty
- ``block.gaslimit`` (``uint``): current block gaslimit
- ``block.number`` (``uint``): current block number
-- ``block.timestamp`` (``uint``): current block timestamp
+- ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch
- ``msg.data`` (``bytes``): complete calldata
- ``msg.gas`` (``uint``): remaining gas
- ``msg.sender`` (``address``): sender of the message (current call)
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index dad05a78..590f9ad6 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -184,7 +184,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
int const stackHeight = m_stackHeight;
bool success = boost::apply_visitor(*this, *_varDecl.value);
solAssert(m_stackHeight - stackHeight == 1, "Invalid value size.");
- boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.name)).active = true;
+ boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.variable.name)).active = true;
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
return success;
}
@@ -193,7 +193,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
{
Scope& bodyScope = scope(&_funDef.body);
for (auto const& var: _funDef.arguments + _funDef.returns)
- boost::get<Scope::Variable>(bodyScope.identifiers.at(var)).active = true;
+ boost::get<Scope::Variable>(bodyScope.identifiers.at(var.name)).active = true;
int const stackHeight = m_stackHeight;
m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
@@ -232,8 +232,9 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
},
[&](Scope::Function const& _fun)
{
- arguments = _fun.arguments;
- returns = _fun.returns;
+ /// TODO: compare types too
+ arguments = _fun.arguments.size();
+ returns = _fun.returns.size();
}
)))
{
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index c19667b4..137a70f5 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -204,7 +204,7 @@ public:
int height = m_state.assembly.deposit();
boost::apply_visitor(*this, *_varDecl.value);
expectDeposit(1, height);
- auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.name));
+ auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.variable.name));
var.stackHeight = height;
var.active = true;
}
diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h
index d61b5803..363873ab 100644
--- a/libsolidity/inlineasm/AsmData.h
+++ b/libsolidity/inlineasm/AsmData.h
@@ -33,12 +33,17 @@ namespace solidity
namespace assembly
{
+using Type = std::string;
+
+struct TypedName { SourceLocation location; std::string name; Type type; };
+using TypedNameList = std::vector<TypedName>;
+
/// What follows are the AST nodes for assembly.
/// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; };
/// Literal number or string (up to 32 bytes)
-struct Literal { SourceLocation location; bool isNumber; std::string value; };
+struct Literal { SourceLocation location; bool isNumber; std::string value; Type type; };
/// External / internal identifier or label reference
struct Identifier { SourceLocation location; std::string name; };
struct FunctionalInstruction;
@@ -52,18 +57,18 @@ struct FunctionDefinition;
struct FunctionCall;
struct 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
+/// Functional assignment ("x := mload(20:u256)", 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))"
+/// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, 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-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
+struct VariableDeclaration { SourceLocation location; TypedName variable; std::shared_ptr<Statement> value; };
/// Block that creates a scope (frees declared stack variables)
struct Block { SourceLocation location; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }")
-struct FunctionDefinition { SourceLocation location; std::string name; std::vector<std::string> arguments; std::vector<std::string> returns; Block body; };
+struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList arguments; TypedNameList returns; Block body; };
struct LocationExtractor: boost::static_visitor<SourceLocation>
{
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index d9b0b3e0..7ecad5ea 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -201,16 +201,26 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
}
else
ret = Identifier{location(), literal};
+ m_scanner->next();
break;
}
case Token::StringLiteral:
case Token::Number:
{
- ret = Literal{
+ Literal literal{
location(),
m_scanner->currentToken() == Token::Number,
- m_scanner->currentLiteral()
+ m_scanner->currentLiteral(),
+ ""
};
+ m_scanner->next();
+ if (m_julia)
+ {
+ expectToken(Token::Colon);
+ literal.location.end = endPosition();
+ literal.type = expectAsmIdentifier();
+ }
+ ret = std::move(literal);
break;
}
default:
@@ -220,7 +230,6 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
"Expected elementary inline assembly operation."
);
}
- m_scanner->next();
return ret;
}
@@ -228,7 +237,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
expectToken(Token::Let);
- varDecl.name = expectAsmIdentifier();
+ varDecl.variable = parseTypedName();
expectToken(Token::Colon);
expectToken(Token::Assign);
varDecl.value.reset(new Statement(parseExpression()));
@@ -244,7 +253,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
expectToken(Token::LParen);
while (m_scanner->currentToken() != Token::RParen)
{
- funDef.arguments.push_back(expectAsmIdentifier());
+ funDef.arguments.emplace_back(parseTypedName());
if (m_scanner->currentToken() == Token::RParen)
break;
expectToken(Token::Comma);
@@ -256,7 +265,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
expectToken(Token::GreaterThan);
while (true)
{
- funDef.returns.push_back(expectAsmIdentifier());
+ funDef.returns.emplace_back(parseTypedName());
if (m_scanner->currentToken() == Token::LBrace)
break;
expectToken(Token::Comma);
@@ -335,6 +344,19 @@ assembly::Statement Parser::parseFunctionalInstruction(assembly::Statement&& _in
return {};
}
+TypedName Parser::parseTypedName()
+{
+ TypedName typedName = createWithLocation<TypedName>();
+ typedName.name = expectAsmIdentifier();
+ if (m_julia)
+ {
+ expectToken(Token::Colon);
+ typedName.location.end = endPosition();
+ typedName.type = expectAsmIdentifier();
+ }
+ return typedName;
+}
+
string Parser::expectAsmIdentifier()
{
string name = m_scanner->currentLiteral();
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index c55fd2ac..addc1725 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -69,6 +69,7 @@ protected:
VariableDeclaration parseVariableDeclaration();
FunctionDefinition parseFunctionDefinition();
Statement parseFunctionalInstruction(Statement&& _instruction);
+ TypedName parseTypedName();
std::string expectAsmIdentifier();
private:
diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp
index 4a6f975d..f3b66aee 100644
--- a/libsolidity/inlineasm/AsmPrinter.cpp
+++ b/libsolidity/inlineasm/AsmPrinter.cpp
@@ -47,7 +47,7 @@ string AsmPrinter::operator()(assembly::Instruction const& _instruction)
string AsmPrinter::operator()(assembly::Literal const& _literal)
{
if (_literal.isNumber)
- return _literal.value;
+ return _literal.value + appendTypeName(_literal.type);
string out;
for (char c: _literal.value)
if (c == '\\')
@@ -74,7 +74,7 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
}
else
out += c;
- return "\"" + out + "\"";
+ return "\"" + out + "\"" + appendTypeName(_literal.type);
}
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
@@ -113,14 +113,30 @@ string AsmPrinter::operator()(assembly::FunctionalAssignment const& _functionalA
string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDeclaration)
{
- return "let " + _variableDeclaration.name + " := " + boost::apply_visitor(*this, *_variableDeclaration.value);
+ return "let " + _variableDeclaration.variable.name + appendTypeName(_variableDeclaration.variable.type) + " := " + boost::apply_visitor(*this, *_variableDeclaration.value);
}
string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition)
{
- string out = "function " + _functionDefinition.name + "(" + boost::algorithm::join(_functionDefinition.arguments, ", ") + ")";
+ string out = "function " + _functionDefinition.name + "(";
+ out += boost::algorithm::join(
+ _functionDefinition.arguments | boost::adaptors::transformed(
+ [this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
+ ),
+ ", "
+ );
+ out += ")";
if (!_functionDefinition.returns.empty())
- out += " -> " + boost::algorithm::join(_functionDefinition.returns, ", ");
+ {
+ out += " -> ";
+ out += boost::algorithm::join(
+ _functionDefinition.returns | boost::adaptors::transformed(
+ [this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
+ ),
+ ", "
+ );
+ }
+
return out + "\n" + (*this)(_functionDefinition.body);
}
@@ -145,3 +161,10 @@ string AsmPrinter::operator()(Block const& _block)
boost::replace_all(body, "\n", "\n ");
return "{\n " + body + "\n}";
}
+
+string AsmPrinter::appendTypeName(std::string const& _type)
+{
+ if (m_julia)
+ return ":" + _type;
+ return "";
+}
diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h
index 038c6d85..282fd7e3 100644
--- a/libsolidity/inlineasm/AsmPrinter.h
+++ b/libsolidity/inlineasm/AsmPrinter.h
@@ -60,6 +60,8 @@ public:
std::string operator()(assembly::Block const& _block);
private:
+ std::string appendTypeName(std::string const& _type);
+
bool m_julia = false;
};
diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index 609dca16..e3f4615a 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -32,15 +32,17 @@ bool Scope::registerLabel(string const& _name)
return true;
}
-bool Scope::registerVariable(string const& _name)
+bool Scope::registerVariable(string const& _name, JuliaType const& _type)
{
if (exists(_name))
return false;
- identifiers[_name] = Variable();
+ Variable variable;
+ variable.type = _type;
+ identifiers[_name] = variable;
return true;
}
-bool Scope::registerFunction(string const& _name, size_t _arguments, size_t _returns)
+bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns)
{
if (exists(_name))
return false;
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index b70bee67..dd45613d 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -61,6 +61,8 @@ struct GenericVisitor<>: public boost::static_visitor<> {
struct Scope
{
+ using JuliaType = std::string;
+
struct Variable
{
/// Used during code generation to store the stack height. @todo move there.
@@ -68,6 +70,7 @@ struct Scope
/// Used during analysis to check whether we already passed the declaration inside the block.
/// @todo move there.
bool active = false;
+ JuliaType type;
};
struct Label
@@ -78,18 +81,22 @@ struct Scope
struct Function
{
- Function(size_t _arguments, size_t _returns): arguments(_arguments), returns(_returns) {}
- size_t arguments = 0;
- size_t returns = 0;
+ Function(std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns): arguments(_arguments), returns(_returns) {}
+ std::vector<JuliaType> arguments;
+ std::vector<JuliaType> returns;
};
using Identifier = boost::variant<Variable, Label, Function>;
using Visitor = GenericVisitor<Variable const, Label const, Function const>;
using NonconstVisitor = GenericVisitor<Variable, Label, Function>;
- bool registerVariable(std::string const& _name);
+ bool registerVariable(std::string const& _name, JuliaType const& _type);
bool registerLabel(std::string const& _name);
- bool registerFunction(std::string const& _name, size_t _arguments, size_t _returns);
+ bool registerFunction(
+ std::string const& _name,
+ std::vector<JuliaType> const& _arguments,
+ std::vector<JuliaType> const& _returns
+ );
/// Looks up the identifier in this or super scopes and returns a valid pointer if found
/// or a nullptr if not found. Variable lookups up across function boundaries will fail, as
diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp
index 4a651388..eb10dbb3 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.cpp
+++ b/libsolidity/inlineasm/AsmScopeFiller.cpp
@@ -59,13 +59,19 @@ bool ScopeFiller::operator()(Label const& _item)
bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl)
{
- return registerVariable(_varDecl.name, _varDecl.location, *m_currentScope);
+ return registerVariable(_varDecl.variable, _varDecl.location, *m_currentScope);
}
bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef)
{
bool success = true;
- if (!m_currentScope->registerFunction(_funDef.name, _funDef.arguments.size(), _funDef.returns.size()))
+ vector<Scope::JuliaType> arguments;
+ for (auto const& _argument: _funDef.arguments)
+ arguments.push_back(_argument.type);
+ vector<Scope::JuliaType> returns;
+ for (auto const& _return: _funDef.returns)
+ returns.push_back(_return.type);
+ if (!m_currentScope->registerFunction(_funDef.name, arguments, returns))
{
//@TODO secondary location
m_errors.push_back(make_shared<Error>(
@@ -102,14 +108,14 @@ bool ScopeFiller::operator()(Block const& _block)
return success;
}
-bool ScopeFiller::registerVariable(string const& _name, SourceLocation const& _location, Scope& _scope)
+bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& _location, Scope& _scope)
{
- if (!_scope.registerVariable(_name))
+ if (!_scope.registerVariable(_name.name, _name.type))
{
//@TODO secondary location
m_errors.push_back(make_shared<Error>(
Error::Type::DeclarationError,
- "Variable name " + _name + " already taken in this scope.",
+ "Variable name " + _name.name + " already taken in this scope.",
_location
));
return false;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h
index bb62948b..61428eea 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.h
+++ b/libsolidity/inlineasm/AsmScopeFiller.h
@@ -34,6 +34,7 @@ namespace solidity
namespace assembly
{
+struct TypedName;
struct Literal;
struct Block;
struct Label;
@@ -72,7 +73,7 @@ public:
private:
bool registerVariable(
- std::string const& _name,
+ TypedName const& _name,
SourceLocation const& _location,
Scope& _scope
);
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 9c9c9614..5c836358 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -451,9 +451,6 @@ Json::Value const& CompilerStack::interface(string const& _contractName) const
Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const
{
- if (m_stackState < AnalysisSuccessful)
- BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
-
return metadata(contract(_contractName), _type);
}
@@ -491,23 +488,32 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat
string const& CompilerStack::onChainMetadata(string const& _contractName) const
{
if (m_stackState != CompilationSuccessful)
- BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
return contract(_contractName).onChainMetadata;
}
Scanner const& CompilerStack::scanner(string const& _sourceName) const
{
+ if (m_stackState < ParsingSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
return *source(_sourceName).scanner;
}
SourceUnit const& CompilerStack::ast(string const& _sourceName) const
{
+ if (m_stackState < ParsingSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
return *source(_sourceName).ast;
}
ContractDefinition const& CompilerStack::contractDefinition(string const& _contractName) const
{
+ if (m_stackState != CompilationSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
+
return *contract(_contractName).contract;
}
@@ -736,6 +742,9 @@ void CompilerStack::compileContract(
std::string CompilerStack::defaultContractName() const
{
+ if (m_stackState != CompilationSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
+
return contract("").contract->name();
}
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index 0dfd3033..c401f57b 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -89,11 +89,6 @@ bool successParse(std::string const& _source, bool _allowWarnings = true)
return !parseAndReturnFirstError(_source, _allowWarnings);
}
-bool successAssemble(string const& _source, bool _allowWarnings = true)
-{
- return successParse(_source, _allowWarnings);
-}
-
Error expectError(std::string const& _source, bool _allowWarnings = false)
{
@@ -122,12 +117,12 @@ BOOST_AUTO_TEST_CASE(smoke_test)
BOOST_AUTO_TEST_CASE(vardecl)
{
- BOOST_CHECK(successParse("{ let x := 7 }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 7:u256 }"));
}
BOOST_AUTO_TEST_CASE(assignment)
{
- BOOST_CHECK(successParse("{ let x := 2 let y := x }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 2:u256 let y:u256 := x }"));
}
BOOST_AUTO_TEST_CASE(function_call)
@@ -137,27 +132,27 @@ BOOST_AUTO_TEST_CASE(function_call)
BOOST_AUTO_TEST_CASE(vardecl_complex)
{
- BOOST_CHECK(successParse("{ let y := 2 let x := add(7, mul(6, y)) }"));
+ BOOST_CHECK(successParse("{ let y:u256 := 2:u256 let x:u256 := add(7:u256, mul(6:u256, y)) }"));
}
BOOST_AUTO_TEST_CASE(blocks)
{
- BOOST_CHECK(successParse("{ let x := 7 { let y := 3 } { let z := 2 } }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 7:u256 { let y:u256 := 3:u256 } { let z:u256 := 2:u256 } }"));
}
BOOST_AUTO_TEST_CASE(function_definitions)
{
- BOOST_CHECK(successParse("{ function f() { } function g(a) -> x { } }"));
+ BOOST_CHECK(successParse("{ function f() { } function g(a:u256) -> x:u256 { } }"));
}
BOOST_AUTO_TEST_CASE(function_definitions_multiple_args)
{
- BOOST_CHECK(successParse("{ function f(a, d) { } function g(a, d) -> x, y { } }"));
+ BOOST_CHECK(successParse("{ function f(a:u256, d:u256) { } function g(a:u256, d:u256) -> x:u256, y:u256 { } }"));
}
BOOST_AUTO_TEST_CASE(function_calls)
{
- BOOST_CHECK(successParse("{ function f(a) -> b {} function g(a, b, c) {} function x() { g(1, 2, f(mul(2, 3))) x() } }"));
+ BOOST_CHECK(successParse("{ function f(a:u256) -> b:u256 {} function g(a:u256, b:u256, c:u256) {} function x() { g(1:u256, 2:u256, f(mul(2:u256, 3:u256))) x() } }"));
}
BOOST_AUTO_TEST_CASE(label)
@@ -172,12 +167,12 @@ BOOST_AUTO_TEST_CASE(instructions)
BOOST_AUTO_TEST_CASE(push)
{
- CHECK_ERROR("{ 0x42 }", ParserError, "Call or assignment expected.");
+ CHECK_ERROR("{ 0x42:u256 }", ParserError, "Call or assignment expected.");
}
BOOST_AUTO_TEST_CASE(assign_from_stack)
{
- CHECK_ERROR("{ =: x }", ParserError, "Literal or identifier expected.");
+ CHECK_ERROR("{ =: x:u256 }", ParserError, "Literal or identifier expected.");
}
BOOST_AUTO_TEST_CASE(empty_call)
@@ -185,6 +180,14 @@ BOOST_AUTO_TEST_CASE(empty_call)
CHECK_ERROR("{ () }", ParserError, "Literal or identifier expected.");
}
+BOOST_AUTO_TEST_CASE(lacking_types)
+{
+ CHECK_ERROR("{ let x := 1:u256 }", ParserError, "Expected token Identifier got 'Assign'");
+ CHECK_ERROR("{ let x:u256 := 1 }", ParserError, "Expected token Colon got 'RBrace'");
+ CHECK_ERROR("{ function f(a) {} }", ParserError, "Expected token Colon got 'RParen'");
+ CHECK_ERROR("{ function f(a:u256) -> b {} }", ParserError, "Expected token Colon got 'LBrace'");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}