/*
 *	InstrumentCompilation.java
 *
 *	This file is part of Tritonus: http://www.tritonus.org/
 */

/*
 *  Copyright (c) 2002 by Matthias Pfisterer
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as published
 *   by the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
|<---            this code is formatted to fit into 80 columns             --->|
*/

package org.tritonus.saol.compiler;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import java.util.HashMap;
import java.util.Map;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.*;

import org.tritonus.saol.sablecc.analysis.*;
import org.tritonus.saol.sablecc.node.*;



public class InstrumentCompilation
extends DepthFirstAdapter
{
	private static final boolean	DEBUG = true;

	// may become "org.tritonus.saol.generated."
	private static final String	PACKAGE_PREFIX = "";
	private static final String	CLASSFILENAME_PREFIX = "src/";
	private static final String	CLASSFILENAME_SUFFIX = ".class";
	private static final String	SUPERCLASS_NAME = "org.tritonus.saol.engine.AbstractInstrument";
	private static final String	SUPERCLASS_CONSTRUCTOR_NAME = "AbstractInstrument";

	private static final int	METHOD_CONSTR = WidthAndRate.RATE_UNKNOWN;
	private static final int	METHOD_I = WidthAndRate.RATE_I;
	private static final int	METHOD_K = WidthAndRate.RATE_K;
	private static final int	METHOD_A = WidthAndRate.RATE_A;

	private static final Type	FLOAT_ARRAY = new ArrayType(Type.FLOAT, 1);



	private SAOLGlobals		m_saolGlobals;

	// maps instrument names (String) to classes (Class)
	private Map			m_instrumentMap;
	private Map			m_nodeAttributes;
	private String			m_strClassName;
	private ClassGen		m_classGen;
	private ConstantPoolGen		m_constantPoolGen;
	// private MethodGen		m_methodGen;
	// private InstructionList		m_instructionList;
	private InstructionFactory	m_instructionFactory;
	// private BranchInstruction	m_pendingBranchInstruction;

	// TODO: should be made obsolete by using node attributes
	private boolean			m_bOpvardecls;
	private MemoryClassLoader	m_classLoader = new MemoryClassLoader();

	// 0: constructor
	// 1: doIPass()
	// 2: doKPass()
	// 3: doAPass()
	private InstrumentMethod[]	m_aMethods;


	public InstrumentCompilation(SAOLGlobals saolGlobals,
				     Map instrumentMap)
	{
		m_saolGlobals = saolGlobals;
		m_instrumentMap = instrumentMap;
		m_nodeAttributes = new HashMap();
		m_aMethods = new InstrumentMethod[4];
	}




	public void inAInstrdeclInstrdecl(AInstrdeclInstrdecl node)
	{
		String	strInstrumentName = node.getIdentifier().getText();
		m_strClassName = PACKAGE_PREFIX + strInstrumentName;
		m_classGen = new ClassGen(m_strClassName,
					  SUPERCLASS_NAME,
					  "<generated>",
					  Constants.ACC_PUBLIC | Constants.ACC_SUPER,
					  null);
		m_constantPoolGen = m_classGen.getConstantPool();
		m_instructionFactory = new InstructionFactory(m_constantPoolGen);
		m_aMethods[METHOD_CONSTR] = new InstrumentMethod(m_classGen, "<init>");
		m_aMethods[METHOD_I] = new InstrumentMethod(m_classGen, "doIPass");
		m_aMethods[METHOD_K] = new InstrumentMethod(m_classGen, "doKPass");
		m_aMethods[METHOD_A] = new InstrumentMethod(m_classGen, "doAPass");
		m_aMethods[METHOD_CONSTR].appendInstruction(InstructionConstants.ALOAD_0);
		Instruction	invokeSuperInstruction = m_instructionFactory.createInvoke(SUPERCLASS_NAME, "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL);
//		Instruction	invokeSuperInstruction = m_instructionFactory.createInvoke(SUPERCLASS_NAME, SUPERCLASS_CONSTRUCTOR_NAME, Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL);
		m_aMethods[METHOD_CONSTR].appendInstruction(invokeSuperInstruction);
	}



	public void outAInstrdeclInstrdecl(AInstrdeclInstrdecl node)
	{
		for (int i = 0; i < m_aMethods.length; i++)
		{
			m_aMethods[i].finish();
		}
		JavaClass	javaClass = m_classGen.getJavaClass();
		try
		{
			ByteArrayOutputStream	baos = new ByteArrayOutputStream();
			javaClass.dump(baos);
			byte[]	abData = baos.toByteArray();
			Class	instrumentClass = m_classLoader.findClass(m_strClassName, abData);
			m_instrumentMap.put(m_strClassName, instrumentClass);
			if (DEBUG)
			{
				javaClass.dump(m_strClassName + CLASSFILENAME_SUFFIX);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

//     public void caseAInstrdeclInstrdecl(AInstrdeclInstrdecl node)
//     {
//         inAInstrdeclInstrdecl(node);
//         if(node.getInstr() != null)
//         {
//             node.getInstr().apply(this);
//         }
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getIdentlist() != null)
//         {
//             node.getIdentlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getLBrace() != null)
//         {
//             node.getLBrace().apply(this);
//         }
//         {
//             Object temp[] = node.getOpvardecl().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((POpvardecl) temp[i]).apply(this);
//             }
//         }
//         if(node.getBlock() != null)
//         {
//             node.getBlock().apply(this);
//         }
//         if(node.getRBrace() != null)
//         {
//             node.getRBrace().apply(this);
//         }
//         outAInstrdeclInstrdecl(node);
//     }






	public void inABlockBlock(ABlockBlock node)
	{
	}

	public void outABlockBlock(ABlockBlock node)
	{
	}

//     public void caseABlockBlock(ABlockBlock node)
//     {
//         inABlockBlock(node);
//         {
//             Object temp[] = node.getStatement().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PStatement) temp[i]).apply(this);
//             }
//         }
//         outABlockBlock(node);
//     }

// 	public void inAAssignmentStatement(AAssignmentStatement node)
// 	{
// 	}



	public void outAAssignmentStatement(AAssignmentStatement node)
	{
		Instruction	instruction = (Instruction) getNodeAttribute(node.getLvalue());
		m_aMethods[METHOD_A].appendInstruction(instruction);
	}



	public void inAExpressionStatement(AExpressionStatement node)
	{
	}

	public void outAExpressionStatement(AExpressionStatement node)
	{
	}

//     public void caseAExpressionStatement(AExpressionStatement node)
//     {
//         inAExpressionStatement(node);
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAExpressionStatement(node);
//     }

	public void inAIfStatement(AIfStatement node)
	{
	}

	public void outAIfStatement(AIfStatement node)
	{
	}



	public void caseAIfStatement(AIfStatement node)
	{
		inAIfStatement(node);
        if(node.getIf() != null)
        {
            node.getIf().apply(this);
        }
        if(node.getLPar() != null)
        {
            node.getLPar().apply(this);
        }
        if(node.getExpr() != null)
        {
            node.getExpr().apply(this);
        }
        if(node.getRPar() != null)
        {
            node.getRPar().apply(this);
        }
	m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCONST_0);
	m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCMPL);
	BranchInstruction	ifeq = new IFEQ(null);
	m_aMethods[METHOD_A].appendInstruction(ifeq);
        if(node.getLBrace() != null)
        {
            node.getLBrace().apply(this);
        }
        if(node.getBlock() != null)
        {
            node.getBlock().apply(this);
        }
        if(node.getRBrace() != null)
        {
            node.getRBrace().apply(this);
        }
	m_aMethods[METHOD_A].setPendingBranchInstruction(ifeq);
        outAIfStatement(node);
    }

	public void inAIfElseStatement(AIfElseStatement node)
	{
	}

	public void outAIfElseStatement(AIfElseStatement node)
	{
	}

//     public void caseAIfElseStatement(AIfElseStatement node)
//     {
//         inAIfElseStatement(node);
//         if(node.getIf() != null)
//         {
//             node.getIf().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getLBrace1() != null)
//         {
//             node.getLBrace1().apply(this);
//         }
//         if(node.getBlock1() != null)
//         {
//             node.getBlock1().apply(this);
//         }
//         if(node.getRBrace1() != null)
//         {
//             node.getRBrace1().apply(this);
//         }
//         if(node.getElse() != null)
//         {
//             node.getElse().apply(this);
//         }
//         if(node.getLBrace2() != null)
//         {
//             node.getLBrace2().apply(this);
//         }
//         if(node.getBlock2() != null)
//         {
//             node.getBlock2().apply(this);
//         }
//         if(node.getRBrace2() != null)
//         {
//             node.getRBrace2().apply(this);
//         }
//         outAIfElseStatement(node);
//     }

	public void inAWhileStatement(AWhileStatement node)
	{
	}

	public void outAWhileStatement(AWhileStatement node)
	{
	}

//     public void caseAWhileStatement(AWhileStatement node)
//     {
//         inAWhileStatement(node);
//         if(node.getWhile() != null)
//         {
//             node.getWhile().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getLBrace() != null)
//         {
//             node.getLBrace().apply(this);
//         }
//         if(node.getBlock() != null)
//         {
//             node.getBlock().apply(this);
//         }
//         if(node.getRBrace() != null)
//         {
//             node.getRBrace().apply(this);
//         }
//         outAWhileStatement(node);
//     }

	public void inAInstrumentStatement(AInstrumentStatement node)
	{
	}

	public void outAInstrumentStatement(AInstrumentStatement node)
	{
	}

//     public void caseAInstrumentStatement(AInstrumentStatement node)
//     {
//         inAInstrumentStatement(node);
//         if(node.getInstr() != null)
//         {
//             node.getInstr().apply(this);
//         }
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAInstrumentStatement(node);
//     }

	public void inAOutputStatement(AOutputStatement node)
	{
	}

	public void outAOutputStatement(AOutputStatement node)
	{
	}

//     public void caseAOutputStatement(AOutputStatement node)
//     {
//         inAOutputStatement(node);
//         if(node.getOutput() != null)
//         {
//             node.getOutput().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAOutputStatement(node);
//     }

	public void inASpatializeStatement(ASpatializeStatement node)
	{
	}

	public void outASpatializeStatement(ASpatializeStatement node)
	{
	}

//     public void caseASpatializeStatement(ASpatializeStatement node)
//     {
//         inASpatializeStatement(node);
//         if(node.getSpatialize() != null)
//         {
//             node.getSpatialize().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outASpatializeStatement(node);
//     }

	public void inAOutbusStatement(AOutbusStatement node)
	{
	}

	public void outAOutbusStatement(AOutbusStatement node)
	{
	}

//     public void caseAOutbusStatement(AOutbusStatement node)
//     {
//         inAOutbusStatement(node);
//         if(node.getOutbus() != null)
//         {
//             node.getOutbus().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAOutbusStatement(node);
//     }

	public void inAExtendStatement(AExtendStatement node)
	{
	}

	public void outAExtendStatement(AExtendStatement node)
	{
	}

//     public void caseAExtendStatement(AExtendStatement node)
//     {
//         inAExtendStatement(node);
//         if(node.getExtend() != null)
//         {
//             node.getExtend().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAExtendStatement(node);
//     }

	public void inATurnoffStatement(ATurnoffStatement node)
	{
	}

	public void outATurnoffStatement(ATurnoffStatement node)
	{
	}

//     public void caseATurnoffStatement(ATurnoffStatement node)
//     {
//         inATurnoffStatement(node);
//         if(node.getTurnoff() != null)
//         {
//             node.getTurnoff().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outATurnoffStatement(node);
//     }

	public void inAReturnStatement(AReturnStatement node)
	{
	}

	public void outAReturnStatement(AReturnStatement node)
	{
	}

//     public void caseAReturnStatement(AReturnStatement node)
//     {
//         inAReturnStatement(node);
//         if(node.getReturn() != null)
//         {
//             node.getReturn().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outAReturnStatement(node);
//     }

// 	public void inASimpleLvalue(ASimpleLvalue node)
// 	{
// 	}

	public void outASimpleLvalue(ASimpleLvalue node)
	{
		/*	This is needed at the very end, when the putfield
			instruction is executed.
		*/
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.ALOAD_0);
		String	strVariableName = node.getIdentifier().getText();
		// TODO: use getClassName()
		// set the instruction to be executed after the rvalue is calculated
		Instruction	instruction = getInstructionFactory().createPutField(m_strClassName, strVariableName, Type.FLOAT);
		setNodeAttribute(node, instruction);
	}


	public void inAIndexedLvalue(AIndexedLvalue node)
	{
		// push the array reference onto the stack
		String	strVariableName = node.getIdentifier().getText();
		m_aMethods[METHOD_A].appendGetField(strVariableName);
	}

	public void outAIndexedLvalue(AIndexedLvalue node)
	{
		/*	The array reference still is on the stack. Now,
			also the array index (as a float) is on the stack.
			It has to be transformed to integer.
		*/
		// TODO: correct rounding (1.5 -> 2.0)
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.F2I);
		// set the instruction to be executed after the rvalue is calculated
		setNodeAttribute(node, InstructionConstants.FASTORE);
	}

