diff options
author | Christian <c@ethdev.com> | 2014-11-22 02:14:56 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-24 04:28:45 +0800 |
commit | 583a315d3d282ab9fd871bb2ea3beded367be6d0 (patch) | |
tree | 8471241f34041fe5aadd7fc0a574fef8c80e2aa8 /ExpressionCompiler.cpp | |
parent | c50cd646ce3b8b6c20da747efee89f9420526cae (diff) | |
download | dexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.tar.gz dexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.tar.zst dexon-solidity-583a315d3d282ab9fd871bb2ea3beded367be6d0.zip |
Magic variables.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 85 |
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.")); } |