trifork$erjang
return "'" + encode_escapes(value) + "'";
EAtom
EAtom testAtom()
return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;
EAtom
EAtom asAtom()
trifork$erjang
return "'" + encode_escapes(value) + "'";
EAtom
EAtom testAtom()
return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;
EAtom
EAtom asAtom()
trifork$erjang
ECons
ECons testCons()
ECons
ECons asCons()
trifork$erjang
ECons
ECons testCons()
ECons
ECons asCons()
trifork$erjang
EInteger
EInteger testInteger()
EInteger
EInteger asInteger()
trifork$erjang
EInteger
EInteger testInteger()
EInteger
EInteger asInteger()
trifork$erjang
ENumber
ENumber testNumber()
ENumber
ENumber asNumber()
trifork$erjang
ENumber
ENumber testNumber()
ENumber
ENumber asNumber()
trifork$erjang
EPID
EPID testPID()
EPID
EPID asPID()
trifork$erjang
EPID
EPID testPID()
EPID
EPID asPID()
trifork$erjang
ESeq
ESeq testSeq()
ESeq
ESeq asSeq()
trifork$erjang
ESeq
ESeq testSeq()
ESeq
ESeq asSeq()
trifork$erjang
ETuple
ETuple testTuple()
ETuple
ETuple asTuple()
trifork$erjang
ETuple
ETuple testTuple()
ETuple
ETuple asTuple()
trifork$erjang
int i
EObject
EObject elm(int i)
int i
EObject
EObject nth(int i)
trifork$erjang
int i
EObject
EObject elm(int i)
int i
EObject
EObject nth(int i)
trifork$erjang
int i
EObject
EObject elm(int i)
int i
EObject
EObject nth(int i)
trifork$erjang
int i
EObject
EObject elm(int i)
int i
EObject
EObject nth(int i)
trifork$erjang
int i
EObject
EObject elm(int i)
int i
EObject
EObject nth(int i)
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/.classpath
https://api.github.com/repos/trifork/erjang/contents/.classpath?ref=070f8a4124a580cd7a140029dee655beeae8540b
.classpath
	<classpathentry kind="lib" path="lib/asm-xml-3.2.jar"/>
@@ -10,5 +10,6 @@
 	<classpathentry kind="lib" path="lib/asm-analysis-3.2.jar"/>
 	<classpathentry kind="lib" path="lib/asm-util-3.2.jar"/>
 	<classpathentry kind="lib" path="lib/asm-tree-3.2.jar"/>
+	<classpathentry kind="lib" path="lib/asm-xml-3.2.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/.classpath
657678d24a2cff764e5c0e4527868d212e50acad
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEAtom.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEAtom.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EAtom.java
	public EAtom testAtom() {

			return "'" + encode_escapes(value) + "'";
		}
	}

	/**
	 * @param value2
	 * @return
	 */
	private String encode_escapes(CharSequence seq) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < seq.length(); i++) {
			char ch = seq.charAt(i);
			if ((ch >= 0x20 && ch <= 0xff) && ch != '\'' && ch != 0x7f) {
				sb.append(ch);
			} else {
				switch (ch) {
				case '\t':
					sb.append("\\t");
					break;
				case '\n':
					sb.append("\\n");
					break;
				case '\r':
					sb.append("\\r");
					break;
				case '\f':
					sb.append("\\f");
					break;
				case '\b':
					sb.append("\\b");
					break;
				case '\'':
					sb.append("\\'");
					break;
				default:
					sb.append("\\");
					String.format("%2x", (int) ch);
					// TODO: figure out if this is right
				}
			}
		return sb.toString();

	public boolean isAtom(String name) {




				"intern", "(" + STRING_TYPE.getDescriptor() + ")"
						+ type.getDescriptor());
		return type;
	}