//     public void caseAIndexedLvalue(AIndexedLvalue node)
//     {
//         inAIndexedLvalue(node);
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLBracket() != null)
//         {
//             node.getLBracket().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRBracket() != null)
//         {
//             node.getRBracket().apply(this);
//         }
//         outAIndexedLvalue(node);
//     }

	public void inAIdentlistIdentlist(AIdentlistIdentlist node)
	{
	}

	public void outAIdentlistIdentlist(AIdentlistIdentlist node)
	{
	}

//     public void caseAIdentlistIdentlist(AIdentlistIdentlist node)
//     {
//         inAIdentlistIdentlist(node);
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         {
//             Object temp[] = node.getIdentlistTail().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PIdentlistTail) temp[i]).apply(this);
//             }
//         }
//         outAIdentlistIdentlist(node);
//     }

	public void inAIdentlistTailIdentlistTail(AIdentlistTailIdentlistTail node)
	{
	}

	public void outAIdentlistTailIdentlistTail(AIdentlistTailIdentlistTail node)
	{
	}

//     public void caseAIdentlistTailIdentlistTail(AIdentlistTailIdentlistTail node)
//     {
//         inAIdentlistTailIdentlistTail(node);
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         outAIdentlistTailIdentlistTail(node);
//     }

	public void inAParamlistParamlist(AParamlistParamlist node)
	{
	}

	public void outAParamlistParamlist(AParamlistParamlist node)
	{
	}

//     public void caseAParamlistParamlist(AParamlistParamlist node)
//     {
//         inAParamlistParamlist(node);
//         if(node.getParamdecl() != null)
//         {
//             node.getParamdecl().apply(this);
//         }
//         {
//             Object temp[] = node.getParamlistTail().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PParamlistTail) temp[i]).apply(this);
//             }
//         }
//         outAParamlistParamlist(node);
//     }

	public void inAParamlistTailParamlistTail(AParamlistTailParamlistTail node)
	{
	}

	public void outAParamlistTailParamlistTail(AParamlistTailParamlistTail node)
	{
	}

//     public void caseAParamlistTailParamlistTail(AParamlistTailParamlistTail node)
//     {
//         inAParamlistTailParamlistTail(node);
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getParamdecl() != null)
//         {
//             node.getParamdecl().apply(this);
//         }
//         outAParamlistTailParamlistTail(node);
//     }

	public void inASigvarVardecl(ASigvarVardecl node)
	{
	}

	public void outASigvarVardecl(ASigvarVardecl node)
	{
	}

