/******************************************************************************* * Copyright (c) 2009 Centrum Wiskunde en Informatica (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: * Arnold Lankamp - interfaces and implementation * Paul Klint - Implemented replace *******************************************************************************/ package org.rascalmpl.value.impl.fast; import java.util.Iterator; import java.util.Map; import org.rascalmpl.value.IList; import org.rascalmpl.value.INode; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.value.impl.AbstractNode; import org.rascalmpl.value.impl.func.NodeFunctions; import org.rascalmpl.value.type.Type; import org.rascalmpl.value.type.TypeFactory; import org.rascalmpl.value.visitors.IValueVisitor; import io.usethesource.capsule.ArrayIterator; /** * Implementation of INode. * * @author Arnold Lankamp */ /*package*/ class Node extends AbstractNode implements INode { protected final static Type NODE_TYPE = TypeFactory.getInstance().nodeType(); protected final static Type VALUE_TYPE = TypeFactory.getInstance().valueType(); protected final String name; protected final IValue[] children; /*package*/ static INode newNode(String name, IValue[] children) { return new Node(name, children); } private Node(String name, IValue[] children) { super(); this.name = (name != null ? name.intern() : null); // Handle (weird) special case. this.children = children; } /*package*/ static INode newNode(String name, IList children) { return new Node(name, children); } private Node(String name, IList children) { super(); IValue[] childArray = new IValue[children.length()]; this.name = (name != null ? name.intern() : null); // Handle (weird) special case. for(int i = 0; i < childArray.length; i++){ childArray[i] = children.get(i); } this.children = childArray; } /*package*/ static INode newNode(String name, IValue[] children, Map<String, IValue> keyArgValues) { INode node = new Node(name, children, keyArgValues); if (keyArgValues != null && keyArgValues.size() > 0) { return node.asWithKeywordParameters().setParameters(keyArgValues); } return node; } private Node(String name, IValue[] children, Map<String, IValue> keyArgValues) { super(); this.name = (name != null ? name.intern() : null); // Handle (weird) special case. this.children = children; } @Override public Type getType(){ return NODE_TYPE; } @Override public int arity(){ return children.length; } @Override protected IValueFactory getValueFactory() { return ValueFactory.getInstance(); } @Override public IValue get(int i){ return children[i]; } @Override public String getName(){ return name; } @Override public Iterator<IValue> iterator(){ return ArrayIterator.of(children); } @Override public Iterable<IValue> getChildren(){ return this; } @Override public INode set(int i, IValue arg){ IValue[] newChildren = children.clone(); newChildren[i] = arg; return newNode(name, newChildren); } @Override public <T, E extends Throwable> T accept(IValueVisitor<T,E> v) throws E{ return v.visitNode(this); } @Override public int hashCode(){ int hash = name.hashCode(); for(int i = children.length - 1; i >= 0; i--){ hash = (hash << 23) + (hash >> 5); hash ^= children[i].hashCode(); } return hash; } @Override public boolean equals(Object o){ if (o == this) { return true; } if (o == null) { return false; } if (o.getClass() != getClass()) { return false; } Node other = (Node) o; // Yes '!=' works here, since it has been interned. if (name != other.name) { return false; } IValue[] otherChildren = other.children; int nrOfChildren = children.length; if (otherChildren.length != nrOfChildren) { return false; } for (int i = nrOfChildren - 1; i >= 0; i--) { if (!otherChildren[i].equals(children[i])) { return false; } } return true; } /** * TODO: Check if it is easily possible to cast annotatable's content to * List and to reuse old isEqual. */ @Override public boolean isEqual(IValue value){ return NodeFunctions.isEqual(getValueFactory(), this, value); } }