Package anvil.script.statements

Source Code of anvil.script.statements.ForeachStatement

/*
* $Id: ForeachStatement.java,v 1.31 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script.statements;

import anvil.core.Any;
import anvil.Location;
import anvil.codec.Code;
import anvil.codec.Source;
import anvil.codec.Target;
import anvil.codec.ConstantPool;
import anvil.parser.Tag;
import anvil.ErrorListener;
import anvil.script.compiler.ByteCompiler;
import anvil.script.Context;
import anvil.script.expression.AssignmentNode;
import anvil.script.expression.Expression;
import anvil.script.expression.ExpressionList;
import anvil.script.expression.VariableNode;
import anvil.script.expression.Node;
import anvil.script.parser.TemplateParser;
import anvil.script.Grammar;
import anvil.java.util.BindingEnumeration;
import java.io.IOException;

/**
* class ForeachStatement
*
* @author: Jani Lehtim�ki
*/
public class ForeachStatement extends ScopedStatement implements Labeled
{

  private Expression   _expression;
  private Statement    _statement = EMPTY;
  private Expression[] _index;
  private Expression[] _key;
  private Expression[] _value;
  private VariableNode _enumvar;
  private VariableNode _indexvar;
  private String       _label ;
  private Source       _startscope;
  private Source       _endscope;


  public ForeachStatement(Statement parent, Location location)
  {
    super(parent, location);
  }


  public ForeachStatement(Statement parent, Location location,
    Expression[] index, Expression[] key, Expression[] value,
    Expression expression, String label)
  {
    super(parent, location);
    _index = index;
    _key = key;
    _value = value;
    _expression = expression;
    _label = label;
  }


  public int typeOf()
  {
    return Statement.ST_FOREACH;
  }


  public String name()
  {
    return "foreach";
  }


  public String getLabel()
  {
    return _label;
  }


  public void parse(TemplateParser parser, Tag tag)
  {
    String s;

    s = tag.getValue("index");
    if (s != null) {
      _index = Grammar.parseForeachExpression(s, getLocation(), parser);
    }
   
    s = tag.getValue("key");
    if (s != null) {
      _key = Grammar.parseForeachExpression(s, getLocation(), parser);
    }
   
    s = tag.getValue("value");
    if (s != null) {
      _value = Grammar.parseForeachExpression(s, getLocation(), parser);
    }
   
    s = tag.getValue("expr");
    if (s == null) {
      s = tag.getValue("in");
    }
    _expression = Grammar.parseExpression(s, getLocation(), parser);

    _label = parseLabel(parser, tag);
  }


  public boolean onTag(TemplateParser parser, int type, Tag tag)
  {
    switch(type) {
    case ST_ENDFOREACH:
      parser.pop();
      break;
    default:
      return super.onTag(parser, type, tag);
    }
    return true
  }


  public Statement getChildStatement()
  {
    return _statement;
  }  


  public void setChildStatement(Statement statement)
  {
    _statement = statement;
  }  


  public void check(ErrorListener context)
  {
    if (_index != null) {
      int n = _index.length;
      for(int i=0; i<n; i++) {
        Expression expr = _index[i];
        expr.check(context);
        if (!expr.isAssignable()) {
          context.error(getLocation(), "Index expression #"+(i+1)+" is not assignable");
        }
      }
    }
    if (_key != null) {
      int n = _key.length;
      for(int i=0; i<n; i++) {
        Expression expr = _key[i];
        expr.check(context);
        if (!expr.isAssignable()) {
          context.error(getLocation(), "Key expression #"+(i+1)+" is not assignable");
        }
      }
    }
    if (_value != null) {
      int n = _value.length;
      for(int i=0; i<n; i++) {
        Expression expr = _value[i];
        expr.check(context);
        if (!expr.isAssignable()) {
          context.error(getLocation(), "Value expression  #"+(i+1)+" is not assignable");
        }
      }
    }
    _expression.check(context);
    _statement.check(context);
    FunctionStatement function = getFunctionStatement();
    if (function.isGenerator()) {
      _enumvar = new VariableNode(function.declare("enum$"+hashCode()));
      if (_index != null) {
        _indexvar = new VariableNode(function.declare("index$"+hashCode()));
      }
    } 
  }