//     public void caseASigvarVardecl(ASigvarVardecl node)
//     {
//         inASigvarVardecl(node);
//         if(node.getTaglist() != null)
//         {
//             node.getTaglist().apply(this);
//         }
//         if(node.getStype() != null)
//         {
//             node.getStype().apply(this);
//         }
//         if(node.getNamelist() != null)
//         {
//             node.getNamelist().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outASigvarVardecl(node);
//     }

	public void inATablemapVardecl(ATablemapVardecl node)
	{
	}

	public void outATablemapVardecl(ATablemapVardecl node)
	{
	}

//     public void caseATablemapVardecl(ATablemapVardecl node)
//     {
//         inATablemapVardecl(node);
//         if(node.getTablemap() != null)
//         {
//             node.getTablemap().apply(this);
//         }
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getIdentlist() != null)
//         {
//             node.getIdentlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outATablemapVardecl(node);
//     }

	public void inASigvarOpvardecl(ASigvarOpvardecl node)
	{
		m_bOpvardecls = true;
	}


	public void outASigvarOpvardecl(ASigvarOpvardecl node)
	{
		m_bOpvardecls = false;
	}



//     public void caseASigvarOpvardecl(ASigvarOpvardecl node)
//     {
//         inASigvarOpvardecl(node);
//         if(node.getTaglist() != null)
//         {
//             node.getTaglist().apply(this);
//         }
//         if(node.getOtype() != null)
//         {
//             node.getOtype().apply(this);
//         }
//         if(node.getNamelist() != null)
//         {
//             node.getNamelist().apply(this);
//         }
//         if(node.getSemicolon() != null)
//         {
//             node.getSemicolon().apply(this);
//         }
//         outASigvarOpvardecl(node);
//     }

	public void inAParamdeclParamdecl(AParamdeclParamdecl node)
	{
	}

	public void outAParamdeclParamdecl(AParamdeclParamdecl node)
	{
	}

