aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-11-22 02:14:56 +0800
committerChristian <c@ethdev.com>2014-11-24 04:28:45 +0800
commit583a315d3d282ab9fd871bb2ea3beded367be6d0 (patch)
tree8471241f34041fe5aadd7fc0a574fef8c80e2aa8 /ExpressionCompiler.cpp
parentc50cd646ce3b8b6c20da747efee89f9420526cae (diff)
downloaddexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.tar.gz
dexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.tar.zst
dexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.zip
Magic variables.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp85
1 files changed, 57 insertions, 28 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 4d175527..b1a49457 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -162,7 +162,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
{
if (_functionCall.isTypeConversion())
{
- //@todo we only have integers and bools for now which cannot be explicitly converted
+ //@todo struct construction
if (asserts(_functionCall.getArguments().size() == 1))
BOOST_THROW_EXCEPTION(InternalCompilerError());
Expression& firstArgument = *_functionCall.getArguments().front();
@@ -179,6 +179,8 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
}
else
{
+ //@todo: check for "external call" (to be stored in type)
+
// Calling convention: Caller pushes return address and arguments
// Callee removes them and pushes return values
FunctionDefinition const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType()).getFunction();
@@ -193,9 +195,6 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType());
}
_functionCall.getExpression().accept(*this);
- if (asserts(m_currentLValue.isInCode()))
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Code reference expected."));
- m_currentLValue.reset();
m_context.appendJump();
m_context << returnLabel;
@@ -213,19 +212,36 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
{
- if (asserts(m_currentLValue.isInStorage()))
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to a non-storage value."));
- StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
- m_context << type.getStorageOffsetOfMember(_memberAccess.getMemberName()) << eth::Instruction::ADD;
- m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
+ switch (_memberAccess.getExpression().getType()->getCategory())
+ {
+ case Type::Category::INTEGER:
+ if (asserts(_memberAccess.getMemberName() == "balance"))
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer."));
+ m_context << eth::Instruction::BALANCE;
+ break;
+ case Type::Category::CONTRACT:
+ // call function
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Contract variables not yet implemented."));
+ break;
+ case Type::Category::MAGIC:
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Magic variables not yet implemented."));
+ break;
+ case Type::Category::STRUCT:
+ {
+ StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
+ m_context << type.getStorageOffsetOfMember(_memberAccess.getMemberName()) << eth::Instruction::ADD;
+ m_currentLValue = LValue(m_context, LValue::STORAGE);
+ m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
+ break;
+ }
+ default:
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
+ }
}
bool ExpressionCompiler::visit(IndexAccess& _indexAccess)
{
- m_currentLValue.reset();
_indexAccess.getBaseExpression().accept(*this);
- if (asserts(m_currentLValue.isInStorage()))
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Index access to a non-storage value."));
_indexAccess.getIndexExpression().accept(*this);
appendTypeConversion(*_indexAccess.getIndexExpression().getType(),
*dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType(),
@@ -242,8 +258,25 @@ bool ExpressionCompiler::visit(IndexAccess& _indexAccess)
void ExpressionCompiler::endVisit(Identifier& _identifier)
{
- m_currentLValue.fromDeclaration(_identifier, *_identifier.getReferencedDeclaration());
- m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
+ Declaration* declaration = _identifier.getReferencedDeclaration();
+ if (MagicVariableDeclaration* magicVar = dynamic_cast<MagicVariableDeclaration*>(declaration))
+ {
+ if (magicVar->getKind() == MagicVariableDeclaration::VariableKind::THIS)
+ m_context << eth::Instruction::ADDRESS;
+ return;
+ }
+ if (FunctionDefinition* functionDef = dynamic_cast<FunctionDefinition*>(declaration))
+ {
+ m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag();
+ return;
+ }
+ if (VariableDeclaration* varDef = dynamic_cast<VariableDeclaration*>(declaration))
+ {
+ m_currentLValue.fromIdentifier(_identifier, *_identifier.getReferencedDeclaration());
+ m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
+ return;
+ }
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
}
void ExpressionCompiler::endVisit(Literal& _literal)
@@ -410,9 +443,6 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo
{
switch (m_type)
{
- case CODE:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Tried to retrieve value of a function."));
- break;
case STACK:
{
unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset));
@@ -423,11 +453,15 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo
break;
}
case STORAGE:
+ if (!_expression.getType()->isValueType())
+ break; // no distinction between value and reference for non-value types
if (!_remove)
*m_context << eth::Instruction::DUP1;
*m_context << eth::Instruction::SLOAD;
break;
case MEMORY:
+ if (!_expression.getType()->isValueType())
+ break; // no distinction between value and reference for non-value types
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation())
<< errinfo_comment("Location type not yet implemented."));
break;
@@ -455,15 +489,15 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool
break;
}
case LValue::STORAGE:
+ if (!_expression.getType()->isValueType())
+ break; // no distinction between value and reference for non-value types
if (!_move)
*m_context << eth::Instruction::DUP2 << eth::Instruction::SWAP1;
*m_context << eth::Instruction::SSTORE;
break;
- case LValue::CODE:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation())
- << errinfo_comment("Location type does not support assignment."));
- break;
case LValue::MEMORY:
+ if (!_expression.getType()->isValueType())
+ break; // no distinction between value and reference for non-value types
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation())
<< errinfo_comment("Location type not yet implemented."));
break;
@@ -483,7 +517,7 @@ void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression co
}
}
-void ExpressionCompiler::LValue::fromDeclaration(Expression const& _expression, Declaration const& _declaration)
+void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, Declaration const& _declaration)
{
if (m_context->isLocalVariable(&_declaration))
{
@@ -495,13 +529,8 @@ void ExpressionCompiler::LValue::fromDeclaration(Expression const& _expression,
m_type = STORAGE;
*m_context << m_context->getStorageLocationOfVariable(_declaration);
}
- else if (m_context->isFunctionDefinition(&_declaration))
- {
- m_type = CODE;
- *m_context << m_context->getFunctionEntryLabel(dynamic_cast<FunctionDefinition const&>(_declaration)).pushTag();
- }
else
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation())
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_identifier.getLocation())
<< errinfo_comment("Identifier type not supported or identifier not found."));
}