/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.openquark.cal.internal.machine.lecc; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; /** * This is a helper class to generate the source code for the RTFullApp.General * sub-classes for 1 through 15 arguments. * It simply generates the source for the static inner classes of RTFullApp.General * and dumps it to the file specified in the arguments to main. * * @author rcypher */ public class FullAppNodeGenerator { private final int scArity; private final PrintStream ps; private FullAppNodeGenerator (int scArity, PrintStream ps) { this.scArity = scArity; this.ps = ps; } private final void generateFields () { for (int i = 1; i <= scArity; ++i) { println(ps, 2, "RTValue arg" + i + ";"); } ps.println(); } private void generateConstructor () { print(ps, 2, "public _" + scArity + " (RTSupercombinator function"); for (int i = 1; i <= scArity; ++i) { ps.print(", RTValue arg" + i); } ps.println(") {"); println(ps, 3, "super (function);"); if (scArity > 0) { print(ps, 3, "assert ("); for (int i = 1; i <= scArity; ++i) { ps.print("arg" + i + " != null"); if (i < scArity) { ps.print(" && "); } } ps.println(") : \"Invalid argument value in RTFullApp.General._" + scArity + " constructor.\";"); } ps.println(); for (int i = 1; i <= scArity; ++i) { println(ps, 3, "this.arg" + i + " = arg" + i + ";"); } println(ps, 2, "}"); ps.println(); } private final void generateClassDec () { println(ps, 1, "/**"); println(ps, 1, " * WARNING- this class was automatically generated by FullAppNodeGenerator. DO NOT MANUALLY EDIT THIS CLASS."); println(ps, 1, " * "); if (scArity > 0) { println(ps, 1, " * This class is used to represent a full application of an"); println(ps, 1, " * arity " + scArity + " function."); println(ps, 1, " */"); println(ps, 1, "public static abstract class _" + scArity + " extends General {"); } else { println(ps, 1, " * Representation of an arity zero function applied to nothing."); println(ps, 1, " * This may sound silly but it keeps things simple as zero arity"); println(ps, 1, " * functions and CAFs can be derived from RTSupercombinator like"); println(ps, 1, " * all other functions and the _0 class handles indirecting to"); println(ps, 1, " * a result."); println(ps, 1, " * Creation: Aug. 3, 2006"); println(ps, 1, " */"); println(ps, 1, "public static final class _" + scArity + " extends General {"); } ps.println(); // RTValue fields for arguments. generateFields(); // Create the constructor for the node. generateConstructor(); // Now generate the clearMembers method. generateClearMembers(); // Generate the debugging info methods. generateDebug_getNChildren(); generateDebug_getChild(); generateDebug_getNodeStartText(); generateDebug_getNodeEndText(); generateDebug_getChildPrefixText(); if (scArity == 0) { generateReduce(true); } else { generateLazyNodeClass(); generateStrictNodeClass(); } println(ps, 1, "}"); } private final void generateInnerConstructor (boolean lazy) { if (lazy) { print(ps, 3, "public _L(RTSupercombinator function"); } else { print(ps, 3, "public _S(RTSupercombinator function"); } for (int i = 1; i <= scArity; ++i) { ps.print(", RTValue arg" + i); } ps.println(") {"); print(ps, 4, " super(function"); for (int i = 1; i <= scArity; ++i) { ps.print(", arg" + i); } ps.println(");"); println(ps, 3, "}"); } private final void generateReduce(boolean lazy) { println(ps, 3, "/**"); println(ps, 3, " * {@inheritDoc}"); println(ps, 3, " */"); println(ps, 3, "@Override"); println(ps, 3, "protected final RTValue reduce(RTExecutionContext ec)"); println(ps, 3, " throws CALExecutorException {"); println(ps, 3, " // Reduce from this application"); println(ps, 3, " // Update and return result"); //println(ps, 3, " ec.setRootNode(this);"); String functionName = "f"; if (scArity > 0) { println(ps, 3, " if (arg1 != null) {"); functionName = functionName + scArity; if (lazy) { functionName = functionName + "L"; } else { functionName = functionName + "S"; } } println(ps, 3, " setResult(function." + functionName + "("); if (scArity > 0) { for (int i = 1; i <= scArity; ++i) { println(ps, 3, " RTValue.lastRef(arg" + i + ", (arg" + i + " = null)),"); } } else { println(ps, 3, " this,"); } println(ps, 3, " ec));"); //println(ps, 3, " clearMembers();"); if (scArity > 0) { println(ps, 3, " } else if (result == null) {"); println(ps, 3, " throw new NullPointerException("); println(ps, 3, " \"Invalid reduction state in application. This is probably caused by a circular function definition.\");"); println(ps, 3, " }"); } println(ps, 3, " return (result);"); println(ps, 3, "}"); } private final void generateLazyNodeClass () { println(ps, 2, "public static final class _L extends _" + scArity + " {"); generateInnerConstructor(true); generateReduce(true); println(ps, 2, "}"); } private final void generateStrictNodeClass () { println(ps, 2, "public static final class _S extends _" + scArity + " {"); generateInnerConstructor(false); generateReduce(false); println(ps, 2, "}"); } private final void generateDebug_getChildPrefixText () { println(ps, 2, "/**"); println(ps, 2, " * {@inheritDoc}"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final String debug_getChildPrefixText(int childN) {"); println(ps, 2, " if (result != null) {"); println(ps, 2, " return super.debug_getChildPrefixText(childN);"); println(ps, 2, " }"); ps.println(); println(ps, 2, " if (childN >= 0 && childN < " + scArity + ") {"); println(ps, 2, " return \" \";"); println(ps, 2, " }"); ps.println(); println(ps, 2, " throw new IndexOutOfBoundsException();"); println(ps, 2, "}"); ps.println(); } private final void generateDebug_getNodeEndText() { println(ps, 2, "/**"); println(ps, 2, " * {@inheritDoc}"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final String debug_getNodeEndText() {"); println(ps, 2, " if (result != null) {"); println(ps, 2, " return super.debug_getNodeEndText();"); println(ps, 2, " }"); ps.println(); if (scArity > 0) { println(ps, 2, " return \")\";"); } else { println(ps, 2, " return \"\";"); } println(ps, 2, "}"); } private final void generateDebug_getNodeStartText() { println(ps, 2, "/**"); println(ps, 2, " * {@inheritDoc}"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final String debug_getNodeStartText() {"); println(ps, 2, " if (result != null) {"); println(ps, 2, " return super.debug_getNodeStartText();"); println(ps, 2, " }"); ps.println(); if (scArity > 0) { println(ps, 2, " return \"(\" + function.getQualifiedName();"); } else { println(ps, 2, " return function.getQualifiedName();"); } println(ps, 2, "}"); } private final void generateDebug_getChild() { println(ps, 2, "/**"); println(ps, 2, " * {@inheritDoc}"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final CalValue debug_getChild(int childN) {"); println(ps, 2, " if (result != null) {"); println(ps, 2, " return super.debug_getChild(childN);"); println(ps, 2, " }"); ps.println(); if (scArity > 0) { println(ps, 2, " switch (childN) {"); for (int i = 0; i < scArity; ++i) { println(ps, 2, " case " + i + ":"); println(ps, 2, " return arg" + (i + 1) + ";"); } println(ps, 2, " default:"); println(ps, 2, " throw new IndexOutOfBoundsException();"); println(ps, 2, " }"); } else { println(ps, 2, " throw new IndexOutOfBoundsException();"); } println(ps, 2, "}"); } private final void generateClearMembers() { println(ps, 2, "/*"); println(ps, 2, " * (non-Javadoc)"); println(ps, 2, " * @see org.openquark.cal.internal.runtime.lecc.RTResultFunction#clearMembers()"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final void clearMembers() {"); for (int i = 1; i <= scArity; ++i) { println(ps, 3, "arg" + i + " = null;"); } println(ps, 2, "}"); ps.println(); } private final void generateDebug_getNChildren () { println(ps, 2, "/**"); println(ps, 2, " * {@inheritDoc}"); println(ps, 2, " */"); println(ps, 2, "@Override"); println(ps, 2, "public final int debug_getNChildren() {"); println(ps, 3, "if (result != null) {"); println(ps, 4, "return super.debug_getNChildren();"); println(ps, 3, "}"); println(ps, 3, "return " + scArity + ";"); println(ps, 2, "}"); } public static void main(String[] args) { try { // Set up the file for i/o. File f = new File (args[0]); FileOutputStream fs = new FileOutputStream(f); PrintStream ps = new PrintStream (fs); // There is a static inner class derived from RTFullApp.General for // each arity from 1 to 15. for (int scArity = 0; scArity <= 15; ++scArity) { FullAppNodeGenerator generator = new FullAppNodeGenerator(scArity, ps); generator.generateClassDec(); ps.println(); } } catch (Exception e) { System.out.println("Exception generating code for partial application classes. " + e); } System.out.println("Generated source text sent to " + args[0]); } private static void print(final PrintStream ps, final int nTabs, final String text) { StringBuilder indentedText = new StringBuilder(); for (int i = 0; i < nTabs; ++i) { indentedText.append(" "); } indentedText.append(text); ps.print(indentedText.toString()); } private static void println(final PrintStream ps, final int nTabs, final String text) { print(ps, nTabs, text); ps.println(); } }