
// JepInterp.java
// Andrew Davison, ad@coe.psu.ac.th, July 2023

/* Short Jep (Java Embedded Python) examples.
   https://github.com/ninia/jep
     * set(), exec(), getValue()
     * use of Python import
     * Python functions
     * Python arrays, tuples, dictionaries
     * Python classes
     * Python scripts (hello.py)

  Usage:
     > compile JepInterp
     > run JepInterp 
*/

import java.util.*;

import jep.*;
import jep.python.*;


public class JepInterp 
{

  public static void main(String[] args) throws JepException 
  {
    System.out.println("Starting Jep...");
    Interpreter jep = new SharedInterpreter();

    jep.set("arg", 42);
    jep.exec("print('arg =',arg)");

    jep.exec("x = 2 + 2");
    Long x = (Long) jep.getValue("x");
    System.out.println("x: " + x);

    jep.exec("s = 'Hello World'");
    jep.exec("print(s)");
    jep.exec("print(s[1:-1])");

    // import 
    jep.exec("import random");
    jep.exec("random.seed(5)");
    jep.exec("print(random.random())");
    double rnd = jep.getValue("random.random()", Double.class);
    System.out.println("rnd = " + rnd);

    // functions
    jep.eval("def hi(arg):\n" +
              "    return 'Hi ' +  str(arg)");
    PyCallable pyHi = jep.getValue("hi", PyCallable.class);
    String result = (String) pyHi.call("World");
    System.out.println(result);

    jep.eval("def mysqr(x):\n" +
              "    return x*x");
    PyCallable pySqr = (PyCallable) jep.getValue("mysqr");
    long res = (long) pySqr.call(2);
    System.out.println("mysqr(2) = " + res);

    // arrays
    int[] ia = new int[] {3, 4, 5};
    double[] da = new double[] {2.0};
    String[] sa = new String[] {"0"};

    jep.eval("def manip(li, val):\n\tli[0]=val\n\tli.commit()");
                // without commit there is no change
    jep.invoke("manip", ia, 1);
    jep.invoke("manip", da, 1.0);
    jep.invoke("manip", sa, "1");
    System.out.println(Arrays.toString(ia));
    System.out.println(da[0] + ", " + sa[0]);

    // tuples --> list
    List<?> tup = (List<?>) jep.getValue(
                        "('apple', 'banana', 'cherry')");
    System.out.println("tup: " + tup);

    // dictionary --> map
    HashMap<?,?> map = (HashMap<?,?>) jep.getValue(
                "{ 'United States': 'Washington D.C.', " +
                  "'Italy': 'Rome', " +
                  "'England': 'London' }" );
    System.out.println("Capital of England: " + 
                                      map.get("England"));

    // classes
    jep.eval("class Hey(object):\n" +
              "    def __init__(self):\n" +
              "        pass\n" +
              "    def foo(self):\n" +
              "        return 'Hey World'\n");
    jep.eval("h = Hey()");
    PyObject pyHey = jep.getValue("h", PyObject.class);
    PyCallable pyHeyFoo = pyHey.getAttr("foo", PyCallable.class);
    result = (String) pyHeyFoo.call();
    System.out.println("h.foo(): " + result);

    // scripts
    jep.set("name", "Andrew");
    jep.runScript("hello.py");
  } // end of main()

} // end of JepInterp class
