Package railo.transformer.bytecode.statement

Source Code of railo.transformer.bytecode.statement.NativeSwitch$Case

package railo.transformer.bytecode.statement;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.Label;
import org.objectweb.asm.commons.GeneratorAdapter;

import railo.transformer.bytecode.Body;
import railo.transformer.bytecode.BytecodeContext;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.Statement;
import railo.transformer.bytecode.util.ExpressionUtil;

public final class NativeSwitch extends StatementBaseNoFinal implements FlowControlBreak,FlowControlContinue,HasBodies {

  public static final short LOCAL_REF=0;
  public static final short ARG_REF=1;
  public static final short PRIMITIVE=1;
 
 
  private int value;
  private Label end;
  private Statement defaultCase;
  List<Case> cases=new ArrayList<Case>();
  private Label[] labels=new Label[0];
  private int[] values=new int[0];
  private short type;
 
  public NativeSwitch(int value, short type, Position start, Position end) {
    super(start, end);
    this.value=value;
    this.type=type;
  }

  public void _writeOut(BytecodeContext bc) throws BytecodeException {
    end = new Label();
    GeneratorAdapter adapter = bc.getAdapter();

    if(type==LOCAL_REF) adapter.loadLocal(value);
    else if(type==ARG_REF) adapter.loadArg(value);
    else adapter.push(value);
   
    Label beforeDefault = new Label();
    adapter.visitLookupSwitchInsn(beforeDefault, values, labels);
   
    Iterator<Case> it = cases.iterator();
    Case c;
    while(it.hasNext()) {
      c= it.next();
      adapter.visitLabel(c.label);
      ExpressionUtil.visitLine(bc, c.startPos);
      c.body.writeOut(bc);
      ExpressionUtil.visitLine(bc, c.endPos);
      if(c.doBreak){
        adapter.goTo(end);
      }
    }
   
   
    adapter.visitLabel(beforeDefault);
    if(defaultCase!=null)defaultCase.writeOut(bc);
    adapter.visitLabel(end);

  }
 
  public void addCase(int value, Statement body,Position start,Position end,boolean doBreak) {
   
    Case nc = new Case(value,body,start,end,doBreak);

    Label[] labelsTmp = new Label[cases.size()+1];
    int[] valuesTmp = new int[cases.size()+1];
   
    int count=0;
    boolean hasAdd=false;
    for(int i=0;i<labels.length;i++) {
      if(!hasAdd && nc.value<values[i]) {
        labelsTmp[count]=nc.label;
        valuesTmp[count]=nc.value;
        count++;
        hasAdd=true;
      }
      labelsTmp[count]=labels[i];
      valuesTmp[count]=values[i];
      count++;
    }
    if(!hasAdd) {
      labelsTmp[labels.length]=nc.label;
      valuesTmp[values.length]=nc.value;
    }
    labels=labelsTmp;
    values=valuesTmp;
   
   
    cases.add(nc);
  }
 
  public void addDefaultCase(Statement defaultStatement) {
    this.defaultCase=defaultStatement;
  }
 
  class Case {

    public boolean doBreak;
    private int value;
    private Statement body;
    private Label label=new Label();
    private Position startPos;
    private Position endPos;

    public Case(int value, Statement body,Position startline,Position endline, boolean doBreak) {
      this.value=value;
      this.body=body;
      this.startPos=startline;
      this.endPos=endline;
      this.doBreak=doBreak;
    }

  }

  /**
   *
   * @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel()
   */
  public Label getBreakLabel() {
    return end;
  }

  /**
   *
   * @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel()
   */
  public Label getContinueLabel() {
    return end;
  }

  /**
   * @see railo.transformer.bytecode.statement.HasBodies#getBodies()
   */
  public Body[] getBodies() {
    if(cases==null) {
      if(defaultCase!=null) return new Body[]{(Body) defaultCase};
      return new Body[]{};
    }
   
    int len=cases.size(),count=0;
    if(defaultCase!=null)len++;
    Body[] bodies=new Body[len];
    Case c;
    Iterator<Case> it = cases.iterator();
    while(it.hasNext()) {
      c=it.next();
      bodies[count++]=(Body) c.body;
    }
    if(defaultCase!=null)bodies[count++]=(Body) defaultCase;
   
    return bodies;
  }

  @Override
  public String getLabel() {
    return null;
  }
}
TOP

Related Classes of railo.transformer.bytecode.statement.NativeSwitch$Case

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.