//     public void caseAParamdeclParamdecl(AParamdeclParamdecl node)
//     {
//         inAParamdeclParamdecl(node);
//         if(node.getOtype() != null)
//         {
//             node.getOtype().apply(this);
//         }
//         if(node.getName() != null)
//         {
//             node.getName().apply(this);
//         }
//         outAParamdeclParamdecl(node);
//     }

	public void inANamelistNamelist(ANamelistNamelist node)
	{
	}

	public void outANamelistNamelist(ANamelistNamelist node)
	{
	}

//     public void caseANamelistNamelist(ANamelistNamelist node)
//     {
//         inANamelistNamelist(node);
//         if(node.getName() != null)
//         {
//             node.getName().apply(this);
//         }
//         {
//             Object temp[] = node.getNamelistTail().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PNamelistTail) temp[i]).apply(this);
//             }
//         }
//         outANamelistNamelist(node);
//     }

	public void inANamelistTailNamelistTail(ANamelistTailNamelistTail node)
	{
	}

	public void outANamelistTailNamelistTail(ANamelistTailNamelistTail node)
	{
	}

//     public void caseANamelistTailNamelistTail(ANamelistTailNamelistTail node)
//     {
//         inANamelistTailNamelistTail(node);
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getName() != null)
//         {
//             node.getName().apply(this);
//         }
//         outANamelistTailNamelistTail(node);
//     }


	public void outASimpleName(ASimpleName node)
	{
		if (m_bOpvardecls)
		{
			String	strVariableName = node.getIdentifier().getText();
			addLocalVariable(strVariableName);
		}
	}



	public void outAIndexedName(AIndexedName node)
	{
		if (m_bOpvardecls)
		{
			String	strVariableName = node.getIdentifier().getText();
			String	strInteger = node.getInteger().getText();
			int	nInteger = Integer.parseInt(strInteger);
			addLocalArray(strVariableName);
			// code to allocate array in constructor
			m_aMethods[METHOD_CONSTR].appendInstruction(InstructionConstants.ALOAD_0);
			Instruction	instruction = (Instruction) getInstructionFactory().createNewArray(Type.FLOAT, (short) nInteger);
			m_aMethods[METHOD_CONSTR].appendInstruction(instruction);
			m_aMethods[METHOD_CONSTR].appendPutField(strVariableName);
		}
	}



	public void outAInchannelsName(AInchannelsName node)
	{
		// TODO:
	}


	public void outAOutchannelsName(AOutchannelsName node)
	{
		// TODO:
	}



	public void outAIvarStype(AIvarStype node)
	{
		setNodeAttribute(node, new WidthAndRate(WidthAndRate.WIDTH_UNKNOWN, WidthAndRate.RATE_I));
	}


	public void outAKsigStype(AKsigStype node)
	{
		setNodeAttribute(node, new WidthAndRate(WidthAndRate.WIDTH_UNKNOWN, WidthAndRate.RATE_K));
	}


	public void outAAsigStype(AAsigStype node)
	{
		setNodeAttribute(node, new WidthAndRate(WidthAndRate.WIDTH_UNKNOWN, WidthAndRate.RATE_A));
	}


	public void outATableStype(ATableStype node)
	{
		// TODO:
	}


	public void outAOparrayStype(AOparrayStype node)
	{
		// TODO:
	}


	public void outAXsigOtype(AXsigOtype node)
	{
		// TODO:
	}


	public void outAStypeOtype(AStypeOtype node)
	{
		setNodeAttribute(node, getNodeAttribute(node.getStype()));
	}



	public void inATabledeclTabledecl(ATabledeclTabledecl node)
	{
	}

	public void outATabledeclTabledecl(ATabledeclTabledecl node)
	{
	}

