//! Possible call target node types:
//! - SymbolASTNode
//! - ExprASTNode
//!
//! Possible call argument node types:
//! - ExprASTNode
//! - NULL
OperationSequence * ConversionController::convertCallStatement(CallStatementASTNode * statement)
{
	ExecuteOperation * op = NULL;
	
	try
	{
		// create operation from AST nodes
		op = new ExecuteOperation();
		
		bool isHAB = statement->isHAB();
		
		op->setTarget(createTargetFromNode(statement->getTarget()));
		
		// set argument value, which defaults to 0 if no expression was provided
		uint32_t arg = 0;
		ASTNode * argNode = statement->getArgument();
		if (argNode)
		{
			ExprASTNode * argExprNode = dynamic_cast<ExprASTNode*>(argNode);
			if (!argExprNode)
			{
				throw semantic_error(format_string("line %d: call argument is unexpected type", argNode->getFirstLine()));
			}
			argExprNode = argExprNode->reduce(m_context);
			IntConstExprASTNode * intNode = dynamic_cast<IntConstExprASTNode*>(argExprNode);
			if (!intNode)
			{
				throw semantic_error(format_string("line %d: call argument did not evaluate to an integer", argExprNode->getFirstLine()));
			}
			
			arg = intNode->getValue();
		}
		op->setArgument(arg);
		
		// set call type
		switch (statement->getCallType())
		{
			case CallStatementASTNode::kCallType:
				op->setExecuteType(ExecuteOperation::kCall);
				break;
			case CallStatementASTNode::kJumpType:
				op->setExecuteType(ExecuteOperation::kJump);
				break;
		}
		
		// Set the HAB mode flag.
		op->setIsHAB(isHAB);
		
		return new OperationSequence(op);
	}
	catch (...)
	{
		// delete op and rethrow exception
		if (op)
		{
			delete op;
		}
		throw;
	}
}
//! @param node The AST node instance for the assignment expression.
//! @param[out] ident Upon exit this string will be set the the left hand side of the
//!		assignment expression, the identifier name.
//!
//! @return An object that is a subclass of Value is returned. The specific subclass will
//!		depend on the type of the right hand side of the assignment expression whose AST
//!		node was provided in the @a node argument.
//!
//! @exception semantic_error Thrown for any error where an AST node is an unexpected type.
//!		This may be the @a node argument itself, if it is not an AssignmentASTNode. Or it
//!		may be an unexpected type for either the right or left hand side of the assignment.
//!		The message for the exception will contain a description of the error.
Value * ConversionController::convertAssignmentNodeToValue(ASTNode * node, std::string & ident)
{
	Value * resultValue = NULL;
	
	// each item of the options list should be an assignment node
	AssignmentASTNode * assignmentNode = dynamic_cast<AssignmentASTNode*>(node);
	if (!node)
	{
		throw semantic_error(format_string("line %d: node is wrong type", assignmentNode->getFirstLine()));
	}
	
	// save the left hand side (the identifier) into ident
	ident = *assignmentNode->getIdent();
	
	// get the right hand side and convert it to a Value instance
	ASTNode * valueNode = assignmentNode->getValue();
	StringConstASTNode * str;
	ExprASTNode * expr;
	if (str = dynamic_cast<StringConstASTNode*>(valueNode))
	{
		// the option value is a string constant
		resultValue = new StringValue(str->getString());

//#if PRINT_VALUES
//		Log::log("option %s => \'%s\'\n", ident->c_str(), str->getString()->c_str());
//#endif
	}
	else if (expr = dynamic_cast<ExprASTNode*>(valueNode))
	{
		ExprASTNode * reducedExpr = expr->reduce(m_context);
		IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(reducedExpr);
		if (!intConst)
		{
			throw semantic_error(format_string("line %d: expression didn't evaluate to an integer", expr->getFirstLine()));
		}
		
//#if PRINT_VALUES
//		Log::log("option ");
//		printIntConstExpr(*ident, intConst);
//#endif
		
		resultValue = new SizedIntegerValue(intConst->getValue(), intConst->getSize());
	}
	else
	{
		throw semantic_error(format_string("line %d: right hand side node is an unexpected type", valueNode->getFirstLine()));
	}
	
	return resultValue;
}
DataSource * ConversionController::createIVTDataSource(IVTConstASTNode * ivtNode)
{
    IVTDataSource * source = new IVTDataSource;
    
    // Iterate over the assignment statements in the IVT definition.
    ListASTNode * fieldList = ivtNode->getFieldAssignments();
    
    if (fieldList)
    {
        ListASTNode::iterator it = fieldList->begin();
        for (; it != fieldList->end(); ++it)
        {
            AssignmentASTNode * assignmentNode = dynamic_cast<AssignmentASTNode*>(*it);
            if (!assignmentNode)
            {
                throw std::runtime_error(format_string("line %d: unexpected node type in IVT definition", (*it)->getFirstLine()));
            }
            
            // Get the IVT field name.
            std::string * fieldName = assignmentNode->getIdent();
            
            // Reduce the field expression and get the integer result.
            ASTNode * valueNode = assignmentNode->getValue();
            ExprASTNode * valueExpr = dynamic_cast<ExprASTNode*>(valueNode);
            if (!valueExpr)
            {
                throw semantic_error("IVT field must have a valid expression");
            }
            IntConstExprASTNode * valueIntExpr = dynamic_cast<IntConstExprASTNode*>(valueExpr->reduce(m_context));
            if (!valueIntExpr)
            {
                throw semantic_error(format_string("line %d: IVT field '%s' does not evaluate to an integer", valueNode->getFirstLine(), fieldName->c_str()));
            }
            uint32_t value = static_cast<uint32_t>(valueIntExpr->getValue());
            
            // Set the field in the IVT data source.
            if (!source->setFieldByName(*fieldName, value))
            {
                throw semantic_error(format_string("line %d: unknown IVT field '%s'", assignmentNode->getFirstLine(), fieldName->c_str()));
            }
        }
    }
    
    return source;
}