org.jawk.backend
Class AwkCompilerImpl

java.lang.Object
  extended by org.jawk.backend.AwkCompilerImpl
All Implemented Interfaces:
AwkCompiler

public class AwkCompilerImpl
extends java.lang.Object
implements AwkCompiler

The reference implementation of the Jawk compiler. Jawk intermediate code is analyzed and converted to appropriate Java bytecode for execution on a modern JVM. The Apache Byte Code Engineering Library (BCEL) is used to manage the construction of the compiled bytecode.

Since this reference implementation relies on the BCEL to execute, Jawk employs reflection to classload this compiler implementation. If the reflection fails, it is most likely because the BCEL library cannot be found in the classpath. Reflection was used to ensure that Jawk will build and execute, even without the presence of the BCEL.

The architecture of the resultant class is nearly identical to the following Java code (assuming AwkScript as the classname and no package name is provided via the -d argument):


 import org.jawk.jrt.*;
 import org.jawk.util.AwkParameters;

 import java.util.*;
 import java.util.regex.*;
 import java.io.*;

 public class AwkScript implements VariableManager {

        // use this field as the third argument to the AwkParameters
        // constructor when executing ScriptMain directly

        public static final String EXTENSION_DESCRIPTION = extension-description-string;

        private static final Integer ZERO = new Integer(0);
        private static final Integer ONE = new Integer(1);
        private static final Integer MINUS_ONE = new Integer(-1);

        public static void main(String args[]) {
                AwkScript as = new AwkScript();
                // this is why org.jawk.util.AwkParameters is in jrt.jar ...
                AwkParameters ap = new AwkParameters(AwkScript.class, args, EXTENSION_DESCRIPTION);
                // to send the error code back to the calling process
                System.exit(as.ScriptMain(ap));
        }

        // to satisfy the VariableManager interface

        // Note: field names here correspond to a global_N field
        // which are assigned upon compilation of the script.

        public final Object getARGC() { if (argc_field == null) return ""; else return argc_field; }
        public final Object getCONVFMT() { if (convfmt_field == null) return ""; else return convfmt_field; }
        public final Object getFS() { if (fs_field == null) return ""; else return fs_field; }
        public final Object getARGV() { return argv_field; }
        public final Object getOFS() { if (ofs_field == null) return ""; else return ofs_field; }
        public final Object getRS() { if (rs_field == null) return ""; else return rs_field; }
        public final void setFILENAME(String arg) { filename_field = arg; }
        public final void setNF(String arg) { nf_field = arg; }

        private final Object getNR() { if (nr_field == null) return ""; else return nr_field; }
        private final Object getFNR() { if (fnr_field == null) return ""; else return fnr_field; }

        public final void incNR() { nr_field = (int) JRT.toDouble(JRT.inc(getNR())); }
        public final void incFNR() { fnr_field = (int) JRT.toDouble(JRT.inc(getFNR())); }
        public final void resetFNR() { fnr_field = ZERO; }

        public final void assignField(String name, Object value) {
                if (name.equals("scalar1")) scalar1_field = value;
                else if (name.equals("scalar2")) scalar2_field = value;
                else if (name.equals("scalar3")) scalar3_field = value;
                ...
                else if (name.equals("scalarN")) scalarN_field = value;
                else if (name.equals("funcName1")) throw an exception;
                else if (name.equals("funcName2")) throw an exception;
                ...
                else if (name.equals("funcNameX")) throw an exception;
                else if (name.equals("assocArrayName1")) throw an exception;
                else if (name.equals("assocArrayName2")) throw an exception;
                ...
                else if (name.equals("assocArrayNameM")) throw an exception;
        }

        private JRT input_runtime;
        private HashMap regexps;
        private HashMap pattern_pairs;
        private int exit_code;

        private int oldseed;

        private Random random_number_generator;

        // global_N refers to all the global variables,
        // those which are defined by default
        // (i.e., ARGC, ARGV, ENVIRON, NF, etc.)
        // and vars declared by the script.
        // The _SET_NUM_GLOBALS_ opcode allocates
        // these fields.

        private Object global_0;
        private Object global_1;
        private Object global_2;
        ...
        private Object global_N;

        // Call this method to invoke the Jawk script.
        // Refer to the static main method implementation
        // and Javadocs on how to build the AwkParameters.
        // Use the public static String EXTENSION_DESCRIPTION
        // field (within AwkScript) as the third parameter
        // to the AwkParameters constructor to ensure proper
        // extension description in the usage statement.

        public final int ScriptMain(AwkParameters awk_parameters) {

                // local variables

                double dregister;
                StringBuffer sb = new StringBuffer();

                // Field Allocation
                // ----------------
                // Could have be done in the class constructor,
                // but placed here to ensure proper repeat initialization
                // if repeat execution is required
                // within the same JVM instance.  Because
                // if these were within the class constructor, each of these
                // data structures / int values would have to be
                // reinitialized in some way anyway.

                input_runtime = JRT(this);      // this = VariableManager
                regexps = new HashMap();
                pattern_pairs = new HashMap();
                oldseed = 0;
                random_number_generator = new Random(null);
                exit_code = 0;

                // script execution

                try {
                        ///
                        /// Compiled BEGIN and input rule blocks code here.
                        /// (EndException is thrown when exit() is encountered.)
                        ///
                } catch (EndException ee) {
                        // do nothing
                }

                try {
                        runEndBlocks();
                } catch (EndException ee) {
                        // do nothing
                }

                return exit_code;
        }

        public void runEndBlocks() {
                double dregister;
                StringBuffer sb = new StringBuffer();

                ///
                /// Compiled END blocks code here.
                /// (EndException is thrown when exit() is encountered.)
                ///
        }

        // One of these exists for every function definition.
        // Arguments are reversed from its Jawk source.
        public Object FUNC_function_name(Object oN, Object oN-1, ... Object o2, Object o1) {
                Object _return_value_ = null;
                StringBuffer sb = new StringBuffer();
                double dregister = 0.0;

                ///
                /// Compiled function function_name code here.
                /// (A return() sets the _return_value_ and falls out of this
                ///  function code block.)
                /// (EndException is thrown when exit() is encountered.)
                ///

                return _return_value_;
        }

        // The following is created for every optarg version of the function
        // call that exists within the script for this function_name.
        // X > 0 && N > X
        public final Object FUNC_function_name(Object oX, Object oX-1, ... Object o2, Object o1) {
                return FUNC_function_name(null, null, ..., null, oX, oX-1, ..., o2, o1);
        }
 }
 

See Also:
AwkCompiler, AVM, VariableManager

Constructor Summary
AwkCompilerImpl(AwkParameters parameters)
          Creates the compiler implementation.
 
Method Summary
 void compile(AwkTuples tuples)
          Entry point to the compiler.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

AwkCompilerImpl

public AwkCompilerImpl(AwkParameters parameters)
Creates the compiler implementation. Jawk invokes this via reflection.

Parameters:
parameters - Parameters to the script compiler.
See Also:
Awk
Method Detail

compile

public final void compile(AwkTuples tuples)
Entry point to the compiler. The compiler traverses the AwkTuples produced by the intermediate step, translating each tuple into JVM code. Some post-processing occurs to resolve branching (jumps to Addresses).

Specified by:
compile in interface AwkCompiler
Parameters:
tuples - The tuples which are traversed to produce the compiled result.
See Also:
Address