0001: /*
0002: * xtc - The eXTensible Compiler
0003: * Copyright (C) 2007 IBM Corp.
0004: *
0005: * This program is free software; you can redistribute it and/or
0006: * modify it under the terms of the GNU General Public License
0007: * version 2 as published by the Free Software Foundation.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
0017: * USA.
0018: */
0019: package xtc.lang.jeannie;
0020:
0021: import java.io.File;
0022: import java.util.ArrayList;
0023: import java.util.HashMap;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028: import java.util.Stack;
0029:
0030: import xtc.Constants;
0031: import xtc.Limits;
0032: import xtc.lang.CAnalyzer;
0033: import xtc.lang.JavaAnalyzer;
0034: import xtc.lang.JavaEntities;
0035: import xtc.lang.JavaTypeConverter;
0036: import xtc.tree.GNode;
0037: import xtc.tree.LineMarker;
0038: import xtc.tree.Locatable;
0039: import xtc.tree.Node;
0040: import xtc.tree.Visitor;
0041: import xtc.type.ClassT;
0042: import xtc.type.FunctionT;
0043: import xtc.type.MethodT;
0044: import xtc.type.PointerT;
0045: import xtc.type.Type;
0046: import xtc.type.VariableT;
0047: import xtc.type.VoidT;
0048: import xtc.type.Type.Tag;
0049: import xtc.util.Runtime;
0050: import xtc.util.SymbolTable;
0051: import xtc.util.SymbolTable.Scope;
0052:
0053: /**
0054: * A visitor that constructs separate C and Java ASTs from a JNI AST. Assumes
0055: * that the input AST has been simplified with jeannie.AstSimplifier, and its types
0056: * have been analyzed with jeannie.Analyzer.
0057: *
0058: * @author Martin Hirzel
0059: */
0060: public class CodeGenerator extends Visitor {
0061: public static final class Context {
0062: final String _activeLanguage;
0063: final String _cEnvStructName;
0064: final boolean _cHasEnv;
0065: final String _javaEnvClassName;
0066: final String _javaEnvPackageName;
0067: final boolean _javaIsStatic;
0068: final String _openArray;
0069: final Type _snippetType;
0070:
0071: public Context(final Context other, final String activeLanguage) {
0072: this (activeLanguage, other._cEnvStructName, other._cHasEnv,
0073: other._javaEnvClassName, other._javaEnvPackageName,
0074: other._javaIsStatic, other._openArray,
0075: other._snippetType);
0076: }
0077:
0078: public Context(final String activeLanguage,
0079: final String cEnvStructName, final boolean cHasEnv,
0080: final String javaEnvClassName,
0081: final String javaEnvPackageName,
0082: final boolean javaIsStatic, final String openArray,
0083: final Type snippetType) {
0084: _activeLanguage = activeLanguage;
0085: _cEnvStructName = cEnvStructName;
0086: _cHasEnv = cHasEnv;
0087: _javaEnvClassName = javaEnvClassName;
0088: _javaEnvPackageName = javaEnvPackageName;
0089: _javaIsStatic = javaIsStatic;
0090: _openArray = openArray;
0091: _snippetType = snippetType;
0092: }
0093: }
0094:
0095: public static final class Out {
0096: public final List<Node> _cExternalDeclarations;
0097: public final List<Node> _cMembers;
0098: public final Node _cNode;
0099: public final List<Node> _javaMembers;
0100: public final Node _javaNode;
0101:
0102: public Out(final List<Node> cExternalDeclarations,
0103: final List<Node> cMembers, final Node cNode,
0104: final List<Node> javaMembers, final Node javaNode) {
0105: _cExternalDeclarations = cExternalDeclarations;
0106: _cMembers = cMembers;
0107: _cNode = cNode;
0108: _javaMembers = javaMembers;
0109: _javaNode = javaNode;
0110: }
0111:
0112: public final Out addAll(final Out other) {
0113: if (null != other) {
0114: _cExternalDeclarations
0115: .addAll(other._cExternalDeclarations);
0116: _cMembers.addAll(other._cMembers);
0117: _javaMembers.addAll(other._javaMembers);
0118: }
0119: return this ;
0120: }
0121: }
0122:
0123: static final class StringString {
0124: final String _s1;
0125: final String _s2;
0126:
0127: StringString(final String s1, final String s2) {
0128: _s1 = s1;
0129: _s2 = s2;
0130: }
0131: }
0132:
0133: static final class Substitutions implements Iterable<StringString> {
0134: private final Map<String, Map<String, String>> _map = new HashMap<String, Map<String, String>>();
0135:
0136: final String get(final SymbolTable.Scope scope,
0137: final String srcId) {
0138: final Map<String, String> m = _map.get(scope
0139: .getQualifiedName());
0140: return null == m ? null : m.get(srcId);
0141: }
0142:
0143: public Iterator<StringString> iterator() {
0144: final List<StringString> l = new ArrayList<StringString>();
0145: for (final String scopeName : _map.keySet())
0146: for (final String srcId : _map.get(scopeName).keySet())
0147: l.add(new StringString(scopeName, srcId));
0148: return l.iterator();
0149: }
0150:
0151: final Substitutions put(final SymbolTable.Scope scope,
0152: final String srcId, final String tgtId) {
0153: final String scopeName = scope.getQualifiedName();
0154: if (!_map.containsKey(scopeName))
0155: _map.put(scopeName, new HashMap<String, String>());
0156: _map.get(scopeName).put(srcId, tgtId);
0157: return this ;
0158: }
0159: }
0160:
0161: private static String getFileStem(final GNode n) {
0162: final String fileName = n.getLocation().file;
0163: final int lastSlash = Math.max(fileName.lastIndexOf('/'),
0164: fileName.lastIndexOf('\\'));
0165: final int firstDot = fileName.indexOf('.', lastSlash);
0166: final int end = -1 == firstDot ? fileName.length() : firstDot;
0167: return fileName.substring(1 + lastSlash, end);
0168: }
0169:
0170: private static Type getType(final GNode n) {
0171: return (Type) n.getProperty(Constants.TYPE);
0172: }
0173:
0174: private static GNode idNode(final Locatable loc, final String id) {
0175: return setLoc(loc, GNode.create("PrimaryIdentifier", id));
0176: }
0177:
0178: /** Set location from loc to n, return n. */
0179: public static GNode setLoc(final Locatable loc, final GNode n) {
0180: n.setLocation(loc);
0181: return n;
0182: }
0183:
0184: final Substitutions _cSubstitutions;
0185:
0186: final Substitutions _javaSubstitutions;
0187: final JeannieJavaFactory _astFactoryJava;
0188: final JeannieCFactory _astFactoryC;
0189: final Stack<Context> _contexts;
0190: final Map<String, Integer> _freshIdCount;
0191: final Runtime _runtime;
0192: final SymbolTable _table;
0193:
0194: Set<String> _usedIdentifiers;
0195:
0196: public CodeGenerator(final Runtime runtime, final SymbolTable table) {
0197: _astFactoryC = new JeannieCFactory();
0198: _astFactoryJava = new JeannieJavaFactory();
0199: _contexts = new Stack<Context>();
0200: _cSubstitutions = new Substitutions();
0201: _freshIdCount = new HashMap<String, Integer>();
0202: _javaSubstitutions = new Substitutions();
0203: _runtime = runtime;
0204: _table = table;
0205: }
0206:
0207: private GNode abruptFlowCheck(final Locatable loc,
0208: final List<Node> cMembers, final List<Node> javaMembers) {
0209: final GNode fieldName = cStringNode(liftIdJava(
0210: currentMethodScope(), loc, "returnAbrupt", JavaEntities
0211: .nameToBaseType("boolean"), javaMembers));
0212: final GNode jump = abruptFlowJump(loc, cMembers);
0213: final GNode result;
0214: if (existsOpenArrayInSameSnippet()) {
0215: final String arr = context()._openArray;
0216: final String releaseAbrupt = liftIdC(declaringScope(arr),
0217: arr + "ReleaseAbrupt", typedefType("jint"),
0218: cMembers);
0219: result = (GNode) _astFactoryC.abruptFlowCheckOpenArray(
0220: releaseAbrupt, fieldName, jump);
0221: } else {
0222: result = (GNode) _astFactoryC.abruptFlowCheck(fieldName,
0223: jump);
0224: }
0225: return setLoc(loc, result);
0226: }
0227:
0228: private GNode abruptFlowJump(final Locatable loc,
0229: final List<Node> cMembers) {
0230: final GNode jumpStatement;
0231: if (existsOpenArrayInSameSnippet()) {
0232: final String arr = context()._openArray;
0233: final String label = liftIdCLabel(declaringScope(arr),
0234: "release_" + arr);
0235: jumpStatement = (GNode) _astFactoryC
0236: .abruptFlowJumpOpenArray(label);
0237: } else {
0238: final Type returnType = context()._snippetType;
0239: final GNode value = returnType.hasTag(Tag.VOID) ? null
0240: : GNode.create("CastExpression", Utilities
0241: .cTypeToAst(returnType, null, "TypeName"),
0242: GNode.create("IntegerConstant", "0"));
0243: jumpStatement = GNode.create("ReturnStatement", value);
0244: }
0245: return setLoc(loc, jumpStatement);
0246: }
0247:
0248: private GNode cEnvJavaTypeAst() {
0249: final String name;
0250: switch (Limits.POINTER_SIZE) {
0251: case 4:
0252: name = "int";
0253: break;
0254: case 8:
0255: name = "long";
0256: break;
0257: default:
0258: throw new Error();
0259: }
0260: return JavaEntities.javaTypeToAst(_table, JavaEntities
0261: .nameToBaseType(name));
0262: }
0263:
0264: private Out cInJavaCode(final GNode n, final boolean isExpression) {
0265: assert "Java".equals(context()._activeLanguage);
0266: final GNode childNode = n.getGeneric(0);
0267: final Type childType = isExpression ? getType(childNode)
0268: : VoidT.TYPE;
0269: _contexts.push(new Context("C", context()._cEnvStructName,
0270: true, context()._javaEnvClassName,
0271: context()._javaEnvPackageName, context()._javaIsStatic,
0272: context()._openArray, childType));
0273: final Out childOut = (Out) dispatch(childNode);
0274: _contexts.pop();
0275: final Type ownType = isExpression ? getType(n) : JavaEntities
0276: .nameToBaseType("void");
0277: final String methodName = freshIdentifier("j2c");
0278: final List<Node> javaMembers = cInJavaCode_javaMembers(
0279: methodName, ownType, childOut);
0280: final Out ownOut = new Out(cInJavaCode_cExternalDeclarations(
0281: methodName, childType, childOut), childOut._cMembers,
0282: null, javaMembers, cInJavaCode_javaNode(n, methodName,
0283: javaMembers, isExpression));
0284: return ownOut;
0285: }
0286:
0287: private List<Node> cInJavaCode_cExternalDeclarations(
0288: final String methodName, final Type childType,
0289: final Out childOut) {
0290: final String functionName = mangledFunctionName(methodName);
0291: final GNode function;
0292: { //parse prototype with empty body first
0293: final String jniCall = _runtime.getString("jniCall");
0294: // on cygwin: "__attribute__((__stdcall__))"
0295: final String core = null == jniCall ? functionName
0296: : jniCall + " " + functionName;
0297: final Type pure = Utilities.pureCType(_table, _runtime,
0298: childType);
0299: String code = Utilities.cTypeToString(pure, core) + "(";
0300: code = Utilities.copyDropAuto(code);
0301: code += " JNIEnv *env, jobject jEnv";
0302: // represent C pointer as Java long, i.e., using 64 bits
0303: if (context()._cHasEnv)
0304: switch (Limits.POINTER_SIZE) {
0305: case 4:
0306: code += ", const jint cEnv";
0307: break;
0308: case 8:
0309: code += ", const jlong cEnv";
0310: break;
0311: default:
0312: throw new Error();
0313: }
0314: code += ") { }";
0315: final Set<String> typedefs = Utilities.typedefs(childType);
0316: typedefs.addAll(Utilities.standardJniTypeDefs());
0317: function = Utilities.cStringToAst("FunctionDefinition",
0318: code, typedefs);
0319: }
0320: { //then plug in real body
0321: final String tag = context()._cEnvStructName;
0322: final Node action = childOut._cNode;
0323: final Node body;
0324: if (context()._cHasEnv)
0325: body = childType.isVoid() ? _astFactoryC
0326: .cInJavaStatementWithCEnv(tag, action)
0327: : _astFactoryC.cInJavaExpressionWithCEnv(tag,
0328: action);
0329: else
0330: body = childType.isVoid() ? _astFactoryC
0331: .cInJavaStatementWithoutCEnv(tag, action)
0332: : _astFactoryC.cInJavaExpressionWithoutCEnv(
0333: tag, action);
0334: function.set(function.size() - 1, setLoc(childOut._cNode,
0335: (GNode) body));
0336: }
0337: final List<Node> result = childOut._cExternalDeclarations;
0338: result.add(function);
0339: return result;
0340: }
0341:
0342: private List<Node> cInJavaCode_javaMembers(final String methodName,
0343: final Type ownType, final Out childOut) {
0344: final GNode returnType = JavaEntities.javaTypeToAst(_table,
0345: ownType);
0346: final Node n = context()._cHasEnv ? _astFactoryJava
0347: .cInJavaCodeWithCEnv(returnType, methodName,
0348: cEnvJavaTypeAst()) : _astFactoryJava
0349: .cInJavaCodeWithoutCEnv(returnType, methodName);
0350: //TD 41 throws clause on j2c native method
0351: final List<Node> result = childOut._javaMembers;
0352: result.add(setLoc(childOut._cNode, (GNode) n));
0353: return result;
0354: }
0355:
0356: private GNode cInJavaCode_javaNode(final Locatable loc,
0357: final String methodName, final List<Node> javaMembers,
0358: final boolean isExpression) {
0359: final Node result;
0360: if (isExpression) {
0361: result = context()._cHasEnv ? _astFactoryJava
0362: .cInJavaExpressionWithCEnv(methodName)
0363: : _astFactoryJava
0364: .cInJavaExpressionWithoutCEnv(methodName);
0365: } else {
0366: final String returnAbruptName = liftIdJava(
0367: currentMethodScope(), loc, "returnAbrupt",
0368: JavaEntities.nameToBaseType("boolean"), javaMembers);
0369: result = context()._cHasEnv ? _astFactoryJava
0370: .cInJavaStatementWithCEnv(methodName,
0371: returnAbruptName) : _astFactoryJava
0372: .cInJavaStatementWithoutCEnv(methodName,
0373: returnAbruptName);
0374: }
0375: return setLoc(loc, (GNode) result);
0376: }
0377:
0378: private final Context context() {
0379: return _contexts.peek();
0380: }
0381:
0382: private GNode cStringNode(final String string) {
0383: return GNode.create("StringConstant", "\"" + string + "\"");
0384: }
0385:
0386: private SymbolTable.Scope currentMethodScope() {
0387: for (SymbolTable.Scope s = _table.current(); !s.isRoot(); s = s
0388: .getParent()) {
0389: final String scopeName = s.getName();
0390: if (SymbolTable.isInNameSpace(scopeName, "method")
0391: || SymbolTable.isFunctionScopeName(scopeName)
0392: || SymbolTable.isMacroScopeName(scopeName))
0393: return s;
0394: }
0395: return null;
0396: }
0397:
0398: private SymbolTable.Scope declaringScope(final String id) {
0399: return _table.lookupScope(id);
0400: }
0401:
0402: private boolean existsOpenArrayInSameSnippet() {
0403: final String o = context()._openArray;
0404: if (null == o)
0405: return false;
0406: final String a = context()._activeLanguage;
0407: for (int i = _contexts.size() - 2; i >= 0; i--) {
0408: final Context c = _contexts.get(i);
0409: if (!a.equals(c._activeLanguage))
0410: return false;
0411: if (!o.equals(c._openArray))
0412: return true;
0413: }
0414: return true;
0415: }
0416:
0417: /**
0418: * Returns a new globally unique identifier that starts with the base name.
0419: * Takes care to avoid shadowing other identifiers that the program already
0420: * uses, including free identifiers that are bound in imports or superclasses,
0421: * and even "funny names" that programmers are unlikely to write but that may
0422: * arise in other automatically generated code.
0423: */
0424: private String freshIdentifier(final String base) {
0425: int i = _freshIdCount.containsKey(base) ? _freshIdCount.get(
0426: base).intValue() : -1;
0427: String result;
0428: do {
0429: i++;
0430: result = (0 == i) ? base : base + i;
0431: } while (_usedIdentifiers.contains(result));
0432: _freshIdCount.put(base, new Integer(i));
0433: _usedIdentifiers.add(result);
0434: return result;
0435: }
0436:
0437: private boolean isUtf8(final Type cPtrType, final Type javaType) {
0438: if (JavaTypeConverter.isIdentical(javaType, JavaEntities
0439: .tString(_table))) {
0440: final Type cTgtType = ((PointerT) Utilities.c().pointerize(
0441: cPtrType)).getType();
0442: return Utilities.hasTypedefName(cTgtType, "jbyte");
0443: }
0444: return false;
0445: }
0446:
0447: private Out javaInCCode(final GNode n, final boolean isExpression) {
0448: assert "C".equals(context()._activeLanguage);
0449: _contexts.push(new Context(context(), "Java"));
0450: final Out javaOut = (Out) dispatch(n);
0451: _contexts.pop();
0452: final Type javaType = isExpression ? JavaAnalyzer
0453: .getRValueNoError(getType(n)) : JavaEntities
0454: .nameToBaseType("void");
0455: final String methodName = freshIdentifier("c2j");
0456: final List<Node> cMembers = javaOut._cMembers;
0457: final List<Node> javaMembers = javaOut._javaMembers;
0458: final boolean isNonVoidExpression = isExpression
0459: && !getType(n).isVoid();
0460: final Out ownOut = new Out(javaOut._cExternalDeclarations,
0461: cMembers, javaInCCode_cNode(methodName, javaType,
0462: isNonVoidExpression, n, cMembers, javaMembers),
0463: javaInCCode_javaMembers(methodName, javaType,
0464: isExpression, javaOut), null);
0465: return ownOut;
0466: }
0467:
0468: private GNode javaInCCode_cNode(final String methodName,
0469: final Type javaType, final boolean isExpression,
0470: final GNode n, final List<Node> cMembers,
0471: final List<Node> javaMembers) {
0472: final GNode name = cStringNode(methodName);
0473: final boolean is32bit = 4 == Limits.POINTER_SIZE;
0474: assert is32bit || 8 == Limits.POINTER_SIZE;
0475: final GNode signature = cStringNode((is32bit ? "(I)" : "(J)")
0476: + JavaEntities.typeToDescriptor(_table, javaType));
0477: final String apiFunction = "CallNonvirtual"
0478: + Utilities.javaTypeToApiType(javaType, true, false)
0479: + "Method";
0480: final GNode abruptFlowCheck = abruptFlowCheck(n, cMembers,
0481: javaMembers);
0482: final Node result;
0483: if (isExpression) {
0484: final Type cType = Utilities.javaTypeToCType(_table,
0485: _runtime, n, javaType, false);
0486: final GNode tmpDeclaration = Utilities.cTypeToAst(cType,
0487: "tmp", "Declaration");
0488: result = is32bit ? _astFactoryC.javaInCExpression32(name,
0489: signature, tmpDeclaration, apiFunction,
0490: abruptFlowCheck) : _astFactoryC
0491: .javaInCExpression64(name, signature,
0492: tmpDeclaration, apiFunction,
0493: abruptFlowCheck);
0494: } else {
0495: result = is32bit ? _astFactoryC.javaInCStatement32(name,
0496: signature, apiFunction, abruptFlowCheck)
0497: : _astFactoryC.javaInCStatement64(name, signature,
0498: apiFunction, abruptFlowCheck);
0499: }
0500: return setLoc(n, (GNode) result);
0501: }
0502:
0503: private List<Node> javaInCCode_javaMembers(final String methodName,
0504: final Type javaType, final boolean isExpression,
0505: final Out javaOut) {
0506: final GNode typeAst = JavaEntities.javaTypeToAst(_table,
0507: javaType);
0508: final Node n = isExpression ? javaType.isVoid() ? _astFactoryJava
0509: .javaInCExpressionVoid(methodName, cEnvJavaTypeAst(),
0510: javaOut._javaNode)
0511: : _astFactoryJava.javaInCExpression(typeAst,
0512: methodName, cEnvJavaTypeAst(),
0513: javaOut._javaNode)
0514: : _astFactoryJava.javaInCStatement(methodName,
0515: cEnvJavaTypeAst(), javaOut._javaNode);
0516: final List<Node> result = javaOut._javaMembers;
0517: result.add(setLoc(javaOut._javaNode, (GNode) n));
0518: return result;
0519: }
0520:
0521: private Out jeannieCancelOrCommit(final Locatable loc,
0522: final String arr, final boolean isCommit) {
0523: final List<Node> cMembers = new ArrayList<Node>();
0524: final GNode jump = abruptFlowJump(loc, cMembers);
0525: final String field = liftIdC(declaringScope(arr), arr
0526: + "ReleaseAbrupt", typedefType("jint"), cMembers);
0527: final Node n = isCommit ? _astFactoryC.commit(field, jump)
0528: : _astFactoryC.cancel(field, jump);
0529: setLoc(loc, (GNode) n);
0530: final Out ownOut = new Out(new ArrayList<Node>(0), cMembers,
0531: (GNode) n, new ArrayList<Node>(0), null);
0532: return ownOut;
0533: }
0534:
0535: private String jeannieCopyApiFunction(final Type javaType,
0536: final boolean isAcquire, final boolean isUtf8) {
0537: final StringBuffer result = new StringBuffer();
0538: result.append(isAcquire ? "Get" : "Set");
0539: if (JavaTypeConverter.isIdentical(javaType, JavaEntities
0540: .tString(_table)))
0541: result.append(isUtf8 ? "StringUTF" : "String");
0542: else
0543: result.append(Utilities.javaTypeToApiType(javaType, true,
0544: true));
0545: result.append("Region");
0546: return result.toString();
0547: }
0548:
0549: private String liftIdC(final SymbolTable.Scope scope,
0550: final String srcId, final Type type,
0551: final List<Node> cMembers) {
0552: if (null == _cSubstitutions.get(scope, srcId)) {
0553: final String tgtId = freshIdentifier("_" + srcId);
0554: final Type pureCType = Utilities.c().pointerize(
0555: Utilities.pureCType(_table, _runtime, type));
0556: final GNode fieldDecl = Utilities.cTypeToAst(pureCType,
0557: tgtId, "StructureDeclaration");
0558: cMembers.add(fieldDecl);
0559: _cSubstitutions.put(scope, srcId, tgtId);
0560: }
0561: return _cSubstitutions.get(scope, srcId);
0562: }
0563:
0564: private String liftIdCLabel(final SymbolTable.Scope scope,
0565: final String srcId) {
0566: //TD 41 avoid clashes with locals
0567: if (null == _cSubstitutions.get(scope, srcId)) {
0568: final String tgtId = freshIdentifier(srcId);
0569: _cSubstitutions.put(scope, srcId, tgtId);
0570: }
0571: return _cSubstitutions.get(scope, srcId);
0572: }
0573:
0574: private String liftIdJava(final SymbolTable.Scope scope,
0575: final Locatable loc, final String srcId, final Type type,
0576: final List<Node> javaMembers) {
0577: if (null == _javaSubstitutions.get(scope, srcId)) {
0578: final String tgtId = freshIdentifier("_" + srcId);
0579: final Type r = JavaEntities.isGeneralLValueT(type) ? JavaEntities
0580: .dereference(type)
0581: : type;
0582: final Node n = _astFactoryJava.declareField(JavaEntities
0583: .javaTypeToAst(_table, r), tgtId);
0584: javaMembers.add(setLoc(loc, (GNode) n));
0585: _javaSubstitutions.put(scope, srcId, tgtId);
0586: }
0587: return _javaSubstitutions.get(scope, srcId);
0588: }
0589:
0590: private String mangledFunctionName(final String methodName) {
0591: final String packageAndClass;
0592: if (null == context()._javaEnvPackageName) {
0593: final ClassT baseClass = JavaEntities.currentType(_table)
0594: .toClass();
0595: final String baseName = JavaEntities.qNameWithDollars(
0596: _table, baseClass);
0597: packageAndClass = baseName + "$"
0598: + context()._javaEnvClassName;
0599: } else {
0600: final String slashes = context()._javaEnvPackageName
0601: + context()._javaEnvClassName;
0602: packageAndClass = slashes.replace('/', '.');
0603: }
0604: final String qualifiedName = packageAndClass + '.' + methodName;
0605: final String result = "Java_"
0606: + Utilities.jniMangledName(qualifiedName);
0607: return result;
0608: }
0609:
0610: private Out processBuiltin(final GNode n) {
0611: assert "C".equals(context()._activeLanguage);
0612: final String name = n.getGeneric(0).getString(0);
0613: final Out argsOut = (Out) dispatch(n.getGeneric(1));
0614: assert null == argsOut._javaNode;
0615: if ("_copyFromJava".equals(name)) {
0616: final GNode cArray = argsOut._cNode.getGeneric(0);
0617: final GNode cArrayStart = argsOut._cNode.getGeneric(1);
0618: final GNode javaArray = argsOut._cNode.getGeneric(2);
0619: final GNode javaArrayStart = argsOut._cNode.getGeneric(3);
0620: final GNode length = argsOut._cNode.getGeneric(4);
0621: final GNode abruptFlowCheck = abruptFlowCheck(n,
0622: argsOut._cMembers, argsOut._javaMembers);
0623: final Type javaType = Utilities.cTypeToJavaType(_table,
0624: _runtime, n.getGeneric(1).getGeneric(2), getType(n
0625: .getGeneric(1).getGeneric(2)));
0626: final boolean primiv = JavaTypeConverter.isIdentical(
0627: javaType, JavaEntities.tString(_table))
0628: || javaType.isArray()
0629: && JavaEntities.isPrimitiveT(JavaEntities
0630: .arrayElementType(javaType.toArray()));
0631: final Node ownNode;
0632: if (primiv) {
0633: final boolean utf8 = isUtf8(getType(n.getGeneric(1)
0634: .getGeneric(0)), javaType);
0635: final String apiFunction = jeannieCopyApiFunction(
0636: javaType, true, utf8);
0637: ownNode = utf8 ? _astFactoryC.copyBetweenJavaAndCUTF(
0638: javaArray, javaArrayStart, length, apiFunction,
0639: cArray, cArrayStart, abruptFlowCheck)
0640: : _astFactoryC.copyBetweenJavaAndC(apiFunction,
0641: javaArray, javaArrayStart, length,
0642: cArray, cArrayStart, abruptFlowCheck);
0643: } else {
0644: ownNode = _astFactoryC.copyFromJavaReference(javaArray,
0645: javaArrayStart, length, cArray, cArrayStart,
0646: abruptFlowCheck);
0647: }
0648: setLoc(n, (GNode) ownNode);
0649: final Out ownOut = new Out(new ArrayList<Node>(0),
0650: argsOut._cMembers, (GNode) ownNode,
0651: argsOut._javaMembers, null);
0652: return ownOut;
0653: } else if ("_copyToJava".equals(name)) {
0654: final GNode javaArray = argsOut._cNode.getGeneric(0);
0655: final GNode javaArrayStart = argsOut._cNode.getGeneric(1);
0656: final GNode cArray = argsOut._cNode.getGeneric(2);
0657: final GNode cArrayStart = argsOut._cNode.getGeneric(3);
0658: final GNode length = argsOut._cNode.getGeneric(4);
0659: final GNode abruptFlowCheck = abruptFlowCheck(n,
0660: argsOut._cMembers, argsOut._javaMembers);
0661: final Type javaType = Utilities.cTypeToJavaType(_table,
0662: _runtime, n.getGeneric(1).getGeneric(0), getType(n
0663: .getGeneric(1).getGeneric(0)));
0664: final boolean primiv = JavaTypeConverter.isIdentical(
0665: javaType, JavaEntities.tString(_table))
0666: || javaType.isArray()
0667: && JavaEntities.isPrimitiveT(JavaEntities
0668: .arrayElementType(javaType.toArray()));
0669: final Node ownNode;
0670: if (primiv) {
0671: final boolean utf8 = isUtf8(getType(n.getGeneric(1)
0672: .getGeneric(2)), javaType);
0673: final String apiFunction = jeannieCopyApiFunction(
0674: javaType, false, utf8);
0675: ownNode = utf8 ? _astFactoryC.copyBetweenJavaAndCUTF(
0676: javaArray, javaArrayStart, length, apiFunction,
0677: cArray, cArrayStart, abruptFlowCheck)
0678: : _astFactoryC.copyBetweenJavaAndC(apiFunction,
0679: javaArray, javaArrayStart, length,
0680: cArray, cArrayStart, abruptFlowCheck);
0681: } else {
0682: ownNode = _astFactoryC.copyToJavaReference(javaArray,
0683: javaArrayStart, length, cArray, cArrayStart,
0684: abruptFlowCheck);
0685: }
0686: setLoc(n, (GNode) ownNode);
0687: final Out ownOut = new Out(new ArrayList<Node>(0),
0688: argsOut._cMembers, (GNode) ownNode,
0689: argsOut._javaMembers, null);
0690: return ownOut;
0691: } else if ("_newJavaString".equals(name)) {
0692: final Type t = getType(n.getGeneric(1).getGeneric(0));
0693: final String apiFunction = "NewString"
0694: + (Utilities.isPtrTypedef(t, "jchar") ? "" : "UTF");
0695: final GNode cString = argsOut._cNode.getGeneric(0);
0696: final GNode abruptFlowCheck = abruptFlowCheck(n,
0697: argsOut._cMembers, argsOut._javaMembers);
0698: final GNode cNode = (GNode) _astFactoryC.newJavaString(
0699: apiFunction, cString, abruptFlowCheck);
0700: setLoc(n, (GNode) cNode);
0701: final Out ownOut = new Out(argsOut._cExternalDeclarations,
0702: argsOut._cMembers, cNode, argsOut._javaMembers,
0703: null);
0704: return ownOut;
0705: } else if ("_stringUTFLength".equals(name)) {
0706: final Node ac = argsOut._cNode;
0707: final Node javaString = ac.getNode(0);
0708: final Node cNode;
0709: if (1 == n.getGeneric(1).size())
0710: cNode = _astFactoryC.stringUTFLength1(javaString);
0711: else
0712: cNode = _astFactoryC.stringUTFLength3(javaString, ac
0713: .getNode(1), ac.getNode(2));
0714: final Out ownOut = new Out(argsOut._cExternalDeclarations,
0715: argsOut._cMembers, setLoc(n, (GNode) cNode),
0716: argsOut._javaMembers, null);
0717: return ownOut;
0718: } else {
0719: throw new Error("builtin " + name
0720: + " not (yet) implemented");
0721: }
0722: }
0723:
0724: private List<Node> processDeclarators(final GNode declarators,
0725: final List<Node> cExternalDeclarations,
0726: final List<Node> cMembers, final List<Node> javaMembers) {
0727: assert "Java".equals(context()._activeLanguage)
0728: && declarators.hasName("Declarators");
0729: final List<Node> result = new ArrayList<Node>();
0730: for (final Object declObj : declarators) {
0731: final GNode declNode = (GNode) declObj;
0732: final GNode initNode = declNode.getGeneric(2);
0733: if (null == initNode)
0734: continue;
0735: final Out initOut = (Out) dispatch(initNode);
0736: assert null == initOut._cNode;
0737: cExternalDeclarations
0738: .addAll(initOut._cExternalDeclarations);
0739: cMembers.addAll(initOut._cMembers);
0740: javaMembers.addAll(initOut._javaMembers);
0741: final VariableT type = getType(declNode).toVariable();
0742: final String srcId = type.getName();
0743: final String subst = liftIdJava(declaringScope(srcId),
0744: declNode, srcId, type, javaMembers);
0745: final Node javaNode;
0746: if (initOut._javaNode.hasName("ArrayInitializer")) {
0747: final GNode typeAst = JavaEntities.javaTypeToAst(
0748: _table, type.getType());
0749: javaNode = setLoc(initOut._javaNode, GNode.create(
0750: "NewArrayExpression", typeAst.getGeneric(0),
0751: null, typeAst.getGeneric(1), initOut._javaNode));
0752: } else {
0753: javaNode = initOut._javaNode;
0754: }
0755: result.add(setLoc(javaNode, (GNode) _astFactoryJava
0756: .setThisDotField(subst, javaNode)));
0757: }
0758: return result;
0759: }
0760:
0761: private Type typedefType(final String symbol) {
0762: final Type result = (Type) _table.root().lookup(symbol);
0763: assert null != result;
0764: return result;
0765: }
0766:
0767: public final Out visit(final LineMarker m) {
0768: final boolean c = "C".equals(context()._activeLanguage);
0769: final Node n = m.getNode();
0770: if (null == n)
0771: return new Out(new ArrayList<Node>(0), new ArrayList<Node>(
0772: 0), c ? m : null, new ArrayList<Node>(0), c ? null
0773: : m);
0774: final Out childOut = (Out) dispatch(n);
0775: if (c) {
0776: assert null != childOut._cNode
0777: && null == childOut._javaNode;
0778: m.setNode(childOut._cNode);
0779: } else {
0780: assert null == childOut._cNode
0781: && null != childOut._javaNode;
0782: m.setNode(childOut._javaNode);
0783: }
0784: final Out result = new Out(childOut._cExternalDeclarations,
0785: childOut._cMembers, c ? m : null,
0786: childOut._javaMembers, c ? null : m);
0787: return result;
0788: }
0789:
0790: /** Catch-all visit method. */
0791: public final Out visit(final Node n) {
0792: _table.enter(n);
0793: //TD 42 don't create a new node, just rewrite the old node's children
0794: final GNode ownNode = setLoc(n, GNode.create(n.getName(), n
0795: .size()));
0796: final boolean c = "C".equals(context()._activeLanguage);
0797: final Out ownOut = new Out(new ArrayList<Node>(),
0798: new ArrayList<Node>(), c ? ownNode : null,
0799: new ArrayList<Node>(), c ? null : ownNode);
0800: for (int i = 0; i < n.size(); i++)
0801: if (n.get(i) instanceof Node) {
0802: final Out childOut = (Out) dispatch(n.getNode(i));
0803: ownNode
0804: .add(i, c ? childOut._cNode
0805: : childOut._javaNode);
0806: ownOut.addAll(childOut);
0807: assert null == (c ? childOut._javaNode
0808: : childOut._cNode);
0809: } else {
0810: ownNode.add(i, n.get(i));
0811: }
0812: _table.exit(n);
0813: return ownOut;
0814: }
0815:
0816: /**
0817: * Visit a BasicForControl = Modifiers Type Declarators [Expression] [ExpressionList]
0818: * / null null [ExpressionList] [Expression] [ExpressionList] (gosling_et_al_2000
0819: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#40898">§8.3</a>).
0820: */
0821: public final Out visitBasicForControl(final GNode n) {
0822: assert "Java".equals(context()._activeLanguage);
0823: if (null == context()._javaEnvClassName || null == n.get(0))
0824: return visit(n);
0825: final List<Node> cExternalDeclarations = new ArrayList<Node>();
0826: final List<Node> cMembers = new ArrayList<Node>();
0827: final List<Node> javaMembers = new ArrayList<Node>();
0828: final List<Node> decls = processDeclarators(n.getGeneric(2),
0829: cExternalDeclarations, cMembers, javaMembers);
0830: final GNode initNode = 0 == decls.size() ? null : setLoc(n
0831: .getGeneric(2), (GNode) GNode.create("ExpressionList",
0832: decls.size()).addAll(decls));
0833: final Out testOut = (Out) dispatch(n.getGeneric(3));
0834: final Out incrOut = (Out) dispatch(n.getGeneric(4));
0835: final GNode javaNode = setLoc(n, GNode.create(
0836: "BasicForControl", null, null, initNode,
0837: testOut._javaNode, incrOut._javaNode));
0838: final Out ownOut = new Out(cExternalDeclarations, cMembers,
0839: null, javaMembers, javaNode);
0840: ownOut.addAll(testOut).addAll(incrOut);
0841: return ownOut;
0842: }
0843:
0844: /** Visit a CancelStatement = JeannieC.PrimaryIdentifier. */
0845: public final Out visitCancelStatement(final GNode n) {
0846: return jeannieCancelOrCommit(n, n.getGeneric(0).getString(0),
0847: false);
0848: }
0849:
0850: /** Visit a CDeclarations = ExternalDeclaration* Annotations. */
0851: public final Out visitCDeclarations(final GNode n) {
0852: final Out ownOut = new Out(new ArrayList<Node>(),
0853: new ArrayList<Node>(), null, new ArrayList<Node>(),
0854: null);
0855: assert _table.current().isRoot();
0856: assert 1 == _contexts.size()
0857: && "C".equals(context()._activeLanguage);
0858: for (int i = 0; i < n.size() - 1; i++) {
0859: final Out childOut = (Out) dispatch(n.getNode(i));
0860: assert null == childOut._javaNode;
0861: ownOut._javaMembers.addAll(childOut._javaMembers);
0862: ownOut._cExternalDeclarations
0863: .addAll(childOut._cExternalDeclarations);
0864: ownOut._cExternalDeclarations.add(childOut._cNode);
0865: }
0866: assert _table.current().isRoot();
0867: return ownOut;
0868: }
0869:
0870: /** Visit a CInCBlock = LocalLabelDeclaration* JeannieC.DeclarationOrStatement* Annotations. */
0871: public final Out visitCInCBlock(final GNode n) {
0872: assert "C".equals(context()._activeLanguage);
0873: final Out genericOut = visit(n);
0874: assert genericOut._cNode.hasName("CInCBlock");
0875: final List<Node> cNodes = new ArrayList<Node>(n.size() - 1);
0876: for (int i = 0; i < n.size() - 1; i++) {
0877: final GNode src = n.getGeneric(i), tgt = genericOut._cNode
0878: .getGeneric(i);
0879: if (src.hasName("Declaration")) {
0880: if (tgt.hasName("CompoundStatement")) //flatten, to expand scope of auxiliary declarations
0881: for (final Object t : tgt)
0882: cNodes.add((GNode) t);
0883: else if (!tgt.hasName("EmptyStatement")) //skip, to keep code more readable
0884: cNodes.add(tgt);
0885: } else {
0886: cNodes.add(tgt);
0887: }
0888: }
0889: final Out ownOut = new Out(genericOut._cExternalDeclarations,
0890: genericOut._cMembers, setLoc(n, GNode.create(
0891: "CompoundStatement", cNodes.size() + 1)),
0892: genericOut._javaMembers, genericOut._javaNode);
0893: for (int i = 0; i < cNodes.size(); i++)
0894: ownOut._cNode.add(i, cNodes.get(i));
0895: return ownOut;
0896: }
0897:
0898: /** Visit a CInJavaBlock = CInCBlock. */
0899: public final Out visitCInJavaBlock(final GNode n) {
0900: return cInJavaCode(n, false);
0901: }
0902:
0903: /** Visit a CInJavaExpression = JeannieC.UnaryExpression. */
0904: public final Out visitCInJavaExpression(final GNode n) {
0905: return cInJavaCode(n, true);
0906: }
0907:
0908: /**
0909: * Visit a ClassBody = Declaration* (gosling_et_al_2000
0910: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#18988">§8.1.5</a>,
0911: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/interfaces.doc.html#236431">§9.1.3</a>,
0912: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#41147">§15.9</a>).
0913: */
0914: public final Out visitClassBody(final GNode n) {
0915: assert "Java".equals(context()._activeLanguage);
0916: _table.enter(n);
0917: final Out ownOut = new Out(new ArrayList<Node>(),
0918: new ArrayList<Node>(), null, new ArrayList<Node>(),
0919: setLoc(n, GNode.create("ClassBody")));
0920: if (Utilities.containsJavaToCTransition(n)) {
0921: if (JavaEntities.isTypeTopLevel(JavaEntities
0922: .currentType(_table))) {
0923: final GNode name = GNode.create("StringLiteral", "\""
0924: + getFileStem(n) + "\"");
0925: final Node block = _astFactoryJava.loadLibrary(name);
0926: ownOut._javaNode.add(setLoc(n, GNode.create(
0927: "BlockDeclaration", "static", block)));
0928: }
0929: }
0930: for (final Object child : n) {
0931: final Out childOut = (Out) dispatch((GNode) child);
0932: ownOut._cExternalDeclarations
0933: .addAll(childOut._cExternalDeclarations);
0934: assert childOut._cMembers.isEmpty()
0935: && null == childOut._cNode;
0936: ownOut._javaNode.add(childOut._javaNode);
0937: ownOut._javaNode.addAll(childOut._javaMembers);
0938: }
0939: _table.exit(n);
0940: return ownOut;
0941: }
0942:
0943: /** Visit a CommitStatement = JeannieC.PrimaryIdentifier. */
0944: public final Out visitCommitStatement(final GNode n) {
0945: return jeannieCancelOrCommit(n, n.getGeneric(0).getString(0),
0946: true);
0947: }
0948:
0949: /**
0950: * Visit a CompilationUnit = CDeclarations [PackageDeclaration]
0951: * ImportDeclaration* JeannieJava.Declaration*
0952: * (gosling_et_al_2000
0953: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/packages.doc.html#40031">§7.3</a>).
0954: */
0955: public final Out visitCompilationUnit(final GNode n) {
0956: assert _contexts.isEmpty();
0957: _usedIdentifiers = JavaEntities.allUsedIdentifiers(n);
0958: final GNode cNode = setLoc(n, GNode.create("TranslationUnit"));
0959: final Out cChildOut;
0960: {
0961: final StringBuffer packageName = new StringBuffer();
0962: if (null != n.get(1))
0963: for (final Object o : n.getNode(1).getNode(1))
0964: packageName.append(o).append('/');
0965: _contexts.push(new Context("C", null, false, null,
0966: packageName.toString(), true, null, null));
0967: cChildOut = (Out) dispatch(n.getGeneric(0));
0968: _contexts.pop();
0969: }
0970: assert cChildOut._cMembers.isEmpty()
0971: && null == cChildOut._cNode
0972: && null == cChildOut._javaNode;
0973: cNode.addAll(cChildOut._cExternalDeclarations);
0974: final GNode javaNode = setLoc(n, GNode
0975: .create("CompilationUnit"));
0976: javaNode.add(n.getGeneric(1));
0977: _contexts.push(new Context("Java", null, false, null, null,
0978: true, null, null));
0979: JavaEntities.enterScopeByQualifiedName(_table, (String) n
0980: .getProperty(Constants.SCOPE));
0981: for (int i = 2; i < n.size(); i++) {
0982: final Out javaChildOut = (Out) dispatch(n.getGeneric(i));
0983: cNode.addAll(javaChildOut._cExternalDeclarations);
0984: javaNode.add(javaChildOut._javaNode);
0985: assert javaChildOut._cMembers.isEmpty()
0986: && null == javaChildOut._cNode
0987: && javaChildOut._javaMembers.isEmpty();
0988: }
0989: javaNode.addAll(cChildOut._javaMembers);
0990: _contexts.pop();
0991: final Out ownOut = new Out(null, null, cNode, null, javaNode);
0992: return ownOut;
0993: }
0994:
0995: /** Visit a JeannieC.Declaration = ["__extension__"] DeclarationSpecifiers [InitializedDeclaratorList]. */
0996: public final Out visitDeclaration(final GNode n) {
0997: assert "C".equals(context()._activeLanguage);
0998: if (null == context()._cEnvStructName || null == n.get(2))
0999: return visit(n);
1000: final List<Node> cExternalDeclarations = new ArrayList<Node>();
1001: final List<Node> cMembers = new ArrayList<Node>();
1002: final List<Node> javaMembers = new ArrayList<Node>();
1003: final List<Node> declResults = new ArrayList<Node>();
1004: for (final Object declObj : n.getGeneric(2)) {
1005: final GNode declNode = (GNode) declObj;
1006: final String srcId = Utilities
1007: .getSimpleDeclarator(declNode);
1008: final Type type = Utilities.pureCType(_table, _runtime,
1009: (Type) _table.lookup(srcId));
1010: final String tgtId = liftIdC(declaringScope(srcId), srcId,
1011: type, cMembers);
1012: if (declNode.getGeneric(1).hasName("ArrayDeclarator")) {
1013: final Out specsOut = (Out) dispatch(n.getGeneric(1));
1014: assert null == specsOut._javaNode;
1015: cExternalDeclarations
1016: .addAll(specsOut._cExternalDeclarations);
1017: cMembers.addAll(specsOut._cMembers);
1018: javaMembers.addAll(specsOut._javaMembers);
1019: final Out declOut = (Out) dispatch(declNode);
1020: assert null == declOut._javaNode;
1021: cExternalDeclarations
1022: .addAll(declOut._cExternalDeclarations);
1023: cMembers.addAll(declOut._cMembers);
1024: javaMembers.addAll(declOut._javaMembers);
1025: final GNode declLocal = setLoc(declNode, GNode.create(
1026: "Declaration", n.getString(0), specsOut._cNode,
1027: GNode.create("InitializedDeclaratorList",
1028: declOut._cNode)));
1029: declResults.add(declLocal);
1030: final GNode setField = (GNode) _astFactoryC
1031: .setPCEnvField(tgtId, GNode.create(
1032: "PrimaryIdentifier", srcId));
1033: declResults.add(setLoc(declNode, setField));
1034: } else if (null != declNode.getGeneric(4)) {
1035: final Out initOut = (Out) dispatch(declNode
1036: .getGeneric(4));
1037: assert null == initOut._javaNode;
1038: cExternalDeclarations
1039: .addAll(initOut._cExternalDeclarations);
1040: cMembers.addAll(initOut._cMembers);
1041: javaMembers.addAll(initOut._javaMembers);
1042: final GNode typeAST = Utilities.cTypeToAst(type, null,
1043: "TypeName");
1044: final GNode cast = GNode.create("CastExpression",
1045: typeAST, initOut._cNode);
1046: declResults.add(setLoc(declNode, (GNode) _astFactoryC
1047: .setPCEnvField(tgtId, cast)));
1048: }
1049: }
1050: final Node cNode = (0 == declResults.size()) ? GNode
1051: .create("EmptyStatement")
1052: : (1 == declResults.size()) ? declResults.get(0)
1053: : /* else */_astFactoryC.block(declResults);
1054: final Out ownOut = new Out(cExternalDeclarations, cMembers,
1055: setLoc(n.getGeneric(2), (GNode) cNode), javaMembers,
1056: null);
1057: return ownOut;
1058: }
1059:
1060: /**
1061: * Visit a FieldDeclaration = Modifiers Type Declarators (gosling_et_al_2000
1062: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#40898">§8.3</a>).
1063: */
1064: public final Out visitFieldDeclaration(final GNode n) {
1065: assert "Java".equals(context()._activeLanguage);
1066: if (null == context()._javaEnvClassName)
1067: return visit(n);
1068: final List<Node> cExternalDeclarations = new ArrayList<Node>();
1069: final List<Node> cMembers = new ArrayList<Node>();
1070: final List<Node> javaMembers = new ArrayList<Node>();
1071: final List<Node> decls = processDeclarators(n.getGeneric(2),
1072: cExternalDeclarations, cMembers, javaMembers);
1073: final GNode javaNode;
1074: if (0 == decls.size()) {
1075: javaNode = GNode.create("EmptyStatement");
1076: } else if (1 == decls.size()) {
1077: javaNode = GNode
1078: .create("ExpressionStatement", decls.get(0));
1079: } else {
1080: javaNode = GNode.create("Block", decls.size());
1081: for (final Node d : decls)
1082: javaNode.add(GNode.create("ExpressionStatement", d));
1083: }
1084: final Out ownOut = new Out(cExternalDeclarations, cMembers,
1085: null, javaMembers, setLoc(n.getGeneric(2), javaNode));
1086: return ownOut;
1087: }
1088:
1089: /**
1090: * Visit a ForStatement = (Declaration / [Expression]) [Expression] [Expression] Statement.
1091: */
1092: public final Out visitForStatement(final GNode n) {
1093: if ("Java".equals(context()._activeLanguage)
1094: || null == context()._cEnvStructName
1095: || null == n.get(0)
1096: || !n.getGeneric(0).hasName("Declaration"))
1097: return visit(n);
1098: _table.enter(n);
1099: final Out initOut = (Out) dispatch(n.getGeneric(0));
1100: final Out testOut = (Out) dispatch(n.getGeneric(1));
1101: final Out incrOut = (Out) dispatch(n.getGeneric(2));
1102: final Out bodyOut = (Out) dispatch(n.getGeneric(3));
1103: final GNode loopNode = GNode
1104: .create("ForStatement", null, null == testOut ? null
1105: : testOut._cNode, null == incrOut ? null
1106: : incrOut._cNode, bodyOut._cNode);
1107: final GNode cNode = GNode.create("CompoundStatement",
1108: initOut._cNode, loopNode, null);
1109: final Out ownOut = new Out(new ArrayList<Node>(),
1110: new ArrayList<Node>(), setLoc(n, cNode),
1111: new ArrayList<Node>(), null);
1112: ownOut.addAll(initOut).addAll(testOut).addAll(incrOut).addAll(
1113: bodyOut);
1114: _table.exit(n);
1115: return ownOut;
1116: }
1117:
1118: /** Visit a FunctionCall = (PrimaryIdentifier / JeannieC.PostfixExpression) JeannieC.ExpressionList. */
1119: public final Out visitFunctionCall(final GNode n) {
1120: assert "C".equals(context()._activeLanguage);
1121: if (null == context()._javaEnvClassName)
1122: return visit(n);
1123: if (n.getGeneric(0).hasName("PrimaryIdentifier")
1124: && Analyzer.BUILTINS.contains(n.getGeneric(0)
1125: .getString(0)))
1126: return processBuiltin(n);
1127: final Out plainOut = visit(n);
1128: final Type cType = getType(n);
1129: final GNode cNode;
1130: final Node call = plainOut._cNode;
1131: final GNode abruptFlowCheck = abruptFlowCheck(n,
1132: plainOut._cMembers, plainOut._javaMembers);
1133: final Type cTypeMinusAnnotations = cType.isAnnotated() ? cType
1134: .toAnnotated().getType() : cType;
1135: if (cTypeMinusAnnotations.isVoid()) {
1136: cNode = (GNode) _astFactoryC.checkedFunctionCallVoid(call,
1137: abruptFlowCheck);
1138: } else {
1139: final GNode tmpDeclaration = Utilities.cTypeToAst(cType,
1140: "tmp", "Declaration");
1141: cNode = (GNode) _astFactoryC.checkedFunctionCallResult(
1142: tmpDeclaration, call, abruptFlowCheck);
1143: }
1144: setLoc(n, cNode);
1145: final Out ownOut = new Out(plainOut._cExternalDeclarations,
1146: plainOut._cMembers, cNode, plainOut._javaMembers,
1147: plainOut._javaNode);
1148: return ownOut;
1149: }
1150:
1151: /** Visit a FunctionDeclarator = (ParameterTypeList / IdentifierList) JavaThrows. */
1152: public final Out visitFunctionDeclarator(final GNode n) {
1153: assert "C".equals(context()._activeLanguage);
1154: /* TD 41 jeannie.CodeGenerator.visitFunctionDeclarator: drop the throws clause */
1155: return visit(n);
1156: }
1157:
1158: /** Visit a FunctionDefinition = ["__extension__"] [DeclarationSpecifiers] Declarator
1159: * [DeclarationList] CompoundStatement. */
1160: public final Out visitFunctionDefinition(final GNode n) {
1161: assert "C".equals(context()._activeLanguage);
1162: if (!Utilities.containsCToJavaTransition(n))
1163: return visit(n);
1164: _table.enter(n);
1165: final String functionName = SymbolTable.fromNameSpace(_table
1166: .current().getName());
1167: final String javaEnvClassName = freshIdentifier("JavaEnvFor_"
1168: + functionName);
1169: final String cEnvStructName = freshIdentifier("CEnvFor_"
1170: + functionName);
1171: final FunctionT function = ((Type) _table.current().getParent()
1172: .lookupLocally(functionName)).resolve().toFunction();
1173: _contexts.push(new Context("C", cEnvStructName, true,
1174: javaEnvClassName, context()._javaEnvPackageName, true,
1175: null, function.getResult()));
1176: final Out childOut = (Out) dispatch(n.getNode(4));
1177: final List<Node> cExternalDeclarations = visitMethodDeclaration_cExternalDeclarations(childOut);
1178: final GNode cNode;
1179: {
1180: final Node body;
1181: final GNode javaEnvNode = GNode.create("StringConstant",
1182: '"' + context()._javaEnvPackageName
1183: + javaEnvClassName + '"');
1184: final GNode copyFormals = setLoc(n.getGeneric(2), GNode
1185: .create("CompoundStatement", function
1186: .getParameters().size() - 1));
1187: for (final Type formal : function.getParameters()) {
1188: final String srcId = formal.toVariable().getName();
1189: if (!"env".equals(srcId)) {
1190: final String fieldName = liftIdC(
1191: declaringScope(srcId), srcId, formal
1192: .toVariable().getType(),
1193: childOut._cMembers);
1194: final Node copy = _astFactoryC.setPCEnvField(
1195: fieldName, GNode.create(
1196: "PrimaryIdentifier", srcId));
1197: copyFormals.add(copy);
1198: }
1199: }
1200: assert function.getResult().hasTag(Tag.VOID); //TD 06 C function definition that also contains Java code somewhere and returns non-void
1201: body = _astFactoryC.closureStatement(cEnvStructName,
1202: copyFormals, javaEnvNode, childOut._cNode);
1203: cNode = n;
1204: cNode.set(4, setLoc(childOut._cNode, (GNode) body));
1205: }
1206: final List<Node> javaTopLevelDeclarations;
1207: {
1208: final GNode classBody = GNode.create("ClassBody",
1209: childOut._javaMembers.size());
1210: classBody.addAll(childOut._javaMembers);
1211: final GNode modifiers = GNode.create("Modifiers", GNode
1212: .create("Modifier", "final"));
1213: final GNode classDecl = setLoc(n, GNode.create(
1214: "ClassDeclaration", modifiers,
1215: context()._javaEnvClassName, null, null, null,
1216: classBody));
1217: javaTopLevelDeclarations = new ArrayList<Node>(1);
1218: javaTopLevelDeclarations.add(classDecl);
1219: }
1220: final Out ownOut = new Out(cExternalDeclarations,
1221: new ArrayList<Node>(), cNode, javaTopLevelDeclarations,
1222: null);
1223: _contexts.pop();
1224: _table.exit(n);
1225: return ownOut;
1226: }
1227:
1228: /** Visit a JavaImports = ImportDeclaration*. */
1229: public final Out visitJavaImports(final GNode n) {
1230: assert "C".equals(context()._activeLanguage);
1231: /* TD 41 jeannie.CodeGenerator.visitJavaImports: drop (or don't dispatch in first place) */
1232: return visit(n);
1233: }
1234:
1235: /** Visit a JavaInCBlock = JavaInJavaBlock. */
1236: public final Out visitJavaInCBlock(final GNode n) {
1237: return javaInCCode(n.getGeneric(0), false);
1238: }
1239:
1240: /** Visit a JavaInCExpression = JeannieJava.UnaryExpression. */
1241: public final Out visitJavaInCExpression(final GNode n) {
1242: return javaInCCode(n.getGeneric(0), true);
1243: }
1244:
1245: /** Visit a JavaInCStatement = TryStatement / SynchronizedStatement / ThrowStatement. */
1246: public final Out visitJavaInCStatement(final GNode n) {
1247: return javaInCCode(n.getGeneric(0), false);
1248: }
1249:
1250: /** Visit a JavaInJavaBlock = JeannieJava.DeclarationOrStatement*. */
1251: public final Out visitJavaInJavaBlock(final GNode n) {
1252: assert "Java".equals(context()._activeLanguage);
1253: final Out genericOut = visit(n);
1254: assert genericOut._javaNode.hasName("JavaInJavaBlock");
1255: final Out ownOut = new Out(genericOut._cExternalDeclarations,
1256: genericOut._cMembers, genericOut._cNode,
1257: genericOut._javaMembers, setLoc(n, GNode.create(
1258: "Block", n.size())));
1259: for (int i = 0; i < n.size(); i++)
1260: ownOut._javaNode.add(i, genericOut._javaNode.get(i));
1261: return ownOut;
1262: }
1263:
1264: /** Visit a JavaThrows = [ThrowsClause]. */
1265: public final Out visitJavaThrows(final GNode n) {
1266: assert "C".equals(context()._activeLanguage);
1267: /* TD 41 jeannie.CodeGenerator.visitJavaThrows: drop (or don't dispatch in first place) */
1268: return visit(n);
1269: }
1270:
1271: /** Visit a JavaType = Java.TypeName. */
1272: public final Out visitJavaType(final GNode n) {
1273: assert "C".equals(context()._activeLanguage);
1274: final Type cType = Utilities.pureCType(_table, _runtime,
1275: getType(n));
1276: final GNode ownNode = Utilities.cTypeToAst(cType, null,
1277: "TypeName");
1278: final Out ownOut = new Out(new ArrayList<Node>(),
1279: new ArrayList<Node>(), ownNode, new ArrayList<Node>(),
1280: null);
1281: return ownOut;
1282: }
1283:
1284: /**
1285: * Visit a MethodDeclaration = Modifiers null Type Identifier FormalParameters [Dimensions]
1286: * [ThrowsClause] [Block] (gosling_et_al_2000 <a
1287: * href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#40420">§8.4</a>,
1288: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#41652">8.8</a>,
1289: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/interfaces.doc.html#78651">9.4</a>).
1290: */
1291: public final Out visitMethodDeclaration(final GNode n) {
1292: assert "Java".equals(context()._activeLanguage);
1293: if (!Utilities.containsJavaToCTransition(n))
1294: return visit(n);
1295: _table.enter(n);
1296: final MethodT method = JavaEntities.currentMethod(_table);
1297: final String javaEnvClassName = freshIdentifier("JavaEnvFor_"
1298: + method.getName());
1299: final String cEnvStructName = freshIdentifier("CEnvFor_"
1300: + Utilities.jniMangledName(_table, method));
1301: _contexts.push(new Context("Java", cEnvStructName, false,
1302: javaEnvClassName, context()._javaEnvPackageName,
1303: Utilities.javaIsStaticMethod(n), null, method
1304: .getResult()));
1305: final Out childOut = (Out) dispatch(n.getGeneric(7));
1306: final Out ownOut = new Out(
1307: visitMethodDeclaration_cExternalDeclarations(childOut),
1308: new ArrayList<Node>(), null,
1309: visitMethodDeclaration_javaMembers(n, childOut),
1310: visitMethodDeclaration_javaNode(n));
1311: _contexts.pop();
1312: _table.exit(n);
1313: return ownOut;
1314: }
1315:
1316: private List<Node> visitMethodDeclaration_cExternalDeclarations(
1317: final Out childOut) {
1318: final List<Node> members = new ArrayList<Node>(
1319: childOut._cMembers.size());
1320: members.addAll(childOut._cMembers);
1321: final List<Node> result = new ArrayList<Node>(
1322: 1 + childOut._cExternalDeclarations.size());
1323: final GNode struct = (GNode) _astFactoryC.declareStruct(
1324: context()._cEnvStructName, members);
1325: result.add(setLoc(null == childOut._cNode ? childOut._javaNode
1326: : childOut._cNode, struct));
1327: result.addAll(childOut._cExternalDeclarations);
1328: return result;
1329: }
1330:
1331: private List<Node> visitMethodDeclaration_javaMembers(
1332: final GNode n, final Out childOut) {
1333: final GNode nodeFormals = n.getGeneric(4);
1334: // field for caching result and formals
1335: if (!Utilities.javaIsVoidMethod(n))
1336: liftIdJava(currentMethodScope(), n, "returnResult",
1337: getType(n).toMethod().getResult(),
1338: childOut._javaMembers);
1339: for (final Object o : nodeFormals) {
1340: final GNode formal = (GNode) o;
1341: final String srcId = formal.getString(3);
1342: liftIdJava(declaringScope(srcId), formal, srcId,
1343: getType(formal), childOut._javaMembers);
1344: }
1345: // constructor
1346: final List<Node> statements = new ArrayList<Node>();
1347: final String idAbrupt = liftIdJava(currentMethodScope(), n,
1348: "returnAbrupt", JavaEntities.nameToBaseType("boolean"),
1349: childOut._javaMembers);
1350: statements.add(GNode.create("ExpressionStatement",
1351: _astFactoryJava.setThisDotField(idAbrupt, GNode.create(
1352: "BooleanLiteral", "false"))));
1353: for (final Object o : nodeFormals) {
1354: final GNode formal = (GNode) o;
1355: final String srcId = formal.getString(3);
1356: final String tgtId = _javaSubstitutions.get(
1357: declaringScope(srcId), srcId);
1358: statements.add(GNode.create("ExpressionStatement",
1359: _astFactoryJava.setThisDotField(tgtId, idNode(
1360: formal, srcId))));
1361: }
1362: statements.add(childOut._javaNode);
1363: final GNode constructor = GNode.create(
1364: "ConstructorDeclaration", GNode.create("Modifiers",
1365: false), null, context()._javaEnvClassName,
1366: nodeFormals, null, _astFactoryJava.block(statements));
1367: // class declaration
1368: childOut._javaMembers.add(constructor);
1369: final GNode classBody = GNode.create("ClassBody",
1370: childOut._javaMembers.size());
1371: classBody.addAll(childOut._javaMembers);
1372: final GNode modifiers = context()._javaIsStatic ? GNode.create(
1373: "Modifiers", GNode.create("Modifier", "private"), GNode
1374: .create("Modifier", "static"), GNode.create(
1375: "Modifier", "final")) : GNode.create(
1376: "Modifiers", GNode.create("Modifier", "private"), GNode
1377: .create("Modifier", "final"));
1378: final GNode classDecl = setLoc(n, GNode.create(
1379: "ClassDeclaration", modifiers,
1380: context()._javaEnvClassName, null, null, null,
1381: classBody));
1382: final List<Node> result = new ArrayList<Node>(1);
1383: result.add(classDecl);
1384: return result;
1385: }
1386:
1387: private GNode visitMethodDeclaration_javaNode(final GNode n) {
1388: final List<Node> actuals = new ArrayList<Node>(n.getGeneric(4)
1389: .size());
1390: for (final Object o : n.getGeneric(4))
1391: actuals.add(idNode((Locatable) o, ((Node) o).getString(3)));
1392: final GNode clazz = GNode.create("QualifiedIdentifier",
1393: context()._javaEnvClassName);
1394: final Node body;
1395: if (Utilities.javaIsVoidMethod(n)) {
1396: body = _astFactoryJava.closureStatement(clazz, actuals);
1397: } else {
1398: final String resultFieldName = _javaSubstitutions.get(
1399: currentMethodScope(), "returnResult");
1400: body = _astFactoryJava.closureExpression(clazz, actuals,
1401: resultFieldName);
1402: }
1403: final GNode result = setLoc(n, GNode.create(
1404: "MethodDeclaration", 8));
1405: result.add(0, GNode.create("Modifiers"));
1406: for (final Object o : n.getGeneric(0))
1407: if (!"native".equals(((Node) o).getString(0)))
1408: result.getGeneric(0).add(o);
1409: for (int i = 1; i < 7; i++)
1410: result.add(i, n.get(i));
1411: result.add(7, body);
1412: return result;
1413: }
1414:
1415: /**
1416: * Visit a PrimaryIdentifier = Identifier (gosling_et_al_2000 <a
1417: * href="http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#106941">§6.5</a>).
1418: */
1419: public final Out visitPrimaryIdentifier(final GNode n) {
1420: final String id = n.getString(0);
1421: final Out ownOut;
1422: final Type type = getType(n);
1423: if ("C".equals(context()._activeLanguage)) {
1424: final GNode cNode;
1425: final List<Node> cMembers = new ArrayList<Node>();
1426: if (null == type || null == context()._cEnvStructName) {
1427: cNode = n;
1428: } else if (!type.isVariable()) {
1429: if (type.hasAttribute(Constants.ATT_STORAGE_AUTO, true))
1430: cNode = (GNode) _astFactoryC.getPCEnvField(liftIdC(
1431: declaringScope(id), id, type, cMembers));
1432: else
1433: cNode = n;
1434: } else {
1435: final VariableT var = type.toVariable();
1436: if (VariableT.Kind.LOCAL == var.getKind()
1437: || VariableT.Kind.PARAMETER == var.getKind())
1438: cNode = (GNode) _astFactoryC.getPCEnvField(liftIdC(
1439: declaringScope(id), id, var.getType(),
1440: cMembers));
1441: else
1442: cNode = n;
1443: }
1444: ownOut = new Out(new ArrayList<Node>(0), cMembers, setLoc(
1445: n, cNode), new ArrayList<Node>(0), null);
1446: } else {
1447: final GNode javaNode;
1448: final List<Node> javaMembers = new ArrayList<Node>();
1449: if (null == context()._javaEnvClassName
1450: || !JavaEntities.isParameterT(type)
1451: && !JavaEntities.isLocalT(type))
1452: javaNode = n;
1453: else
1454: javaNode = (GNode) _astFactoryJava
1455: .getThisDotField(liftIdJava(declaringScope(id),
1456: n, id, type, javaMembers));
1457: ownOut = new Out(new ArrayList<Node>(0),
1458: new ArrayList<Node>(0), null, javaMembers, setLoc(
1459: n, javaNode));
1460: }
1461: return ownOut;
1462: }
1463:
1464: /**
1465: * Visit a ReturnStatement = [Expression] (gosling_et_al_2000 <a
1466: * href="http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#6767">§14.16</a>).
1467: */
1468: public final Out visitReturnStatement(final GNode n) {
1469: final Out ownOut;
1470: if ("C".equals(context()._activeLanguage)) {
1471: if (null == context()._cEnvStructName) {
1472: ownOut = visit(n);
1473: } else {
1474: final List<Node> cExternalDeclarations = new ArrayList<Node>();
1475: final List<Node> cMembers = new ArrayList<Node>();
1476: final List<Node> javaMembers = new ArrayList<Node>();
1477: final GNode ownNode;
1478: final GNode jumpStatement = abruptFlowJump(n, cMembers);
1479: final GNode abruptStringAst = cStringNode(liftIdJava(
1480: currentMethodScope(), n, "returnAbrupt",
1481: JavaEntities.nameToBaseType("boolean"),
1482: javaMembers));
1483: if (null == n.get(0)) {
1484: ownNode = (GNode) _astFactoryC.returnVoid(
1485: abruptStringAst, jumpStatement);
1486: } else {
1487: final Out childOut = (Out) dispatch(n.getGeneric(0));
1488: cExternalDeclarations
1489: .addAll(childOut._cExternalDeclarations);
1490: cMembers.addAll(childOut._cMembers);
1491: javaMembers.addAll(childOut._javaMembers);
1492: final Type fun = Utilities
1493: .currentFunctionOrMethod(_table);
1494: assert fun.isMethod(); //TD 06 C return statement in C function that also contains Java code somewhere
1495: final Type javaType = Utilities.returnType(fun);
1496: final GNode resultStringAst = cStringNode(liftIdJava(
1497: currentMethodScope(), n, "returnResult",
1498: javaType, javaMembers));
1499: final GNode signatureStringAst = cStringNode(JavaEntities
1500: .typeToDescriptor(_table, javaType));
1501: final String setter = "Set"
1502: + Utilities.javaTypeToApiType(javaType,
1503: true, false) + "Field";
1504: ownNode = (GNode) _astFactoryC.returnResult(
1505: resultStringAst, signatureStringAst,
1506: setter, childOut._cNode, abruptStringAst,
1507: jumpStatement);
1508: }
1509: ownOut = new Out(cExternalDeclarations, cMembers,
1510: setLoc(n, ownNode), javaMembers, null);
1511: }
1512: } else {
1513: if (null == context()._javaEnvClassName) {
1514: ownOut = visit(n);
1515: } else {
1516: final List<Node> cExternalDeclarations = new ArrayList<Node>();
1517: final List<Node> cMembers = new ArrayList<Node>();
1518: final List<Node> javaMembers = new ArrayList<Node>();
1519: final Type fun = Utilities
1520: .currentFunctionOrMethod(_table);
1521: assert fun.isMethod(); //TD 06 Java return statement in C function
1522: final Type javaType = fun.toMethod().getResult();
1523: final Node ownNode;
1524: final String substAbrupt = liftIdJava(
1525: currentMethodScope(), n, "returnAbrupt",
1526: JavaEntities.nameToBaseType("boolean"),
1527: javaMembers);
1528: if (null == n.get(0)) {
1529: ownNode = _astFactoryJava.returnVoid(substAbrupt);
1530: } else {
1531: final Out childOut = (Out) dispatch(n.getGeneric(0));
1532: cExternalDeclarations
1533: .addAll(childOut._cExternalDeclarations);
1534: cMembers.addAll(childOut._cMembers);
1535: javaMembers.addAll(childOut._javaMembers);
1536: final String substResult = liftIdJava(
1537: currentMethodScope(), n, "returnResult",
1538: javaType, javaMembers);
1539: ownNode = _astFactoryJava.returnResult(substResult,
1540: childOut._javaNode, substAbrupt);
1541: }
1542: ownOut = new Out(cExternalDeclarations, cMembers, null,
1543: javaMembers, setLoc(n, (GNode) ownNode));
1544: }
1545: }
1546: return ownOut;
1547: }
1548:
1549: /**
1550: * Visit a ThisExpression = [Expression] (gosling_et_al_2000
1551: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#251519">§15.8.3</a>,
1552: * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#251603">§15.8.4</a>).
1553: */
1554: public final Out visitThisExpression(final GNode n) {
1555: assert "Java".equals(context()._activeLanguage);
1556: assert null == n.get(0); //TD 41 allow qualified this expressions in input
1557: final String s = JavaEntities.currentType(_table).toClass()
1558: .getName();
1559: final GNode ownNode = setLoc(n, GNode.create("ThisExpression",
1560: GNode.create("Type", GNode.create(
1561: "QualifiedIdentifier", s), GNode
1562: .create("Dimensions"))));
1563: return visit(ownNode);
1564: }
1565:
1566: /** Visit a TranslationUnit = [JavaImports] ExternalDeclaration* Annotations. */
1567: public final Out visitTranslationUnit(final GNode n) {
1568: assert _contexts.isEmpty();
1569: assert false && null == n;
1570: /* TD 41 jeannie.CodeGenerator.visitTranslationUnit: invocation API, when outermost language is C */
1571: return null;
1572: }
1573:
1574: /** Visit a WithStatement = (JeannieC.Declaration / JeannieC.AssignmentExpression) CInCBlock. */
1575: public final Out visitWithStatement(final GNode n) {
1576: assert "C".equals(context()._activeLanguage);
1577: _table.enter(n);
1578: final GNode initNode = n.getGeneric(0);
1579: final String id;
1580: final Type cPtrType, javaType;
1581: final Out lhsOut, rhsOut;
1582: if (initNode.hasName("Declaration")) {
1583: final GNode dtor = initNode.getGeneric(2).getGeneric(0);
1584: final GNode jNode = dtor.getGeneric(4);
1585: id = CAnalyzer.getDeclaredId(dtor.getGeneric(1)).getString(
1586: 0);
1587: lhsOut = (Out) dispatch(setLoc(dtor.getGeneric(1), GNode
1588: .create("PrimaryIdentifier", id)));
1589: rhsOut = (Out) dispatch(jNode);
1590: cPtrType = ((Type) _table.current().lookupLocally(id));
1591: javaType = Utilities.cTypeToJavaType(_table, _runtime,
1592: jNode, getType(jNode));
1593: } else {
1594: assert initNode.hasName("AssignmentExpression");
1595: final GNode cNode = initNode.getGeneric(0), jNode = initNode
1596: .getGeneric(2);
1597: id = cNode.getString(0);
1598: lhsOut = (Out) dispatch(cNode);
1599: rhsOut = (Out) dispatch(jNode);
1600: cPtrType = getType(cNode);
1601: javaType = Utilities.cTypeToJavaType(_table, _runtime,
1602: jNode, getType(jNode));
1603: }
1604: _contexts.push(new Context(context()._activeLanguage,
1605: context()._cEnvStructName, context()._cHasEnv,
1606: context()._javaEnvClassName,
1607: context()._javaEnvPackageName, context()._javaIsStatic,
1608: id, context()._snippetType));
1609: final Out blockOut = (Out) dispatch(n.getGeneric(1));
1610: _contexts.pop();
1611: final List<Node> cMembers = new ArrayList<Node>(), javaMembers = new ArrayList<Node>();
1612: final Node ownNode;
1613: {
1614: final GNode abruptFlowCheck = abruptFlowCheck(n, cMembers,
1615: javaMembers);
1616: final Node init = rhsOut._cNode;
1617: final Scope scope = declaringScope(id);
1618: final String label = liftIdCLabel(scope, "release_" + id);
1619: final Node body = blockOut._cNode;
1620: final String caField = liftIdC(scope, id, cPtrType,
1621: cMembers);
1622: final String releaseAbrupt = liftIdC(scope, id
1623: + "ReleaseAbrupt", typedefType("jint"), cMembers);
1624: if (JavaTypeConverter.isIdentical(javaType, JavaEntities
1625: .tString(_table))) {
1626: final Type cJniType = typedefType("jstring");
1627: final String jsField = liftIdC(scope,
1628: id + "JavaString", cJniType, cMembers);
1629: ownNode = isUtf8(cPtrType, javaType) ? _astFactoryC
1630: .withStringUTF(jsField, init, releaseAbrupt,
1631: caField, body, label, abruptFlowCheck)
1632: : _astFactoryC.withString(jsField, init,
1633: releaseAbrupt, caField, body, label,
1634: abruptFlowCheck);
1635: } else {
1636: final Type tElem = JavaEntities
1637: .arrayElementType(javaType.toArray());
1638: final boolean primiv = JavaEntities.isPrimitiveT(tElem);
1639: final Type cJniType = typedefType(primiv ? "j"
1640: + Utilities.javaTypeToApiType(javaType)
1641: : "jobject");
1642: final String jaField = liftIdC(scope, id + "JavaArray",
1643: cJniType, cMembers);
1644: if (primiv) {
1645: final String arrayDeclString = "j"
1646: + Utilities.javaTypeToApiType(tElem)
1647: + " ca[length];";
1648: final GNode caNode = Utilities.cStringToAst(
1649: "Declaration", arrayDeclString, Utilities
1650: .standardJniTypeDefs());
1651: final String getRegion = withArrayFunction(
1652: javaType, true);
1653: final String setRegion = withArrayFunction(
1654: javaType, false);
1655: ownNode = _astFactoryC.withPrimitiveArray(jaField,
1656: init, releaseAbrupt, caNode, caField,
1657: getRegion, body, label, setRegion,
1658: abruptFlowCheck);
1659: } else {
1660: ownNode = _astFactoryC.withReferenceArray(jaField,
1661: init, releaseAbrupt, caField, body, label,
1662: abruptFlowCheck);
1663: }
1664: }
1665: }
1666: final Out ownOut = new Out(new ArrayList<Node>(0), cMembers,
1667: setLoc(n, (GNode) ownNode), javaMembers, null);
1668: ownOut.addAll(lhsOut).addAll(rhsOut).addAll(blockOut);
1669: _table.exit(n);
1670: return ownOut;
1671: }
1672:
1673: private String withArrayFunction(final Type javaType,
1674: final boolean isAquire) {
1675: final StringBuffer result = new StringBuffer();
1676: result.append(isAquire ? "Get" : "Set");
1677: result
1678: .append(Utilities.javaTypeToApiType(javaType, true,
1679: true));
1680: result.append("Region");
1681: return result.toString();
1682: }
1683: }
|