001: /*
002: * $Id: ByteCompiler.java,v 1.14 2002/09/16 08:05:03 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.script.compiler;
011:
012: import anvil.core.Any;
013: import anvil.core.AnyPattern;
014: import anvil.core.AnyRange;
015: import anvil.core.Array;
016: import anvil.core.Register;
017: import anvil.core.reflect.Reflection;
018: import anvil.Location;
019: import anvil.Log;
020: import anvil.doc.Doc;
021: import anvil.server.Address;
022: import anvil.server.ZoneClassLoader;
023: import anvil.server.Zone;
024: import anvil.server.CompilerPreferences;
025: import anvil.script.CompilableFunction;
026: import anvil.script.ClassType;
027: import anvil.script.Type;
028: import anvil.script.expression.Node;
029: import anvil.script.Smith;
030: import anvil.script.Module;
031: import anvil.script.ModuleEnvelope;
032: import anvil.script.expression.Node;
033: import anvil.script.statements.FunctionStatement;
034: import anvil.script.statements.SwitchStatement;
035: import anvil.java.util.BindingEnumeration;
036: import anvil.util.Conversions;
037: import anvil.java.util.Hashlist;
038: import anvil.java.util.HashlistIterator;
039: import java.io.File;
040: import java.io.FileOutputStream;
041: import java.io.DataOutputStream;
042: import java.io.IOException;
043: import java.io.PrintWriter;
044: import java.io.StringWriter;
045: import java.io.Writer;
046: import java.util.Calendar;
047: import java.util.Date;
048: import java.util.Enumeration;
049: import java.util.Vector;
050: import java.util.Stack;
051:
052: import anvil.codec.Code;
053: import anvil.codec.ClassRoom;
054: import anvil.codec.Method;
055: import anvil.codec.Field;
056: import anvil.codec.CodecConstants;
057: import anvil.codec.ConstantPool;
058: import anvil.codec.Source;
059:
060: /**
061: * class ByteCompiler
062: *
063: * @author: Jani Lehtimäki
064: */
065: public class ByteCompiler implements CodecConstants {
066:
067: public static final int L_THIS = 0;
068: public static final int L_CONTEXT = 0;
069: public static final int L_FRAME = 0;
070:
071: public String TYPE_MODULE;
072: public static final String TYPE_OBJECT = "java/lang/Object";
073: public static final String TYPE_ANY = "anvil/core/Any";
074: public static final String TYPE_ANY_OP = "anvil/core/Any$Op";
075: public static final String TYPE_ANY_ARRAY = "[Lanvil/core/Any;";
076: public static final String TYPE_CONTEXT = "anvil/script/Context";
077: public static final String TYPE_SYMBOLS = "anvil/core/Symbols";
078: public static final String TYPE_FUNCTION = "anvil/script/Function";
079: public static final String TYPE_COMPILED_SCRIPT = "anvil/script/compiler/CompiledModule";
080: public static final String TYPE_STACKFRAME = "anvil/script/StackFrame";
081:
082: public static final int GET = 0;
083: public static final int GET_BOOLEAN = 1;
084: public static final int SET = 2;
085: public static final int CHECK = 3;
086: public static final int DELETE = 4;
087:
088: private Smith _smith;
089: private ModuleEnvelope _envelope;
090: private CompilerPreferences _prefs;
091: private boolean _debug;
092: private Writer _writer;
093: private Hashlist _constants = new Hashlist();
094: private Hashlist _symbols = new Hashlist();
095: private Hashlist _texts = new Hashlist();
096: private Hashlist _reflections = new Hashlist();
097: private Vector _switches = new Vector();
098: private StringBuffer _text = new StringBuffer();
099:
100: private ClassRoom _scriptclass;
101: private ClassRoom _class;
102: private ConstantPool _pool;
103: private Code _code;
104: private Stack _classes = new Stack();
105: private Stack _codes = new Stack();
106:
107: public Field _f_const;
108: public Field _f_text;
109: public Field _f_switch;
110:
111: public ByteCompiler(Smith smith, ModuleEnvelope envelope) {
112: _smith = smith;
113: _envelope = envelope;
114: Zone zone = envelope.getAddress().getZone();
115: _prefs = zone.getCompilerPreferences();
116: _debug = zone.getDebug();
117: }
118:
119: public String getClassname() {
120: return _envelope.getClassname();
121: }
122:
123: public Module getModule() {
124: return _envelope.getModule();
125: }
126:
127: public ClassRoom getModuleClass() {
128: return _scriptclass;
129: }
130:
131: public ClassRoom getClassRoom() {
132: return _class;
133: }
134:
135: public ConstantPool getPool() {
136: return _pool;
137: }
138:
139: public void pushClass(ClassRoom clazz) {
140: if (_scriptclass == null) {
141: _scriptclass = clazz;
142: }
143: _classes.push(clazz);
144: _class = clazz;
145: _pool = clazz.getPool();
146: }
147:
148: public void popClass() {
149: _classes.pop();
150: if (!_classes.isEmpty()) {
151: _class = (ClassRoom) _classes.peek();
152: _pool = _class.getPool();
153: } else {
154: _class = null;
155: _pool = null;
156: }
157: }
158:
159: public Method getMethod() {
160: return getCode().getMethod();
161: }
162:
163: public Code getCode() {
164: return _code;
165: }
166:
167: public void pushCode(Code code) {
168: _codes.push(code);
169: _code = code;
170: }
171:
172: public void popCode() {
173: _codes.pop();
174: if (!_codes.isEmpty()) {
175: _code = (Code) _codes.peek();
176: }
177: }
178:
179: private int addText(String text) {
180: Integer slot = (Integer) _texts.get(text);
181: if (slot != null) {
182: return slot.intValue();
183: } else {
184: int ctr = _texts.size();
185: _texts.put(text, new Integer(ctr));
186: return ctr;
187: }
188: }
189:
190: public ByteCompiler text(Code code, String text, boolean newline) {
191: if (text.length() > 0) {
192: code.aload_first();
193: code.getstatic(code.getPool().addFieldRef(TYPE_MODULE,
194: "_text", "[[B"));
195: code.iconst(addText(text));
196: code.aaload();
197: code.invokevirtual(code.getPool().addMethodRef(
198: "anvil/script/Context",
199: newline ? "println" : "print", "([B)V"));
200: }
201: return this ;
202: }
203:
204: public ByteCompiler symbol(String name) {
205: return symbol(Register.register(name));
206: }
207:
208: public ByteCompiler symbol(int index) {
209: Code code = getCode();
210: String name = Register.getNameOf(index);
211: code.getstatic(getPool().addFieldRef(TYPE_MODULE, "r_" + name,
212: "I"));
213: _symbols.put(new Integer(index), name);
214: return this ;
215: }
216:
217: private int addConstant(Any value) {
218: Integer slot = (Integer) _constants.get(value);
219: if (slot != null) {
220: return slot.intValue();
221: } else {
222: int ctr = _constants.size();
223: _constants.put(value, new Integer(ctr));
224: return ctr;
225: }
226: }
227:
228: public ByteCompiler constant(Any value, boolean canchange) {
229: Code code = getCode();
230: int slot = addConstant(value);
231: code.getstatic(code.getPool().addFieldRef(TYPE_MODULE,
232: "_const", "[Lanvil/core/Any;"));
233: code.iconst(slot);
234: code.aaload();
235: if (canchange && value.isMutable()) {
236: code.invokevirtual(getPool().addMethodRef("anvil/core/Any",
237: "copy", "()Lanvil/core/Any;"));
238: }
239: return this ;
240: }
241:
242: public int addSwitch(Enumeration keys) {
243: _switches.addElement(keys);
244: return _switches.size() - 1;
245: }
246:
247: public ByteCompiler reflect(String classname) {
248: Integer slot = (Integer) _reflections.get(classname);
249: if (slot == null) {
250: slot = new Integer(_reflections.size());
251: _reflections.put(classname, slot);
252: }
253: Code code = getCode();
254: ConstantPool pool = getPool();
255: int javafield = pool.addFieldRef(TYPE_MODULE, "java$" + slot,
256: "Lanvil/core/reflect/Reflection;");
257: int contextclass = pool.addClass(TYPE_CONTEXT);
258: code.getstatic(javafield);
259: Source isnull = code.if_null();
260: code.getstatic(javafield);
261: Source notnull = code.go_to();
262: isnull.bind();
263: code.aload_first();
264: code.astring(classname);
265: code.invokevirtual(pool.addMethodRef(contextclass, "reflect",
266: "(Ljava/lang/String;)Lanvil/core/reflect/Reflection;"));
267: code.dup();
268: code.putstatic(javafield);
269: notnull.bind();
270: code.popop();
271: return this ;
272: }
273:
274: public ByteCompiler location(Location location) {
275: if (_debug && location != null) {
276: Code code = getCode();
277: Method method = code.getMethod();
278: if (method.getClassRoom().getStatic() != method) {
279: code.aload_first();
280: code.iconst(location.getLine());
281: code.invokevirtual(getPool().addMethodRef(
282: "anvil/script/StackFrameStack", "setLine",
283: "(I)V"));
284: }
285: }
286: return this ;
287: }
288:
289: public boolean compile() {
290: Code code;
291:
292: String classname = _envelope.getClassname();
293: Address address = _envelope.getAddress();
294: String pathinfo = address.getPathinfo();
295: String classsig = _envelope.getDescriptor();
296: TYPE_MODULE = classsig;
297:
298: ClassRoom clazz = new ClassRoom();
299: pushClass(clazz);
300: clazz.setClassname(classsig, null);
301: clazz.setSuperClassname("anvil/script/compiler/CompiledModule");
302: clazz.setAccessFlags(ACC_SUPER | ACC_PUBLIC);
303: ConstantPool pool = clazz.getPool();
304:
305: _f_const = clazz.createField("_const", "[Lanvil/core/Any;",
306: ACC_PUBLIC | ACC_STATIC | ACC_FINAL);
307: _f_text = clazz.createField("_text", "[[B", ACC_PUBLIC
308: | ACC_STATIC | ACC_FINAL);
309: _f_switch = clazz.createField("_switch",
310: "[Lanvil/java/util/Hashlist;", ACC_PUBLIC | ACC_STATIC
311: | ACC_FINAL);
312:
313: Method _m_const = clazz.createMethod("_const", "()V",
314: ACC_PUBLIC | ACC_STATIC);
315: Method _m_text = clazz.createMethod("_text", "()V", ACC_PUBLIC
316: | ACC_STATIC);
317: Method _m_switch = clazz.createMethod("_switch", "()V",
318: ACC_PUBLIC | ACC_STATIC);
319: Method _m_symbols = clazz.createMethod("_symbols", "()V",
320: ACC_PUBLIC | ACC_STATIC);
321: //Method _m_imports = clazz.createMethod("_imports", "()V", ACC_PUBLIC|ACC_STATIC);
322:
323: code = clazz.getStatic().getCode();
324: //code.println("MODULE-START:"+classsig);
325: code.invokestatic(_m_const.getIndex());
326: code.invokestatic(_m_text.getIndex());
327: code.invokestatic(_m_switch.getIndex());
328: code.invokestatic(_m_symbols.getIndex());
329: ((anvil.script.statements.ModuleStatement) getModule())
330: .compile(this );
331: //code.println("MODULE-END:"+classsig);
332: code.vreturn();
333:
334: /* constants */
335: code = _m_const.getCode();
336: if (_constants.size() > 0) {
337: code.iconst(_constants.size());
338: code.anewarray(TYPE_ANY);
339: Enumeration e = _constants.keys();
340: for (int i = 0; e.hasMoreElements(); i++) {
341: code.dup();
342: code.iconst(i);
343: ((Any) e.nextElement()).toCode(code);
344: code.aastore();
345: }
346: code.putstatic(_f_const);
347: }
348: code.vreturn();
349:
350: /* texts */
351: code = _m_text.getCode();
352: int getBytes = pool.addMethodRef("anvil/util/Conversions",
353: "getBytes", "(Ljava/lang/String;)[B");
354: if (_texts.size() > 0) {
355: int size = _texts.size();
356: code.iconst(size);
357: code.anewarray("[[B", 1);
358: Enumeration e = _texts.keys();
359: for (int i = 0; e.hasMoreElements(); i++) {
360: code.dup();
361: code.iconst(i);
362: code.astring((String) e.nextElement());
363: code.invokestatic(getBytes);
364: code.aastore();
365: }
366: code.putstatic(_f_text);
367: }
368: code.vreturn();
369:
370: /* switchtables */
371: code = _m_switch.getCode();
372: int n = _switches.size();
373: if (_switches.size() > 0) {
374: int hashlistclazz = pool
375: .addClass("anvil/java/util/Hashlist");
376: int hashlistctor = pool.addMethodRef(hashlistclazz,
377: "<init>", "()V");
378: int hashlistadd = pool
379: .addMethodRef(hashlistclazz, "add",
380: "(Ljava/lang/Object;Ljava/lang/Object;)Lanvil/java/util/Hashlist;");
381: int intclazz = pool.addClass("java/lang/Integer");
382: int intclazzctor = pool.addMethodRef(intclazz, "<init>",
383: "(I)V");
384: code.iconst(n);
385: code.anewarray(hashlistclazz);
386: for (int i = 0; i < n; i++) {
387: code.dup();
388: code.iconst(i);
389: code.anew(hashlistclazz);
390: code.dup();
391: code.invokespecial(hashlistctor);
392: int c = 0;
393: Enumeration keys = (Enumeration) _switches.elementAt(i);
394: while (keys.hasMoreElements()) {
395: Any key = (Any) keys.nextElement();
396: if (key != SwitchStatement.DEFAULT_MARKER) {
397: key.toCode(code);
398: code.anew(intclazz);
399: code.dup();
400: code.iconst(c++);
401: code.invokespecial(intclazzctor);
402: code.invokevirtual(hashlistadd);
403: }
404: }
405: code.aastore();
406: }
407: code.putstatic(_f_switch);
408: }
409: code.vreturn();
410:
411: /* methodindices */
412: code = _m_symbols.getCode();
413: if (_symbols.size() > 0) {
414: int register = pool.addMethodRef(pool
415: .addClass("anvil/core/Register"), "register",
416: "(Ljava/lang/String;)I");
417: BindingEnumeration e = _symbols.keysAndElements();
418: while (e.hasMoreElements()) {
419: int index = ((Integer) e.nextKey()).intValue();
420: String name = (String) e.nextElement();
421: Field field = clazz.createField("r_" + name, "I",
422: ACC_PUBLIC | ACC_STATIC | ACC_FINAL);
423: code.astring(name);
424: code.invokestatic(register);
425: code.putstatic(field);
426: }
427: }
428: code.vreturn();
429:
430: /* reflectionfields */
431: if (_reflections.size() > 0) {
432: BindingEnumeration e = _reflections.keysAndElements();
433: while (e.hasMoreElements()) {
434: int index = ((Integer) e.nextElement()).intValue();
435: clazz.createField("java$" + index,
436: "Lanvil/core/reflect/Reflection;", ACC_PUBLIC
437: | ACC_STATIC);
438: }
439: }
440:
441: popClass();
442:
443: try {
444: clazz.write(_smith);
445: return true;
446: } catch (IOException e) {
447: e.printStackTrace();
448: return false;
449: }
450: }
451:
452: public void compileArgumentList(CompilableFunction function,
453: Node[] parameters) {
454: compileArgumentList(function, parameters, -1);
455: }
456:
457: public void compileArgumentList(CompilableFunction function,
458: Node[] parameters, int contextindex) {
459: Code code = getCode();
460: ConstantPool pool = getPool();
461: int max = (parameters != null) ? parameters.length : 0;
462: int c = 0;
463: int n = function.getParameterCount();
464: for (int i = 0; i < n; i++) {
465: Any defaultValue = function.getParameterDefault(i);
466: switch (function.getParameterType(i)) {
467: case CompilableFunction.PARAMETER_ANY:
468: if (c < max) {
469: parameters[c++].compile(this , Node.GET);
470: } else {
471: if (defaultValue != null) {
472: constant(defaultValue, true);
473: } else {
474: code.aconst_null();
475: }
476: }
477: break;
478:
479: case CompilableFunction.PARAMETER_OBJECT:
480: if (c < max) {
481: parameters[c++].compile(this , Node.GET);
482: code.invokevirtual(pool.addMethodRef(TYPE_ANY,
483: "toObject", "()Ljava/lang/Object;"));
484: } else {
485: if (defaultValue != null) {
486: constant(defaultValue, true);
487: code.invokevirtual(pool.addMethodRef(TYPE_ANY,
488: "toObject", "()Ljava/lang/Object;"));
489: } else {
490: code.aconst_null();
491: }
492: }
493: break;
494:
495: case CompilableFunction.PARAMETER_BOOLEAN:
496: if (c < max) {
497: Node node = parameters[c++];
498: if (node.isConstant()) {
499: code.iconst(node.eval().toBoolean());
500: } else {
501: node.compile(this , Node.GET_BOOLEAN);
502: }
503: } else {
504: if (defaultValue != null) {
505: code.iconst(defaultValue.toBoolean());
506: } else {
507: code.iconst(false);
508: }
509: }
510: break;
511:
512: case CompilableFunction.PARAMETER_INT:
513: if (c < max) {
514: Node node = parameters[c++];
515: if (node.isConstant()) {
516: code.iconst(node.eval().toInt());
517: } else {
518: node.compile(this , Node.GET);
519: code.invokevirtual(pool.addMethodRef(TYPE_ANY,
520: "toInt", "()I"));
521: }
522: } else {
523: if (defaultValue != null) {
524: code.iconst(defaultValue.toInt());
525: } else {
526: code.iconst(0);
527: }
528: }
529: break;
530:
531: case CompilableFunction.PARAMETER_LONG:
532: if (c < max) {
533: Node node = parameters[c++];
534: if (node.isConstant()) {
535: code.lconst(node.eval().toLong());
536: } else {
537: node.compile(this , Node.GET);
538: code.invokevirtual(pool.addMethodRef(TYPE_ANY,
539: "toLong", "()J"));
540: }
541: } else {
542: if (defaultValue != null) {
543: code.lconst(defaultValue.toLong());
544: } else {
545: code.lconst(0);
546: }
547: }
548: break;
549:
550: case CompilableFunction.PARAMETER_DOUBLE:
551: if (c < max) {
552: Node node = parameters[c++];
553: if (node.isConstant()) {
554: code.dconst(node.eval().toDouble());
555: } else {
556: node.compile(this , Node.GET);
557: code.invokevirtual(pool.addMethodRef(TYPE_ANY,
558: "toDouble", "()D"));
559: }
560: } else {
561: if (defaultValue != null) {
562: code.dconst(defaultValue.toDouble());
563: } else {
564: code.dconst(0.0);
565: }
566: }
567: break;
568:
569: case CompilableFunction.PARAMETER_STRING:
570: if (c < max) {
571: Node node = parameters[c++];
572: if (node.isConstant()) {
573: code.astring(node.eval().toString());
574: } else {
575: node.compile(this , Node.GET);
576: code.invokevirtual(pool.addMethodRef(
577: TYPE_OBJECT, "toString",
578: "()Ljava/lang/String;"));
579: }
580: } else {
581: if (defaultValue != null) {
582: code.astring(defaultValue.toString());
583: } else {
584: code.aconst_null();
585: }
586: }
587: break;
588:
589: case CompilableFunction.PARAMETER_ARRAY: {
590: int arrayclazz = pool.addClass("anvil/core/Array");
591: int appendmethod = pool.addMethodRef(arrayclazz,
592: "append",
593: "(Lanvil/core/Any;)Lanvil/core/Array;");
594: code.anew(arrayclazz);
595: code.dup();
596: code.invokespecial(pool.addMethodRef(arrayclazz,
597: "<init>", "()V"));
598: for (; c < max; c++) {
599: code.dup();
600: parameters[c].compile(this , Node.GET);
601: code.invokevirtual(appendmethod);
602: }
603: }
604: break;
605:
606: case CompilableFunction.PARAMETER_ANYLIST:
607: case CompilableFunction.PARAMETER_REST:
608: if (c >= max) {
609: code.getstatic(pool.addFieldRef(TYPE_ANY,
610: "EMPTY_TUPLE", "Lanvil/core/AnyTuple;"));
611: } else {
612: int tupleclazz = pool
613: .addClass("anvil/core/AnyTuple");
614: int appendmethod = pool.addMethodRef(tupleclazz,
615: "append",
616: "(Lanvil/core/Any;)Lanvil/core/Array;");
617: code.anew(tupleclazz);
618: code.dup();
619: code.iconst(max - c);
620: code.anewarray(TYPE_ANY);
621: int index = 0;
622: for (; c < max; c++) {
623: code.dup();
624: code.iconst(index++);
625: parameters[c].compile(this , Node.GET);
626: code.aastore();
627: }
628: code.invokespecial(pool.addMethodRef(tupleclazz,
629: "<init>", "([Lanvil/core/Any;)V"));
630: }
631: break;
632:
633: case CompilableFunction.PARAMETER_LIST:
634: int len = max - c;
635: if (len <= 0) {
636: code.getstatic(pool.addFieldRef(TYPE_ANY, "ARRAY0",
637: "[Lanvil/core/Any;"));
638: } else {
639: code.iconst(len);
640: code.anewarray(TYPE_ANY);
641: int index = 0;
642: for (; c < max; c++) {
643: code.dup();
644: code.iconst(index++);
645: parameters[c].compile(this , Node.GET);
646: code.aastore();
647: }
648: }
649: break;
650:
651: case CompilableFunction.PARAMETER_CONTEXT:
652: if (contextindex == -1) {
653: code.aload_first();
654: } else {
655: code.aload(contextindex);
656: }
657: break;
658: }
659: }
660: }
661:
662: public void compileArgumentList(Node[] parameters) {
663: Code code = getCode();
664: ConstantPool pool = getPool();
665:
666: int n = (parameters != null) ? parameters.length : 0;
667: if (n == 0) {
668: code.getstatic(pool.addFieldRef(TYPE_ANY, "ARRAY0",
669: "[Lanvil/core/Any;"));
670: return;
671: }
672:
673: boolean hasSplices = false;
674: for (int i = 0; i < n; i++) {
675: if (parameters[i].typeOf() == Node.EXPR_SPLICE) {
676: hasSplices = true;
677: break;
678: }
679: }
680:
681: if (hasSplices) {
682: int clazz = pool.addClass("anvil/script/ParameterList");
683: int splicemethod = pool.addMethodRef(clazz, "splice",
684: "(Lanvil/core/Any;)Lanvil/script/ParameterList;");
685: int addmethod = pool.addMethodRef(clazz, "add",
686: "(Lanvil/core/Any;)Lanvil/script/ParameterList;");
687: code.anew(clazz);
688: code.dup();
689: code.iconst(n);
690: code.invokespecial(pool.addMethodRef(clazz, "<init>",
691: "(I)V"));
692: for (int i = 0; i < n; i++) {
693: parameters[i].compile(this , Node.GET);
694: if (parameters[i].typeOf() == Node.EXPR_SPLICE) {
695: code.invokevirtual(splicemethod);
696: } else {
697: code.invokevirtual(addmethod);
698: }
699: }
700: code.invokevirtual(pool.addMethodRef(clazz, "toArray",
701: "()[Lanvil/core/Any;"));
702: } else {
703: code.iconst(n);
704: code.anewarray(TYPE_ANY);
705: for (int i = 0; i < n; i++) {
706: code.dup();
707: code.iconst(i);
708: parameters[i].compile(this , Node.GET);
709: code.aastore();
710: }
711: }
712: }
713:
714: public void compileCall(CompilableFunction function,
715: Node[] parameters) {
716: compileArgumentList(function, parameters);
717: getCode().invokestatic(function.getTypeRef(getPool()));
718: }
719:
720: public static String getSignature(CompilableFunction function) {
721: StringBuffer sig = new StringBuffer();
722: int n = function.getParameterCount();
723: sig.append('(');
724: for (int i = 0; i < n; i++) {
725: sig.append(CompilableFunction.SIGNATURES[function
726: .getParameterType(i)]);
727: }
728: sig.append(')');
729: sig
730: .append(CompilableFunction.SIGNATURES[CompilableFunction.PARAMETER_ANY]);
731: return sig.toString();
732: }
733:
734: public void any2boolean() {
735: Code code = getCode();
736: code.invokevirtual(code.getPool().addMethodRef(
737: "anvil/core/Any", "toBoolean", "()Z"));
738: }
739:
740: public void boolean2any() {
741: Code code = getCode();
742: code.invokestatic(code.getPool().addMethodRef(
743: "anvil/script/compiler/CompiledModule", "b2a",
744: "(Z)Lanvil/core/Any;"));
745: }
746:
747: public void accessInstance(ClassType context, ClassType target) {
748: Code code = getCode();
749: if (context == null || context == target) {
750: code.self();
751: return;
752: }
753: ConstantPool pool = code.getPool();
754: ClassType[] parents = context.getEnclosingClasses();
755: int n = parents.length;
756: for (int i = 0; i < n; i++) {
757: ClassType parent = parents[i];
758: if (parent == target) {
759: code.self();
760: code.getfield(pool.addFieldRef(
761: context.getTypeRef(pool), "this$" + i,
762: 'L' + parent.getDescriptor() + ';'));
763: return;
764: }
765: }
766: code.self();
767: }
768:
769: }
|