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; }