/* * 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. */ /* * EventLoop.java * Created: Jul 21, 2005 * By: Bo Ilic */ package org.openquark.cal.samples; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.openquark.cal.CALPlatformTestModuleNames; import org.openquark.cal.compiler.Compiler; import org.openquark.cal.compiler.CompilerMessageLogger; import org.openquark.cal.compiler.MessageLogger; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.compiler.SourceModel; import org.openquark.cal.compiler.io.EntryPoint; import org.openquark.cal.compiler.io.EntryPointSpec; import org.openquark.cal.compiler.io.InputPolicy; import org.openquark.cal.compiler.io.OutputPolicy; import org.openquark.cal.machine.CALExecutor; import org.openquark.cal.module.Cal.Core.CAL_Prelude; import org.openquark.cal.runtime.CALExecutorException; import org.openquark.cal.runtime.CalValue; import org.openquark.cal.runtime.ExecutionContext; import org.openquark.cal.services.BasicCALServices; import org.openquark.cal.services.WorkspaceManager; /** * Example class showing several different mechanism for CAL and Java to interact. * <p> * The examples are intended to be read in a linear fashion from the beginning of the * file to the end- they are ordered by complexity. * <p> * Some examples show how Java clients can call CAL functions in an "event loop" style * i.e. different CAL functions may be called depending upon user input between calls. * <p> * The Java client is able to supply arguments, some of which are Java * primitive types, and some of which are CAL values obtained from * previous calls to CAL functions in the event loop. The CAL function would then * return a result, part of which may be a Java value directly interpretable by the * Java code, and part may be a CAL value for use in making further CAL calls. * Note that the CAL values obtained as intermediate results may not be fully evaluated. * For example, the value could be a computation producing an infinite list. * <p> * * @author Bo Ilic */ public final class EventLoop { private final BasicCALServices calServices; private final ExecutionContext executionContext; private static final String WORKSPACE_FILE_NAME = "cal.platform.test.cws"; EventLoop() { calServices = BasicCALServices.make(WORKSPACE_FILE_NAME); CompilerMessageLogger messageLogger = new MessageLogger(); if (!calServices.compileWorkspace(null, messageLogger)) { System.err.println(messageLogger.toString()); } executionContext = calServices.getWorkspaceManager().makeExecutionContextWithDefaultProperties(); } /** * Turn on various test programs by editing the main method. Useful VM arguments for running this are: * * -Dorg.openquark.cal.machine.lecc.output_directory="D:\dev\EventLoop_lecc_bytecode" * -Xmx256m * * @param args */ public static void main(String[] args) { usage(); if (args.length != 1) { return; } String command = args[0]; System.out.println("\nDemo program: " + command + "\n"); if (command.equalsIgnoreCase("getNthPrime")) { EventLoop eventLoop = new EventLoop(); eventLoop.getNthPrime(5); } else if (command.equalsIgnoreCase("primesIterator")) { EventLoop eventLoop = new EventLoop(); eventLoop.primesIterator(); } else if (command.equalsIgnoreCase("twoListIterators")) { EventLoop eventLoop = new EventLoop(); eventLoop.twoListIterators(); } else if (command.equalsIgnoreCase("clientPrimePuller")) { EventLoop eventLoop = new EventLoop(); eventLoop.clientPrimePuller(); } else if (command.equalsIgnoreCase("clientTwoListPuller")) { EventLoop eventLoop = new EventLoop(); eventLoop.clientTwoListPuller(); } else if (command.equalsIgnoreCase("touchlessTwoListPuller")) { EventLoop eventLoop = new EventLoop(); eventLoop.touchlessTwoListPuller(); } else { System.out.println("invalid demo program choice"); } } private static void usage() { System.out.println("EventLoop usage: valid command line arguments are one of"); System.out.println(); System.out.println("getNthPrime --reuse of a single EntryPoint over multiple executions"); System.out.println(); System.out.println("primesIterator --client side lazy evaluation of a single CAL list using a Java iterator"); System.out.println("twoListIterators --intertwined multiple client side CAL list lazy evaluation using two Java iterators"); System.out.println(); System.out.println("clientPrimePuller --client side lazy evaluation of a single CAL list"); System.out.println("clientTwoListPuller --multiple lazy lazy evaluation. Multiple EntryPoints"); System.out.println("touchlessTwoListPuller --use of EntryPointSpec and IO policies to avoid marshaling functions in CAL"); } /** * Calls M2.getNthPrime, first with n = 5000, then 5001, etc, and then terminates. * This demonstrates reuse of the EntryPoint over multiple executions. * In particular, once the EntryPoint has been created, there is no further compilation * when evaluating the entry point at different arguments. * * @param nTimes number of times to call the function in a row. First with 5000, then 5001, etc */ private void getNthPrime(int nTimes) { //sample run: //Demo program: getNthPrime // //the result of getNthPrime 5000 is 48619 //the result of getNthPrime 5001 is 48623 //the result of getNthPrime 5002 is 48647 //the result of getNthPrime 5003 is 48649 //the result of getNthPrime 5004 is 48661 CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); EntryPoint entryPoint = compiler.getEntryPoint( EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "getNthPrime")), CALPlatformTestModuleNames.M2, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } CALExecutor executor = workspaceManager.makeExecutor(executionContext); try { for (int i = 0; i < nTimes; ++i) { Object result = executor.exec(entryPoint, new Object[] {new Integer(5000 + i)}); System.out.println("the result of getNthPrime " + (5000 + i) + " is " + result); } } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); } } /** * Illustrates calling a function that produces a lazy CAL list (M1.allPrimes), and then * having the Java client code traverse the list lazily using a java.util.Iterator. * <p> * Once the EntryPoint is created, there is no further compilation, although the CAL evaluator * is involved in evaluating each subsequent element of the list as the Java iterator is traversed. * <p> * Similar to clientPrimePuller, but uses the List.toJIterator function to simplify * client traversal of the CAL list. This approach is perhaps less general than the approach * in clientPrimePuller, but is simpler to use. */ private void primesIterator() { //sample run: //Demo program: primesIterator // //How many more primes would you like? (enter q to quit) //3 //the next 3 primes are [2, 3, 5] //How many more primes would you like? (enter q to quit) //4 //the next 4 primes are [7, 11, 13, 17] //How many more primes would you like? (enter q to quit) //q CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); CALExecutor executor = workspaceManager.makeExecutor(executionContext); //the below function represent a model of what is created when using EntryPointSpec classes i.e. //explicit input and output policies. //allPrimesAdjunct :: Prelude.JObject; //allPrimesAdjunct = (Prelude.output # List.toJIterator) M1.allPrimes; EntryPointSpec allPrimesEntryPointSpec = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M1, "allPrimes"), null, OutputPolicy.ITERATOR_OUTPUT_POLICY); EntryPoint allPrimesEntryPoint = compiler.getEntryPoint(allPrimesEntryPointSpec, CALPlatformTestModuleNames.M1, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } try { Iterator<?> primesIterator = (Iterator<?>)executor.exec(allPrimesEntryPoint, null); BufferedReader inBuff = new BufferedReader(new BufferedReader(new java.io.InputStreamReader(System.in))); while (true) { System.out.println("How many more primes would you like? (enter q to quit)"); String command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nPrimesMore = 1; try { nPrimesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm extremely sorry, but I did not understand you. I'll assume one more prime."); } List<Object> nextNPrimes = new ArrayList<Object>(nPrimesMore); for (int i = 0; i < nPrimesMore; ++i) { nextNPrimes.add(primesIterator.next()); } System.out.println("the next " + nPrimesMore + " primes are " + nextNPrimes); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the allPrimes CAF). workspaceManager.resetCachedResults(executionContext); } } } catch (IOException ioe) { System.out.println(ioe); } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); } } /** * Illustrates calling two different CAL functions producing lazy CAL lists, and then * having the Java client code traverse the lists lazily using two different java.util.Iterators. * The traversals are interspersed with each other. * <p> * Once the EntryPoints are created, there is no further compilation, although the CAL evaluator is involved * in evaluating each subsequent element of the two lists as the Java iterators are traversed. * <p> * Similar to touchlessTwoListPuller but uses the List.toJIterator function to simplify * client traversal of the two CAL lists. This approach is perhaps less general than the approach * in touchlessTwoListPuller, but is simpler to use. */ private void twoListIterators() { //sample run // Demo program: twoListIterators // // How many more primes would you like? (enter q to quit) // 5 // the next 5 primes are [2, 3, 5, 7, 11] // How many more names would you like? (enter q to quit) // 3 // the next 3 names are [Alexander, Andy, Anton] // How many more primes would you like? (enter q to quit) // 3 // the next 3 primes are [13, 17, 19] // How many more names would you like? (enter q to quit) // 4 // the next 4 names are [Frank, Fred, Helen, Linda] // How many more primes would you like? (enter q to quit) // q CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); CALExecutor executor = workspaceManager.makeExecutor(executionContext); List<EntryPointSpec> entryPointSpecs = new ArrayList<EntryPointSpec>(); //list of EntryPointSpec //the below function represent a model of what is created when using EntryPointSpec classes i.e. //explicit input and output policies. //allPrimesAdjunct :: Prelude.JObject; //allPrimesAdjunct = (Prelude.output # List.toJIterator) M1.allPrimes; EntryPointSpec allPrimesEntryPointSpec = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M1, "allPrimes"), null, OutputPolicy.ITERATOR_OUTPUT_POLICY); EntryPointSpec stringListEntryPointSpec = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "stringList"), null, OutputPolicy.ITERATOR_OUTPUT_POLICY); entryPointSpecs.add(allPrimesEntryPointSpec); entryPointSpecs.add(stringListEntryPointSpec); compiler.getEntryPoints(entryPointSpecs, CALPlatformTestModuleNames.M2, messageLogger); List<EntryPoint> entryPoints = compiler.getEntryPoints(entryPointSpecs, CALPlatformTestModuleNames.M2, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } EntryPoint allPrimesEntryPoint = entryPoints.get(0); EntryPoint stringListEntryPoint = entryPoints.get(1); try { Iterator<?> primesIterator = (Iterator<?>)executor.exec(allPrimesEntryPoint, null); Iterator<?> namesIterator = (Iterator<?>)executor.exec(stringListEntryPoint, null); BufferedReader inBuff = new BufferedReader(new BufferedReader(new java.io.InputStreamReader(System.in))); while (true) { System.out.println("How many more primes would you like? (enter q to quit)"); String command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nPrimesMore = 1; try { nPrimesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm extremely sorry, but I did not understand you. I'll assume one more prime."); } List<Object> nextNPrimes = new ArrayList<Object>(nPrimesMore); for (int i = 0; i < nPrimesMore; ++i) { nextNPrimes.add(primesIterator.next()); } System.out.println("the next " + nPrimesMore + " primes are " + nextNPrimes); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the allPrimes CAF). workspaceManager.resetCachedResults(executionContext); } System.out.println("How many more names would you like? (enter q to quit)"); command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nNamesMore = 1; try { nNamesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm surpassingly sorry, but I did not understand you. I'll assume one more name."); } List<Object> nextNNames = new ArrayList<Object>(nNamesMore); for (int i = 0; i < nNamesMore; ++i) { nextNNames.add(namesIterator.next()); } System.out.println("the next " + nNamesMore + " names are " + nextNNames); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the Prelude.stringList CAF). workspaceManager.resetCachedResults(executionContext); } } } catch (IOException ioe) { System.out.println(ioe); } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); } } /** * Demonstrates an interactive, stateful CAL program with a Java client * lazily exploring the results of CAL function. Each "event loop" asks the * user how many more primes they want to see. The CAL function that is run * produces a Java list with the next number of primes the user asked for, * and a CAL list with the remaining primes (this is an infinite list, but * since CAL is lazy that is OK). This list of remaining primes is then * passed back in subsequent calls. */ private void clientPrimePuller() { //Demo program: clientPrimePuller // //How many more primes would you like? (enter q to quit) //4 //the next 4 are [2, 3, 5, 7] //How many more primes would you like? (enter q to quit) //6 //the next 6 are [11, 13, 17, 19, 23, 29] //How many more primes would you like? (enter q to quit) //2 //the next 2 are [31, 37] //How many more primes would you like? (enter q to quit) //q CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); CALExecutor executor = workspaceManager.makeExecutor(executionContext); EntryPoint allPrimesExternalEntryPoint = compiler.getEntryPoint( EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "allPrimesExternal")), CALPlatformTestModuleNames.M2, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } try { CalValue remainingPrimesCalValue = (CalValue)executor.exec(allPrimesExternalEntryPoint, null); EntryPoint nextNPrimesExternalEntryPoint = compiler.getEntryPoint( EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "nextNPrimesExternal")), CALPlatformTestModuleNames.M2, messageLogger); BufferedReader inBuff = new BufferedReader(new BufferedReader(new java.io.InputStreamReader(System.in))); while (true) { System.out.println("How many more primes would you like? (enter q to quit)"); String command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nPrimesMore = 1; try { nPrimesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm extremely sorry, but I did not understand you. I'll assume one more prime."); } //a java.util.List with 2 elements. The first is a java.util.List of nPrimesMore primes. The second is a CalValue //containing the remaining primes (as a lazy internal CAL list). List<?> result = (List<?>)executor.exec(nextNPrimesExternalEntryPoint, new Object[] {remainingPrimesCalValue, new Integer(nPrimesMore)}); List<?> nextNPrimes = (List<?>)result.get(0); remainingPrimesCalValue = (CalValue)result.get(1); System.out.println("the next " + nPrimesMore + " are " + nextNPrimes); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the allPrimes CAF). workspaceManager.resetCachedResults(executionContext); } } } catch (IOException ioe) { System.out.println(ioe); } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); return; } } /** * Demonstrates clients pulling values out of 2 different lists: * a CAL list of primes * a CAL list of Strings * * All EntryPoints are created once and for all at the beginning. */ private void clientTwoListPuller() { //sample run: //Demo program: clientTwoListPuller // //How many more primes would you like? (enter q to quit) //4 //the next 4 primes are [2, 3, 5, 7] //How many more names would you like? (enter q to quit) //3 //the next 3 names are [Alexander, Andy, Anton] //How many more primes would you like? (enter q to quit) //6 //the next 6 primes are [11, 13, 17, 19, 23, 29] //How many more names would you like? (enter q to quit) //2 //the next 2 names are [Frank, Fred] //How many more primes would you like? (enter q to quit) //q CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); CALExecutor executor = workspaceManager.makeExecutor(executionContext); List<QualifiedName> entryPointNames = new ArrayList<QualifiedName>(); //list of QualifiedName entryPointNames.add(QualifiedName.make(CALPlatformTestModuleNames.M2, "allPrimesExternal")); entryPointNames.add(QualifiedName.make(CALPlatformTestModuleNames.M2, "stringListExternal")); entryPointNames.add(QualifiedName.make(CALPlatformTestModuleNames.M2, "takeNExternal_ListOfInt")); entryPointNames.add(QualifiedName.make(CALPlatformTestModuleNames.M2, "takeNExternal_ListOfString")); List<EntryPoint> entryPoints = compiler.getEntryPoints( EntryPointSpec.buildListFromQualifiedNames(entryPointNames), CALPlatformTestModuleNames.M2, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } EntryPoint allPrimesExternal = entryPoints.get(0); EntryPoint stringListExternal = entryPoints.get(1); EntryPoint takeNExternal_ListOfInt = entryPoints.get(2); EntryPoint takeNExternal_ListOfString = entryPoints.get(3); try { CalValue remainingPrimesCalValue = (CalValue)executor.exec(allPrimesExternal, null); CalValue remainingNamesCalValue = (CalValue)executor.exec(stringListExternal, null); BufferedReader inBuff = new BufferedReader(new BufferedReader(new java.io.InputStreamReader(System.in))); while (true) { System.out.println("How many more primes would you like? (enter q to quit)"); String command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nPrimesMore = 1; try { nPrimesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm extremely sorry, but I did not understand you. I'll assume one more prime."); } List<?> result = (List<?>)executor.exec(takeNExternal_ListOfInt, new Object[] {remainingPrimesCalValue, new Integer(nPrimesMore)}); //a java.util.List with 2 elements. The first is a java.util.List of nPrimesMore primes. The second is a CalValue //containing the remaining primes (as a lazy internal CAL list). List<?> nextNPrimes = (List<?>)result.get(0); remainingPrimesCalValue = (CalValue)result.get(1); System.out.println("the next " + nPrimesMore + " primes are " + nextNPrimes); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the allPrimes CAF). workspaceManager.resetCachedResults(executionContext); } System.out.println("How many more names would you like? (enter q to quit)"); command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nNamesMore = 1; try { nNamesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm surpassingly sorry, but I did not understand you. I'll assume one more name."); } List<?> result = (List<?>)executor.exec(takeNExternal_ListOfString, new Object[] {remainingNamesCalValue, new Integer(nNamesMore)}); //a java.util.List with 2 elements. The first is a java.util.List of nNamesMore names. The second is a CalValue //containing the remaining names (as a CAL list). List<?> nextNNames = (List<?>)result.get(0); remainingNamesCalValue = (CalValue)result.get(1); System.out.println("the next " + nNamesMore + " names are " + nextNNames); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the Prelude.stringList CAF). workspaceManager.resetCachedResults(executionContext); } } } catch (IOException ioe) { System.out.println(ioe); } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); } } /** * Demonstrates clients pulling values out of CAL lists with no special marshaling * wrappers added in a CAL module. All EntryPoints are created once and for all at the beginning. */ private void touchlessTwoListPuller() { //sample run // Demo program: touchlessTwoListPuller // // How many more primes would you like? (enter q to quit) // 5 // the next 5 primes are [2, 3, 5, 7, 11] // How many more names would you like? (enter q to quit) // 3 // the next 3 names are [Alexander, Andy, Anton] // How many more primes would you like? (enter q to quit) // 3 // the next 3 primes are [13, 17, 19] // How many more names would you like? (enter q to quit) // 4 // the next 4 names are [Frank, Fred, Helen, Linda] // How many more primes would you like? (enter q to quit) // q CompilerMessageLogger messageLogger = new MessageLogger(); WorkspaceManager workspaceManager = calServices.getWorkspaceManager(); Compiler compiler = calServices.getCompiler(); CALExecutor executor = workspaceManager.makeExecutor(executionContext); List<EntryPointSpec> entryPointSpecs = new ArrayList<EntryPointSpec>(); //list of EntryPointSpec //the below 2 functions represent a model of what is created when using EntryPointSpec classes i.e. //explicit input and output policies. //allPrimesAdjunct :: Prelude.JObject; //allPrimesAdjunct = (\x -> Prelude.output ((Prelude.unsafeCoerce x) :: Prelude.CalValue)) M1.allPrimes; // //takeNIntAdjunct :: Prelude.JObject -> Prelude.JObject -> Prelude.JObject; //takeNIntAdjunct list nToTake = // (\x -> Prelude.output ((Prelude.unsafeCoerce x) :: ([Int], CalValue))) // (takeN // ((\x -> (Prelude.unsafeCoerce ((Prelude.input x) :: Prelude.CalValue)) :: [Prelude.Int]) list) // ((Prelude.input :: Prelude.JObject -> Prelude.Int) nToTake) // ); EntryPointSpec allPrimesEntryPointSpec = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M1, "allPrimes"), new InputPolicy[] {}, OutputPolicy.CAL_VALUE_OUTPUT_POLICY); EntryPointSpec stringListEntryPointSpec = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "stringList"), new InputPolicy[] {}, OutputPolicy.CAL_VALUE_OUTPUT_POLICY); String Prelude_Int = CAL_Prelude.TypeConstructors.Int.getQualifiedName(); String Prelude_CalValue = CAL_Prelude.TypeConstructors.CalValue.getQualifiedName(); String Prelude_String = CAL_Prelude.TypeConstructors.String.getQualifiedName(); String Prelude_unsafeCoerce = CAL_Prelude.Functions.unsafeCoerce.getQualifiedName(); String Prelude_output = CAL_Prelude.Functions.output.getQualifiedName(); SourceModel.TypeExprDefn listOfIntType = SourceModel.TypeExprDefn.List.make(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Int)); EntryPointSpec takeNListOfInt = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "takeN"), new InputPolicy[] { InputPolicy.makeTypedCalValueInputPolicy(listOfIntType), InputPolicy.DEFAULT_INPUT_POLICY }, OutputPolicy.make("(\\x -> " + Prelude_output + " ((" + Prelude_unsafeCoerce + " x) :: ([" + Prelude_Int + "], " + Prelude_CalValue + ")))")); SourceModel.TypeExprDefn listOfStringType = SourceModel.TypeExprDefn.List.make(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.String)); EntryPointSpec takeNListOfString = EntryPointSpec.make(QualifiedName.make(CALPlatformTestModuleNames.M2, "takeN"), new InputPolicy[] { InputPolicy.makeTypedCalValueInputPolicy(listOfStringType), InputPolicy.DEFAULT_INPUT_POLICY }, OutputPolicy.make("(\\x -> " + Prelude_output + " ((" + Prelude_unsafeCoerce + " x) :: ([" + Prelude_String + "], " + Prelude_CalValue + ")))")); entryPointSpecs.add(allPrimesEntryPointSpec); entryPointSpecs.add(stringListEntryPointSpec); entryPointSpecs.add(takeNListOfInt); entryPointSpecs.add(takeNListOfString); List<EntryPoint> entryPoints = compiler.getEntryPoints(entryPointSpecs, CALPlatformTestModuleNames.M2, messageLogger); if (messageLogger.getNMessages() > 0) { System.err.println(messageLogger.toString()); } EntryPoint allPrimesEntryPoint = entryPoints.get(0); EntryPoint stringListEntryPoint = entryPoints.get(1); EntryPoint takeNListOfIntEntryPoint = entryPoints.get(2); EntryPoint takeNListOfStringEntryPoint = entryPoints.get(3); try { CalValue remainingPrimesCalValue = (CalValue)executor.exec(allPrimesEntryPoint, null); CalValue remainingNamesCalValue = (CalValue)executor.exec(stringListEntryPoint, null); BufferedReader inBuff = new BufferedReader(new BufferedReader(new java.io.InputStreamReader(System.in))); while (true) { System.out.println("How many more primes would you like? (enter q to quit)"); String command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nPrimesMore = 1; try { nPrimesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm extremely sorry, but I did not understand you. I'll assume one more prime."); } List<?> result = (List<?>)executor.exec(takeNListOfIntEntryPoint, new Object[] {remainingPrimesCalValue, new Integer(nPrimesMore)}); //a java.util.List with 2 elements. The first is a java.util.List of nPrimesMore primes. The second is a CalValue //containing the remaining primes (as a lazy internal CAL list). List<?> nextNPrimes = (List<?>)result.get(0); remainingPrimesCalValue = (CalValue)result.get(1); System.out.println("the next " + nPrimesMore + " primes are " + nextNPrimes); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the allPrimes CAF). workspaceManager.resetCachedResults(executionContext); } System.out.println("How many more names would you like? (enter q to quit)"); command = inBuff.readLine().trim(); if (command.startsWith("q")) { break; } else { int nNamesMore = 1; try { nNamesMore = Integer.parseInt(command); } catch (NumberFormatException nfe) { System.out.println("I'm surpassingly sorry, but I did not understand you. I'll assume one more name."); } List<?> result = (List<?>)executor.exec(takeNListOfStringEntryPoint, new Object[] {remainingNamesCalValue, new Integer(nNamesMore)}); //a java.util.List with 2 elements. The first is a java.util.List of nNamesMore names. The second is a CalValue //containing the remaining names (as a lazy internal CAL list). List<?> nextNNames = (List<?>)result.get(0); remainingNamesCalValue = (CalValue)result.get(1); System.out.println("the next " + nNamesMore + " names are " + nextNNames); //we can reset cached CAFs here if we like. (Works without this as well. The point here is to not hold onto //the Prelude.stringList CAF). workspaceManager.resetCachedResults(executionContext); } } } catch (IOException ioe) { System.out.println(ioe); } catch (CALExecutorException executorException) { System.out.println("Execution terminated with an executor exception:" + executorException); } } }