Permalink
Browse files

add testsuite, remove ETerm

  • Loading branch information...
1 parent 67e9340 commit a1c318ba767529cde2ce6f0e9a96fb3d0a10879d @krestenkrab krestenkrab committed Nov 20, 2009
View
3 .classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/OtpErlang.jar"/>
<classpathentry kind="lib" path="lib/asm-3.2.jar" sourcepath="lib/src.zip"/>
@@ -9,5 +10,7 @@
<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 combineaccessrules="false" kind="src" path="/clojure"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
View
241 src/main/erl/test1.S
@@ -1,63 +1,240 @@
{module, test1}. %% version = 0
-{exports, [{bar,1},{foo,1},{module_info,0},{module_info,1}]}.
+{exports, [{bar,2},
+ {foo,1},
+ {gen_dec_postponed_decs,2},
+ {module_info,0},
+ {module_info,1}]}.
{attributes, []}.
-{labels, 12}.
+{labels, 26}.
{function, foo, 1, 2}.
{label,1}.
{func_info,{atom,test1},{atom,foo},1}.
{label,2}.
- {gc_bif,'/',{f,3},1,[{x,0},{float,2.0}],{x,1}}.
- {test,is_eq,{f,3},[{x,1},{float,3.3}]}.
- {move,{atom,true},{x,0}}.
+ {make_fun2,{f,25},0,3272456,1}.
return.
+
+
+{function, bar, 2, 4}.
{label,3}.
- {test_heap,{alloc,[{words,0},{floats,1}]},1}.
- {fmove,{float,2.0},{fr,0}}.
- {fconv,{x,0},{fr,1}}.
- fclearerror.
- {bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,1}}.
- {fcheckerror,{f,0}}.
- {fmove,{fr,1},{x,0}}.
+ {func_info,{atom,test1},{atom,bar},2}.
+ {label,4}.
+ {allocate,0,2}.
+ {move,{x,1},{x,2}}.
+ {move,{x,0},{x,1}}.
+ {move,{x,2},{x,0}}.
+ {call_fun,1}.
+ {deallocate,0}.
return.
-{function, bar, 1, 5}.
- {label,4}.
- {func_info,{atom,test1},{atom,bar},1}.
+{function, gen_dec_postponed_decs, 2, 6}.
{label,5}.
- {allocate,2,1}.
- {'catch',{y,1},{f,6}}.
- {move,{x,0},{y,0}}.
- {call_ext,1,{extfunc,foo,bar,1}}.
+ {func_info,{atom,test1},{atom,gen_dec_postponed_decs},2}.
{label,6}.
- {catch_end,{y,1}}.
- {test,is_eq_exact,{f,7},[{x,0},{y,0}]}.
- {move,{atom,true},{x,0}}.
- {deallocate,2}.
- return.
+ {test,is_nonempty_list,{f,5},[{x,1}]}.
+ {get_list,{x,1},{x,2},{x,3}}.
+ {test,is_tuple,{f,5},[{x,2}]}.
+ {test,test_arity,{f,5},[{x,2},6]}.
+ {get_tuple_element,{x,2},1,{x,4}}.
+ {get_tuple_element,{x,2},2,{x,5}}.
+ {get_tuple_element,{x,2},3,{x,6}}.
+ {get_tuple_element,{x,2},5,{x,7}}.
+ {test,is_tuple,{f,5},[{x,4}]}.
+ {test,test_arity,{f,5},[{x,4},2]}.
+ {allocate,7,8}.
+ {get_tuple_element,{x,4},0,{y,1}}.
+ {get_tuple_element,{x,4},1,{y,2}}.
+ {move,{x,0},{y,5}}.
+ {move,{atom,tmpterm},{x,0}}.
+ {move,{x,5},{y,0}}.
+ {move,{x,6},{y,3}}.
+ {move,{x,7},{y,4}}.
+ {move,{x,3},{y,6}}.
+ {call_ext,1,{extfunc,asn1ct_name,new,1}}.
+ {move,{atom,reason},{x,0}}.
+ {call_ext,1,{extfunc,asn1ct_name,new,1}}.
+ {test_heap,5,0}.
+ {put_tuple,4,{x,0}}.
+ {put,{literal,"{"}}.
+ {put,{y,0}}.
+ {put,{literal,", _, _} = "}}.
+ {put,{atom,nl}}.
+ {kill,{y,0}}.
+ {call,1,{f,17}}.
+ {test,is_tuple,{f,7},[{y,4}]}.
+ {test,test_arity,{f,13},[{y,4},2]}.
+ {get_tuple_element,{y,4},0,{x,0}}.
+ {get_tuple_element,{y,4},1,{x,1}}.
+ {test,is_eq_exact,{f,13},[{x,0},{atom,'DEFAULT'}]}.
+ {move,{x,1},{x,0}}.
+ {move,{y,3},{x,1}}.
+ {call,2,{f,19}}.
+ {move,{integer,6},{x,0}}.
+ {jump,{f,10}}.
{label,7}.
- {move,{atom,false},{x,0}}.
- {deallocate,2}.
+ {test,is_atom,{f,13},[{y,4}]}.
+ {select_val,{y,4},
+ {f,13},
+ {list,[{atom,'OPTIONAL'},{f,8},{atom,mandatory},{f,9}]}}.
+ {label,8}.
+ {move,{y,3},{x,1}}.
+ {move,{atom,asn1_NOVALUE},{x,0}}.
+ {call,2,{f,19}}.
+ {move,{integer,6},{x,0}}.
+ {jump,{f,10}}.
+ {label,9}.
+ {move,{integer,0},{x,0}}.
+ {label,10}.
+ {gc_bif,'+',{f,0},1,[{x,0},{integer,3}],{x,1}}.
+ {move,{x,0},{y,0}}.
+ {move,{x,1},{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,18,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,asis}}.
+ {put,{y,1}}.
+ {put_tuple,2,{x,2}}.
+ {put,{atom,asis}}.
+ {put,{y,2}}.
+ {put_tuple,11,{x,3}}.
+ {put,{x,0}}.
+ {put,{literal,"case (catch "}}.
+ {put,{y,5}}.
+ {put,{literal,"("}}.
+ {put,{x,1}}.
+ {put,{literal,", "}}.
+ {put,{y,3}}.
+ {put,{literal,", [], "}}.
+ {put,{x,2}}.
+ {put,{literal,")) of"}}.
+ {put,{atom,nl}}.
+ {kill,{y,1}}.
+ {kill,{y,2}}.
+ {kill,{y,3}}.
+ {move,{x,3},{x,0}}.
+ {call,1,{f,17}}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,6}],{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,6,1}.
+ {put_tuple,5,{x,1}}.
+ {put,{x,0}}.
+ {put,{literal,"{'EXIT', "}}.
+ {put,{literal,{curr,reason}}}.
+ {put,{literal,"} ->"}}.
+ {put,{atom,nl}}.
+ {move,{x,1},{x,0}}.
+ {call,1,{f,17}}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,9}],{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,6,1}.
+ {put_tuple,5,{x,1}}.
+ {put,{x,0}}.
+ {put,{literal,"exit({'Type not compatible with table constraint',"}}.
+ {put,{literal,{curr,reason}}}.
+ {put,{literal,"});"}}.
+ {put,{atom,nl}}.
+ {move,{x,1},{x,0}}.
+ {call,1,{f,17}}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,6}],{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,5,1}.
+ {put_tuple,4,{x,1}}.
+ {put,{x,0}}.
+ {put,{literal,{curr,tmpterm}}}.
+ {put,{literal," ->"}}.
+ {put,{atom,nl}}.
+ {move,{x,1},{x,0}}.
+ {call,1,{f,17}}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,9}],{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,4,1}.
+ {put_tuple,3,{x,1}}.
+ {put,{x,0}}.
+ {put,{literal,{curr,tmpterm}}}.
+ {put,{atom,nl}}.
+ {move,{x,1},{x,0}}.
+ {call,1,{f,17}}.
+ {test,is_eq_exact,{f,11},[{y,4},{atom,mandatory}]}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,3}],{x,0}}.
+ {kill,{y,0}}.
+ {kill,{y,4}}.
+ {call,1,{f,15}}.
+ {test_heap,2,1}.
+ {put_list,{x,0},{literal,["end,",nl]},{x,0}}.
+ {call,1,{f,17}}.
+ {jump,{f,12}}.
+ {label,11}.
+ {gc_bif,'+',{f,0},0,[{y,0},{integer,3}],{x,0}}.
+ {kill,{y,0}}.
+ {kill,{y,4}}.
+ {call,1,{f,15}}.
+ {move,{x,0},{y,4}}.
+ {move,{integer,3},{x,0}}.
+ {call,1,{f,15}}.
+ {test_heap,8,1}.
+ {put_list,{x,0},{literal,["end,",nl]},{x,0}}.
+ {put_list,{atom,nl},{x,0},{x,0}}.
+ {put_list,{literal,"end"},{x,0},{x,1}}.
+ {put_list,{y,4},{x,1},{x,0}}.
+ {kill,{y,4}}.
+ {call,1,{f,17}}.
+ {label,12}.
+ {move,{y,6},{x,1}}.
+ {move,{y,5},{x,0}}.
+ {call_last,2,{f,6},7}.
+ {label,13}.
+ {case_end,{y,4}}.
+
+
+{function, indent, 1, 15}.
+ {label,14}.
+ {func_info,{atom,test1},{atom,indent},1}.
+ {label,15}.
+ {move,nil,{x,0}}.
return.
-{function, module_info, 0, 9}.
- {label,8}.
+{function, emit, 1, 17}.
+ {label,16}.
+ {func_info,{atom,test1},{atom,emit},1}.
+ {label,17}.
+ {move,nil,{x,0}}.
+ return.
+
+
+{function, emit_opt_or_mand_check, 2, 19}.
+ {label,18}.
+ {func_info,{atom,test1},{atom,emit_opt_or_mand_check},2}.
+ {label,19}.
+ {move,nil,{x,0}}.
+ return.
+
+
+{function, module_info, 0, 21}.
+ {label,20}.
{func_info,{atom,test1},{atom,module_info},0}.
- {label,9}.
+ {label,21}.
{move,{atom,test1},{x,0}}.
{call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
-{function, module_info, 1, 11}.
- {label,10}.
+{function, module_info, 1, 23}.
+ {label,22}.
{func_info,{atom,test1},{atom,module_info},1}.
- {label,11}.
+ {label,23}.
{move,{x,0},{x,1}}.
{move,{atom,test1},{x,0}}.
{call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
+
+
+{function, '-foo/1-fun-0-', 2, 25}.
+ {label,24}.
+ {func_info,{atom,test1},{atom,'-foo/1-fun-0-'},2}.
+ {label,25}.
+ {gc_bif,'+',{f,0},2,[{x,0},{x,1}],{x,0}}.
+ return.
View
50 src/main/erl/test1.erl
@@ -1,17 +1,47 @@
-module(test1).
--export([foo/1,bar/1]).
+-export([foo/1,bar/2,gen_dec_postponed_decs/2]).
-foo(X) when (X/2.0)==3.3 ->
- true;
-foo(X) ->
- 2.0*X.
+foo(X) -> fun(A0) -> A0+X end.
+bar(Fun,A1) -> Fun(A1).
-bar(A) ->
- case catch foo:bar(A) of
- A -> true;
- _ -> false
- end.
+gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->
+% asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+ emit({"{",Term,", _, _} = ",nl}),
+ N = case OptOrMand of
+ mandatory -> 0;
+ 'OPTIONAL' ->
+ emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
+ 6;
+ {'DEFAULT',Val} ->
+ emit_opt_or_mand_check(Val,TmpTerm),
+ 6
+ end,
+ emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
+% ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),
+ ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),
+ emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),
+ emit({indent(N+9),"exit({'Type not compatible with table constraint',",
+ {curr,reason},"});",nl}),
+ emit({indent(N+6),{curr,tmpterm}," ->",nl}),
+ emit({indent(N+9),{curr,tmpterm},nl}),
+
+ case OptOrMand of
+ mandatory -> emit([indent(N+3),"end,",nl]);
+ _ ->
+ emit([indent(N+3),"end",nl,
+ indent(3),"end,",nl])
+ end,
+% emit({indent(3),"end,",nl}),
+ gen_dec_postponed_decs(DecObj,Rest).
+
+
+
+indent(_) -> [].
+emit(_) -> [].
+emit_opt_or_mand_check(_,_) -> [].
View
2 src/main/java/erjang/EAtom.java
@@ -25,7 +25,7 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-public class EAtom extends ETerm implements CharSequence {
+public class EAtom extends EObject implements CharSequence {
public EAtom testAtom() {
return this;
View
2 src/main/java/erjang/EBig.java
@@ -24,7 +24,7 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-public class EBig extends ENumber {
+public class EBig extends EInteger {
private final BigInteger value;
View
41 src/main/java/erjang/EBinary.java
@@ -18,18 +18,34 @@
package erjang;
+import java.nio.charset.Charset;
+
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-public class EBinary extends ETerm {
+import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
+
+public class EBinary extends EObject {
- public EBinary(byte[] binaryValue) {
- // TODO Auto-generated constructor stub
+ private static final Type EBINARY_TYPE = Type.getType(EBinary.class);
+ private static final String EBINARY_NAME = EBINARY_TYPE.getInternalName();
+ private final byte[] data;
+
+ public EBinary(byte[] data) {
+ this.data = data;
}
@Override
public Type emit_const(MethodVisitor fa) {
- throw new NotImplemented();
+ char[] chs = new char[data.length];
+ for (int i = 0; i < data.length; i++) { chs[i] = (char) (0xff & (int)data[i]); }
+ String str = new String(chs);
+
+ fa.visitLdcInsn(str);
+ fa.visitMethodInsn(Opcodes.INVOKESTATIC, EBINARY_NAME, "fromString", "(Ljava/lang/String;)L" + EBINARY_NAME + ";");
+
+ return EBINARY_TYPE;
}
public EBinary testBinary() {
@@ -40,7 +56,20 @@ public EBinary testBinary() {
* @return
*/
public byte[] getByteArray() {
- // TODO Auto-generated method stub
- return null;
+ return data;
+ }
+
+ /**
+ * @return
+ */
+ public int byte_size() {
+ return data.length;
+ }
+
+ /**
+ * @return
+ */
+ public int bit_size() {
+ return byte_size() * 8;
}
}
View
4 src/main/java/erjang/ECons.java
@@ -18,9 +18,9 @@
package erjang;
-import erjang.modules.erlang;
+import erjang.bifs.erlang;
-public abstract class ECons extends ETerm {
+public abstract class ECons extends EObject {
public static final ENil NIL = new ENil();
View
2 src/main/java/erjang/EDouble.java
@@ -41,7 +41,7 @@ public int intValue() {
return (int) value;
}
- public static ETerm parseDouble(String string) {
+ public static EObject parseDouble(String string) {
return new EDouble(Double.parseDouble(string));
}
View
95 src/main/java/erjang/EInt32.java
@@ -0,0 +1,95 @@
+/**
+ * This file is part of Erjang - A JVM-based Erlang VM
+ *
+ * Copyright (c) 2009 by Trifork
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+package erjang;
+
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class EInt32 extends EInteger {
+
+ private static final Type EINTEGER_TYPE = Type.getType(EInt32.class);
+ public final int value;
+
+ public EInt32(int value)
+ {
+ this.value = value;
+ }
+
+ /* (non-Javadoc)
+ * @see erjang.EObject#asInt()
+ */
+ @Override
+ public int asInt() {
+ return value;
+ }
+
+ public EInt32 testInteger() {
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof EInt32) {
+ EInt32 o = (EInt32) obj;
+ return o.value == value;
+ }
+ return false;
+ }
+
+ public int intValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public org.objectweb.asm.Type emit_const(MethodVisitor fa) {
+
+ Type type = EINTEGER_TYPE;
+
+ fa.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+ fa.visitInsn(Opcodes.DUP);
+ fa.visitLdcInsn(new Integer(value));
+ fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", "(I)V");
+
+ return type;
+ }
+
+ @Override
+ public EInt32 asb() {
+ return new EInt32 (Math.abs(value));
+ }
+
+ /**
+ * @param arity
+ * @return
+ */
+ public static EInt32 make(int arity) {
+ return new EInt32(arity);
+ }
+}
View
69 src/main/java/erjang/EInteger.java
@@ -16,72 +16,13 @@
* limitations under the License.
**/
-package erjang;
-
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-public class EInteger extends ENumber {
-
- private static final Type EINTEGER_TYPE = Type.getType(EInteger.class);
- public final int value;
-
- public EInteger(int value)
- {
- this.value = value;
- }
-
- public EInteger testInteger() {
- return this;
- }
- @Override
- public int hashCode() {
- return value;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof EInteger) {
- EInteger o = (EInteger) obj;
- return o.value == value;
- }
- return false;
- }
-
- public int intValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
-
- @Override
- public org.objectweb.asm.Type emit_const(MethodVisitor fa) {
+package erjang;
- Type type = EINTEGER_TYPE;
-
- fa.visitTypeInsn(Opcodes.NEW, type.getInternalName());
- fa.visitInsn(Opcodes.DUP);
- fa.visitLdcInsn(new Integer(value));
- fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", "(I)V");
-
- return type;
- }
- @Override
- public EInteger asb() {
- return new EInteger (Math.abs(value));
- }
+/**
+ *
+ */
+public abstract class EInteger extends ENumber {
- /**
- * @param arity
- * @return
- */
- public static EInteger make(int arity) {
- return new EInteger(arity);
- }
}
View
8 src/main/java/erjang/EList.java
@@ -22,7 +22,7 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-import erjang.modules.erlang;
+import erjang.bifs.erlang;
public class EList extends ESeq {
@@ -79,7 +79,7 @@ public String toString() {
static Type ELIST_TYPE = Type.getType(EList.class);
- static Type ETERM_TYPE = Type.getType(ETerm.class);
+ static Type ETERM_TYPE = Type.getType(EObject.class);
static String CONSTRUCTOR_DESC = "(" + ETERM_TYPE.getDescriptor() + ELIST_TYPE.getDescriptor() + ")V";
@Override
@@ -89,8 +89,8 @@ public Type emit_const(MethodVisitor fa) {
fa.visitTypeInsn(Opcodes.NEW, type.getInternalName());
fa.visitInsn(Opcodes.DUP);
- ((ETerm)head).emit_const(fa);
- ((ETerm)tail).emit_const(fa);
+ ((EObject)head).emit_const(fa);
+ ((EObject)tail).emit_const(fa);
fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", CONSTRUCTOR_DESC);
View
2 src/main/java/erjang/ENil.java
@@ -32,7 +32,7 @@ public ENil() {
}
@Override
- public ETerm head() {
+ public EObject head() {
throw new UnsupportedOperationException();
}
View
16 src/main/java/erjang/ENumber.java
@@ -20,14 +20,14 @@
import java.math.BigInteger;
-public abstract class ENumber extends ETerm {
+public abstract class ENumber extends EObject {
public abstract int intValue();
public static ENumber parseInt(String str) {
try {
int val = java.lang.Integer.parseInt(str);
- return new EInteger(val);
+ return new EInt32(val);
} catch (NumberFormatException e) {
BigInteger val = new java.math.BigInteger(str);
return new EBig(val);
@@ -71,7 +71,7 @@ public ENumber multiply(ENumber n2) {
public static ENumber valueFor(long res) {
int intres = (int) res;
- if (res == intres) return new EInteger(intres);
+ if (res == intres) return new EInt32(intres);
return new EBig(res);
}
@@ -104,8 +104,7 @@ public ENumber add(int i2) {
* @return
*/
public ENumber divide(EObject v2) {
- // TODO Auto-generated method stub
- return null;
+ throw new NotImplemented();
}
/**
@@ -116,4 +115,11 @@ public ENumber divide(double d2) {
throw new NotImplemented();
}
+ /**
+ * @return
+ */
+ public ENumber negate() {
+ throw new NotImplemented();
+ }
+
}
View
12 src/main/java/erjang/EObject.java
@@ -18,6 +18,9 @@
package erjang;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
public class EObject {
public ECons cons(EObject h)
@@ -58,7 +61,7 @@ public ECons testCons() {
return null;
}
- public EInteger testInteger() {
+ public EInt32 testInteger() {
return null;
}
@@ -89,5 +92,12 @@ public EPort testPort() {
public EDouble testFloat() {
return null;
}
+
+
+ public Type emit_const(MethodVisitor mv) {
+ throw new NotImplemented();
+ }
+
+
}
View
8 src/main/java/erjang/EPair.java
@@ -44,7 +44,7 @@ public EObject head() {
return head;
}
- public ETerm tail() {
+ public EObject tail() {
return (ECons)tail;
}
@@ -70,7 +70,7 @@ public String toString() {
}
static Type EPAIR_TYPE = Type.getType(EPair.class);
- static Type ETERM_TYPE = Type.getType(ETerm.class);
+ static Type ETERM_TYPE = Type.getType(EObject.class);
static String CONSTRUCTOR_DESC = "(" + ETERM_TYPE.getDescriptor() + ETERM_TYPE.getDescriptor() + ")V";
@Override
@@ -81,8 +81,8 @@ public Type emit_const(MethodVisitor fa) {
fa.visitInsn(Opcodes.DUP);
- ((ETerm)head).emit_const(fa);
- ((ETerm)tail).emit_const(fa);
+ ((EObject)head).emit_const(fa);
+ ((EObject)tail).emit_const(fa);
fa.visitMethodInsn(Opcodes.INVOKESPECIAL, type.getInternalName(), "<init>", CONSTRUCTOR_DESC);
View
8 src/main/java/erjang/EProc.java
@@ -55,5 +55,13 @@ public EObject get(EObject key) {
EObject res = pdict.get(key);
return (res==null) ? ENil.NIL : res;
}
+
+ /**
+ * @return
+ */
+ public ECons get() {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
View
32 src/main/java/erjang/ERT.java
@@ -27,7 +27,7 @@
public static final EAtom AM_BADARITH = EAtom.intern("badarith");
public static final EAtom AM_MODULE = EAtom.intern("module");
- public static ETerm cons(EObject h, EObject t) {
+ public static EObject cons(EObject h, EObject t) {
return t.cons(h);
}
@@ -39,6 +39,10 @@ public static ErlangException badarg() {
throw new ErlangException(AM_BADARG);
}
+ public static ErlangException badarg(Throwable cause, Object... args) {
+ throw new ErlangException(AM_BADARG, cause, args);
+ }
+
public static ErlangException badarg(Object... args) {
throw new ErlangException(AM_BADARG, args);
}
@@ -47,31 +51,31 @@ public static ErlangException badarg(Object o1, Object o2) {
throw new ErlangException(AM_BADARG, new Object[] { o1, o2 });
}
- public static ErlangException badarg(Throwable cause, Object... args) {
- throw new ErlangException(AM_BADARG, cause, args);
- }
-
- public static ErlangException badarg(EObject arg1, int arg2) {
- throw new ErlangException(AM_BADARG, arg1, arg2);
- }
-
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) {
+ public static boolean eq(EAtom o1, EAtom o2) {
return o1 == o2;
}
+
+ public static EAtom is_atom(EObject o) {
+ return o==null?null:o.testAtom();
+ }
- public static boolean eq(EAtom o1, EObject o2) {
- return o1 == o2;
+ public static ECons is_nonempty_list(EObject o) {
+ return o==null?null:o.testNonEmptyList();
}
- public static boolean eq(EAtom o1, EAtom o2) {
- return o1 == o2;
+ public static ENil is_nil(EObject o) {
+ return o==null?ENil.NIL:o.testNil();
+ }
+
+ public static EDouble is_list(EObject o) {
+ return o==null?null:o.testFloat();
}
/**
View
6 src/main/java/erjang/EString.java
@@ -59,7 +59,7 @@ public static EString make(ECons list) {
EObject head = list.head();
- EInteger intval;
+ EInt32 intval;
if ((intval = head.testInteger()) == null) {
throw ERT.badarg();
}
@@ -204,8 +204,8 @@ public ESeq tail() {
* @see erjang.ECons#head()
*/
@Override
- public EInteger head() {
- return new EInteger(data[off] & 0xff);
+ public EInt32 head() {
+ return new EInt32(data[off] & 0xff);
}
@Override
View
32 src/main/java/erjang/ETerm.java
@@ -1,32 +0,0 @@
-/**
- * This file is part of Erjang - A JVM-based Erlang VM
- *
- * Copyright (c) 2009 by Trifork
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-package erjang;
-
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-
-public abstract class ETerm extends EObject {
-
- public abstract Type emit_const(MethodVisitor mv);
-
- public int asInt() {
- return ((EInteger)this).intValue();
- }
-
-}
View
19 src/main/java/erjang/ETuple.java
@@ -31,12 +31,25 @@
import org.objectweb.asm.Type;
import org.objectweb.asm.util.CheckClassAdapter;
-public abstract class ETuple extends ETerm implements Cloneable {
+import clojure.lang.Indexed;
+
+public abstract class ETuple extends EObject implements Cloneable, Indexed {
public ETuple testTuple() {
return this;
}
+ @Override
+ public int count() {
+ return arity();
+ }
+
+ /** tuple's are 1-based, clojure's Indexed are 0-based */
+ @Override
+ public Object nth(int i) {
+ return elm(i+1);
+ }
+
public abstract int arity();
public abstract EObject elm(int i);
@@ -276,7 +289,7 @@ private static void create_tuple_set(int n_cells, ClassAdapter cw,
mv.visitEnd();
}
- protected final ETerm bad_nth(int i) {
+ protected final EObject bad_nth(int i) {
throw new IllegalArgumentException();
}
@@ -390,7 +403,7 @@ public Type emit_const(MethodVisitor fa) {
for (int i = 0; i < arity(); i++) {
fa.visitInsn(Opcodes.DUP);
- ((ETerm) elm(i + 1)).emit_const(fa);
+ ((EObject) elm(i + 1)).emit_const(fa);
fa.visitFieldInsn(Opcodes.PUTFIELD, type.getInternalName(), "elem"
+ (i + 1), ETERM_TYPE.getDescriptor());
View
4 src/main/java/erjang/ErlangException.java
@@ -96,7 +96,7 @@ private EObject erl_value(Object val) {
if (val instanceof String)
return EString.fromString((String) val);
if (val instanceof Integer)
- return EInteger.make(((Integer) val).intValue());
+ return EInt32.make(((Integer) val).intValue());
throw new Error();
}
@@ -186,7 +186,7 @@ private ETuple resolve(Class<?> c, Method m, BIF ann1, ErlFun ann2) {
arity -= 1;
}
- return ETuple.make(EAtom.intern(module), EAtom.intern(fun), EInteger
+ return ETuple.make(EAtom.intern(module), EAtom.intern(fun), EInt32
.make(arity));
}
View
2 src/main/java/erjang/beam/Arg.java
@@ -36,7 +36,7 @@
public final Kind kind;
int no;
- public final Type type;
+ public Type type;
EObject value;
public Arg(Kind kind, int reg) {
View
79 src/main/java/erjang/beam/BIFUtil.java
@@ -28,11 +28,11 @@
import erjang.EAtom;
import erjang.EDouble;
-import erjang.EInteger;
+import erjang.EInt32;
import erjang.EObject;
import erjang.EProc;
-import erjang.modules.BinOps;
-import erjang.modules.erlang;
+import erjang.bifs.BinOps;
+import erjang.bifs.erlang;
/**
* Used by the compiler to find and mange BIF definitions.
@@ -73,7 +73,16 @@
try {
args[i] = Class.forName(types[i].getClassName());
} catch (ClassNotFoundException e) {
- throw new Error(e);
+
+ if (types[i] == Type.BOOLEAN_TYPE) {
+ args[i] = boolean.class;
+ } else if (types[i] == Type.INT_TYPE) {
+ args[i] = int.class;
+ } else if (types[i] == Type.DOUBLE_TYPE) {
+ args[i] = double.class;
+ } else {
+ throw new Error(e);
+ }
}
}
}
@@ -84,7 +93,8 @@ public Args(Class[] a) {
@Override
public int hashCode() {
- if (code != 0) return code;
+ if (code != 0)
+ return code;
for (int i = 0; i < args.length; i++) {
code += args[i].getName().hashCode();
}
@@ -147,33 +157,36 @@ public Args generic() {
ArrayList<Args> res = new ArrayList<Args>();
Class[] aa = this.args.clone();
-
+
for (int i = 0; i < args.length; i++) {
// aa = this.args.clone();
-
+
// vary over arg[i]'s super types
for (Class c = args[i]; !c.equals(Object.class); c = super_class(c)) {
aa[i] = c;
res.add(new Args(aa.clone()));
-
- for (int j = i+1; j<args.length; j++) {
-
+
+ for (int j = i + 1; j < args.length; j++) {
+
for (Class cc = args[j]; !cc.equals(Object.class); cc = super_class(cc)) {
aa[j] = cc;
res.add(new Args(aa.clone()));
}
}
}
}
-
+
return res;
}
private Class super_class(Class c) {
if (c.isPrimitive()) {
- if (c == double.class) return EDouble.class;
- if (c == int.class) return EInteger.class;
- if (c == boolean.class) return EAtom.class;
+ if (c == double.class)
+ return EDouble.class;
+ if (c == int.class)
+ return EInt32.class;
+ if (c == boolean.class)
+ return EAtom.class;
return EObject.class;
} else {
return c.getSuperclass();
@@ -201,7 +214,8 @@ public BIFHandler(String name, String javaName) {
public Type getResult(Type[] parmTypes) {
BuiltInFunction method = getMethod(parmTypes);
if (method == null) {
- throw new Error("no bif name "+this.name+" for parms "+new Args(parmTypes));
+ throw new Error("no bif name " + this.name + " for parms "
+ + new Args(parmTypes));
}
return method.getReturnType();
}
@@ -225,18 +239,20 @@ public void registerMethod(BuiltInFunction method) {
public BuiltInFunction getMethod(Type[] parmTypes) {
BuiltInFunction m = find_bif(parmTypes);
- if (m != null) return m;
-
+ if (m != null)
+ return m;
+
// try with EProc as first argument
if (parmTypes.length == 0 || !EPROC_TYPE.equals(parmTypes[0])) {
- Type[] extra = new Type[parmTypes.length+1];
+ Type[] extra = new Type[parmTypes.length + 1];
extra[0] = EPROC_TYPE;
for (int i = 0; i < parmTypes.length; i++) {
- extra[i+1] = parmTypes[i];
+ extra[i + 1] = parmTypes[i];
}
-
+
m = find_bif(extra);
- if (m != null) return m;
+ if (m != null)
+ return m;
}
return m;
@@ -246,18 +262,20 @@ public BuiltInFunction getMethod(Type[] parmTypes) {
private BuiltInFunction find_bif(Type[] parmTypes) {
Args args = new Args(parmTypes);
BuiltInFunction m = found.get(args);
- if (m != null) { return m; }
-
+ if (m != null) {
+ return m;
+ }
+
for (Args a : args.generalize()) {
m = found.get(a);
- if (m != null) {
-
+ if (m != null) {
+
System.err.println("missed opportunity erlang:"
+ EAtom.intern(name) + "/" + parmTypes.length + " "
+ args + ", \n\tusing " + m);
- return m;
- }
+ return m;
+ }
}
return null;
}
@@ -331,9 +349,12 @@ public static BuiltInFunction getMethod(String name, Type[] parmTypes,
* @param isGuard
* @return
*/
- public static BuiltInFunction getMethod(String name, Arg[] args, boolean isGuard) {
+ public static BuiltInFunction getMethod(String name, Arg[] args,
+ boolean isGuard) {
Type[] parms = new Type[args.length];
- for (int i = 0; i < args.length; i++) { parms[i] = args[i].type; }
+ for (int i = 0; i < args.length; i++) {
+ parms[i] = args[i].type;
+ }
return getMethod(name, parms, isGuard);
}
View
5 src/main/java/erjang/beam/BeamFileData.java
@@ -19,11 +19,10 @@
package erjang.beam;
import erjang.EAtom;
-import erjang.EInteger;
+import erjang.EInt32;
import erjang.EList;
import erjang.EObject;
import erjang.ESeq;
-import erjang.ETerm;
import erjang.ETuple;
import erjang.ETuple0;
@@ -101,7 +100,7 @@ private void visit_insns(EList insns, FunctionVisitor fv) {
BeamOpcode opcode = BeamOpcode.get((EAtom) et.elm(1));
if (opcode == BeamOpcode.label) {
- EInteger label = (EInteger) et.elm(2);
+ EInt32 label = (EInt32) et.elm(2);
if (bbv != null) {
bbv.visitEnd();
View
34 src/main/java/erjang/beam/Compiler.java
@@ -30,7 +30,7 @@
import erjang.EBinary;
import erjang.beam.analysis.BeamTypeAnalysis;
-import erjang.modules.erlang;
+import erjang.bifs.erlang;
public class Compiler implements Opcodes {
@@ -97,20 +97,24 @@ void compile(File file) throws IOException {
try {
// go!
reader.accept(analysis);
- } catch (Error e) {
- e.printStackTrace();
+ } finally {
+ classRepo.store(cv.getInternalClassName(), cw.toByteArray());
}
// get byte code data
- classRepo.store(cv.getInternalClassName(), cw.toByteArray());
+ // classRepo.store(cv.getInternalClassName(), cw.toByteArray());
}
public static String moduleClassName(String moduleName) {
String cn = EUtil.toJavaIdentifier(moduleName);
- String internalEMname = erlang.class.getName().replace('.', '/');
- int idx = internalEMname.lastIndexOf('/');
- String prefix = internalEMname.substring(0, idx + 1);
- return prefix + cn;
+ String base = "erjang/m/" + cn + "/" + cn;
+
+ return base;
+
+// String internalEMname = erlang.class.getName().replace('.', '/');
+// int idx = internalEMname.lastIndexOf('/');
+// String prefix = internalEMname.substring(0, idx + 1);
+// return prefix + cn;
}
public static void main(String[] args) throws Exception {
@@ -127,19 +131,5 @@ public static void main(String[] args) throws Exception {
repo.close();
}
- static void writeTo(File output, byte[] class_data) throws IOException {
-
- output.getParentFile().mkdirs();
-
- FileOutputStream fo = new FileOutputStream(output);
- try {
- fo.write(class_data);
- } finally {
- if (fo != null)
- fo.close();
- }
-
- }
-
}
View
144 src/main/java/erjang/beam/CompilerVisitor.java
@@ -18,7 +18,6 @@
package erjang.beam;
-import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
@@ -43,7 +42,7 @@
import erjang.ECons;
import erjang.EDouble;
import erjang.EFun;
-import erjang.EInteger;
+import erjang.EInt32;
import erjang.EList;
import erjang.EModule;
import erjang.ENil;
@@ -55,14 +54,12 @@
import erjang.ERT;
import erjang.ESeq;
import erjang.EString;
-import erjang.ETerm;
import erjang.ETuple;
import erjang.ETuple2;
import erjang.ErlFun;
import erjang.ErlangException;
import erjang.Module;
import erjang.beam.Arg.Kind;
-import erjang.beam.CompilerVisitor.ASMFunctionAdapter.ASMBlockVisitor;
/**
*
@@ -79,7 +76,7 @@
static final Type ERLANG_EXCEPTION_TYPE = Type
.getType(ErlangException.class);
static final Type ERT_TYPE = Type.getType(ERT.class);
- static final Type EINTEGER_TYPE = Type.getType(EInteger.class);
+ static final Type EINTEGER_TYPE = Type.getType(EInt32.class);
static final Type EMODULE_TYPE = Type.getType(EModule.class);
/**
*
@@ -132,20 +129,20 @@
static final Type EPORT_TYPE = Type.getType(EPort.class);
static final Type EMATCHSTATE_TYPE = Type.getType(EBinMatchState.class);
- static final ETerm TRUE_ATOM = EAtom.intern("true");
- static final ETerm FALSE_ATOM = EAtom.intern("false");
- static final ETerm X_ATOM = EAtom.intern("x");
- static final ETerm Y_ATOM = EAtom.intern("y");
- static final ETerm FR_ATOM = EAtom.intern("fr");
- static final ETerm NIL_ATOM = EAtom.intern("nil");
- static final ETerm INTEGER_ATOM = EAtom.intern("integer");
- static final ETerm FLOAT_ATOM = EAtom.intern("float");
- static final ETerm ATOM_ATOM = EAtom.intern("atom");
- static final ETerm LITERAL_ATOM = EAtom.intern("literal");
- static final ETerm NOFAIL_ATOM = EAtom.intern("nofail");
- static final ETerm F_ATOM = EAtom.intern("f");
- static final ETerm FIELD_FLAGS_ATOM = EAtom.intern("field_flags");
- static final ETerm ERLANG_ATOM = EAtom.intern("erlang");
+ static final EObject TRUE_ATOM = EAtom.intern("true");
+ static final EObject FALSE_ATOM = EAtom.intern("false");
+ static final EObject X_ATOM = EAtom.intern("x");
+ static final EObject Y_ATOM = EAtom.intern("y");
+ static final EObject FR_ATOM = EAtom.intern("fr");
+ static final EObject NIL_ATOM = EAtom.intern("nil");
+ static final EObject INTEGER_ATOM = EAtom.intern("integer");
+ static final EObject FLOAT_ATOM = EAtom.intern("float");
+ static final EObject ATOM_ATOM = EAtom.intern("atom");
+ static final EObject LITERAL_ATOM = EAtom.intern("literal");
+ static final EObject NOFAIL_ATOM = EAtom.intern("nofail");
+ static final EObject F_ATOM = EAtom.intern("f");
+ static final EObject FIELD_FLAGS_ATOM = EAtom.intern("field_flags");
+ static final EObject ERLANG_ATOM = EAtom.intern("erlang");
static final Type MODULE_ANN_TYPE = Type.getType(Module.class);
static final Type ERLFUN_ANN_TYPE = Type.getType(ErlFun.class);
@@ -201,7 +198,7 @@ private String getModuleName() {
return module_name.getName();
}
- Map<ETerm, String> constants = new HashMap<ETerm, String>();
+ Map<EObject, String> constants = new HashMap<EObject, String>();
/*
* (non-Javadoc)
@@ -250,9 +247,9 @@ private void generate_classinit() {
}
- for (Map.Entry<ETerm, String> ent : constants.entrySet()) {
+ for (Map.Entry<EObject, String> ent : constants.entrySet()) {
- ETerm term = ent.getKey();
+ EObject term = ent.getKey();
term.emit_const(mv);
mv.visitFieldInsn(Opcodes.PUTSTATIC, self_type.getInternalName(),
ent.getValue(), Type.getType(term.getClass())
@@ -603,6 +600,8 @@ public BlockVisitor visitLabeledBlock(int label) {
public void visitInsn(BeamOpcode opcode, int failLabel, Arg[] in,
Arg out, BuiltInFunction bif) {
+ test_ex_start();
+
switch (opcode) {
case gc_bif:
case bif:
@@ -617,8 +616,6 @@ public void visitInsn(BeamOpcode opcode, int failLabel, Arg[] in,
if (failLabel != 0) {
// guard
- if (bif.getReturnType().getSort() != Type.OBJECT)
- throw new Error("guards must return object type");
// dup result for test
if (out != null) {
@@ -627,7 +624,13 @@ public void visitInsn(BeamOpcode opcode, int failLabel, Arg[] in,
push(out, bif.getReturnType());
}
- mv.visitJumpInsn(IFNULL, getLabel(failLabel));
+ if (bif.getReturnType().getSort() == Type.BOOLEAN) {
+ mv.visitJumpInsn(IFEQ, getLabel(failLabel));
+ } else {
+ if (bif.getReturnType().getSort() != Type.OBJECT)
+ throw new Error("guards must return object type - "+bif);
+ mv.visitJumpInsn(IFNULL, getLabel(failLabel));
+ }
} else {
pop(out, bif.getReturnType());
}
@@ -684,7 +687,9 @@ private void pop(Arg out, Type stack_type) {
if (out.kind == Kind.X || out.kind == Kind.Y) {
if (out.type == Type.INT_TYPE
|| out.type == Type.BOOLEAN_TYPE
- || (out.type == null && stack_type == Type.INT_TYPE)) {
+ || (out.type == null && stack_type == Type.INT_TYPE)
+ || (out.type == null && stack_type == Type.BOOLEAN_TYPE)
+ ) {
mv.visitVarInsn(ISTORE, var_index(out));
} else {
mv.visitVarInsn(ASTORE, var_index(out));
@@ -823,7 +828,7 @@ private void push(Arg value, Type stack_type) {
} else if (value.kind == Kind.F) {
mv.visitVarInsn(DLOAD, var_index(value));
} else if (value.kind == Kind.IMMEDIATE) {
- t = push_immediate((ETerm) value.value, stack_type);
+ t = push_immediate(value.value, stack_type);
} else {
throw new Error();
}
@@ -838,7 +843,7 @@ private void push(Arg value, Type stack_type) {
* @param stack_type
* TODO
*/
- private Type push_immediate(ETerm value, Type stack_type) {
+ private Type push_immediate(EObject value, Type stack_type) {
if (value == ENil.NIL) {
mv.visitFieldInsn(GETSTATIC, ENIL_NAME, "NIL", ENIL_TYPE
@@ -859,7 +864,7 @@ private Type push_immediate(ETerm value, Type stack_type) {
}
if (stack_type.getSort() != Type.OBJECT) {
- if (value instanceof EInteger) {
+ if (value instanceof EInt32) {
mv.visitLdcInsn(new Integer(value.asInt()));
return Type.INT_TYPE;
} else if (value instanceof EDouble) {
@@ -906,7 +911,7 @@ private Type push_immediate(ETerm value, Type stack_type) {
* @param size
* @return
*/
- private String getConstantName(ETerm value, int size) {
+ private String getConstantName(EObject value, int size) {
if (value instanceof EAtom)
return "atom_" + EUtil.toJavaIdentifier((EAtom) value);
if (value instanceof ENumber)
@@ -963,6 +968,24 @@ public void visitInsn(BeamOpcode opcode, Arg[] in, Arg out) {
+ ECONS_TYPE.getDescriptor());
pop(out, ECONS_TYPE);
return;
+ case call_fun:
+ {
+ int nargs = in.length-1;
+ push(in[nargs], EOBJECT_TYPE);
+
+ String funtype = EFUN_NAME + nargs;
+
+ mv.visitMethodInsn(INVOKESTATIC, funtype, "cast", "(" + EOBJECT_DESCRIPTOR + ")L" + funtype + ";" );
+
+ mv.visitVarInsn(ALOAD, 0); // load proc
+ for (int i = 0; i < nargs; i++) {
+ push(in[i], EOBJECT_TYPE);
+ }
+
+ mv.visitMethodInsn(INVOKEVIRTUAL, funtype, "invoke", EUtil.getSignature(nargs, true));
+ pop(out, EOBJECT_TYPE);
+ return;
+ }
}
throw new Error();
@@ -1006,6 +1029,17 @@ public void visitInsn(BeamOpcode insn) {
throw new Error();
}
+ void test_ex_start()
+ {
+ if (ex_handlers.size() > 0) {
+ EXHandler ex = ex_handlers.peek();
+ if (!ex.is_start_visited) {
+ mv.visitLabel(ex.begin);
+ ex.is_start_visited = true;
+ }
+ }
+ }
+
/*
* (non-Javadoc)
*
@@ -1024,6 +1058,7 @@ public void visitInsn(BeamOpcode opcode, int val, Arg out) {
return;
+ case K_try:
case K_catch: {
EXHandler h = new EXHandler();
h.begin = new Label();
@@ -1034,13 +1069,16 @@ public void visitInsn(BeamOpcode opcode, int val, Arg out) {
mv.visitTryCatchBlock(h.begin, h.end, h.target, Type
.getType(ErlangException.class).getInternalName());
- mv.visitLabel(h.begin);
ex_handlers.push(h);
return;
}
+ case try_end:
case catch_end: {
+
+ test_ex_start();
+
EXHandler h = ex_handlers.pop();
Label after = new Label();
@@ -1071,7 +1109,16 @@ public void visitInsn(BeamOpcode opcode, int val, Arg out) {
mv.visitJumpInsn(IFNE, getLabel(val));
return;
}
+
+ case wait: {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESTATIC, ERT_NAME, "wait_forever",
+ "(" + EPROC_TYPE.getDescriptor() + ")V");
+
+ mv.visitJumpInsn(GOTO, getLabel(val));
+ return;
}
+}
throw new Error();
}
@@ -1405,6 +1452,8 @@ private Method get_test_bif(BeamOpcode test, Type type) {
return IS_PID_TEST;
case is_port:
return IS_PORT_TEST;
+ case is_function:
+ return IS_FUNCTION_TEST;
}
throw new Error("unhandled " + test);
@@ -1427,6 +1476,7 @@ public void visitInsn(BeamOpcode opcode, Arg[] ys) {
for (int i = 0; i < ys.length; i++) {
if (i != (ys.length - 1))
mv.visitInsn(DUP);
+ mv.visitInsn(NOP);
pop(ys[i], ENIL_TYPE);
}
@@ -1644,14 +1694,12 @@ private Type getTubleType(int i) {
public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
boolean isExternal) {
+ test_ex_start();
+
if (false /* fun.mod == ERLANG_ATOM */) {
System.err.println(fun);
- if ("erlang:error/1".equals(fun.toString())) {
- System.err.println("break here!");
- }
-
// functions in module "erlang" compile to direct calls
BuiltInFunction m = BIFUtil.getMethod(fun.fun.getName(),
@@ -1698,7 +1746,7 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
is_tail ? "invoke_tail" : "invoke", EUtil
.getSignature(args.length, true));
- if (is_tail) {
+ if (is_tail || isExitFunc(fun)) {
mv.visitInsn(ARETURN);
} else {
mv.visitVarInsn(ASTORE, xregs[0]);
@@ -1725,6 +1773,20 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
}
}
+
+ /**
+ * @param fun
+ * @return
+ */
+ private boolean isExitFunc(ExtFunc fun) {
+ if (fun.mod == ERLANG_ATOM) {
+ if (fun.fun.getName().equals("exit")) return true;
+ if (fun.fun.getName().equals("error")) return true;
+ if (fun.fun.getName().equals("throw")) return true;
+ }
+
+ return false;
+ }
}
}
@@ -1735,14 +1797,15 @@ public void visitCall(ExtFunc fun, Arg[] args, boolean is_tail,
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_ATOM_TEST = Method.getMethod("erjang.EAtom testAtom()");
static Method IS_FLOAT_TEST = Method
.getMethod("erjang.EDouble testFloat()");
static Method IS_NIL_TEST = Method.getMethod("boolean isNil()");
static Method IS_BOOLEAN_TEST = Method.getMethod("boolean isBoolean()");
- static Method IS_BINARY_TEST = Method.getMethod("boolean isBinary()");
- static Method IS_PID_TEST = Method.getMethod("boolean isPid()");
- static Method IS_PORT_TEST = Method.getMethod("boolean isPort()");
+ static Method IS_BINARY_TEST = Method.getMethod("erjang.EBinary isBinary()");
+ static Method IS_PID_TEST = Method.getMethod("erjang.EPID isPid()");
+ static Method IS_PORT_TEST = Method.getMethod("erjang.EPort isPort()");
+ static Method IS_FUNCTION_TEST = Method.getMethod("erjang.EFun isFunction()");
Map<String, ExtFunc> imported = new HashMap<String, ExtFunc>();
@@ -1933,6 +1996,7 @@ private static void make_go_method(ClassWriter cw, String outer_name,
}
class EXHandler {
+ public boolean is_start_visited;
Arg reg;
Label begin, end, target;
}
View
29 src/main/java/erjang/beam/OtpConverter.java
@@ -31,17 +31,18 @@
import com.ericsson.otp.erlang.OtpErlangTuple;
import erjang.EAtom;
+import erjang.EBig;
import erjang.EBinary;
import erjang.EDouble;
-import erjang.EInteger;
+import erjang.EInt32;
import erjang.EList;
+import erjang.EObject;
import erjang.ERT;
import erjang.EString;
-import erjang.ETerm;
import erjang.ETuple;
abstract class Converter<T> {
- abstract ETerm conv(T obj);
+ abstract EObject conv(T obj);
}
/**
@@ -61,8 +62,8 @@
static {
add(OtpErlangTuple.class, new Converter<OtpErlangTuple>() {
- ETerm conv(OtpErlangTuple obj) {
- ETerm[] vals = new ETerm[obj.arity()];
+ EObject conv(OtpErlangTuple obj) {
+ EObject[] vals = new EObject[obj.arity()];
for (int i = 0; i < obj.arity(); i++) {
vals[i] = convert(obj.elementAt(i));
}
@@ -72,8 +73,8 @@ ETerm conv(OtpErlangTuple obj) {
add(OtpErlangList.class, new Converter<OtpErlangList>() {
@Override
- ETerm conv(OtpErlangList obj) {
- ETerm tail = obj.getLastTail() == null ? EList.NIL
+ EObject conv(OtpErlangList obj) {
+ EObject 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);
@@ -83,37 +84,37 @@ ETerm conv(OtpErlangList obj) {
});
add(OtpErlangAtom.class, new Converter<OtpErlangAtom>() {
- ETerm conv(OtpErlangAtom obj) {
+ EObject conv(OtpErlangAtom obj) {
return EAtom.intern(obj.atomValue());
}
});
add(OtpErlangLong.class, new Converter<OtpErlangLong>() {
- ETerm conv(OtpErlangLong obj) {
- return EInteger.parseInt(obj.toString());
+ EObject conv(OtpErlangLong obj) {
+ return EBig.valueFor(obj.longValue());
}
});
add(OtpErlangString.class, new Converter<OtpErlangString>() {
- ETerm conv(OtpErlangString obj) {
+ EObject conv(OtpErlangString obj) {
return new EString(obj.stringValue());
}
});
add(OtpErlangDouble.class, new Converter<OtpErlangDouble>() {
- ETerm conv(OtpErlangDouble obj) {
+ EObject conv(OtpErlangDouble obj) {
return new EDouble(obj.doubleValue());
}
});
add(OtpErlangBinary.class, new Converter<OtpErlangBinary>() {
- ETerm conv(OtpErlangBinary obj) {
+ EObject conv(OtpErlangBinary obj) {
return new EBinary(obj.binaryValue());
}
});
}
- public static ETerm convert(OtpErlangObject value) {
+ public static EObject convert(OtpErlangObject value) {
Class<? extends OtpErlangObject> c = value.getClass();
Converter cc = conv.get(c);
View
119 src/main/java/erjang/beam/analysis/BeamTypeAnalysis.java
@@ -30,34 +30,32 @@
import java.util.TreeSet;
import org.objectweb.asm.Type;
-import org.objectweb.asm.commons.Method;
import erjang.EAtom;
import erjang.EBinMatchState;
import erjang.EBinary;
import erjang.ECons;
import erjang.EDouble;
import erjang.EFun;
-import erjang.EInteger;
+import erjang.EInt32;
import erjang.EList;
import erjang.ENil;
import erjang.ENumber;
import erjang.EObject;
import erjang.EPID;
import erjang.EPort;
import erjang.ESeq;
-import erjang.ETerm;
import erjang.ETuple;
import erjang.ETuple2;
import erjang.beam.Arg;
-import erjang.beam.BuiltInFunction;
import erjang.beam.BIFUtil;
import erjang.beam.BeamCodeBlock;
import erjang.beam.BeamFunction;
import erjang.beam.BeamInstruction;
import erjang.beam.BeamOpcode;
import erjang.beam.BlockVisitor;
import erjang.beam.BlockVisitor2;
+import erjang.beam.BuiltInFunction;
import erjang.beam.ExtFunc;
import erjang.beam.FunctionAdapter;
import erjang.beam.FunctionVisitor;
@@ -67,15 +65,14 @@
import erjang.beam.Arg.Kind;
public class BeamTypeAnalysis extends ModuleAdapter {
-
/**
*
*/
public BeamTypeAnalysis(ModuleVisitor mv) {
super(mv);
}
- static final Type EINTEGER_TYPE = Type.getType(EInteger.class);
+ static final Type EINTEGER_TYPE = Type.getType(EInt32.class);
static final Type ENUMBER_TYPE = Type.getType(ENumber.class);
static final Type EOBJECT_TYPE = Type.getType(EObject.class);
static final Type EDOUBLE_TYPE = Type.getType(EDouble.class);
@@ -91,22 +88,22 @@ public BeamTypeAnalysis(ModuleVisitor mv) {
static final Type EPORT_TYPE = Type.getType(EPort.class);
static final Type EMATCHSTATE_TYPE = Type.getType(EBinMatchState.class);
- static final ETerm X_ATOM = EAtom.intern("x");
- static final ETerm Y_ATOM = EAtom.intern("y");
- static final ETerm FR_ATOM = EAtom.intern("fr");
- static final ETerm NIL_ATOM = EAtom.intern("nil");
- static final ETerm INTEGER_ATOM = EAtom.intern("integer");
- static final ETerm FLOAT_ATOM = EAtom.intern("float");
- static final ETerm ATOM_ATOM = EAtom.intern("atom");
- static final ETerm LITERAL_ATOM = EAtom.intern("literal");
- static final ETerm NOFAIL_ATOM = EAtom.intern("nofail");
- 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) });
+ static final EObject X_ATOM = EAtom.intern("x");
+ static final EObject Y_ATOM = EAtom.intern("y");
+ static final EObject FR_ATOM = EAtom.intern("fr");
+ static final EObject NIL_ATOM = EAtom.intern("nil");
+ static final EObject INTEGER_ATOM = EAtom.intern("integer");
+ static final EObject FLOAT_ATOM = EAtom.intern("float");
+ static final EObject ATOM_ATOM = EAtom.intern("atom");
+ static final EObject LITERAL_ATOM = EAtom.intern("literal");
+ static final EObject NOFAIL_ATOM = EAtom.intern("nofail");
+ static final EObject F_ATOM = EAtom.intern("f");
+ static final EObject FIELD_FLAGS_ATOM = EAtom.intern("field_flags");
+ static final EObject EXTFUNC_ATOM = EAtom.intern("extfunc");
+ static final EObject APPLY_ATOM = EAtom.intern("apply");
+
+ private static final ETuple X0_REG = ETuple.make(new EObject[] { X_ATOM,
+ new EInt32(0) });
private EAtom moduleName;
private List<FV> functions = new ArrayList<FV>();
@@ -218,6 +215,11 @@ public FV(FunctionVisitor fv, EAtom name, int arity, int startLabel) {
@Override
public void visitEnd() {
+
+ if (this.name.getName().equals("load")) {
+ dump();
+ }
+
LabeledBlock lb = lbs.get(startLabel);
lb.merge_from(this.make_initial());
@@ -322,7 +324,7 @@ private LabeledBlock get_lb(int label, boolean create) {
lbs.put(label, res);
return res;
} else {
- throw new Error("no such bb: " + label);
+ return null;
}
}
@@ -389,7 +391,7 @@ private void accept_2(BlockVisitor2 vis) {
case move: {
// System.err.println(insn);
Arg arg1 = decode_arg(insn_idx, insn.elm(2));
- Arg arg2 = decode_arg(insn_idx, insn.elm(3));
+ Arg arg2 = decode_out_arg(insn_idx, insn.elm(3));
if (arg2.kind != Kind.F) {
if (arg1.kind == Kind.F) {
@@ -458,12 +460,13 @@ private void accept_2(BlockVisitor2 vis) {
vis.visitInsn(opcode, new Arg(Arg.Kind.X, 0, this.map[insn_idx].getx(0)));
break;
+ case allocate_heap_zero:
case allocate_zero: {
int depth = type_map.stacksize;