  public Jumps eliminate(ErrorListener context)
  {
    Jumps jumps = _statement.eliminate(context)
    jumps.setBlocked(false);
    return jumps.shift();
  }


  public Source getStartOfScope()
  {
    return _startscope;
  }
 

  public Source getEndOfScope()
  {
    return _endscope;
  }


  public void compile(ByteCompiler context)
  {
    Code code = context.getCode();
    ConstantPool pool = code.getPool();
    FunctionStatement function = getFunctionStatement();
    final boolean in_generator = function.isGenerator();
   
    if (_expression.needLineNumbers()) {
      context.location(_expression.getLocation());
    }
    if (in_generator) {
   
      if (_index != null) {
        _indexvar.compile(context, new Node()
        {
          public void compile(ByteCompiler context, int operation)
          {
            Code code_ = context.getCode();
            code_.getstatic(code_.getPool().addFieldRef(
              context.TYPE_ANY, "ZERO", "Lanvil/core/Any;"));
          }
        });
        code.pop();
      }

      int clazz1 = pool.addClass("java/util/Enumeration");
      int clazz2 = pool.addClass("anvil/java/util/BindingEnumeration");
      int clazz3 = pool.addClass("anvil/core/AnyBindingEnumeration");
      code.anew(clazz3);
      code.dup();
      _expression.compile(context, Expression.GET);
      code.invokevirtual(pool.addMethodRef(context.TYPE_ANY, "enumeration", "()Lanvil/java/util/BindingEnumeration;"));
      code.invokespecial(pool.addMethodRef(clazz3, "<init>", "(Lanvil/java/util/BindingEnumeration;)V"));
      final int tmp = code.addLocal();
      code.astore(tmp);
      _enumvar.compile(context, new Node()
      {
        public void compile(ByteCompiler context, int operation)
        {
          context.getCode().aload(tmp);
        }
      });
      code.endLocal(tmp);
      code.pop();

      Target start = code.getTarget();
      _startscope = code.getSource();
      _endscope = code.getSource();

      _enumvar.compile(context, Node.GET);
      code.invokeinterface(pool.addInterfaceMethodRef(clazz1, "hasMoreElements", "()Z"));
      code.if_eq(_endscope);

      if (_index != null) {
       
        new AssignmentNode(new ExpressionList(_index,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              _indexvar.compile(context, GET);
            }
          })).compile(context, Node.GET);
         
        code.pop();
       
        _indexvar.compile(context, new Node() {
          public void compile(ByteCompiler context, int operation)
          {
            Code code_ = context.getCode();
            _indexvar.compile(context, GET);
            code_.invokevirtual(code_.getPool().addMethodRef(context.TYPE_ANY,
              "increase", "()Lanvil/core/Any;"));
          }
        });
        code.pop();
      }

