/** * This file is part of Erjang - A JVM-based Erlang VM * * Copyright (c) 2009 by Trifork * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package erjang; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; public class EPair extends ECons { public final EObject head; public final EObject tail; public EPair(EObject h, EObject t) { assert (h != null); assert (t != null); this.head = h; this.tail = t; } public ECons testNonEmptyList() { return this; } public EObject head() { return head; } public EObject tail() { return tail; } @Override public String toString() { StringBuffer sb = new StringBuffer("["); EObject val = this; while (val instanceof ECons && val != ERT.NIL) { ECons ep = (ECons) val; if (val != this) { sb.append(","); } sb.append(ep.head()); val = ep.tail(); } if (val != ERT.NIL) { sb.append('|'); sb.append(val); } sb.append("]"); return sb.toString(); } static Type EPAIR_TYPE = Type.getType(EPair.class); static Type ETERM_TYPE = Type.getType(EObject.class); static String CONSTRUCTOR_DESC = "(" + ETERM_TYPE.getDescriptor() + ETERM_TYPE.getDescriptor() + ")V"; @Override public Type emit_const(MethodVisitor fa) { Type type = EPAIR_TYPE; fa.visitTypeInsn(Opcodes.NEW, type.getInternalName()); fa.visitInsn(Opcodes.DUP); ((EObject)head).emit_const(fa); ((EObject)tail).emit_const(fa); fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", CONSTRUCTOR_DESC); return type; } @Override public void encode(EOutputStream eos) { eos.write_list_head(1); eos.write_any(head); eos.write_any(tail); } @Override public int hashCode() { //TODO: use phash() rather than this brittle nonsense: return 31 * head.hashCode() + tail.hashCode(); } }