src/erjang/EAtom.java
return "'" + encode_escapes(value) + "'";
EAtom testAtom()
CharSequence seq
src/erjang/EAtom.java
StringBuffer sb = new StringBuffer();
		for (int i = 0; i < seq.length(); i++) {
			char ch = seq.charAt(i);
			if ((ch >= 0x20 && ch <= 0xff) && ch != '\'' && ch != 0x7f) {
				sb.append(ch);
String encode_escapes(CharSequence seq)
String name
src/erjang/EAtom.java
"intern", "(" + STRING_TYPE.getDescriptor() + ")"
						+ type.getDescriptor());
		return type;
boolean isAtom(String name)

	public EAtom asAtom() {
	
			return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;	
	}
src/erjang/EAtom.java
return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;
EAtom asAtom()
@@ -21,15 +21,14 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Pattern;
 
-
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 
 import erjang.jbeam.ops.CodeAdapter;
 
 public class EAtom extends ETerm implements CharSequence {
 
-	public EAtom asAtom() {
+	public EAtom testAtom() {
 		return this;
 	}
 
@@ -42,31 +41,70 @@ private EAtom(String name) {
 	}
 
 	Pattern ATOM = Pattern.compile("[a-z_]([a-z]|[A-Z]|@|_|[0-9])*");
-	
+
 	@Override
 	public String toString() {
 		if (ATOM.matcher(value).matches()) {
 			return value;
 		} else {
-			return "'" + value + "'";
+			return "'" + encode_escapes(value) + "'";
+		}
+	}
+
+	/**
+	 * @param value2
+	 * @return
+	 */
+	private String encode_escapes(CharSequence seq) {
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < seq.length(); i++) {
+			char ch = seq.charAt(i);
+			if ((ch >= 0x20 && ch <= 0xff) && ch != '\'' && ch != 0x7f) {
+				sb.append(ch);
+			} else {
+				switch (ch) {
+				case '\t':
+					sb.append("\\t");
+					break;
+				case '\n':
+					sb.append("\\n");
+					break;
+				case '\r':
+					sb.append("\\r");
+					break;
+				case '\f':
+					sb.append("\\f");
+					break;
+				case '\b':
+					sb.append("\\b");
+					break;
+				case '\'':
+					sb.append("\\'");
+					break;
+				default:
+					sb.append("\\");
+					String.format("%2x", (int) ch);
+					// TODO: figure out if this is right
+				}
+			}
 		}
+		return sb.toString();
 	}
-	
-	public boolean isAtom(String name)
-	{
+
+	public boolean isAtom(String name) {
 		return interns.contains(name);
 	}
-	
+
 	@Override
 	public boolean equals(Object obj) {
 		return this == obj;
 	}
- 
+
 	@Override
 	public int hashCode() {
 		return value.hashCode();
 	}
-	
+
 	public static EAtom intern(String name) {
 
 		EAtom res = interns.get(name);
@@ -80,8 +118,6 @@ public static EAtom intern(String name) {
 		return res;
 	}
 
-
-
 	@Override
 	public char charAt(int index) {
 		return value.charAt(index);
@@ -101,21 +137,20 @@ public String getName() {
 		return value;
 	}
 
-
 	private static final Type EATOM_TYPE = Type.getType(EAtom.class);
 	private static final Type STRING_TYPE = Type.getType(String.class);
 
 	@Override
 	public org.objectweb.asm.Type emit_const(CodeAdapter fa) {
 
 		Type type = EATOM_TYPE;
-		
+
 		fa.visitLdcInsn(value);
 		fa.visitMethodInsn(Opcodes.INVOKESTATIC, type.getInternalName(),
-					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
-		
-		return type;	
-	}
+				"intern", "(" + STRING_TYPE.getDescriptor() + ")"
+						+ type.getDescriptor());
 
+		return type;
+	}
 
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEAtom.java
8a163f56e54162c913c6dfe8fbd65f14e3235eb5
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FECons.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FECons.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ECons.java
	public static final ENil NIL = new ENil();
	public ECons testCons() {
		while (cell != NIL && (cell instanceof ECons)) {
	public static final ENil EMPTY = new ENil();
	public ECons asCons() {
		while (cell != EMPTY && (cell instanceof ECons)) {
@@ -20,20 +20,20 @@
 
 public abstract class ECons extends ETerm {
 
-	public static final ENil EMPTY = new ENil();
+	public static final ENil NIL = new ENil();
 
 	public abstract EObject head();
 	public abstract EObject tail();
 	
-	public ECons asCons() {
+	public ECons testCons() {
 		return this;
 	}
 
 	// generic count function that also works for non-well-formed lists
 	public int count() {
 		EObject cell = tail();
 		int count = 1;
-		while (cell != EMPTY && (cell instanceof ECons)) {
+		while (cell != NIL && (cell instanceof ECons)) {
 			cell = ((ECons)cell).tail();
 			count += 1;
 		}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FECons.java
ed18e0f684e0f313d70d68f46690759c21f70f86
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEInteger.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEInteger.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EInteger.java
	public EInteger testInteger() {
	public EInteger asInteger() {
@@ -33,7 +33,7 @@ public EInteger(int value)
 		this.value = value;
 	}
 	
-	public EInteger asInteger() {
+	public EInteger testInteger() {
 		return this;
 	}
 
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEInteger.java
16b52a865a29ff85092c265f6b8cb3e74dd3f07b
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEList.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEList.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EList.java
		if (tail == null) tail = NIL;
	public ECons testNonEmptyList() {
		return this;
	}
	
		while (val != ECons.NIL) {
src/erjang/EList.java
return this;
ECons testNonEmptyList()
		if (tail == null) tail = EMPTY;
		while (val != ECons.EMPTY) {
@@ -29,12 +29,16 @@ public class EList extends ESeq {
 	private final ESeq tail;
 	
 	public EList(EObject h, ESeq tail) {
-		if (tail == null) tail = EMPTY;
+		if (tail == null) tail = NIL;
 		
 		this.head = h;
 		this.tail = tail;
 	}
 	
+	public ECons testNonEmptyList() {
+		return this;
+	}
+	
 	// only for ENil!
 	protected EList() {
 		head = tail = null;
@@ -62,7 +66,7 @@ public String toString() {
 		StringBuffer sb = new StringBuffer("[");
 		
 		ESeq val = this;
-		while (val != ECons.EMPTY) {
+		while (val != ECons.NIL) {
 			if (val != this) { sb.append(","); }
 			sb.append(val.head());
 			val = val.tail();
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEList.java
528e34ddde5f0dcf161fbc0a0447c3e8e302f70e
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FENil.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FENil.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ENil.java
	
	public ENil testNil() {
		return this;
	}


src/erjang/ENil.java
return this;
ENil testNil()
@@ -57,4 +57,10 @@ public Type emit_const(CodeAdapter fa) {
 		fa.visitFieldInsn(Opcodes.GETSTATIC, ECONS_TYPE.getInternalName(), "EMPTY", ENIL_TYPE.getDescriptor());
 		return ENIL_TYPE;
 	}
+	
+	public ENil testNil() {
+		return this;
+	}
+
+
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FENil.java
0816f3acfe124ec0171fc2036cf361cec68372a9
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FENumber.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FENumber.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ENumber.java
	public ENumber testNumber() {
	public ENumber asNumber() {
@@ -34,7 +34,7 @@ public static ENumber parseInt(String str) {
          }
 	}
 
-	public ENumber asNumber() {
+	public ENumber testNumber() {
 		return this;
 	}
 
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FENumber.java
abbee1885edab1c76a26e36a52e2521407bfd1e5
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEObject.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEObject.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EObject.java
	public EAtom testAtom() {
	public ECons testNonEmptyList() {
		return null;
	}
	
	public ETuple testTuple() {
	public ESeq testSeq() {
	public EPID testPID() {
	public ENumber testNumber() {
	public ECons testCons() {
	public EInteger testInteger() {
		return null;
	}
	public ENil testNil() {
src/erjang/EObject.java
public ECons testNonEmptyList() {
		return null;
EAtom testAtom()
src/erjang/EObject.java
public ESeq testSeq() {
	public EPID testPID() {
	public ENumber testNumber() {
	public ECons testCons() {
	public EInteger testInteger() {
		return null;
ETuple testTuple()
	public EAtom asAtom() {
	public ETuple asTuple() {
	public ESeq asSeq() {
	public EPID asPID() {
	public ENumber asNumber() {

	public ECons asCons() {
	public EInteger asInteger() {
@@ -26,37 +26,43 @@ public ECons cons(EObject h)
 	}
 	
 
-	public EAtom asAtom() {
+	public EAtom testAtom() {
 		return null;
 	}
 
-	public ETuple asTuple() {
+	public ECons testNonEmptyList() {
+		return null;
+	}
+	
+	public ETuple testTuple() {
 		return null;
 	}
 
-	public ESeq asSeq() {
+	public ESeq testSeq() {
 		return null;
 	}
 
-	public EPID asPID() {
+	public EPID testPID() {
 		return null;
 	}
 
 	public int asInt() {
 		throw new RuntimeException("cannot convert " + this + " to int");
 	}
 
-	public ENumber asNumber() {
+	public ENumber testNumber() {
 		return null;
 	}
 
-
-	public ECons asCons() {
+	public ECons testCons() {
 		return null;
 	}
 
+	public EInteger testInteger() {
+		return null;
+	}
 
-	public EInteger asInteger() {
+	public ENil testNil() {
 		return null;
 	}
 
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEObject.java
2f53a8d55cac016f99c21707bfba3b57e5aa7ecb
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEPID.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEPID.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EPID.java
	public EPID testPID() {
	public EPID asPID() {
@@ -20,7 +20,7 @@
 
 public class EPID extends EObject {
 
-	public EPID asPID() {
+	public EPID testPID() {
 		return this;
 	}
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEPID.java
025ecae946d85b97b6724ae21bec5e1966027dbd
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEPair.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEPair.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EPair.java
	public ECons testNonEmptyList() {
		return this;
	}
	
		while (val instanceof ECons && val != NIL) {
		if (val != NIL) {
src/erjang/EPair.java
return this;
ECons testNonEmptyList()
		while (val instanceof ECons && val != EMPTY) {
		if (val != EMPTY) {
@@ -36,6 +36,10 @@ public EPair(EObject h, EObject t) {
 		this.tail = t;
 	}
 
+	public ECons testNonEmptyList() {
+		return this;
+	}
+	
 
 	public EObject head() {
 		return head;
@@ -50,14 +54,14 @@ public String toString() {
 		StringBuffer sb = new StringBuffer("[");
 		
 		EObject val = this;
-		while (val instanceof ECons && val != EMPTY) {
+		while (val instanceof ECons && val != NIL) {
 			ECons ep = (ECons) val;
 			if (val != this) { sb.append(","); }
 			sb.append(ep.head());
 			val = ep.tail();
 		}
 		
-		if (val != EMPTY) {
+		if (val != NIL) {
 			sb.append('|');
 			sb.append(val);
 		}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEPair.java
2fdb01692e2088148e39101e61c665b37af07796
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FERT.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FERT.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ERT.java
	public static ETerm cons(EObject h, EObject t) {
		return t.cons(h);
	public static final EAtom ATOM_TRUE = EAtom.intern("true");
	public static final EAtom ATOM_FALSE = EAtom.intern("false");
	
	public static boolean eq(EObject o1, EObject o2) { return o1==null?o2==null:o1.equals(o2); }
	public static boolean eq(EObject o1, EAtom o2) { return o1==o2; }
	public static boolean eq(EAtom o1, EObject o2) { return o1==o2; }
	public static boolean eq(EAtom o1, EAtom o2) { return o1==o2; }

EObject h  EObject t
src/erjang/ERT.java
return t.cons(h);
	public static final EAtom ATOM_TRUE = EAtom.intern("true");
	public static final EAtom ATOM_FALSE = EAtom.intern("false");
	
	public static boolean eq(EObject o1, EObject o2) { return o1==null?o2==null:o1.equals(o2);
ETerm cons(EObject h, EObject t)
EObject o1  EAtom o2
src/erjang/ERT.java
return o1==o2;
boolean eq(EObject o1, EAtom o2)
EAtom o1  EObject o2
src/erjang/ERT.java
return o1==o2;
boolean eq(EAtom o1, EObject o2)
EAtom o1  EAtom o2
src/erjang/ERT.java
return o1==o2;
boolean eq(EAtom o1, EAtom o2)
	public static ETerm cons(EObject h, ETerm t) {
		if (t instanceof ECons) {
			return ((ECons) t).cons(h);
		} else {
			return new EPair(h, t);
		}
	}

	public static ETerm cons(ETerm h, ECons t) {
		return ((ECons) t).cons(h);
EObject h  ETerm t
src/erjang/ERT.java
if (t instanceof ECons) {
			return ((ECons) t).cons(h);
ETerm cons(EObject h, ETerm t)
@@ -24,16 +24,8 @@ public class ERT {
 	public static final EAtom AM_BADMATCH = EAtom.intern("badmatch");
 	public static final EAtom AM_BADARITH = EAtom.intern("badarith");
 
-	public static ETerm cons(EObject h, ETerm t) {
-		if (t instanceof ECons) {
-			return ((ECons) t).cons(h);
-		} else {
-			return new EPair(h, t);
-		}
-	}
-
-	public static ETerm cons(ETerm h, ECons t) {
-		return ((ECons) t).cons(h);
+	public static ETerm cons(EObject h, EObject t) {
+		return t.cons(h);
 	}
 
 	public static ErlangException badarith(ArithmeticException cause,
@@ -64,4 +56,12 @@ public static ErlangException badarg(EObject arg1, int arg2) {
 		throw new ErlangException(AM_BADARG);
 	}
 
+	public static final EAtom ATOM_TRUE = EAtom.intern("true");
+	public static final EAtom ATOM_FALSE = EAtom.intern("false");
+	
+	public static boolean eq(EObject o1, EObject o2) { return o1==null?o2==null:o1.equals(o2); }
+	public static boolean eq(EObject o1, EAtom o2) { return o1==o2; }
+	public static boolean eq(EAtom o1, EObject o2) { return o1==o2; }
+	public static boolean eq(EAtom o1, EAtom o2) { return o1==o2; }
+
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FERT.java
31d6581f75d51cbfd0a3b53fec3fa1c6fa3dc240
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FESeq.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FESeq.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ESeq.java
	public ESeq testSeq() {
		while (curr != NIL) {
		while (curr != NIL) {
	public ESeq asSeq() {
		while (curr != EMPTY) {
		while (curr != EMPTY) {
@@ -24,7 +24,7 @@
 
 public abstract class ESeq extends ECons {
 
-	public ESeq asSeq() {
+	public ESeq testSeq() {
 		return this;
 	}
 
@@ -36,7 +36,7 @@ public ESeq asSeq() {
 	public EObject[] toArray() {
 		List<EObject> out = new ArrayList<EObject>();
 		ESeq curr = this;
-		while (curr != EMPTY) {
+		while (curr != NIL) {
 			out.add(curr.head());
 			curr = curr.tail();
 		}
@@ -46,7 +46,7 @@ public EObject[] toArray() {
 	public int length() {
 		int count = 0;
 		ESeq curr = this;
-		while (curr != EMPTY) {
+		while (curr != NIL) {
 			count += 1;
 			curr = curr.tail();
 		}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FESeq.java
224263b9213beb0c3f8a4cc57505347505155cf0
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEString.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FEString.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/EString.java
public class EString extends ESeq implements CharSequence {
	private byte[] data;
	private int off;
	private int hash = -1;
	private EString(byte[] data, int off)
	{
		this.data = data;
		this.off = off;
	}
	
		if (hash == -1) { hash = stringValue().hashCode(); }
		return new String(data, off, data.length-off, ISO_LATIN_1);
			
			int len1 = data.length-off;
			int len2 = es.data.length-es.off;
			
			if (len1 != len2) return false;
			
			for (int i = 0; i < len1; i++) {
				if (data[off+i] != es.data[es.off+i]) return false;
			return true;

		} else if (obj instanceof String) {			
			return stringValue().equals(obj);
		return (char) (data[off+index] & 0xff);
		return data.length-off;
		if (end == length()) return new EString(data, off+start);
		if (offset < 0 || length < 0 || (offset+length) > length())
	/* (non-Javadoc)
	 * @see erjang.ESeq#cons(erjang.EObject)
	 */
	@Override
	public EList cons(EObject h) {
		return new EList(h, this);
	}

	/* (non-Javadoc)
	 * @see erjang.ESeq#tail()
	 */
	@Override
	public ESeq tail() {
		if (off == data.length) return ENil.NIL;
		return new EString(data, off+1);
	}

	/* (non-Javadoc)
	 * @see erjang.ECons#head()
	 */
	@Override
	public EInteger head() {
		return new EInteger(data[off] & 0xff);
	}

	@Override
	public ENil testNil() {
		return length() == 0 ? ENil.NIL : null;
	}

	public ECons testNonEmptyList() {
		return length() == 0 ? null : this;
	}
	
byte[] data  int off
src/erjang/EString.java
this.data = data;
		this.off = off;
private EString(byte[] data, int off)
obj instanceof String
src/erjang/EString.java
return stringValue().equals(obj);
		return (char) (data[off+index] & 0xff);
		return data.length-off;
		if (end == length()) return new EString(data, off+start);
		if (offset < 0 || length < 0 || (offset+length) > length())
	/* (non-Javadoc)
	 * @see erjang.ESeq#cons(erjang.EObject)
	 */
	@Override
	public EList cons(EObject h) {
		return new EList(h, this);
else if (obj instanceof String)
src/erjang/EString.java
if (off == data.length) return ENil.NIL;
		return new EString(data, off+1);
ESeq tail()
src/erjang/EString.java
return new EInteger(data[off] & 0xff);
EInteger head()
src/erjang/EString.java
return length() == 0 ? ENil.NIL : null;
ENil testNil()
src/erjang/EString.java
return length() == 0 ? null : this;
ECons testNonEmptyList()
public class EString extends ETerm implements CharSequence {
	byte[] data;
	int hash;
		return new String(data, ISO_LATIN_1);
			return es.hash == hash && Arrays.equals(es.data, data);

		} else if (obj instanceof String) {
			if ( hash == obj.hashCode() ) {
				
		return (char) (data[index] & 0xff);
		return data.length;
		if (offset < 0 || length < 0 || (offset+length) > data.length)
@@ -26,55 +26,71 @@
 
 import erjang.jbeam.ops.CodeAdapter;
 
-public class EString extends ETerm implements CharSequence {
+public class EString extends ESeq implements CharSequence {
 
 	private static final Charset ISO_LATIN_1 = Charset.forName("ISO-8859-1");
 	
-	byte[] data;
-	int hash;
+	private byte[] data;
+	private int off;
+	private int hash = -1;
 	
 	public EString(String value) {
 		this.hash = value.hashCode();
 		this.data = value.getBytes(ISO_LATIN_1);
 	}
 
+	private EString(byte[] data, int off)
+	{
+		this.data = data;
+		this.off = off;
+	}
+	
 	@Override
 	public int hashCode() {
+		if (hash == -1) { hash = stringValue().hashCode(); }
 		return hash;
 	}
 	
 	public String stringValue() {
-		return new String(data, ISO_LATIN_1);
+		return new String(data, off, data.length-off, ISO_LATIN_1);
 	}
 	
 	@Override
 	public boolean equals(Object obj) {
 		if (obj instanceof EString) {
 			EString es = (EString) obj;
-			return es.hash == hash && Arrays.equals(es.data, data);
-
-		} else if (obj instanceof String) {
-			if ( hash == obj.hashCode() ) {
-				
+			
+			int len1 = data.length-off;
+			int len2 = es.data.length-es.off;
+			
+			if (len1 != len2) return false;
+			
+			for (int i = 0; i < len1; i++) {
+				if (data[off+i] != es.data[es.off+i]) return false;
 			}
 			
+			return true;
+
+		} else if (obj instanceof String) {			
+			return stringValue().equals(obj);
 		}
 		
 		return false;
 	}
 
 	@Override
 	public char charAt(int index) {
-		return (char) (data[index] & 0xff);
+		return (char) (data[off+index] & 0xff);
 	}
 
 	@Override
 	public int length() {
-		return data.length;
+		return data.length-off;
 	}
 
 	@Override
 	public CharSequence subSequence(final int start, final int end) {		
+		if (end == length()) return new EString(data, off+start);
 		return new SubSequence(start, end-start);
 	}
 	
@@ -108,7 +124,7 @@ public CharSequence subSequence(int start, int end) {
 	}
 
 	void check_subseq(int offset, int length) {
-		if (offset < 0 || length < 0 || (offset+length) > data.length)
+		if (offset < 0 || length < 0 || (offset+length) > length())
 			throw new IllegalArgumentException();
 	}
 	
@@ -136,5 +152,39 @@ public Type emit_const(CodeAdapter fa) {
 		return type;
 	}
 
+	/* (non-Javadoc)
+	 * @see erjang.ESeq#cons(erjang.EObject)
+	 */
+	@Override
+	public EList cons(EObject h) {
+		return new EList(h, this);
+	}
+
+	/* (non-Javadoc)
+	 * @see erjang.ESeq#tail()
+	 */
+	@Override
+	public ESeq tail() {
+		if (off == data.length) return ENil.NIL;
+		return new EString(data, off+1);
+	}
+
+	/* (non-Javadoc)
+	 * @see erjang.ECons#head()
+	 */
+	@Override
+	public EInteger head() {
+		return new EInteger(data[off] & 0xff);
+	}
+
+	@Override
+	public ENil testNil() {
+		return length() == 0 ? ENil.NIL : null;
+	}
+
+	public ECons testNonEmptyList() {
+		return length() == 0 ? null : this;
+	}
+	
 
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FEString.java
ab50df9649cbfc8ea0c725fc79715149add91cc4
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple.java
	public ETuple testTuple() {
	public abstract EObject elm(int i);
		mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "elm", "(I)"
			sb.append(elm(i));
			fa.emit_const(elm(i + 1));
	public ETuple asTuple() {
	public abstract EObject nth(int i);
		mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "nth", "(I)"
			sb.append(nth(i));
			fa.emit_const(nth(i + 1));
@@ -37,13 +37,13 @@
 
 public abstract class ETuple extends ETerm implements Cloneable {
 
-	public ETuple asTuple() {
+	public ETuple testTuple() {
 		return this;
 	}
 
 	public abstract int arity();
 
-	public abstract EObject nth(int i);
+	public abstract EObject elm(int i);
 
 	public static ETuple make(int len) {
 		switch (len) {
@@ -232,7 +232,7 @@ private static void make_blank_bridge(ClassAdapter cw,
 	private static void create_tuple_nth(int n_cells, ClassAdapter cw,
 			String this_class_name) {
 		MethodVisitor mv;
-		mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "nth", "(I)"
+		mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "elm", "(I)"
 				+ ETERM_TYPE.getDescriptor(), null, null);
 		mv.visitCode();
 
@@ -373,7 +373,7 @@ public String toString() {
 		for (int i = 1; i <= this.arity(); i++) {
 			if (i != 1)
 				sb.append(',');
-			sb.append(nth(i));
+			sb.append(elm(i));
 		}
 		sb.append("}");
 		return sb.toString();
@@ -392,7 +392,7 @@ public Type emit_const(CodeAdapter fa) {
 		for (int i = 0; i < arity(); i++) {
 			fa.visitInsn(Opcodes.DUP);
 
-			fa.emit_const(nth(i + 1));
+			fa.emit_const(elm(i + 1));
 
 			fa.visitFieldInsn(Opcodes.PUTFIELD, type.getInternalName(), "elem"
 					+ (i + 1), ETERM_TYPE.getDescriptor());
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple.java
a27eef15603cfb96b62ccf2fcda4456de53249a2
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple0.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple0.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple0.java
	public EObject elm(int i) {
	public EObject nth(int i) {
@@ -30,7 +30,7 @@ public int arity() {
 	}
 
 	@Override
-	public EObject nth(int i) {
+	public EObject elm(int i) {
 		return bad_nth(i);
 	}
 	
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple0.java
27870f76c7fbb0a06ff9335d8dd258999956cd32
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple1.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple1.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple1.java
	public EObject elm(int i) {
	public EObject nth(int i) {
@@ -42,7 +42,7 @@ public void set(int index, EObject term) {
 	}
 
 	@Override
-	public EObject nth(int i) {
+	public EObject elm(int i) {
 		if(i==1) return elem1; 
 		return bad_nth(i);
 	}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple1.java
0721ba6b728089cf8f2d6869386efaecc657ba0b
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple2.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple2.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple2.java
	public EObject elm(int i) {
	public EObject nth(int i) {
@@ -34,7 +34,7 @@ public int arity() {
 	}
 
 	@Override
-	public EObject nth(int i) {
+	public EObject elm(int i) {
 		if (i == 1) {
 			return elem1;
 		} else if (i == 2) {
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple2.java
d5afdcde134be58b21be9bee13b54ae1e4a5297a
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple3.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple3.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple3.java
	public EObject elm(int i) {
	public EObject nth(int i) {
@@ -36,7 +36,7 @@ public int arity() {
 	}
 
 	@Override
-	public EObject nth(int i) {
+	public EObject elm(int i) {
 		switch (i) {
 		case 1:
 			return elem1;
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple3.java
eb427ea2db3d12578243cf732cc36b78b9350181
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple4.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FETuple4.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ETuple4.java
	public EObject elm(int i) {
	public EObject nth(int i) {
@@ -37,7 +37,7 @@ public int arity() {
 	}
 
 	@Override
-	public EObject nth(int i) {
+	public EObject elm(int i) {
 		switch (i) {
 		case 1:
 			return elem1;
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FETuple4.java
c2e434893335acf3a16b9d7d75ab4c2eb715aceb
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FErlangException.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2FErlangException.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/ErlangException.java
		this.args = ECons.NIL;
		ESeq res = ESeq.NIL;
		this.args = ECons.EMPTY;
		ESeq res = ESeq.EMPTY;
@@ -48,11 +48,11 @@ public ErlangException(EAtom reason) {
 		this.reason = reason;
 		this.module = null;
 		this.function = null;
-		this.args = ECons.EMPTY;
+		this.args = ECons.NIL;
 	}
 
 	private ESeq listify(Object[] args) {
-		ESeq res = ESeq.EMPTY;
+		ESeq res = ESeq.NIL;
 		for (int i = args.length-1; i >= 0; i--) {
 			EObject h = erl_value(args[i]);
 			res = res.cons(h);
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2FErlangException.java
384c67cb17bee2938aa51517f4167fb9df6429d9
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBIFUtil.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FBIFUtil.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/BIFUtil.java
import erjang.modules.erl_bif;
		registerBifs(erl_bif.class);
import erjang.modules.ErlangModule;
		registerBifs(ErlangModule.class);
@@ -27,7 +27,7 @@
 import erjang.EAtom;
 import erjang.EObject;
 import erjang.modules.BinOps;
-import erjang.modules.ErlangModule;
+import erjang.modules.erl_bif;
 
 /**
  * Used by the compiler to find and mange BIF definitions.
@@ -42,7 +42,7 @@ public class BIFUtil {
 	static Map<String, BIFHandler> guard_bifs = new HashMap<String, BIFHandler>();
 
 	static {
-		registerBifs(ErlangModule.class);
+		registerBifs(erl_bif.class);
 		registerBifs(BinOps.class);
 	}
 
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBIFUtil.java
637d150b77555528daf6478aa32514bb1051ee00
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBeamFileData.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FBeamFileData.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/BeamFileData.java
		assert (data.elm(1) == BEAM_FILE);
		module = data.elm(2).testAtom();
		exports = data.elm(3).testSeq();
		attributes = data.elm(4).testSeq();
		comp_info = data.elm(5).testSeq();
		code = data.elm(6).testSeq();
		try {
			for (ESeq exp = (ESeq) code; exp != ESeq.NIL; exp = exp.tail()) {
				ETuple fun = (ETuple) exp.head();
				visit_function(v, fun);
			}
		} finally {
			v.visitEnd();
		EAtom name = (EAtom) fun.elm(2);
		int ary = fun.elm(3).asInt();
		int entry = fun.elm(4).asInt();
		EList insns = (EList) fun.elm(5);


		for (ESeq insn = (ESeq) insns; insn != ESeq.NIL; insn = insn.tail()) {

				bbv.visitInsn(opcode, ETuple.make(new EObject[] { i }));

				BeamOpcode opcode = BeamOpcode.get((EAtom) et.elm(1));

					EInteger label = (EInteger) et.elm(2);



		for (ESeq exp = (ESeq) attributes; exp != ESeq.NIL; exp = exp.tail()) {
			v.visitAttribute((EAtom) one.elm(1), one.elm(2));
		for (ESeq exp = (ESeq) exports; exp != ESeq.NIL; exp = exp.tail()) {
			v.visitExport((EAtom) one.elm(1), one.elm(2).asInt(), one.elm(3)
		assert (data.nth(1) == BEAM_FILE);
		module = data.nth(2).asAtom();
		exports = data.nth(3).asSeq();
		attributes = data.nth(4).asSeq();
		comp_info = data.nth(5).asSeq();
		code = data.nth(6).asSeq();
		for (ESeq exp = (ESeq) code; exp != ESeq.EMPTY; exp = exp.tail()) {
			ETuple fun = (ETuple) exp.head();
			visit_function(v, fun);

		v.visitEnd();

		EAtom name = (EAtom) fun.nth(2);
		int ary = fun.nth(3).asInt();
		int entry = fun.nth(4).asInt();
		EList insns = (EList) fun.nth(5);
		
		
		for (ESeq insn = (ESeq) insns; insn != ESeq.EMPTY; insn = insn.tail()) {
			
				bbv.visitInsn(opcode, ETuple.make(new EObject[] {i}));
				
				BeamOpcode opcode = BeamOpcode.get((EAtom) et.nth(1));
				
					EInteger label = (EInteger) et.nth(2);
					
					
		
		for (ESeq exp = (ESeq) attributes; exp != ESeq.EMPTY; exp = exp
				.tail()) {
			v.visitAttribute((EAtom) one.nth(1), one.nth(2));
		for (ESeq exp = (ESeq) exports; exp != ESeq.EMPTY; exp = exp
				.tail()) {
			v.visitExport((EAtom) one.nth(1), one.nth(2).asInt(), one.nth(3)
@@ -43,13 +43,13 @@ public class BeamFileData {
 	private ESeq code;
 
 	public BeamFileData(ETuple data) {
-		assert (data.nth(1) == BEAM_FILE);
+		assert (data.elm(1) == BEAM_FILE);
 
-		module = data.nth(2).asAtom();
-		exports = data.nth(3).asSeq();
-		attributes = data.nth(4).asSeq();
-		comp_info = data.nth(5).asSeq();
-		code = data.nth(6).asSeq();
+		module = data.elm(2).testAtom();
+		exports = data.elm(3).testSeq();
+		attributes = data.elm(4).testSeq();
+		comp_info = data.elm(5).testSeq();
+		code = data.elm(6).testSeq();
 	}
 
 	void accept(ModuleVisitor v) {
@@ -59,22 +59,23 @@ void accept(ModuleVisitor v) {
 
 		visit_attributes(v);
 
-		for (ESeq exp = (ESeq) code; exp != ESeq.EMPTY; exp = exp.tail()) {
-			ETuple fun = (ETuple) exp.head();
+		try {
+			for (ESeq exp = (ESeq) code; exp != ESeq.NIL; exp = exp.tail()) {
+				ETuple fun = (ETuple) exp.head();
 
-			visit_function(v, fun);
+				visit_function(v, fun);
+			}
+		} finally {
+			v.visitEnd();
 		}
-
-		v.visitEnd();
-
 	}
 
 	private void visit_function(ModuleVisitor v, ETuple fun) {
 
-		EAtom name = (EAtom) fun.nth(2);
-		int ary = fun.nth(3).asInt();
-		int entry = fun.nth(4).asInt();
-		EList insns = (EList) fun.nth(5);
+		EAtom name = (EAtom) fun.elm(2);
+		int ary = fun.elm(3).asInt();
+		int entry = fun.elm(4).asInt();
+		EList insns = (EList) fun.elm(5);
 
 		FunctionVisitor fv = v.visitFunction(name, ary, entry);
 
@@ -84,28 +85,28 @@ private void visit_function(ModuleVisitor v, ETuple fun) {
 	}
 
 	private void visit_insns(EList insns, FunctionVisitor fv) {
-		
+
 		BlockVisitor bbv = null;
-		
-		for (ESeq insn = (ESeq) insns; insn != ESeq.EMPTY; insn = insn.tail()) {
+
+		for (ESeq insn = (ESeq) insns; insn != ESeq.NIL; insn = insn.tail()) {
 
 			EObject i = insn.head();
-			
+
 			if (i instanceof EAtom) {
 				BeamOpcode opcode = BeamOpcode.get((EAtom) i);
-				bbv.visitInsn(opcode, ETuple.make(new EObject[] {i}));
-				
+				bbv.visitInsn(opcode, ETuple.make(new EObject[] { i }));
+
 			} else if (i instanceof ETuple) {
 				ETuple et = (ETuple) i;
-				BeamOpcode opcode = BeamOpcode.get((EAtom) et.nth(1));
-				
+				BeamOpcode opcode = BeamOpcode.get((EAtom) et.elm(1));
+
 				if (opcode == BeamOpcode.label) {
-					EInteger label = (EInteger) et.nth(2);
-					
+					EInteger label = (EInteger) et.elm(2);
+
 					if (bbv != null) {
 						bbv.visitEnd();
 					}
-					
+
 					bbv = fv.visitLabeledBlock(label.asInt());
 				} else {
 					bbv.visitInsn(opcode, et);
@@ -114,25 +115,23 @@ private void visit_insns(EList insns, FunctionVisitor fv) {
 				throw new IllegalArgumentException();
 			}
 		}
-		
+
 		if (bbv != null) {
 			bbv.visitEnd();
 		}
 	}
 
 	private void visit_attributes(ModuleVisitor v) {
-		for (ESeq exp = (ESeq) attributes; exp != ESeq.EMPTY; exp = exp
-				.tail()) {
+		for (ESeq exp = (ESeq) attributes; exp != ESeq.NIL; exp = exp.tail()) {
 			ETuple one = (ETuple) exp.head();
-			v.visitAttribute((EAtom) one.nth(1), one.nth(2));
+			v.visitAttribute((EAtom) one.elm(1), one.elm(2));
 		}
 	}
 
 	private void visit_exports(ModuleVisitor v) {
-		for (ESeq exp = (ESeq) exports; exp != ESeq.EMPTY; exp = exp
-				.tail()) {
+		for (ESeq exp = (ESeq) exports; exp != ESeq.NIL; exp = exp.tail()) {
 			ETuple one = (ETuple) exp.head();
-			v.visitExport((EAtom) one.nth(1), one.nth(2).asInt(), one.nth(3)
+			v.visitExport((EAtom) one.elm(1), one.elm(2).asInt(), one.elm(3)
 					.asInt());
 		}
 	}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBeamFileData.java
748a88ec399dc464fd7fb36edfeb5fab3896dd38
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBlockVisitor2.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FBlockVisitor2.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/BlockVisitor2.java

	/**
	 * @param opcode
	 * @param ys
	 */
	void visitInsn(BeamOpcode opcode, Arg[] ys);

	/**
	 * @param opcode
	 * @param efun
	 * @param freevars
	 */
	void visitInsn(BeamOpcode opcode, ExtFunc efun, Arg[] freevars);

	/**
	 * @param opcode
	 * @param in
	 * @param out
	 */
	void visitInsn(BeamOpcode opcode, Arg[] in, Arg out);

	/**
	 * @param opcode
	 * @param asInt
	 * @param decodeOutArg
	 */
	void visitInsn(BeamOpcode opcode, int val, Arg out);

	/**
	 * @param opcode
	 * @param val
	 * @param tupleReg
	 * @param i
	 */
	void visitInsn(BeamOpcode opcode, Arg val, Arg out, int pos);

	/**
	 * @param in
	 * @param failLabel
	 * @param arities
	 * @param targets
	 */
	void visitSelectTuple(Arg in, int failLabel, int[] arities, int[] targets);

	/**
	 * @param in
	 * @param failLabel
	 * @param values
	 * @param targets
	 */
	void visitSelectValue(Arg in, int failLabel, Arg[] values, int[] targets);

	/**
	 * @param test
	 * @param failLabel
	 * @param arg
	 * @param arity
	 * @param tupleType
	 */
	void visitTest(BeamOpcode test, int failLabel, Arg arg, int arity,
			Type tupleType);

	/**
	 * @param decodeLabelref
	 */
	void visitJump(int decodeLabelref);

@@ -72,6 +72,73 @@ void visitTest(BeamOpcode test, int failLabel, Arg[] args, Arg out,
 	 * @param isExternal
 	 */
 	void visitCall(ExtFunc fun, Arg[] args, boolean isTail, boolean isExternal);
+
+	/**
+	 * @param opcode
+	 * @param ys
+	 */
+	void visitInsn(BeamOpcode opcode, Arg[] ys);
+
+	/**
+	 * @param opcode
+	 * @param efun
+	 * @param freevars
+	 */
+	void visitInsn(BeamOpcode opcode, ExtFunc efun, Arg[] freevars);
+
+	/**
+	 * @param opcode
+	 * @param in
+	 * @param out
+	 */
+	void visitInsn(BeamOpcode opcode, Arg[] in, Arg out);
+
+	/**
+	 * @param opcode
+	 * @param asInt
+	 * @param decodeOutArg
+	 */
+	void visitInsn(BeamOpcode opcode, int val, Arg out);
+
+	/**
+	 * @param opcode
+	 * @param val
+	 * @param tupleReg
+	 * @param i
+	 */
+	void visitInsn(BeamOpcode opcode, Arg val, Arg out, int pos);
+
+	/**
+	 * @param in
+	 * @param failLabel
+	 * @param arities
+	 * @param targets
+	 */
+	void visitSelectTuple(Arg in, int failLabel, int[] arities, int[] targets);
+
+	/**
+	 * @param in
+	 * @param failLabel
+	 * @param values
+	 * @param targets
+	 */
+	void visitSelectValue(Arg in, int failLabel, Arg[] values, int[] targets);
+
+	/**
+	 * @param test
+	 * @param failLabel
+	 * @param arg
+	 * @param arity
+	 * @param tupleType
+	 */
+	void visitTest(BeamOpcode test, int failLabel, Arg arg, int arity,
+			Type tupleType);
+
+	/**
+	 * @param decodeLabelref
+	 */
+	void visitJump(int decodeLabelref);
+
 	
 
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FBlockVisitor2.java
3a48cb03ce7abbd5dfe19d9416691de558c57b7f
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FCompiler.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FCompiler.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/Compiler.java
		try {
			// go!
			reader.accept(analysis);
		} catch (Error e) {
			e.printStackTrace();
		}


			String jbeam_name = beam_name.substring(0, beam_name
					.lastIndexOf('.') + 1)
					+ "jbeam";
			File outfile = new File(out_dir, jbeam_name);
			writeTo(outfile, data);
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import com.sun.tools.javac.resources.compiler;
import erjang.EModule;
import erjang.EObject;
import erjang.ErlFun;
import erjang.Module;
		// go!
		reader.accept(analysis);

		
			
			String jbeam_name = beam_name.substring(0, beam_name.lastIndexOf('.')+1) + "jbeam";
			File outfile = new File(out_dir, beam_name);
			writeTo(outfile , data);
		
@@ -18,32 +18,15 @@
 
 package erjang.beam;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
 
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodAdapter;
-import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
 
 import com.ericsson.otp.erlang.OtpAuthException;
-import com.sun.tools.javac.resources.compiler;
 
-import erjang.EModule;
-import erjang.EObject;
-import erjang.ErlFun;
-import erjang.Module;
 import erjang.beam.analysis.BeamTypeAnalysis;
 
 public class Compiler implements Opcodes {
@@ -73,9 +56,12 @@ byte[] compile(File file) throws IOException {
 		// the beam file reader, phase 1
 		BeamFileData reader = loader.load(file);
 
-		// go!
-		reader.accept(analysis);
-
+		try {
+			// go!
+			reader.accept(analysis);
+		} catch (Error e) {
+			e.printStackTrace();
+		}
 		// get byte code data
 		return cw.toByteArray();
 	}
@@ -84,18 +70,19 @@ public static void main(String[] args) throws Exception {
 
 		File out_dir = new File("out");
 		Compiler cc = new Compiler();
-		
+
 		for (int i = 0; i < args.length; i++) {
-			
+
 			File infile = new File(args[i]);
 			byte[] data = cc.compile(infile);
 			String beam_name = infile.getName();
-			String jbeam_name = beam_name.substring(0, beam_name.lastIndexOf('.')+1) + "jbeam";
-			File outfile = new File(out_dir, beam_name);
-			writeTo(outfile , data);
+			String jbeam_name = beam_name.substring(0, beam_name
+					.lastIndexOf('.') + 1)
+					+ "jbeam";
+			File outfile = new File(out_dir, jbeam_name);
+			writeTo(outfile, data);
 		}
 
-		
 	}
 
 	static void writeTo(File output, byte[] class_data) throws IOException {
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FCompiler.java
e9d1929d4ec2ed87a99e644292e594149945befe
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FCompilerVisitor.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FCompilerVisitor.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/CompilerVisitor.java
import erjang.EString;
import erjang.NotImplemented;
import erjang.modules.erl_bif;
	ECons atts = EList.NIL;
		cv.visit(V1_6, ACC_PUBLIC, self_type.getInternalName(), null,
		String internalEMname = erl_bif.class.getName().replace('.', '/');
	Map<ETerm, String> constants = new HashMap<ETerm, String>();

		private Label start;
		private Label end;
		private int scratch_reg;
			this.start = new Label();
			this.end = new Label();

			mv.visitLabel(start);

			mv.visitMaxs(20, scratch_reg + 1);
			mv.visitLabel(end);
				mv.visitLocalVariable("X" + i, EOBJECT_TYPE.getDescriptor(),
						null, start, end, local);

				mv.visitLocalVariable("Y" + i, EOBJECT_TYPE.getDescriptor(),
						null, start, end, local);
				mv.visitLocalVariable("F" + i,
						Type.DOUBLE_TYPE.getDescriptor(), null, start, end,
						local);
			this.scratch_reg = local;




				mv.visitMethodInsn(INVOKESTATIC, ERT_TYPE.getInternalName(),
						"unbox" + primTypeName(toType), "("
								+ fromType.getDescriptor() + ")"
								+ toType.getDescriptor());

			}

			/**
			 * @param toType
			 * @return
			 */
			private String primTypeName(Type typ) {
				switch (typ.getSort()) {
				case Type.DOUBLE:
					return "Double";
				case Type.INT:
					return "Integer";
				case Type.BOOLEAN:
					return "Atom";
				default:
					throw new Error();
				}
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "box", "("
									+ fromType.getDescriptor() + ")"
									+ toType.getDescriptor());
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "box", "("
									+ fromType.getDescriptor() + ")"
									+ toType.getDescriptor());
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "box", "("
									+ fromType.getDescriptor() + ")"
									+ toType.getDescriptor());
				if (value == ENil.NIL) {
					mv.visitFieldInsn(GETSTATIC, ENIL_TYPE.getInternalName(),
							"NIL", ENIL_TYPE.getDescriptor());
					return ENIL_TYPE;
				}

				if (value == ERT.ATOM_TRUE) {
					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
							"ATOM_TRUE", EATOM_TYPE.getDescriptor());
					return EATOM_TYPE;
				}

				if (value == ERT.ATOM_FALSE) {
					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
							"ATOM_FALSE", EATOM_TYPE.getDescriptor());
					return EATOM_TYPE;
				}


					Type type = Type.getType(value.getClass());

					String cn = getConstantName(value, constants.size());

					constants.put(value, known = cn);
					cv.visitField(ACC_STATIC, known, type.getDescriptor(),
							null, null);

					System.err.println(constants);

					mv.visitFieldInsn(GETSTATIC, self_type.getInternalName(),
							known, type.getDescriptor());

				throw new Error("cannot push " + value + " as " + stack_type);
			/**
			 * @param value
			 * @param size
			 * @return
			 */
			private String getConstantName(ETerm value, int size) {
				if (value instanceof EAtom)
					return "atom_" + EUtil.toJavaIdentifier((EAtom) value);
				if (value instanceof ENumber)
					return EUtil.toJavaIdentifier("num_"
							+ value.toString().replace('.', '_').replace('-',
									'_'));
				if (value instanceof EString)
					return "str_" + size;
				else
					return "cst_" + size;
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
			 * erjang.beam.Arg[], erjang.beam.Arg)
			 */
			@Override
			public void visitInsn(BeamOpcode opcode, Arg[] in, Arg out) {
				switch (opcode) {
				case put_list:
					push(in[0], EOBJECT_TYPE);
					push(in[1], EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "cons", "("
									+ EOBJECT_TYPE.getDescriptor()
									+ EOBJECT_TYPE.getDescriptor() + ")"
									+ ECONS_TYPE.getDescriptor());
					pop(out, ECONS_TYPE);
					return;
				}

				throw new Error();
			}

					mv.visitVarInsn(ALOAD, 0);
				case if_end:
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "if_end", EUtil
									.getSignature(0));
					mv.visitInsn(ARETURN);
					return;

				}

				throw new Error();
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
			 * int, erjang.beam.Arg)
			 */
			@Override
			public void visitInsn(BeamOpcode opcode, int val, Arg out) {
				switch (opcode) {
				case put_tuple:
					mv.visitTypeInsn(NEW, out.type.getInternalName());
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKESPECIAL, out.type
							.getInternalName(), "<init>", "()V");
					pop(out, out.type);

					return;
				}
				throw new Error();
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
			 * erjang.beam.Arg, erjang.beam.Arg, int)
			 */
			@Override
			public void visitInsn(BeamOpcode opcode, Arg val, Arg out, int pos) {
				if (opcode == BeamOpcode.put) {
					push(out, out.type);
					push(val, EOBJECT_TYPE);
					mv.visitFieldInsn(PUTFIELD, out.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					return;

				} else if (opcode == BeamOpcode.get_tuple_element) {
					push(val, val.type);
					mv.visitFieldInsn(GETFIELD, val.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					pop(out, EOBJECT_TYPE);
					return;
				} else if (opcode == BeamOpcode.set_tuple_element) {
					push(out, out.type);
					push(val, val.type);
					mv.visitFieldInsn(PUTFIELD, val.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					return;
			/**
			 * @param pos
			 */
			private void push_int(int pos) {
				if (pos >= -1 && pos <= 5) {
					mv.visitInsn(ICONST_0 + pos);
				} else {
					mv.visitLdcInsn(new Integer(pos));
				}
			}

				switch (opcode) {
				case func_info:
					ExtFunc f = (ExtFunc) arg;
					push_immediate(f.mod, EATOM_TYPE);
					push_immediate(f.fun, EATOM_TYPE);
					mv.visitLdcInsn(new Integer(arg.no));
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "func_info", "("
									+ ETUPLE_TYPE.getDescriptor()
									+ ETUPLE_TYPE.getDescriptor() + "I)"
									+ EOBJECT_TYPE.getDescriptor());
					mv.visitInsn(ARETURN);
					return;

				case init:
					push_immediate(ENil.NIL, ENIL_TYPE);
					pop(arg, ENIL_TYPE);
					return;

				case case_end:
					push(arg, EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "case_end", EUtil
									.getSignature(1));
					mv.visitInsn(ARETURN);
					return;

				case badmatch:
					push(arg, EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "badmatch", EUtil
									.getSignature(1));
					mv.visitInsn(ARETURN);
					return;

				}

				throw new Error("unhandled " + opcode);
				System.err.println(test_bif);

				push(arg1, arg1.type);
					if (returnType.getSort() == Type.BOOLEAN) {
						mv.visitJumpInsn(IFEQ, getLabel(failLabel));

					} else {

						// guard
						if (returnType.getSort() != Type.OBJECT)
							throw new Error("guards must return object type");
						// dup result for test
						if (arg1 != null) {
							mv.visitInsn(DUP);
							mv.visitVarInsn(ASTORE, scratch_reg);
						}
						mv.visitJumpInsn(IFNULL, getLabel(failLabel));
						if (arg1 != null) {
							mv.visitVarInsn(ALOAD, scratch_reg);
							pop(arg1, returnType);
						}
			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitTest(erjang.beam.BeamOpcode,
			 * int, erjang.beam.Arg, int, org.objectweb.asm.Type)
			 */
			@Override
			public void visitTest(BeamOpcode test, int failLabel, Arg arg,
					int arity, Type tupleType) {

				if (test != BeamOpcode.test_arity)
					throw new Error();

				push(arg, ETUPLE_TYPE);
				mv.visitMethodInsn(INVOKEVIRTUAL,
						ETUPLE_TYPE.getInternalName(), "count", "()I");
				push_int(arity);
				mv.visitJumpInsn(IF_ICMPNE, getLabel(failLabel));
				push(arg, ETUPLE_TYPE);
				mv.visitTypeInsn(CHECKCAST, tupleType.getInternalName());
				pop(arg, tupleType);
			}

				if (test == BeamOpcode.is_eq_exact
						&& (args[0].type.equals(EATOM_TYPE) || args[1].type
								.equals(EATOM_TYPE))) {
					push(args[0], EOBJECT_TYPE);
					push(args[1], EOBJECT_TYPE);
					mv.visitJumpInsn(IF_ACMPNE, getLabel(failLabel));
					return;
				}

					switch (bif.getReturnType().getSort()) {
					case Type.BOOLEAN:
						if (out == null) {
							mv.visitJumpInsn(IFEQ, getLabel(failLabel));
						}
						break;
					case Type.OBJECT:

						if (out != null) {
							pop(out, bif.getReturnType());
							push(out, bif.getReturnType());
						}

						mv.visitJumpInsn(IFNULL, getLabel(failLabel));
						break;
					default:
						throw new Error("guards must return object type");

							pop(arg2, EDOUBLE_TYPE);
							pop(arg2, arg1.type);
				if (!type.getInternalName().startsWith("erjang/E")) {
				case is_boolean:
					return IS_BOOLEAN_TEST;
				case is_atom:
					return IS_ATOM_TEST;
				case is_tuple:
					return IS_TUPLE_TEST;
				case is_integer:
					return IS_INTEGER_TEST;
			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
			 * erjang.beam.Arg[])
			 */
			@Override
			public void visitInsn(BeamOpcode opcode, Arg[] ys) {

				if (opcode == BeamOpcode.allocate_zero
						|| opcode == BeamOpcode.allocate_heap_zero) {

					mv.visitFieldInsn(GETSTATIC, ENIL_TYPE.getInternalName(),
							"NIL", ENIL_TYPE.getDescriptor());
					for (int i = 0; i < ys.length; i++) {
						if (i != (ys.length - 1))
							mv.visitInsn(DUP);
						pop(ys[i], ENIL_TYPE);
					}

					return;
				} else if (opcode == BeamOpcode.get_list) {

					push(ys[0], ECONS_TYPE);
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
							.getInternalName(), "head", "()"
							+ EOBJECT_TYPE.getDescriptor());
					pop(ys[1], EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
							.getInternalName(), "tail", "()"
							+ EOBJECT_TYPE.getDescriptor());
					pop(ys[2], EOBJECT_TYPE);
					return;

				} else if (opcode == BeamOpcode.apply) {

					for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
					}
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "apply", EUtil
									.getSignature(ys.length));
					mv.visitVarInsn(ASTORE, xregs[0]);

					return;
					
				} else if (opcode == BeamOpcode.apply_last) {

					for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
					}
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "apply$last", EUtil
									.getSignature(ys.length));

					mv.visitInsn(ARETURN);

					return;
					
				} else if (opcode == BeamOpcode.send) {
					for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
					}
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "send", EUtil
									.getSignature(ys.length));
					mv.visitVarInsn(ASTORE, xregs[0]);

					return;
				}

				throw new Error("unhandled:" + opcode);
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
			 * erjang.beam.ExtFunc, int)
			 */
			@Override
			public void visitInsn(BeamOpcode opcode, ExtFunc efun,
					Arg[] freevars) {
				if (opcode == BeamOpcode.make_fun2) {

					String funtype = EFUN_TYPE.getInternalName() + efun.no;
					for (int i = 0; i < freevars.length; i++) {
						push(freevars[i], EOBJECT_TYPE);
					}

					StringBuilder sb = new StringBuilder("(");
					for (int i = 0; i < freevars.length; i++) {
						sb.append(EOBJECT_TYPE.getDescriptor());
					}
					sb.append(")");
					sb.append("L").append(funtype).append(";");
					String gen_fun_desc = sb.toString();
					String gen_fun_name = "make_fun2_"
							+ EUtil.getJavaName(efun);

					mv.visitMethodInsn(INVOKESTATIC, self_type
							.getInternalName(), gen_fun_name, gen_fun_desc);

					mv.visitVarInsn(ASTORE, 0);

					return;
				}

				throw new Error();
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitSelectValue(erjang.beam.Arg,
			 * int, erjang.beam.Arg[], int[])
			 */
			@Override
			public void visitSelectValue(Arg in, int failLabel, Arg[] values,
					int[] targets) {
				int[] hash = new int[values.length];
				Label[] label = new Label[values.length];
				for (int i = 0; i < values.length; i++) {
					hash[i] = values[i].value.hashCode();
					label[i] = new Label();
				}

				push(in, EOBJECT_TYPE);
				mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
						"hashCode", "()I");
				mv.visitLookupSwitchInsn(getLabel(failLabel), hash, label);

				for (int i = 0; i < hash.length; i++) {
					int h = hash[i];
					for (int j = i; j < hash.length; j++) {
						if (h == hash[j] && label[j] != null)
							mv.visitLabel(label[j]);
					}

					for (int j = i; j < hash.length; j++) {
						if (h == hash[j] && label[j] != null) {

							if (values[j].type.equals(EATOM_TYPE)) {

								push(in, in.type);
								push(values[j], values[j].type);
								mv.visitJumpInsn(IF_ACMPEQ,
										getLabel(targets[j]));

							} else {

								if (in.type == values[j].type) {
									push(in, in.type);
									push(values[j], values[j].type);

									mv.visitMethodInsn(INVOKESTATIC, ERT_TYPE
											.getInternalName(), "eq", "("
											+ in.type.getDescriptor()
											+ in.type.getDescriptor() + ")Z");
								} else {
									push(in, EOBJECT_TYPE);
									push(values[j], EOBJECT_TYPE);
									mv.visitMethodInsn(INVOKEVIRTUAL,
											"java/lang/Object", "equals",
											"(Ljava/lang/Object;)Z");
								}
								mv.visitJumpInsn(IFNE, getLabel(targets[j]));
							}
							label[j] = null;
						}
					}

					mv.visitJumpInsn(GOTO, getLabel(failLabel));
				}
			}

			@Override
			public void visitSelectTuple(Arg in, int failLabel, int[] arities,
					int[] targets) {

				push(in, ETUPLE_TYPE);

				mv.visitMethodInsn(INVOKEVIRTUAL,
						ETUPLE_TYPE.getInternalName(), "count", "()I");

				Label[] targetLabels = new Label[targets.length];
				for (int i = 0; i < targets.length; i++) {
					targetLabels[i] = new Label();
				}
				mv.visitLookupSwitchInsn(getLabel(failLabel), arities,
						targetLabels);
				for (int i = 0; i < targetLabels.length; i++) {
					mv.visitLabel(targetLabels[i]);
					push(in, ETUPLE_TYPE);
					mv.visitTypeInsn(CHECKCAST, getTubleType(arities[i])
							.getInternalName());
					pop(in, getTubleType(arities[i]));
					mv.visitJumpInsn(GOTO, getLabel(targets[i]));
				}

			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see erjang.beam.BlockVisitor2#visitJump(int)
			 */
			@Override
			public void visitJump(int label) {
				mv.visitJumpInsn(GOTO, getLabel(label));
			}

			/**
			 * @param i
			 * @return
			 */
			private Type getTubleType(int i) {
				return Type.getType("L" + ETUPLE_TYPE.getInternalName() + i
						+ ";");
			}

					String funTypeName = EFUN_TYPE.getInternalName()
							+ args.length;
							field, "L" + funTypeName + ";");
					mv.visitMethodInsn(INVOKEVIRTUAL, funTypeName,
							is_tail ? "invoke_tail" : "invoke", EUtil
									.getSignature(args.length));
					} else {
						mv.visitVarInsn(ASTORE, 0);
					} else {
						mv.visitVarInsn(ASTORE, 0);
			.getMethod("erjang.ECons testNonEmptyList()");
	static Method IS_LIST_TEST = Method.getMethod("erjang.ECons testCons()");
	static Method IS_TUPLE_TEST = Method.getMethod("erjang.ETuple testTuple()");
	static Method IS_INTEGER_TEST = Method.getMethod("erjang.ETuple testInteger()");
	static Method IS_ATOM_TEST = Method.getMethod("erjang.ETuple testAtom()");
	static Method IS_NIL_TEST = Method.getMethod("boolean isNil()");
	static Method IS_BOOLEAN_TEST = Method.getMethod("boolean isBoolean()");
Type typ
src/erjang/beam/CompilerVisitor.java
switch (typ.getSort()) {
				case Type.DOUBLE:
					return "Double";
				case Type.INT:
					return "Integer";
				case Type.BOOLEAN:
					return "Atom";
				default:
					throw new Error();
String primTypeName(Type typ)
ETerm value  int size
src/erjang/beam/CompilerVisitor.java
if (value instanceof EAtom)
					return "atom_" + EUtil.toJavaIdentifier((EAtom) value);
				if (value instanceof ENumber)
					return EUtil.toJavaIdentifier("num_"
							+ value.toString().replace('.', '_').replace('-',
									'_'));
				if (value instanceof EString)
					return "str_" + size;
				else
					return "cst_" + size;
String getConstantName(ETerm value, int size)
BeamOpcode opcode  Arg[] in  Arg out
src/erjang/beam/CompilerVisitor.java
switch (opcode) {
				case put_list:
					push(in[0], EOBJECT_TYPE);
					push(in[1], EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKESTATIC,
							ERT_TYPE.getInternalName(), "cons", "("
									+ EOBJECT_TYPE.getDescriptor()
									+ EOBJECT_TYPE.getDescriptor() + ")"
									+ ECONS_TYPE.getDescriptor());
					pop(out, ECONS_TYPE);
					return;
void visitInsn(BeamOpcode opcode, Arg[] in, Arg out)
BeamOpcode opcode  int val  Arg out
src/erjang/beam/CompilerVisitor.java
switch (opcode) {
				case put_tuple:
					mv.visitTypeInsn(NEW, out.type.getInternalName());
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKESPECIAL, out.type
							.getInternalName(), "<init>", "()V");
					pop(out, out.type);

					return;
void visitInsn(BeamOpcode opcode, int val, Arg out)
BeamOpcode opcode  Arg val  Arg out  int pos
src/erjang/beam/CompilerVisitor.java
if (opcode == BeamOpcode.put) {
					push(out, out.type);
					push(val, EOBJECT_TYPE);
					mv.visitFieldInsn(PUTFIELD, out.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					return;
void visitInsn(BeamOpcode opcode, Arg val, Arg out, int pos)
opcode == BeamOpcode.get_tuple_element
src/erjang/beam/CompilerVisitor.java
push(val, val.type);
					mv.visitFieldInsn(GETFIELD, val.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					pop(out, EOBJECT_TYPE);
					return;
else if (opcode == BeamOpcode.get_tuple_element)
opcode == BeamOpcode.set_tuple_element
src/erjang/beam/CompilerVisitor.java
push(out, out.type);
					push(val, val.type);
					mv.visitFieldInsn(PUTFIELD, val.type.getInternalName(),
							"elm" + pos, EOBJECT_TYPE.getDescriptor());
					return;
			/**
			 * @param pos
			 */
			private void push_int(int pos) {
				if (pos >= -1 && pos <= 5) {
					mv.visitInsn(ICONST_0 + pos);
else if (opcode == BeamOpcode.set_tuple_element)
arg1 != null
src/erjang/beam/CompilerVisitor.java
mv.visitInsn(DUP);
							mv.visitVarInsn(ASTORE, scratch_reg);
test
						if (arg1 != null)
BeamOpcode test  int failLabel  Arg arg 
					int arity  Type tupleType
src/erjang/beam/CompilerVisitor.java
if (test != BeamOpcode.test_arity)
					throw new Error();

				push(arg, ETUPLE_TYPE);
				mv.visitMethodInsn(INVOKEVIRTUAL,
						ETUPLE_TYPE.getInternalName(), "count", "()I");
				push_int(arity);
				mv.visitJumpInsn(IF_ICMPNE, getLabel(failLabel));
				push(arg, ETUPLE_TYPE);
				mv.visitTypeInsn(CHECKCAST, tupleType.getInternalName());
				pop(arg, tupleType);
void visitTest(BeamOpcode test, int failLabel, Arg arg,
					int arity, Type tupleType)
BeamOpcode opcode  Arg[] ys
src/erjang/beam/CompilerVisitor.java
if (opcode == BeamOpcode.allocate_zero
						|| opcode == BeamOpcode.allocate_heap_zero) {

					mv.visitFieldInsn(GETSTATIC, ENIL_TYPE.getInternalName(),
							"NIL", ENIL_TYPE.getDescriptor());
					for (int i = 0; i < ys.length; i++) {
						if (i != (ys.length - 1))
							mv.visitInsn(DUP);
						pop(ys[i], ENIL_TYPE);
void visitInsn(BeamOpcode opcode, Arg[] ys)
opcode == BeamOpcode.get_list
src/erjang/beam/CompilerVisitor.java
push(ys[0], ECONS_TYPE);
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
							.getInternalName(), "head", "()"
							+ EOBJECT_TYPE.getDescriptor());
					pop(ys[1], EOBJECT_TYPE);
					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
							.getInternalName(), "tail", "()"
							+ EOBJECT_TYPE.getDescriptor());
					pop(ys[2], EOBJECT_TYPE);
					return;
else if (opcode == BeamOpcode.get_list)
opcode == BeamOpcode.apply
src/erjang/beam/CompilerVisitor.java
for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
else if (opcode == BeamOpcode.apply)
opcode == BeamOpcode.apply_last
src/erjang/beam/CompilerVisitor.java
for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
else if (opcode == BeamOpcode.apply_last)
opcode == BeamOpcode.send
src/erjang/beam/CompilerVisitor.java
for (int i = 0; i < ys.length; i++) {
						push(ys[i], EOBJECT_TYPE);
else if (opcode == BeamOpcode.send)
BeamOpcode opcode  ExtFunc efun 
					Arg[] freevars
src/erjang/beam/CompilerVisitor.java
if (opcode == BeamOpcode.make_fun2) {

					String funtype = EFUN_TYPE.getInternalName() + efun.no;
					for (int i = 0; i < freevars.length; i++) {
						push(freevars[i], EOBJECT_TYPE);
void visitInsn(BeamOpcode opcode, ExtFunc efun,
					Arg[] freevars)
Arg in  int failLabel  Arg[] values 
					int[] targets
src/erjang/beam/CompilerVisitor.java
int[] hash = new int[values.length];
				Label[] label = new Label[values.length];
				for (int i = 0; i < values.length; i++) {
					hash[i] = values[i].value.hashCode();
					label[i] = new Label();
void visitSelectValue(Arg in, int failLabel, Arg[] values,
					int[] targets)
Arg in  int failLabel  int[] arities 
					int[] targets
src/erjang/beam/CompilerVisitor.java
push(in, ETUPLE_TYPE);

				mv.visitMethodInsn(INVOKEVIRTUAL,
						ETUPLE_TYPE.getInternalName(), "count", "()I");

				Label[] targetLabels = new Label[targets.length];
				for (int i = 0; i < targets.length; i++) {
					targetLabels[i] = new Label();
void visitSelectTuple(Arg in, int failLabel, int[] arities,
					int[] targets)
int label
src/erjang/beam/CompilerVisitor.java
mv.visitJumpInsn(GOTO, getLabel(label));
void visitJump(int label)
int i
src/erjang/beam/CompilerVisitor.java
return Type.getType("L" + ETUPLE_TYPE.getInternalName() + i
						+ ";");
Type getTubleType(int i)
import erjang.modules.ErlangModule;
	ECons atts = EList.EMPTY;
		cv.visit(V1_5, ACC_PUBLIC, self_type.getInternalName(), null,
		String internalEMname = ErlangModule.class.getName().replace('.', '/');
					
					
				throw new Error();
					mv.visitTypeInsn(NEW, EINTEGER_TYPE.getInternalName());
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKESPECIAL, EINTEGER_TYPE
							.getInternalName(), "<init>", "(I)V");
					mv.visitTypeInsn(NEW, EDOUBLE_TYPE.getInternalName());
					mv.visitInsn(DUP);
					mv.visitMethodInsn(INVOKESPECIAL, EDOUBLE_TYPE
							.getInternalName(), "<init>", "(D)V");
					Label true_case = new Label();
					Label end_case = new Label();

					mv.visitJumpInsn(IFEQ, true_case);
					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
							"FALSE", EATOM_TYPE.getInternalName());
					mv.visitJumpInsn(GOTO, end_case);
					mv.visitLabel(true_case);
					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
							"TRUE", EATOM_TYPE.getInternalName());
					mv.visitLabel(end_case);

			Map<ETerm,String> constants = new HashMap<ETerm,String>(); 
			
				
					constants.put(value, known = "cp$" + constants.size());
				
					mv.visitFieldInsn(GETSTATIC, self_type.getInternalName(), known, type.getDescriptor());
				
				throw new Error("cannot push "+value + " as "+stack_type);
				throw new Error();
				push(arg1, test_bif.getArgumentTypes()[0]);
					// guard
					if (returnType.getSort() != Type.OBJECT)
						throw new Error("guards must return object type");
					// dup result for test
					if (arg1 != null) {
						pop(arg1, returnType);
						push(new Arg(arg1, returnType), returnType);
					mv.visitJumpInsn(IFNULL, getLabel(failLabel));
					if (bif.getReturnType().getSort() != Type.OBJECT)
						throw new Error("guards must return object type");
					if (out != null) {
						pop(out, bif.getReturnType());
						push(out, bif.getReturnType());
					mv.visitJumpInsn(IFNULL, getLabel(failLabel));
						
							pop(arg2, EDOUBLE_TYPE);							
							pop(arg2, arg1.type);							

				if (!EOBJECT_TYPE.equals(type)) {
							field, EFUN_TYPE.getDescriptor());
					mv.visitMethodInsn(INVOKEVIRTUAL, EFUN_TYPE
							.getInternalName(), is_tail ? "invoke_tail"
							: "invoke", EUtil.getSignature(args.length));
			.getMethod("erjang.ESeq asSeq()");
	static Method IS_LIST_TEST = Method.getMethod("erjang.ECons asCons()");
	static Method IS_NIL_TEST = Method.getMethod("erjang.ENil asNil()");
@@ -48,20 +48,22 @@
 import erjang.EPort;
 import erjang.ERT;
 import erjang.ESeq;
+import erjang.EString;
 import erjang.ETerm;
 import erjang.ETuple;
 import erjang.ETuple2;
 import erjang.ErlFun;
 import erjang.Module;
+import erjang.NotImplemented;
 import erjang.beam.Arg.Kind;
-import erjang.modules.ErlangModule;
+import erjang.modules.erl_bif;
 
 /**
  * 
  */
 public class CompilerVisitor implements ModuleVisitor, Opcodes {
 
-	ECons atts = EList.EMPTY;
+	ECons atts = EList.NIL;
 	private Set<String> exported = new HashSet<String>();
 
 	private final ClassVisitor cv;
@@ -122,7 +124,7 @@ public void visitModule(EAtom name) {
 
 		this.self_type = Type.getObjectType(getInternalClassName());
 
-		cv.visit(V1_5, ACC_PUBLIC, self_type.getInternalName(), null,
+		cv.visit(V1_6, ACC_PUBLIC, self_type.getInternalName(), null,
 				EMODULE_TYPE.getInternalName(), null);
 
 		add_module_annotation(cv);
@@ -141,7 +143,7 @@ private void add_module_annotation(ClassVisitor cv) {
 	private String getInternalClassName() {
 		String cn = EUtil.toJavaIdentifier(getModuleName());
 
-		String internalEMname = ErlangModule.class.getName().replace('.', '/');
+		String internalEMname = erl_bif.class.getName().replace('.', '/');
 		int idx = internalEMname.lastIndexOf('/');
 		String prefix = internalEMname.substring(0, idx + 1);
 		return prefix + cn;
@@ -154,6 +156,8 @@ private String getModuleName() {
 		return module_name.getName();
 	}
 
+	Map<ETerm, String> constants = new HashMap<ETerm, String>();
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -211,6 +215,9 @@ class ASMFunctionAdapter implements FunctionVisitor2 {
 		private int[] xregs;
 		private int[] yregs;
 		private int[] fpregs;
+		private Label start;
+		private Label end;
+		private int scratch_reg;
 
 		Label getLabel(int i) {
 			if (i <= 0)
@@ -246,9 +253,14 @@ public void visitMaxs(int x_count, int y_count, int fp_count,
 
 			add_erlfun_annotation(mv);
 
+			this.start = new Label();
+			this.end = new Label();
+
 			allocate_regs_to_locals(x_count, y_count, fp_count);
 
 			mv.visitCode();
+			mv.visitLabel(start);
+
 			mv.visitJumpInsn(GOTO, getLabel(startLabel));
 		}
 
@@ -259,6 +271,8 @@ public void visitMaxs(int x_count, int y_count, int fp_count,
 		 */
 		@Override
 		public void visitEnd() {
+			mv.visitMaxs(20, scratch_reg + 1);
+			mv.visitLabel(end);
 			mv.visitEnd();
 		}
 
@@ -277,22 +291,32 @@ private void allocate_regs_to_locals(int xCount, int yCount, int fpCount) {
 
 			xregs = new int[max_x];
 			for (int i = 0; i < max_x; i++) {
+				mv.visitLocalVariable("X" + i, EOBJECT_TYPE.getDescriptor(),
+						null, start, end, local);
 				xregs[i] = local;
 				local += 1;
+
 			}
 
 			yregs = new int[max_y];
 			for (int i = 0; i < max_y; i++) {
+				mv.visitLocalVariable("Y" + i, EOBJECT_TYPE.getDescriptor(),
+						null, start, end, local);
 				yregs[i] = local;
 				local += 1;
 			}
 
 			fpregs = new int[max_f];
 			for (int i = 0; i < max_f; i++) {
+				mv.visitLocalVariable("F" + i,
+						Type.DOUBLE_TYPE.getDescriptor(), null, start, end,
+						local);
 				fpregs[i] = local;
 				local += 2;
 			}
 
+			this.scratch_reg = local;
+
 		}
 
 		private void add_erlfun_annotation(MethodVisitor mv) {
@@ -354,6 +378,7 @@ public void visitInsn(BeamOpcode opcode, int failLabel, Arg[] in,
 							pop(out, bif.getReturnType());
 							push(out, bif.getReturnType());
 						}
+
 						mv.visitJumpInsn(IFNULL, getLabel(failLabel));
 					} else {
 						pop(out, bif.getReturnType());
@@ -402,11 +427,11 @@ private void pop(Arg out, Type stack_type) {
 				if (out.kind == Kind.X || out.kind == Kind.Y) {
 					mv.visitVarInsn(ASTORE, var_index(out));
 				} else if (out.kind == Kind.F) {
-					
+
 					if (!stack_type.equals(Type.DOUBLE_TYPE)) {
 						emit_convert(stack_type, Type.DOUBLE_TYPE);
 					}
-					
+
 					mv.visitVarInsn(FSTORE, var_index(out));
 				} else {
 					throw new Error();
@@ -455,7 +480,28 @@ private void emit_unbox(Type fromType, Type toType) {
 					}
 				}
 
-				throw new Error();
+				mv.visitMethodInsn(INVOKESTATIC, ERT_TYPE.getInternalName(),
+						"unbox" + primTypeName(toType), "("
+								+ fromType.getDescriptor() + ")"
+								+ toType.getDescriptor());
+
+			}
+
+			/**
+			 * @param toType
+			 * @return
+			 */
+			private String primTypeName(Type typ) {
+				switch (typ.getSort()) {
+				case Type.DOUBLE:
+					return "Double";
+				case Type.INT:
+					return "Integer";
+				case Type.BOOLEAN:
+					return "Atom";
+				default:
+					throw new Error();
+				}
 			}
 
 			/**
@@ -465,30 +511,22 @@ private void emit_unbox(Type fromType, Type toType) {
 			private void emit_box(Type fromType, Type toType) {
 				if (fromType.equals(Type.INT_TYPE)
 						&& toType.getSort() == Type.OBJECT) {
-					mv.visitTypeInsn(NEW, EINTEGER_TYPE.getInternalName());
-					mv.visitInsn(DUP);
-					mv.visitMethodInsn(INVOKESPECIAL, EINTEGER_TYPE
-							.getInternalName(), "<init>", "(I)V");
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "box", "("
+									+ fromType.getDescriptor() + ")"
+									+ toType.getDescriptor());
 				} else if (fromType.equals(Type.DOUBLE_TYPE)
 						&& toType.getSort() == Type.OBJECT) {
-					mv.visitTypeInsn(NEW, EDOUBLE_TYPE.getInternalName());
-					mv.visitInsn(DUP);
-					mv.visitMethodInsn(INVOKESPECIAL, EDOUBLE_TYPE
-							.getInternalName(), "<init>", "(D)V");
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "box", "("
+									+ fromType.getDescriptor() + ")"
+									+ toType.getDescriptor());
 				} else if (fromType.equals(Type.BOOLEAN_TYPE)
 						&& toType.getSort() == Type.OBJECT) {
-					Label true_case = new Label();
-					Label end_case = new Label();
-
-					mv.visitJumpInsn(IFEQ, true_case);
-					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
-							"FALSE", EATOM_TYPE.getInternalName());
-					mv.visitJumpInsn(GOTO, end_case);
-					mv.visitLabel(true_case);
-					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
-							"TRUE", EATOM_TYPE.getInternalName());
-					mv.visitLabel(end_case);
-
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "box", "("
+									+ fromType.getDescriptor() + ")"
+									+ toType.getDescriptor());
 				} else {
 					throw new Error("cannot box " + fromType + " -> " + toType);
 				}
@@ -526,15 +564,31 @@ private void push(Arg value, Type stack_type) {
 				}
 			}
 
-			Map<ETerm,String> constants = new HashMap<ETerm,String>(); 
-			
 			/**
 			 * @param value
 			 * @param stack_type
 			 *            TODO
 			 */
 			private Type push_immediate(ETerm value, Type stack_type) {
 
+				if (value == ENil.NIL) {
+					mv.visitFieldInsn(GETSTATIC, ENIL_TYPE.getInternalName(),
+							"NIL", ENIL_TYPE.getDescriptor());
+					return ENIL_TYPE;
+				}
+
+				if (value == ERT.ATOM_TRUE) {
+					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
+							"ATOM_TRUE", EATOM_TYPE.getDescriptor());
+					return EATOM_TYPE;
+				}
+
+				if (value == ERT.ATOM_FALSE) {
+					mv.visitFieldInsn(GETSTATIC, ERT_TYPE.getInternalName(),
+							"ATOM_FALSE", EATOM_TYPE.getDescriptor());
+					return EATOM_TYPE;
+				}
+
 				if (stack_type.getSort() != Type.OBJECT) {
 					if (value instanceof EInteger) {
 						mv.visitLdcInsn(new Integer(value.asInt()));
@@ -553,22 +607,73 @@ private Type push_immediate(ETerm value, Type stack_type) {
 				}
 
 				String known = constants.get(value);
-				
+
 				if (known == null) {
-					constants.put(value, known = "cp$" + constants.size());
+					Type type = Type.getType(value.getClass());
+
+					String cn = getConstantName(value, constants.size());
+
+					constants.put(value, known = cn);
+					cv.visitField(ACC_STATIC, known, type.getDescriptor(),
+							null, null);
+
+					System.err.println(constants);
 				}
-				
+
 				if (known != null) {
 					Type type = Type.getType(value.getClass());
-					mv.visitFieldInsn(GETSTATIC, self_type.getInternalName(), known, type.getDescriptor());
+					mv.visitFieldInsn(GETSTATIC, self_type.getInternalName(),
+							known, type.getDescriptor());
 					return type;
 				}
-				
-				throw new Error("cannot push "+value + " as "+stack_type);
+
+				throw new Error("cannot push " + value + " as " + stack_type);
 
 				// return Type.getType(value.getClass());
 			}
 
+			/**
+			 * @param value
+			 * @param size
+			 * @return
+			 */
+			private String getConstantName(ETerm value, int size) {
+				if (value instanceof EAtom)
+					return "atom_" + EUtil.toJavaIdentifier((EAtom) value);
+				if (value instanceof ENumber)
+					return EUtil.toJavaIdentifier("num_"
+							+ value.toString().replace('.', '_').replace('-',
+									'_'));
+				if (value instanceof EString)
+					return "str_" + size;
+				else
+					return "cst_" + size;
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
+			 * erjang.beam.Arg[], erjang.beam.Arg)
+			 */
+			@Override
+			public void visitInsn(BeamOpcode opcode, Arg[] in, Arg out) {
+				switch (opcode) {
+				case put_list:
+					push(in[0], EOBJECT_TYPE);
+					push(in[1], EOBJECT_TYPE);
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "cons", "("
+									+ EOBJECT_TYPE.getDescriptor()
+									+ EOBJECT_TYPE.getDescriptor() + ")"
+									+ ECONS_TYPE.getDescriptor());
+					pop(out, ECONS_TYPE);
+					return;
+				}
+
+				throw new Error();
+			}
+
 			/*
 			 * (non-Javadoc)
 			 * 
@@ -578,14 +683,86 @@ private Type push_immediate(ETerm value, Type stack_type) {
 			public void visitInsn(BeamOpcode insn) {
 				switch (insn) {
 				case K_return:
+					mv.visitVarInsn(ALOAD, 0);
 					mv.visitInsn(ARETURN);
 					return;
 
+				case if_end:
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "if_end", EUtil
+									.getSignature(0));
+					mv.visitInsn(ARETURN);
+					return;
+
+				}
+
+				throw new Error();
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
+			 * int, erjang.beam.Arg)
+			 */
+			@Override
+			public void visitInsn(BeamOpcode opcode, int val, Arg out) {
+				switch (opcode) {
+				case put_tuple:
+					mv.visitTypeInsn(NEW, out.type.getInternalName());
+					mv.visitInsn(DUP);
+					mv.visitMethodInsn(INVOKESPECIAL, out.type
+							.getInternalName(), "<init>", "()V");
+					pop(out, out.type);
+
+					return;
+				}
+				throw new Error();
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
+			 * erjang.beam.Arg, erjang.beam.Arg, int)
+			 */
+			@Override
+			public void visitInsn(BeamOpcode opcode, Arg val, Arg out, int pos) {
+				if (opcode == BeamOpcode.put) {
+					push(out, out.type);
+					push(val, EOBJECT_TYPE);
+					mv.visitFieldInsn(PUTFIELD, out.type.getInternalName(),
+							"elm" + pos, EOBJECT_TYPE.getDescriptor());
+					return;
+
+				} else if (opcode == BeamOpcode.get_tuple_element) {
+					push(val, val.type);
+					mv.visitFieldInsn(GETFIELD, val.type.getInternalName(),
+							"elm" + pos, EOBJECT_TYPE.getDescriptor());
+					pop(out, EOBJECT_TYPE);
+					return;
+				} else if (opcode == BeamOpcode.set_tuple_element) {
+					push(out, out.type);
+					push(val, val.type);
+					mv.visitFieldInsn(PUTFIELD, val.type.getInternalName(),
+							"elm" + pos, EOBJECT_TYPE.getDescriptor());
+					return;
 				}
 
 				throw new Error();
 			}
 
+			/**
+			 * @param pos
+			 */
+			private void push_int(int pos) {
+				if (pos >= -1 && pos <= 5) {
+					mv.visitInsn(ICONST_0 + pos);
+				} else {
+					mv.visitLdcInsn(new Integer(pos));
+				}
+			}
+
 			/*
 			 * (non-Javadoc)
 			 * 
@@ -627,7 +804,44 @@ public void visitInsn(BeamOpcode opcode, ETuple et) {
 			 */
 			@Override
 			public void visitInsn(BeamOpcode opcode, Arg arg) {
-				throw new Error();
+				switch (opcode) {
+				case func_info:
+					ExtFunc f = (ExtFunc) arg;
+					push_immediate(f.mod, EATOM_TYPE);
+					push_immediate(f.fun, EATOM_TYPE);
+					mv.visitLdcInsn(new Integer(arg.no));
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "func_info", "("
+									+ ETUPLE_TYPE.getDescriptor()
+									+ ETUPLE_TYPE.getDescriptor() + "I)"
+									+ EOBJECT_TYPE.getDescriptor());
+					mv.visitInsn(ARETURN);
+					return;
+
+				case init:
+					push_immediate(ENil.NIL, ENIL_TYPE);
+					pop(arg, ENIL_TYPE);
+					return;
+
+				case case_end:
+					push(arg, EOBJECT_TYPE);
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "case_end", EUtil
+									.getSignature(1));
+					mv.visitInsn(ARETURN);
+					return;
+
+				case badmatch:
+					push(arg, EOBJECT_TYPE);
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "badmatch", EUtil
+									.getSignature(1));
+					mv.visitInsn(ARETURN);
+					return;
+
+				}
+
+				throw new Error("unhandled " + opcode);
 			}
 
 			/*
@@ -641,30 +855,65 @@ public void visitTest(BeamOpcode test, int failLabel, Arg arg1,
 					Type out) {
 				Method test_bif = get_test_bif(test, arg1.type);
 
-				push(arg1, test_bif.getArgumentTypes()[0]);
+				System.err.println(test_bif);
+
+				push(arg1, arg1.type);
 
 				mv.visitMethodInsn(INVOKEVIRTUAL, EOBJECT_TYPE
 						.getInternalName(), test_bif.getName(), test_bif
 						.getDescriptor());
 
 				Type returnType = test_bif.getReturnType();
 				if (failLabel != 0) {
-					// guard
-					if (returnType.getSort() != Type.OBJECT)
-						throw new Error("guards must return object type");
+					if (returnType.getSort() == Type.BOOLEAN) {
+						mv.visitJumpInsn(IFEQ, getLabel(failLabel));
+
+					} else {
+
+						// guard
+						if (returnType.getSort() != Type.OBJECT)
+							throw new Error("guards must return object type");
 
-					// dup result for test
-					if (arg1 != null) {
-						pop(arg1, returnType);
-						push(new Arg(arg1, returnType), returnType);
+						// dup result for test
+						if (arg1 != null) {
+							mv.visitInsn(DUP);
+							mv.visitVarInsn(ASTORE, scratch_reg);
+						}
+						mv.visitJumpInsn(IFNULL, getLabel(failLabel));
+						if (arg1 != null) {
+							mv.visitVarInsn(ALOAD, scratch_reg);
+							pop(arg1, returnType);
+						}
 					}
-					mv.visitJumpInsn(IFNULL, getLabel(failLabel));
 				} else {
 					pop(arg1, returnType);
 				}
 
 			}
 
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitTest(erjang.beam.BeamOpcode,
+			 * int, erjang.beam.Arg, int, org.objectweb.asm.Type)
+			 */
+			@Override
+			public void visitTest(BeamOpcode test, int failLabel, Arg arg,
+					int arity, Type tupleType) {
+
+				if (test != BeamOpcode.test_arity)
+					throw new Error();
+
+				push(arg, ETUPLE_TYPE);
+				mv.visitMethodInsn(INVOKEVIRTUAL,
+						ETUPLE_TYPE.getInternalName(), "count", "()I");
+				push_int(arity);
+				mv.visitJumpInsn(IF_ICMPNE, getLabel(failLabel));
+				push(arg, ETUPLE_TYPE);
+				mv.visitTypeInsn(CHECKCAST, tupleType.getInternalName());
+				pop(arg, tupleType);
+			}
+
 			/*
 			 * (non-Javadoc)
 			 * 
@@ -675,6 +924,15 @@ public void visitTest(BeamOpcode test, int failLabel, Arg arg1,
 			public void visitTest(BeamOpcode test, int failLabel, Arg[] args,
 					Arg out, Type outType) {
 
+				if (test == BeamOpcode.is_eq_exact
+						&& (args[0].type.equals(EATOM_TYPE) || args[1].type
+								.equals(EATOM_TYPE))) {
+					push(args[0], EOBJECT_TYPE);
+					push(args[1], EOBJECT_TYPE);
+					mv.visitJumpInsn(IF_ACMPNE, getLabel(failLabel));
+					return;
+				}
+
 				BIF bif = BIFUtil.getMethod(test.name(), args, true);
 
 				for (int i = 0; i < args.length; i++) {
@@ -686,15 +944,26 @@ public void visitTest(BeamOpcode test, int failLabel, Arg[] args,
 
 				if (failLabel != 0) {
 					// guard
-					if (bif.getReturnType().getSort() != Type.OBJECT)
-						throw new Error("guards must return object type");
+					switch (bif.getReturnType().getSort()) {
+					case Type.BOOLEAN:
+						if (out == null) {
+							mv.visitJumpInsn(IFEQ, getLabel(failLabel));
+						}
+						break;
 
-					if (out != null) {
-						pop(out, bif.getReturnType());
-						push(out, bif.getReturnType());
+					case Type.OBJECT:
+
+						if (out != null) {
+							pop(out, bif.getReturnType());
+							push(out, bif.getReturnType());
+						}
+
+						mv.visitJumpInsn(IFNULL, getLabel(failLabel));
+						break;
+					default:
+						throw new Error("guards must return object type");
 					}
 
-					mv.visitJumpInsn(IFNULL, getLabel(failLabel));
 				} else {
 					pop(out, bif.getReturnType());
 				}
@@ -718,25 +987,24 @@ public void visitInsn(BeamOpcode opcode, Arg arg1, Arg arg2) {
 				case fmove:
 					if (arg1.kind == Kind.F) {
 						push(arg1, Type.DOUBLE_TYPE);
-						
+
 						if (arg2.kind == Kind.F) {
 							pop(arg2, Type.DOUBLE_TYPE);
 						} else {
 							emit_convert(Type.DOUBLE_TYPE, EDOUBLE_TYPE);
-							pop(arg2, EDOUBLE_TYPE);							
+							pop(arg2, EDOUBLE_TYPE);
 						}
 					} else {
 						if (arg2.kind == Kind.F) {
 							push(arg1, Type.DOUBLE_TYPE);
 							pop(arg2, Type.DOUBLE_TYPE);
 						} else {
 							push(arg1, arg1.type);
-							pop(arg2, arg1.type);							
+							pop(arg2, arg1.type);
 						}
 					}
 					break;
 
-
 				default:
 					throw new Error("unhandled: " + opcode);
 				}
@@ -750,7 +1018,7 @@ public void visitInsn(BeamOpcode opcode, Arg arg1, Arg arg2) {
 			 */
 			private Method get_test_bif(BeamOpcode test, Type type) {
 
-				if (!EOBJECT_TYPE.equals(type)) {
+				if (!type.getInternalName().startsWith("erjang/E")) {
 					throw new Error("expecting EObject");
 				}
 
@@ -759,13 +1027,243 @@ private Method get_test_bif(BeamOpcode test, Type type) {
 					return IS_NONEMPTY_LIST_TEST;
 				case is_nil:
 					return IS_NIL_TEST;
+				case is_boolean:
+					return IS_BOOLEAN_TEST;
+				case is_atom:
+					return IS_ATOM_TEST;
 				case is_list:
 					return IS_LIST_TEST;
+				case is_tuple:
+					return IS_TUPLE_TEST;
+				case is_integer:
+					return IS_INTEGER_TEST;
 				}
 
 				throw new Error("unhandled " + test);
 			}
 
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
+			 * erjang.beam.Arg[])
+			 */
+			@Override
+			public void visitInsn(BeamOpcode opcode, Arg[] ys) {
+
+				if (opcode == BeamOpcode.allocate_zero
+						|| opcode == BeamOpcode.allocate_heap_zero) {
+
+					mv.visitFieldInsn(GETSTATIC, ENIL_TYPE.getInternalName(),
+							"NIL", ENIL_TYPE.getDescriptor());
+					for (int i = 0; i < ys.length; i++) {
+						if (i != (ys.length - 1))
+							mv.visitInsn(DUP);
+						pop(ys[i], ENIL_TYPE);
+					}
+
+					return;
+				} else if (opcode == BeamOpcode.get_list) {
+
+					push(ys[0], ECONS_TYPE);
+					mv.visitInsn(DUP);
+					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
+							.getInternalName(), "head", "()"
+							+ EOBJECT_TYPE.getDescriptor());
+					pop(ys[1], EOBJECT_TYPE);
+					mv.visitMethodInsn(INVOKEVIRTUAL, ECONS_TYPE
+							.getInternalName(), "tail", "()"
+							+ EOBJECT_TYPE.getDescriptor());
+					pop(ys[2], EOBJECT_TYPE);
+					return;
+
+				} else if (opcode == BeamOpcode.apply) {
+
+					for (int i = 0; i < ys.length; i++) {
+						push(ys[i], EOBJECT_TYPE);
+					}
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "apply", EUtil
+									.getSignature(ys.length));
+					mv.visitVarInsn(ASTORE, xregs[0]);
+
+					return;
+					
+				} else if (opcode == BeamOpcode.apply_last) {
+
+					for (int i = 0; i < ys.length; i++) {
+						push(ys[i], EOBJECT_TYPE);
+					}
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "apply$last", EUtil
+									.getSignature(ys.length));
+
+					mv.visitInsn(ARETURN);
+
+					return;
+					
+				} else if (opcode == BeamOpcode.send) {
+					for (int i = 0; i < ys.length; i++) {
+						push(ys[i], EOBJECT_TYPE);
+					}
+					mv.visitMethodInsn(INVOKESTATIC,
+							ERT_TYPE.getInternalName(), "send", EUtil
+									.getSignature(ys.length));
+					mv.visitVarInsn(ASTORE, xregs[0]);
+
+					return;
+				}
+
+				throw new Error("unhandled:" + opcode);
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitInsn(erjang.beam.BeamOpcode,
+			 * erjang.beam.ExtFunc, int)
+			 */
+			@Override
+			public void visitInsn(BeamOpcode opcode, ExtFunc efun,
+					Arg[] freevars) {
+				if (opcode == BeamOpcode.make_fun2) {
+
+					String funtype = EFUN_TYPE.getInternalName() + efun.no;
+					for (int i = 0; i < freevars.length; i++) {
+						push(freevars[i], EOBJECT_TYPE);
+					}
+
+					StringBuilder sb = new StringBuilder("(");
+					for (int i = 0; i < freevars.length; i++) {
+						sb.append(EOBJECT_TYPE.getDescriptor());
+					}
+					sb.append(")");
+					sb.append("L").append(funtype).append(";");
+					String gen_fun_desc = sb.toString();
+					String gen_fun_name = "make_fun2_"
+							+ EUtil.getJavaName(efun);
+
+					mv.visitMethodInsn(INVOKESTATIC, self_type
+							.getInternalName(), gen_fun_name, gen_fun_desc);
+
+					mv.visitVarInsn(ASTORE, 0);
+
+					return;
+				}
+
+				throw new Error();
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitSelectValue(erjang.beam.Arg,
+			 * int, erjang.beam.Arg[], int[])
+			 */
+			@Override
+			public void visitSelectValue(Arg in, int failLabel, Arg[] values,
+					int[] targets) {
+				int[] hash = new int[values.length];
+				Label[] label = new Label[values.length];
+				for (int i = 0; i < values.length; i++) {
+					hash[i] = values[i].value.hashCode();
+					label[i] = new Label();
+				}
+
+				push(in, EOBJECT_TYPE);
+				mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
+						"hashCode", "()I");
+				mv.visitLookupSwitchInsn(getLabel(failLabel), hash, label);
+
+				for (int i = 0; i < hash.length; i++) {
+					int h = hash[i];
+					for (int j = i; j < hash.length; j++) {
+						if (h == hash[j] && label[j] != null)
+							mv.visitLabel(label[j]);
+					}
+
+					for (int j = i; j < hash.length; j++) {
+						if (h == hash[j] && label[j] != null) {
+
+							if (values[j].type.equals(EATOM_TYPE)) {
+
+								push(in, in.type);
+								push(values[j], values[j].type);
+								mv.visitJumpInsn(IF_ACMPEQ,
+										getLabel(targets[j]));
+
+							} else {
+
+								if (in.type == values[j].type) {
+									push(in, in.type);
+									push(values[j], values[j].type);
+
+									mv.visitMethodInsn(INVOKESTATIC, ERT_TYPE
+											.getInternalName(), "eq", "("
+											+ in.type.getDescriptor()
+											+ in.type.getDescriptor() + ")Z");
+								} else {
+									push(in, EOBJECT_TYPE);
+									push(values[j], EOBJECT_TYPE);
+									mv.visitMethodInsn(INVOKEVIRTUAL,
+											"java/lang/Object", "equals",
+											"(Ljava/lang/Object;)Z");
+								}
+								mv.visitJumpInsn(IFNE, getLabel(targets[j]));
+							}
+							label[j] = null;
+						}
+					}
+
+					mv.visitJumpInsn(GOTO, getLabel(failLabel));
+				}
+			}
+
+			@Override
+			public void visitSelectTuple(Arg in, int failLabel, int[] arities,
+					int[] targets) {
+
+				push(in, ETUPLE_TYPE);
+
+				mv.visitMethodInsn(INVOKEVIRTUAL,
+						ETUPLE_TYPE.getInternalName(), "count", "()I");
+
+				Label[] targetLabels = new Label[targets.length];
+				for (int i = 0; i < targets.length; i++) {
+					targetLabels[i] = new Label();
+				}
+				mv.visitLookupSwitchInsn(getLabel(failLabel), arities,
+						targetLabels);
+				for (int i = 0; i < targetLabels.length; i++) {
+					mv.visitLabel(targetLabels[i]);
+					push(in, ETUPLE_TYPE);
+					mv.visitTypeInsn(CHECKCAST, getTubleType(arities[i])
+							.getInternalName());
+					pop(in, getTubleType(arities[i]));
+					mv.visitJumpInsn(GOTO, getLabel(targets[i]));
+				}
+
+			}
+
+			/*
+			 * (non-Javadoc)
+			 * 
+			 * @see erjang.beam.BlockVisitor2#visitJump(int)
+			 */
+			@Override
+			public void visitJump(int label) {
+				mv.visitJumpInsn(GOTO, getLabel(label));
+			}
+
+			/**
+			 * @param i
+			 * @return
+			 */
+			private Type getTubleType(int i) {
+				return Type.getType("L" + ETUPLE_TYPE.getInternalName() + i
+						+ ";");
+			}
+
 			/*
 			 * (non-Javadoc)
 			 * 
@@ -779,18 +1277,22 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
 				if (isExternal) {
 					String field = CompilerVisitor.this
 							.getExternalFunction(fun);
+					String funTypeName = EFUN_TYPE.getInternalName()
+							+ args.length;
 					mv.visitFieldInsn(GETSTATIC, self_type.getInternalName(),
-							field, EFUN_TYPE.getDescriptor());
+							field, "L" + funTypeName + ";");
 					for (int i = 0; i < args.length; i++) {
 						push(args[i], EOBJECT_TYPE);
 					}
 
-					mv.visitMethodInsn(INVOKEVIRTUAL, EFUN_TYPE
-							.getInternalName(), is_tail ? "invoke_tail"
-							: "invoke", EUtil.getSignature(args.length));
+					mv.visitMethodInsn(INVOKEVIRTUAL, funTypeName,
+							is_tail ? "invoke_tail" : "invoke", EUtil
+									.getSignature(args.length));
 
 					if (is_tail) {
 						mv.visitInsn(ARETURN);
+					} else {
+						mv.visitVarInsn(ASTORE, 0);
 					}
 
 				} else {
@@ -807,6 +1309,8 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
 
 					if (is_tail) {
 						mv.visitInsn(ARETURN);
+					} else {
+						mv.visitVarInsn(ASTORE, 0);
 					}
 
 				}
@@ -816,9 +1320,13 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
 	}
 
 	static Method IS_NONEMPTY_LIST_TEST = Method
-			.getMethod("erjang.ESeq asSeq()");
-	static Method IS_LIST_TEST = Method.getMethod("erjang.ECons asCons()");
-	static Method IS_NIL_TEST = Method.getMethod("erjang.ENil asNil()");
+			.getMethod("erjang.ECons testNonEmptyList()");
+	static Method IS_LIST_TEST = Method.getMethod("erjang.ECons testCons()");
+	static Method IS_TUPLE_TEST = Method.getMethod("erjang.ETuple testTuple()");
+	static Method IS_INTEGER_TEST = Method.getMethod("erjang.ETuple testInteger()");
+	static Method IS_ATOM_TEST = Method.getMethod("erjang.ETuple testAtom()");
+	static Method IS_NIL_TEST = Method.getMethod("boolean isNil()");
+	static Method IS_BOOLEAN_TEST = Method.getMethod("boolean isBoolean()");
 
 	Map<String, ExtFunc> imported = new HashMap<String, ExtFunc>();
 
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FCompilerVisitor.java
0361c1f81877cf304ad870d7145324f60abc57f0
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FExtFunc.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FExtFunc.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/ExtFunc.java
import erjang.ETuple;
	/**
	 * @param ext
	 */
	public ExtFunc(ETuple ext) {
		super(Kind.EXT_FUNC, ext.elm(3).asInt());
		this.mod = ext.elm(1).testAtom();
		this.fun = ext.elm(2).testAtom();
	}

ETuple ext
src/erjang/beam/ExtFunc.java
super(Kind.EXT_FUNC, ext.elm(3).asInt());
		this.mod = ext.elm(1).testAtom();
		this.fun = ext.elm(2).testAtom();
public ExtFunc(ETuple ext)
@@ -20,6 +20,7 @@
 package erjang.beam;
 
 import erjang.EAtom;
+import erjang.ETuple;
 
 /**
  * 
@@ -40,4 +41,13 @@ public ExtFunc(EAtom mod, EAtom fun, int arity) {
 
 	}
 
+	/**
+	 * @param ext
+	 */
+	public ExtFunc(ETuple ext) {
+		super(Kind.EXT_FUNC, ext.elm(3).asInt());
+		this.mod = ext.elm(1).testAtom();
+		this.fun = ext.elm(2).testAtom();
+	}
+
 }
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FExtFunc.java
536cb3ef544435b981b4f78524b4e37e13e1d7d7
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FOtpConverter.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2FOtpConverter.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/OtpConverter.java
				ETerm tail = obj.getLastTail() == null ? EList.NIL
				ETerm tail = obj.getLastTail() == null ? EList.EMPTY
@@ -73,7 +73,7 @@ ETerm conv(OtpErlangTuple obj) {
 		add(OtpErlangList.class, new Converter<OtpErlangList>() {
 			@Override
 			ETerm conv(OtpErlangList obj) {
-				ETerm tail = obj.getLastTail() == null ? EList.EMPTY
+				ETerm tail = obj.getLastTail() == null ? EList.NIL
 						: convert(obj.getLastTail());
 				for (int i = obj.arity() - 1; i >= 0; i--) {
 					tail = ERT.cons(convert(obj.elementAt(i)), tail);
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2FOtpConverter.java
faff42da4473e6cf9789c9c8601b39a434701760
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2Fanalysis%2FBeamTypeAnalysis.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fbeam%2Fanalysis%2FBeamTypeAnalysis.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/beam/analysis/BeamTypeAnalysis.java
	static final ETerm APPLY_ATOM = EAtom.intern("apply");
					if (BeamOpcode.get(lb.insns.get(0).elm(1).testAtom()) == BeamOpcode.func_info) {
			try {
				if (fv instanceof FunctionVisitor2) {
					((FunctionVisitor2) fv).visitMaxs(this.max_xreg,
							this.max_stack, this.max_freg,
							this.is_tail_recursive);
				}
				for (LabeledBlock block : this.lbs.values()) {
					BlockVisitor vis = super.fv
							.visitLabeledBlock(block.block_label);
					block.accept(vis);
				}
			} finally {
				super.fv.visitEnd();
				try {
					if (!isDeadCode()) {
						if (vis instanceof BlockVisitor2) {
							accept_2((BlockVisitor2) vis);
						} else {
							accept_1(vis);
						}
					}
				} finally {
					vis.visitEnd();
					BeamOpcode opcode = BeamOpcode.get(insn.elm(1).testAtom());
				int tuple_pos = 0;
				Arg tuple_reg = null;

					BeamOpcode opcode = BeamOpcode.get(insn.elm(1).testAtom());
					TypeMap type_map = this.map[insn_idx];
						System.err.print("go: " + insn);
						vis.visitInsn(opcode,
								(Arg) new ExtFunc(insn.elm(2).testTuple().elm(2)
										.testAtom(), insn.elm(3).testTuple().elm(2)
										.testAtom(), insn.elm(4).asInt()));

						Arg arg1 = decode_arg(insn_idx, insn.elm(2));
						Arg arg2 = decode_arg(insn_idx, insn.elm(3));


					case arithfbif: {
						System.err.println("gen: " + insn);
						EAtom name = insn.elm(2).testAtom();
						int failLabel = decode_labelref(insn.elm(3));
						ESeq parms = insn.elm(4).testSeq();
						Arg out = decode_out_arg(insn_idx, insn.elm(5));
					case bif: {
						System.err.println("gen: " + insn);
						EAtom name = insn.elm(2).testAtom();
						int failLabel = decode_labelref(insn.elm(3));
						ESeq parms = insn.elm(4).testSeq();
						Arg out = decode_out_arg(insn_idx, insn.elm(5));

					case gc_bif: {
						System.err.println("gen: " + insn);
						EAtom name = insn.elm(2).testAtom();
						int failLabel = decode_labelref(insn.elm(3));
						ESeq parms = insn.elm(5).testSeq();
						Arg[] in = decode_args(insn_idx, parms.toArray());
						Arg out = decode_out_arg(insn_idx, insn.elm(6));

						BIF bif = BIFUtil.getMethod(name.getName(), parmTypes(
								this.map[insn_idx], parms), failLabel != 0);

						vis.visitInsn(opcode, failLabel, in, out, bif);
						break;
					}


					case allocate_zero: {
						int depth = type_map.stacksize;
						int count = insn.elm(2).asInt();
						Arg[] ys = new Arg[count];
						for (int i = 0; i < count; i++) {
							ys[i] = new Arg(Arg.Kind.Y, i);
						}
						vis.visitInsn(opcode, (Arg[]) ys);
						break;

					}



					case call_ext_last:
						do_call(vis, insn_idx, insn, true, true);
						break;

					case call_ext:
						do_call(vis, insn_idx, insn, false, true);
						break;

					case call:
						do_call(vis, insn_idx, insn, false, false);
						break;

					case call_last:
					case call_only:
						do_call(vis, insn_idx, insn, true, false);
						break;

					case apply_last:
					case apply: {
						Arg[] args = new Arg[2+insn.elm(2).asInt()];
						for (int i = 0; i < args.length; i++) {
							args[i] = new Arg(Arg.Kind.X, i, map[insn_idx].getx(i));
						}
						vis.visitInsn(opcode, args);
						break;
						
					}
						
					case make_fun2:
					{
						ExtFunc efun = new ExtFunc(insn.elm(2).testTuple());
						int numfree = insn.elm(5).asInt();
						Arg[] free = new Arg[numfree];
						for (int i = 0; i < numfree; i++) { free[i] = new Arg(Arg.Kind.X, i, map[insn_idx].getx(i)); }
						vis.visitInsn(opcode, efun, free);
						break;
					}
						
					case init:
						vis.visitInsn(opcode, decode_arg(insn_idx, insn.elm(2)));
						break;
						
					case put_list:
					{
						Arg[] in = new Arg[] { decode_arg(insn_idx, insn.elm(2)), decode_arg(insn_idx, insn.elm(3)) };
						Arg out = decode_out_arg(insn_idx, insn.elm(4));
						
						vis.visitInsn(opcode, in, out);
						break;
					}
					
					case put_tuple:
					{
						
						int arity = insn.elm(2).asInt();
						Type tupleType = getTupleType(arity);
						tuple_reg = new Arg (decode_out_arg(insn_idx, insn.elm(3)), tupleType);
						vis.visitInsn(opcode, arity, tuple_reg);
						tuple_pos = 1;
						break;
					}
						
					case put: 
					{
						Arg val = decode_arg(insn_idx, insn.elm(2));
						vis.visitInsn(opcode, val, tuple_reg, tuple_pos++);
						break;
					}

					case set_tuple_element: {
						Arg in = decode_arg(insn_idx, insn.elm(2));
						Arg out = decode_arg(insn_idx, insn.elm(3));
						int idx = insn.elm(4).asInt();

						vis.visitInsn(opcode, in, out, idx);
						
						break;
					}
					

					case allocate_heap:
					case allocate:
					case deallocate:
						// need to zero out refs?
						break;
					}
					
					case select_tuple_arity: {
						int failLabel = decode_labelref(insn.elm(3));
						Arg in = decode_arg(insn_idx, insn.elm(2));

						
						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
						int len = cases.length()/2;
						
						int[] arities = new int[len];
						int[] targets = new int[len];

						int idx = 0;
						
						while (cases != ESeq.NIL) {
							arities[idx] = cases.head().asInt();
							EObject target = cases.tail().head();
							targets[idx] = decode_labelref(target);

							cases = cases.tail().tail();
							idx += 1;
						
						vis.visitSelectTuple(in, failLabel, arities, targets);
						
						break;

					case select_val: {
						Arg in = decode_arg(insn_idx, insn.elm(2));
						int failLabel = decode_labelref(insn.elm(3));
						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
						int len = cases.length()/2;
						
						Arg[] values = new Arg[len];
						int[] targets = new int[len];

						int idx = 0;
						
						while (cases != ESeq.NIL) {
							values[idx] = decode_value (cases.head());
							EObject target = cases.tail().head();
							targets[idx] = decode_labelref(target);

							cases = cases.tail().tail();
							idx += 1;
						}
						
						vis.visitSelectValue(in, failLabel, values, targets);
						
						break;
					}


					
					case get_tuple_element: {
						
						Arg in = decode_arg(insn_idx, insn.elm(2));
						int idx = insn.elm(3).asInt();
						Arg out = decode_out_arg(insn_idx, insn.elm(4));

						vis.visitInsn(opcode, in, out, idx);
						
						break;
					}
					
					case jump:
						vis.visitJump(decode_labelref(insn.elm(2)));
						break;
						
					case trim:
						break;
					
					case get_list:
						vis.visitInsn(opcode, new Arg[] { decode_arg(insn_idx, insn.elm(2)), 
								decode_out_arg(insn_idx, insn.elm(3)), 
								decode_out_arg(insn_idx, insn.elm(4))
								});
						break;
						
					case badmatch:
					case case_end:
						vis.visitInsn(opcode, decode_arg(insn_idx, insn.elm(2)));
					case if_end:
						vis.visitInsn(opcode);
						break;
						
					case send: {
						vis.visitInsn(opcode, new Arg[] { new Arg(Arg.Kind.X, 0), new Arg(Arg.Kind.X, 1) });
						break;
					}
						
			private void do_call(BlockVisitor2 vis, int insn_idx, ETuple insn,
					boolean is_tail, boolean is_external) throws Error {
				int arg_count = insn.elm(2).asInt();
				Arg[] args = new Arg[arg_count];
				for (int i = 0; i < arg_count; i++) {
					args[i] = new Arg(Kind.X, i, this.map[insn_idx].getx(i));
				}
				
				ETuple ft = insn.elm(3).testTuple();
				ExtFunc fun;
				if (ft.elm(1) != EXTFUNC_ATOM)
					fun = new ExtFunc(ft.elm(1).testAtom(), ft.elm(2)
							.testAtom(), ft.elm(3).asInt());
				else
					fun = new ExtFunc(ft.elm(2).testAtom(), ft.elm(3)
						.testAtom(), ft.elm(4).asInt());
				vis.visitCall(fun, args, is_tail, is_external);
			}

				int failLabel = decode_labelref(insn.elm(3));
				EObject[] argExprs = insn.elm(4).testSeq().toArray();
				Arg[] args = decode_args(insn_idx, argExprs);
				BeamOpcode test = BeamOpcode.get(insn.elm(2).testAtom());
				case is_boolean:
				case is_atom:
					vis.visitTest(test, failLabel, args[0], EATOM_TYPE);
					break;

				case is_integer:
					vis.visitTest(test, failLabel, args[0], EINTEGER_TYPE);
					break;

				case is_tuple:
					vis.visitTest(test, failLabel, args[0], ETUPLE_TYPE);
					break;

				case is_lt:
				case is_ge:
				case is_eq_exact:
				case is_ne_exact:
				case is_ne:
					vis.visitTest(test, failLabel, args, (Arg) null,
							Type.VOID_TYPE);
					break;

				case test_arity:
					int arity = argExprs[1].asInt();
					vis.visitTest(test, failLabel, args[0], arity, getTupleType(arity));
					
							+ insn_idx + " // " + test + ":" + test.ordinal());
						return new Arg(tup.elem2, EATOM_TYPE);
						if (tup.elem2.testInteger() != null) {
					return new Arg(ENil.NIL, ENIL_TYPE);
			/**
			 * @param insnIdx
			 * @param eObject
			 * @return
			 */
			private Arg decode_value(EObject src) {

				if (src instanceof ETuple2) {
					ETuple2 tup = (ETuple2) src;
					if (tup.elem1 == ATOM_ATOM) {
						return new Arg(tup.elem2, EATOM_TYPE);
					} else if (tup.elem1 == LITERAL_ATOM) {
						return new Arg(tup.elem2);
					} else if (tup.elem1 == INTEGER_ATOM) {
						if (tup.elem2.testInteger() != null) {
							return new Arg(tup.elem2, Type.INT_TYPE);
						} else {
							return new Arg(tup.elem2);
						}
					} else if (tup.elem1 == FLOAT_ATOM) {
						return new Arg(tup.elem2, Type.DOUBLE_TYPE);
					}

				} else if (src == NIL_ATOM) {
					return new Arg(ENil.NIL, ENIL_TYPE);

				}

				throw new Error("unknown value");

			}


			
					}
				if (f_tup == NOFAIL_ATOM)
					return 0;
				assert (f_tup.testTuple().elm(1) == F_ATOM);
				return f_tup.testTuple().elm(2).asInt();
					BeamOpcode code = BeamOpcode.get(insn.elm(1).testAtom());
						EObject src = insn.elm(2);
						EObject dst = insn.elm(3);
						current = branch(current, insn.elm(2), insn_idx);
						EAtom name = insn.elm(2).testAtom();
						ESeq parms = insn.elm(4).testSeq();
						current = setType(current, insn.elm(5), type);
						if (insn.elm(3).testTuple().elm(2).asInt() != 0) {
						current = branch(current, insn.elm(3), insn_idx);
						EAtom name = insn.elm(2).testAtom();
						ESeq parms = insn.elm(5).testSeq();
						current = setType(current, insn.elm(6), type);
						current = branch(current, insn.elm(3), insn_idx);
						EAtom name = insn.elm(2).testAtom();
						ESeq parms = insn.elm(4).testSeq();
						current = setType(current, insn.elm(5), type);
						getType(current, insn.elm(2));
						current = setType(current, insn.elm(3),
						current = setType(current, insn.elm(2), null);
						getType(current, insn.elm(2));
						getType(current, insn.elm(3));
						EObject src = insn.elm(2);
						int idx = insn.elm(3).asInt();
						EObject dst = insn.elm(4);
						EObject from = insn.elm(2);
						EObject head_into = insn.elm(3);
						EObject tail_into = insn.elm(4);
						Type head_type = getType(current, insn.elm(2));
						Type tail_type = getType(current, insn.elm(3));
							throw new Error("value: " + insn.elm(3)
							current = setType(current, insn.elm(4), ELIST_TYPE);
							current = setType(current, insn.elm(4), ECONS_TYPE);
						int arity = insn.elm(2).asInt();
						ETuple reg = insn.elm(3).testTuple();
						current = setType(current, insn.elm(2), EOBJECT_TYPE);
						current = branch(current, insn.elm(3), insn_idx);
						getType(current, insn.elm(2));
						if (insn.elm(2).testTuple().elm(2).asInt() != 0) {
						checkArgs(current, insn.elm(3), insn);
						current = setType(current, insn.elm(4), EOBJECT_TYPE);
						current = branch(current, insn.elm(3), insn_idx);
						current.touchx(0, insn.elm(5).asInt());
						current = branch(current, insn.elm(2), insn_idx);
						current = setType(current, insn.elm(3), EOBJECT_TYPE);
						Type timeout_type = getType(current, insn.elm(3));
						current = branch(current, insn.elm(2), insn_idx);
						int howmuch = insn.elm(2).asInt();
						int slots = insn.elm(2).asInt();
						current = current.alloc_y(insn.elm(2).asInt());
						getType(current, insn.elm(2));
						current = branch(current, insn.elm(3), insn_idx);
						getType(current, insn.elm(2));
						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
						while (cases != ESeq.NIL) {
							current = setType(current, insn.elm(2), getTupleType(value.asInt()));
							
						current = branch(current, insn.elm(3), insn_idx);
						getType(current, insn.elm(2));
						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
						while (cases != ESeq.NIL) {
						int argCount = insn.elm(2).asInt();
						int argCount = insn.elm(2).asInt();
						Type ctx = getType(current, insn.elm(2));
				if ((at = cell.testTuple()) != null) {
						if (at.elm(1) == X_ATOM)
						if (at.elm(1) == Y_ATOM)
						if (at.elm(1) == FR_ATOM)
				while (args != ESeq.NIL) {
				ESeq args = eTerm.testSeq();
				while (args != ESeq.NIL) {
				current = branch(current, insn.elm(3), insn_idx);
				EObject[] args = insn.elm(4).testSeq().toArray();
				BeamOpcode test = BeamOpcode.get(insn.elm(2).testAtom());
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), ENIL_TYPE);
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), ECONS_TYPE);
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), EBINARY_TYPE);
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), ETUPLE_TYPE);
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), getTupleType(arg2
					checkArgs(current, insn.elm(4), insn);
					return setType(current, arg1.testTuple(), EATOM_TYPE);
					checkArgs(current, insn.elm(4), insn);
					checkArgs(current, insn.elm(4), insn);
					checkArgs(current, insn.elm(4), insn);
					checkArgs(current, insn.elm(4), insn);
					checkArgs(current, insn.elm(4), insn);
					checkArgs(current, insn.elm(4), insn);
							current = setType(current, arg1.testTuple(), t2);
							current = setType(current, arg2.testTuple(), t1);
					checkArgs(current, insn.elm(4), insn);
					if ((tup = args[3].testTuple()) != null) {
						if (tup.elm(1) == INTEGER_ATOM
								&& tup.elm(2).asInt() <= 32) {
					ETuple tuple = nth.testTuple();
					if (tuple.elm(1) != F_ATOM)
					int target = tuple.elm(2).asInt();
				ETuple et = arg2.testTuple();
				return (et != null && et.elm(1) == X_ATOM
						|| et.elm(1) == Y_ATOM || et.elm(1) == FR_ATOM);
				ETuple dst = dd.testTuple();
				EObject key = dst.elm(1);
				EObject value = dst.elm(2);
					return BeamOpcode.get(insn.elm(1).testAtom());
EObject src
src/erjang/beam/analysis/BeamTypeAnalysis.java
if (src instanceof ETuple2) {
					ETuple2 tup = (ETuple2) src;
					if (tup.elem1 == ATOM_ATOM) {
						return new Arg(tup.elem2, EATOM_TYPE);
Arg decode_value(EObject src)
tup.elem1 == LITERAL_ATOM
src/erjang/beam/analysis/BeamTypeAnalysis.java
return new Arg(tup.elem2);
else if (tup.elem1 == LITERAL_ATOM)
tup.elem1 == INTEGER_ATOM
src/erjang/beam/analysis/BeamTypeAnalysis.java
if (tup.elem2.testInteger() != null) {
							return new Arg(tup.elem2, Type.INT_TYPE);
else if (tup.elem1 == INTEGER_ATOM)
tup.elem1 == FLOAT_ATOM
src/erjang/beam/analysis/BeamTypeAnalysis.java
return new Arg(tup.elem2, Type.DOUBLE_TYPE);
else if (tup.elem1 == FLOAT_ATOM)
src == NIL_ATOM
src/erjang/beam/analysis/BeamTypeAnalysis.java
return new Arg(ENil.NIL, ENIL_TYPE);
else if (src == NIL_ATOM)
					if (BeamOpcode.get(lb.insns.get(0).nth(1).asAtom()) == BeamOpcode.func_info) {
			if (fv instanceof FunctionVisitor2) {
				((FunctionVisitor2) fv).visitMaxs(this.max_xreg,
						this.max_stack, this.max_freg, this.is_tail_recursive);
			}
			for (LabeledBlock block : this.lbs.values()) {
				BlockVisitor vis = super.fv
						.visitLabeledBlock(block.block_label);
				block.accept(vis);

			super.fv.visitEnd();
				if (!isDeadCode()) {
					if (vis instanceof BlockVisitor2) {
						accept_2((BlockVisitor2) vis);
					} else {
						accept_1(vis);
					}

				vis.visitEnd();
					BeamOpcode opcode = BeamOpcode.get(insn.nth(1).asAtom());
					BeamOpcode opcode = BeamOpcode.get(insn.nth(1).asAtom());
						vis.visitInsn(opcode, (Arg) new ExtFunc(insn.nth(2)
								.asAtom(), insn.nth(3).asAtom(), insn.nth(4)
								.asInt()));
						
						Arg arg1 = decode_arg(insn_idx, insn.nth(2));
						Arg arg2 = decode_arg(insn_idx, insn.nth(3));
						
						
						
					case arithfbif:
					{
						System.err.println("gen: "+insn);
						EAtom name = insn.nth(2).asAtom();
						int failLabel = decode_labelref(insn.nth(3));
						ESeq parms = insn.nth(4).asSeq();
						Arg out = decode_out_arg(insn_idx, insn.nth(5));
						
					case gc_bif:
					case bif:
					{
						System.err.println("gen: "+insn);
						EAtom name = insn.nth(2).asAtom();
						int failLabel = decode_labelref(insn.nth(3));
						ESeq parms = insn.nth(5).asSeq();
						Arg out = decode_out_arg(insn_idx, insn.nth(6));
						
						
						
						
						boolean is_tail = true;
						boolean is_external = true;
						int arg_count = insn.nth(2).asInt();
						Arg[] args = new Arg[arg_count];
						for (int i = 0; i < arg_count; i++) {
							args[i] = new Arg(Kind.X, i, this.map[insn_idx].getx(i));
						ETuple ft = insn.nth(3).asTuple();
						if (ft.nth(1) != EXTFUNC_ATOM) throw new Error();
						ExtFunc fun = new ExtFunc(ft.nth(2).asAtom(), ft.nth(3).asAtom(), ft.nth(4).asInt());
						vis.visitCall(fun, args, is_tail, is_external);
				int failLabel = decode_labelref(insn.nth(3));
				Arg[] args = decode_args(insn_idx, insn.nth(4).asSeq()
						.toArray());
				BeamOpcode test = BeamOpcode.get(insn.nth(2).asAtom());
					vis.visitTest(test, failLabel, args, (Arg)null, Type.VOID_TYPE);
							+ insn_idx);
						return new Arg(tup.elem2);
						if (tup.elem2.asInteger() != null) {
					return new Arg(src);
					} 
				assert (f_tup.asTuple().nth(1) == F_ATOM);
				return f_tup.asTuple().nth(2).asInt();
					BeamOpcode code = BeamOpcode.get(insn.nth(1).asAtom());
						EObject src = insn.nth(2);
						EObject dst = insn.nth(3);
						current = branch(current, insn.nth(2), insn_idx);
						EAtom name = insn.nth(2).asAtom();
						ESeq parms = insn.nth(4).asSeq();
						current = setType(current, insn.nth(5), type);
						if (insn.nth(3).asTuple().nth(2).asInt() != 0) {
						current = branch(current, insn.nth(3), insn_idx);
						EAtom name = insn.nth(2).asAtom();
						ESeq parms = insn.nth(5).asSeq();
						current = setType(current, insn.nth(6), type);
						current = branch(current, insn.nth(3), insn_idx);
						EAtom name = insn.nth(2).asAtom();
						ESeq parms = insn.nth(4).asSeq();
						current = setType(current, insn.nth(5), type);
						getType(current, insn.nth(2));
						current = setType(current, insn.nth(3),
						current = setType(current, insn.nth(2), null);
						getType(current, insn.nth(2));
						getType(current, insn.nth(3));
						EObject src = insn.nth(2);
						int idx = insn.nth(3).asInt();
						EObject dst = insn.nth(4);
						EObject from = insn.nth(2);
						EObject head_into = insn.nth(3);
						EObject tail_into = insn.nth(4);
						Type head_type = getType(current, insn.nth(2));
						Type tail_type = getType(current, insn.nth(3));
							throw new Error("value: " + insn.nth(3)
							current = setType(current, insn.nth(4), ELIST_TYPE);
							current = setType(current, insn.nth(4), ECONS_TYPE);
						int arity = insn.nth(2).asInt();
						ETuple reg = insn.nth(3).asTuple();
						current = setType(current, insn.nth(2), EOBJECT_TYPE);
						current = branch(current, insn.nth(3), insn_idx);
						getType(current, insn.nth(2));
						if (insn.nth(2).asTuple().nth(2).asInt() != 0) {
						checkArgs(current, insn.nth(3), insn);
						current = setType(current, insn.nth(4), EOBJECT_TYPE);
						current = branch(current, insn.nth(3), insn_idx);
						current.touchx(0, insn.nth(5).asInt());
						current = branch(current, insn.nth(2), insn_idx);
						current = setType(current, insn.nth(3), EOBJECT_TYPE);
						Type timeout_type = getType(current, insn.nth(3));
						current = branch(current, insn.nth(2), insn_idx);
						int howmuch = insn.nth(2).asInt();
						int slots = insn.nth(2).asInt();
						current = current.alloc_y(insn.nth(2).asInt());
						getType(current, insn.nth(2));
						current = branch(current, insn.nth(3), insn_idx);
						getType(current, insn.nth(2));
						ESeq cases = insn.nth(4).asTuple().nth(2).asSeq();
						while (cases != ESeq.EMPTY) {
						current = branch(current, insn.nth(3), insn_idx);
						getType(current, insn.nth(2));
						ESeq cases = insn.nth(4).asTuple().nth(2).asSeq();
						while (cases != ESeq.EMPTY) {
						int argCount = insn.nth(2).asInt();
						int argCount = insn.nth(2).asInt();
						Type ctx = getType(current, insn.nth(2));
				if ((at = cell.asTuple()) != null) {
						if (at.nth(1) == X_ATOM)
						if (at.nth(1) == Y_ATOM)
						if (at.nth(1) == FR_ATOM)
				while (args != ESeq.EMPTY) {
				ESeq args = eTerm.asSeq();
				while (args != ESeq.EMPTY) {
				current = branch(current, insn.nth(3), insn_idx);
				EObject[] args = insn.nth(4).asSeq().toArray();
				BeamOpcode test = BeamOpcode.get(insn.nth(2).asAtom());
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), ENIL_TYPE);
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), ECONS_TYPE);
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), EBINARY_TYPE);
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), ETUPLE_TYPE);
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), getTupleType(arg2
					checkArgs(current, insn.nth(4), insn);
					return setType(current, arg1.asTuple(), EATOM_TYPE);
					checkArgs(current, insn.nth(4), insn);
					checkArgs(current, insn.nth(4), insn);
					checkArgs(current, insn.nth(4), insn);
					checkArgs(current, insn.nth(4), insn);
					checkArgs(current, insn.nth(4), insn);
					checkArgs(current, insn.nth(4), insn);
							current = setType(current, arg1.asTuple(), t2);
							current = setType(current, arg2.asTuple(), t1);
					checkArgs(current, insn.nth(4), insn);
					if ((tup = args[3].asTuple()) != null) {
						if (tup.nth(1) == INTEGER_ATOM
								&& tup.nth(2).asInt() <= 32) {
					ETuple tuple = nth.asTuple();
					if (tuple.nth(1) != F_ATOM)
					int target = tuple.nth(2).asInt();
				ETuple et = arg2.asTuple();
				return (et != null && et.nth(1) == X_ATOM
						|| et.nth(1) == Y_ATOM || et.nth(1) == FR_ATOM);
				ETuple dst = dd.asTuple();
				EObject key = dst.nth(1);
				EObject value = dst.nth(2);
					return BeamOpcode.get(insn.nth(1).asAtom());
@@ -103,6 +103,7 @@ public BeamTypeAnalysis(ModuleVisitor mv) {
 	static final ETerm F_ATOM = EAtom.intern("f");
 	static final ETerm FIELD_FLAGS_ATOM = EAtom.intern("field_flags");
 	static final ETerm EXTFUNC_ATOM = EAtom.intern("extfunc");
+	static final ETerm APPLY_ATOM = EAtom.intern("apply");
 
 	private static final ETuple X0_REG = ETuple.make(new ETerm[] { X_ATOM,
 			new EInteger(0) });
@@ -245,7 +246,7 @@ public void visitEnd() {
 			for (int i : labels) {
 				lb = lbs.get(i);
 				if (lb.isDeadCode()) {
-					if (BeamOpcode.get(lb.insns.get(0).nth(1).asAtom()) == BeamOpcode.func_info) {
+					if (BeamOpcode.get(lb.insns.get(0).elm(1).testAtom()) == BeamOpcode.func_info) {
 						// ignore this
 					} else {
 						System.err.println("UNREACHABLE " + lb.block_label);
@@ -263,20 +264,23 @@ public void visitEnd() {
 
 		private void function_visit_end() {
 
-			if (fv instanceof FunctionVisitor2) {
-				((FunctionVisitor2) fv).visitMaxs(this.max_xreg,
-						this.max_stack, this.max_freg, this.is_tail_recursive);
-			}
+			try {
+				if (fv instanceof FunctionVisitor2) {
+					((FunctionVisitor2) fv).visitMaxs(this.max_xreg,
+							this.max_stack, this.max_freg,
+							this.is_tail_recursive);
+				}
 
-			for (LabeledBlock block : this.lbs.values()) {
+				for (LabeledBlock block : this.lbs.values()) {
 
-				BlockVisitor vis = super.fv
-						.visitLabeledBlock(block.block_label);
+					BlockVisitor vis = super.fv
+							.visitLabeledBlock(block.block_label);
 
-				block.accept(vis);
+					block.accept(vis);
+				}
+			} finally {
+				super.fv.visitEnd();
 			}
-
-			super.fv.visitEnd();
 		}
 
 		private void dump() {
@@ -335,47 +339,54 @@ public LabeledBlock(int label) {
 			 */
 			public void accept(BlockVisitor vis) {
 
-				if (!isDeadCode()) {
+				try {
+					if (!isDeadCode()) {
 
-					if (vis instanceof BlockVisitor2) {
-						accept_2((BlockVisitor2) vis);
-					} else {
-						accept_1(vis);
-					}
+						if (vis instanceof BlockVisitor2) {
+							accept_2((BlockVisitor2) vis);
+						} else {
+							accept_1(vis);
+						}
 
+					}
+				} finally {
+					vis.visitEnd();
 				}
-
-				vis.visitEnd();
 			}
 
 			private void accept_1(BlockVisitor vis) {
 				for (int i = 0; i < insns.size(); i++) {
 					ETuple insn = insns.get(i);
-					BeamOpcode opcode = BeamOpcode.get(insn.nth(1).asAtom());
+					BeamOpcode opcode = BeamOpcode.get(insn.elm(1).testAtom());
 					vis.visitInsn(opcode, insn);
 				}
 			}
 
 			private void accept_2(BlockVisitor2 vis) {
+				int tuple_pos = 0;
+				Arg tuple_reg = null;
+
 				for (int insn_idx = 0; insn_idx < insns.size(); insn_idx++) {
 					ETuple insn = insns.get(insn_idx);
-					BeamOpcode opcode = BeamOpcode.get(insn.nth(1).asAtom());
+					BeamOpcode opcode = BeamOpcode.get(insn.elm(1).testAtom());
+					TypeMap type_map = this.map[insn_idx];
 
 					switch (opcode) {
 					case func_info:
-						vis.visitInsn(opcode, (Arg) new ExtFunc(insn.nth(2)
-								.asAtom(), insn.nth(3).asAtom(), insn.nth(4)
-								.asInt()));
+						System.err.print("go: " + insn);
+						vis.visitInsn(opcode,
+								(Arg) new ExtFunc(insn.elm(2).testTuple().elm(2)
+										.testAtom(), insn.elm(3).testTuple().elm(2)
+										.testAtom(), insn.elm(4).asInt()));
 						break;
-						
+
 					case fconv:
 					case fmove:
 					case move: {
 						System.err.println(insn);
-						Arg arg1 = decode_arg(insn_idx, insn.nth(2));
-						Arg arg2 = decode_arg(insn_idx, insn.nth(3));
-						
-						
+						Arg arg1 = decode_arg(insn_idx, insn.elm(2));
+						Arg arg2 = decode_arg(insn_idx, insn.elm(3));
+
 						if (arg2.kind != Kind.F) {
 							if (arg1.kind == Kind.F) {
 								arg2 = new Arg(arg2, EDOUBLE_TYPE);
@@ -385,94 +396,311 @@ private void accept_2(BlockVisitor2 vis) {
 						} else {
 							// arg2.kind == F
 						}
-						
+
 						vis.visitInsn(opcode, arg1, arg2);
 						break;
 					}
 
-					case arithfbif:
-					{
-						System.err.println("gen: "+insn);
-						EAtom name = insn.nth(2).asAtom();
-						int failLabel = decode_labelref(insn.nth(3));
-						ESeq parms = insn.nth(4).asSeq();
+					case arithfbif: {
+						System.err.println("gen: " + insn);
+						EAtom name = insn.elm(2).testAtom();
+						int failLabel = decode_labelref(insn.elm(3));
+						ESeq parms = insn.elm(4).testSeq();
 						Arg[] in = decode_args(insn_idx, parms.toArray());
-						Arg out = decode_out_arg(insn_idx, insn.nth(5));
+						Arg out = decode_out_arg(insn_idx, insn.elm(5));
 
 						BIF bif = BIFUtil.getMethod(name.getName(), parmTypes(
 								this.map[insn_idx], parms), failLabel != 0);
 
-						
 						vis.visitInsn(opcode, failLabel, in, out, bif);
 						break;
 					}
 
-					case gc_bif:
-					case bif:
-					{
-						System.err.println("gen: "+insn);
-						EAtom name = insn.nth(2).asAtom();
-						int failLabel = decode_labelref(insn.nth(3));
-						ESeq parms = insn.nth(5).asSeq();
+					case bif: {
+						System.err.println("gen: " + insn);
+						EAtom name = insn.elm(2).testAtom();
+						int failLabel = decode_labelref(insn.elm(3));
+						ESeq parms = insn.elm(4).testSeq();
 						Arg[] in = decode_args(insn_idx, parms.toArray());
-						Arg out = decode_out_arg(insn_idx, insn.nth(6));
+						Arg out = decode_out_arg(insn_idx, insn.elm(5));
 
 						BIF bif = BIFUtil.getMethod(name.getName(), parmTypes(
 								this.map[insn_idx], parms), failLabel != 0);
 
-						
 						vis.visitInsn(opcode, failLabel, in, out, bif);
 						break;
 					}
-						
+
+					case gc_bif: {
+						System.err.println("gen: " + insn);
+						EAtom name = insn.elm(2).testAtom();
+						int failLabel = decode_labelref(insn.elm(3));
+						ESeq parms = insn.elm(5).testSeq();
+						Arg[] in = decode_args(insn_idx, parms.toArray());
+						Arg out = decode_out_arg(insn_idx, insn.elm(6));
+
+						BIF bif = BIFUtil.getMethod(name.getName(), parmTypes(
+								this.map[insn_idx], parms), failLabel != 0);
+
+						vis.visitInsn(opcode, failLabel, in, out, bif);
+						break;
+					}
+
 					case test:
 						accept_2_test(vis, insn, insn_idx);
 						break;
 
 					case K_return:
 						vis.visitInsn(opcode);
 						break;
+
 						
+					case allocate_zero: {
+						int depth = type_map.stacksize;
+						int count = insn.elm(2).asInt();
+						Arg[] ys = new Arg[count];
+						for (int i = 0; i < count; i++) {
+							ys[i] = new Arg(Arg.Kind.Y, i);
+						}
+						vis.visitInsn(opcode, (Arg[]) ys);
+						break;
+
+					}
+
 					case test_heap:
 						break;
-						
+
 					case fclearerror:
 					case fcheckerror:
 						break;
-						
+
+					case call_ext_last:
 					case call_ext_only:
+						do_call(vis, insn_idx, insn, true, true);
+						break;
+
+					case call_ext:
+						do_call(vis, insn_idx, insn, false, true);
+						break;
+
+					case call:
+						do_call(vis, insn_idx, insn, false, false);
+						break;
+
+					case call_last:
+					case call_only:
+						do_call(vis, insn_idx, insn, true, false);
+						break;
+
+					case apply_last:
+					case apply: {
+						Arg[] args = new Arg[2+insn.elm(2).asInt()];
+						for (int i = 0; i < args.length; i++) {
+							args[i] = new Arg(Arg.Kind.X, i, map[insn_idx].getx(i));
+						}
+						vis.visitInsn(opcode, args);
+						break;
+						
+					}
+						
+					case make_fun2:
+					{
+						ExtFunc efun = new ExtFunc(insn.elm(2).testTuple());
+						int numfree = insn.elm(5).asInt();
+						Arg[] free = new Arg[numfree];
+						for (int i = 0; i < numfree; i++) { free[i] = new Arg(Arg.Kind.X, i, map[insn_idx].getx(i)); }
+						vis.visitInsn(opcode, efun, free);
+						break;
+					}
+						
+					case init:
+						vis.visitInsn(opcode, decode_arg(insn_idx, insn.elm(2)));
+						break;
+						
+					case put_list:
+					{
+						Arg[] in = new Arg[] { decode_arg(insn_idx, insn.elm(2)), decode_arg(insn_idx, insn.elm(3)) };
+						Arg out = decode_out_arg(insn_idx, insn.elm(4));
+						
+						vis.visitInsn(opcode, in, out);
+						break;
+					}
+					
+					case put_tuple:
+					{
+						
+						int arity = insn.elm(2).asInt();
+						Type tupleType = getTupleType(arity);
+						tuple_reg = new Arg (decode_out_arg(insn_idx, insn.elm(3)), tupleType);
+						vis.visitInsn(opcode, arity, tuple_reg);
+						tuple_pos = 1;
+						break;
+					}
+						
+					case put: 
+					{
+						Arg val = decode_arg(insn_idx, insn.elm(2));
+						vis.visitInsn(opcode, val, tuple_reg, tuple_pos++);
+						break;
+					}
+
+					case set_tuple_element: {
+						Arg in = decode_arg(insn_idx, insn.elm(2));
+						Arg out = decode_arg(insn_idx, insn.elm(3));
+						int idx = insn.elm(4).asInt();
+
+						vis.visitInsn(opcode, in, out, idx);
+						
+						break;
+					}
+					
+
+					case allocate_heap:
+					case allocate:
+					case deallocate:
 					{
-						boolean is_tail = true;
-						boolean is_external = true;
-						int arg_count = insn.nth(2).asInt();
-						Arg[] args = new Arg[arg_count];
-						for (int i = 0; i < arg_count; i++) {
-							args[i] = new Arg(Kind.X, i, this.map[insn_idx].getx(i));
+						// need to zero out refs?
+						break;
+					}
+					
+					case select_tuple_arity: {
+						int failLabel = decode_labelref(insn.elm(3));
+						Arg in = decode_arg(insn_idx, insn.elm(2));
+
+						
+						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
+						int len = cases.length()/2;
+						
+						int[] arities = new int[len];
+						int[] targets = new int[len];
+
+						int idx = 0;
+						
+						while (cases != ESeq.NIL) {
+							arities[idx] = cases.head().asInt();
+							EObject target = cases.tail().head();
+							targets[idx] = decode_labelref(target);
+
+							cases = cases.tail().tail();
+							idx += 1;
 						}
-						ETuple ft = insn.nth(3).asTuple();
-						if (ft.nth(1) != EXTFUNC_ATOM) throw new Error();
-						ExtFunc fun = new ExtFunc(ft.nth(2).asAtom(), ft.nth(3).asAtom(), ft.nth(4).asInt());
-						vis.visitCall(fun, args, is_tail, is_external);
+						
+						vis.visitSelectTuple(in, failLabel, arities, targets);
+						
+						break;
 					}
+
+					case select_val: {
+						Arg in = decode_arg(insn_idx, insn.elm(2));
+						int failLabel = decode_labelref(insn.elm(3));
+						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
+						int len = cases.length()/2;
+						
+						Arg[] values = new Arg[len];
+						int[] targets = new int[len];
+
+						int idx = 0;
+						
+						while (cases != ESeq.NIL) {
+							values[idx] = decode_value (cases.head());
+							EObject target = cases.tail().head();
+							targets[idx] = decode_labelref(target);
+
+							cases = cases.tail().tail();
+							idx += 1;
+						}
+						
+						vis.visitSelectValue(in, failLabel, values, targets);
+						
+						break;
+					}
+
+
+					
+					case get_tuple_element: {
+						
+						Arg in = decode_arg(insn_idx, insn.elm(2));
+						int idx = insn.elm(3).asInt();
+						Arg out = decode_out_arg(insn_idx, insn.elm(4));
+
+						vis.visitInsn(opcode, in, out, idx);
+						
+						break;
+					}
+					
+					case jump:
+						vis.visitJump(decode_labelref(insn.elm(2)));
+						break;
+						
+					case trim:
+						break;
+					
+					case get_list:
+						vis.visitInsn(opcode, new Arg[] { decode_arg(insn_idx, insn.elm(2)), 
+								decode_out_arg(insn_idx, insn.elm(3)), 
+								decode_out_arg(insn_idx, insn.elm(4))
+								});
+						break;
+						
+					case badmatch:
+					case case_end:
+						vis.visitInsn(opcode, decode_arg(insn_idx, insn.elm(2)));
 						break;
 						
+					case if_end:
+						vis.visitInsn(opcode);
+						break;
+						
+					case send: {
+						vis.visitInsn(opcode, new Arg[] { new Arg(Arg.Kind.X, 0), new Arg(Arg.Kind.X, 1) });
+						break;
+					}
+						
 					default:
 						throw new Error("unhandled insn: " + insn);
 					}
 
 				}
 			}
 
+			private void do_call(BlockVisitor2 vis, int insn_idx, ETuple insn,
+					boolean is_tail, boolean is_external) throws Error {
+				int arg_count = insn.elm(2).asInt();
+				Arg[] args = new Arg[arg_count];
+				for (int i = 0; i < arg_count; i++) {
+					args[i] = new Arg(Kind.X, i, this.map[insn_idx].getx(i));
+				}
+				
+				ETuple ft = insn.elm(3).testTuple();
+				ExtFunc fun;
+				if (ft.elm(1) != EXTFUNC_ATOM)
+					fun = new ExtFunc(ft.elm(1).testAtom(), ft.elm(2)
+							.testAtom(), ft.elm(3).asInt());
+				else
+					fun = new ExtFunc(ft.elm(2).testAtom(), ft.elm(3)
+						.testAtom(), ft.elm(4).asInt());
+				vis.visitCall(fun, args, is_tail, is_external);
+			}
+
 			private void accept_2_test(BlockVisitor2 vis, ETuple insn,
 					int insn_idx) {
 
-				int failLabel = decode_labelref(insn.nth(3));
+				int failLabel = decode_labelref(insn.elm(3));
 
-				Arg[] args = decode_args(insn_idx, insn.nth(4).asSeq()
-						.toArray());
+				EObject[] argExprs = insn.elm(4).testSeq().toArray();
+				Arg[] args = decode_args(insn_idx, argExprs);
 
-				BeamOpcode test = BeamOpcode.get(insn.nth(2).asAtom());
+				BeamOpcode test = BeamOpcode.get(insn.elm(2).testAtom());
 				switch (test) {
+				case is_boolean:
+				case is_atom:
+					vis.visitTest(test, failLabel, args[0], EATOM_TYPE);
+					break;
+
+				case is_integer:
+					vis.visitTest(test, failLabel, args[0], EINTEGER_TYPE);
+					break;
+
 				case is_list:
 					vis.visitTest(test, failLabel, args[0], ECONS_TYPE);
 					break;
@@ -481,17 +709,33 @@ private void accept_2_test(BlockVisitor2 vis, ETuple insn,
 					vis.visitTest(test, failLabel, args[0], ESEQ_TYPE);
 					break;
 
+				case is_tuple:
+					vis.visitTest(test, failLabel, args[0], ETUPLE_TYPE);
+					break;
+
 				case is_nil:
 					vis.visitTest(test, failLabel, args[0], ENIL_TYPE);
 					break;
 
+				case is_lt:
+				case is_ge:
+				case is_eq_exact:
+				case is_ne_exact:
+				case is_ne:
 				case is_eq:
-					vis.visitTest(test, failLabel, args, (Arg)null, Type.VOID_TYPE);
+					vis.visitTest(test, failLabel, args, (Arg) null,
+							Type.VOID_TYPE);
+					break;
+
+				case test_arity:
+					int arity = argExprs[1].asInt();
+					vis.visitTest(test, failLabel, args[0], arity, getTupleType(arity));
 					break;
 					
+					
 				default:
 					throw new Error("unhandled test: " + insn + " at index "
-							+ insn_idx);
+							+ insn_idx + " // " + test + ":" + test.ordinal());
 				}
 
 			}
@@ -530,11 +774,11 @@ private Arg decode_arg(int insn_idx, EObject src) {
 						int freg = tup.elem2.asInt();
 						return new Arg(Arg.Kind.F, freg, Type.DOUBLE_TYPE);
 					} else if (tup.elem1 == ATOM_ATOM) {
-						return new Arg(tup.elem2);
+						return new Arg(tup.elem2, EATOM_TYPE);
 					} else if (tup.elem1 == LITERAL_ATOM) {
 						return new Arg(tup.elem2);
 					} else if (tup.elem1 == INTEGER_ATOM) {
-						if (tup.elem2.asInteger() != null) {
+						if (tup.elem2.testInteger() != null) {
 							return new Arg(tup.elem2, Type.INT_TYPE);
 						} else {
 							return new Arg(tup.elem2);
@@ -544,14 +788,48 @@ private Arg decode_arg(int insn_idx, EObject src) {
 					}
 
 				} else if (src == NIL_ATOM) {
-					return new Arg(src);
+					return new Arg(ENil.NIL, ENIL_TYPE);
 
 				}
 
 				return null;
 
 			}
 
+			/**
+			 * @param insnIdx
+			 * @param eObject
+			 * @return
+			 */
+			private Arg decode_value(EObject src) {
+
+				if (src instanceof ETuple2) {
+					ETuple2 tup = (ETuple2) src;
+					if (tup.elem1 == ATOM_ATOM) {
+						return new Arg(tup.elem2, EATOM_TYPE);
+					} else if (tup.elem1 == LITERAL_ATOM) {
+						return new Arg(tup.elem2);
+					} else if (tup.elem1 == INTEGER_ATOM) {
+						if (tup.elem2.testInteger() != null) {
+							return new Arg(tup.elem2, Type.INT_TYPE);
+						} else {
+							return new Arg(tup.elem2);
+						}
+					} else if (tup.elem1 == FLOAT_ATOM) {
+						return new Arg(tup.elem2, Type.DOUBLE_TYPE);
+					}
+
+				} else if (src == NIL_ATOM) {
+					return new Arg(ENil.NIL, ENIL_TYPE);
+
+				}
+
+				throw new Error("unknown value");
+
+			}
+
+
+			
 			private Arg decode_out_arg(int insn_idx, EObject src) {
 				TypeMap current = this.map[insn_idx];
 
@@ -566,7 +844,7 @@ private Arg decode_out_arg(int insn_idx, EObject src) {
 					} else if (tup.elem1 == FR_ATOM) {
 						int freg = tup.elem2.asInt();
 						return new Arg(Arg.Kind.F, freg);
-					} 
+					}
 				}
 
 				throw new Error();
@@ -578,8 +856,10 @@ private Arg decode_out_arg(int insn_idx, EObject src) {
 			 * @return
 			 */
 			private int decode_labelref(EObject f_tup) {
-				assert (f_tup.asTuple().nth(1) == F_ATOM);
-				return f_tup.asTuple().nth(2).asInt();
+				if (f_tup == NOFAIL_ATOM)
+					return 0;
+				assert (f_tup.testTuple().elm(1) == F_ATOM);
+				return f_tup.testTuple().elm(2).asInt();
 			}
 
 			public boolean isDeadCode() {
@@ -622,7 +902,7 @@ public void analyze0() {
 
 					map[insn_idx] = current;
 					ETuple insn = insns.get(insn_idx);
-					BeamOpcode code = BeamOpcode.get(insn.nth(1).asAtom());
+					BeamOpcode code = BeamOpcode.get(insn.elm(1).testAtom());
 					last_opcode = code;
 					/*
 					 * System.out.println(name + "(" + bb_label + "):" + i +
@@ -631,8 +911,8 @@ public void analyze0() {
 					switch (code) {
 					case fmove:
 					case move: {
-						EObject src = insn.nth(2);
-						EObject dst = insn.nth(3);
+						EObject src = insn.elm(2);
+						EObject dst = insn.elm(3);
 
 						Type srcType = getType(current, src);
 
@@ -654,7 +934,7 @@ public void analyze0() {
 					}
 
 					case jump: {
-						current = branch(current, insn.nth(2), insn_idx);
+						current = branch(current, insn.elm(2), insn_idx);
 						continue next_insn;
 
 					}
@@ -667,15 +947,15 @@ public void analyze0() {
 
 					case arithfbif: {
 						System.err.println(insn);
-						EAtom name = insn.nth(2).asAtom();
-						ESeq parms = insn.nth(4).asSeq();
+						EAtom name = insn.elm(2).testAtom();
+						ESeq parms = insn.elm(4).testSeq();
 
 						checkArgs(current, parms, insn);
 
 						Type type = getBifResult(name.getName(), parmTypes(
 								current, parms), false);
 
-						current = setType(current, insn.nth(5), type);
+						current = setType(current, insn.elm(5), type);
 
 						continue next_insn;
 					}
@@ -684,40 +964,40 @@ public void analyze0() {
 						// {gc_bif,BifName,F,Live,[A1,A2?],Reg};
 
 						boolean is_guard = false;
-						if (insn.nth(3).asTuple().nth(2).asInt() != 0) {
+						if (insn.elm(3).testTuple().elm(2).asInt() != 0) {
 							is_guard = true;
 						}
 
 						// System.err.println(insn);
-						current = branch(current, insn.nth(3), insn_idx);
+						current = branch(current, insn.elm(3), insn_idx);
 
-						EAtom name = insn.nth(2).asAtom();
-						ESeq parms = insn.nth(5).asSeq();
+						EAtom name = insn.elm(2).testAtom();
+						ESeq parms = insn.elm(5).testSeq();
 
 						checkArgs(current, parms, insn);
 
 						Type type = getBifResult(name.getName(), parmTypes(
 								current, parms), is_guard);
 
-						current = setType(current, insn.nth(6), type);
+						current = setType(current, insn.elm(6), type);
 
 						// dump();
 						continue next_insn;
 					}
 
 					case bif: {
 						// System.err.println(insn);
-						current = branch(current, insn.nth(3), insn_idx);
+						current = branch(current, insn.elm(3), insn_idx);
 
-						EAtom name = insn.nth(2).asAtom();
-						ESeq parms = insn.nth(4).asSeq();
+						EAtom name = insn.elm(2).testAtom();
+						ESeq parms = insn.elm(4).testSeq();
 
 						checkArgs(current, parms, insn);
 
 						Type type = getBifResult(name.getName(), parmTypes(
 								current, parms), false);
 
-						current = setType(current, insn.nth(5), type);
+						current = setType(current, insn.elm(5), type);
 
 						continue next_insn;
 					}
@@ -736,36 +1016,36 @@ public void analyze0() {
 
 					case fconv: {
 						// unbox and convert to DOUBLE
-						getType(current, insn.nth(2));
-						current = setType(current, insn.nth(3),
+						getType(current, insn.elm(2));
+						current = setType(current, insn.elm(3),
 								Type.DOUBLE_TYPE);
 						continue next_insn;
 					}
 
 					case init: {
-						current = setType(current, insn.nth(2), null);
+						current = setType(current, insn.elm(2), null);
 						continue next_insn;
 					}
 
 					case set_tuple_element: {
-						getType(current, insn.nth(2));
-						getType(current, insn.nth(3));
+						getType(current, insn.elm(2));
+						getType(current, insn.elm(3));
 						continue next_insn;
 					}
 
 					case get_tuple_element: {
-						EObject src = insn.nth(2);
-						int idx = insn.nth(3).asInt();
-						EObject dst = insn.nth(4);
+						EObject src = insn.elm(2);
+						int idx = insn.elm(3).asInt();
+						EObject dst = insn.elm(4);
 						getType(current, src);
 						current = setType(current, dst, EOBJECT_TYPE);
 						continue next_insn;
 					}
 
 					case get_list: {
-						EObject from = insn.nth(2);
-						EObject head_into = insn.nth(3);
-						EObject tail_into = insn.nth(4);
+						EObject from = insn.elm(2);
+						EObject head_into = insn.elm(3);
+						EObject tail_into = insn.elm(4);
 
 						current = setType(current, head_into, EOBJECT_TYPE);
 
@@ -781,35 +1061,35 @@ public void analyze0() {
 
 					case put_list: {
 
-						Type head_type = getType(current, insn.nth(2));
-						Type tail_type = getType(current, insn.nth(3));
+						Type head_type = getType(current, insn.elm(2));
+						Type tail_type = getType(current, insn.elm(3));
 
 						if (tail_type == null) {
-							throw new Error("value: " + insn.nth(3)
+							throw new Error("value: " + insn.elm(3)
 									+ " has no type");
 						}
 
 						if (tail_type.equals(ENIL_TYPE)
 								|| tail_type.equals(ESEQ_TYPE)
 								|| tail_type.equals(ELIST_TYPE)) {
-							current = setType(current, insn.nth(4), ELIST_TYPE);
+							current = setType(current, insn.elm(4), ELIST_TYPE);
 						} else {
-							current = setType(current, insn.nth(4), ECONS_TYPE);
+							current = setType(current, insn.elm(4), ECONS_TYPE);
 						}
 						continue next_insn;
 					}
 
 					case put_tuple: {
-						int arity = insn.nth(2).asInt();
-						ETuple reg = insn.nth(3).asTuple();
+						int arity = insn.elm(2).asInt();
+						ETuple reg = insn.elm(3).testTuple();
 
 						current = setType(current, reg, getTupleType(arity));
 						continue next_insn;
 					}
 
 					case K_try:
-						current = setType(current, insn.nth(2), EOBJECT_TYPE);
-						current = branch(current, insn.nth(3), insn_idx);
+						current = setType(current, insn.elm(2), EOBJECT_TYPE);
+						current = branch(current, insn.elm(3), insn_idx);
 						continue next_insn;
 
 					case try_case_end:
@@ -818,39 +1098,39 @@ public void analyze0() {
 						continue next_insn;
 
 					case try_case:
-						getType(current, insn.nth(2));
+						getType(current, insn.elm(2));
 						current = current.setx(0, EATOM_TYPE); // reason
 						current = current.setx(1, EOBJECT_TYPE); // value
 						current = current.setx(2, EOBJECT_TYPE); // trace
 						continue next_insn;
 
 					case raise:
 						boolean is_guard = false;
-						if (insn.nth(2).asTuple().nth(2).asInt() != 0) {
+						if (insn.elm(2).testTuple().elm(2).asInt() != 0) {
 							is_guard = true;
 						}
 
-						checkArgs(current, insn.nth(3), insn);
-						current = setType(current, insn.nth(4), EOBJECT_TYPE);
+						checkArgs(current, insn.elm(3), insn);
+						current = setType(current, insn.elm(4), EOBJECT_TYPE);
 
 						continue next_insn;
 
 					case K_catch:
-						current = branch(current, insn.nth(3), insn_idx);
+						current = branch(current, insn.elm(3), insn_idx);
 						continue next_insn;
 
 					case catch_end:
 						continue next_insn;
 
 					case make_fun2: {
-						current.touchx(0, insn.nth(5).asInt());
+						current.touchx(0, insn.elm(5).asInt());
 						current = current.setx(0, EFUN_TYPE);
 						continue next_insn;
 					}
 
 					case loop_rec: {
-						current = branch(current, insn.nth(2), insn_idx);
-						current = setType(current, insn.nth(3), EOBJECT_TYPE);
+						current = branch(current, insn.elm(2), insn_idx);
+						current = setType(current, insn.elm(3), EOBJECT_TYPE);
 						continue next_insn;
 					}
 
@@ -866,16 +1146,16 @@ public void analyze0() {
 					}
 
 					case wait_timeout: {
-						Type timeout_type = getType(current, insn.nth(3));
+						Type timeout_type = getType(current, insn.elm(3));
 					}
 					case wait: {
-						current = branch(current, insn.nth(2), insn_idx);
+						current = branch(current, insn.elm(2), insn_idx);
 						continue next_insn;
 					}
 
 					case deallocate:
 					case trim: {
-						int howmuch = insn.nth(2).asInt();
+						int howmuch = insn.elm(2).asInt();
 						current = current.trim_y(howmuch);
 						continue next_insn;
 					}
@@ -887,7 +1167,7 @@ public void analyze0() {
 
 					case allocate_zero:
 					case allocate_heap_zero: {
-						int slots = insn.nth(2).asInt();
+						int slots = insn.elm(2).asInt();
 						current = current.alloc_y(slots);
 						for (int slot = 0; slot < slots; slot++) {
 							current = current.sety(slot, ENIL_TYPE);
@@ -897,7 +1177,7 @@ public void analyze0() {
 
 					case allocate:
 					case allocate_heap: {
-						current = current.alloc_y(insn.nth(2).asInt());
+						current = current.alloc_y(insn.elm(2).asInt());
 						continue next_insn;
 					}
 
@@ -906,20 +1186,22 @@ public void analyze0() {
 						continue next_insn;
 
 					case put:
-						getType(current, insn.nth(2));
+						getType(current, insn.elm(2));
 						continue next_insn;
 
 					case select_tuple_arity: {
-						current = branch(current, insn.nth(3), insn_idx);
+						current = branch(current, insn.elm(3), insn_idx);
 
 						// touch select reg
-						getType(current, insn.nth(2));
+						getType(current, insn.elm(2));
 
-						ESeq cases = insn.nth(4).asTuple().nth(2).asSeq();
-						while (cases != ESeq.EMPTY) {
+						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
+						while (cases != ESeq.NIL) {
 							EObject value = cases.head();
 							EObject target = cases.tail().head();
 
+							current = setType(current, insn.elm(2), getTupleType(value.asInt()));
+							
 							current = branch(current, target, insn_idx);
 
 							cases = cases.tail().tail();
@@ -929,13 +1211,13 @@ public void analyze0() {
 					}
 
 					case select_val: {
-						current = branch(current, insn.nth(3), insn_idx);
+						current = branch(current, insn.elm(3), insn_idx);
 
 						// touch select reg
-						getType(current, insn.nth(2));
+						getType(current, insn.elm(2));
 
-						ESeq cases = insn.nth(4).asTuple().nth(2).asSeq();
-						while (cases != ESeq.EMPTY) {
+						ESeq cases = insn.elm(4).testTuple().elm(2).testSeq();
+						while (cases != ESeq.NIL) {
 							EObject value = cases.head();
 							EObject target = cases.tail().head();
 
@@ -952,7 +1234,7 @@ public void analyze0() {
 					case apply:
 					case call:
 					case call_ext: {
-						int argCount = insn.nth(2).asInt();
+						int argCount = insn.elm(2).asInt();
 						current.touchx(0, argCount);
 						current = current.setx(0, EOBJECT_TYPE);
 						continue next_insn;
@@ -968,7 +1250,7 @@ public void analyze0() {
 					case call_ext_last:
 					case call_ext_only:
 						is_tail_recursive = true;
-						int argCount = insn.nth(2).asInt();
+						int argCount = insn.elm(2).asInt();
 						current.touchx(0, argCount);
 						continue next_insn;
 
@@ -981,7 +1263,7 @@ public void analyze0() {
 						continue next_insn;
 
 					case bs_context_to_binary: {
-						Type ctx = getType(current, insn.nth(2));
+						Type ctx = getType(current, insn.elm(2));
 						current = current.setx(0, EBINARY_TYPE);
 						continue next_insn;
 					}
@@ -1038,13 +1320,13 @@ boolean is_term(BeamOpcode code) {
 			private int sizeof(TypeMap current, EObject cell) {
 
 				ETuple at;
-				if ((at = cell.asTuple()) != null) {
+				if ((at = cell.testTuple()) != null) {
 					if (at.arity() == 2) {
-						if (at.nth(1) == X_ATOM)
+						if (at.elm(1) == X_ATOM)
 							return 32;
-						if (at.nth(1) == Y_ATOM)
+						if (at.elm(1) == Y_ATOM)
 							return 32;
-						if (at.nth(1) == FR_ATOM)
+						if (at.elm(1) == FR_ATOM)
 							return 64;
 					}
 				}
@@ -1065,7 +1347,7 @@ private Type getBifResult(String name, Type[] parmTypes,
 			private Type[] parmTypes(TypeMap current, ESeq args) {
 				ArrayList<Type> res = new ArrayList<Type>();
 
-				while (args != ESeq.EMPTY) {
+				while (args != ESeq.NIL) {
 					EObject arg = args.head();
 					res.add(getType(current, arg));
 					args = args.tail();
@@ -1075,9 +1357,9 @@ private Type[] parmTypes(TypeMap current, ESeq args) {
 			}
 
 			private void checkArgs(TypeMap current, EObject eTerm, ETuple insn) {
-				ESeq args = eTerm.asSeq();
+				ESeq args = eTerm.testSeq();
 
-				while (args != ESeq.EMPTY) {
+				while (args != ESeq.NIL) {
 					EObject arg = args.head();
 
 					if (getType(current, arg) == null) {
@@ -1091,91 +1373,91 @@ private void checkArgs(TypeMap current, EObject eTerm, ETuple insn) {
 			private TypeMap analyze_test(TypeMap current, ETuple insn,
 					int insn_idx) {
 
-				current = branch(current, insn.nth(3), insn_idx);
+				current = branch(current, insn.elm(3), insn_idx);
 
-				EObject[] args = insn.nth(4).asSeq().toArray();
+				EObject[] args = insn.elm(4).testSeq().toArray();
 				EObject arg1 = args[0];
 				EObject arg2 = (args.length > 1) ? args[1] : null;
 
-				BeamOpcode test = BeamOpcode.get(insn.nth(2).asAtom());
+				BeamOpcode test = BeamOpcode.get(insn.elm(2).testAtom());
 				switch (test) {
 				case is_nil: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), ENIL_TYPE);
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), ENIL_TYPE);
 				}
 
 				case is_list:
 				case is_nonempty_list: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), ECONS_TYPE);
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), ECONS_TYPE);
 				}
 
 				case is_binary: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), EBINARY_TYPE);
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), EBINARY_TYPE);
 				}
 				case is_tuple: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), ETUPLE_TYPE);
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), ETUPLE_TYPE);
 				}
 
 				case test_arity: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), getTupleType(arg2
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), getTupleType(arg2
 							.asInt()));
 				}
 
 				case is_boolean:
 				case is_atom: {
-					checkArgs(current, insn.nth(4), insn);
-					return setType(current, arg1.asTuple(), EATOM_TYPE);
+					checkArgs(current, insn.elm(4), insn);
+					return setType(current, arg1.testTuple(), EATOM_TYPE);
 				}
 
 				case is_integer: {
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return setType(current, arg1, EINTEGER_TYPE);
 				}
 
 				case is_pid: {
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return setType(current, arg1, EPID_TYPE);
 				}
 
 				case is_port: {
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return setType(current, arg1, EPORT_TYPE);
 				}
 
 				case is_float: {
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return setType(current, arg1, EDOUBLE_TYPE);
 				}
 
 				case is_ge:
 				case is_ne:
 				case is_ne_exact:
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return current;
 
 				case is_eq:
 				case is_eq_exact: {
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					Type t1 = getType(current, arg1);
 					Type t2 = getType(current, arg2);
 
 					if (!t1.equals(t2)) {
 						if (isReg(arg1)) {
-							current = setType(current, arg1.asTuple(), t2);
+							current = setType(current, arg1.testTuple(), t2);
 						} else if (isReg(arg2)) {
-							current = setType(current, arg2.asTuple(), t1);
+							current = setType(current, arg2.testTuple(), t1);
 						}
 					}
 
 					return current;
 				}
 
 				case is_lt:
-					checkArgs(current, insn.nth(4), insn);
+					checkArgs(current, insn.elm(4), insn);
 					return current;
 
 				case bs_start_match2:
@@ -1189,9 +1471,9 @@ private TypeMap analyze_test(TypeMap current, ETuple insn,
 					}
 
 					ETuple tup;
-					if ((tup = args[3].asTuple()) != null) {
-						if (tup.nth(1) == INTEGER_ATOM
-								&& tup.nth(2).asInt() <= 32) {
+					if ((tup = args[3].testTuple()) != null) {
+						if (tup.elm(1) == INTEGER_ATOM
+								&& tup.elm(2).asInt() <= 32) {
 							current = setType(current, args[5], Type.INT_TYPE);
 							return current;
 						}
@@ -1246,11 +1528,11 @@ private void check(TypeMap current, EObject src) {
 			private TypeMap branch(TypeMap current, EObject nth, int idx) {
 				if (nth != NOFAIL_ATOM) {
 
-					ETuple tuple = nth.asTuple();
-					if (tuple.nth(1) != F_ATOM)
+					ETuple tuple = nth.testTuple();
+					if (tuple.elm(1) != F_ATOM)
 						throw new Error("not a branch target: " + nth);
 
-					int target = tuple.nth(2).asInt();
+					int target = tuple.elm(2).asInt();
 					if (target != 0) {
 						get_lb(target, false).merge_from(current);
 					}
@@ -1265,9 +1547,9 @@ private Type getTupleType(int arity) {
 			}
 
 			private boolean isReg(EObject arg2) {
-				ETuple et = arg2.asTuple();
-				return (et != null && et.nth(1) == X_ATOM
-						|| et.nth(1) == Y_ATOM || et.nth(1) == FR_ATOM);
+				ETuple et = arg2.testTuple();
+				return (et != null && et.elm(1) == X_ATOM
+						|| et.elm(1) == Y_ATOM || et.elm(1) == FR_ATOM);
 			}
 
 			public void merge_from(TypeMap typeMap) {
@@ -1304,10 +1586,10 @@ public void visitInsn(BeamOpcode opcode, ETuple insn) {
 			}
 
 			private TypeMap setType(TypeMap current, EObject dd, Type type) {
-				ETuple dst = dd.asTuple();
+				ETuple dst = dd.testTuple();
 
-				EObject key = dst.nth(1);
-				EObject value = dst.nth(2);
+				EObject key = dst.elm(1);
+				EObject value = dst.elm(2);
 				if (key == X_ATOM) {
 					current = current.setx(value.asInt(), type);
 				} else if (key == Y_ATOM) {
@@ -1385,7 +1667,7 @@ public BInsn(ETuple insn, TypeMap current) {
 
 				@Override
 				public BeamOpcode opcode() {
-					return BeamOpcode.get(insn.nth(1).asAtom());
+					return BeamOpcode.get(insn.elm(1).testAtom());
 				}
 
 				@Override
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fbeam%2Fanalysis%2FBeamTypeAnalysis.java
de39e7b609d9037b01a334371d2f3bdef61446d5
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2FBEAMFile.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fjbeam%2FBEAMFile.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/jbeam/BEAMFile.java
			return sym2enum((EAtom) stmt.elm(1));
		Object nth = vec.elm(i);
		BeamFileTag opcode = sym2enum((EAtom) stmt.elm(1));
			return (EInteger) stmt.elm(2);
			return (EAtom) stmt.elm(2);
			ETuple vec = (ETuple) stmt.elm(3);
			EAtom mod = (EAtom) vec.elm(1);
			EAtom fun = (EAtom) vec.elm(2);
			EInteger ari = (EInteger) vec.elm(3);
			ETuple vec = (ETuple) stmt.elm(3);
			EAtom mod = (EAtom) vec.elm(1);
			EAtom fun = (EAtom) vec.elm(2);
			EInteger ari = (EInteger) vec.elm(3);
		ESeq v = (ESeq) stmt.elm(i);
		while (v != ECons.NIL) {
		return (EList) stmt.elm(i);
		return (EString) stmt.elm(i);
		return (EAtom) stmt.elm(i);
		return ((EInteger) stmt.elm(i)).intValue();
		if (value != ECons.NIL && value instanceof ECons) {
				registerConst(t.elm(i));
			return sym2enum((EAtom) stmt.nth(1));
		Object nth = vec.nth(i);
		BeamFileTag opcode = sym2enum((EAtom) stmt.nth(1));
			return (EInteger) stmt.nth(2);
			return (EAtom) stmt.nth(2);
			ETuple vec = (ETuple) stmt.nth(3);
			EAtom mod = (EAtom) vec.nth(1);
			EAtom fun = (EAtom) vec.nth(2);
			EInteger ari = (EInteger) vec.nth(3);
			ETuple vec = (ETuple) stmt.nth(3);
			EAtom mod = (EAtom) vec.nth(1);
			EAtom fun = (EAtom) vec.nth(2);
			EInteger ari = (EInteger) vec.nth(3);
		ESeq v = (ESeq) stmt.nth(i);
		while (v != ECons.EMPTY) {
		return (EList) stmt.nth(i);
		return (EString) stmt.nth(i);
		return (EAtom) stmt.nth(i);
		return ((EInteger) stmt.nth(i)).intValue();
		if (value != ECons.EMPTY && value instanceof ECons) {
				registerConst(t.nth(i));
@@ -247,7 +247,7 @@ private BeamFileTag lookahead(List<ETerm> vec, int i) {
 			return sym2enum((EAtom) nth);
 		} else {
 			ETuple stmt = (ETuple) nth;
-			return sym2enum((EAtom) stmt.nth(1));
+			return sym2enum((EAtom) stmt.elm(1));
 		}
 	}
 
@@ -257,7 +257,7 @@ private Object decode(List<ETerm> vec, int i) throws Exception {
 	}
 
 	private Object decode(ETuple vec, int i) throws Exception {
-		Object nth = vec.nth(i);
+		Object nth = vec.elm(i);
 		return decode_one(nth);
 	}
 
@@ -277,7 +277,7 @@ private Object decode_one(Object nth) throws Exception {
 
 	private Object decode_record(ETuple stmt) throws Exception {
 
-		BeamFileTag opcode = sym2enum((EAtom) stmt.nth(1));
+		BeamFileTag opcode = sym2enum((EAtom) stmt.elm(1));
 		switch (opcode) {
 
 		case file:
@@ -313,10 +313,10 @@ private Object decode_record(ETuple stmt) throws Exception {
 			return (Register) new RegisterY(integer(stmt, 2));
 
 		case integer:
-			return (EInteger) stmt.nth(2);
+			return (EInteger) stmt.elm(2);
 
 		case atom:
-			return (EAtom) stmt.nth(2);
+			return (EAtom) stmt.elm(2);
 
 		case test:
 			return (Insn) new Test(atom(stmt, 2), (Label) decode(stmt, 3),
@@ -340,19 +340,19 @@ private Object decode_record(ETuple stmt) throws Exception {
 
 		case call: {
 			int nargs = integer(stmt, 2);
-			ETuple vec = (ETuple) stmt.nth(3);
-			EAtom mod = (EAtom) vec.nth(1);
-			EAtom fun = (EAtom) vec.nth(2);
-			EInteger ari = (EInteger) vec.nth(3);
+			ETuple vec = (ETuple) stmt.elm(3);
+			EAtom mod = (EAtom) vec.elm(1);
+			EAtom fun = (EAtom) vec.elm(2);
+			EInteger ari = (EInteger) vec.elm(3);
 			return new Call(nargs, mod, fun, ari.intValue(), false);
 		}
 
 		case call_only: {
 			int nargs = integer(stmt, 2);
-			ETuple vec = (ETuple) stmt.nth(3);
-			EAtom mod = (EAtom) vec.nth(1);
-			EAtom fun = (EAtom) vec.nth(2);
-			EInteger ari = (EInteger) vec.nth(3);
+			ETuple vec = (ETuple) stmt.elm(3);
+			EAtom mod = (EAtom) vec.elm(1);
+			EAtom fun = (EAtom) vec.elm(2);
+			EInteger ari = (EInteger) vec.elm(3);
 			return new Call(nargs, mod, fun, ari.intValue(), true);
 		}
 
@@ -385,35 +385,35 @@ private Object decode_record(ETuple stmt) throws Exception {
 	}
 
 	private Object[] decode_list(ETuple stmt, int i) throws Exception {
-		ESeq v = (ESeq) stmt.nth(i);
+		ESeq v = (ESeq) stmt.elm(i);
 
 		Object[] result = new Object[v.count()];
 		int pos = 0;
-		while (v != ECons.EMPTY) {
+		while (v != ECons.NIL) {
 			result[pos++] = decode_record((ETuple) v.head());
 			v = v.tail();
 		}
 		return result;
 	}
 
 	private EList list(ETuple stmt, int i) {
-		return (EList) stmt.nth(i);
+		return (EList) stmt.elm(i);
 	}
 
 	private EString string(ETuple stmt, int i) {
-		return (EString) stmt.nth(i);
+		return (EString) stmt.elm(i);
 	}
 
 	private EAtom atom(ETuple stmt, int i) {
-		return (EAtom) stmt.nth(i);
+		return (EAtom) stmt.elm(i);
 	}
 
 	private Register reg(ETuple stmt, int i) throws Exception {
 		return (Register) decode(stmt, i);
 	}
 
 	private int integer(ETuple stmt, int i) {
-		return ((EInteger) stmt.nth(i)).intValue();
+		return ((EInteger) stmt.elm(i)).intValue();
 	}
 
 	BeamFileTag sym2enum(EAtom sym) {
@@ -452,13 +452,13 @@ public String registerConst(ETerm value) {
 			consts.put(value, str);
 		}
 		
-		if (value != ECons.EMPTY && value instanceof ECons) {
+		if (value != ECons.NIL && value instanceof ECons) {
 			registerConst(((ECons)value).head());
 			registerConst(((ECons)value).tail());
 		} else if (value instanceof ETuple) {
 			ETuple t = (ETuple) value;
 			for (int i = 1; i <= t.arity(); i++) {
-				registerConst(t.nth(i));
+				registerConst(t.elm(i));
 			}
 		}
 		
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2FBEAMFile.java
b04c5cc2cc5825b6047718f1a969a06292cd04d5
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2Fops%2FGCBif.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fjbeam%2Fops%2FGCBif.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/jbeam/ops/GCBif.java
import erjang.modules.erl_bif;
	private static final Type BIF_TYPE = Type.getType(erl_bif.class);
import erjang.modules.ErlangModule;
	private static final Type BIF_TYPE = Type.getType(ErlangModule.class);
@@ -5,13 +5,13 @@
 
 import erjang.EAtom;
 import erjang.ETerm;
-import erjang.modules.ErlangModule;
+import erjang.modules.erl_bif;
 
 public class GCBif extends Insn {
 
 	private static final Type EXCEPTION_TYPE = Type.getType(Exception.class);
 
-	private static final Type BIF_TYPE = Type.getType(ErlangModule.class);
+	private static final Type BIF_TYPE = Type.getType(erl_bif.class);
 
 	private static final Type ETERM_TYPE = Type.getType(ETerm.class);
 	
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2Fops%2FGCBif.java
6ecba722bec22195cd63421f935fdf3e0b4f1df0
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2Fops%2FTest.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fjbeam%2Fops%2FTest.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/jbeam/ops/Test.java
import erjang.modules.erl_bif;
	private static final Type BIF_TYPE = Type.getType(erl_bif.class);
import erjang.modules.ErlangModule;
	private static final Type BIF_TYPE = Type.getType(ErlangModule.class);
@@ -4,15 +4,15 @@
 import org.objectweb.asm.Type;
 
 import erjang.EAtom;
-import erjang.modules.ErlangModule;
+import erjang.modules.erl_bif;
 
 public class Test extends Insn {
 
 	private final EAtom how;
 	private final Label failto;
 	private final Object[] args;
 
-	private static final Type BIF_TYPE = Type.getType(ErlangModule.class);
+	private static final Type BIF_TYPE = Type.getType(erl_bif.class);
 	
 	public Test(EAtom how, Label failto, Object[] args) {
 		this.how = how;
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fjbeam%2Fops%2FTest.java
1d6798b3a98f1f8f300ede51d3b19d779622695c
modified
https://github.com/trifork/erjang/blob/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fmodules%2FBinOps.java
https://api.github.com/repos/trifork/erjang/contents/src%2Ferjang%2Fmodules%2FBinOps.java?ref=070f8a4124a580cd7a140029dee655beeae8540b
src/erjang/modules/BinOps.java
		if ((n1=o1.testNumber()) != null) {
			if ((n2=o2.testNumber()) != null) {
		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
		if ((n1=o1.testNumber()) != null) {
			if ((n2=o2.testNumber()) != null) {
		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
		if ((n1=o1.testNumber()) != null) {
			if ((n2=o2.testNumber()) != null) {
		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
		if ((n1=o1.testNumber()) != null) {
			if ((n2=o2.testNumber()) != null) {
		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
		if ((n1=o1.testNumber()) != null) {
			if ((n2=o2.testNumber()) != null) {
		if ((n1=o1.asNumber()) != null) {
			if ((n2=o2.asNumber()) != null) {
		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
		if ((n1=o1.asNumber()) != null) {
			if ((n2=o2.asNumber()) != null) {
		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
		if ((n1=o1.asNumber()) != null) {
			if ((n2=o2.asNumber()) != null) {
		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
		if ((n1=o1.asNumber()) != null) {
			if ((n2=o2.asNumber()) != null) {
		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
		if ((n1=o1.asNumber()) != null) {
			if ((n2=o2.asNumber()) != null) {
@@ -14,8 +14,8 @@ static public ENumber band_guard(EObject o1, EObject o2)
 	{
 		ENumber n1;
 		ENumber n2;
-		if ((n1=o1.asNumber()) != null) {
-			if ((n2=o2.asNumber()) != null) {
+		if ((n1=o1.testNumber()) != null) {
+			if ((n2=o2.testNumber()) != null) {
 				return n1.bitAnd(n2);
 			}
 		}
@@ -28,15 +28,15 @@ static public ENumber band_guard(EObject o1, EObject o2)
 	static public ENumber band(EObject o1, EObject o2)
 	{
 		EInteger i1, i2;
-		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
+		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
 		{
 			return new EInteger(i1.value & i2.value);
 		}
 		
 		ENumber n1;
 		ENumber n2;
-		if ((n1=o1.asNumber()) != null) {
-			if ((n2=o2.asNumber()) != null) {
+		if ((n1=o1.testNumber()) != null) {
+			if ((n2=o2.testNumber()) != null) {
 				return n1.bitAnd(n2);
 			}
 		}
@@ -57,15 +57,15 @@ static public int bor(int n1, int n2)
 	static public ENumber bor(EObject o1, EObject o2)
 	{
 		EInteger i1, i2;
-		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
+		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
 		{
 			return new EInteger(i1.value | i2.value);
 		}
 		
 		ENumber n1;
 		ENumber n2;
-		if ((n1=o1.asNumber()) != null) {
-			if ((n2=o2.asNumber()) != null) {
+		if ((n1=o1.testNumber()) != null) {
+			if ((n2=o2.testNumber()) != null) {
 				return n1.bitOr(n2);
 			}
 		}
@@ -88,15 +88,15 @@ static public int band(int n1, int n2)
 	static public ENumber bsr(EObject o1, EObject o2)
 	{
 		EInteger i1, i2;
-		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
+		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
 		{
 			return new EInteger(i1.value >> i2.value);
 		}
 		
 		ENumber n1;
 		ENumber n2;
-		if ((n1=o1.asNumber()) != null) {
-			if ((n2=o2.asNumber()) != null) {
+		if ((n1=o1.testNumber()) != null) {
+			if ((n2=o2.testNumber()) != null) {
 				return n1.bitShiftRight(n2);
 			}
 		}
@@ -108,15 +108,15 @@ static public ENumber bsr(EObject o1, EObject o2)
 	static public ENumber bsl(EObject o1, EObject o2)
 	{
 		EInteger i1, i2;
-		if ((i1=o1.asInteger()) != null && (i2=o2.asInteger()) != null)
+		if ((i1=o1.testInteger()) != null && (i2=o2.testInteger()) != null)
 		{
 			return new EInteger(i1.value << i2.value);
 		}
 		
 		ENumber n1;
 		ENumber n2;
-		if ((n1=o1.asNumber()) != null) {
-			if ((n2=o2.asNumber()) != null) {
+		if ((n1=o1.testNumber()) != null) {
+			if ((n2=o2.testNumber()) != null) {
 				return n1.bitShiftLeft(n2);
 			}
 		}
https://github.com/trifork/erjang/raw/070f8a4124a580cd7a140029dee655beeae8540b/src%2Ferjang%2Fmodules%2FBinOps.java
261157682d41aac4f152031302faf94a1b62c923
modified
trifork$erjang
return "'" + encode_escapes(value) + "'";
EAtom
EAtom testAtom()
return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;
EAtom
EAtom asAtom()
trifork$erjang
return "'" + encode_escapes(value) + "'";
EAtom
EAtom testAtom()
return "'" + value + "'";
	
	public boolean isAtom(String name)
	{
	
 
	



		
					"intern", "(" + STRING_TYPE.getDescriptor() + ")" + type.getDescriptor());
		
		return type;
EAtom
EAtom asAtom()