Package anvil.script.statements

Source Code of anvil.script.statements.CustomTagStatement$FrameNode

/*
* $Id: CustomTagStatement.java,v 1.12 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.core.Array;
import anvil.codec.Code;
import anvil.codec.ConstantPool;
import anvil.codec.Source;
import anvil.codec.Target;
import anvil.codec.ExceptionHandler;
import anvil.Location;
import anvil.ErrorListener;
import anvil.script.compiler.ByteCompiler;
import anvil.script.Context;
import anvil.script.Name;
import anvil.script.StackFrame;
import anvil.script.expression.ArrayNode;
import anvil.script.expression.Node;
import anvil.script.expression.ConstantNode;
import anvil.script.expression.Expression;
import anvil.script.expression.ExpressionList;
import anvil.script.expression.LinkNode;
import anvil.script.expression.MappingNode;
import anvil.script.expression.Expression;
import anvil.script.expression.InvokeNode;
import anvil.script.parser.TemplateParser;
import anvil.script.parser.ExpressionParser;
import anvil.script.Grammar;
import anvil.script.statements.taglib.TagLibrary;
import anvil.script.statements.taglib.Attribute;
import anvil.script.statements.taglib.Tag;
import java.io.IOException;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.Iterator;

/**�
* class CustomTagStatement
*
* @author: Jani Lehtim�ki
*/
public class CustomTagStatement extends Statement
{

  private String _namespace;
  private String _name;
  private Tag _tagdef = null;
  private anvil.parser.Tag _tag = null;
  private boolean _hasEnd = false;
  private Statement _statement = null;
  private Expression _init = null;
  private Expression _start = null;
  private Expression _end = null;
  private Expression _release = null;
  private ExceptionHandler _handler = null;
  private int _framelocal = 0;

  public CustomTagStatement(Statement parent, Location location, Tag tagdef, anvil.parser.Tag tag)
  {
    super(parent, location);
    _namespace = tagdef.getLibrary().getNamespace();
    _name = tag.getName();
    _tagdef = tagdef;
    _tag = tag;
    _hasEnd = tagdef.hasContent() && !tag.hasEndSlash();
  }


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


  public String name()
  {
    return _name;
  }


  public void parse(TemplateParser parser, anvil.parser.Tag tag)
  {
    ArrayList nodes = new ArrayList();
    Enumeration e = _tagdef.getAttributes();
    while(e.hasMoreElements()) {
      Attribute attr = (Attribute)e.nextElement();
      String name = attr.getName();
      String value = tag.getValue(attr.getName());
      if (value == null) {
        if (attr.isRequired()) {
          parser.error(parser.getLocation(), "Required attribute '"+name+"' missing");
        } else {
          value = attr.getDefault();
        }
      }
      if (value != null) {
        Node node = ConstantNode.UNDEFINED;
        switch(attr.getType()) {
        case Attribute.TYPE_STRING:
          node = new ConstantNode(Any.create(value));
          break;

        case Attribute.TYPE_DOUBLE:
          try {
            node = new ConstantNode(Any.create(Double.parseDouble(value)));
          } catch (NumberFormatException nfe) {
            parser.error(parser.getLocation(), "Value of attribute '"+name+"' is not a floating point number");
          }
          break;

        case Attribute.TYPE_INT:
          try {
            node = new ConstantNode(Any.create(anvil.util.Conversions.parseNumberUnsafe(value)));
          } catch (NumberFormatException nfe) {
            parser.error(parser.getLocation(), "Value of attribute '"+name+"' is not an integer");
          }
          break;
         
        case Attribute.TYPE_BOOLEAN:
          node = new ConstantNode(Any.create(Any.IS_BOOLEAN, value));
          break;
           
        case Attribute.TYPE_EXPR:
          value = value.trim();
          if (value.length() > 0) {
            ExpressionParser p = new ExpressionParser(parser, parser.getLocation(), value);
            node = p.parseExpression(p.TYPE_VALUE).getChild();
          } else {
            node = ConstantNode.UNDEFINED;
          }
          break;
        }
        nodes.add(new MappingNode(new ConstantNode(name), node));
      }
    }
    if (_tagdef.allowAnyAttributes()) {
      Iterator iter = _tag.getAttributes();
      while(iter.hasNext()) {
        anvil.parser.Attribute attr = (anvil.parser.Attribute)iter.next();
        String name = attr.getName();
        if (!_tagdef.hasAttribute(name)) {
          nodes.add(new MappingNode(
            new ConstantNode(name),
            new ConstantNode(attr.getValue())));
        }
      }
    }

    int n = nodes.size();
    ExpressionList childs = new ExpressionList(n);
    for(int i=0; i<n; i++) {
      childs.setChild(i, (Node)nodes.get(i));
    }

    Location location = getLocation();
   
    _init = buildExpr(location,
      _tagdef.getInitHandler(),
      null,
      new ExpressionList(
        new ParentNode(), new ConstantNode(_name),
        new ArrayNode(childs)));
       
    _start = buildExpr(location,
      _tagdef.getStartHandler(),
      _tagdef.getStartMethod(),
      ARGS);
     
    _end = buildExpr(location,
      _tagdef.getEndHandler(),
      _tagdef.getEndMethod(),
      ARGS);

    _release = buildExpr(location,
      _tagdef.getReleaseHandler(),
      _tagdef.getReleaseMethod(),
      ARGS);
  }


