提交 0163a2a2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Java to C converter (moving forward C++ will be used)

上级 b8c6a437
...@@ -204,6 +204,11 @@ class MethodObj { ...@@ -204,6 +204,11 @@ class MethodObj {
*/ */
boolean isVirtual; boolean isVirtual;
/**
* Whether this method is to be ignored (using the Ignore annotation).
*/
boolean isIgnore;
/** /**
* The name. * The name.
*/ */
...@@ -285,6 +290,11 @@ class FieldObj { ...@@ -285,6 +290,11 @@ class FieldObj {
*/ */
boolean isPublic; boolean isPublic;
/**
* Whether this method is to be ignored (using the Ignore annotation).
*/
boolean isIgnore;
/** /**
* The initial value expression (may be null). * The initial value expression (may be null).
*/ */
...@@ -317,6 +327,15 @@ class Type { ...@@ -317,6 +327,15 @@ class Type {
*/ */
boolean isVarArgs; boolean isVarArgs;
/**
* Whether this is a non-array primitive type.
*
* @return true if yes
*/
public boolean isSimplePrimitive() {
return arrayLevel == 0 && classObj.isPrimitive;
}
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toC(classObj.toString())); buff.append(JavaParser.toC(classObj.toString()));
......
...@@ -54,6 +54,16 @@ class CallExpr implements Expr { ...@@ -54,6 +54,16 @@ class CallExpr implements Expr {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
String methodName; String methodName;
initMethod(); initMethod();
if (method.isIgnore) {
if (args.size() == 0) {
// ignore
} else if (args.size() == 1) {
buff.append(args.get(0));
} else {
throw new IllegalArgumentException(
"Cannot ignore method with multiple arguments: " + method);
}
} else {
if (method.isVirtual) { if (method.isVirtual) {
methodName = "virtual_" + method.name + "[CLASS_ID("+expr.toString()+")]"; methodName = "virtual_" + method.name + "[CLASS_ID("+expr.toString()+")]";
} else { } else {
...@@ -72,7 +82,9 @@ class CallExpr implements Expr { ...@@ -72,7 +82,9 @@ class CallExpr implements Expr {
i++; i++;
buff.append(a); buff.append(a);
} }
return buff.append(")").toString(); buff.append(")");
}
return buff.toString();
} }
public Type getType() { public Type getType() {
...@@ -92,12 +104,17 @@ class AssignExpr implements Expr { ...@@ -92,12 +104,17 @@ class AssignExpr implements Expr {
Expr right; Expr right;
public String toString() { public String toString() {
if (left.getType().isSimplePrimitive()) {
return left + " " + op + " " + right; return left + " " + op + " " + right;
} }
if (right.toString().equals("null")) {
return "release(" + left + ")";
}
return left + " = set(" + left + ", " + right + ")";
}
public Type getType() { public Type getType() {
// TODO return left.getType();
return null;
} }
} }
...@@ -115,8 +132,7 @@ class ConditionalExpr implements Expr { ...@@ -115,8 +132,7 @@ class ConditionalExpr implements Expr {
} }
public Type getType() { public Type getType() {
// TODO return ifTrue.getType();
return null;
} }
} }
...@@ -288,6 +304,11 @@ class NewExpr implements Expr { ...@@ -288,6 +304,11 @@ class NewExpr implements Expr {
*/ */
class StringExpr implements Expr { class StringExpr implements Expr {
/**
* The constant name.
*/
String constantName;
/** /**
* The literal. * The literal.
*/ */
...@@ -301,7 +322,7 @@ class StringExpr implements Expr { ...@@ -301,7 +322,7 @@ class StringExpr implements Expr {
} }
public String toString() { public String toString() {
return "STRING(\"" + javaEncode(text) + "\")"; return constantName;
} }
public Type getType() { public Type getType() {
...@@ -407,13 +428,16 @@ class VariableExpr implements Expr { ...@@ -407,13 +428,16 @@ class VariableExpr implements Expr {
private void init() { private void init() {
if (field == null) { if (field == null) {
if (base == null) {
System.out.println("??");
}
Type t = base.getType(); Type t = base.getType();
if (t.arrayLevel > 0) { if (t.arrayLevel > 0) {
if ("length".equals(name)) { if ("length".equals(name)) {
field = new FieldObj(); field = new FieldObj();
field.type = context.getClassObj("int").baseType; field.type = context.getClassObj("int").baseType;
} else { } else {
throw new RuntimeException("Unknown array method: " + name); throw new IllegalArgumentException("Unknown array method: " + name);
} }
} else { } else {
field = t.classObj.getField(name); field = t.classObj.getField(name);
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.java;
/**
* This annotation marks methods that are only needed for testing.
*/
public @interface Ignore {
// empty
}
...@@ -11,9 +11,11 @@ import java.io.PrintWriter; ...@@ -11,9 +11,11 @@ import java.io.PrintWriter;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import org.h2.util.New;
/** /**
* Converts Java to C. * Converts Java to C.
...@@ -27,11 +29,11 @@ public class JavaParser { ...@@ -27,11 +29,11 @@ public class JavaParser {
private static final int TOKEN_IDENTIFIER = 4; private static final int TOKEN_IDENTIFIER = 4;
private static final int TOKEN_OTHER = 5; private static final int TOKEN_OTHER = 5;
private static final HashSet<String> RESERVED = new HashSet<String>(); private static final HashSet<String> RESERVED = New.hashSet();
private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>(); private static final HashMap<String, String> JAVA_IMPORT_MAP = New.hashMap();
private final ArrayList<ClassObj> allClasses = new ArrayList<ClassObj>(); private final ArrayList<ClassObj> allClasses = New.arrayList();
private final HashMap<String, ClassObj> builtInTypes = new HashMap<String, ClassObj>(); private final HashMap<String, ClassObj> builtInTypes = New.hashMap();
private String source; private String source;
...@@ -42,12 +44,15 @@ public class JavaParser { ...@@ -42,12 +44,15 @@ public class JavaParser {
private int nextClassId; private int nextClassId;
private MethodObj method; 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();
private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>(); private HashMap<String, ClassObj> classes = New.hashMap();
private LinkedHashMap<String, FieldObj> localVars = new LinkedHashMap<String, FieldObj>(); private LinkedHashMap<String, FieldObj> localVars = new LinkedHashMap<String, FieldObj>();
private HashMap<String, MethodObj> allMethodsMap = new HashMap<String, MethodObj>(); private HashMap<String, MethodObj> allMethodsMap = New.hashMap();
private ArrayList<Statement> nativeHeaders = new ArrayList<Statement>(); private ArrayList<Statement> nativeHeaders = New.arrayList();
private HashMap<String, String> stringToStringConstantMap = New.hashMap();
private HashMap<String, String> stringConstantToStringMap = New.hashMap();
public JavaParser() { public JavaParser() {
addBuiltInTypes(); addBuiltInTypes();
...@@ -279,6 +284,12 @@ public class JavaParser { ...@@ -279,6 +284,12 @@ public class JavaParser {
classObj.nativeCode.add(s); classObj.nativeCode.add(s);
} }
thisPointer = null; thisPointer = null;
HashSet<String> annotations = New.hashSet();
while (readIf("@")) {
String annotation = readIdentifier();
annotations.add(annotation);
}
boolean isIgnore = annotations.contains("Ignore");
boolean isStatic = false; boolean isStatic = false;
boolean isFinal = false; boolean isFinal = false;
boolean isPrivate = false; boolean isPrivate = false;
...@@ -301,6 +312,7 @@ public class JavaParser { ...@@ -301,6 +312,7 @@ public class JavaParser {
} }
if (readIf("{")) { if (readIf("{")) {
method = new MethodObj(); method = new MethodObj();
method.isIgnore = isIgnore;
method.name = isStatic ? "cl_init_obj" : "init_obj"; method.name = isStatic ? "cl_init_obj" : "init_obj";
method.isStatic = isStatic; method.isStatic = isStatic;
localVars.clear(); localVars.clear();
...@@ -313,6 +325,7 @@ public class JavaParser { ...@@ -313,6 +325,7 @@ public class JavaParser {
String typeName = readTypeOrIdentifier(); String typeName = readTypeOrIdentifier();
Type type = readType(typeName); Type type = readType(typeName);
method = new MethodObj(); method = new MethodObj();
method.isIgnore = isIgnore;
method.returnType = type; method.returnType = type;
method.isStatic = isStatic; method.isStatic = isStatic;
method.isFinal = isFinal; method.isFinal = isFinal;
...@@ -347,6 +360,7 @@ public class JavaParser { ...@@ -347,6 +360,7 @@ public class JavaParser {
addMethod(method); addMethod(method);
} else { } else {
FieldObj field = new FieldObj(); FieldObj field = new FieldObj();
field.isIgnore = isIgnore;
field.type = type; field.type = type;
field.name = name; field.name = name;
field.isStatic = isStatic; field.isStatic = isStatic;
...@@ -354,11 +368,6 @@ public class JavaParser { ...@@ -354,11 +368,6 @@ public class JavaParser {
field.isPublic = isPublic; field.isPublic = isPublic;
field.isPrivate = isPrivate; field.isPrivate = isPrivate;
field.declaredClass = classObj; field.declaredClass = classObj;
if (isStatic) {
classObj.addStaticField(field);
} else {
classObj.addInstanceField(field);
}
if (readIf("=")) { if (readIf("=")) {
if (field.type.arrayLevel > 0 && readIf("{")) { if (field.type.arrayLevel > 0 && readIf("{")) {
field.value = readArrayInit(field.type); field.value = readArrayInit(field.type);
...@@ -367,6 +376,11 @@ public class JavaParser { ...@@ -367,6 +376,11 @@ public class JavaParser {
} }
} }
read(";"); read(";");
if (isStatic) {
classObj.addStaticField(field);
} else {
classObj.addInstanceField(field);
}
} }
} }
} }
...@@ -409,7 +423,7 @@ public class JavaParser { ...@@ -409,7 +423,7 @@ public class JavaParser {
private void initThisPointer() { private void initThisPointer() {
thisPointer = new FieldObj(); thisPointer = new FieldObj();
thisPointer.isLocal = true; thisPointer.isLocal = true;
thisPointer.name = "this"; thisPointer.name = "thiz";
thisPointer.type = new Type(); thisPointer.type = new Type();
thisPointer.type.classObj = classObj; thisPointer.type.classObj = classObj;
} }
...@@ -464,7 +478,7 @@ public class JavaParser { ...@@ -464,7 +478,7 @@ public class JavaParser {
private Statement readNativeStatementIf() { private Statement readNativeStatementIf() {
if (readIf("//")) { if (readIf("//")) {
read(); boolean isC = readIdentifierIf("c");
int start = current.index; int start = current.index;
while (source.charAt(current.index) != '\n') { while (source.charAt(current.index) != '\n') {
current.index++; current.index++;
...@@ -472,9 +486,9 @@ public class JavaParser { ...@@ -472,9 +486,9 @@ public class JavaParser {
StatementNative stat = new StatementNative(); StatementNative stat = new StatementNative();
stat.code = source.substring(start, current.index).trim(); stat.code = source.substring(start, current.index).trim();
read(); read();
return stat; return isC ? stat : null;
} else if (readIf("/*")) { } else if (readIf("/*")) {
read(); boolean isC = readIdentifierIf("c");
int start = current.index; int start = current.index;
while (source.charAt(current.index) != '*' || source.charAt(current.index + 1) != '/') { while (source.charAt(current.index) != '*' || source.charAt(current.index + 1) != '/') {
current.index++; current.index++;
...@@ -483,7 +497,7 @@ public class JavaParser { ...@@ -483,7 +497,7 @@ public class JavaParser {
stat.code = source.substring(start, current.index).trim(); stat.code = source.substring(start, current.index).trim();
current.index += 2; current.index += 2;
read(); read();
return stat; return isC ? stat : null;
} }
return null; return null;
} }
...@@ -745,23 +759,30 @@ public class JavaParser { ...@@ -745,23 +759,30 @@ public class JavaParser {
LiteralExpr expr = new LiteralExpr(this, "boolean"); LiteralExpr expr = new LiteralExpr(this, "boolean");
expr.literal = "false"; expr.literal = "false";
return expr; return expr;
} } else if (readIf("true")) {
if (readIf("true")) {
LiteralExpr expr = new LiteralExpr(this, "boolean"); LiteralExpr expr = new LiteralExpr(this, "boolean");
expr.literal = "true"; expr.literal = "true";
return expr; return expr;
} } else if (readIf("null")) {
if (readIf("null")) {
LiteralExpr expr = new LiteralExpr(this, "java.lang.Object"); LiteralExpr expr = new LiteralExpr(this, "java.lang.Object");
expr.literal = "null"; expr.literal = "null";
return expr; return expr;
} } else if (current.type == TOKEN_LITERAL_NUMBER) {
if (current.type == TOKEN_LITERAL_NUMBER) {
// TODO or long, float, double // TODO or long, float, double
LiteralExpr expr = new LiteralExpr(this, "int"); LiteralExpr expr = new LiteralExpr(this, "int");
expr.literal = current.token.substring(1); expr.literal = current.token.substring(1);
readToken(); readToken();
return expr; return expr;
} else if (current.type == TOKEN_LITERAL_CHAR) {
LiteralExpr expr = new LiteralExpr(this, "char");
expr.literal = current.token + "'";
readToken();
return expr;
} else if (current.type == TOKEN_LITERAL_STRING) {
String text = current.token.substring(1);
StringExpr expr = getStringConstant(text);
readToken();
return expr;
} }
Expr expr; Expr expr;
expr = readExpr5(); expr = readExpr5();
...@@ -799,6 +820,47 @@ public class JavaParser { ...@@ -799,6 +820,47 @@ public class JavaParser {
return expr; return expr;
} }
private StringExpr getStringConstant(String s) {
String c = stringToStringConstantMap.get(s);
if (c == null) {
StringBuilder buff = new StringBuilder();
for (int i = 0; i < s.length() && i < 16; i++) {
char ch = s.charAt(i);
if (ch >= 'a' && ch <= 'z') {
// don't use Character.toUpperCase
// to avoid locale problems
// (the uppercase of i isn't always I)
buff.append((char) (ch + 'A' - 'a'));
} else if (ch >= 'A' && ch <= 'Z') {
buff.append(ch);
} else if (ch == '_' || ch == ' ') {
buff.append('_');
}
}
c = buff.toString();
if (c.length() == 0 || stringConstantToStringMap.containsKey(c)) {
if (c.length() == 0) {
c = "X";
}
int i = 2;
for (;; i++) {
String c2 = c + "_" + i;
if (!stringConstantToStringMap.containsKey(c2)) {
c = c2;
break;
}
}
}
c = "STRING_" + c;
stringToStringConstantMap.put(s, c);
stringConstantToStringMap.put(c, s);
}
StringExpr expr = new StringExpr(this);
expr.text = s;
expr.constantName = c;
return expr;
}
private Expr readExpr5() { private Expr readExpr5() {
if (readIf("new")) { if (readIf("new")) {
NewExpr expr = new NewExpr(this); NewExpr expr = new NewExpr(this);
...@@ -822,12 +884,6 @@ public class JavaParser { ...@@ -822,12 +884,6 @@ public class JavaParser {
} }
return expr; return expr;
} }
if (current.type == TOKEN_LITERAL_STRING) {
StringExpr expr = new StringExpr(this);
expr.text = current.token.substring(1);
readToken();
return expr;
}
if (readIf("this")) { if (readIf("this")) {
VariableExpr expr = new VariableExpr(this); VariableExpr expr = new VariableExpr(this);
expr.field = thisPointer; expr.field = thisPointer;
...@@ -947,6 +1003,14 @@ public class JavaParser { ...@@ -947,6 +1003,14 @@ public class JavaParser {
return result; return result;
} }
private boolean readIdentifierIf(String token) {
if (current.type == TOKEN_IDENTIFIER && token.equals(current.token)) {
readToken();
return true;
}
return false;
}
private boolean readIf(String token) { private boolean readIf(String token) {
if (current.type != TOKEN_IDENTIFIER && token.equals(current.token)) { if (current.type != TOKEN_IDENTIFIER && token.equals(current.token)) {
readToken(); readToken();
...@@ -1123,6 +1187,7 @@ public class JavaParser { ...@@ -1123,6 +1187,7 @@ public class JavaParser {
case ',': case ',':
case '?': case '?':
case ':': case ':':
case '@':
break; break;
case '.': case '.':
if (source.charAt(current.index) == '.' && source.charAt(current.index + 1) == '.') { if (source.charAt(current.index) == '.' && source.charAt(current.index + 1) == '.') {
...@@ -1159,7 +1224,8 @@ public class JavaParser { ...@@ -1159,7 +1224,8 @@ public class JavaParser {
} }
break; break;
case '/': case '/':
if (source.charAt(current.index) == '*' || source.charAt(current.index) == '/') { if (source.charAt(current.index) == '*' || source.charAt(current.index) == '/'
|| source.charAt(current.index) == '=') {
current.index++; current.index++;
} }
break; break;
...@@ -1318,7 +1384,9 @@ public class JavaParser { ...@@ -1318,7 +1384,9 @@ public class JavaParser {
} }
out.println(); out.println();
for (ClassObj c : classes.values()) { for (ClassObj c : classes.values()) {
out.println("/* " + c.className + ".h */"); out.println("struct " + toC(c.className) + ";");
}
for (ClassObj c : classes.values()) {
for (FieldObj f : c.staticFields.values()) { for (FieldObj f : c.staticFields.values()) {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append("extern "); buff.append("extern ");
...@@ -1336,21 +1404,36 @@ public class JavaParser { ...@@ -1336,21 +1404,36 @@ public class JavaParser {
buff.append(";"); buff.append(";");
out.println(buff.toString()); out.println(buff.toString());
} }
out.println("struct " + toC(c.className) + " {"); out.println("typedef struct " + toC(c.className) + " {");
for (FieldObj f : c.instanceFields.values()) { for (FieldObj f : c.instanceFields.values()) {
out.print(" " + toC(f.type.toString()) + " " + f.name); out.print(" ");
if (!f.type.classObj.isPrimitive) {
out.print("struct ");
}
out.print(toC(f.type.toString()) + " " + f.name);
if (f.value != null) { if (f.value != null) {
out.print(" = " + f.value); out.print(" = " + f.value);
} }
out.println(";"); out.println(";");
} }
if (c.instanceFields.size() == 0) { if (c.instanceFields.size() == 0) {
out.println("int dummy;"); out.println(" int dummy;");
} }
out.println("};"); out.println("} " + toC(c.className) + ";");
out.println("typedef struct " + toC(c.className) + " " + toC(c.className) + ";"); }
ArrayList<String> constantNames = New.arrayList(stringConstantToStringMap.keySet());
Collections.sort(constantNames);
for (String c : constantNames) {
String s = stringConstantToStringMap.get(c);
out.println("const java_lang_String* " + c + " = STRING(\"" + s + "\");");
}
for (ClassObj c : classes.values()) {
out.println("/* " + c.className + " */");
for (ArrayList<MethodObj> list : c.methods.values()) { for (ArrayList<MethodObj> list : c.methods.values()) {
for (MethodObj m : list) { for (MethodObj m : list) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic && !m.isConstructor) { if (!m.isStatic && !m.isConstructor) {
...@@ -1398,6 +1481,9 @@ public class JavaParser { ...@@ -1398,6 +1481,9 @@ public class JavaParser {
void writeSource(PrintWriter out) { void writeSource(PrintWriter out) {
out.println("/* method pointers */"); out.println("/* method pointers */");
for (MethodObj m : allMethodsMap.values()) { for (MethodObj m : allMethodsMap.values()) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " (*virtual_" + m.name + "[])("); out.print(m.returnType + " (*virtual_" + m.name + "[])(");
int i = 0; int i = 0;
if (!m.isConstructor) { if (!m.isConstructor) {
...@@ -1448,6 +1534,9 @@ public class JavaParser { ...@@ -1448,6 +1534,9 @@ public class JavaParser {
} }
for (ArrayList<MethodObj> list : c.methods.values()) { for (ArrayList<MethodObj> list : c.methods.values()) {
for (MethodObj m : list) { for (MethodObj m : list) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic && !m.isConstructor) { if (!m.isStatic && !m.isConstructor) {
......
...@@ -13,66 +13,93 @@ import java.util.ArrayList; ...@@ -13,66 +13,93 @@ import java.util.ArrayList;
*/ */
public interface Statement { public interface Statement {
boolean isEnd();
// toString // toString
} }
/**
* The base class for statements.
*/
abstract class StatementBase implements Statement {
public boolean isEnd() {
return false;
}
}
/** /**
* A "return" statement. * A "return" statement.
*/ */
class ReturnStatement implements Statement { class ReturnStatement extends StatementBase {
Expr expr; Expr expr;
public String toString() { public String toString() {
return "return " + (expr == null ? "" : expr) + ";"; return "return " + (expr == null ? "" : expr) + ";";
} }
} }
/** /**
* A "do .. while" statement. * A "do .. while" statement.
*/ */
class DoWhileStatement implements Statement { class DoWhileStatement extends StatementBase {
Expr condition; Expr condition;
Statement block; Statement block;
public String toString() { public String toString() {
return "do {\n" + block + "} while (" + condition + ");"; return "do {\n" + block + "} while (" + condition + ");";
} }
} }
/** /**
* A "continue" statement. * A "continue" statement.
*/ */
class ContinueStatement implements Statement { class ContinueStatement extends StatementBase {
public String toString() { public String toString() {
return "continue;"; return "continue;";
} }
} }
/** /**
* A "break" statement. * A "break" statement.
*/ */
class BreakStatement implements Statement { class BreakStatement extends StatementBase {
public String toString() { public String toString() {
return "break;"; return "break;";
} }
} }
/** /**
* An empty statement. * An empty statement.
*/ */
class EmptyStatement implements Statement { class EmptyStatement extends StatementBase {
public String toString() { public String toString() {
return ";"; return ";";
} }
} }
/** /**
* A "switch" statement. * A "switch" statement.
*/ */
class SwitchStatement implements Statement { class SwitchStatement extends StatementBase {
Expr expr; Expr expr;
StatementBlock defaultBlock; StatementBlock defaultBlock;
ArrayList<Expr> cases = new ArrayList<Expr>(); ArrayList<Expr> cases = new ArrayList<Expr>();
ArrayList<StatementBlock> blocks = new ArrayList<StatementBlock>(); ArrayList<StatementBlock> blocks = new ArrayList<StatementBlock>();
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append("switch (").append(expr).append(") {\n"); buff.append("switch (").append(expr).append(") {\n");
...@@ -87,38 +114,47 @@ class SwitchStatement implements Statement { ...@@ -87,38 +114,47 @@ class SwitchStatement implements Statement {
buff.append("}"); buff.append("}");
return buff.toString(); return buff.toString();
} }
} }
/** /**
* An expression statement. * An expression statement.
*/ */
class ExprStatement implements Statement { class ExprStatement extends StatementBase {
Expr expr; Expr expr;
public String toString() { public String toString() {
return expr + ";"; return expr + ";";
} }
} }
/** /**
* A "while" statement. * A "while" statement.
*/ */
class WhileStatement implements Statement { class WhileStatement extends StatementBase {
Expr condition; Expr condition;
Statement block; Statement block;
public String toString() { public String toString() {
String w = "while (" + condition + ")"; String w = "while (" + condition + ")";
String s = block.toString(); String s = block.toString();
return w + "\n" + s; return w + "\n" + s;
} }
} }
/** /**
* An "if" statement. * An "if" statement.
*/ */
class IfStatement implements Statement { class IfStatement extends StatementBase {
Expr condition; Expr condition;
Statement block; Statement block;
Statement elseBlock; Statement elseBlock;
public String toString() { public String toString() {
String w = "if (" + condition + ") {\n"; String w = "if (" + condition + ") {\n";
String s = block.toString(); String s = block.toString();
...@@ -127,12 +163,14 @@ class IfStatement implements Statement { ...@@ -127,12 +163,14 @@ class IfStatement implements Statement {
} }
return w + s + "}"; return w + s + "}";
} }
} }
/** /**
* A "for" statement. * A "for" statement.
*/ */
class ForStatement implements Statement { class ForStatement extends StatementBase {
Statement init; Statement init;
Expr condition; Expr condition;
Expr update; Expr update;
...@@ -141,6 +179,7 @@ class ForStatement implements Statement { ...@@ -141,6 +179,7 @@ class ForStatement implements Statement {
Type iterableType; Type iterableType;
String iterableVariable; String iterableVariable;
Expr iterable; Expr iterable;
public String toString() { public String toString() {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
buff.append("for ("); buff.append("for (");
...@@ -174,54 +213,81 @@ class ForStatement implements Statement { ...@@ -174,54 +213,81 @@ class ForStatement implements Statement {
} }
return buff.toString(); return buff.toString();
} }
} }
/** /**
* A statement block. * A statement block.
*/ */
class StatementBlock implements Statement { class StatementBlock extends StatementBase {
ArrayList<Statement> instructions = new ArrayList<Statement>(); ArrayList<Statement> instructions = new ArrayList<Statement>();
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
for (Statement s : instructions) { for (Statement s : instructions) {
if (s.isEnd()) {
break;
}
buff.append(JavaParser.indent(s.toString())); buff.append(JavaParser.indent(s.toString()));
} }
return buff.toString(); return buff.toString();
} }
} }
/** /**
* A variable declaration. * A variable declaration.
*/ */
class VarDecStatement implements Statement { class VarDecStatement extends StatementBase {
Type type; Type type;
ArrayList<String> variables = new ArrayList<String>(); ArrayList<String> variables = new ArrayList<String>();
ArrayList<Expr> values = new ArrayList<Expr>(); ArrayList<Expr> values = new ArrayList<Expr>();
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(type).append(' '); buff.append(type).append(' ');
StringBuilder assign = new StringBuilder();
for (int i = 0; i < variables.size(); i++) { for (int i = 0; i < variables.size(); i++) {
if (i > 0) { if (i > 0) {
buff.append(", "); buff.append(", ");
} }
buff.append(variables.get(i)); String varName = variables.get(i);
buff.append(varName);
Expr value = values.get(i); Expr value = values.get(i);
if (value != null) { if (value != null) {
if (value.getType().isSimplePrimitive()) {
buff.append(" = ").append(value); buff.append(" = ").append(value);
} else {
assign.append(varName).append(" = reference(").append(value).append(");\n");
}
} }
} }
buff.append(";"); buff.append(";");
if (assign.length() > 0) {
buff.append("\n");
buff.append(assign);
}
return buff.toString(); return buff.toString();
} }
} }
/** /**
* A native statement. * A native statement.
*/ */
class StatementNative implements Statement { class StatementNative extends StatementBase {
String code; String code;
public String toString() { public String toString() {
return code; return code;
} }
public boolean isEnd() {
return code.equals("return;");
}
} }
...@@ -26,10 +26,14 @@ public class Test extends TestBase { ...@@ -26,10 +26,14 @@ public class Test extends TestBase {
} }
public void test() throws IOException { public void test() throws IOException {
// gcc --std=c99 test.c // gcc --std=c99 -o test test.cpp
// chmod +x test
// ./test
// (for "mixed declarations and code") // (for "mixed declarations and code")
// not supported yet: // not supported yet:
// exceptions
// HexadecimalFloatingPointLiteral // HexadecimalFloatingPointLiteral
// int x()[] { return null; } // int x()[] { return null; }
// annotations // annotations
......
...@@ -25,7 +25,11 @@ int main(int argc, char** argv) { ...@@ -25,7 +25,11 @@ int main(int argc, char** argv) {
* @param args the command line arguments * @param args the command line arguments
*/ */
public static void main(String... args) { public static void main(String... args) {
System.out.println("Hello " + "World" + 1); for (int i = 0; i < 10; i++) {
String s = "Hello " + i;
System.out.println(s);
s = null;
}
} }
} }
...@@ -11,6 +11,10 @@ package org.h2.java.lang; ...@@ -11,6 +11,10 @@ package org.h2.java.lang;
*/ */
public class Integer { public class Integer {
public static final int MIN_VALUE = 1 << 31;
public static final int MAX_VALUE = (int) ((1L << 31) - 1);
/** /**
* Convert a value to a String. * Convert a value to a String.
* *
...@@ -21,7 +25,32 @@ public class Integer { ...@@ -21,7 +25,32 @@ public class Integer {
// c: char ch[20]; // c: char ch[20];
// c: snprintf(ch, 20, "%d", x); // c: snprintf(ch, 20, "%d", x);
// c: return string(ch); // c: return string(ch);
return null; // c: return;
if (x == MIN_VALUE) {
return String.wrap("-2147483648");
}
char[] ch = new char[20];
int i = 20 - 1, count = 0;
boolean negative;
if (x < 0) {
negative = true;
x = -x;
} else {
negative = false;
}
for (; i >= 0; i--) {
ch[i] = (char) ('0' + (x % 10));
x /= 10;
count++;
if (x == 0) {
break;
}
}
if (negative) {
ch[--i] = '-';
count++;
}
return new String(ch, i, count);
} }
} }
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
*/ */
package org.h2.java.lang; package org.h2.java.lang;
import org.h2.java.Ignore;
/* c: /* c:
#include <stdlib.h> #include <stdlib.h>
...@@ -38,16 +40,24 @@ package org.h2.java.lang; ...@@ -38,16 +40,24 @@ package org.h2.java.lang;
void* new_array(jint object, jint size, jint length); void* new_array(jint object, jint size, jint length);
void* new_object(jint type, jint size); void* new_object(jint type, jint size);
void* set_object(void** target, void* o); void* reference(void* o);
void release(void* o);
void* set(void* o, void* n);
void* string(char* s); void* string(char* s);
*/ */
/* /*
* Object layout: * Object layout:
* m-3: arrays: length; otherwise not allocated * m-2: data type
* m-2: arrays: 0; otherwise type * m-1: number of references
* m: object data
*
* Array layout:
* m-3: length (number of elements)
* m-2: 0 (array marker)
* m-1: number of references * m-1: number of references
* m: first element
*/ */
/** /**
...@@ -57,25 +67,57 @@ public class String { ...@@ -57,25 +67,57 @@ public class String {
/* c: /* c:
void* new_array(jint object, jint size, jint length) { void* new_array_with_count(jint object, jint size, jint length, jint refCount) {
int count = sizeof(jint) * 3 + size * length; jint count = sizeof(jint) * 3 + size * length;
int* m = (jint*) calloc(1, count); jint* m = (jint*) calloc(1, count);
*m = length; *m = length;
*(m + 2) = 1; *(m + 2) = refCount;
return m + 3; return m + 3;
} }
void* new_object(jint type, jint size) { void* new_array(jint object, jint size, jint length) {
int count = sizeof(jint) * 2 + size; return new_array_with_count(object, size, length, 1);
int* m = (jint*) calloc(1, count); }
void* new_static_array(jint object, jint size, jint length) {
return new_array_with_count(object, size, length, 0);
}
void* new_object_with_count(jint type, jint size, jint refCount) {
jint count = sizeof(jint) * 2 + size;
jint* m = (jint*) calloc(1, count);
*m = type; *m = type;
*(m + 1) = 1; *(m + 1) = refCount;
return m + 2; return m + 2;
} }
void* set_object(void** target, void* o) { void* new_object(jint type, jint size) {
int* m = (jint*) target; return new_object_with_count(type, size, 1);
if (*(m - 1) == 1) { }
void* new_static_object(jint type, jint size) {
return new_object_with_count(type, size, 0);
}
void* reference(void* o) {
if (o != 0) {
jint* m = (jint*) o;
if (*(m - 1) > 0) {
(*(m - 1))++;
}
}
return o;
}
void release(void* o) {
if (o == 0) {
return;
}
jint* m = (jint*) o;
if (*(m - 1) <= 1) {
if (*(m - 1) == 0) {
return;
}
if (*(m - 2) == 0) { if (*(m - 2) == 0) {
free(m - 3); free(m - 3);
} else { } else {
...@@ -84,16 +126,15 @@ void* set_object(void** target, void* o) { ...@@ -84,16 +126,15 @@ void* set_object(void** target, void* o) {
} else { } else {
(*(m - 1))--; (*(m - 1))--;
} }
*target = o; }
m = (jint*) target;
if (o != 0) { void* set(void* o, void* n) {
(*(m - 1))++; release(o);
} return reference(n);
return m;
} }
void* string(char* s) { void* string(char* s) {
int len = strlen(s); jint len = strlen(s);
jchar* chars = NEW_ARRAY(sizeof(jchar), len); jchar* chars = NEW_ARRAY(sizeof(jchar), len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
chars[i] = s[i]; chars[i] = s[i];
...@@ -144,4 +185,14 @@ void* string(char* s) { ...@@ -144,4 +185,14 @@ void* string(char* s) {
return chars.length; return chars.length;
} }
@Ignore
public java.lang.String asString() {
return new java.lang.String(chars);
}
@Ignore
public static String wrap(java.lang.String x) {
return new String(x.toCharArray());
}
} }
...@@ -33,6 +33,8 @@ public class System { ...@@ -33,6 +33,8 @@ public class System {
memmove(((jchar*)dest) + destPos, memmove(((jchar*)dest) + destPos,
((jchar*)src) + srcPos, sizeof(jchar) * length); ((jchar*)src) + srcPos, sizeof(jchar) * length);
*/ */
// c: return;
java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
} }
/** /**
...@@ -50,7 +52,8 @@ public class System { ...@@ -50,7 +52,8 @@ public class System {
memmove(((jbyte*)dest) + destPos, memmove(((jbyte*)dest) + destPos,
((jbyte*)src) + srcPos, sizeof(jbyte) * length); ((jbyte*)src) + srcPos, sizeof(jbyte) * length);
*/ */
// c: return;
java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
} }
} }
...@@ -18,7 +18,7 @@ public class Arrays { ...@@ -18,7 +18,7 @@ public class Arrays {
* @param x the value * @param x the value
*/ */
public static void fill(char[] array, char x) { public static void fill(char[] array, char x) {
for (int i = 0; i < array.length; i++) { for (int i = 0, size = array.length; i < size; i++) {
array[i] = x; array[i] = x;
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论