//     public void caseATabledeclTabledecl(ATabledeclTabledecl node)
//     {
//         inATabledeclTabledecl(node);
//         if(node.getTable() != null)
//         {
//             node.getTable().apply(this);
//         }
//         if(node.getIdentifier1() != null)
//         {
//             node.getIdentifier1().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getIdentifier2() != null)
//         {
//             node.getIdentifier2().apply(this);
//         }
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getExprstrlist() != null)
//         {
//             node.getExprstrlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         outATabledeclTabledecl(node);
//     }

	public void inAImportsTaglist(AImportsTaglist node)
	{
	}

	public void outAImportsTaglist(AImportsTaglist node)
	{
	}

//     public void caseAImportsTaglist(AImportsTaglist node)
//     {
//         inAImportsTaglist(node);
//         if(node.getImports() != null)
//         {
//             node.getImports().apply(this);
//         }
//         outAImportsTaglist(node);
//     }

	public void inAExportsTaglist(AExportsTaglist node)
	{
	}

	public void outAExportsTaglist(AExportsTaglist node)
	{
	}

//     public void caseAExportsTaglist(AExportsTaglist node)
//     {
//         inAExportsTaglist(node);
//         if(node.getExports() != null)
//         {
//             node.getExports().apply(this);
//         }
//         outAExportsTaglist(node);
//     }

	public void inAImportsexportsTaglist(AImportsexportsTaglist node)
	{
	}

	public void outAImportsexportsTaglist(AImportsexportsTaglist node)
	{
	}

//     public void caseAImportsexportsTaglist(AImportsexportsTaglist node)
//     {
//         inAImportsexportsTaglist(node);
//         if(node.getImports() != null)
//         {
//             node.getImports().apply(this);
//         }
//         if(node.getExports() != null)
//         {
//             node.getExports().apply(this);
//         }
//         outAImportsexportsTaglist(node);
//     }

	public void inAExportsimportsTaglist(AExportsimportsTaglist node)
	{
	}

	public void outAExportsimportsTaglist(AExportsimportsTaglist node)
	{
	}

//     public void caseAExportsimportsTaglist(AExportsimportsTaglist node)
//     {
//         inAExportsimportsTaglist(node);
//         if(node.getExports() != null)
//         {
//             node.getExports().apply(this);
//         }
//         if(node.getImports() != null)
//         {
//             node.getImports().apply(this);
//         }
//         outAExportsimportsTaglist(node);
//     }

	public void inAAopcodeOptype(AAopcodeOptype node)
	{
	}

	public void outAAopcodeOptype(AAopcodeOptype node)
	{
	}

//     public void caseAAopcodeOptype(AAopcodeOptype node)
//     {
//         inAAopcodeOptype(node);
//         if(node.getAopcode() != null)
//         {
//             node.getAopcode().apply(this);
//         }
//         outAAopcodeOptype(node);
//     }

	public void inAKopcodeOptype(AKopcodeOptype node)
	{
	}

	public void outAKopcodeOptype(AKopcodeOptype node)
	{
	}

//     public void caseAKopcodeOptype(AKopcodeOptype node)
//     {
//         inAKopcodeOptype(node);
//         if(node.getKopcode() != null)
//         {
//             node.getKopcode().apply(this);
//         }
//         outAKopcodeOptype(node);
//     }

	public void inAIopcodeOptype(AIopcodeOptype node)
	{
	}

	public void outAIopcodeOptype(AIopcodeOptype node)
	{
	}

//     public void caseAIopcodeOptype(AIopcodeOptype node)
//     {
//         inAIopcodeOptype(node);
//         if(node.getIopcode() != null)
//         {
//             node.getIopcode().apply(this);
//         }
//         outAIopcodeOptype(node);
//     }

	public void inAOpcodeOptype(AOpcodeOptype node)
	{
	}

	public void outAOpcodeOptype(AOpcodeOptype node)
	{
	}

//     public void caseAOpcodeOptype(AOpcodeOptype node)
//     {
//         inAOpcodeOptype(node);
//         if(node.getOpcode() != null)
//         {
//             node.getOpcode().apply(this);
//         }
//         outAOpcodeOptype(node);
//     }


	public void inAAltExpr(AAltExpr node)
	{
		// TODO:
	}


	public void outAAltExpr(AAltExpr node)
	{
		// TODO:
	}


