001: /**************************************************************************/
002: /* N I C E */
003: /* A high-level object-oriented research language */
004: /* (c) Daniel Bonniot 2002 */
005: /* */
006: /* This program is free software; you can redistribute it and/or modify */
007: /* it under the terms of the GNU General Public License as published by */
008: /* the Free Software Foundation; either version 2 of the License, or */
009: /* (at your option) any later version. */
010: /* */
011: /**************************************************************************/package nice.lang.inline;
012:
013: /**
014: Tests if a value belongs to a class.
015:
016: The second parameter should be a QuoteExp wrapping a
017: <code>gnu.bytecode.Type</code>.
018:
019: @version $Date: 2005/03/09 14:47:48 $
020: @author Daniel Bonniot (Daniel.Bonniot@inria.fr)
021: */
022:
023: import gnu.bytecode.*;
024: import gnu.mapping.*;
025: import gnu.expr.*;
026:
027: public class Instanceof extends Procedure2 implements Inlineable {
028: private final boolean option;
029:
030: public static Instanceof create(String param) {
031: if ("option".equals(param))
032: return optionInstance;
033:
034: return instance;
035: }
036:
037: private Instanceof(boolean option) {
038: this .option = option;
039: }
040:
041: public final static Instanceof instance = new Instanceof(false);
042: public final static Instanceof optionInstance = new Instanceof(true);
043:
044: public void compile(ApplyExp exp, Compilation comp, Target target) {
045: Expression[] args = exp.getArgs();
046: Expression value = args[0];
047: Expression typeExp = args[1];
048:
049: if (typeExp instanceof QuoteExp
050: && ((QuoteExp) typeExp).getValue() instanceof Type)
051: compile(value, (Type) ((QuoteExp) typeExp).getValue(),
052: comp, exp);
053: else
054: compile(value, typeExp, comp);
055:
056: target.compileFromStack(comp, Type.boolean_type);
057: }
058:
059: private void compile(Expression value, Type type, Compilation comp,
060: Expression applyExp) {
061: gnu.bytecode.CodeAttr code = comp.getCode();
062:
063: // instanceof on boolean can make sense
064: if (type == Type.boolean_type)
065: type = Type.boolean_ctype;
066:
067: if (type instanceof PrimType)
068: throw new bossa.util.UserError(applyExp,
069: "instanceof cannot be used with primitive types");
070:
071: value.compile(comp, Target.pushObject);
072:
073: if (type == nice.tools.code.SpecialArray.wrappedType()
074: && code.topType().isArray()) {
075: /* If we want to test if the value is 'instanceof Array', and
076: we know statically that it is an array, we just need to make
077: sure it is not null.
078: */
079: if (option)
080: code.emitPushBoolean(true);
081: else {
082: code.emitIfNull();
083: code.emitPushBoolean(false);
084: code.emitElse();
085: code.emitPushBoolean(true);
086: code.emitFi();
087: }
088: } else {
089: if (option) {
090: code.emitDup();
091: code.emitIfNull();
092: code.emitPop(1);
093: code.emitPushBoolean(true);
094: code.emitElse();
095: }
096:
097: code.emitInstanceof(type);
098:
099: if (option)
100: code.emitFi();
101: }
102: }
103:
104: private void compile(Expression value, Expression type,
105: Compilation comp) {
106: gnu.bytecode.CodeAttr code = comp.getCode();
107:
108: if (option) {
109: code.emitDup();
110: code.emitIfNull();
111: code.emitPop(1);
112: code.emitPushBoolean(true);
113: code.emitElse();
114: }
115:
116: type.compile(comp, Target.pushObject);
117: value.compile(comp, Target.pushObject);
118: code.emitInvoke(ClassType.make("java.lang.Class")
119: .getDeclaredMethod("isInstance", 1));
120:
121: if (option)
122: code.emitFi();
123: }
124:
125: public Type getReturnType(Expression[] args) {
126: return Type.boolean_type;
127: }
128:
129: /****************************************************************
130: * Interpretation
131: ****************************************************************/
132:
133: public Object apply2(Object arg1, Object arg2) {
134: throw new Error("Not implemented");
135: }
136: }
|