      if (_key != null) {
        new AssignmentNode(new ExpressionList(_key,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              Code code_ = context.getCode();
              ConstantPool pool_ = code_.getPool();
              _enumvar.compile(context, Node.GET);
              code_.invokeinterface(pool_.addInterfaceMethodRef("anvil/java/util/BindingEnumeration", "nextKey", "()Ljava/lang/Object;"));
              code_.invokestatic(pool_.addMethodRef(context.TYPE_ANY, "create", "(Ljava/lang/Object;)Lanvil/core/Any;"));
            }
          })).compile(context, Node.GET);
        code.pop();
      }


      if (_value != null) {
        new AssignmentNode(new ExpressionList(_value,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              Code code_ = context.getCode();
              ConstantPool pool_ = code_.getPool();
              _enumvar.compile(context, Node.GET);
              code_.invokeinterface(pool_.addInterfaceMethodRef("java/util/Enumeration", "nextElement", "()Ljava/lang/Object;"));
              code_.invokestatic(pool_.addMethodRef(context.TYPE_ANY, "create", "(Ljava/lang/Object;)Lanvil/core/Any;"));
            }
          })).compile(context, Node.GET);
        code.pop();

      } else
        _enumvar.compile(context, Node.GET);
        code.invokeinterface(pool.addInterfaceMethodRef(clazz1, "nextElement", "()Ljava/lang/Object;"));
        code.pop();

      }

      _statement.compile(context);
      code.go_to(_startscope);
      _endscope.bind();
      _startscope.bind(start);

    } else {

      final int l_enum = code.addLocal();
      final int l_index = (_index != null) ? code.addLocal() : 0;
      if (l_index != 0) {
        code.iconst(0);
        code.istore(l_index);
      }

      // create enumeration, and wrap it
      int clazz1 = pool.addClass("java/util/Enumeration");
      int clazz2 = pool.addClass("anvil/java/util/BindingEnumeration");
      _expression.compile(context, Expression.GET);
      code.invokevirtual(pool.addMethodRef(context.TYPE_ANY, "enumeration", "()Lanvil/java/util/BindingEnumeration;"));
      code.astore(l_enum);
      int sun_hack_1 = 10 + l_enum;

      Target start = code.getTarget();
      _startscope = code.getSource();
      _endscope = code.getSource();

      code.aload(l_enum);
      int sun_hack_2 = 10 + l_enum;
     
      code.invokeinterface(pool.addInterfaceMethodRef(clazz1, "hasMoreElements", "()Z"));
      code.if_eq(_endscope);

      if (_index != null) {
        new AssignmentNode(new ExpressionList(_index,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              Code code_ = context.getCode();
              code_.iload(l_index);
              code_.iinc(l_index, 1);
              code_.invokestatic(code_.getPool().addMethodRef(
                context.TYPE_ANY, "create", "(I)Lanvil/core/Any;"));
            }
          })).compile(context, Node.GET);
        code.pop();
      }

      if (_key != null) {
        new AssignmentNode(new ExpressionList(_key,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              Code code_ = context.getCode();
              ConstantPool pool_ = code_.getPool();
              code_.aload(l_enum);
              code_.invokeinterface(pool_.addInterfaceMethodRef("anvil/java/util/BindingEnumeration", "nextKey", "()Ljava/lang/Object;"));
              code_.invokestatic(pool_.addMethodRef(context.TYPE_ANY, "create", "(Ljava/lang/Object;)Lanvil/core/Any;"));
            }
          })).compile(context, Node.GET);
        code.pop();
      }

      if (_value != null) {
        new AssignmentNode(new ExpressionList(_value,
          new Node() {
            public void compile(ByteCompiler context, int operation)
            {
              Code code_ = context.getCode();
              ConstantPool pool_ = code_.getPool();
              code_.aload(l_enum);
              code_.invokeinterface(pool_.addInterfaceMethodRef("java/util/Enumeration", "nextElement", "()Ljava/lang/Object;"));
              code_.invokestatic(pool_.addMethodRef(context.TYPE_ANY, "create", "(Ljava/lang/Object;)Lanvil/core/Any;"));
            }
          })).compile(context, Node.GET);
        code.pop();

      } else
        code.aload(l_enum);
        code.invokeinterface(pool.addInterfaceMethodRef(clazz1, "nextElement", "()Ljava/lang/Object;"));
        code.pop();

      }

      _statement.compile(context);
      code.go_to(_startscope);
      _endscope.bind();
      _startscope.bind(start);
     
      code.endLocal(l_enum);
      if (l_index != 0) {
        code.endLocal(l_index);
      }

    }
  }
   

}
TOP

Related Classes of anvil.script.statements.ForeachStatement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.