// Append to list
int ListNode::append(VSLNode *list)
{
    // Search end of list
    ListNode *nprev = this;
    VSLNode *node = tail();
    while (node->isListNode())
    {
	nprev = (ListNode *)node; 
	node = nprev->tail();
    }

    // If last element != [], abort (cannot append)
    EmptyListNode empty;
    if (*node != empty)
	return -1;

    // Replace [] by LIST
    delete nprev->tail();
    nprev->tail() = list;

    return 0;
}
Beispiel #2
0
int APLValue::size()
{
    int sz = 1;
    for (ListNode* n = shapedata; !n->isNil(); n = n->tail())
    {
        IntegerExpression* extent = n->head()->isInteger();
        if (extent)
        {
            sz *= extent->val();
        }
    }
    return sz;
}
// Dump
void ListNode::dump(std::ostream &s) const
{
    if (VSEFlags::include_list_info)
    {
	// Formal list
	s << "[" << *head() << "|" << *tail() << "]";
    }
    else
    {
	// Somewhat cuter

	EmptyListNode *empty = new EmptyListNode;

	s << "(";

	const VSLNode *node = this; 
	while (node)
	{
	    if (node->isListNode())
	    {
		if (node != this)
		    s << ", ";

		ListNode *list = (ListNode *)node;
		s << *(list->head());
		node = list->tail();
	    }
	    else
	    {
		if (*node != *empty)
		{
		    if (node != this)
			s << ", ";

		    s << *node << "...";
		}
		node = 0;
	    }
	}

	s << ")";

	delete empty;
    }
}
// ...as tree
void ListNode::_dumpTree(std::ostream& s) const
{
    if (VSEFlags::include_list_info)
    {
	// Formal list
	head()->dumpTree(s);
	s << ",";
	tail()->dumpTree(s);
    }
    else
    {
	// Somewhat cuter

	EmptyListNode *empty = new EmptyListNode;

	const VSLNode *node = this; 
	while (node)
	{
	    if (node->isListNode())
	    {
		if (node != this)
		    s << ", ";

		ListNode *list = (ListNode *)node;
		list->head()->dumpTree(s);
		node = list->tail();
	    }
	    else
	    {
		if (*node != *empty)
		{
		    if (node != this)
			s << ", ";
		    node->dumpTree(s);
		}
		node = 0;
	    }
	}

	delete empty;
    }
}
int BuiltinCallNode::foldOps(VSLDef *cdef, VSLNode** node)
{
    assert (this == *node);
    int changes = 0;

    // Apply on all arguments
    changes += CallNode::foldOps(cdef, node);

    // If non-associative, return
    if (!VSLBuiltin::isAssoc(_index))
	return changes;

    // If arg is not a list, return
    if (!arg()->isListNode())
	return changes;

    ListNode *args = (ListNode *)arg(); // dirty trick

    // First arg must be a builtin call
    if (!args->head()->isBuiltinCallNode())
	return changes;

    BuiltinCallNode *callee = (BuiltinCallNode *)args->head(); // dirty trick

    // First arg must call the same function
    if (_index != callee->_index)
	return changes;

    // Arg must be a list
    if (!callee->arg()->isListNode())
	return changes;

    ListNode *callArgs = (ListNode *)callee->arg(); // dirty trick

    // Insert list
    if (VSEFlags::show_optimize)
    {
	std::cout << "\n" << cdef->longname() << ": foldOps: replacing\n" 
	    << *this << '\n';
	std::cout.flush();
    }

    int err = callArgs->append(args->tail());
    if (err)
    {
	if (VSEFlags::show_optimize)
	{
	    std::cout << "ABORTING (no replace) since append impossible\n";
	    std::cout.flush();
	}
	return changes;
    }

    VSLNode *newArgs = callee->arg();
    callee->arg() = 0; args->tail() = 0; delete args;
    arg() = newArgs;

    if (VSEFlags::show_optimize)
    {
	std::cout << "by " << *this << '\n';
	std::cout.flush();
    }

    changes++;

    return changes;
}
int BuiltinCallNode::foldConsts(VSLDef *cdef, VSLNode** node)
{
    // Apply standard optimization
    int changes = CallNode::foldConsts(cdef, node);

    // If optimization was a success, return
    if (*node != this || isConst())
	return changes;

    // If non-associative, return
    if (!VSLBuiltin::isAssoc(_index))
	return changes;

    // Otherwise: isolate constant args in constant subexpressions and
    // optimize them separately
    for (VSLNode *a = arg();
	 a->isListNode() && ((ListNode *)a)->tail()->isListNode();
	 a = ((ListNode *)a)->tail())
    {
	ListNode *list = (ListNode *)a;
	ListNode *tail = (ListNode *)list->tail();

	VSLNode *arg1 = list->head();
	VSLNode *arg2 = tail->head();

	if (arg1->isConst() && arg2->isConst())
	{
	    if (VSEFlags::show_optimize)
	    {
		std::cout << "\n" << cdef->longname() << ": foldConsts: replacing\n"
		    << *this << '\n';
		std::cout.flush();
	    }

	    // Found 2 args arg1, arg2 that are both constant: Replace
	    // f(..., arg1, arg2, ...) by f(..., f(arg1, arg2), ...)

	    // Create f(arg1, arg2)
	    ListNode *new_args = new FixListNode(arg1, arg2);
	    BuiltinCallNode *new_f = new BuiltinCallNode(_index, new_args);

	    // Move nextarg into f(arg, nextarg)
	    list->head() = new_f;
	    list->tail() = tail->tail();

	    tail->head() = 0; tail->tail() = 0; delete tail;

	    if (VSEFlags::show_optimize)
	    {
		std::cout << "by " << *this << '\n';
		std::cout.flush();
	    }

	    changes++;
	}
    }

    // Now try optimization once again
    changes += CallNode::foldConsts(cdef, node);

    return changes;
}