001: package gnu.kawa.reflect;
002:
003: import gnu.bytecode.*;
004: import gnu.mapping.*;
005: import gnu.expr.*;
006:
007: public class InstanceOf extends Procedure2 implements CanInline,
008: Inlineable {
009: protected Language language;
010:
011: public InstanceOf(Language language) {
012: this .language = language;
013: }
014:
015: public InstanceOf(Language language, String name) {
016: this .language = language;
017: setName(name);
018: }
019:
020: public Object apply2(Object arg1, Object arg2) {
021: Type type = language.asType(arg2);
022: return language.booleanObject(type.isInstance(arg1));
023: }
024:
025: static gnu.bytecode.ClassType typeType;
026: static gnu.bytecode.Method instanceMethod;
027:
028: public Expression inline(ApplyExp exp, ExpWalker walker) {
029: exp = Invoke.inlineClassName(exp, 1, (InlineCalls) walker);
030: Expression[] args = exp.getArgs();
031: if (args.length == 2) {
032: Expression value = args[0];
033: Expression texp = args[1];
034: if (texp instanceof QuoteExp) {
035: Object t = ((QuoteExp) texp).getValue();
036: if (t instanceof Type) {
037: Type type = (Type) t;
038: if (value instanceof QuoteExp)
039: return type.isInstance(((QuoteExp) value)
040: .getValue()) ? QuoteExp.trueExp
041: : QuoteExp.falseExp;
042: if (!value.side_effects()) {
043: int comp = type.compare(value.getType());
044: if (comp == 1 || comp == 0)
045: return QuoteExp.trueExp;
046: if (comp == -3)
047: return QuoteExp.falseExp;
048: }
049: }
050: }
051: }
052: return exp;
053: }
054:
055: public void compile(ApplyExp exp, Compilation comp, Target target) {
056: Expression[] args = exp.getArgs();
057: CodeAttr code = comp.getCode();
058: Type type = null;
059: Expression typeArg = args[1];
060: if (typeArg instanceof QuoteExp) {
061: try {
062: type = language.asType(((QuoteExp) typeArg).getValue());
063: } catch (Exception ex) {
064: comp.error('w', "unknown type spec: " + type);
065: }
066: } else
067: type = language.getTypeFor(typeArg);
068: if (type != null) {
069: args[0].compile(comp, Target.pushObject);
070: if (type instanceof TypeValue) {
071: ((TypeValue) type).emitIsInstance(null, comp, target);
072: return;
073: } else
074: type.emitIsInstance(code);
075: comp.usedClass(type);
076: } else {
077: if (typeType == null) {
078: typeType = ClassType.make("gnu.bytecode.Type");
079: instanceMethod = typeType.addMethod("isInstance",
080: Compilation.apply1args, Type.boolean_type,
081: gnu.bytecode.Access.PUBLIC);
082: }
083: args[1].compile(comp, typeType);
084: args[0].compile(comp, Target.pushObject);
085: code.emitInvokeVirtual(instanceMethod);
086: }
087: target
088: .compileFromStack(comp, language
089: .getTypeFor(Boolean.TYPE));
090: }
091:
092: public Type getReturnType(Expression[] args) {
093: return language.getTypeFor(Boolean.TYPE);
094: }
095:
096: public static void emitIsInstance(TypeValue type,
097: Variable incoming, Compilation comp, Target target) {
098: CodeAttr code = comp.getCode();
099: type.emitTestIf(null, null, comp);
100: ConditionalTarget cond = null;
101: if (target instanceof ConditionalTarget) {
102: cond = (ConditionalTarget) target;
103: code.emitGoto(cond.ifTrue);
104: } else
105: code.emitPushInt(1);
106: code.emitElse();
107: if (cond != null)
108: code.emitGoto(cond.ifFalse);
109: else
110: code.emitPushInt(0);
111: code.emitFi();
112: if (cond == null)
113: target.compileFromStack(comp, comp.getLanguage()
114: .getTypeFor(Boolean.TYPE));
115: }
116: }
|