001: /*
002: * $Id: EscapedVariableNode.java,v 1.13 2002/09/16 08:05:04 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.expression;
011:
012: import anvil.core.Any;
013: import anvil.ErrorListener;
014: import anvil.codec.Code;
015: import anvil.codec.ConstantPool;
016: import anvil.script.compiler.ByteCompiler;
017: import anvil.script.Context;
018: import anvil.script.Type;
019: import anvil.script.StackFrame;
020: import anvil.script.statements.FunctionStatement;
021: import anvil.script.statements.LocalVariableStatement;
022: import java.io.IOException;
023:
024: /**
025: * class EscapedVariableNode
026: *
027: * @author: Jani Lehtimäki
028: */
029: public class EscapedVariableNode extends Node {
030:
031: private FunctionStatement _context;
032: private LocalVariableStatement _local;
033: private int _index = 0;
034: private int _depth = 0;
035:
036: public EscapedVariableNode(String variable,
037: LocalVariableStatement local, FunctionStatement context) {
038: super ();
039: _local = local;
040: _index = local.getSlot();
041: _context = context;
042: local.markEscaped();
043: FunctionStatement function = context;
044: while (function != null && function != local.getParent()) {
045: _depth++;
046: function = function.getContext();
047: if (function != null) {
048: function.markEscaped();
049: }
050: }
051: }
052:
053: public LocalVariableStatement getVariable() {
054: return _local;
055: }
056:
057: public int getDepth() {
058: return _depth;
059: }
060:
061: public int typeOf() {
062: return Node.EXPR_VARIABLE;
063: }
064:
065: public boolean isConstant() {
066: return false;
067: }
068:
069: public Node optimize() {
070: return this ;
071: }
072:
073: public void compile(ByteCompiler context, Node child) {
074: Code code = context.getCode();
075: ConstantPool pool = code.getPool();
076: code.aload(_context.getFrameIndex());
077: code.iconst(_depth);
078: code.iconst(_index);
079: child.compile(context, GET);
080: code.invokevirtual(code.getPool().addMethodRef(
081: context.TYPE_STACKFRAME, "setLocal",
082: "(IILanvil/core/Any;)Lanvil/core/Any;"));
083: }
084:
085: public void compile(ByteCompiler context, int operation) {
086: Code code = context.getCode();
087: ConstantPool pool = code.getPool();
088: switch (operation) {
089: case GET:
090: case CHECK:
091: code.aload(_context.getFrameIndex());
092: code.iconst(_depth);
093: code.iconst(_index);
094: code.invokevirtual(code.getPool().addMethodRef(
095: context.TYPE_STACKFRAME, "getLocal",
096: "(II)Lanvil/core/Any;"));
097: break;
098:
099: case GET_REF:
100: int refclass = pool
101: .addClass("anvil/core/AnyEscapedLocalRef");
102: code.anew(refclass);
103: code.dup();
104: code.aload(_context.getFrameIndex());
105: code.iconst(_depth);
106: code.iconst(_index);
107: code.invokespecial(pool.addMethodRef(refclass, "<init>",
108: "(Lanvil/script/StackFrame;II)V"));
109: break;
110:
111: case GET_BOOLEAN:
112: code.aload(_context.getFrameIndex());
113: code.iconst(_depth);
114: code.iconst(_index);
115: code.invokevirtual(code.getPool().addMethodRef(
116: context.TYPE_STACKFRAME, "getLocal",
117: "(II)Lanvil/core/Any;"));
118: context.any2boolean();
119: break;
120:
121: case DELETE:
122: code.iconst(false);
123: break;
124: }
125: }
126:
127: }
|