mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Converted all asserts to exceptions.
This commit is contained in:
parent
1de66d6e9e
commit
c1f7a1665f
25
AST.cpp
25
AST.cpp
@ -293,9 +293,10 @@ void Break::checkTypeRequirements()
|
|||||||
|
|
||||||
void Return::checkTypeRequirements()
|
void Return::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
assert(m_returnParameters);
|
|
||||||
if (!m_expression)
|
if (!m_expression)
|
||||||
return;
|
return;
|
||||||
|
if (asserts(m_returnParameters))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Return parameters not assigned."));
|
||||||
if (m_returnParameters->getParameters().size() != 1)
|
if (m_returnParameters->getParameters().size() != 1)
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Different number of arguments in return statement "
|
BOOST_THROW_EXCEPTION(createTypeError("Different number of arguments in return statement "
|
||||||
"than in returns declaration."));
|
"than in returns declaration."));
|
||||||
@ -377,7 +378,6 @@ void BinaryOperation::checkTypeRequirements()
|
|||||||
m_type = make_shared<BoolType>();
|
m_type = make_shared<BoolType>();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(Token::isBinaryOp(m_operator));
|
|
||||||
m_type = m_commonType;
|
m_type = m_commonType;
|
||||||
if (!m_commonType->acceptsBinaryOperator(m_operator))
|
if (!m_commonType->acceptsBinaryOperator(m_operator))
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type."));
|
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type."));
|
||||||
@ -393,25 +393,22 @@ void FunctionCall::checkTypeRequirements()
|
|||||||
Type const* expressionType = m_expression->getType().get();
|
Type const* expressionType = m_expression->getType().get();
|
||||||
if (isTypeConversion())
|
if (isTypeConversion())
|
||||||
{
|
{
|
||||||
TypeType const* type = dynamic_cast<TypeType const*>(expressionType);
|
TypeType const& type = dynamic_cast<TypeType const&>(*expressionType);
|
||||||
assert(type);
|
|
||||||
//@todo for structs, we have to check the number of arguments to be equal to the
|
//@todo for structs, we have to check the number of arguments to be equal to the
|
||||||
// number of non-mapping members
|
// number of non-mapping members
|
||||||
if (m_arguments.size() != 1)
|
if (m_arguments.size() != 1)
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for "
|
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for "
|
||||||
"explicit type conersion."));
|
"explicit type conersion."));
|
||||||
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type->getActualType()))
|
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
|
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
|
||||||
m_type = type->getActualType();
|
m_type = type.getActualType();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//@todo would be nice to create a struct type from the arguments
|
//@todo would be nice to create a struct type from the arguments
|
||||||
// and then ask if that is implicitly convertible to the struct represented by the
|
// and then ask if that is implicitly convertible to the struct represented by the
|
||||||
// function parameters
|
// function parameters
|
||||||
FunctionType const* function = dynamic_cast<FunctionType const*>(expressionType);
|
FunctionDefinition const& fun = dynamic_cast<FunctionType const&>(*expressionType).getFunction();
|
||||||
assert(function);
|
|
||||||
FunctionDefinition const& fun = function->getFunction();
|
|
||||||
vector<ASTPointer<VariableDeclaration>> const& parameters = fun.getParameters();
|
vector<ASTPointer<VariableDeclaration>> const& parameters = fun.getParameters();
|
||||||
if (parameters.size() != m_arguments.size())
|
if (parameters.size() != m_arguments.size())
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
|
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
|
||||||
@ -434,19 +431,21 @@ bool FunctionCall::isTypeConversion() const
|
|||||||
|
|
||||||
void MemberAccess::checkTypeRequirements()
|
void MemberAccess::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
assert(false); // not yet implemented
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access not yet implemented."));
|
||||||
// m_type = ;
|
// m_type = ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexAccess::checkTypeRequirements()
|
void IndexAccess::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
assert(false); // not yet implemented
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Index access not yet implemented."));
|
||||||
// m_type = ;
|
// m_type = ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Identifier::checkTypeRequirements()
|
void Identifier::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
assert(m_referencedDeclaration);
|
if (asserts(m_referencedDeclaration))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved."));
|
||||||
|
|
||||||
//@todo these dynamic casts here are not really nice...
|
//@todo these dynamic casts here are not really nice...
|
||||||
// is i useful to have an AST visitor here?
|
// is i useful to have an AST visitor here?
|
||||||
// or can this already be done in NameAndTypeResolver?
|
// or can this already be done in NameAndTypeResolver?
|
||||||
@ -487,7 +486,7 @@ void Identifier::checkTypeRequirements()
|
|||||||
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef));
|
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(false); // declaration reference of unknown/forbidden type
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Declaration reference of unknown/forbidden type."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElementaryTypeNameExpression::checkTypeRequirements()
|
void ElementaryTypeNameExpression::checkTypeRequirements()
|
||||||
|
32
AST.h
32
AST.h
@ -243,7 +243,10 @@ class ElementaryTypeName: public TypeName
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ElementaryTypeName(Location const& _location, Token::Value _type):
|
explicit ElementaryTypeName(Location const& _location, Token::Value _type):
|
||||||
TypeName(_location), m_type(_type) {}
|
TypeName(_location), m_type(_type)
|
||||||
|
{
|
||||||
|
if (asserts(Token::isElementaryTypeName(_type))) BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual std::shared_ptr<Type> toType() override { return Type::fromElementaryTypeName(m_type); }
|
virtual std::shared_ptr<Type> toType() override { return Type::fromElementaryTypeName(m_type); }
|
||||||
|
|
||||||
@ -407,7 +410,12 @@ public:
|
|||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; }
|
void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; }
|
||||||
ParameterList const& getFunctionReturnParameters() const { assert(m_returnParameters); return *m_returnParameters; }
|
ParameterList const& getFunctionReturnParameters() const
|
||||||
|
{
|
||||||
|
if (asserts(m_returnParameters))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
return *m_returnParameters;
|
||||||
|
}
|
||||||
Expression* getExpression() const { return m_expression.get(); }
|
Expression* getExpression() const { return m_expression.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -495,7 +503,10 @@ public:
|
|||||||
Assignment(Location const& _location, ASTPointer<Expression> const& _leftHandSide,
|
Assignment(Location const& _location, ASTPointer<Expression> const& _leftHandSide,
|
||||||
Token::Value _assignmentOperator, ASTPointer<Expression> const& _rightHandSide):
|
Token::Value _assignmentOperator, ASTPointer<Expression> const& _rightHandSide):
|
||||||
Expression(_location), m_leftHandSide(_leftHandSide),
|
Expression(_location), m_leftHandSide(_leftHandSide),
|
||||||
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide) {}
|
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide)
|
||||||
|
{
|
||||||
|
if (asserts(Token::isAssignmentOp(_assignmentOperator))) BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
@ -519,7 +530,10 @@ public:
|
|||||||
UnaryOperation(Location const& _location, Token::Value _operator,
|
UnaryOperation(Location const& _location, Token::Value _operator,
|
||||||
ASTPointer<Expression> const& _subExpression, bool _isPrefix):
|
ASTPointer<Expression> const& _subExpression, bool _isPrefix):
|
||||||
Expression(_location), m_operator(_operator),
|
Expression(_location), m_operator(_operator),
|
||||||
m_subExpression(_subExpression), m_isPrefix(_isPrefix) {}
|
m_subExpression(_subExpression), m_isPrefix(_isPrefix)
|
||||||
|
{
|
||||||
|
if (asserts(Token::isUnaryOp(_operator))) BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
@ -541,7 +555,10 @@ class BinaryOperation: public Expression
|
|||||||
public:
|
public:
|
||||||
BinaryOperation(Location const& _location, ASTPointer<Expression> const& _left,
|
BinaryOperation(Location const& _location, ASTPointer<Expression> const& _left,
|
||||||
Token::Value _operator, ASTPointer<Expression> const& _right):
|
Token::Value _operator, ASTPointer<Expression> const& _right):
|
||||||
Expression(_location), m_left(_left), m_operator(_operator), m_right(_right) {}
|
Expression(_location), m_left(_left), m_operator(_operator), m_right(_right)
|
||||||
|
{
|
||||||
|
if (asserts(Token::isBinaryOp(_operator) || Token::isCompareOp(_operator))) BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
@ -658,7 +675,10 @@ class ElementaryTypeNameExpression: public PrimaryExpression
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ElementaryTypeNameExpression(Location const& _location, Token::Value _typeToken):
|
ElementaryTypeNameExpression(Location const& _location, Token::Value _typeToken):
|
||||||
PrimaryExpression(_location), m_typeToken(_typeToken) {}
|
PrimaryExpression(_location), m_typeToken(_typeToken)
|
||||||
|
{
|
||||||
|
if (asserts(Token::isElementaryTypeName(_typeToken))) BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
|
@ -252,14 +252,16 @@ bool Compiler::visit(WhileStatement& _whileStatement)
|
|||||||
|
|
||||||
bool Compiler::visit(Continue&)
|
bool Compiler::visit(Continue&)
|
||||||
{
|
{
|
||||||
assert(!m_continueTags.empty());
|
if (asserts(!m_continueTags.empty()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"continue\"."));
|
||||||
m_context.appendJumpTo(m_continueTags.back());
|
m_context.appendJumpTo(m_continueTags.back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(Break&)
|
bool Compiler::visit(Break&)
|
||||||
{
|
{
|
||||||
assert(!m_breakTags.empty());
|
if (asserts(!m_breakTags.empty()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"break\"."));
|
||||||
m_context.appendJumpTo(m_breakTags.back());
|
m_context.appendJumpTo(m_breakTags.back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
* Utilities for the solidity compiler.
|
* Utilities for the solidity compiler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <libsolidity/AST.h>
|
#include <libsolidity/AST.h>
|
||||||
@ -45,14 +44,16 @@ void CompilerContext::initializeLocalVariables(unsigned _numVariables)
|
|||||||
int CompilerContext::getStackPositionOfVariable(const Declaration& _declaration)
|
int CompilerContext::getStackPositionOfVariable(const Declaration& _declaration)
|
||||||
{
|
{
|
||||||
auto res = find(begin(m_localVariables), end(m_localVariables), &_declaration);
|
auto res = find(begin(m_localVariables), end(m_localVariables), &_declaration);
|
||||||
assert(res != m_localVariables.end());
|
if (asserts(res != m_localVariables.end()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found on stack."));
|
||||||
return end(m_localVariables) - res - 1 + m_asm.deposit();
|
return end(m_localVariables) - res - 1 + m_asm.deposit();
|
||||||
}
|
}
|
||||||
|
|
||||||
eth::AssemblyItem CompilerContext::getFunctionEntryLabel(const FunctionDefinition& _function) const
|
eth::AssemblyItem CompilerContext::getFunctionEntryLabel(const FunctionDefinition& _function) const
|
||||||
{
|
{
|
||||||
auto res = m_functionEntryLabels.find(&_function);
|
auto res = m_functionEntryLabels.find(&_function);
|
||||||
assert(res != m_functionEntryLabels.end());
|
if (asserts(res != m_functionEntryLabels.end()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function entry label not found."));
|
||||||
return res->second.tag();
|
return res->second.tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ struct ParserError: virtual Exception {};
|
|||||||
struct TypeError: virtual Exception {};
|
struct TypeError: virtual Exception {};
|
||||||
struct DeclarationError: virtual Exception {};
|
struct DeclarationError: virtual Exception {};
|
||||||
struct CompilerError: virtual Exception {};
|
struct CompilerError: virtual Exception {};
|
||||||
|
struct InternalCompilerError: virtual Exception {};
|
||||||
|
|
||||||
typedef boost::error_info<struct tag_sourcePosition, int> errinfo_sourcePosition;
|
typedef boost::error_info<struct tag_sourcePosition, int> errinfo_sourcePosition;
|
||||||
typedef boost::error_info<struct tag_sourceLocation, Location> errinfo_sourceLocation;
|
typedef boost::error_info<struct tag_sourceLocation, Location> errinfo_sourceLocation;
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
* Solidity AST to EVM bytecode compiler for expressions.
|
* Solidity AST to EVM bytecode compiler for expressions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <libsolidity/AST.h>
|
#include <libsolidity/AST.h>
|
||||||
@ -105,7 +104,8 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation)
|
|||||||
m_context << u256(0) << eth::Instruction::SUB;
|
m_context << u256(0) << eth::Instruction::SUB;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false); // invalid operation
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid unary operator: " +
|
||||||
|
string(Token::toString(_unaryOperation.getOperator()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,8 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
|
|||||||
rightExpression.accept(*this);
|
rightExpression.accept(*this);
|
||||||
|
|
||||||
// the types to compare have to be the same, but the resulting type is always bool
|
// the types to compare have to be the same, but the resulting type is always bool
|
||||||
assert(*leftExpression.getType() == *rightExpression.getType());
|
if (asserts(*leftExpression.getType() == *rightExpression.getType()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
appendCompareOperatorCode(op, *leftExpression.getType());
|
appendCompareOperatorCode(op, *leftExpression.getType());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -148,7 +149,8 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
if (_functionCall.isTypeConversion())
|
if (_functionCall.isTypeConversion())
|
||||||
{
|
{
|
||||||
//@todo we only have integers and bools for now which cannot be explicitly converted
|
//@todo we only have integers and bools for now which cannot be explicitly converted
|
||||||
assert(_functionCall.getArguments().size() == 1);
|
if (asserts(_functionCall.getArguments().size() == 1))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
Expression& firstArgument = *_functionCall.getArguments().front();
|
Expression& firstArgument = *_functionCall.getArguments().front();
|
||||||
firstArgument.accept(*this);
|
firstArgument.accept(*this);
|
||||||
cleanHigherOrderBitsIfNeeded(*firstArgument.getType(), *_functionCall.getType());
|
cleanHigherOrderBitsIfNeeded(*firstArgument.getType(), *_functionCall.getType());
|
||||||
@ -159,28 +161,28 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
// Callee removes them and pushes return values
|
// Callee removes them and pushes return values
|
||||||
m_currentLValue = nullptr;
|
m_currentLValue = nullptr;
|
||||||
_functionCall.getExpression().accept(*this);
|
_functionCall.getExpression().accept(*this);
|
||||||
FunctionDefinition const* function = dynamic_cast<FunctionDefinition*>(m_currentLValue);
|
FunctionDefinition const& function = dynamic_cast<FunctionDefinition&>(*m_currentLValue);
|
||||||
assert(function);
|
|
||||||
|
|
||||||
eth::AssemblyItem returnLabel = m_context.pushNewTag();
|
eth::AssemblyItem returnLabel = m_context.pushNewTag();
|
||||||
std::vector<ASTPointer<Expression>> const& arguments = _functionCall.getArguments();
|
std::vector<ASTPointer<Expression>> const& arguments = _functionCall.getArguments();
|
||||||
assert(arguments.size() == function->getParameters().size());
|
if (asserts(arguments.size() == function.getParameters().size()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
for (unsigned i = 0; i < arguments.size(); ++i)
|
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||||
{
|
{
|
||||||
arguments[i]->accept(*this);
|
arguments[i]->accept(*this);
|
||||||
cleanHigherOrderBitsIfNeeded(*arguments[i]->getType(),
|
cleanHigherOrderBitsIfNeeded(*arguments[i]->getType(),
|
||||||
*function->getParameters()[i]->getType());
|
*function.getParameters()[i]->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_context.appendJumpTo(m_context.getFunctionEntryLabel(*function));
|
m_context.appendJumpTo(m_context.getFunctionEntryLabel(function));
|
||||||
m_context << returnLabel;
|
m_context << returnLabel;
|
||||||
|
|
||||||
// callee adds return parameters, but removes arguments and return label
|
// callee adds return parameters, but removes arguments and return label
|
||||||
m_context.adjustStackOffset(function->getReturnParameters().size() - arguments.size() - 1);
|
m_context.adjustStackOffset(function.getReturnParameters().size() - arguments.size() - 1);
|
||||||
|
|
||||||
// @todo for now, the return value of a function is its first return value, so remove
|
// @todo for now, the return value of a function is its first return value, so remove
|
||||||
// all others
|
// all others
|
||||||
for (unsigned i = 1; i < function->getReturnParameters().size(); ++i)
|
for (unsigned i = 1; i < function.getReturnParameters().size(); ++i)
|
||||||
m_context << eth::Instruction::POP;
|
m_context << eth::Instruction::POP;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -227,7 +229,7 @@ void ExpressionCompiler::endVisit(Literal& _literal)
|
|||||||
m_context << _literal.getType()->literalValue(_literal);
|
m_context << _literal.getType()->literalValue(_literal);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false); // @todo
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer and boolean literals implemented for now."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,15 +251,15 @@ void ExpressionCompiler::cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack,
|
|||||||
{
|
{
|
||||||
// If we get here, there is either an implementation missing to clean higher oder bits
|
// If we get here, there is either an implementation missing to clean higher oder bits
|
||||||
// for non-integer types that are explicitly convertible or we got here in error.
|
// for non-integer types that are explicitly convertible or we got here in error.
|
||||||
assert(!_typeOnStack.isExplicitlyConvertibleTo(_targetType));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested."));
|
||||||
assert(false); // these types should not be convertible.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation)
|
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation)
|
||||||
{
|
{
|
||||||
Token::Value const op = _binaryOperation.getOperator();
|
Token::Value const op = _binaryOperation.getOperator();
|
||||||
assert(op == Token::OR || op == Token::AND);
|
if (asserts(op == Token::OR || op == Token::AND))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
|
||||||
_binaryOperation.getLeftExpression().accept(*this);
|
_binaryOperation.getLeftExpression().accept(*this);
|
||||||
m_context << eth::Instruction::DUP1;
|
m_context << eth::Instruction::DUP1;
|
||||||
@ -279,9 +281,8 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IntegerType const* type = dynamic_cast<IntegerType const*>(&_type);
|
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
|
||||||
assert(type);
|
bool const isSigned = type.isSigned();
|
||||||
bool const isSigned = type->isSigned();
|
|
||||||
|
|
||||||
// note that EVM opcodes compare like "stack[0] < stack[1]",
|
// note that EVM opcodes compare like "stack[0] < stack[1]",
|
||||||
// but our left value is at stack[1], so everyhing is reversed.
|
// but our left value is at stack[1], so everyhing is reversed.
|
||||||
@ -302,7 +303,7 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
|
|||||||
m_context << (isSigned ? eth::Instruction::SGT : eth::Instruction::GT);
|
m_context << (isSigned ? eth::Instruction::SGT : eth::Instruction::GT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown comparison operator."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,14 +317,13 @@ void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token::Value _operator
|
|||||||
else if (Token::isShiftOp(_operator))
|
else if (Token::isShiftOp(_operator))
|
||||||
appendShiftOperatorCode(_operator);
|
appendShiftOperatorCode(_operator);
|
||||||
else
|
else
|
||||||
assert(false); // unknown binary operator
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown binary operator."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Type const& _type)
|
void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Type const& _type)
|
||||||
{
|
{
|
||||||
IntegerType const* type = dynamic_cast<IntegerType const*>(&_type);
|
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
|
||||||
assert(type);
|
bool const isSigned = type.isSigned();
|
||||||
bool const isSigned = type->isSigned();
|
|
||||||
|
|
||||||
switch (_operator)
|
switch (_operator)
|
||||||
{
|
{
|
||||||
@ -343,7 +343,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
|
|||||||
m_context << eth::Instruction::SWAP1 << (isSigned ? eth::Instruction::SMOD : eth::Instruction::MOD);
|
m_context << eth::Instruction::SWAP1 << (isSigned ? eth::Instruction::SMOD : eth::Instruction::MOD);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown arithmetic operator."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,22 +361,21 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
|
|||||||
m_context << eth::Instruction::XOR;
|
m_context << eth::Instruction::XOR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown bit operator."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
|
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
|
||||||
{
|
{
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Shift operators not yet implemented."));
|
||||||
switch (_operator)
|
switch (_operator)
|
||||||
{
|
{
|
||||||
case Token::SHL:
|
case Token::SHL:
|
||||||
assert(false); //@todo
|
|
||||||
break;
|
break;
|
||||||
case Token::SAR:
|
case Token::SAR:
|
||||||
assert(false); //@todo
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown shift operator."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +401,8 @@ void ExpressionCompiler::moveToLValue(Expression const& _expression)
|
|||||||
|
|
||||||
unsigned ExpressionCompiler::stackPositionOfLValue() const
|
unsigned ExpressionCompiler::stackPositionOfLValue() const
|
||||||
{
|
{
|
||||||
assert(m_currentLValue);
|
if (asserts(m_currentLValue))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not available on request."));
|
||||||
return m_context.getStackPositionOfVariable(*m_currentLValue);
|
return m_context.getStackPositionOfVariable(*m_currentLValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
* Parser part that determines the declarations corresponding to names and the types of expressions.
|
* Parser part that determines the declarations corresponding to names and the types of expressions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <libsolidity/NameAndTypeResolver.h>
|
#include <libsolidity/NameAndTypeResolver.h>
|
||||||
#include <libsolidity/AST.h>
|
#include <libsolidity/AST.h>
|
||||||
#include <libsolidity/Exceptions.h>
|
#include <libsolidity/Exceptions.h>
|
||||||
@ -123,7 +122,8 @@ void DeclarationRegistrationHelper::endVisit(VariableDefinition& _variableDefini
|
|||||||
{
|
{
|
||||||
// Register the local variables with the function
|
// Register the local variables with the function
|
||||||
// This does not fit here perfectly, but it saves us another AST visit.
|
// This does not fit here perfectly, but it saves us another AST visit.
|
||||||
assert(m_currentFunction);
|
if (asserts(m_currentFunction))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable definition without function."));
|
||||||
m_currentFunction->addLocalVariable(_variableDefinition.getDeclaration());
|
m_currentFunction->addLocalVariable(_variableDefinition.getDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,19 +138,22 @@ void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _node)
|
|||||||
map<ASTNode const*, Scope>::iterator iter;
|
map<ASTNode const*, Scope>::iterator iter;
|
||||||
bool newlyAdded;
|
bool newlyAdded;
|
||||||
tie(iter, newlyAdded) = m_scopes.emplace(&_node, Scope(m_currentScope));
|
tie(iter, newlyAdded) = m_scopes.emplace(&_node, Scope(m_currentScope));
|
||||||
assert(newlyAdded);
|
if (asserts(newlyAdded))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to add new scope."));
|
||||||
m_currentScope = &iter->second;
|
m_currentScope = &iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::closeCurrentScope()
|
void DeclarationRegistrationHelper::closeCurrentScope()
|
||||||
{
|
{
|
||||||
assert(m_currentScope);
|
if (asserts(m_currentScope))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Closed non-existing scope."));
|
||||||
m_currentScope = m_currentScope->getEnclosingScope();
|
m_currentScope = m_currentScope->getEnclosingScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
|
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
|
||||||
{
|
{
|
||||||
assert(m_currentScope);
|
if (asserts(m_currentScope))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Declaration registered without scope."));
|
||||||
if (!m_currentScope->registerDeclaration(_declaration))
|
if (!m_currentScope->registerDeclaration(_declaration))
|
||||||
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation())
|
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation())
|
||||||
<< errinfo_comment("Identifier already declared."));
|
<< errinfo_comment("Identifier already declared."));
|
||||||
@ -177,7 +180,8 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable)
|
|||||||
|
|
||||||
bool ReferencesResolver::visit(Return& _return)
|
bool ReferencesResolver::visit(Return& _return)
|
||||||
{
|
{
|
||||||
assert(m_returnParameters);
|
if (asserts(m_returnParameters))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Return parameters not set."));
|
||||||
_return.setFunctionReturnParameters(*m_returnParameters);
|
_return.setFunctionReturnParameters(*m_returnParameters);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
33
Scanner.cpp
33
Scanner.cpp
@ -50,7 +50,6 @@
|
|||||||
* Solidity scanner.
|
* Solidity scanner.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <libsolidity/Scanner.h>
|
#include <libsolidity/Scanner.h>
|
||||||
@ -113,11 +112,10 @@ void Scanner::reset(CharStream const& _source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Scanner::scanHexNumber(char& o_scannedNumber, int _expectedLength)
|
bool Scanner::scanHexByte(char& o_scannedByte)
|
||||||
{
|
{
|
||||||
assert(_expectedLength <= 4); // prevent overflow
|
|
||||||
char x = 0;
|
char x = 0;
|
||||||
for (int i = 0; i < _expectedLength; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
int d = HexValue(m_char);
|
int d = HexValue(m_char);
|
||||||
if (d < 0)
|
if (d < 0)
|
||||||
@ -128,7 +126,7 @@ bool Scanner::scanHexNumber(char& o_scannedNumber, int _expectedLength)
|
|||||||
x = x * 16 + d;
|
x = x * 16 + d;
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
o_scannedNumber = x;
|
o_scannedByte = x;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +173,8 @@ Token::Value Scanner::skipSingleLineComment()
|
|||||||
|
|
||||||
Token::Value Scanner::skipMultiLineComment()
|
Token::Value Scanner::skipMultiLineComment()
|
||||||
{
|
{
|
||||||
assert(m_char == '*');
|
if (asserts(m_char == '*'))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
advance();
|
advance();
|
||||||
while (!isSourcePastEndOfInput())
|
while (!isSourcePastEndOfInput())
|
||||||
{
|
{
|
||||||
@ -418,15 +417,11 @@ bool Scanner::scanEscape()
|
|||||||
case 't':
|
case 't':
|
||||||
c = '\t';
|
c = '\t';
|
||||||
break;
|
break;
|
||||||
case 'u':
|
|
||||||
if (!scanHexNumber(c, 4))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
c = '\v';
|
c = '\v';
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
if (!scanHexNumber(c, 2))
|
if (!scanHexByte(c))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -468,7 +463,9 @@ void Scanner::scanDecimalDigits()
|
|||||||
|
|
||||||
Token::Value Scanner::scanNumber(bool _periodSeen)
|
Token::Value Scanner::scanNumber(bool _periodSeen)
|
||||||
{
|
{
|
||||||
assert(IsDecimalDigit(m_char)); // the first digit of the number or the fraction
|
// the first digit of the number or the fraction
|
||||||
|
if (asserts(IsDecimalDigit(m_char)))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Number does not start with decimal digit."));
|
||||||
enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
|
enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
|
||||||
LiteralScope literal(this);
|
LiteralScope literal(this);
|
||||||
if (_periodSeen)
|
if (_periodSeen)
|
||||||
@ -510,7 +507,8 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
|
|||||||
// scan exponent, if any
|
// scan exponent, if any
|
||||||
if (m_char == 'e' || m_char == 'E')
|
if (m_char == 'e' || m_char == 'E')
|
||||||
{
|
{
|
||||||
assert(kind != HEX); // 'e'/'E' must be scanned as part of the hex number
|
if (asserts(kind != HEX)) // 'e'/'E' must be scanned as part of the hex number
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
if (kind != DECIMAL) return Token::ILLEGAL;
|
if (kind != DECIMAL) return Token::ILLEGAL;
|
||||||
// scan exponent
|
// scan exponent
|
||||||
addLiteralCharAndAdvance();
|
addLiteralCharAndAdvance();
|
||||||
@ -606,7 +604,8 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
|
|||||||
|
|
||||||
static Token::Value KeywordOrIdentifierToken(string const& input)
|
static Token::Value KeywordOrIdentifierToken(string const& input)
|
||||||
{
|
{
|
||||||
assert(!input.empty());
|
if (asserts(!input.empty()))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
int const kMinLength = 2;
|
int const kMinLength = 2;
|
||||||
int const kMaxLength = 10;
|
int const kMaxLength = 10;
|
||||||
if (input.size() < kMinLength || input.size() > kMaxLength)
|
if (input.size() < kMinLength || input.size() > kMaxLength)
|
||||||
@ -634,7 +633,8 @@ case ch:
|
|||||||
|
|
||||||
Token::Value Scanner::scanIdentifierOrKeyword()
|
Token::Value Scanner::scanIdentifierOrKeyword()
|
||||||
{
|
{
|
||||||
assert(IsIdentifierStart(m_char));
|
if (asserts(IsIdentifierStart(m_char)))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
LiteralScope literal(this);
|
LiteralScope literal(this);
|
||||||
addLiteralCharAndAdvance();
|
addLiteralCharAndAdvance();
|
||||||
// Scan the rest of the identifier characters.
|
// Scan the rest of the identifier characters.
|
||||||
@ -656,7 +656,8 @@ char CharStream::advanceAndGet()
|
|||||||
|
|
||||||
char CharStream::rollback(size_t _amount)
|
char CharStream::rollback(size_t _amount)
|
||||||
{
|
{
|
||||||
assert(m_pos >= _amount);
|
if (asserts(m_pos >= _amount))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
m_pos -= _amount;
|
m_pos -= _amount;
|
||||||
return get();
|
return get();
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ private:
|
|||||||
/// If the next character is _next, advance and return _then, otherwise return _else.
|
/// If the next character is _next, advance and return _then, otherwise return _else.
|
||||||
inline Token::Value selectToken(char _next, Token::Value _then, Token::Value _else);
|
inline Token::Value selectToken(char _next, Token::Value _then, Token::Value _else);
|
||||||
|
|
||||||
bool scanHexNumber(char& o_scannedNumber, int _expectedLength);
|
bool scanHexByte(char& o_scannedByte);
|
||||||
|
|
||||||
/// Scans a single JavaScript token.
|
/// Scans a single JavaScript token.
|
||||||
void scanToken();
|
void scanToken();
|
||||||
|
64
Token.h
64
Token.h
@ -42,9 +42,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
#include <libdevcore/Log.h>
|
#include <libdevcore/Log.h>
|
||||||
|
#include <libsolidity/Exceptions.h>
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
@ -81,8 +81,6 @@ namespace solidity
|
|||||||
T(SEMICOLON, ";", 0) \
|
T(SEMICOLON, ";", 0) \
|
||||||
T(PERIOD, ".", 0) \
|
T(PERIOD, ".", 0) \
|
||||||
T(CONDITIONAL, "?", 3) \
|
T(CONDITIONAL, "?", 3) \
|
||||||
T(INC, "++", 0) \
|
|
||||||
T(DEC, "--", 0) \
|
|
||||||
T(ARROW, "=>", 0) \
|
T(ARROW, "=>", 0) \
|
||||||
\
|
\
|
||||||
/* Assignment operators. */ \
|
/* Assignment operators. */ \
|
||||||
@ -136,6 +134,8 @@ namespace solidity
|
|||||||
/* being contiguous and sorted in the same order! */ \
|
/* being contiguous and sorted in the same order! */ \
|
||||||
T(NOT, "!", 0) \
|
T(NOT, "!", 0) \
|
||||||
T(BIT_NOT, "~", 0) \
|
T(BIT_NOT, "~", 0) \
|
||||||
|
T(INC, "++", 0) \
|
||||||
|
T(DEC, "--", 0) \
|
||||||
K(DELETE, "delete", 0) \
|
K(DELETE, "delete", 0) \
|
||||||
\
|
\
|
||||||
/* Keywords */ \
|
/* Keywords */ \
|
||||||
@ -224,7 +224,8 @@ public:
|
|||||||
// (e.g. "LT" for the token LT).
|
// (e.g. "LT" for the token LT).
|
||||||
static char const* getName(Value tok)
|
static char const* getName(Value tok)
|
||||||
{
|
{
|
||||||
assert(tok < NUM_TOKENS); // tok is unsigned
|
if (asserts(tok < NUM_TOKENS))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
return m_name[tok];
|
return m_name[tok];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,55 +250,10 @@ public:
|
|||||||
isEqualityOp(op) || isInequalityOp(op);
|
isEqualityOp(op) || isInequalityOp(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value negateCompareOp(Value op)
|
|
||||||
{
|
|
||||||
assert(isArithmeticCompareOp(op));
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case EQ:
|
|
||||||
return NE;
|
|
||||||
case NE:
|
|
||||||
return EQ;
|
|
||||||
case LT:
|
|
||||||
return GTE;
|
|
||||||
case GT:
|
|
||||||
return LTE;
|
|
||||||
case LTE:
|
|
||||||
return GT;
|
|
||||||
case GTE:
|
|
||||||
return LT;
|
|
||||||
default:
|
|
||||||
assert(false); // should not get here
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Value reverseCompareOp(Value op)
|
|
||||||
{
|
|
||||||
assert(isArithmeticCompareOp(op));
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case EQ:
|
|
||||||
return EQ;
|
|
||||||
case NE:
|
|
||||||
return NE;
|
|
||||||
case LT:
|
|
||||||
return GT;
|
|
||||||
case GT:
|
|
||||||
return LT;
|
|
||||||
case LTE:
|
|
||||||
return GTE;
|
|
||||||
case GTE:
|
|
||||||
return LTE;
|
|
||||||
default:
|
|
||||||
assert(false); // should not get here
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Value AssignmentToBinaryOp(Value op)
|
static Value AssignmentToBinaryOp(Value op)
|
||||||
{
|
{
|
||||||
assert(isAssignmentOp(op) && op != ASSIGN);
|
if (asserts(isAssignmentOp(op) && op != ASSIGN))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
return Token::Value(op + (BIT_OR - ASSIGN_BIT_OR));
|
return Token::Value(op + (BIT_OR - ASSIGN_BIT_OR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +267,8 @@ public:
|
|||||||
// have a (unique) string (e.g. an IDENTIFIER).
|
// have a (unique) string (e.g. an IDENTIFIER).
|
||||||
static char const* toString(Value tok)
|
static char const* toString(Value tok)
|
||||||
{
|
{
|
||||||
assert(tok < NUM_TOKENS); // tok is unsigned.
|
if (asserts(tok < NUM_TOKENS))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
return m_string[tok];
|
return m_string[tok];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +276,8 @@ public:
|
|||||||
// operators; returns 0 otherwise.
|
// operators; returns 0 otherwise.
|
||||||
static int precedence(Value tok)
|
static int precedence(Value tok)
|
||||||
{
|
{
|
||||||
assert(tok < NUM_TOKENS); // tok is unsigned.
|
if (asserts(tok < NUM_TOKENS))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
return m_precedence[tok];
|
return m_precedence[tok];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
Types.cpp
14
Types.cpp
@ -20,7 +20,6 @@
|
|||||||
* Solidity data types
|
* Solidity data types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <libdevcore/CommonIO.h>
|
#include <libdevcore/CommonIO.h>
|
||||||
#include <libdevcore/CommonData.h>
|
#include <libdevcore/CommonData.h>
|
||||||
#include <libsolidity/Types.h>
|
#include <libsolidity/Types.h>
|
||||||
@ -33,6 +32,9 @@ namespace solidity
|
|||||||
|
|
||||||
std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
|
std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
|
||||||
{
|
{
|
||||||
|
if (asserts(Token::isElementaryTypeName(_typeToken)))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
|
||||||
if (Token::INT <= _typeToken && _typeToken <= Token::HASH256)
|
if (Token::INT <= _typeToken && _typeToken <= Token::HASH256)
|
||||||
{
|
{
|
||||||
int offset = _typeToken - Token::INT;
|
int offset = _typeToken - Token::INT;
|
||||||
@ -52,7 +54,8 @@ std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
|
|||||||
else if (_typeToken == Token::BOOL)
|
else if (_typeToken == Token::BOOL)
|
||||||
return std::make_shared<BoolType>();
|
return std::make_shared<BoolType>();
|
||||||
else
|
else
|
||||||
assert(false); // @todo add other tyes
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
|
||||||
|
std::string(Token::toString(_typeToken)) + " to type."));
|
||||||
return std::shared_ptr<Type>();
|
return std::shared_ptr<Type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +66,7 @@ std::shared_ptr<Type> Type::fromUserDefinedTypeName(UserDefinedTypeName const& _
|
|||||||
|
|
||||||
std::shared_ptr<Type> Type::fromMapping(Mapping const&)
|
std::shared_ptr<Type> Type::fromMapping(Mapping const&)
|
||||||
{
|
{
|
||||||
assert(false); //@todo not yet implemented
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Mapping types not yet implemented."));
|
||||||
return std::shared_ptr<Type>();
|
return std::shared_ptr<Type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +97,8 @@ IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier):
|
|||||||
{
|
{
|
||||||
if (isAddress())
|
if (isAddress())
|
||||||
_bits = 160;
|
_bits = 160;
|
||||||
assert(_bits > 0 && _bits <= 256 && _bits % 8 == 0);
|
if (asserts(_bits > 0 && _bits <= 256 && _bits % 8 == 0))
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid bit number for integer type: " + dev::toString(_bits)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
@ -187,7 +191,7 @@ u256 BoolType::literalValue(Literal const& _literal) const
|
|||||||
else if (_literal.getToken() == Token::FALSE_LITERAL)
|
else if (_literal.getToken() == Token::FALSE_LITERAL)
|
||||||
return u256(0);
|
return u256(0);
|
||||||
else
|
else
|
||||||
assert(false);
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal."));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContractType::operator==(Type const& _other) const
|
bool ContractType::operator==(Type const& _other) const
|
||||||
|
7
Types.h
7
Types.h
@ -26,6 +26,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
|
#include <libsolidity/Exceptions.h>
|
||||||
#include <libsolidity/ASTForward.h>
|
#include <libsolidity/ASTForward.h>
|
||||||
#include <libsolidity/Token.h>
|
#include <libsolidity/Token.h>
|
||||||
|
|
||||||
@ -75,7 +76,11 @@ public:
|
|||||||
virtual unsigned getCalldataEncodedSize() const { return 0; }
|
virtual unsigned getCalldataEncodedSize() const { return 0; }
|
||||||
|
|
||||||
virtual std::string toString() const = 0;
|
virtual std::string toString() const = 0;
|
||||||
virtual u256 literalValue(Literal const&) const { assert(false); }
|
virtual u256 literalValue(Literal const&) const
|
||||||
|
{
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
|
||||||
|
"for type without literals."));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user