//     public void caseAAltExpr(AAltExpr node)
//     {
//         inAAltExpr(node);
//         if(node.getOrexpr1() != null)
//         {
//             node.getOrexpr1().apply(this);
//         }
//         if(node.getQuestMark() != null)
//         {
//             node.getQuestMark().apply(this);
//         }
//         if(node.getOrexpr2() != null)
//         {
//             node.getOrexpr2().apply(this);
//         }
//         if(node.getColon() != null)
//         {
//             node.getColon().apply(this);
//         }
//         if(node.getOrexpr3() != null)
//         {
//             node.getOrexpr3().apply(this);
//         }
//         outAAltExpr(node);
//     }



	public void outAOrOrexpr(AOrOrexpr node)
	{
		// TODO:
	}



	public void outAAndAndexpr(AAndAndexpr node)
	{
		// TODO:
	}



	public void outANeqEqualityexpr(ANeqEqualityexpr node)
	{
		BranchInstruction	branch = new IFNE(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void outAEqEqualityexpr(AEqEqualityexpr node)
	{
		BranchInstruction	branch = new IFEQ(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void inAGtRelationalexpr(AGtRelationalexpr node)
	{
	}

	public void outAGtRelationalexpr(AGtRelationalexpr node)
	{
		BranchInstruction	branch = new IFGT(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void outALtRelationalexpr(ALtRelationalexpr node)
	{
		BranchInstruction	branch = new IFLT(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void outALteqRelationalexpr(ALteqRelationalexpr node)
	{
		BranchInstruction	branch = new IFLE(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void outAGteqRelationalexpr(AGteqRelationalexpr node)
	{
		BranchInstruction	branch = new IFGE(null);
		m_aMethods[METHOD_A].appendRelationalOperation(branch);
	}



	public void outAPlusAddexpr(APlusAddexpr node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FADD);
	}



	public void outAMinusAddexpr(AMinusAddexpr node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FSUB);
	}



	public void outAMultFactor(AMultFactor node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FMUL);
	}



	public void outADivFactor(ADivFactor node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FDIV);
	}



	public void outANotUnaryminusterm(ANotUnaryminusterm node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FNEG);
	}



	public void outANotNotterm(ANotNotterm node)
	{
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCONST_0);
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCMPL);
		BranchInstruction	branch0 = new IFNE(null);
		m_aMethods[METHOD_A].appendInstruction(branch0);
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCONST_1);
		BranchInstruction	branch1 = new GOTO(null);
		m_aMethods[METHOD_A].appendInstruction(branch1);
		m_aMethods[METHOD_A].setPendingBranchInstruction(branch0);
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.FCONST_0);
		m_aMethods[METHOD_A].setPendingBranchInstruction(branch1);
	}



	public void outAIdentifierTerm(AIdentifierTerm node)
	{
		String	strVariableName = node.getIdentifier().getText();
		m_aMethods[METHOD_A].appendGetField(strVariableName);
	}


	public void outAConstantTerm(AConstantTerm node)
	{
		Object	constant = getNodeAttribute(node.getConst());
		if (constant instanceof Integer ||
		    constant instanceof Float)
		{
			float	fValue = ((Number) constant).floatValue();
			m_aMethods[METHOD_A].appendFloatConstant(fValue);
		}
		else
		{
			throw new RuntimeException("constant is neither int nor float");
		}
	}



	public void inAIndexedTerm(AIndexedTerm node)
	{
		// push the array reference onto the stack
		String	strVariableName = node.getIdentifier().getText();
		m_aMethods[METHOD_A].appendGetField(strVariableName);
	}

	public void outAIndexedTerm(AIndexedTerm node)
	{
		/*	The array reference still is on the stack. Now,
			also the array index (as a float) is on the stack.
			It has to be transformed to integer.
		*/
		// TODO: correct rounding (1.5 -> 2.0)
		m_aMethods[METHOD_A].appendInstruction(InstructionConstants.F2I);
		// and now fetch the value from the array
		setNodeAttribute(node, InstructionConstants.FALOAD);
	}



	public void inASasbfTerm(ASasbfTerm node)
	{
	}

	public void outASasbfTerm(ASasbfTerm node)
	{
	}

//     public void caseASasbfTerm(ASasbfTerm node)
//     {
//         inASasbfTerm(node);
//         if(node.getSasbf() != null)
//         {
//             node.getSasbf().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         outASasbfTerm(node);
//     }

    public void inAFunctionTerm(AFunctionTerm node)
    {
    }

    public void outAFunctionTerm(AFunctionTerm node)
    {
    }

//     public void caseAFunctionTerm(AFunctionTerm node)
//     {
//         inAFunctionTerm(node);
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         outAFunctionTerm(node);
//     }

    public void inAIndexedfunctionTerm(AIndexedfunctionTerm node)
    {
    }

    public void outAIndexedfunctionTerm(AIndexedfunctionTerm node)
    {
    }

//     public void caseAIndexedfunctionTerm(AIndexedfunctionTerm node)
//     {
//         inAIndexedfunctionTerm(node);
//         if(node.getIdentifier() != null)
//         {
//             node.getIdentifier().apply(this);
//         }
//         if(node.getLBracket() != null)
//         {
//             node.getLBracket().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         if(node.getRBracket() != null)
//         {
//             node.getRBracket().apply(this);
//         }
//         if(node.getLPar() != null)
//         {
//             node.getLPar().apply(this);
//         }
//         if(node.getExprlist() != null)
//         {
//             node.getExprlist().apply(this);
//         }
//         if(node.getRPar() != null)
//         {
//             node.getRPar().apply(this);
//         }
//         outAIndexedfunctionTerm(node);
//     }


    public void inAExprlistExprlist(AExprlistExprlist node)
    {
    }


    public void outAExprlistExprlist(AExprlistExprlist node)
    {
    }


//     public void caseAExprlistExprlist(AExprlistExprlist node)
//     {
//         inAExprlistExprlist(node);
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         {
//             Object temp[] = node.getExprlistTail().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PExprlistTail) temp[i]).apply(this);
//             }
//         }
//         outAExprlistExprlist(node);
//     }

    public void inAExprlistTailExprlistTail(AExprlistTailExprlistTail node)
    {
    }

    public void outAExprlistTailExprlistTail(AExprlistTailExprlistTail node)
    {
    }

//     public void caseAExprlistTailExprlistTail(AExprlistTailExprlistTail node)
//     {
//         inAExprlistTailExprlistTail(node);
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         outAExprlistTailExprlistTail(node);
//     }

    public void inAExprstrlistExprstrlist(AExprstrlistExprstrlist node)
    {
    }

    public void outAExprstrlistExprstrlist(AExprstrlistExprstrlist node)
    {
    }

//     public void caseAExprstrlistExprstrlist(AExprstrlistExprstrlist node)
//     {
//         inAExprstrlistExprstrlist(node);
//         if(node.getExprOrString() != null)
//         {
//             node.getExprOrString().apply(this);
//         }
//         {
//             Object temp[] = node.getExprstrlistTail().toArray();
//             for(int i = 0; i < temp.length; i++)
//             {
//                 ((PExprstrlistTail) temp[i]).apply(this);
//             }
//         }
//         outAExprstrlistExprstrlist(node);
//     }

    public void inAExprstrlistTailExprstrlistTail(AExprstrlistTailExprstrlistTail node)
    {
    }

    public void outAExprstrlistTailExprstrlistTail(AExprstrlistTailExprstrlistTail node)
    {
    }

//     public void caseAExprstrlistTailExprstrlistTail(AExprstrlistTailExprstrlistTail node)
//     {
//         inAExprstrlistTailExprstrlistTail(node);
//         if(node.getComma() != null)
//         {
//             node.getComma().apply(this);
//         }
//         if(node.getExprOrString() != null)
//         {
//             node.getExprOrString().apply(this);
//         }
//         outAExprstrlistTailExprstrlistTail(node);
//     }

    public void inAExprExprOrString(AExprExprOrString node)
    {
    }

    public void outAExprExprOrString(AExprExprOrString node)
    {
    }

//     public void caseAExprExprOrString(AExprExprOrString node)
//     {
//         inAExprExprOrString(node);
//         if(node.getExpr() != null)
//         {
//             node.getExpr().apply(this);
//         }
//         outAExprExprOrString(node);
//     }

    public void inAStringExprOrString(AStringExprOrString node)
    {
    }

    public void outAStringExprOrString(AStringExprOrString node)
    {
    }

//     public void caseAStringExprOrString(AStringExprOrString node)
//     {
//         inAStringExprOrString(node);
//         if(node.getString() != null)
//         {
//             node.getString().apply(this);
//         }
//         outAStringExprOrString(node);
//     }

	public void inAIntegerConst(AIntegerConst node)
	{
	}

    public void outAIntegerConst(AIntegerConst node)
    {
		String	strInteger = node.getInteger().getText();
		Integer	integer = new Integer(strInteger);
		setNodeAttribute(node, integer);
    }

//     public void caseAIntegerConst(AIntegerConst node)
//     {
//         inAIntegerConst(node);
//         if(node.getInteger() != null)
//         {
//             node.getInteger().apply(this);
//         }
//         outAIntegerConst(node);
//     }

// 	public void inANumberConst(ANumberConst node)
// 	{
// 	}



	public void outANumberConst(ANumberConst node)
	{
		String	strNumber = node.getNumber().getText();
		Float	number = new Float(strNumber);
		setNodeAttribute(node, number);
	}



//     public void caseANumberConst(ANumberConst node)
//     {
//         inANumberConst(node);
//         if(node.getNumber() != null)
//         {
//             node.getNumber().apply(this);
//         }
//         outANumberConst(node);
//     }


////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////





	// helper methods



	private void setNodeAttribute(Node node, Object attribute)
	{
		m_nodeAttributes.put(node, attribute);
	}



	private Object getNodeAttribute(Node node)
	{
		return m_nodeAttributes.get(node);
	}



	private void addLocalVariable(String strVariableName)
	{
		FieldGen	fieldGen;
		fieldGen = new FieldGen(Constants.ACC_PRIVATE,
					Type.FLOAT,
					strVariableName,
					m_constantPoolGen);
		m_classGen.addField(fieldGen.getField());

	}



	private void addLocalArray(String strVariableName)
	{
		FieldGen	fieldGen;
		fieldGen = new FieldGen(Constants.ACC_PRIVATE,
					FLOAT_ARRAY,
					strVariableName,
					m_constantPoolGen);
		m_classGen.addField(fieldGen.getField());

	}



	/**	Returns the InstructionFactory.
		This method is mainly for use by inner classes.
		A bit dangerous, since that has to be one
		InstructionFactory per generated class.
	*/
	private InstructionFactory getInstructionFactory()
	{
		return m_instructionFactory;
	}





	private class InstrumentMethod
	{
		private ClassGen		m_classGen;
		private MethodGen		m_methodGen;
		private InstructionList		m_instructionList;
		private BranchInstruction	m_pendingBranchInstruction;


		public InstrumentMethod(ClassGen classGen, String strMethodName)
		{
			m_classGen = classGen;
			m_instructionList = new InstructionList();
			m_methodGen = new MethodGen(
				Constants.ACC_PUBLIC,
				Type.VOID,
				new Type[]{new ObjectType("org.tritonus.saol.engine.RTSystem")},
				new String[]{"rtSystem"},
				strMethodName,
				m_classGen.getClassName(),
				m_instructionList,
				m_classGen.getConstantPool());
		}



		/**	Append an instruction to the method's Instruction
			list. If a BranchInstruction is pending, it is
			targetted here.
		*/
		public InstructionHandle appendInstruction(Instruction instruction)
		{
			// System.out.println("instruction: " + instruction);
			InstructionHandle	target = null;
			if (instruction instanceof BranchInstruction)
			{
				target = m_instructionList.append((BranchInstruction) instruction);
			}
			else if (instruction instanceof CompoundInstruction)
			{
				target = m_instructionList.append((CompoundInstruction) instruction);
			}
			else
			{
				target = m_instructionList.append(instruction);
			}
			if (m_pendingBranchInstruction != null)
			{
				m_pendingBranchInstruction.setTarget(target);
				m_pendingBranchInstruction = null;
			}
			return target;
		}



	/**	Set the 'pending' BranchInstruction.
		This is a mechanism to avoid NOPs. If a BranchInstruction
		has to be targeted at an instruction that is immediately
		following, but has not been generated yet, set this
		BranchInstruction as the pending BranchInstruction.
		The next instruction added to the method's InstructionList
		with appendInstruction() will become the target of
		the pending BranchInstruction.
	*/
	public void setPendingBranchInstruction(BranchInstruction branchInstruction)
	{
		if (m_pendingBranchInstruction != null)
		{
			throw new RuntimeException("pending branch instruction already set");
		}
		m_pendingBranchInstruction = branchInstruction;
	}


	public void appendGetField(String strVariableName)
	{
		// System.out.println("class name: " + m_strClassName);
		// System.out.println("var name: " + strVariableName);
		appendInstruction(InstructionConstants.ALOAD_0);
		Instruction	instruction = getInstructionFactory().createGetField(m_strClassName, strVariableName, Type.FLOAT);
		appendInstruction(instruction);
	}


	/**
	   NOTE: this method does not append an ALOAD_0 instruction!
	 */
	public void appendPutField(String strVariableName)
	{
		// System.out.println("class name: " + m_strClassName);
		// System.out.println("var name: " + strVariableName);
		Instruction	instruction = getInstructionFactory().createPutField(m_strClassName, strVariableName, Type.FLOAT);
		appendInstruction(instruction);
	}



	public void appendIntegerConstant(int nValue)
	{
		Instruction	instruction = null;
		switch (nValue)
		{
		case -1:
			instruction = InstructionConstants.ICONST_M1;
			break;

		case 0:
			instruction = InstructionConstants.ICONST_0;
			break;

		case 1:
			instruction = InstructionConstants.ICONST_1;
			break;

		case 2:
			instruction = InstructionConstants.ICONST_2;
			break;

		case 3:
			instruction = InstructionConstants.ICONST_3;
			break;

		case 4:
			instruction = InstructionConstants.ICONST_4;
			break;

		case 5:
			instruction = InstructionConstants.ICONST_5;
			break;

		default:
			int	nConstantIndex = m_constantPoolGen.addInteger(nValue);
			instruction = new LDC(nConstantIndex);
		}
		appendInstruction(instruction);
	}


	public void appendFloatConstant(float fValue)
	{
		Instruction	instruction = null;
		if (fValue == 0.0)
		{
			instruction = InstructionConstants.FCONST_0;
		}
		else if (fValue == 1.0)
		{
			instruction = InstructionConstants.FCONST_1;
		}
		else if (fValue == 2.0)
		{
			instruction = InstructionConstants.FCONST_2;
		}
		else
		{
			int	nConstantIndex = m_constantPoolGen.addFloat(fValue);
			instruction = new LDC(nConstantIndex);
		}
		appendInstruction(instruction);
	}



		public void appendRelationalOperation(BranchInstruction branch0)
		{
			appendInstruction(InstructionConstants.FCMPL);
			appendInstruction(branch0);
			appendInstruction(InstructionConstants.FCONST_0);
			BranchInstruction	branch1 = new GOTO(null);
			appendInstruction(branch1);
			setPendingBranchInstruction(branch0);
			appendInstruction(InstructionConstants.FCONST_1);
			setPendingBranchInstruction(branch1);
		}



		public void finish()
		{
			appendInstruction(InstructionConstants.RETURN);
			m_methodGen.setMaxStack();
			m_classGen.addMethod(m_methodGen.getMethod());
		}
	}
}



/*** InstrumentCompilation.java ***/
