blob: 56e0f4b238662fb425c4790f055e08030ddaefc0 [file] [log] [blame]
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.model.types;
import com.apple.internal.jobjc.generator.classes.RootJObjCClass;
import com.apple.internal.jobjc.generator.model.CFType;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Opaque;
import com.apple.internal.jobjc.generator.model.Struct;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.ComplexCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.IDCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.NSClassCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.PointerCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.SELCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.StructCoderDescriptor;
import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.UnknownCoderDescriptor;
import com.apple.internal.jobjc.generator.model.types.NType.NPrimitive;
import com.apple.jobjc.ID;
import com.apple.jobjc.NSClass;
import com.apple.jobjc.NativeArgumentBuffer;
import com.apple.jobjc.Pointer;
import com.apple.jobjc.SEL;
public abstract class JType {
public abstract String getJavaTypeName();
public String getJavaClassName() { return getJavaTypeName().substring(getJavaTypeName().lastIndexOf('.') + 1); }
public String getJavaReturnTypeName() { return getJavaTypeName(); }
public String getReturnTypeCast() { return null; }
public String getTypeNameAsParam() { return getJavaTypeName(); }
public abstract CoderDescriptor getCoderDescriptor();
public String getDefaultReturnValue() { return "null"; }
public String getAppendableDescription() { return getJavaTypeName().substring(getJavaTypeName().lastIndexOf('.') + 1); }
/**
* Used for primitive types (like int) that can't be used as generic arguments. This returns an appropriate Java class (like Integer).
*/
public JType getParameterizableType() { return this; }
//
// Writer ops
//
public String createDeclareBuffer(String contextName) {
return "final " + NativeArgumentBuffer.class.getName() + " " + contextName + " = getRuntime().getThreadLocalState();";
}
public String createInit(final String contextName, final String functionIdentifier, final String initWithObj) {
return functionIdentifier + ".init(" + contextName + (initWithObj != null ? ", " + initWithObj : "") + ");";
}
public String createInvoke(final String contextName, final String functionIdentifier) {
return functionIdentifier + ".invoke(" + contextName + ");";
}
public String createPop(final String contextName) {
return getCoderDescriptor().getPopStatementFor(contextName, getJavaTypeName(), "returnValue", null);
}
public String createPopAddr(final String runtime, final String addr) {
return getCoderDescriptor().getPopAddrStatementFor(runtime, addr, getJavaTypeName(), "returnValue", null);
}
public String createReturn() {
final String preCast = getReturnTypeCast();
return "return " + (preCast == null ? "" : "(" + preCast + ")") + "returnValue;";
}
//
// Specialized
//
static public class JUnknown extends JType {
final Type type;
protected JUnknown(final Type type) {
this.type = type;
TypeCache.inst().getUnknownTypes().add(type);
}
@Override public String getJavaTypeName() { return "Object /* " + type + " */"; }
@Override public String getAppendableDescription() { return "Unknown"; }
@Override public CoderDescriptor getCoderDescriptor() { return UnknownCoderDescriptor.UNKNOWN_DESC; }
}
static class JVoid extends JType {
public static JVoid INST = new JVoid();
@Override public String getJavaTypeName() { return "Void"; }
@Override public String getJavaReturnTypeName() { return "void"; }
@Override public CoderDescriptor getCoderDescriptor(){ return CoderDescriptor.VOID_DESC; }
@Override public String createPop(final String contextName){ return ""; }
@Override public String createReturn(){ return ""; }
};
static class JSelector extends JType {
public static JSelector INST = new JSelector();
@Override public String getJavaTypeName() { return SEL.class.getName(); }
@Override public CoderDescriptor getCoderDescriptor() { return SELCoderDescriptor.INST; }
};
static class JCFType extends JType{
final CFType cfType;
public JCFType(final CFType cfType){ this.cfType = cfType; }
@Override public String getJavaTypeName() { return cfType.parent.pkg + "." + cfType.name + "CFType"; }
@Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; }
@Override public String createPop(final String contextName) {
return "\t\t" + getCoderDescriptor().getPopStatementFor(contextName, getJavaReturnTypeName(), "returnValue", "new " + getJavaTypeName());
}
}
static class JOpaque extends JType{
final Opaque opaque;
public JOpaque(final Opaque opaque){ this.opaque = opaque; }
@Override public String getJavaTypeName() { return opaque.parent.pkg + "." + opaque.name + "Opaque"; }
@Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; }
@Override public String createPop(final String contextName) {
return "\t\t" + getCoderDescriptor().getPopStatementFor(contextName, getJavaReturnTypeName(), "returnValue", "new " + getJavaTypeName());
}
}
static class JPointer extends JType {
static JType VOID_PTR = new JPointer(JVoid.INST);
final JType subject;
protected JPointer(final JType javaType) { this.subject = javaType; }
@Override public String getJavaTypeName() { return Pointer.class.getName() + "<" + subject.getParameterizableType().getJavaTypeName() + ">"; }
@Override public String getAppendableDescription() { return "PointerTo" + subject.getAppendableDescription(); }
@Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; }
}
static class JObject extends JType {
public static JType ID_TYPE = new JType() {
@Override public String getJavaTypeName() { return ID.class.getName(); }
@Override public String getJavaReturnTypeName() { return "<T extends " + getJavaTypeName() + "> T"; }
@Override public String getReturnTypeCast() { return "T"; }
@Override public CoderDescriptor getCoderDescriptor() { return IDCoderDescriptor.INST; }
};
final Type type;
final Clazz clazz;
public JObject(final Type type, final Clazz clazz) {
this.type = type;
this.clazz = clazz;
}
@Override public String getJavaTypeName() { return clazz.getFullPath();}
@Override public CoderDescriptor getCoderDescriptor() { return IDCoderDescriptor.INST; }
}
static class JClass extends JType {
public static JClass INST = new JClass();
@Override public String getJavaTypeName() { return NSClass.class.getName(); }
@Override public String getJavaReturnTypeName() { return "<T extends " + super.getJavaReturnTypeName() + "> T"; }
@Override public String getTypeNameAsParam() { return super.getTypeNameAsParam(); }
@Override public String getReturnTypeCast() { return "T"; }
@Override public CoderDescriptor getCoderDescriptor() { return NSClassCoderDescriptor.INST; }
};
public static class JStruct extends JType {
public final Struct struct;
public JStruct(final Struct struct) { this.struct = struct; }
@Override public String getJavaTypeName() { return struct.parent.pkg + "." + struct.name; }
@Override public String getJavaReturnTypeName() { return getJavaTypeName(); }
StructCoderDescriptor coderDescriptor = new StructCoderDescriptor(this);
@Override public CoderDescriptor getCoderDescriptor() { return coderDescriptor; }
public String createReturnValue() {
return "\t\t" + getJavaReturnTypeName() + " returnValue = " + RootJObjCClass.runtimeFrameworkInstR(struct.parent.name)
+ ".make" + struct.name + "();";
}
@Override public String createInvoke(final String contextName, final String functionIdentifier) {
return createReturnValue() + "\n\t\t" + functionIdentifier + ".invoke(" + contextName + ", returnValue);";
}
@Override public String createPop(final String contextName){ return ""; }
}
public static class JPrimitive extends JType {
final Type type;
final ComplexCoderDescriptor coderDescriptor;
final JType parameterizable;
public JPrimitive(final Type type, final ComplexCoderDescriptor coderDesc) {
this.type = type;
this.coderDescriptor = coderDesc;
this.parameterizable = new JType() {
@Override public String getJavaTypeName() { return coderDescriptor.getJavaObjectClass(); }
@Override public CoderDescriptor getCoderDescriptor() { throw new RuntimeException(); }
};
}
@Override public String getJavaTypeName() { return coderDescriptor.getName(); }
@Override public String getDefaultReturnValue() { return coderDescriptor.getDefaultReturnValue(); }
@Override public JType getParameterizableType() { return parameterizable; }
@Override public CoderDescriptor getCoderDescriptor() { return coderDescriptor; }
/**
* Return the suffix placed on java literals to indicate the type. If none applies, return ' '.
*/
public char getLiteralSuffix() {
char t = ((NPrimitive)type.type64).type;
switch(t){
case 'l': case 'L': case 'f': case 'd': return t;
case 'q': case 'Q': return 'L';
}
return ' ';
}
}
}