/******************************************************************************* * Copyright (c) 2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI *******************************************************************************/ package org.rascalmpl.value.impl.func; import java.util.ArrayList; import java.util.Iterator; import org.rascalmpl.value.IList; import org.rascalmpl.value.INode; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.value.exceptions.FactTypeUseException; public class NodeFunctions { /* * TODO: merge with ListFunctions.replace(...). Algorithm is exactly the same, the only difference is * that difference interfaces are used (IList, INode). */ public static INode replace(IValueFactory vf, INode node1, int first, int second, int end, IList repl) throws FactTypeUseException, IndexOutOfBoundsException { ArrayList<IValue> newChildren = new ArrayList<>(); int rlen = repl.length(); int increment = Math.abs(second - first); if (first < end) { int childIndex = 0; // Before begin while (childIndex < first) { newChildren.add(node1.get(childIndex++)); } int replIndex = 0; boolean wrapped = false; // Between begin and end while (childIndex < end) { newChildren.add(repl.get(replIndex++)); if (replIndex == rlen) { replIndex = 0; wrapped = true; } childIndex++; //skip the replaced element for (int j = 1; j < increment && childIndex < end; j++) { newChildren.add(node1.get(childIndex++)); } } if (!wrapped) { while (replIndex < rlen) { newChildren.add(repl.get(replIndex++)); } } // After end int dlen = node1.arity(); while (childIndex < dlen) { newChildren.add(node1.get(childIndex++)); } } else { // Before begin (from right to left) int childIndex = node1.arity() - 1; while (childIndex > first) { newChildren.add(0, node1.get(childIndex--)); } // Between begin (right) and end (left) int replIndex = 0; boolean wrapped = false; while (childIndex > end) { newChildren.add(0, repl.get(replIndex++)); if (replIndex == repl.length()) { replIndex = 0; wrapped = true; } childIndex--; //skip the replaced element for (int j = 1; j < increment && childIndex > end; j++) { newChildren.add(0, node1.get(childIndex--)); } } if (!wrapped) { while (replIndex < rlen) { newChildren.add(0, repl.get(replIndex++)); } } // Left of end while (childIndex >= 0) { newChildren.add(0, node1.get(childIndex--)); } } IValue[] childArray = new IValue[newChildren.size()]; newChildren.toArray(childArray); return vf.node(node1.getName(), childArray); } public static boolean isEqual(IValueFactory vf, INode node1, IValue value) { if(value == node1) return true; if(value == null) return false; if (node1.getType() != value.getType()) { return false; } if (value instanceof INode) { INode node2 = (INode) value; // Object equality ('==') is not applicable here // because value is cast to {@link INode}. if (!node1.getName().equals(node2.getName())) { return false; } if (node1.arity() != node2.arity()) { return false; } Iterator<IValue> it1 = node1.iterator(); Iterator<IValue> it2 = node2.iterator(); while (it1.hasNext()) { if (!it1.next().isEqual(it2.next())) { return false; } } if (node1.mayHaveKeywordParameters() && node2.mayHaveKeywordParameters()) { return node1.asWithKeywordParameters().equalParameters(node2.asWithKeywordParameters()); } if (node1.mayHaveKeywordParameters() && node1.asWithKeywordParameters().hasParameters()) { return false; } if (node2.mayHaveKeywordParameters() && node2.asWithKeywordParameters().hasParameters()) { return false; } return true; } return false; } }