  public boolean onTag(TemplateParser parser, int type, anvil.parser.Tag tag)
  {
    switch(type) {
    case ST_TAG:
      if (tag.isEndTagOf(_tag)) {
        parser.pop();
        break;
      }

    default:
      return super.onTag(parser, type, tag);
    }
   
    return true;
  }




  private Expression buildExpr(Location location, String handler, String method, ExpressionList args)
  {
    if (handler != null) {
      handler = handler.trim();
      return new Expression(new LinkNode(this, location,
        new Name().add(_namespace).add(handler), args,
        LinkNode.GET) ,location);
       
    } else if (method != null) {
      return new Expression(new InvokeNode(FRAME, method, EMPTY_ARGS), location);
     
    } else {
      return null;
    }
  }


  public boolean hasEnd()
  {
    return _hasEnd;
  }
 

  public Statement getChildStatement()
  {
    return _statement;
  }  


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


  public void check(ErrorListener context)
  {
    if (_init != null) {
      _init.check(context);
    }
    if (_start != null) {
      _start.check(context);
    }
    if (_end != null) {
      _end.check(context);
    }
    if (_release != null) {
      _release.check(context);
    }
    if (_statement != null) {
      _statement.check(context);
    }
  }


  public Jumps eliminate(ErrorListener context)
  {
    if (_statement != null) {
      Jumps jumps = _statement.eliminate(context);
      jumps.setBlocked(false);
      return jumps.shift();
    } else {
      return new Jumps();
    }
  }
 
  public void compile(ByteCompiler context)
  {
    Code code = context.getCode();
    ConstantPool pool = code.getPool();
    boolean needloop =
      (_start != null) ||
      (_end != null) ||
      (_release != null) ||
      (_statement != null);

    if (needloop) {
      if (_init != null) {
        _init.compile(context, Node.GET);
      } else {
        code.getstatic(pool.addFieldRef(context.TYPE_ANY, "UNDEFINED",
          "Lanvil/core/Any;"));
      }
      code.dup();

      int contextframe = pool.addMethodRef(context.TYPE_CONTEXT, "frame",
        "()Lanvil/script/StackFrame;");
      code.aload_first();
      code.invokevirtual(contextframe);
      code.swap();
      code.invokevirtual(pool.addMethodRef("anvil/script/StackFrame",
        "push", "(Lanvil/core/Any;)V"));

      _framelocal = code.addLocal();
      code.astore(_framelocal);

      ExceptionHandler handler = code.startExceptionHandler(true);
      _handler = handler;
      Target tostart = code.getTarget();
      if (_start != null) {
        _start.compile(context, Node.GET_BOOLEAN);
        Source istrue = code.if_ne();
        handler.callFinally();
        handler.jumpOut();
        istrue.bind();
      }
      if (_statement != null) {
        _statement.compile(context);
      }
      if (_end != null) {
        _end.compile(context, Node.GET_BOOLEAN);
        code.if_ne(tostart);
      }
      handler.endTry();
      if (_statement == null || !_statement.isBlocked()) {
        handler.callFinally();
        handler.jumpOut();
      }
      handler.endProtectedRegion();

      handler.startCatch(0);
      int thrown = code.addLocal();
      code.astore(thrown);
      handler.callFinally();
      code.aload(thrown);
      code.athrow();
      handler.endCatches();
       _handler = null;

      // finally
      handler.startFinally();
      int returnto = code.addLocal();
      code.astore(returnto);
      code.aload_first();
      code.invokevirtual(contextframe);
      code.invokevirtual(pool.addMethodRef("anvil/script/StackFrame",
        "pop", "()Lanvil/core/Any;"));
      code.pop();
      if (_release != null) {
        _release.compile(context, Node.GET);
        code.pop();
      }
      code.ret(returnto);
      handler.endFinally();
      handler.end();
     
      code.endLocal(_framelocal);
     
    } else {
      if (_init != null) {
        _init.compile(context, Node.GET);
        code.pop();
      }
    }
  }
 

  public boolean callFinalizer()
  {
    _handler.callFinally();
    return false;
  }


  private Node FRAME = new FrameNode();
  private ExpressionList ARGS = new ExpressionList(FRAME);
  private static final ExpressionList EMPTY_ARGS = new ExpressionList(0);

  private static class ParentNode extends Node
  {
   
    public void compile(ByteCompiler context, int operation)
    {
      Code code = context.getCode();
      ConstantPool pool = code.getPool();
      code.aload_first();
      code.invokevirtual(pool.addMethodRef(context.TYPE_CONTEXT, "frame",
        "()Lanvil/script/StackFrame;"));
      code.invokevirtual(pool.addMethodRef("anvil/script/StackFrame", "peek",
        "()Lanvil/core/Any;"));
    }

  }

  private class FrameNode extends Node
  {
   
    public void compile(ByteCompiler context, int operation)
    {
      Code code = context.getCode();
      ConstantPool pool = code.getPool();
      code.aload(_framelocal);
    }

  }

}
TOP

Related Classes of anvil.script.statements.CustomTagStatement$FrameNode

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.