提交 3f377668 authored 作者: Thomas Mueller's avatar Thomas Mueller

A Java parser / Java to C converter.

上级 cf69bd38
...@@ -56,7 +56,7 @@ public class ClassObj { ...@@ -56,7 +56,7 @@ public class ClassObj {
ArrayList<Statement> nativeCode = new ArrayList<Statement>(); ArrayList<Statement> nativeCode = new ArrayList<Statement>();
String id; int id;
/** /**
* Add a method. * Add a method.
...@@ -87,9 +87,9 @@ public class ClassObj { ...@@ -87,9 +87,9 @@ public class ClassObj {
public String toString() { public String toString() {
if (isPrimitive) { if (isPrimitive) {
return name; return "j" + name;
} }
return "struct " + name; return name;
} }
} }
...@@ -127,7 +127,7 @@ class MethodObj { ...@@ -127,7 +127,7 @@ class MethodObj {
/** /**
* The parameter list. * The parameter list.
*/ */
ArrayList<FieldObj> parameters = new ArrayList<FieldObj>(); LinkedHashMap<String, FieldObj> parameters = new LinkedHashMap<String, FieldObj>();
/** /**
* Whether this method is final. * Whether this method is final.
...@@ -143,6 +143,11 @@ class MethodObj { ...@@ -143,6 +143,11 @@ class MethodObj {
* Whether this method is native. * Whether this method is native.
*/ */
boolean isNative; boolean isNative;
/**
* Whether this is a constructor.
*/
boolean isConstructor;
} }
/** /**
...@@ -209,7 +214,7 @@ class Type { ...@@ -209,7 +214,7 @@ class Type {
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toC(type.name)); buff.append(JavaParser.toC(type.toString()));
if (!type.isPrimitive) { if (!type.isPrimitive) {
buff.append("*"); buff.append("*");
} }
......
...@@ -41,7 +41,7 @@ class CallExpr implements Expr { ...@@ -41,7 +41,7 @@ class CallExpr implements Expr {
if (className != null) { if (className != null) {
buff.append(JavaParser.toC(className + "." + name)).append("("); buff.append(JavaParser.toC(className + "." + name)).append("(");
} else { } else {
buff.append(JavaParser.toC(expr.getType().type.name + "." + name)).append("("); buff.append(JavaParser.toC(expr.getType().type + "." + name)).append("(");
} }
int i = 0; int i = 0;
if (expr != null) { if (expr != null) {
...@@ -198,7 +198,7 @@ class StringExpr implements Expr { ...@@ -198,7 +198,7 @@ class StringExpr implements Expr {
String text; String text;
public String toString() { public String toString() {
return "\"" + javaEncode(text) + "\""; return "STRING(\"" + javaEncode(text) + "\")";
} }
public Type getType() { public Type getType() {
...@@ -282,7 +282,8 @@ class VariableExpr implements Expr { ...@@ -282,7 +282,8 @@ class VariableExpr implements Expr {
} }
if (field != null) { if (field != null) {
if (field.isStatic) { if (field.isStatic) {
buff.append(JavaParser.toC(field.type.type.name + "." + field.name)); // buff.append(JavaParser.toC(field.type.type.name + "." + field.name));
buff.append(JavaParser.toC(name));
} else { } else {
buff.append(field.name); buff.append(field.name);
} }
......
...@@ -31,16 +31,20 @@ public class JavaParser { ...@@ -31,16 +31,20 @@ public class JavaParser {
private static final HashMap<String, ClassObj> BUILT_IN_TYPES = new HashMap<String, ClassObj>(); private static final HashMap<String, ClassObj> BUILT_IN_TYPES = new HashMap<String, ClassObj>();
private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>(); private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>();
private static int firstClassId;
private String source; private String source;
private ParseState current = new ParseState(); private ParseState current = new ParseState();
private String packageName; private String packageName;
private ClassObj classObj; private ClassObj classObj;
private int classId = firstClassId;
private MethodObj method;
private FieldObj thisPointer; private FieldObj thisPointer;
private HashMap<String, String> importMap = new HashMap<String, String>(); private HashMap<String, String> importMap = new HashMap<String, String>();
private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>(); private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>();
private LinkedHashMap<String, FieldObj> localFields = new LinkedHashMap<String, FieldObj>(); private LinkedHashMap<String, FieldObj> localVars = new LinkedHashMap<String, FieldObj>();
private ArrayList<Statement> nativeHeaders = new ArrayList<Statement>(); private ArrayList<Statement> nativeHeaders = new ArrayList<Statement>();
...@@ -54,26 +58,29 @@ public class JavaParser { ...@@ -54,26 +58,29 @@ public class JavaParser {
for (String s : list) { for (String s : list) {
RESERVED.add(s); RESERVED.add(s);
} }
addBuiltInType(true, "void"); int id = 0;
addBuiltInType(true, "int"); addBuiltInType(id++, true, "void");
addBuiltInType(true, "char"); addBuiltInType(id++, true, "int");
addBuiltInType(true, "byte"); addBuiltInType(id++, true, "char");
addBuiltInType(true, "long"); addBuiltInType(id++, true, "byte");
addBuiltInType(true, "double"); addBuiltInType(id++, true, "long");
addBuiltInType(true, "float"); addBuiltInType(id++, true, "double");
addBuiltInType(true, "boolean"); addBuiltInType(id++, true, "float");
addBuiltInType(true, "short"); addBuiltInType(id++, true, "boolean");
addBuiltInType(id++, true, "short");
String[] java = new String[] { "Boolean", "Byte", "Character", "Class", "ClassLoader", "Double", "Float", String[] java = new String[] { "Boolean", "Byte", "Character", "Class", "ClassLoader", "Double", "Float",
"Integer", "Long", "Math", "Number", "Object", "Runtime", "Short", "String", "StringBuffer", "Integer", "Long", "Math", "Number", "Object", "Runtime", "Short", "String", "StringBuffer",
"StringBuilder", "System", "Thread", "ThreadGroup", "ThreadLocal", "Throwable", "Void" }; "StringBuilder", "System", "Thread", "ThreadGroup", "ThreadLocal", "Throwable", "Void" };
for (String s : java) { for (String s : java) {
JAVA_IMPORT_MAP.put(s, "java.lang." + s); JAVA_IMPORT_MAP.put(s, "java.lang." + s);
addBuiltInType(false, "java.lang." + s); addBuiltInType(id++, false, "java.lang." + s);
} }
firstClassId = id;
} }
private static void addBuiltInType(boolean primitive, String type) { private static void addBuiltInType(int id, boolean primitive, String type) {
ClassObj typeObj = new ClassObj(); ClassObj typeObj = new ClassObj();
typeObj.id = id;
typeObj.name = type; typeObj.name = type;
typeObj.isPrimitive = primitive; typeObj.isPrimitive = primitive;
BUILT_IN_TYPES.put(type, typeObj); BUILT_IN_TYPES.put(type, typeObj);
...@@ -134,6 +141,7 @@ public class JavaParser { ...@@ -134,6 +141,7 @@ public class JavaParser {
} }
while (true) { while (true) {
classObj = new ClassObj(); classObj = new ClassObj();
classObj.id = classId++;
classObj.isPublic = readIf("public"); classObj.isPublic = readIf("public");
if (readIf("class")) { if (readIf("class")) {
classObj.isInterface = false; classObj.isInterface = false;
...@@ -196,7 +204,7 @@ public class JavaParser { ...@@ -196,7 +204,7 @@ public class JavaParser {
private void parseClassBody() { private void parseClassBody() {
read("{"); read("{");
localFields.clear(); localVars.clear();
while (true) { while (true) {
if (readIf("}")) { if (readIf("}")) {
break; break;
...@@ -231,10 +239,10 @@ public class JavaParser { ...@@ -231,10 +239,10 @@ public class JavaParser {
} }
} }
if (readIf("{")) { if (readIf("{")) {
MethodObj method = new MethodObj(); method = new MethodObj();
method.name = isStatic ? "cl_init_obj" : "init_obj"; method.name = isStatic ? "cl_init_obj" : "init_obj";
method.isStatic = isStatic; method.isStatic = isStatic;
localFields.clear(); localVars.clear();
if (!isStatic) { if (!isStatic) {
initThisPointer(); initThisPointer();
} }
...@@ -243,14 +251,14 @@ public class JavaParser { ...@@ -243,14 +251,14 @@ public class JavaParser {
} else { } else {
String typeName = readTypeOrIdentifier(); String typeName = readTypeOrIdentifier();
Type type = readType(typeName); Type type = readType(typeName);
MethodObj method = new MethodObj(); method = new MethodObj();
method.returnType = type; method.returnType = type;
method.isStatic = isStatic; method.isStatic = isStatic;
method.isFinal = isFinal; method.isFinal = isFinal;
method.isPublic = isPublic; method.isPublic = isPublic;
method.isPrivate = isPrivate; method.isPrivate = isPrivate;
method.isNative = isNative; method.isNative = isNative;
localFields.clear(); localVars.clear();
if (!isStatic) { if (!isStatic) {
initThisPointer(); initThisPointer();
} }
...@@ -259,7 +267,8 @@ public class JavaParser { ...@@ -259,7 +267,8 @@ public class JavaParser {
throw getSyntaxException("Constructor of wrong type: " + type); throw getSyntaxException("Constructor of wrong type: " + type);
} }
method.name = "init_obj"; method.name = "init_obj";
parseFormalParameters(method); method.isConstructor = true;
parseFormalParameters();
if (!readIf(";")) { if (!readIf(";")) {
method.block = readStatement(); method.block = readStatement();
} }
...@@ -268,7 +277,7 @@ public class JavaParser { ...@@ -268,7 +277,7 @@ public class JavaParser {
String name = readIdentifier(); String name = readIdentifier();
method.name = name; method.name = name;
if (readIf("(")) { if (readIf("(")) {
parseFormalParameters(method); parseFormalParameters();
if (!readIf(";")) { if (!readIf(";")) {
method.block = readStatement(); method.block = readStatement();
} }
...@@ -317,7 +326,7 @@ public class JavaParser { ...@@ -317,7 +326,7 @@ public class JavaParser {
return type; return type;
} }
private void parseFormalParameters(MethodObj method) { private void parseFormalParameters() {
if (readIf(")")) { if (readIf(")")) {
return; return;
} }
...@@ -327,7 +336,7 @@ public class JavaParser { ...@@ -327,7 +336,7 @@ public class JavaParser {
String typeName = readTypeOrIdentifier(); String typeName = readTypeOrIdentifier();
field.type = readType(typeName); field.type = readType(typeName);
field.name = readIdentifier(); field.name = readIdentifier();
method.parameters.add(field); method.parameters.put(field.name, field);
if (readIf(")")) { if (readIf(")")) {
break; break;
} }
...@@ -504,7 +513,7 @@ public class JavaParser { ...@@ -504,7 +513,7 @@ public class JavaParser {
f.isLocal = true; f.isLocal = true;
f.type = dec.type; f.type = dec.type;
f.name = varName; f.name = varName;
localFields.put(varName, f); localVars.put(varName, f);
dec.variables.add(varName); dec.variables.add(varName);
dec.values.add(value); dec.values.add(value);
if (readIf(";")) { if (readIf(";")) {
...@@ -708,7 +717,9 @@ public class JavaParser { ...@@ -708,7 +717,9 @@ public class JavaParser {
} }
String name = readIdentifier(); String name = readIdentifier();
if (readIf("(")) { if (readIf("(")) {
CallExpr expr = new CallExpr(this, null, classObj.name, name, false); VariableExpr t = new VariableExpr();
t.field = thisPointer;
CallExpr expr = new CallExpr(this, t, classObj.name, name, false);
if (!readIf(")")) { if (!readIf(")")) {
while (true) { while (true) {
expr.args.add(readExpr()); expr.args.add(readExpr());
...@@ -721,48 +732,50 @@ public class JavaParser { ...@@ -721,48 +732,50 @@ public class JavaParser {
return expr; return expr;
} }
VariableExpr expr = new VariableExpr(); VariableExpr expr = new VariableExpr();
FieldObj f = localFields.get(name); FieldObj f = localVars.get(name);
if (f == null) {
f = method.parameters.get(name);
}
if (f == null) { if (f == null) {
f = classObj.staticFields.get(name); f = classObj.staticFields.get(name);
if (f == null) { }
f = classObj.instanceFields.get(name); if (f == null) {
if (f == null) { f = classObj.instanceFields.get(name);
String imp = importMap.get(name); }
if (imp == null) { if (f == null) {
imp = JAVA_IMPORT_MAP.get(name); String imp = importMap.get(name);
} if (imp == null) {
if (imp != null) { imp = JAVA_IMPORT_MAP.get(name);
name = imp; }
if (readIf(".")) { if (imp != null) {
String n = readIdentifier(); name = imp;
if (readIf("(")) { if (readIf(".")) {
CallExpr e2 = new CallExpr(this, null, imp, n, true); String n = readIdentifier();
if (!readIf(")")) { if (readIf("(")) {
while (true) { CallExpr e2 = new CallExpr(this, null, imp, n, true);
e2.args.add(readExpr()); if (!readIf(")")) {
if (!readIf(",")) { while (true) {
read(")"); e2.args.add(readExpr());
break; if (!readIf(",")) {
} read(")");
} break;
} }
return e2;
} }
VariableExpr e2 = new VariableExpr();
// static member variable
e2.name = imp + "." + n;
ClassObj c = classes.get(imp);
FieldObj sf = c.staticFields.get(n);
e2.field = sf;
return e2;
} }
// TODO static field or method of a class return e2;
} }
} else { VariableExpr e2 = new VariableExpr();
expr.field = f; // static member variable
e2.name = imp + "." + n;
ClassObj c = classes.get(imp);
FieldObj sf = c.staticFields.get(n);
e2.field = sf;
return e2;
} }
// TODO static field or method of a class
} }
} }
expr.field = f;
if (f != null && (!f.isLocal && !f.isStatic)) { if (f != null && (!f.isLocal && !f.isStatic)) {
VariableExpr ve = new VariableExpr(); VariableExpr ve = new VariableExpr();
ve.field = thisPointer; ve.field = thisPointer;
...@@ -783,7 +796,7 @@ public class JavaParser { ...@@ -783,7 +796,7 @@ public class JavaParser {
private String readQualifiedIdentifier() { private String readQualifiedIdentifier() {
String id = readIdentifier(); String id = readIdentifier();
if (localFields.containsKey(id)) { if (localVars.containsKey(id)) {
return id; return id;
} }
if (classObj != null) { if (classObj != null) {
...@@ -1209,11 +1222,11 @@ public class JavaParser { ...@@ -1209,11 +1222,11 @@ public class JavaParser {
for (MethodObj m : c.methods.values()) { for (MethodObj m : c.methods.values()) {
out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic) { if (!m.isStatic && !m.isConstructor) {
out.print(toC(c.name) + "* this"); out.print(toC(c.name) + "* this");
i++; i++;
} }
for (FieldObj p : m.parameters) { for (FieldObj p : m.parameters.values()) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
} }
...@@ -1249,11 +1262,11 @@ public class JavaParser { ...@@ -1249,11 +1262,11 @@ public class JavaParser {
for (MethodObj m : c.methods.values()) { for (MethodObj m : c.methods.values()) {
out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic) { if (!m.isStatic && !m.isConstructor) {
out.print(toC(c.name) + "* this"); out.print(toC(c.name) + "* this");
i++; i++;
} }
for (FieldObj p : m.parameters) { for (FieldObj p : m.parameters.values()) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
} }
...@@ -1261,6 +1274,9 @@ public class JavaParser { ...@@ -1261,6 +1274,9 @@ public class JavaParser {
i++; i++;
} }
out.println(") {"); out.println(") {");
if (m.isConstructor) {
out.println(indent(toC(c.name) + "* this = NEW_OBJ(" + c.id + ", " + toC(c.name) +");"));
}
if (m.block != null) { if (m.block != null) {
out.print(m.block.toString()); out.print(m.block.toString());
} }
......
...@@ -77,7 +77,7 @@ class SwitchStatement implements Statement { ...@@ -77,7 +77,7 @@ class SwitchStatement implements Statement {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append("switch (").append(expr).append(") {\n"); buff.append("switch (").append(expr).append(") {\n");
for (int i = 0; i < cases.size(); i++) { for (int i = 0; i < cases.size(); i++) {
buff.append("case: " + cases.get(i) + ":\n"); buff.append("case " + cases.get(i) + ":\n");
buff.append(blocks.get(i).toString()); buff.append(blocks.get(i).toString());
} }
if (defaultBlock != null) { if (defaultBlock != null) {
...@@ -148,7 +148,7 @@ class ForStatement implements Statement { ...@@ -148,7 +148,7 @@ class ForStatement implements Statement {
Type it = iterable.getType(); Type it = iterable.getType();
if (it != null && it.arrayLevel > 0) { if (it != null && it.arrayLevel > 0) {
String idx = "i_" + iterableVariable; String idx = "i_" + iterableVariable;
buff.append("int " + idx + " = 0; " + idx + " < LEN(" + iterable + "); " + idx + "++"); buff.append("int " + idx + " = 0; " + idx + " < LENGTH(" + iterable + "); " + idx + "++");
buff.append(") {\n"); buff.append(") {\n");
buff.append(JavaParser.indent(iterableType + " " + iterableVariable + " = " + iterable + "["+ idx +"];\n")); buff.append(JavaParser.indent(iterableType + " " + iterableVariable + " = " + iterable + "["+ idx +"];\n"));
buff.append(block.toString()).append("}"); buff.append(block.toString()).append("}");
......
...@@ -26,6 +26,9 @@ public class Test extends TestBase { ...@@ -26,6 +26,9 @@ public class Test extends TestBase {
} }
public void test() throws IOException { public void test() throws IOException {
// gcc --std=c99 test.c
// (for "mixed declarations and code")
// not supported yet: // not supported yet:
// HexadecimalFloatingPointLiteral // HexadecimalFloatingPointLiteral
// int x()[] { return null; } // int x()[] { return null; }
......
...@@ -9,10 +9,15 @@ package org.h2.java; ...@@ -9,10 +9,15 @@ package org.h2.java;
/** /**
* A test application. * A test application.
*/ */
/// #include <stdio.h>
public class TestApp { public class TestApp {
// private static final int FINAL_VALUE = 10; /* c:
int main(char** args) {
org_h2_java_TestApp_main(null);
}
*/
/** /**
* Run this application. * Run this application.
......
...@@ -2,17 +2,33 @@ package org.h2.java.lang; ...@@ -2,17 +2,33 @@ package org.h2.java.lang;
/* c: /* c:
#define boolean int #include <stdlib.h>
#include <stdio.h>
#define LENGTH(a) (*(((int*)(a))-1)) #include <string.h>
#define jvoid void
#define jboolean int8_t
#define jbyte int8_t
#define jchar int16_t
#define jint int32_t
#define jlong int64_t
#define jfloat float
#define jdouble double
#define true 1
#define false 0
#define null 0
#define LENGTH(a) (*(((jint*)(a))-1))
#define NEW_ARRAY(size, length) new_array(0, size, length) #define NEW_ARRAY(size, length) new_array(0, size, length)
#define NEW_OBJ_ARRAY(length) new_array(1, sizeof(void*), length) #define NEW_OBJ_ARRAY(length) new_array(1, sizeof(void*), length)
#define NEW_OBJ(type, size) new_object(type, sizeof(struct type)) #define NEW_OBJ(typeId, typeName) new_object(typeId, sizeof(struct typeName))
#define SET(variable, p) set_object(variable, p) #define SET(variable, p) set_object(variable, p)
#define STRING(s) ((java_lang_String*) string(s))
void* new_array(int object, int size, int length); void* new_array(jint object, jint size, jint length);
void* new_object(int type, int size); void* new_object(jint type, jint size);
void* set_object(void** target, void* o); void* set_object(void** target, void* o);
void* string(char* s);
*/ */
...@@ -23,38 +39,45 @@ public class String { ...@@ -23,38 +39,45 @@ public class String {
/* c: /* c:
#include <stdlib.h> void* new_array(jint object, jint size, jint length) {
int count = sizeof(jint) * 2 + size * length;
void* new_array(int object, int size, int length) { int* m = (jint*) calloc(1, count);
int count = sizeof(int) * 2 + size * length;
int* m = (int*) calloc(1, count);
*m = object << 31 + length; *m = object << 31 + length;
*(m+1) = 1; *(m+1) = 1;
return m + 2; return m + 2;
} }
void* new_object(int type, int size) { void* new_object(jint type, jint size) {
int count = sizeof(int) * 2 + size; int count = sizeof(jint) * 2 + size;
int* m = (int*) calloc(1, count); int* m = (jint*) calloc(1, count);
*m = type; *m = type;
*(m+1) = 1; *(m+1) = 1;
return m + 2; return m + 2;
} }
void* set_object(void** target, void* o) { void* set_object(void** target, void* o) {
int* m = (int*) target; int* m = (jint*) target;
if (*(m - 2) == 1) { if (*(m - 2) == 1) {
free(m - 1); free(m - 1);
} else { } else {
(*(m - 2))--; (*(m - 2))--;
} }
*target = o; *target = o;
m = (int*) target; m = (jint*) target;
if (o != 0) { if (o != 0) {
(*(m - 2))++; (*(m - 2))++;
} }
} }
void* string(char* s) {
int len = strlen(s);
jchar* chars = NEW_ARRAY(sizeof(char), 1 * LENGTH(chars));
for (int i = 0; i < len; i++) {
chars[i] = s[i];
}
return java_lang_String_init_obj(chars);
}
*/ */
private char[] chars; private char[] chars;
......
...@@ -7,8 +7,6 @@ import java.io.PrintStream; ...@@ -7,8 +7,6 @@ import java.io.PrintStream;
*/ */
public class System { public class System {
// c: #include <stdio>
/** /**
* The stdout stream. * The stdout stream.
*/ */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论