package org.scribble.ast.name; import java.util.Arrays; import org.antlr.runtime.tree.CommonTree; import org.scribble.ast.ScribNodeBase; import org.scribble.sesstype.kind.Kind; import org.scribble.sesstype.name.Named; // Kind parameter used for typing help, but NameNodes don't record kind as state (not part of the syntax) -- so kind doesn't affect e.g. equals (i.e. names nodes of different kinds are still only compared syntactically) public abstract class NameNode<K extends Kind> extends ScribNodeBase implements Named<K> { protected final String[] elems; public NameNode(CommonTree source, String... elems) { super(source); this.elems = elems; } @Override public abstract NameNode<K> clone(); public String[] getElements() { return Arrays.copyOf(this.elems, this.elems.length); } public int getElementCount() { return this.elems.length; } public boolean isEmpty() { return this.elems.length == 0; } protected boolean isPrefixed() { return this.elems.length > 1; } protected String[] getPrefixElements() { return Arrays.copyOfRange(this.elems, 0, this.elems.length - 1); } protected String getLastElement() { return this.elems[this.elems.length - 1]; } @Override public boolean equals(Object o) // FIXME: should NameNodes ever be used in an equality checking context? (cf. other AST nodes) -- this work should be done using sesstype.Name instead? { if (this == o) { return true; } if (!(o instanceof NameNode<?>)) { return false; } NameNode<?> nn = (NameNode<?>) o; return nn.canEqual(this) && Arrays.equals(this.elems, nn.elems); } public abstract boolean canEqual(Object o); @Override public int hashCode() { int hash = 317; hash = 31 * hash + this.elems.hashCode(); return hash; } @Override public String toString() { return toName().toString(); } }