diff options
| author | Joshua Rahm <joshua.rahm@colorado.edu> | 2015-01-27 18:40:32 -0700 |
|---|---|---|
| committer | Joshua Rahm <joshua.rahm@colorado.edu> | 2015-01-27 18:40:32 -0700 |
| commit | 5f3fb9afece2125cbeba79d61a8d88460b7878d7 (patch) | |
| tree | b0e1e60bae9927a9449561bf7fe9431a54d12be9 | |
| download | LegacyQBar-5f3fb9afece2125cbeba79d61a8d88460b7878d7.tar.gz LegacyQBar-5f3fb9afece2125cbeba79d61a8d88460b7878d7.tar.bz2 LegacyQBar-5f3fb9afece2125cbeba79d61a8d88460b7878d7.zip | |
initial commit
137 files changed, 8594 insertions, 0 deletions
diff --git a/hello.qbar b/hello.qbar new file mode 100755 index 0000000..a18e8de --- /dev/null +++ b/hello.qbar @@ -0,0 +1,8 @@ +#!/usr/bin/qbar +Import qbar/lang/System.qbar; + +let main = do { + for [ 0 .. ] -> i { + System.printStrLn( "" ++ i ++ ".)" ); + } +} diff --git a/installer/README.txt b/installer/README.txt new file mode 100755 index 0000000..b621bb5 --- /dev/null +++ b/installer/README.txt @@ -0,0 +1 @@ +To install it is very simple, just run installer.sh diff --git a/installer/install.sh b/installer/install.sh new file mode 100755 index 0000000..c0c47e3 --- /dev/null +++ b/installer/install.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +if [ `whoami` != root ] ; then + echo "Woah! Not so fast, need to be root!" + exit 1 +fi + +if [ -d /usr/lib/qbar ] ; then + echo "Wait, qbar is already installed, or at least the directory is still there (/usr/lib/qbar)" + + echo "Would you like to reinstall it? [Y/n]" + read input + + while [[ ($input != Y && $input != n) ]] ; do + echo "Y or n" + read input + done + + if [ $input == n ] ; then + exit 0 + else + rm -rv /usr/lib/qbar + rm -v /usr/bin/qbar + fi +fi + +tar -xzvf qbar_package.tgz +mv -v qbar/ /usr/lib/ + +# ---------- Time to install the binary into the right directory ------------ +cd /usr/bin + +# need to sym-link to qbar, then we should be good. +ln -sv /usr/lib/qbar/qbar.sh qbar +chmod +x qbar + diff --git a/installer/qbar/lib/JavaCommon.jar b/installer/qbar/lib/JavaCommon.jar Binary files differnew file mode 100644 index 0000000..604c670 --- /dev/null +++ b/installer/qbar/lib/JavaCommon.jar diff --git a/installer/qbar/lib/QBarInterpreter.jar b/installer/qbar/lib/QBarInterpreter.jar Binary files differnew file mode 100644 index 0000000..a95ecb1 --- /dev/null +++ b/installer/qbar/lib/QBarInterpreter.jar diff --git a/installer/qbar/lib/endorsed/io.jar b/installer/qbar/lib/endorsed/io.jar Binary files differnew file mode 100644 index 0000000..38cb62e --- /dev/null +++ b/installer/qbar/lib/endorsed/io.jar diff --git a/installer/qbar/lib/endorsed/mysql-connector-java-5.1.16-bin.jar b/installer/qbar/lib/endorsed/mysql-connector-java-5.1.16-bin.jar Binary files differnew file mode 100644 index 0000000..e62f2cb --- /dev/null +++ b/installer/qbar/lib/endorsed/mysql-connector-java-5.1.16-bin.jar diff --git a/installer/qbar/lib/endorsed/mysql.jar b/installer/qbar/lib/endorsed/mysql.jar Binary files differnew file mode 100644 index 0000000..023d025 --- /dev/null +++ b/installer/qbar/lib/endorsed/mysql.jar diff --git a/installer/qbar/qbar.sh b/installer/qbar/qbar.sh new file mode 100755 index 0000000..31d7033 --- /dev/null +++ b/installer/qbar/qbar.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +java -jar /usr/lib/qbar/lib/QBarInterpreter.jar -p /usr/lib/qbar $@ diff --git a/installer/qbar/qbar/io/BufferedReader.qbar b/installer/qbar/qbar/io/BufferedReader.qbar new file mode 100644 index 0000000..0b5c382 --- /dev/null +++ b/installer/qbar/qbar/io/BufferedReader.qbar @@ -0,0 +1,62 @@ +Import qbar/io/Reader.qbar;
+Import qbar/lang/Maybe.qbar;
+Import qbar/lang/System.qbar;
+
+Namespace BufferedReader {
+ Incorporate Reader;
+
+ Struct BufferedReader extends Reader {
+ let new BufferedReader( reader ) = do {
+ this.init( reader );
+
+ if reader isa Reader {
+ this.reader <- reader;
+ } else {
+ this.reader <- new Reader( reader );
+ }
+
+ this.buffer <- [];
+ this.bufSize <- 4096;
+ this.bufCur <- 0;
+ this.dbg <- 1;
+
+ System.printStrLn( "START" );
+
+ this.readBuffer();
+ }
+
+ let read = do {
+ if this.bufCur == this.bufSize {
+ this.readBuffer();
+ this.bufCur <- 0;
+ }
+
+ yeild <- this.buffer#this.bufCur;
+ this.bufCur <- this.bufCur + 1;
+
+ return yeild;
+ }
+
+ let readBuffer = do {
+ System.printStrLn( "Reading Buffer " ++ this.dbg );
+ this.buffer <- this.readBytes( this.bufSize );
+ this.dbg <- this.dbg + 1;
+ }
+
+ let readLine = do {
+ str <- "" ++ "";
+
+ i <- 0;
+ while ( i <- this.read() ) != 10 {
+ if i == -1 {
+ return if str.length == 0 then Maybe.new Null()
+ else Maybe.new Maybe( str );
+ }
+
+ str +< i as Character;
+ }
+
+ return Maybe.new Maybe(str);
+ }
+ }
+}
\ No newline at end of file diff --git a/installer/qbar/qbar/io/File.qbar b/installer/qbar/qbar/io/File.qbar new file mode 100644 index 0000000..3f848aa --- /dev/null +++ b/installer/qbar/qbar/io/File.qbar @@ -0,0 +1,10 @@ +-{
+ This namespace has several native methods
+ that are used to help dealing with file operations.
+}-
+Namespace File {
+ -{
+ Incorporates com.modulus.qbar.io.IOTools class
+ }-
+ Incorporate Native com.modulus.qbar.io.IOTools;
+}
\ No newline at end of file diff --git a/installer/qbar/qbar/io/Reader.qbar b/installer/qbar/qbar/io/Reader.qbar new file mode 100644 index 0000000..3522adf --- /dev/null +++ b/installer/qbar/qbar/io/Reader.qbar @@ -0,0 +1,24 @@ +Namespace Reader {
+ Struct Reader {
+ -- some kind of instream
+ let new Reader( instream ) = this.init( instream );
+
+ let init( instream ) = this.instream <- instream;
+
+ let close = this.instream.close();
+
+ let mark = this.instream.mark();
+
+ let reset = this.instream.reset();
+
+ let read = this.instream.read();
+
+ let readBytes(n) = this.instream.readBytes(n);
+
+ let skip(n) = this.instream.skip();
+
+ let available = this.instream.available();
+
+ let nextChar = this.read() as Character;
+ }
+}
\ No newline at end of file diff --git a/installer/qbar/qbar/lang/Math.qbar b/installer/qbar/qbar/lang/Math.qbar new file mode 100644 index 0000000..965c123 --- /dev/null +++ b/installer/qbar/qbar/lang/Math.qbar @@ -0,0 +1,84 @@ +-{
+ Math namespace, this holds many
+ useful functions for anytime
+ math computations.
+
+ This namespace includes aliases
+ of all the functions in java.lang.Math
+ and also includes some extra series
+ functions.
+ }-
+Namespace QBMath {
+
+ -- need to include the native java class
+ Incorporate Native java.lang.Math;
+
+ -{
+ The constructor of QBMath creates some
+ of the basic series that QBMath uses.
+ }-
+ let construct = do {
+
+
+ -- the `this` is negated all too often
+ -{
+ The series list for pascal's
+ triangle.
+ }-
+ this.pascalSeries <- [ n | if n <= 0 then [1]
+ else if n == 1 then [ 1, 1 ]
+ else QBMath.pascalTriangle( this#(n-1) ) ];
+
+ -{
+ The series list for the fibonacci
+ series
+ }-
+ this.fibonacciSeries <- [ n | if n < 2 then n
+ else this#( n - 1 ) + this#(n - 2) ];
+
+ -{
+ The series list for the
+ factorial series.
+ }-
+ this.factorialSeries <- [ n | if n <= 1 then 1
+ else n * this#(n - 1) ];
+ }
+
+ -{
+ The pascal function takes
+ a list and uses that list
+ to generate what would be
+ the next list in the pascal
+ series.
+ }-
+ let pascalTriangle( lastList ) = do {
+ ret <- [1];
+
+ for [ 0 .. lastList.length - 2 ] -> n {
+ ret +< lastList#n + lastList#(n+1);
+ }
+
+ ret +< 1;
+ return ret;
+ }
+
+ -{
+ Directly accesses the factorialSeries
+ get function.
+
+ @return the factorial of `n` (`n!`)
+ }-
+ let factorial( n ) = this.factorialSeries # n;
+
+ -{
+ @return the `n`<sup>th</sup> number
+ in the fibonacci series.
+ }-
+ let fibonacci( n ) = this.fibonacciSeries # n;
+
+ -{
+ @return the `n`<sup>th</sup> list in
+ pascal's triangle list.
+ }-
+ let pascal( n ) = this.pascalList # n;
+}
\ No newline at end of file diff --git a/installer/qbar/qbar/lang/Maybe.qbar b/installer/qbar/qbar/lang/Maybe.qbar new file mode 100644 index 0000000..5b4e37d --- /dev/null +++ b/installer/qbar/qbar/lang/Maybe.qbar @@ -0,0 +1,16 @@ +Import qbar/lang/System.qbar;
+
+Namespace Maybe {
+ Struct Maybe {
+ let new Null = this.null <- 1;
+
+ let new Maybe( obj ) = do {
+ this.obj <- obj;
+ this.null <- 0;
+ }
+
+ let isNull = this.null;
+
+ let getObj = this.obj;
+ }
+}
\ No newline at end of file diff --git a/installer/qbar/qbar/lang/System.qbar b/installer/qbar/qbar/lang/System.qbar new file mode 100644 index 0000000..6b04d59 --- /dev/null +++ b/installer/qbar/qbar/lang/System.qbar @@ -0,0 +1,11 @@ +
+-{
+ This namespace holds many raw and basic
+ functions that the user may want to use.
+
+ This Namespace is for the most part native.
+ }-
+Namespace System {
+ -- incorporate the native QBSystem class
+ Incorporate Native com.modulus.qbar.lang.QBSystem;
+}
\ No newline at end of file diff --git a/installer/qbar_package.tgz b/installer/qbar_package.tgz Binary files differnew file mode 100755 index 0000000..2d6d4a6 --- /dev/null +++ b/installer/qbar_package.tgz diff --git a/project/JavaCommon/.classpath b/project/JavaCommon/.classpath new file mode 100644 index 0000000..fb50116 --- /dev/null +++ b/project/JavaCommon/.classpath @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/project/JavaCommon/.project b/project/JavaCommon/.project new file mode 100644 index 0000000..0e6dc5d --- /dev/null +++ b/project/JavaCommon/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>JavaCommon</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/project/JavaCommon/build.xml b/project/JavaCommon/build.xml new file mode 100644 index 0000000..cc80037 --- /dev/null +++ b/project/JavaCommon/build.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- ====================================================================== + Apr 5, 2011 7:08:11 PM + + JavaCommon + Common resources shared by all java projects + + jrahm + ====================================================================== --> +<project name="JavaCommon" default="build"> + + <import file="common_build.xml" /> + + <path id="project.class.path"> + <fileset dir="${lib.dir}" includes="**/*.jar" /> + </path> + + <target name="lib" description="Builds The Lib Direrctory"> + <mkdir dir="${lib.dir}" /> + + <copy todir="${lib.dir}" > + <fileset dir="lib" includes="**/*.jar" /> + </copy> + </target> + + <target name="compile" depends="lib"> + <mkdir dir="${bin.dir}" /> + <javac srcdir="${src.dir}" includes="**" encoding="utf-8" destdir="${bin.dir}"> + <classpath refid="project.class.path" /> + </javac> + </target> + + <target name="package" depends="compile" > + <mkdir dir="${lib.dir}"/> + <jar basedir="${bin.dir}" destfile="${lib.dir}/${ant.project.name}.jar" /> + </target> + + <target name="doc"> + <mkdir dir="${doc.dir}" /> + <javadoc sourcepath="${src.dir}" destdir="${doc.dir}" /> + </target> + + <target name="build" depends="package" /> + + <target name="clean"> + <delete dir="bin"/> + </target> +</project> diff --git a/project/JavaCommon/common_build.xml b/project/JavaCommon/common_build.xml new file mode 100644 index 0000000..c41aade --- /dev/null +++ b/project/JavaCommon/common_build.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- ====================================================================== + Apr 5, 2011 11:04:12 PM + + project + description + + jrahm + ====================================================================== --> +<project name="BuildCommon" > + + <property name="lib.dir" value="../../../build/java_libs"/> + <property name="bin.dir" value="classes" /> + <property name="src.dir" value="src" /> + <property name="doc.dir" value="../../../build/java_libs/doc"/> + <property name="endorsed.dir" value="../../../build/qbar/lib/endorsed"/> + +</project> diff --git a/project/JavaCommon/src/.project b/project/JavaCommon/src/.project new file mode 100644 index 0000000..9fdd004 --- /dev/null +++ b/project/JavaCommon/src/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>JavaExtendedAPI</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/project/JavaCommon/src/com/modulus/access/ArrayFunction.java b/project/JavaCommon/src/com/modulus/access/ArrayFunction.java new file mode 100644 index 0000000..89ce636 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/access/ArrayFunction.java @@ -0,0 +1,24 @@ +package com.modulus.access; + +/** + * Any kind of function that takes an array of type <code>E</code> + * and returns an object of type <code>T</code>. + * + * Usually, the return type and the argument types are the same type. + * + * @author jrahm + * + * @param <T> the return type of this function + * @param <E> the argument type of the function + */ +public interface ArrayFunction< T, E > { + + /** + * Executes this function using the arguments <code>args</code> + * and returns an object of type <code>T</code> + * + * @param args the arguments to execute this function with. + * @return some value of type <code>T</code> + */ + public T execute( E[] args ); +} diff --git a/project/JavaCommon/src/com/modulus/common/TwoTypeBean.java b/project/JavaCommon/src/com/modulus/common/TwoTypeBean.java new file mode 100644 index 0000000..28e1e41 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/TwoTypeBean.java @@ -0,0 +1,44 @@ +package com.modulus.common; + +/** + * Class that simply holds two different (or same) object + * types. It is a rough implementation of what a tuple can be + * considered + * + * @author jrahm + * + * @param <T> type of object 1 + * @param <E> type of object 2 + */ +public class TwoTypeBean<T, E> { + private T obj1; + private E obj2; + + /** + * Creates a new TwoTypeBean from the two + * objects. + * + * @param obj1 object 1 + * @param obj2 object 2 + */ + public TwoTypeBean(T obj1, E obj2){ + this.obj1 = obj1; + this.obj2 = obj2; + } + + /** + * Returns the first object + * @return the first object + */ + public T getObject1(){ + return obj1; + } + + /** + * Returns the second object + * @return the second object + */ + public E getObject2(){ + return obj2; + } +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/ArrayStack.java b/project/JavaCommon/src/com/modulus/common/collections/ArrayStack.java new file mode 100644 index 0000000..17dfcb1 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/ArrayStack.java @@ -0,0 +1,101 @@ +package com.modulus.common.collections; + +import java.io.Serializable; + +/** + * Class which uses an array to be used to + * implement a stack. + * + * This class is most efficient for + * nearly every purpose. + * + * @author jrahm + * + * @param <T> the type this stack holds + */ +public class ArrayStack<T> implements Stack<T>, Serializable{ + + private Object[] arr; + private int pointer = -1; + + /** + * Creates a new ArrayStack with a + * default starting size of 10 + */ + public ArrayStack(){ + this(10); + } + + /** + * Creates a new ArrayStack with + * a default starting size of <code>size</code> + * @param size + */ + public ArrayStack( int size ){ + arr = new Object[size]; + } + + /** + * Ensures that this ArrayStack has enough space + * to store <code>size</code> number of elements. + * + * @param size the number of elements needed to store + */ + public void ensureSize( int size ){ + + if(arr.length > size) + return; + + Object[] tmp = new Object[size*2]; + for ( int i = 0;i < arr.length; i ++ ){ + tmp[i] = arr[i]; + } + + arr = tmp; + } + + @Override + public boolean isEmpty() { + return pointer == -1; + } + + @SuppressWarnings("unchecked") + @Override + public T peek() { + return (T)arr[pointer]; + } + + @SuppressWarnings("unchecked") + @Override + public T pop() { + return (T) arr[ pointer -- ]; + } + + @Override + public void push(T obj) { + pointer ++; + this.ensureSize(pointer); + arr[pointer] = obj; + } + + @Override + public int size() { + return pointer + 1; + } + + @Override + public void clear(){ + pointer = 0; + } + + @Override + public String toString(){ + StringBuffer buf = new StringBuffer("["); + + for( int i = pointer; i >= 1; i --) + buf.append(arr[i] + ", "); + + buf.append(arr[0] + "]"); + return buf.toString(); + } +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/BaseModelData.java b/project/JavaCommon/src/com/modulus/common/collections/BaseModelData.java new file mode 100644 index 0000000..250f980 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/BaseModelData.java @@ -0,0 +1,29 @@ +package com.modulus.common.collections; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class BaseModelData<T> implements ModelData<T>{ + private Map<Object, T> map = new HashMap<Object, T>(); + + @Override + public T get(Object key) { + return map.get(key); + } + + @Override + public Object[] keys() { + Set<Object> keys = map.keySet(); + + return keys.toArray( new Object[keys.size()] ); + } + + @Override + public void set(Object key, Object obj) { + // TODO Auto-generated method stub + + } + + +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/Collections2.java b/project/JavaCommon/src/com/modulus/common/collections/Collections2.java new file mode 100644 index 0000000..65bcc60 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/Collections2.java @@ -0,0 +1,28 @@ +package com.modulus.common.collections; + +public class Collections2 { + + static public Integer[] rangeAsObjects(int start, int stop) + { + Integer[] result = new Integer[stop-start]; + + for(int i=0;i<stop-start;i++) + result[i] = start+i; + + return result; + } + + static public int[] range(int start, int stop) + { + int[] result = new int[stop-start]; + + for(int i=0;i<stop-start;i++) + result[i] = start+i; + + return result; + } + + static public int[] range(int stop){ + return range(0, stop); + } +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/Grid.java b/project/JavaCommon/src/com/modulus/common/collections/Grid.java new file mode 100644 index 0000000..817a36c --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/Grid.java @@ -0,0 +1,35 @@ +package com.modulus.common.collections; + +/** + * Interface describing an immutable grid interface. + * + * @author jrahm + * + * @param <T> the type of object this grid holds + */ +public interface Grid<T> { + /** + * Returns the object stored in + * row <code>row</code> and column + * <code>col</code> + * + * @param row the row of the object + * @param col the column of the object + * @return the object stored in that row and column + */ + public T get(int row, int col); + + /** + * Returns the number of columns in this grid + * + * @return the number of columns in this grid + */ + public int numberOfColumns(); + + /** + * Returns the number of columns in this grid. + * + * @return the number of columns in this grid + */ + public int numberOfRows(); +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/IntMap.java b/project/JavaCommon/src/com/modulus/common/collections/IntMap.java new file mode 100644 index 0000000..558cd9f --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/IntMap.java @@ -0,0 +1,84 @@ +package com.modulus.common.collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class IntMap<T> implements Map<Integer, T> { + private List<T> list = new ArrayList<T>(); + + @Override + public void clear() { + this.list.clear(); + } + + @Override + public boolean containsKey(Object arg0) { + if( arg0 instanceof Integer) + return ((Integer) arg0) < this.list.size(); + + return false; + } + + @Override + public boolean containsValue(Object arg0) { + return list.contains(arg0); + } + + @Override + public Set<java.util.Map.Entry<Integer, T>> entrySet() { + throw new RuntimeException("Not Implemented (At The Moment)"); + } + + @Override + public T get(Object arg0) { + try{ + return list.get( (Integer)arg0 ); + } catch(ClassCastException e){ + return null; + } + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public Set<Integer> keySet() { + return new HashSet<Integer>( Arrays.asList( Collections2.rangeAsObjects(0, list.size()) ) ); + } + + @Override + public T put(Integer arg0, T arg1) { + return list.set(arg0, arg1); + } + + @Override + public void putAll(Map<? extends Integer, ? extends T> arg0) { + throw new RuntimeException("Not Implemented At the Moment"); + } + + @Override + public T remove(Object arg0) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int size() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Collection<T> values() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/MArrays.java b/project/JavaCommon/src/com/modulus/common/collections/MArrays.java new file mode 100644 index 0000000..08d9540 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/MArrays.java @@ -0,0 +1,180 @@ +package com.modulus.common.collections; + +import java.lang.reflect.Array; +import java.util.AbstractList; +import java.util.List; + +public class MArrays { + public static int indexOf( Object[] objs , Object obj, int start ){ + for ( int i = start; i < objs.length; i ++) + if(objs[i].equals(obj)) + return i; + return -1; + } + + public static int lastIndexOf( Object[] objs , Object obj, int end ){ + for ( int i = end; i >= 0; i --) + if(objs[i].equals(obj)) + return i; + return -1; + } + + public static int indexOf( Object[] objs, Object obj ){ + return indexOf( objs, obj, 0 ); + } + + public static int lastIndexOf( Object[] objs, Object obj ){ + return lastIndexOf( objs, obj, objs.length - 1 ); + } + + public static String concat(String[] args, int off, int len, String sep){ + StringBuffer buf = new StringBuffer(); + int lastDex = len + off; + + for(int i = off;i < lastDex-1;i++) + buf.append(args[i] + sep); + buf.append(args[lastDex-1]); + + return buf.toString(); + } + + public static String concat(String[] args, int off, String sep){ + return concat(args, off, args.length-off, sep); + } + + public static String concat(String[] args, String sep){ + return concat(args, 0, args.length, sep); + } + + public static String concat(String[] args, int off){ + return concat(args, off, ""); + } + + public static String concat(String[] args){ + return concat(args, ""); + } + + public static String concat(String[] args, int off, int len){ + return concat(args, off, len, ""); + } + + public static List<Byte> asList( final byte[] bytes ){ + return new AbstractList<Byte>() { + + @Override + public Byte get(int arg0) { + return bytes[arg0]; + } + + @Override + public int size() { + return bytes.length; + } + }; + } + + public static List<Character> asList( final char[] chars ){ + return new AbstractList<Character>() { + + @Override + public Character get(int arg0) { + return chars[arg0]; + } + + @Override + public int size() { + return chars.length; + } + }; + } + + public static List<Integer> asList( final int[] ints ){ + return new AbstractList<Integer>() { + + @Override + public Integer get(int arg0) { + return ints[arg0]; + } + + @Override + public int size() { + return ints.length; + } + }; + } + + public static List<Long> asList( final long[] longs ){ + return new AbstractList<Long>() { + + @Override + public Long get(int arg0) { + return longs[arg0]; + } + + @Override + public int size() { + return longs.length; + } + }; + } + + public static List<Double> asList( final double[] doubles ){ + return new AbstractList<Double>() { + + @Override + public Double get(int arg0) { + return doubles[arg0]; + } + + @Override + public int size() { + return doubles.length; + } + }; + } + + public static List<Float> asList( final float[] floats ){ + return new AbstractList<Float>() { + + @Override + public Float get(int arg0) { + return floats[arg0]; + } + + @Override + public int size() { + return floats.length; + } + }; + } + + public static List<Short> asList( final short[] shorts ){ + return new AbstractList<Short>() { + + @Override + public Short get(int arg0) { + return shorts[arg0]; + } + + @Override + public int size() { + return shorts.length; + } + }; + } + + public static List<Boolean> asList( final boolean[] bools ){ + return new AbstractList<Boolean>() { + + @Override + public Boolean get(int arg0) { + return bools[arg0]; + } + + @Override + public int size() { + return bools.length; + } + }; + } +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/ModelData.java b/project/JavaCommon/src/com/modulus/common/collections/ModelData.java new file mode 100644 index 0000000..245015b --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/ModelData.java @@ -0,0 +1,9 @@ +package com.modulus.common.collections; + +public interface ModelData<T> { + public T get(Object key); + + public void set(Object key, T obj); + + public Object[] keys(); +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/Stack.java b/project/JavaCommon/src/com/modulus/common/collections/Stack.java new file mode 100644 index 0000000..1d2c36c --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/Stack.java @@ -0,0 +1,57 @@ +package com.modulus.common.collections; + +/** + * Class defines a better used stack than what is + * in the java api. This stack is an interface + * with many different implementations. + * + * @author jrahm + * + * @param <T> the type this stack stores + */ +public interface Stack<T> { + /** + * Removes and returns the element that is on + * the top of the stack. + * + * @return the element which is on the top of the stack. + */ + public T pop(); + + /** + * Places object <code>obj</code> on the top of + * the stack + * + * @param obj the object to push on the stack. + */ + public void push(T obj); + + /** + * Returns the object on the top of the stack + * but does <b>not</b> remove it. + * + * @return the object on the top of the stack + */ + public T peek(); + + /** + * Returns the number of elements in this + * stack. + * + * @return the number of elements in this stack. + */ + public int size(); + + /** + * Returns true of this stack has no elements, + * returns false otherwise. + * + * @return true it this stack has no elements, false otherwise + */ + public boolean isEmpty(); + + /** + * Empties the stack. + */ + public void clear(); +} diff --git a/project/JavaCommon/src/com/modulus/common/collections/UpdateableGrid.java b/project/JavaCommon/src/com/modulus/common/collections/UpdateableGrid.java new file mode 100644 index 0000000..a48ee31 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/collections/UpdateableGrid.java @@ -0,0 +1,21 @@ +package com.modulus.common.collections; + +/** + * Interface that extends grid to make a grid + * mutable. + * + * @author jrahm + * + * @param <T> the type this grid holds + */ +public interface UpdateableGrid<T> extends Grid<T>{ + /** + * sets the reference in row <code>row</code> and column <code>col</code> + * to <code>obj</code> + * + * @param row the row + * @param col the column + * @param obj the object + */ + public void set(int row, int col, T obj); +} diff --git a/project/JavaCommon/src/com/modulus/common/strings/Tokenizer.java b/project/JavaCommon/src/com/modulus/common/strings/Tokenizer.java new file mode 100644 index 0000000..80363cd --- /dev/null +++ b/project/JavaCommon/src/com/modulus/common/strings/Tokenizer.java @@ -0,0 +1,48 @@ +package com.modulus.common.strings; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Class that tokenizes strings based on which groups + * the characters fit into. + * + * If the group is -1, then that tells the tokenizer to + * not include those tokens and instead delete the characters + * that belong to that group in the process of splitting. + * + * @author jrahm + * + */ +public abstract class Tokenizer { + + public String[] tokenize(String str){ + if(str.length() == 0) + return new String[]{}; + + List<String> tokens = new ArrayList<String>(); + StringBuffer buffer = new StringBuffer(); + + int curGroup = groupOf(str.charAt(0)); + for(int i = 0;i < str.length();i++){ + char ch = str.charAt(i); + + int temp = groupOf(ch); + if(temp != curGroup && curGroup != -1){ + curGroup = temp; + tokens.add(buffer.toString()); + + buffer = new StringBuffer(); + } + + if(temp != -1) + buffer.append(ch); + } + tokens.add(buffer.toString()); + + return tokens.toArray(new String[tokens.size()]); + } + + public abstract int groupOf(char ch); +} diff --git a/project/JavaCommon/src/com/modulus/console/InputReader.java b/project/JavaCommon/src/com/modulus/console/InputReader.java new file mode 100644 index 0000000..0cda313 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/console/InputReader.java @@ -0,0 +1,9 @@ +package com.modulus.console; + +public class InputReader { + private StringBuffer buffer = new StringBuffer(); + + public String getBuffer(){ + return buffer.toString(); + } +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java new file mode 100644 index 0000000..c2ec699 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java @@ -0,0 +1,125 @@ +package com.modulus.dataread.expressions; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * this class outlines a rough diagram of what a statement + * looks like. The major importance is how it already + * correctly implements the tree fasion that statements + * should in theory be ordered in. + * + * @author jrahm + * + */ +public abstract class AbstractStatement implements Statement, Serializable{ + private static final long serialVersionUID = -6717726729821743941L; + private Collection<Statement> children; + private int line = -1; + + /** + * the header of this statement. + */ + protected String header; + + /** + * Creates a new AbstractStatement with the + * default header being an empty string. + */ + public AbstractStatement(){ + this.children = new ArrayList<Statement>(); + this.header = ""; + } + + @Override + public void addChild(Statement child) { + this.children.add(child); + } + + @Override + public Statement[] getChildren() { + return children.toArray(new Statement[children.size()]); + } + + @Override + public String getHeader() { + return header; + } + + @Override + public void removeChild(Statement child) { + this.children.remove(child); + } + + @Override + public String toString(){ + return toString(0); + } + + public String toString( int recur ){ + StringBuffer buffer = new StringBuffer(); + String tab = ""; + for(int i = 0;i < recur;i++) + tab += '\t'; + + + buffer.append(tab + header); + + if(children.size() > 0){ + buffer.append("{\n"); + for(Statement child : children){ + buffer.append(child.toString( recur + 1 ) + "\n"); + } + buffer.append(tab + "}"); + } else{ + buffer.append(";"); + } + + return buffer.toString(); + } + + @Override + public Statement getChildByHeader(String header){ + + for(Statement child : children){ + String chHeader = child.getHeader(); + + if(chHeader.equals(header)) + return child; + } + + return null; + } + + @Override + public Statement[] getChildrenByHeader(String header){ + List<Statement> ret = new ArrayList<Statement>(); + + for(Statement child : children){ + String chHeader = child.getHeader(); + + if(chHeader.equals(header)) + ret.add(child); + } + + return ret.toArray(new Statement[ret.size()]); + } + + public int getLineNumber(){ + return line; + } + + public void setLineNumber(int line){ + this.line = line; + } + + public boolean hasChildren(){ + return !children.isEmpty(); + } + + public void clearChildren(){ + this.children.clear(); + } +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java new file mode 100644 index 0000000..c62243a --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java @@ -0,0 +1,5 @@ +package com.modulus.dataread.expressions; + +public interface ExpressionParser { + ExpressionPart parseExpressions( String exp ); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java new file mode 100644 index 0000000..bf4e8d8 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java @@ -0,0 +1,136 @@ +package com.modulus.dataread.expressions; + +/** + * This class is used to help to assemble the code into more + * readable code for the computer, it sets the system based on + * a more of a stack-ish way so the virtual machine can linearly + * push/pop arguments and call functions. + * + * @author jrahm + * + */ +public abstract class ExpressionPart { + + // Null if function is global + private ExpressionPart caller; + private ExpressionPart[] args; + + private String function; + private boolean primary = false; + + private ExpressionPart(){} + + /** + * This creates a new Expression part meant to handle multi-part + * expressions such as expressions with parenthesis, functions + * inside of functions and so on. + * + * Q-Bar is set up to be very functional, to the point where every entity is made + * of functions being called on arguments and such. + * + * @param caller the caller of the function (null if the function is global) + * @param function the function to be called + * @param args the arguments of the function + * @return an expression part that describes this layout + */ + public static ExpressionPart makePrimaryExpressionPart( ExpressionPart caller, String function, ExpressionPart[] args ){ + ExpressionPart ths = new ExpressionPart(){ + private String compile; + @Override + public String compilePart() { + + if( compile == null ){ + StringBuffer buf = new StringBuffer(); + ExpressionPart caller = this.getCaller(); + + // else + // buf.append( "$global$" ); + for(ExpressionPart part : this.getArgs()){ + buf.append(' '); + buf.append( part.compilePart() ); + } + + if(caller != null) + buf.append( " " + caller.compilePart() ); + + buf.append(' '); + if(this.getFunction().trim().length() > 0){ + if(caller != null){ + // \u00FF is the marker for what is an instance function + buf.append( "\u00FF" + this.getFunction() ); + } + else{ + // \u00FE is the marker for a global function + buf.append( "\u00FE" + this.getFunction() ); + } + } + compile = buf.toString().replaceAll("\\s+", " "); + } + + return compile; + } + }; + + ths.caller = caller; + ths.function = function; + ths.args = args; + + ths.primary = true; + + return ths; + } + + /** + * This method returns an expression part that is made entirely up + * of one single variable name. On a side note, these parts are the + * recursive base case for the compilation. + * + * The name of the variable is stored in the function value, as a variable + * name can be thought of as a function that returns that point in + * memory. + * + * @param name the name of the variable. + * @return A base case ExpressionPart + */ + public static ExpressionPart makeExpressionPart( String name ){ + ExpressionPart ths = new ExpressionPart(){ + @Override + public String compilePart() { + return this.getFunction(); + } + }; + ths.function = name; + + return ths; + } + + /** + * @return the caller + */ + public ExpressionPart getCaller() { + return caller; + } + + /** + * @return the args + */ + public ExpressionPart[] getArgs() { + return args; + } + + /** + * @return the function + */ + public String getFunction() { + return function; + } + + /** + * @return the primary + */ + public boolean isPrimary() { + return primary; + } + + public abstract String compilePart(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java new file mode 100644 index 0000000..df51f2b --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java @@ -0,0 +1,3 @@ +package com.modulus.dataread.expressions; + +public enum FlowStatement { WHILE, FOR, IF, ELSE, RETURN, NONE } diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java b/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java new file mode 100644 index 0000000..29cb0a1 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java @@ -0,0 +1,25 @@ +package com.modulus.dataread.expressions; + +public class LineNumberException extends RuntimeException{ + private int line; + + public LineNumberException( int line ) { + super(); + this.line = line; + } + + public LineNumberException(String message, int line) { + super(message + " line " + line); + this.line = line; + } + + public LineNumberException(String message, Throwable cause, int line) { + super(message + " line " + line, cause); + this.line = line; + } + + public int getLine(){ + return line; + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java new file mode 100644 index 0000000..a48f3b9 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java @@ -0,0 +1,84 @@ +package com.modulus.dataread.expressions; + +/** + * Interface defines a set of rules used to parse + * text files. These rules include such rules like + * in string or folder start and end etc. + * + * @author jrahm + * + */ +public interface ParseRules { + /** + * First formats the code to make + * life much easier for the parser. + * + * This should be the first method to be + * called at all times. + */ + void format(); + + /** + * Signals these parse rules that the user has read the character at + * the point <code>off</code> of which the parser dictates how much + * code to skip. + * + * @param off point in the code which was read + * @return how many characters the parser should skip. + */ + int read( int off ); + + /** + * Returns true if the parser is in quotes, false otherwise. + * + * @return true if the parser is in quotes, false otherwuse. + */ + boolean inQuotes(); + + /** + * Returns true if the parser is in a + * comment or not. + * + * @return true if the parser is in a + * comment or not. + */ + boolean inComment(); + + /** + * returns true if at position <code>off</code> + * a folder is being opened. + * + * @param off the position in the code + * @return true if at position <code>off</code> a + * folder is being opened. + */ + boolean openFolder( int off ); + + /** + * returns true if at position <code>off</code> + * a folder is being closed in the code. + * + * @param off the position of the parser + * @return if a folder is being closed at position <code>off</code> + */ + boolean closeFolder( int off ); + + /** + * returns true if a statement is terminated at position <code>off</code> + * + * @param off the position in the code. + * @return true if a statement is terminated at position <code>off</code> + */ + boolean statementTerminated( int off ); + + /** + * Returns the code which these parse rules are using. + * @return the code which these parse rules are using. + */ + String getCode(); + + /** + * Returns the line number of this reader + */ + int getLineNumber(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java new file mode 100644 index 0000000..27df480 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java @@ -0,0 +1,105 @@ +package com.modulus.dataread.expressions; + +/** + * This interface is used to store interpreted + * information from a text file in a way that + * most represents a tree. for easy parsing + * for an interpreter or compiler. + * + * @author jrahm + * + */ +public interface Statement { + + /** + * Returns the child statements of this class + * + * @return the child statements of this class + */ + Statement[] getChildren(); + + /** + * Adds a child statement to this Statement + * + * @param child the child statement to add + */ + void addChild(Statement child); + + /** + * Removes a child statement from this Statement object + * + * @param child this child to remove from this statement + */ + void removeChild(Statement child); + + /** + * Sets the header for this statement object + * + * @param header the header for this statement. + */ + void setHeader(String header); + + /** + * returns the header for this statement object + * @return + */ + String getHeader(); + + /** + * side effect method to get nicely formatted printouts + * of the statement class. + * @param recur + * @return + */ + String toString( int recur ); + + /** + * Returns the child of this Statement that has + * the header <code>header</code>. If there is no + * child with that header, then the method should + * then return <code>null</code>. If there are multiple + * children with the same header, then the first one should + * be returned. If all children with that header should be + * returned, then use the <code>getChildrenByHeader</code> method. + * + * @param header the header of the child to return + * @return a child with the header <code>header</code> + */ + Statement getChildByHeader(String header); + + /** + * Returns an array of children of this Statement that have + * the header <code>header</code>. If no children have that header, + * then an empty array is returned. + * + * @param header the header of the children to return. + * @return an array of children that have the header <code>header</code> + */ + Statement[] getChildrenByHeader(String header); + + /** + * Returns the line number that this statement starts on. + * @return the line number that this statement starts on. + */ + int getLineNumber(); + + /** + * Sets the line number that this statement + * starts on. + * + * @param line the line this statement starts on. + */ + void setLineNumber(int line); + + /** + * Returns true if this statement has children, false otherwise. + * + * @return true if this statement has children. + */ + boolean hasChildren(); + + /** + * Deletes all children from this statement + */ + void clearChildren(); +}
\ No newline at end of file diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java new file mode 100644 index 0000000..16da8aa --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java @@ -0,0 +1,28 @@ +package com.modulus.dataread.expressions; + +import java.util.Map; + +/** + * Interface describes how an object is supposed to + * generate statements. This class is to be used int tandem + * with the ExpressionParser interface to generate + * Statements of a specific type; + * + * @author jrahm + * + * @param <T> the type of statement this StatementFactory creates + */ +public interface StatementFactory<T extends Statement> { + + /** + * Creates a new statement with the type <code>T</code> based + * on what the parameters contain. + * + * The parameters contain useful information about where the parser + * currently is and how to create the new statement. + * + * @param params the parameters + * @return a new statement of type <code>T</code> based off of the parameters. + */ + T generateStatement(Map<String, Object> params); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java new file mode 100644 index 0000000..8070034 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java @@ -0,0 +1,26 @@ +package com.modulus.dataread.expressions; + +import java.io.Serializable; + +/** + * Classes that implement this interface are used + * to format string before they become a part of + * a statement. + * + * These classes are the classes responsible for making + * sure the headers are formatted in such a way that they might + * be easy to parse. + * + * @author jrahm + */ +public interface StatementFormatter extends Serializable{ + /** + * Given the String <code>header</code> as a header of a statement, + * format it so it can easily be parsed by custom parsing + * techniques. + * + * @param header the header to parse + * @return a formatted version of the header. + */ + String formatHeader(String header); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java new file mode 100644 index 0000000..854d4d2 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java @@ -0,0 +1,21 @@ +package com.modulus.dataread.expressions; + +/** + * Interface which describes how an expression parser + * will handle information from an interpreter file. + * + * @author jrahm + * + * @param S the statement type which is used to create this class + */ +public interface StatementTreeParser { + + /** + * Parse a block of code into statements using the statement factory <code>factory</code> + * to generate the statements to use. + * @param <T> the type of statement to use. + * @param factory the factory to generate the statements + * @return a Statement of type <code>T</code> that represents the code parsed + */ + <T extends Statement> Statement parseStatements(StatementFactory<T> factory); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java new file mode 100644 index 0000000..ebdb2dc --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java @@ -0,0 +1,197 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.ParseRules; + +/** + * Class which implements ParseRules with rules + * of a language which is very close to the C Programming + * Language and others based off it. + * + * @author jrahm + */ +public abstract class AbstractParseRules implements ParseRules{ + private static final String w = "\\s"; + + private int lineNumber = 0; + /* + * the code this class will follow + */ + private String code; + /* + * value which tells this class + * if it is in quotes or not. + */ + private boolean inQuotes = false; + + /* + * value which dictates if the parser + * is in comments. + */ + private boolean inComments = false; + + /* + * this tells if the parser is in + * a comment delimited by '//' + */ + private boolean inLineComment = false; + /** + * Constructs a new CBasedParseRules object with <code>code</code> + * as the code which is being parsed. + * + * @param code the code to be parsed. + */ + public AbstractParseRules(String code){ + this.code = code; + format(); + + deleteComments(); + } + + @Override + public boolean closeFolder(int off) { + + return code.startsWith(this.getCloseFolderString(), off); + } + + @Override + public boolean inComment() { + return inComments || inLineComment; + } + + @Override + public boolean inQuotes() { + return inQuotes; + } + + @Override + public boolean openFolder(int off) { + return code.startsWith( this.getOpenFolderString(), off ); + } + + /* + * this is where most of the logic + * goes for this class, this method is + * what dictates the flow of the parser + * and whether or not the parser is in + * quotes or comments etc. + * + * @see com.modulus.dataread.expressions.ParseRules#read(int) + */ + @Override + public int read(int off) { + // Here we will handle to see if the parser + // has run into a string literal. + + // System.out.print( code.charAt(off) ); + if(code.charAt(off) == '"'){ + if( off == 0 || code.charAt(off - 1) != '\\' ){ + inQuotes = !inQuotes; + } + } + + return 1; + } + + public boolean statementTerminated( int off ){ + boolean tmp = code.startsWith( this.getStatementTerminatingCharacter(), off ) && !inQuotes(); + + // if(tmp) { + // System.out.printf("%s\t%s\t%s\n", code.substring(off), off, inQuotes ); + // } + + return tmp; + } + + @Override + public void format() { + // for most C-based languages white space can just be + // Truncated like so. + // this.code = this.code.replaceAll(w+"+\n"+w+"+", "\n"); + this.code = this.code.replace('\n', '\u0088'); + // this.code = this.code.replaceAll(w+"+", " "); + // this.code = this.code.replaceAll(w+"*\\}"+w+"*", "}"); + // this.code = this.code.replaceAll(w+"*;"+w+"*", ";"); + StringBuffer total = new StringBuffer(); + + int i = 0; + int old = 0; + + boolean inQuotes = false; + + while( i != this.code.length() ) { + old = i; + i = code.indexOf('"', i+1); + + if( i == -1 ) + i = this.code.length(); + + String sub = code.substring(old, i); + + if(!inQuotes) { + sub = sub.replaceAll(w+"+", " "); + sub = sub.replaceAll(w+"*\\}"+w+"*", "}"); + sub = sub.replaceAll(w+"*;"+w+"*", ";"); + } + + total.append(sub); + + inQuotes = !inQuotes; + } + total.append( code.substring(old) ); + + code = total.toString(); + //this.code = this.code.replaceAll("[^;]\\}", ";}"); + + // System.out.println("Format: " + this.code); + } + + public String getCode(){ + return code.replace('\u0088', '\n'); + } + + @Override + public int getLineNumber() { + return lineNumber; + } + + private void deleteComments(){ + StringBuffer code2 = new StringBuffer(); + + for( int i = 0;i < code.length(); i ++){ + if(code.startsWith( this.getCommentOpen(), i )){ + while(!code.startsWith( this.getCommentClose(), i)){ + if(code.charAt(i) == '\u0088') + code2.append(code.charAt(i)); + i ++; + } + i += this.getCommentClose().length(); + } + + if(code.startsWith( this.getLineCommentDelimeter(), i)){ + while(code.charAt(i) != '\u0088'){ + i++; + } + } + + code2.append( code.charAt(i) ); + } + + code = code2.toString(); + } + + public abstract String getOpenFolderString(); + + public abstract String getCloseFolderString(); + + public abstract String getStatementTerminatingCharacter(); + + public abstract String getStringDelimiter(); + + public abstract String getEscapeSequence(); + + public abstract String getCommentOpen(); + + public abstract String getCommentClose(); + + public abstract String getLineCommentDelimeter(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java new file mode 100644 index 0000000..33dad25 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java @@ -0,0 +1,57 @@ +package com.modulus.dataread.expressions.impl; + +public class CBasedParseRules extends AbstractParseRules{ + + public CBasedParseRules(String code) { + super(code); + } + + @Override + public String getOpenFolderString() { + // TODO Auto-generated method stub + return "{"; + } + + @Override + public String getCloseFolderString() { + // TODO Auto-generated method stub + return "}"; + } + + @Override + public String getStatementTerminatingCharacter() { + // TODO Auto-generated method stub + return ";"; + } + + @Override + public String getStringDelimiter() { + // TODO Auto-generated method stub + return "\""; + } + + @Override + public String getEscapeSequence() { + // TODO Auto-generated method stub + return "\\"; + } + + @Override + public String getCommentOpen() { + // TODO Auto-generated method stub + return "/*"; + } + + @Override + public String getCommentClose() { + // TODO Auto-generated method stub + return "*/"; + } + + @Override + public String getLineCommentDelimeter() { + // TODO Auto-generated method stub + return "//"; + } + +}
\ No newline at end of file diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java new file mode 100644 index 0000000..8a4b3ad --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java @@ -0,0 +1,52 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.AbstractStatement; +import com.modulus.dataread.expressions.StatementFormatter; + +/** + * This class that extends AbstractStatement will first + * format its header before it sets the actual header to + * what the user sends, using a statement formatter. + * + * @author jrahm + * + */ +public class FormatStatement extends AbstractStatement{ + private static final long serialVersionUID = -4973798175965745298L; + private StatementFormatter formatter; + + /** + * This creates a new Statement with <code>formatter</code> + * as the default formatter for this Statement. + * + * @param formatter the formatter for this statement + */ + public FormatStatement(StatementFormatter formatter){ + this.formatter = formatter; + } + + protected FormatStatement(){ + } + + @Override + public void setHeader(String header) { + this.header = formatter.formatHeader(header); + } + + /** + * Returns the formatter for this Statement + * @return the formatter for this Statement + */ + public StatementFormatter getFormatter(){ + return formatter; + } + + /** + * Sets the formatter for this statement + * @param formatter the formatter for this statement + */ + public void setFormatter(StatementFormatter formatter){ + this.formatter = formatter; + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java new file mode 100644 index 0000000..22f1be5 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java @@ -0,0 +1,139 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.common.TwoTypeBean; +import com.modulus.dataread.expressions.StatementTreeParser; +import com.modulus.dataread.expressions.ParseRules; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; + +/** + * This simple expression parser is meant not to do anything fancy + * all it does is break up the file into a tree based on the folders + * in the file. + * + * @author jrahm + * + */ +public class SimpleExpressionParser implements StatementTreeParser{ + /* + * used by methods to keep track of + * the number of lines + */ + private int line = 0; + /* + * The rules to parse by + */ + private ParseRules rules; + + /** + * Creates a new <code>SimpleExpressionParser</code> based + * off of the rules that was given to it. + * + * @param rules the rules to parse by + */ + public SimpleExpressionParser(ParseRules rules){ + this.rules = rules; + } + + @Override + public <T extends Statement> Statement parseStatements(StatementFactory<T> factory) { + // set the line counter to 1 + this.line = 1; + return recurParseStatement(factory, 0).getObject1(); + } + + /* + * Setup a recursive parser to + * return a tree of statements + */ + private <T extends Statement> TwoTypeBean<T, Integer> recurParseStatement(StatementFactory<T> factory, int off){ + // System.out.println(" parseStatements"); + final String code = rules.getCode(); + + // statement which will be returned in the end, + // this statement is the parent of all the other + // statements + T ret = factory.generateStatement(null); + int i = off; + + + // start an iteration through the + // string + for( ;i < code.length(); i ++ ){ + + // if the next character is a new line character, + // the increment the line counter + if(code.charAt(i) == '\n') + line ++; + + // check to see if the rules say that here a statement + // is to be terminated + if( rules.statementTerminated(i) ){ + + // if so, then it is time to manifest a new statement + // header is equal to the substring of the code from + // off to i + String header = code.substring(off, i); + + // create a new child from the type provided + T child = factory.generateStatement(null); + + // set the line number to what it should be + child.setLineNumber( this.line ); + + // set the header + child.setHeader( header ); + + // we are done with creating this beam, so it is time to + // return it + return new TwoTypeBean<T, Integer>(child, i); + } + + // if the rules say that at this point, + // a folder is opened, then it is time to + // use recursion to implement a tree. + else if ( rules.openFolder(i) ){ + + // the header is from off to when the + // folder is being closed + String header = code.substring(off, i); + + // set the header + ret.setHeader(header); + + // set the line number + ret.setLineNumber(line); + + // it is time to increment i by the + // amount the rules say to. + i += rules.read(i); + + // while the folder is not closed + while( !rules.closeFolder(i) ){ + + // read the next statement + TwoTypeBean<T, Integer> bean = recurParseStatement(factory, i); + + // the second object is the offset + //that the previous call terminated with + i = bean.getObject2(); + + // add this child to the main bean + ret.addChild(bean.getObject1()); + + // increment the incrementer by how + // much the rules say to + i += rules.read(i); + } + + // When finished reading this file, it is time + // to return the main bean. + return new TwoTypeBean<T, Integer>(ret, i); + } + } + + // System.out.println(" /parseStatements"); + return new TwoTypeBean<T, Integer>(ret, i); + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java new file mode 100644 index 0000000..f32cfca --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java @@ -0,0 +1,19 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.AbstractStatement; + +public class SimpleStatement extends AbstractStatement { + private static final long serialVersionUID = -8730515046885236907L; + + public SimpleStatement(){} + + public SimpleStatement(String string) { + super(); + this.setHeader(string); + } + + @Override + public void setHeader(String header) { + this.header = header; + } +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java new file mode 100644 index 0000000..70ebd95 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java @@ -0,0 +1,162 @@ +package com.modulus.dataread.expressions.impl; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; + +import com.modulus.common.TwoTypeBean; +import com.modulus.dataread.expressions.LineNumberException; +import com.modulus.dataread.expressions.StatementFormatter; +import com.modulus.dataread.expressions.StatementTreeParser; +import com.modulus.dataread.expressions.ParseRules; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; + +/** + * This simple expression parser is meant not to do anything fancy + * all it does is break up the file into a tree based on the folders + * in the file. + * + * @author jrahm + * + */ +public class SimpleStatementTreeParser implements StatementTreeParser{ + + /* + * used by methods to keep track of + * the number of lines + */ + private int line = 0; + /* + * The rules to parse by + */ + private ParseRules rules; + + /** + * Creates a new <code>SimpleExpressionParser</code> based + * off of the rules that was given to it. + * + * @param rules the rules to parse by + */ + public SimpleStatementTreeParser(ParseRules rules){ + this.rules = rules; + } + + @Override + public <T extends Statement> Statement parseStatements(StatementFactory<T> factory) { + // set the line counter to 1 + this.line = 0; + return recurParseStatement(factory, 0).getObject1(); + } + + /* + * Setup a recursive parser to + * return a tree of statements + */ + private <T extends Statement> TwoTypeBean<T, Integer> recurParseStatement(StatementFactory<T> factory, int off){ + try{ + // System.out.println(" parseStatements"); + final String code = rules.getCode(); + + // statement which will be returned in the end, + // this statement is the parent of all the other + // statements + T ret = factory.generateStatement(null); + int i = off; + int n = 0; + + // start an iteration through the + // string + for( ;i < code.length(); n++, i += rules.read(i) ){ + // if the next character is a new line character, + // the increment the line counter + // System.out.println( i ); + if(code.charAt(i) == '\n'){ + line ++; + // that is all a new line does; + continue; + } + + // check to see if the rules say that here a statement + // is to be terminated + if( rules.statementTerminated(i) ){ + + // if so, then it is time to manifest a new statement + // header is equal to the substring of the code from + // off to i + String header = code.substring(off, i); + + // create a new child from the type provided + T child = factory.generateStatement(null); + + // set the header + child.setHeader( header ); + + // set the line number to what it should be + child.setLineNumber( this.line ); + + // we are done with creating this beam, so it is time to + // return it + return new TwoTypeBean<T, Integer>(child, i); + } + + // if the rules say that at this point, + // a folder is opened, then it is time to + // use recursion to implement a tree. + else if ( rules.openFolder(i) ){ + + // the header is from off to when the + // folder is being closed + String header = code.substring(off, i); + + // set the header + ret.setHeader(header); + + // set the line number + ret.setLineNumber(line); + + // it is time to increment i by the + // amount the rules say to. + i += rules.read(i); + + // while the folder is not closed + while( !rules.closeFolder(i) ){ + + // read the next statement + TwoTypeBean<T, Integer> bean = recurParseStatement(factory, i); + + // the second object is the offset + //that the previous call terminated with + i = bean.getObject2(); + + // add this child to the main bean + ret.addChild(bean.getObject1()); + + // increment the incrementer by how + // much the rules say to + i += rules.read(i); + + while(code.charAt(i) == '\n'){ + line ++; + i++; + } + } + + // When finished reading this file, it is time + // to return the main bean. + return new TwoTypeBean<T, Integer>(ret, i); + } + + } + + // System.out.println(" /parseStatements"); + return new TwoTypeBean<T, Integer>(ret, i); + } catch( Exception e ){ + throw new LineNumberException("Sytax error", e, line); + } + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java new file mode 100644 index 0000000..7a91585 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java @@ -0,0 +1,5 @@ +package com.modulus.dataread.expressions.impl; + +public class StatementParser { + +} diff --git a/project/QBarInterpreter/.classpath b/project/QBarInterpreter/.classpath new file mode 100644 index 0000000..039e0d8 --- /dev/null +++ b/project/QBarInterpreter/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry combineaccessrules="false" kind="src" path="/JavaCommon"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/project/QBarInterpreter/.project b/project/QBarInterpreter/.project new file mode 100644 index 0000000..cc15c0c --- /dev/null +++ b/project/QBarInterpreter/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>QBarInterpreter</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/project/QBarInterpreter/TestQBFile.qbar b/project/QBarInterpreter/TestQBFile.qbar new file mode 100644 index 0000000..9c258bc --- /dev/null +++ b/project/QBarInterpreter/TestQBFile.qbar @@ -0,0 +1,7 @@ +Import qbar/io/IO; +Import qbar/lang/System; + +let main = do { + test <- "Hello; World"; + System.printStrLn( test ); +}
\ No newline at end of file diff --git a/project/QBarInterpreter/TestQBFile.qbc b/project/QBarInterpreter/TestQBFile.qbc Binary files differnew file mode 100644 index 0000000..9d9d8d3 --- /dev/null +++ b/project/QBarInterpreter/TestQBFile.qbc diff --git a/project/QBarInterpreter/TestQBFile2.qbar b/project/QBarInterpreter/TestQBFile2.qbar new file mode 100644 index 0000000..bbf58ee --- /dev/null +++ b/project/QBarInterpreter/TestQBFile2.qbar @@ -0,0 +1,60 @@ +Incorporate Native com.modulus.qbar.lang.QBSystem; +Import Native java.lang.Math as JavaMath; +-{ + This part of this file is just used to + test some of the common mathematical series. +}- + +Namespace Test { + let construct = do { + this.x <- 5; + } +} + +Namespace Series { + Struct Temp { + let new Temp() = do { + this.tmp <- Series.new Temp2(); + } + + let new Temp2() = do { + this.i <- 5; + } + } + + let construct = do { + + this.factorial <- [ n | if n <= 1 then 1 else n * this # (n - 1) ]; + + this.fibonacci <- [ n | if n < 2 then n else this # (n - 1) + this # ( n - 2 ) ]; + + this.collatz <- [ n | if n <= 1 then 0 + else if n % 2 == 0 then 1 + this # (n div 2) + else 1 + this # (n * 3 + 1) ]; + + this.pascalsTriangle <- [ n | if n <= 0 then [ 1 ] + else if n == 1 then [ 1, 1 ] + else Series.pascalFromList( this # (n-1) ) ]; + } + + let pascal( n ) = this.pascalsTriangle # n; + + let pascalFromList( last ) = do { + tmp <- [ 1 ]; + + for [ 0 .. last.length - 2 ] -> n { + tmp +< last # n + last # (n + 1); + } + + tmp +< 1; + return tmp; + } + + let test = Test.x; +} +Incorporate Series; + +let main = do { + -- printStrLn( "This is the JavaMath.cos(15) call: " ++ JavaMath.cos(15) ); + printStrLn( "Test: " ++ test() ); +}
\ No newline at end of file diff --git a/project/QBarInterpreter/build.xml b/project/QBarInterpreter/build.xml new file mode 100644 index 0000000..f86b527 --- /dev/null +++ b/project/QBarInterpreter/build.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- ====================================================================== + Apr 5, 2011 10:02:29 PM + + QBarInterpreter + description + + jrahm + ====================================================================== --> +<project name="QBarInterpreter" default="build"> + <import file="../JavaCommon/common_build.xml"/> + + <property name="prj.src.dir" value="src" /> + <property name="prj.bin.dir" value="bin" /> + + <path id="project.class.path"> + <fileset dir="${lib.dir}" includes="**/*.jar" /> + </path> + + <description> + description + </description> + + <!-- ================================= + target: build + ================================= --> + + <!-- - - - - - - - - - - - - - - - - - + target: lib + - - - - - - - - - - - - - - - - - --> + <target name="lib"> + <mkdir dir="${lib.dir}"/> + <copy todir="${lib.dir}" > + <fileset dir="lib" includes="**/*.jar" /> + </copy> + </target> + + <target name="compile" depends="lib"> + <mkdir dir="${prj.bin.dir}" /> + <javac srcdir="${prj.src.dir}" destdir="${prj.bin.dir}" includes="**" encoding="utf-8" > + <classpath refid="project.class.path" /> + </javac> + </target> + + <target name="package" depends="compile"> + <mkdir dir="${lib.dir}"/> + <copy todir="${lib.dir}"> + <fileset file="qbar" /> + </copy> + <manifestclasspath property="lib.list" jarfile="${lib.dir}/CommonJava.jar"> + <classpath refid="project.class.path"/> + </manifestclasspath> + + + <jar basedir="${prj.bin.dir}" destfile="${lib.dir}/${ant.project.name}.jar" > + <manifest> + <attribute name="Main-Class" + value="com.modulus.qbar.core.interpreter.Main"/> + <attribute name="Class-Path" value="${lib.list}" /> + </manifest> + </jar> + </target> + + <target name="doc"> + <mkdir dir="${doc.dir}" /> + <javadoc sourcepath="${prj.src.dir}" destdir="${doc.dir}" /> + </target> + + <target name="build" depends="package,clean" /> + <target name="clean" > + <delete dir="bin"> + </delete> + </target> +</project> diff --git a/project/QBarInterpreter/completions.txt b/project/QBarInterpreter/completions.txt new file mode 100644 index 0000000..bd56bd2 --- /dev/null +++ b/project/QBarInterpreter/completions.txt @@ -0,0 +1 @@ +if then else Import Static Native Incorporate as let and or xor not while for else do isa where return Struct new this Namespace diff --git a/project/QBarInterpreter/qbar b/project/QBarInterpreter/qbar new file mode 120000 index 0000000..703cd45 --- /dev/null +++ b/project/QBarInterpreter/qbar @@ -0,0 +1 @@ +qbar_lang
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar.sh b/project/QBarInterpreter/qbar.sh new file mode 100755 index 0000000..1b150f7 --- /dev/null +++ b/project/QBarInterpreter/qbar.sh @@ -0,0 +1,36 @@ +#!/bin/sh +interpret=0; + +is_interpreted() { + for i in $@ ; do + if [ "$i" == "-i" ] ; then + interpret=1; + break + fi + done; +} + +is_interpreted; + +if [ $interpret ] ; then + qb_dir=/home/`whoami`/ + if [ ! -e $qb_dir ] ; then + history=""; + else + qb_dir=$qb_dir/.qbar + if [ ! -e $qb_dir ] ; then + mkdir $qb_dir + fi + + qb_hist_file=$qb_dir/qb_history + if [ ! -e $qb_hist_file ] ; then + touch $qb_hist_file + fi + + history="-H $qb_hist_file" + fi + + rlwrap $history -c -f /usr/lib/qbar/aux/completions.txt java -jar /usr/lib/qbar/lib/QBarInterpreter.jar -p /usr/lib/qbar $@ +else + java -jar /usr/lib/qbar/lib/QBarInterpreter.jar -p /usr/lib/qbar $@ +fi diff --git a/project/QBarInterpreter/qbar_lang/io/BufferedReader.qbar b/project/QBarInterpreter/qbar_lang/io/BufferedReader.qbar new file mode 100644 index 0000000..0b5c382 --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/io/BufferedReader.qbar @@ -0,0 +1,62 @@ +Import qbar/io/Reader.qbar;
+Import qbar/lang/Maybe.qbar;
+Import qbar/lang/System.qbar;
+
+Namespace BufferedReader {
+ Incorporate Reader;
+
+ Struct BufferedReader extends Reader {
+ let new BufferedReader( reader ) = do {
+ this.init( reader );
+
+ if reader isa Reader {
+ this.reader <- reader;
+ } else {
+ this.reader <- new Reader( reader );
+ }
+
+ this.buffer <- [];
+ this.bufSize <- 4096;
+ this.bufCur <- 0;
+ this.dbg <- 1;
+
+ System.printStrLn( "START" );
+
+ this.readBuffer();
+ }
+
+ let read = do {
+ if this.bufCur == this.bufSize {
+ this.readBuffer();
+ this.bufCur <- 0;
+ }
+
+ yeild <- this.buffer#this.bufCur;
+ this.bufCur <- this.bufCur + 1;
+
+ return yeild;
+ }
+
+ let readBuffer = do {
+ System.printStrLn( "Reading Buffer " ++ this.dbg );
+ this.buffer <- this.readBytes( this.bufSize );
+ this.dbg <- this.dbg + 1;
+ }
+
+ let readLine = do {
+ str <- "" ++ "";
+
+ i <- 0;
+ while ( i <- this.read() ) != 10 {
+ if i == -1 {
+ return if str.length == 0 then Maybe.new Null()
+ else Maybe.new Maybe( str );
+ }
+
+ str +< i as Character;
+ }
+
+ return Maybe.new Maybe(str);
+ }
+ }
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar_lang/io/File.qbar b/project/QBarInterpreter/qbar_lang/io/File.qbar new file mode 100644 index 0000000..3f848aa --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/io/File.qbar @@ -0,0 +1,10 @@ +-{
+ This namespace has several native methods
+ that are used to help dealing with file operations.
+}-
+Namespace File {
+ -{
+ Incorporates com.modulus.qbar.io.IOTools class
+ }-
+ Incorporate Native com.modulus.qbar.io.IOTools;
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar_lang/io/IO.qbar b/project/QBarInterpreter/qbar_lang/io/IO.qbar new file mode 100644 index 0000000..ad6a3cc --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/io/IO.qbar @@ -0,0 +1,12 @@ +-{
+ This namespace has several native methods
+ that are used to help dealing with file operations.
+}-
+
+@infix << 30;
+Namespace IO {
+ -{
+ Incorporates com.modulus.qbar.io.IOTools class
+ }-
+ Incorporate Native com.modulus.qbar.io.IOTools;
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar_lang/io/Reader.qbar b/project/QBarInterpreter/qbar_lang/io/Reader.qbar new file mode 100644 index 0000000..3522adf --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/io/Reader.qbar @@ -0,0 +1,24 @@ +Namespace Reader {
+ Struct Reader {
+ -- some kind of instream
+ let new Reader( instream ) = this.init( instream );
+
+ let init( instream ) = this.instream <- instream;
+
+ let close = this.instream.close();
+
+ let mark = this.instream.mark();
+
+ let reset = this.instream.reset();
+
+ let read = this.instream.read();
+
+ let readBytes(n) = this.instream.readBytes(n);
+
+ let skip(n) = this.instream.skip();
+
+ let available = this.instream.available();
+
+ let nextChar = this.read() as Character;
+ }
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar_lang/lang/Math.qbar b/project/QBarInterpreter/qbar_lang/lang/Math.qbar new file mode 100644 index 0000000..77416b2 --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/lang/Math.qbar @@ -0,0 +1,131 @@ +Import qbar/lang/System;
+
+-{
+ Math namespace, this holds many
+ useful functions for anytime
+ math computations.
+
+ This namespace includes aliases
+ of all the functions in java.lang.Math
+ and also includes some extra series
+ functions.
+ }-
+Namespace Math {
+
+ -- need to include the native java class
+ Incorporate Native com.modulus.qbar.lang.QBMath;
+
+ -{
+ The constructor of QBMath creates some
+ of the basic series that QBMath uses.
+ }-
+ let construct = do {
+
+
+ -- the `this` is negated all too often
+ -{
+ The series list for pascal's
+ triangle.
+ }-
+ this.pascalSeries <- [ n | if n <= 0 then [1]
+ else if n == 1 then [ 1, 1 ]
+ else QBMath.pascalTriangle( this#(n-1) ) ];
+
+ -{
+ The series list for the fibonacci
+ series
+ }-
+ this.fibonacciSeries <- [ n | if n < 2 then n
+ else this#( n - 1 ) + this#(n - 2) ];
+
+ -{
+ The series list for the
+ factorial series.
+ }-
+ this.factorialSeries <- [ n | if n <= 1 then 1
+ else n * this#(n - 1) ];
+
+ this.dx <- 0.00000000001;
+ }
+
+ -{
+ The pascal function takes
+ a list and uses that list
+ to generate what would be
+ the next list in the pascal
+ series.
+ }-
+ let pascalTriangle( lastList ) = do {
+ ret <- [1];
+
+ for [ 0 .. lastList.length - 2 ] -> n {
+ ret +< lastList#n + lastList#(n+1);
+ }
+
+ ret +< 1;
+ return ret;
+ }
+
+ -{
+ Directly accesses the factorialSeries
+ get function.
+
+ @return the factorial of `n` (`n!`)
+ }-
+ let factorial( n ) = this.factorialSeries # n;
+
+ -{
+ @return the `n`<sup>th</sup> number
+ in the fibonacci series.
+ }-
+ let fibonacci( n ) = this.fibonacciSeries # n;
+
+ -{
+ @return the `n`<sup>th</sup> list in
+ pascal's triangle list.
+ }-
+ let pascal( n ) = this.pascalList # n;
+
+ -{
+ @return a function that is a rough derivative
+ of the original that was passed. This function
+ uses the `dx` defined in the Math namespace.
+
+ The Function will inherently round to three decimal places.
+ }-
+ let derivative( func ) = do {
+ let tmp(x) = roundN( ( func(x + this.dx) + ( 0 - func(x) ) ) / this.dx, 3 );
+
+ return tmp;
+ }
+
+ -{
+ @return a function that is a rough derivative
+ of the original that was passed. This function
+ takes a function, the percision of `dx` and an
+ integer value of how many decimals to round to.
+ }-
+ let derivativedx( func, dx, round ) = do {
+ let tmp(x) = roundN( ( func(x + this.dx) + ( 0 - func(x) ) ) / dx, round );
+
+ return tmp;
+ }
+
+ let integral( func ) = do {
+ lst <- [ n | if this.abs( n ) <= this.dx then func( n ) * this.dx
+ else ( func( n ) +
+
+ ( if n < 0 then this#( n + dx )
+ else this#( n - dx ) ) ) * this.dx ];
+ return lst;
+ }
+
+ -{
+ @return a number that has been rounded
+ to `n` decimal places.
+ }-
+ let roundN( x, n ) = do {
+ pow <- 10.0 ^ n;
+ return Math.round( x * pow ) / pow;
+ }
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/qbar_lang/lang/Maybe.qbar b/project/QBarInterpreter/qbar_lang/lang/Maybe.qbar new file mode 100644 index 0000000..fa97265 --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/lang/Maybe.qbar @@ -0,0 +1,4 @@ +Namespace Maybe {
+ Incorporate Native com.modulus.qbar.lang.QBMaybe;
+}
+
diff --git a/project/QBarInterpreter/qbar_lang/lang/System.qbar b/project/QBarInterpreter/qbar_lang/lang/System.qbar new file mode 100644 index 0000000..d0836e7 --- /dev/null +++ b/project/QBarInterpreter/qbar_lang/lang/System.qbar @@ -0,0 +1,29 @@ +Import qbar/io/IO.qbar;
+
+-{
+ This namespace holds many raw and basic
+ functions that the user may want to use.
+
+ This Namespace is for the most part native.
+ }-
+Namespace System {
+ -- incorporate the native QBSystem class
+ Incorporate Native com.modulus.qbar.lang.QBSystem;
+
+ let construct = do {
+ this.out <- IO.getStdOut();
+ this.in <- IO.getStdIn();
+ this.err <- IO.getStdErr();
+
+ this.bufferedIn <- IO.new BufferedReader( this.in );
+ }
+
+ let printStrLn( str ) =
+ this.out.printStrLn( str );
+
+ let printStr( str ) =
+ this.out.printStr( str );
+
+ let readLine =
+ this.bufferedIn.readLine();
+}
\ No newline at end of file diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/NaturalFunctions.java b/project/QBarInterpreter/src/com/modulus/qbar/core/NaturalFunctions.java new file mode 100644 index 0000000..4a3e040 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/NaturalFunctions.java @@ -0,0 +1,376 @@ +package com.modulus.qbar.core; + +import com.modulus.qbar.core.primitive.QBChar; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class NaturalFunctions { + public static final QBFunction ADD = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -458278389954945664L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( obj1.doubleValue() + obj2.doubleValue() ); + } + }; + + public static final QBFunction SUB = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 8875619169775793806L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( obj1.doubleValue() - obj2.doubleValue() ); + } + }; + + public static final QBFunction MUL = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -5397892833871103232L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( obj1.doubleValue() * obj2.doubleValue() ); + } + }; + + public static final QBFunction DIV = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 6929787162778332248L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( obj1.doubleValue() / obj2.doubleValue() ); + } + }; + + public static final QBFunction DIVI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 6929787162778332248L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( obj1.doubleValue() / obj2.doubleValue() ); + + return new QBInt( obj1.intValue() / obj2.intValue() ); + } + }; + + public static final QBFunction ADDI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -458278389954945664L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( obj1.doubleValue() + obj2.doubleValue() ); + + return new QBInt( obj1.intValue() + obj2.intValue() ); + } + }; + + public static final QBFunction SUBI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 8875619169775793806L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( obj1.doubleValue() - obj2.doubleValue() ); + + return new QBInt( obj1.intValue() - obj2.intValue() ); + } + }; + + public static final QBFunction MULI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -5397892833871103232L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( obj1.doubleValue() * obj2.doubleValue() ); + + return new QBInt( obj1.intValue() * obj2.intValue() ); + } + }; + + public static final QBFunction POWI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 5551940214654416862L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( Math.pow(obj1.doubleValue(), obj2.doubleValue()) ); + + return new QBInt( (int) Math.pow(obj1.intValue(), obj2.intValue()) ); + } + }; + + + public static final QBFunction POW = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 5551940214654416862L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( Math.pow(obj1.doubleValue(), obj2.doubleValue()) ); + } + }; + + public static final QBFunction AND = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -2549738198868255228L; + + @Override + public QBObject execute(QBObject[] args) { + QBInt obj2 = (QBInt) args[0]; + QBInt obj1 = (QBInt) args[1]; + + return new QBInt( obj1.intValue() & obj2.intValue() ); + } + }; + + public static final QBFunction OR = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -4783153883428278962L; + + @Override + public QBObject execute(QBObject[] args) { + QBInt obj2 = (QBInt) args[0]; + QBInt obj1 = (QBInt) args[1]; + + return new QBDouble( obj1.intValue() | obj2.intValue() ); + } + }; + + public static final QBFunction MOD = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -4919278872817004237L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBDouble( obj1.doubleValue() % obj2.doubleValue() ); + } + }; + + public static final QBFunction MODI = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -4919278872817004237L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if(obj2 instanceof QBDouble) + return new QBDouble( obj1.doubleValue() % obj2.doubleValue() ); + + return new QBInt( obj1.intValue() % obj2.intValue() ); + } + }; + + public static final QBFunction XOR = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -1376100825702322135L; + + @Override + public QBObject execute(QBObject[] args) { + QBInt obj2 = (QBInt) args[0]; + QBInt obj1 = (QBInt) args[1]; + + return new QBInt( obj1.intValue() ^ obj2.intValue() ); + } + }; + + public static final QBFunction NOT = new QBFunction(1) { + /** + * + */ + private static final long serialVersionUID = -2508035483288699515L; + + @Override + public QBObject execute(QBObject[] args) { + QBInt obj2 = (QBInt) args[0]; + + return new QBInt( ~obj2.intValue() ); + } + }; + + public static final QBFunction GT = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -3405854489760677489L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) == 1 ? 1 : 0 ); + } + }; + + public static final QBFunction LT = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -3758428556267202922L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) == -1 ? 1 : 0 ); + } + }; + + public static final QBFunction EQ = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -3756644511236409624L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) == 0 ? 1 : 0 ); + } + }; + + public static final QBFunction LTE = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -8301307408804643494L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) <= 0 ? 1 : 0 ); + } + }; + + public static final QBFunction GTE = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -3805394859773545337L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) >= 0 ? 1 : 0 ); + } + }; + + public static final QBFunction NE = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = -5958431913044160689L; + + @Override + public QBObject execute(QBObject[] args) { + QBPrimitive obj2 = (QBPrimitive) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + return new QBInt( obj1.compareTo(obj2) != 0 ? 1 : 0 ); + } + }; + + public static final QBFunction AS = new QBFunction(2){ + + @Override + public QBObject execute(QBObject[] args) { + QBStruct obj2 = (QBStruct) args[0]; + QBPrimitive obj1 = (QBPrimitive) args[1]; + + if( obj2 == QBInt.struct ) + return new QBInt( obj1.intValue() ); + + else if(obj2 == QBDouble.struct ) + return new QBDouble( obj1.doubleValue() ); + + else if(obj2 == QBChar.struct) + return new QBChar( obj1.charValue() ); + + throw new RuntimeException("Exhauseted all options"); + } + }; +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBArray.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBArray.java new file mode 100644 index 0000000..b03154e --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBArray.java @@ -0,0 +1,26 @@ +package com.modulus.qbar.core; + +public class QBArray extends QBObject{ + /** + * + */ + private static final long serialVersionUID = -5554983175051078215L; + private QBObject[] arr; + + public QBArray(int len){ + super( QBStruct.array ); + this.arr = new QBObject[len]; + } + + public void set(int idx, QBObject obj){ + this.arr[idx] = obj; + } + + public QBObject get(int idx){ + return this.arr[idx]; + } + + public int getLength(){ + return arr.length; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBConstructor.java new file mode 100644 index 0000000..e3759d7 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBConstructor.java @@ -0,0 +1,46 @@ +package com.modulus.qbar.core; + +import com.modulus.common.collections.ArrayStack; +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.core.parser.stmt.QBStatement; + +public class QBConstructor extends QBSyntheticFunction{ + + /** + * + */ + private static final long serialVersionUID = 1795350337497901352L; + private QBStruct struct; + private Stack<QBObject> thses = new ArrayStack<QBObject>(); + + public QBConstructor(QBStatement code, QBStruct struct, QBParser parser) { + super(code, parser); + + this.struct = struct; + this.setGlobal(true); + } + + public QBStruct getObjectStruct(){ + return struct; + } + + + @Override + public QBObject execute( QBObject[] arr ){ + QBObject ths = new QBObject(struct); + this.thses.push(ths); + super.execute(arr); + this.thses.pop(); + return ths; + } + + @Override + public QBObject get(String str){ + + if(str.equals("this")) + return thses.peek(); + + return super.get(str); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBFile.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBFile.java new file mode 100644 index 0000000..94b8a63 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBFile.java @@ -0,0 +1,36 @@ +package com.modulus.qbar.core; + +import java.io.File; + +import com.modulus.qbar.core.interpreter.Main; + +public class QBFile { + private static String[] extensions = new String[]{"", ".qbz", ".qbc", ".qbar"}; + public static File getQBFile( String filename ){ + String[] folders = Main.getPath(); + + if( folders == null ) + folders = new String[]{}; + + File file = new File(filename); + + for(String path : folders){ + + for(String str : extensions) { + if(file.exists()) { + Main.debug(QBFile.class, " Found File " + file + " on the classpath!"); + return file; + } + + + file = new File(path, filename + str); + // Main.debug(QBFile.class, " Looking for File " + file.getAbsolutePath() + " on the classpath."); + } + } + + if(!file.exists()) + throw new RuntimeException("The file: " + filename + " cannot be found on the classpath!"); + + return file; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBFunction.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBFunction.java new file mode 100644 index 0000000..398e21a --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBFunction.java @@ -0,0 +1,131 @@ +package com.modulus.qbar.core; + +import com.modulus.access.ArrayFunction; +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.parser.ByteOperation; + +public abstract class QBFunction extends QBObject implements ArrayFunction< QBObject, QBObject >{ + /** + * + */ + private static final long serialVersionUID = -7422585311092161908L; + + private boolean global; + + public static final QBStruct functionStruct = new QBStruct("function"){ + /** + * + */ + private static final long serialVersionUID = -2742542386017721944L; + + @Override + public QBObject newInstance() { + return this; + } + }; + + protected QBObject returnedValue; + + private int argc; + + public QBFunction( int argc ) { + super(functionStruct); + this.argc = argc; + } + + public int getArgc(){ + return argc; + } + + public String getName(){ + return this.toString(); + } + + @Override + public abstract QBObject execute(QBObject[] args); + + protected void setGlobal( boolean global ){ + this.global = global; + } + + protected void setArgc( int argc ){ + this.argc = argc; + } + + public boolean isGlobal(){ + return global; + } + + /** + * Relatively low level function call that pushes the object + * it returned onto the stack. + * @param func the function to call + * @param stack the stack to call it on + */ + public static void callFunction( QBFunction func, Stack<QBObject> stack ){ + int argc = func.getArgc(); + QBObject[] nextArgs = new QBObject[ argc ]; + + for( int i = 0; i < argc; i ++ ){ + //System.out.println(func + " argc: " + argc + " i: " + i ); + nextArgs[ argc - i - 1 ] = stack.pop(); + } + + stack.push( func.execute(nextArgs) ); + } + + /* + * Very, very low level computation, deals with all + * of the individual statements that need to be executed. + */ + public void exec( ByteOperation[] arr, Stack<QBObject> stack){ +// System.out.println(Arrays.toString(arr)); + if(arr == null) + return; + + for( ByteOperation op : arr ){ + switch( op.getOperator() ){ + case CALLG: + //System.out.println(op.getArg().toString()); + callFunction( (QBFunction)this.get(op.getArg().toString()), stack); + break; + case CALL: + QBObject caller = stack.peek(); + + if(caller instanceof QBUtilityNamespace) + stack.pop(); + //System.out.println("CALL " + caller); + callFunction( (QBFunction)caller.get(op.getArg().toString()), stack); + break; + case PUSH: + String[] str = (String[]) op.getArgs(); + + stack.push( this.hardGet(str) ); + break; + case PUSHO: + QBObject obj = (QBObject) op.getArg(); + stack.push(obj); + break; + + case STO: + QBObject pop = stack.peek(); + this.hardSet((String[]) op.getArgs(), pop); + break; + + case ITR: + QBObject popped = stack.peek(); + String name = op.getArg().toString(); + stack.push(popped.iterator(name, this)); + + } + } + + // this method does not return via the stack, but pops the value + // into a holder to help prevent stack memory leaks. + returnedValue = stack.pop(); + } + + public QBObject getReturnedValue(){ + return returnedValue; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBNamespace.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBNamespace.java new file mode 100644 index 0000000..82a66d9 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBNamespace.java @@ -0,0 +1,161 @@ +package com.modulus.qbar.core; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +/** + * Class is the very root of all the interpreter classes. + * a QBNamespace is anything that has the ability to store variables + * including QBObjects and Functions. + * + * @author jrahm + * + */ +public class QBNamespace implements Serializable{ + /** + * + */ + private static final long serialVersionUID = -102581163781603724L; + + private QBNamespace superNamespace; + private String name = super.toString(); + // The map this namespace delegates, + // This map can be of different types + // like a HashTable. + private Map<String, QBObject> map; + + /** + * Creates a new QBNamespace with the map <code>map</code> + * @param map + */ + public QBNamespace( Map<String, QBObject> map ){ + this( map, null ); + } + + public QBNamespace( Map<String, QBObject> map, QBNamespace sup){ + this.map = map; + this.superNamespace = sup; + } + + /** + * Sets the object with the name <code>name</code> + * to the specific <code>QBObject obj</code> + * + * @param name the name of the variable to set + * @param obj the object to set that name equal to. + */ + public void set(String name, QBObject obj){ + this.map.put(name, obj); + } + + /** + * Returns the object that is referenced by the + * string <code>name</code> from this Namespace + * + * @param name the name of the object to retrieve + * @return the object referenced as <code>name</code> + */ + public QBObject get(String name){ + // System.out.println("THIS: " + this); + QBObject obj = this.map.get(name); + + if(obj == null && superNamespace != null) + obj = superNamespace.get(name); + + if(obj == null) + throw new RuntimeException("The variable: " + name + " does not exist in the current namespace. " + this); + + return obj; + } + + /** + * Returns the object that is referenced by the + * string <code>name</code> from this Namespace + * + * This version of the function will not error + * if the object is not found + * + * @param name the name of the object to retrieve + * @return the object referenced as <code>name</code> + */ + public QBObject getNoError(String name){ + QBObject obj = this.map.get(name); + + if(obj == null && superNamespace != null) + obj = superNamespace.getNoError(name); + + return obj; + } + + public QBNamespace getSuper(){ + return this.superNamespace; + } + + public void setSuper( QBNamespace sup ){ + this.superNamespace = sup; + } + + public String toString2(){ + StringBuffer buf = new StringBuffer(); + for( String key : this.map.keySet() ){ + buf.append(key + ":\t"); + buf.append( this.get(key) + "\n"); + } + + return buf.toString(); + } + + public Set<String> getKeySet(){ + return map.keySet(); + } + + public boolean hasKey( String key ){ + return map.containsKey(key); + } + + public QBObject hardGet(String[] args){ + QBNamespace cur = this; + + for(int i = 0;i < args.length - 1;i ++) + cur = cur.get(args[i]); + + return cur.get(args[args.length - 1]); + } + + public void hardSet(String[] args, QBObject obj){ + QBNamespace cur = this; + + for(int i = 0;i < args.length - 1;i ++) + cur = cur.get(args[i]); + + cur.set(args[args.length - 1], obj); + } + + /** + * Incorporates two namespaces and + * makes them clients to one and other, + * so that if something is added to one, + * then it is added to the other. + * + * @param other the other namespace + */ + public void incoporate( QBNamespace other ){ + load( other ); + // make the other one your bitch + other.map = this.map; + } + + /** + * Same as incorporates, except that in this case, + * the two namespaces remain sovereign and do not + * become clients. + * + * @param other the other namespace + */ + public void load( QBNamespace other ){ + for (String key : other.getKeySet() ){ + this.set(key, other.get(key)); + } + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBObject.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBObject.java new file mode 100644 index 0000000..c187c12 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBObject.java @@ -0,0 +1,89 @@ +package com.modulus.qbar.core; + +import java.util.Hashtable; + +import com.modulus.qbar.integration.QBWrappedObject; +import com.modulus.qbar.lang.QBIterator; +import com.modulus.qbar.lang.QBSyntheticIterator; + +public class QBObject extends QBNamespace implements Cloneable{ + /** + * + */ + private static final long serialVersionUID = -3738912814141895851L; + private QBStruct struct; + + + public QBObject( QBStruct struct ){ + super( new Hashtable<String, QBObject>(), struct ); + this.struct = struct; + } + + public QBStruct getStruct(){ + return struct; + } + + protected void setStruct(QBStruct struct){ + this.struct = struct; + } + + public Object getWrapped(){ + // throw new RuntimeException("The type: " + struct.getName() + " is not of native origin."); + return this; + } +// @Override +// public void setSuper(QBNamespace sup){ +// new Exception().printStackTrace(); +// super.setSuper(sup); +// } + + public QBObject clone(){ + try { + return (QBObject) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + + public QBIterator<?> iterator(String varName, QBNamespace sup){ + QBFunction iterator = (QBFunction) this.get("iterator"); + + if(iterator == null) + return null; + + QBIterator<?> ret; + + QBObject obj = iterator.execute(new QBObject[]{this}); + + if(!(obj instanceof QBIterator)) + ret = new QBSyntheticIterator(this, obj); + else + ret = (QBIterator<?>) obj; + + ret.setVariableName(varName); + ret.setVariableNmspce(sup); + + return ret; + } + + public static long totalTime = 0; + public QBObject get(String name){ + long t1 = System.currentTimeMillis(); + try{ + QBObject ret = super.get(name); + long t2 = System.currentTimeMillis(); + totalTime += (t2 -t1); + return ret; + } catch(Exception e){ + throw new RuntimeException("The variable: " + name + " does not exist for object: " + this); + } + + } + + public String toString(){ + String tmp = super.toString(); + + return (struct == null ? "QBObject" : struct.getName()) + tmp.substring(tmp.indexOf("@")); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBReference.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBReference.java new file mode 100644 index 0000000..c8fa0f5 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBReference.java @@ -0,0 +1,19 @@ +package com.modulus.qbar.core; + +public class QBReference extends QBObject { + /** + * + */ + private static final long serialVersionUID = 4662929761631550702L; + private String str; + + public QBReference(String str) { + super(null); + this.str = str; + } + + public String getString(){ + return str; + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBStruct.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBStruct.java new file mode 100644 index 0000000..66935d4 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBStruct.java @@ -0,0 +1,137 @@ +package com.modulus.qbar.core; + +import java.util.ArrayList; +import java.util.List; + +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.integration.QBWrappedObject; + + +public class QBStruct extends QBObject{ + /** + * + */ + private static final long serialVersionUID = 1271467629591493953L; + + private List<QBStruct> superStruct = new ArrayList<QBStruct>(); + + + + public static final QBStruct clazz = new QBStruct(){ + /** + * + */ + private static final long serialVersionUID = 1915609768305262326L; + + @Override + public QBObject newInstance() { + return this; + } + }; + public static final QBStruct array = new QBStruct("Array"){ + /** + * + */ + private static final long serialVersionUID = -6966880297599366521L; + + @Override + public QBObject newInstance() { + return this; + } + }; + + static{ + clazz.name = "Class"; + clazz.pack = "core"; + + clazz.setStruct(clazz); + clazz.setSuper( QBInterpreter.instance().getGlobalNamespace() ); + } + + private String name; + private String pack; + + private QBStruct(){ super(null); init(); }; + + protected QBStruct(boolean nill) { super(clazz); init(); }; + public QBStruct(String name){ + super(clazz); + this.name = name; + + QBInterpreter.instance().getGlobalNamespace().set(name, this); + init(); + } + + public QBStruct(String name, QBStruct sup){ + super(clazz); + this.name = name; + + this.load(sup); + this.superStruct.add(sup); + + QBInterpreter.instance().getGlobalNamespace().set(name, this); + init(); + } + + public String getName(){ + return name; + } + + public String getPackage(){ + return pack; + } + + public void setName(String name){ + this.name = name; + } + + public QBObject newInstance(){ + return null; + } + + public String toString(){ + return name; + } + + public void addSuperStruct( QBStruct sup ){ + this.superStruct.add(sup); + this.load(sup); + } + + private void init(){ + this.set("getType", new QBFunction(1) { + private static final long serialVersionUID = -278677571392736723L; + + @Override + public QBObject execute(QBObject[] args) { + return this; + } + }); + + this.set("isa", new QBFunction(2){ + private static final long serialVersionUID = 3535644877614653590L; + + @Override + public QBObject execute(QBObject[] args) { + QBObject ths = args[1]; + QBStruct struct = (QBStruct) args[0]; + + return QBWrappedObject.wrap( ths.getStruct().instanceOf(struct) ); + } + + }); + + + } + + public boolean instanceOf(QBStruct struct) { + if( this == struct ) + return true; + + for( QBStruct sup : superStruct ) + if( sup.instanceOf(struct) ) + return true; + + return false; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticFunction.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticFunction.java new file mode 100644 index 0000000..fc8b317 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticFunction.java @@ -0,0 +1,338 @@ +package com.modulus.qbar.core; + +import java.util.HashMap; +import java.util.Map; + +import com.modulus.common.collections.ArrayStack; +import com.modulus.common.collections.Stack; +import com.modulus.dataread.expressions.FlowStatement; +import com.modulus.dataread.expressions.Statement; +import com.modulus.qbar.core.exceptions.ParseException; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.ByteOperation; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.core.parser.stmt.QBStatement; +import com.modulus.qbar.core.primitive.QBPrimitive; +import com.modulus.qbar.lang.QBIterator; + +public class QBSyntheticFunction extends QBFunction{ + private Stack<QBNamespace> namespaceCalls = new ArrayStack<QBNamespace>(); + /** + * + */ + private static final long serialVersionUID = 2890479116324397754L; + private QBStatement code; + private String name; + private String[] args; + private Map<String, QBObject> namespaceTemplate = new HashMap<String,QBObject>(); + private QBObject defaultThis; + + private Map<String, QBObject> subs = new HashMap<String, QBObject>(); + + public QBSyntheticFunction( QBStatement code, QBParser parser ){ + super( -1 ); + this.code = code; + + namespaceCalls.push(new QBNamespace(namespaceTemplate)); + parse(parser); + } + + public void parse(QBParser parser){ + String header = code.getHeader(); // should return header, e.g. let someFunction(a,b,c) = do + + if(!header.startsWith("let")){ + throw new ParseException("Invalid Syntax For Function, expected `let`", code); + } + + // this means that code is a one-line function and we need to break it up + if( !code.hasChildren() ){ + String[] arr = header.split("=", 2); + header = arr[0] + " = "; + + QBStatement onlyChild = new QBStatement(QBParser.formatter); + onlyChild.setLineNumber(code.getLineNumber()); + onlyChild.setHeader(arr[1]); + + + code.addChild(onlyChild); + code.setHeader(header); + } + + this.args = chompArgs( header ); + this.name = chompName( header ); + + for( Statement stmt : code.getChildren() ){ + String expression = stmt.getHeader(); + + //System.out.println("EXPPRS: "+expression); + + stmt.setHeader(expression); + + parser.readStatement( stmt, this ); + } + } + + /* + * Return the args of a function + */ + private String[] chompArgs(String header){ + // System.out.println(header); + int idx1 = header.indexOf('('); + int idx2 = header.lastIndexOf(')'); + + if(idx1 == idx2 && idx1 == -1){ + return new String[]{"this"}; + } else if( idx1 == -1 || idx2 == -1){ + throw new ParseException("Syntax Error", code); + } + // should parse header, like the a,b,c part of + // let someFunction(a,b,c) = do + String args = header.substring( idx1 + 1, idx2 ).trim(); + + // split the arguments into string[], trimming all unnecessary whitespace + String[] ret = (args + ",this").split("\\s*,\\s*"); + + + return ret; + } + + /* + * return the name of the function + */ + static private String chompName(String header){ + // given header is to the effect of, `let someFunction(a,b,c) = do` + + // Chop the `let` from the string + header = header.substring(3); + int idx = header.indexOf('('); + if(idx == -1) + idx = header.indexOf('='); + // get the name + return header.substring(0, idx).trim(); + } + + private boolean ifBit; +// private QBObject returnedValue; + + @Override + public QBObject execute(QBObject[] args) { + // System.out.println("Executing: " + this.getName()); + QBNamespace layer = new QBNamespace(new HashMap<String, QBObject>()); + layer.setSuper(this.getSuper()); + + for( String str : subs.keySet() ) { + QBObject clone = subs.get(str).clone(); + layer.set(str, clone); + clone.setSuper(layer); + } + + // System.out.println(layer.toString2()); + //System.out.println("push"); + namespaceCalls.push(layer); + + mapArgs( args ); + Stack<QBObject> stack = QBInterpreter.instance().getStack(); + Statement[] statements = code.getChildren(); + // System.out.println(Arrays.toString(statements)); + execute(statements, stack); + + //System.out.println("pop"); + namespaceCalls.pop(); + return stack.pop(); + } + + /** + * Guts of the exection process, when it operates on this low of of level + */ + public void execute(Statement[] statements, Stack <QBObject> stack){ + QBStatement exe = null; + Map<QBStatement, QBIterator> iterators = new HashMap<QBStatement, QBIterator>(); + Stack<QBStatement> toProcess = new ArrayStack<QBStatement>(); + try{ + // push all of the statements onto the stack + // the pushAll method pushes the statements on backwards + pushAll(statements, toProcess); + + // execute the statements + while(!toProcess.isEmpty()){ + + //if(toProcess.size() == 1 && namespaceCalls.size() == 2) + // System.out.println("Processing: " + toProcess.peek().getHeader() + " :: " + namespaceCalls.size() ); + // get the next statement to execute + exe = toProcess.peek(); // look at the statement + // System.out.println("EXE " + exe + ", " + exe.getFlowStatement()); + // is there some kind of a flow statement attached with this function? + FlowStatement flow = exe.getFlowStatement(); + + if( flow == FlowStatement.FOR){ + QBIterator<?> iter = iterators.get(exe); + + if(iter == null){ + ByteOperation[] ops = exe.getOperations(); + exec(ops, stack); + iter = (QBIterator<?>) returnedValue; + + iterators.put(exe, iter); + } + + if(!iter.hasNext()){ + toProcess.pop(); + iterators.put(exe, null); + } else{ + iter.next(); + pushAll( exe.getChildren(), toProcess ); + } + } + // if and whiles are very similar, the only difference being that one repeats and the other does not + else if(flow == FlowStatement.IF || flow == FlowStatement.WHILE){ + + // if statements do not repeat + if(flow == FlowStatement.IF) + toProcess.pop(); // pop it off to make it not repeat. + + // these are the operations + ByteOperation[] ops = exe.getOperations(); + + // execute the operations + exec(ops, stack); + + // the method exec pops what it returns in returnedValue; + QBObject obj = returnedValue; + + // check to see if the boolean evaluated to true + if( obj instanceof QBPrimitive &&((QBPrimitive) obj).intValue() > 0){ // TODO fix this to use method in Core + pushAll( exe.getChildren(), toProcess ); + ifBit = true; + } + // if not + else{ + // when the while statement is false, it is time to move on + if(flow == FlowStatement.WHILE){ + toProcess.pop(); + } else{ + ifBit = false; + } + } + } else if( flow == FlowStatement.ELSE){ + // just pop it + toProcess.pop(); + + // if the if bit was false + if( !ifBit ){ + + // push all the children + pushAll( exe.getChildren(), toProcess ); + } + } + // if there is a return statement stop right now + else if ( flow == FlowStatement.RETURN ){ + toProcess.pop(); + exec( exe.getOperations(), stack ); + + stack.push( returnedValue ); + return; + } + // if there is no flow, then just pop and execute. + else { + toProcess.pop(); + exec( exe.getOperations(), stack ); + } + } + + // if this is the end, then it is time just to return the value that was executed by the last command, + // this means that if there is no return statement, then the last command becomes the return statement. + stack.push( returnedValue ); + } catch(RuntimeException e){ + e.printStackTrace(); + throw new ParseException(e.getMessage(), e, exe); + } + } + + /* + * This function pushes all of the elements in an array + * onto the stack in reverse order. + */ + private void pushAll( Statement[] arr, Stack<QBStatement> toProcess ){ + for ( int i = arr.length - 1; i >= 0; i --){ + toProcess.push( (QBStatement) arr[i]); + } + } + + + + + + + private void mapArgs(QBObject[] args){ + + for( int i = 0;i < args.length; i ++){ + this.set(this.args[i], args[i]); + } + + if( defaultThis != null ) + this.set("this", defaultThis); + } + + @Override + public int getArgc(){ + return this.args.length; + } + + @Override + public String getName(){ + return name; + } + + public String toString2(){ + return code.toString(); + } + + @Override + public void setGlobal( boolean global ){ + super.setGlobal(global); + + if( global ){ + if(args[args.length - 1].equals("this")){ + String[] next = new String[args.length - 1]; + System.arraycopy(this.args, 0, next, 0, args.length - 1); + args = next; + } else if(!args[args.length - 1].equals("this")){ + String[] next = new String[args.length + 1]; + System.arraycopy(this.args, 0, next, 0, args.length); + next[args.length] = "this"; + args = next; + } + } + + } + + @Override + public void setSuper( QBNamespace space){ + super.setSuper(space); + // System.out.println("Setting Space To " + space); + + if( space instanceof QBObject && !(space instanceof QBUtilityNamespace)){ + setGlobal(false); + } else { + setGlobal(true); + } + + if(space instanceof QBUtilityNamespace){ + this.defaultThis = (QBObject) space; + } + } + + @Override + public QBObject get(String name){ + return namespaceCalls.peek().get(name); + } + + @Override + public void set(String name, QBObject obj){ + namespaceCalls.peek().set(name, obj); + } + + public void addSubObject( String name, QBObject obj ){ + this.subs.put(name, obj); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticStruct.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticStruct.java new file mode 100644 index 0000000..d76a8ae --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticStruct.java @@ -0,0 +1,68 @@ +package com.modulus.qbar.core; + +import java.util.Arrays; +import java.util.Collections; + +import com.modulus.dataread.expressions.Statement; +import com.modulus.qbar.core.exceptions.ParseException; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.lang.QBArrayList; +import com.modulus.qbar.lang.QBList; + +public class QBSyntheticStruct extends QBStruct{ + private static final long serialVersionUID = -1080935988322343396L; + // This maps an instance variable to its default value, if the struct is null + // the instance will be null defaultly + // private Map<String, QBStruct> instanceVars = new HashMap<String, QBStruct>(); + private Statement code; + + public QBSyntheticStruct( Statement code, QBParser parser, QBNamespace sup ) { + super(false); + + this.setSuper(sup); + this.code = code; + if( !code.getHeader().startsWith("Struct") ){ + throw new ParseException("Syntax error while creating struct, expected `Struct`", code); + } + // code header should be in the form of `Struct someStruct = ` + + String[] split = code.getHeader().split("\\s+"); + + if( code.getHeader().contains("extends") ){ + QBList supers = new QBArrayList(); + this.set( "supers", supers ); + + String header = code.getHeader(); + String ext = header.split("\\s+extends\\s+")[1]; + + String[] extending = ext.split("\\s*,\\s*"); + Collections.reverse(Arrays.asList(extending)); + + for(String s : extending){ + QBStruct obj = (QBStruct) get(s); + this.addSuperStruct(obj); + + supers.add(obj); + } + } + + String name = split[1]; + + this.setName(name); + + for(Statement child : code.getChildren()) + parser.readStatement(child, this); + } + + @Override + public QBObject newInstance() { + // TODO Auto-generated method stub + return null; + } + + public String toString(){ + return code.toString(); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticUtilityNamespace.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticUtilityNamespace.java new file mode 100644 index 0000000..8153ae8 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBSyntheticUtilityNamespace.java @@ -0,0 +1,38 @@ +package com.modulus.qbar.core; + +import com.modulus.dataread.expressions.Statement; +import com.modulus.qbar.core.parser.QBParser; + +public class QBSyntheticUtilityNamespace extends QBUtilityNamespace { + private static final long serialVersionUID = 1941492008845020291L; + + private String name; + + public QBSyntheticUtilityNamespace(Statement stat, QBParser parser, QBNamespace superNamespace) { + String header = stat.getHeader(); + this.setSuper(superNamespace); + // chop off `Namespace` + name = header.substring(9).trim(); + + for(Statement child : stat.getChildren()) + parser.readStatement(child, this); + + this.set("this", this); + } + + @Override + public String getName() { + return name; + } + + @Override + public void construct() { + QBObject obj = this.getNoError("construct"); + if( obj instanceof QBFunction ){ + ((QBFunction) obj).execute( new QBObject[]{} ); + } + } + + + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/QBUtilityNamespace.java b/project/QBarInterpreter/src/com/modulus/qbar/core/QBUtilityNamespace.java new file mode 100644 index 0000000..7728327 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/QBUtilityNamespace.java @@ -0,0 +1,22 @@ +package com.modulus.qbar.core; + +public abstract class QBUtilityNamespace extends QBObject{ + private static final long serialVersionUID = -5228021096385368069L; + + public QBUtilityNamespace() { + super( new QBStruct("Namespace") ); + } + + public QBUtilityNamespace( QBStruct struct ){ + super(struct); + } + + public abstract String getName(); + + public abstract void construct(); + + public void setStruct( QBStruct struct ){ + super.setStruct(struct); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/Type.java b/project/QBarInterpreter/src/com/modulus/qbar/core/Type.java new file mode 100644 index 0000000..1e5d224 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/Type.java @@ -0,0 +1,5 @@ +package com.modulus.qbar.core; + +public interface Type { + public Type getSuper(); +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/compile/ByteOps.java b/project/QBarInterpreter/src/com/modulus/qbar/core/compile/ByteOps.java new file mode 100644 index 0000000..88fbf0c --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/compile/ByteOps.java @@ -0,0 +1,21 @@ +package com.modulus.qbar.core.compile; +/** + * The simple byte code operators needed to + * run these simple functions. + * + * @author jrahm + * + */ + +/* + * STOre + * CALL + * PUSH + * PUSH Object + * PUSH Hard Find + * PUSH Reference + * POP + * CALL Global + * IToRator + */ +public enum ByteOps { STO, CALL, PUSH, PUSHO, PUSHHF, PUSHR, POP, CALLG, ITR } diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ExecutionException.java b/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ExecutionException.java new file mode 100644 index 0000000..fd898ac --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ExecutionException.java @@ -0,0 +1,23 @@ +package com.modulus.qbar.core.exceptions; + +public class ExecutionException extends RuntimeException{ + private static final long serialVersionUID = 5108754994935394009L; + + public ExecutionException() { + super(); + } + + public ExecutionException(String message, Throwable cause) { + super(message, cause); + } + + public ExecutionException(String message) { + super(message); + } + + public ExecutionException(Throwable cause) { + super(cause); + } + + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ParseException.java b/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ParseException.java new file mode 100644 index 0000000..58c5c4b --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/exceptions/ParseException.java @@ -0,0 +1,32 @@ +package com.modulus.qbar.core.exceptions; + +import com.modulus.dataread.expressions.Statement; + +public class ParseException extends RuntimeException{ + private static final long serialVersionUID = 5108754994935394009L; + private int line; + public ParseException(Statement stmt) { + super(); + line = stmt.getLineNumber(); + } + + public ParseException(String message, Throwable cause, Statement stmt) { + super(message + " Line: " + stmt.getLineNumber() + "\n" + "Near: " + stmt.getHeader(), cause); + line = stmt.getLineNumber(); + } + + public ParseException(String message, Statement stmt) { + super(message + " Line: " + stmt.getLineNumber()+ "\n" + "Near: " + stmt.getHeader()); + line = stmt.getLineNumber(); + } + + public ParseException(Throwable cause, Statement stmt) { + super(cause); + line = stmt.getLineNumber(); + } + + public int getLineNumber(){ + return line; + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompiledReader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompiledReader.java new file mode 100644 index 0000000..8c7b8a1 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompiledReader.java @@ -0,0 +1,13 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.IOException; +import java.io.InputStream; + +public class CompiledReader implements QBInterpreterReader { + + @Override + public QBInterpreter readFromStream(InputStream in) throws IOException, ClassNotFoundException { + return QBInterpreter.readInterpreter(in); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompressedReader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompressedReader.java new file mode 100644 index 0000000..dffe06c --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/CompressedReader.java @@ -0,0 +1,13 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.IOException; +import java.io.InputStream; + +public class CompressedReader implements QBInterpreterReader { + + @Override + public QBInterpreter readFromStream(InputStream in) throws IOException, ClassNotFoundException { + return QBInterpreter.readInterpreterCompressed(in); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/Main.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/Main.java new file mode 100644 index 0000000..cda942f --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/Main.java @@ -0,0 +1,217 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.modulus.dataread.expressions.Statement; +import com.modulus.qbar.core.QBFile; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.parser.AnnotationReader; +import com.modulus.qbar.core.parser.QBExpressionParser; +import com.modulus.qbar.core.parser.QBFileType; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.integration.QBWrappedObject; + +public class Main { + private static String[] clsPath; + private static boolean compile; + private static boolean zip; + private static boolean debug; + private static boolean interactive; + private static String file; + private static String[] progArgs; + public static void main(String[] args){ + try{ + if(args.length == 0){ + printHelp(); + return; + } + + parseArgs(args); + + File f = file == null ? null : QBFile.getQBFile( file ); + + if(f != null && f.isDirectory()) { + System.out.println("Cannot execute on directory!"); + printHelp(); + + return; + } + + QBParser.addAnnotationReader( new AnnotationReader() { + + @Override + public void readAnnotation(Statement stmt) { + String header = stmt.getHeader().substring(1); + if(header.startsWith("infix")){ + header = header.substring(5).trim(); + + String[] headers = header.split("\\s+"); + int prec = 30; + String op; + + if(headers.length == 2){ + prec = Integer.parseInt(headers[1]); + } + + op = headers[0]; + QBExpressionParser.mapOp(op, prec); + } + } + }); + + // System.out.println("Hello?"); + + if( compile ){ + compile(f, zip); + } else if(interactive) { + QBInteractiveInterpreter interpreter = new QBInteractiveInterpreter(); + interpreter.startInterpreter(); + } else{ + go(f); + } + + } catch(Exception e){ + e.printStackTrace(); + } + } + + public static void go( File f ) throws Exception{ + QBInterpreter interpreter = openFile(f); + + long time = 0, time2 = 0; + if(debug){ + System.out.println("Namespace: " + interpreter.getGlobalNamespace().toString2()); + time = System.currentTimeMillis(); + } + + QBFunction func = (QBFunction) interpreter.getGlobalNamespace().get("main"); + QBObject finish = func.execute(new QBObject[]{}); + + if(debug){ + time2 = System.currentTimeMillis(); + System.out.println("Result: " + finish); + System.out.println("Total time: " + (time2 - time) / 1000.0 + " seconds"); + + System.out.println("Time spent on one method: " + QBObject.totalTime / 1000.0 + " seconds"); + } + } + + public static void compile( File f, boolean zip ) throws Exception{ + QBInterpreter interpreter = openFile(f); + + String str = f.getName(); + int idx = str.lastIndexOf('.'); + if (idx >= 0) { + str = str.substring(0,idx); + } + + if(zip) { + str += ".qbz"; + } else { + str += ".qbc"; + } + + File newFile = new File(str); + OutputStream out = new FileOutputStream(newFile); + + if( zip ) { + interpreter.writeSelfCompressed(out); + } else { + interpreter.writeSelf(out); + } + } + + private static void parseArgs(String[] args) { + List<String> path = new ArrayList<String>(); + + path.add("."); + + for( int i = 0; i < args.length; i++) { + String str = args[i]; + if(str.startsWith("-")) { + if(str.equals("-p") || str.equals("--path")) { + if( i == args.length ) { + System.err.println("--path takes 1 argument"); + System.exit(1); + } + + String pathArg = args[ ++i ]; + String[] paths = pathArg.split(";"); + path.addAll( Arrays.asList(paths) ); + } else if( str.equals("-c") || str.equals("--compile") ){ + if(compile) + warn("compiling already enabled"); + + compile = true; + } else if( str.equals("-z") || str.equals("--zip") ){ + if(compile) + warn("compiling already enabled"); + if(zip) + warn("zipping already enabled"); + + compile = true; + zip = true; + } else if( str.equals("--debug") ){ + debug = true; + } else if( str.equals("-i") ) { + interactive = true; + } else { + System.err.println("Illegal option " + str); + } + } else { + progArgs = new String[ args.length - i ]; + System.arraycopy(args, i, progArgs, 0, progArgs.length); + file = progArgs[0]; + break; + } + } + + clsPath = path.toArray(new String[path.size()]); + } + + private static void printHelp() { + System.out.println("QBarInterpreter v. 0.028 BETA (More Like DELTA)\nUsage: qbar [ -p [CLASSPATH] ] [FILENAME]\nExecutes a qbar " + + "file using the classpath defined as the search path for modules\n\nInterpreter executes the `main` function of" + + " the file.\nOptions:\n\n\t-p : add a path to the classpath\n\t-c : compile source file\n\t-z : compile source file and zip it\n\t--debug : enable debugging mode (for development)" + "\n\nAuthor: Josh Rahm"); + } + + public static void warn(String str){ + System.out.println("[Warn] " + str); + } + + public static QBInterpreter openFile( File f ) throws Exception{ + QBFileType type = QBFileType.getFileType( f.getName() ); + return type.getReader().readFromStream( new FileInputStream(f) ); + } + + public static String[] getPath() { + return clsPath; + } + + public static void debug(Class<?> cls, String str){ + if( debug ){ + System.out.println("[DEBUG] - " + cls.getSimpleName() + " - " + str); + } + } + + public static void prettyThrow( RuntimeException e ){ + if( debug ) { + throw e; + } + + List<String> lines = new ArrayList<String>(); + List<String> messages = new ArrayList<String>(); + + Exception cur = e; + while( cur != null ) { + messages.add("cur"); + } + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInteractiveInterpreter.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInteractiveInterpreter.java new file mode 100644 index 0000000..d748d40 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInteractiveInterpreter.java @@ -0,0 +1,113 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.modulus.dataread.expressions.Statement; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBSyntheticFunction; +import com.modulus.qbar.core.parser.ByteOperation; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.core.parser.stmt.QBStatement; +import com.modulus.qbar.lang.QBMaybe; + +public class QBInteractiveInterpreter extends QBInterpreter{ + private BufferedReader console; + private QBParser parser; + private QBStatement alwaysSuper = new QBStatement( QBParser.formatter ); + public static void main(String[] args) { + QBInteractiveInterpreter interpreter = new QBInteractiveInterpreter(); + interpreter.startInterpreter(); + } + + public QBInteractiveInterpreter(){ + super(); + + alwaysSuper.setHeader("let tmp = do"); + + console = new BufferedReader( new InputStreamReader( System.in ) ); + this.parser = new QBParser( this ); + } + + public void startInterpreter(){ + while(true){ + try{ + TransparentFunction func = readStatement(); + QBObject ret = func.execute(new QBObject[]{}); + + if( ret == null ) + ret = QBMaybe.new$0x20Null(); + + System.out.println("?: " + ret); + this.getGlobalNamespace().set("ans", ret); + + } catch(Exception e){ + e.printStackTrace(); + } + } + } + + private int depth = 0; + public TransparentFunction readStatement() throws Exception{ + System.out.print(">>> "); + StringBuffer tot = new StringBuffer(); + + tot.append(readLine()); + while(tot.length() == 0){ + System.out.print(">>> "); + tot.append(readLine()); + } + + while( depth > 0 ) { + System.out.print("... "); + tot.append(readLine()); + } + + QBStatement sup = alwaysSuper.clone(); + sup.clearChildren(); + QBStatement tmp; + + try{ + tmp = parser.parseCode(tot.toString()); + } catch( RuntimeException e ) { + tmp = parser.parseCode( tot.toString() + ";" ); + } + + for( Statement stmt : tmp.getChildren()){ + sup.addChild(stmt); + } + + return new TransparentFunction(sup, parser, this); + } + + public String readLine() throws IOException{ + String ret = console.readLine(); + + if( ret == null ) { + System.out.println("Goodbye."); + System.exit(0); + } + + int quotes = 0; + + for( int i = 0;i < ret.length();i++) { + if(ret.charAt(i) == '"') + quotes ++; + + if(quotes % 2 == 1) + continue; + + if(ret.charAt(i) == '{') { + depth ++; + } else if( ret.charAt(i) == '}') { + depth --; + } + } + + return ret; + } + + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreter.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreter.java new file mode 100644 index 0000000..448a901 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreter.java @@ -0,0 +1,193 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.QBUtilityNamespace; +import com.modulus.qbar.core.parser.Core; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.core.primitive.QBChar; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class QBInterpreter implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 3717481804592061086L; + private static QBInterpreter instance; + private Core core; + private transient QBParser parser; + private QBJarLoader loader; + + private static class QBThread extends Thread{ + private QBInterpreter instance; + + public QBThread( QBInterpreter cur ){ + this.instance = cur; + } + + public QBInterpreter instance(){ + return instance; + } + } + + public QBThread run(){ + + QBThread thread = new QBThread(this){ + public void run(){ + QBFunction main = (QBFunction) core.getGlobalNamespace().get("main"); + main.execute(new QBObject[]{}); + } + }; + + + thread.start(); + return thread; + } + + public static QBInterpreter instance(){ + Thread t = Thread.currentThread(); + + if( t instanceof QBThread ) + return ((QBThread) t).instance(); + + return instance; + } + + public QBInterpreter( String code ){ + try { + loader = new QBJarLoader("/usr/lib/qbar/lib/endorsed"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + parser = new QBParser( this ); + + instance = this; + + this.core = parser.getSystemCore(); + loadLang(); + + parser.parseCode(code); + + + parser.resetCore(); + + this.getGlobalNamespace().set("Null", new QBObject(null)); + ((QBUtilityNamespace) this.getGlobalNamespace()).setStruct( new QBStruct("NamespaceUtility") ); + + + } + + protected QBInterpreter(){ + try { + loader = new QBJarLoader("/usr/lib/qbar/lib/endorsed"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + instance = this; + this.core = new Core(); + + loadLang(); + this.getGlobalNamespace().set("Null", new QBObject(null)); + ((QBUtilityNamespace) this.getGlobalNamespace()).setStruct( new QBStruct("NamespaceUtility") ); + } + + public QBNamespace getGlobalNamespace(){ + return core.getGlobalNamespace(); + } + + public Stack<QBObject> getStack(){ + return core.getStack(); + } + + public void merge(QBInterpreter other){ + this.core.merge(other.core); + } + public void writeSelf( OutputStream out ) throws IOException{ + this.core.writeSelf( out ); + } + + public static QBInterpreter readInterpreter( InputStream in ) throws IOException, ClassNotFoundException{ + QBInterpreter ret = new QBInterpreter(); + + ret.parser = new QBParser( ret ); + ret.core = new Core(); + + ret.core.readSelf( in ); + + return ret; + } + + public void writeSelfCompressed(final OutputStream out) throws IOException{ + GZIPOutputStream zipOut = new GZIPOutputStream(out); + writeSelf(zipOut); + } + + public static QBInterpreter readInterpreterFromSource( InputStream in ) throws IOException{ + BufferedReader reader = new BufferedReader( new InputStreamReader( in ) ); + StringBuffer buf = new StringBuffer(); + + String line; + boolean begin = true; + while((line = reader.readLine()) != null){ + if(begin && line.startsWith("#")) + continue; + + buf.append(line + "\n"); + + if(begin && line.trim() != "") + begin = false; + } + + QBInterpreter old = instance(); + QBInterpreter interpreter = new QBInterpreter(buf.toString()); + + if(old != null) + instance = old; + + return interpreter; + } + + public static QBInterpreter readInterpreterCompressed( InputStream in ) throws IOException, ClassNotFoundException{ + GZIPInputStream zipIn = new GZIPInputStream(in); + return readInterpreter(zipIn); + } + + private void loadLang(){ + QBNamespace global = core.getGlobalNamespace(); + + global.set(QBInt.struct.getName(), QBInt.struct); + global.set(QBDouble.struct.getName(), QBDouble.struct); + global.set(QBChar.struct.getName(), QBChar.struct); + global.set(QBPrimitive.struct.getName(), QBPrimitive.struct); + + } + + public QBParser getParser() { + return parser; + } + + public ClassLoader getClassLoader() { + return loader.getLoader(); + } + +} + diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreterReader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreterReader.java new file mode 100644 index 0000000..b9e18f1 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBInterpreterReader.java @@ -0,0 +1,7 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.InputStream; + +public interface QBInterpreterReader{ + QBInterpreter readFromStream( InputStream in ) throws Exception; +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBJarLoader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBJarLoader.java new file mode 100644 index 0000000..a02c438 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/QBJarLoader.java @@ -0,0 +1,49 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +public class QBJarLoader { + private ClassLoader loader; + + public QBJarLoader( String dir ) throws MalformedURLException{ + this( new File(dir) ); + } + + public QBJarLoader( File dir ) throws MalformedURLException{ + loader = new URLClassLoader( listJarUrls(dir), ClassLoader.getSystemClassLoader() ); + } + + public void load(){ + } + + public ClassLoader getLoader(){ + return loader; + } + + private URL[] listJarUrls( File dir ) throws MalformedURLException{ + if( dir.isFile() ){ + return new URL[]{ dir.toURI().toURL() }; + } else { + File[] files = dir.listFiles( new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + + URL[] ret = new URL[ files.length ]; + + for( int i = 0;i < files.length; i ++) + ret[i] = files[i].toURI().toURL(); + + return ret; + } + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/SourceReader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/SourceReader.java new file mode 100644 index 0000000..db0e204 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/SourceReader.java @@ -0,0 +1,13 @@ +package com.modulus.qbar.core.interpreter; + +import java.io.IOException; +import java.io.InputStream; + +public class SourceReader implements QBInterpreterReader { + + @Override + public QBInterpreter readFromStream(InputStream in) throws IOException { + return QBInterpreter.readInterpreterFromSource(in); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/TransparentFunction.java b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/TransparentFunction.java new file mode 100644 index 0000000..7400f88 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/interpreter/TransparentFunction.java @@ -0,0 +1,24 @@ +package com.modulus.qbar.core.interpreter; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBSyntheticFunction; +import com.modulus.qbar.core.parser.QBParser; +import com.modulus.qbar.core.parser.stmt.QBStatement; + +public class TransparentFunction extends QBSyntheticFunction { + private QBInteractiveInterpreter ths; + public TransparentFunction(QBStatement code, QBParser parser, QBInteractiveInterpreter ths) { + super(code, parser); + this.ths = ths; + } + + @Override + public QBObject get( String name ){ + return ths.getGlobalNamespace().get( name ); + } + + @Override + public void set( String name, QBObject obj ) { + ths.getGlobalNamespace().set(name, obj); + } + +}
\ No newline at end of file diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/AnnotationReader.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/AnnotationReader.java new file mode 100644 index 0000000..45b6b0a --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/AnnotationReader.java @@ -0,0 +1,7 @@ +package com.modulus.qbar.core.parser; + +import com.modulus.dataread.expressions.Statement; + +public interface AnnotationReader { + void readAnnotation( Statement stmt ); +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ByteOperation.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ByteOperation.java new file mode 100644 index 0000000..20e7cae --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ByteOperation.java @@ -0,0 +1,43 @@ +package com.modulus.qbar.core.parser; + +import java.io.Serializable; +import java.util.Arrays; + +import com.modulus.qbar.core.compile.ByteOps; + +public class ByteOperation implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 8120121479968460423L; + private ByteOps operator; + private Object[] args = {null}; + + public ByteOperation(ByteOps op, Object arg){ + this.operator = op; + this.args = new Object[]{arg}; + } + + public ByteOperation(ByteOps op, Object[] args){ + this.operator = op; + + if(args.length > 0) + this.args = args; + } + + public ByteOps getOperator(){ + return operator; + } + + public Object[] getArgs(){ + return args; + } + + public Object getArg(){ + return args[0]; + } + + public String toString(){ + return operator.toString() + " " + Arrays.toString(args); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/Core.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/Core.java new file mode 100644 index 0000000..a10c530 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/Core.java @@ -0,0 +1,78 @@ +package com.modulus.qbar.core.parser; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.HashMap; + +import com.modulus.common.collections.ArrayStack; +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.QBUtilityNamespace; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class Core implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 2963257754134148521L; + private QBUtilityNamespace globalNamespace; + private Stack<QBObject> stack; + + public Core(){ + this.globalNamespace = new QBUtilityNamespace( null ){ + private static final long serialVersionUID = 3278462104573891204L; + private String name = "Global"; + @Override + public String getName() { + return name; + } + + @Override + public void construct() { + } + + }; + + this.stack = new ArrayStack<QBObject>(); + } + + public QBNamespace getGlobalNamespace(){ + return globalNamespace; + } + + public Stack<QBObject> getStack(){ + return stack; + } + + public void merge(Core other){ + this.globalNamespace.incoporate( other.getGlobalNamespace() ); + } + + public static boolean QBObjectIsTrue(QBObject obj){ + return obj instanceof QBPrimitive && ((QBPrimitive) obj).intValue() != 0; + } + + public void writeSelf(OutputStream out) throws IOException { + ObjectOutputStream oout = new ObjectOutputStream(out); + + + oout.writeObject( globalNamespace ); + oout.flush(); + oout.close(); + } + + public void readSelf(InputStream in) throws IOException, ClassNotFoundException { + ObjectInputStream oin = new ObjectInputStream(in); + Object ret = oin.readObject(); + + oin.close(); + + this.globalNamespace = (QBUtilityNamespace) ret; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionCompiler.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionCompiler.java new file mode 100644 index 0000000..7a62366 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionCompiler.java @@ -0,0 +1,62 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.List; + +import com.modulus.dataread.expressions.ExpressionPart; +import com.modulus.qbar.core.compile.ByteOps; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; + +public class ExpressionCompiler { + private QBExpressionParser parser = new QBExpressionParser(); + public ExpressionCompiler(){ + + } + + public ByteOperation[] compile( String expression ){ +// System.out.println("EXP: "+expression); + List<ByteOperation> ret = new ArrayList<ByteOperation>(); + + ExpressionPart part = parser.parseExpressions(expression); + String compiled = part.compilePart(); + + String[] split = compiled.split("\\s+"); + + for ( String str : split ){ + if(str.length() > 0){ + if (str.startsWith("<-",1) ){ + ByteOperation tmp = ret.remove(ret.size()-1); + ret.add( new ByteOperation(ByteOps.STO, tmp.getArgs() ) ); + } else if (str.startsWith("->",1) ){ + ByteOperation tmp = ret.remove(ret.size()-1); + ret.add( new ByteOperation(ByteOps.ITR, tmp.getArgs() ) ); + } else if(str.charAt(0) == '\u00FF'){ + ret.add( new ByteOperation(ByteOps.CALL, str.substring(1)) ); + } else if(str.charAt(0) == '\u00FE'){ + ret.add( new ByteOperation(ByteOps.CALLG, str.substring(1)) ); + } else { + + if( Character.isDigit( str.charAt(0) ) || (str.charAt(0) == '-' && str.length() > 1 && Character.isDigit(str.charAt(1)) )) { + if(str.contains(".") || str.endsWith("d")){ + if(str.endsWith("d")) + str = str.substring(0, str.length() - 1); + double dval = Double.parseDouble(str); + ret.add(new ByteOperation( ByteOps.PUSHO, new QBDouble(dval) )); + } else{ + if(str.endsWith("i")) + str = str.substring(0, str.length() - 1); + int dval = Integer.parseInt(str); + ret.add(new ByteOperation( ByteOps.PUSHO, new QBInt(dval) )); + } + + } else { + ret.add( new ByteOperation( ByteOps.PUSH, str.split("\\.") ) ); + } + } + } + } + + return ret.toArray( new ByteOperation[ret.size()] ); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionPuller.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionPuller.java new file mode 100644 index 0000000..9618881 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionPuller.java @@ -0,0 +1,160 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.List; + +import com.modulus.common.collections.MArrays; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.lang.QBString; + +public class ExpressionPuller { + public static void main(String[] args){ + String str = "\"Hello, World!\""; + + str = pullStrings(str); + System.out.println(str); + } + + public static String pullLists(String expression, QBNamespace sup, QBParser parser){ + String tmp; + + while(!(tmp = replaceOneList(expression, sup, parser)).equals(expression)) + expression = replaceOneList(tmp, sup, parser); + + return expression; + } + + public static String pullStrings(String expression){ + List<Integer> points = new ArrayList<Integer>(); + points.add(0); + + for(int i = 0;i < expression.length();i++){ + if(expression.charAt(i) == '"' && !(i > 0 && expression.charAt(i-1) == '\\') ){ + int stamp = i; + i++; + while(expression.charAt(i) != '"'){ + if(expression.charAt(i) == '\\') + i++; // skip the next character + i++; + } + + points.add( stamp ); + points.add( i+1 ); + } + } + points.add( expression.length() ); + + StringBuffer total = new StringBuffer(); + boolean inString = false; + for(int i = 1;i < points.size();i++){ + int i1 = points.get(i-1); + int i2 = points.get(i); + // System.out.println("("+i1+", "+i2+")"); + if(!inString){ + total.append( expression.substring(i1, i2) ); + } else{ + String exp = expression.substring(i1+1, i2-1); + int hash = exp.hashCode(); + + String name = "$string$"+Math.abs(hash); + total.append(name); + + QBString str = new QBString(exp, true); + QBInterpreter.instance().getGlobalNamespace().set(name, str); + } + + inString = !inString; + } + + return total.toString(); + } + + public static String pullIfThenElse( String[] exp, QBNamespace sup ){ + exp = fixIfThenElseParts(exp); + + + int thenIdx = MArrays.indexOf(exp, "then"); + String ifPart = MArrays.concat(exp, 1, thenIdx-1, " "); + + int elseIdx = MArrays.indexOf(exp, "else"); + String thenPart = MArrays.concat(exp, thenIdx+1, elseIdx-thenIdx-1, " "); + // System.out.println("Pull If Then Else EXP: " + Arrays.toString(exp) + " $ " + elseIdx); + String elsePart = MArrays.concat(exp, elseIdx+1, " "); + + QBFunction func = IfThenElseFunctionFactory.makeIfThenElse(ifPart, thenPart, elsePart); + + if(sup != null) + func.setSuper(sup); + + String name = "$if$then$else"+ Math.abs((ifPart+elsePart+thenPart).hashCode()); + QBInterpreter.instance().getGlobalNamespace().set(name, func); + + return name + "()"; + } + + public static String replaceOneList(String exp, QBNamespace sup, QBParser parser){ + if(!exp.contains("[")) + return exp; + + int off = exp.indexOf('[') + 1; + off = off == 0 ? 1 : off; + + int bracket = 1; + int i; + + for(i = off;bracket != 0 && i < exp.length();i++){ + if(exp.charAt(i) == '[') + bracket ++; + else if(exp.charAt(i) == ']') + bracket --; + } + + String start = exp.substring(0, off-1); + String end = exp.substring(i); + + String middle = exp.substring(off-1, i); + + int hash = Math.abs(middle.hashCode()); + String name = "$list$constructor$"+hash; + + QBFunction func = ListConstructorFactory.makeNewQBListConstructor(middle, sup, parser); + QBNamespace global = QBInterpreter.instance().getGlobalNamespace(); + + global.set(name, func); + + return start+ name + "()" + end; + } + + private static String[] fixIfThenElseParts(String[] ifthenelse){ + ArrayList<String> strs = new ArrayList<String>(); + + for(String s : ifthenelse){ + if(s.startsWith("if") && s.length() > 2 && !Character.isLetterOrDigit(s.charAt(2))){ + String str1 = s.substring(0,2); + String str2 = s.substring(2); + + strs.add(str1); + strs.add(str2); + } else if(s.startsWith("then") && s.length() > 4 && !Character.isLetterOrDigit(s.charAt(4))){ + String str1 = s.substring(0,4); + String str2 = s.substring(4); + + strs.add(str1); + strs.add(str2); + } else if(s.startsWith("else") && s.length() > 4 && !Character.isLetterOrDigit(s.charAt(4))){ + String str1 = s.substring(0,4); + String str2 = s.substring(4); + + strs.add(str1); + strs.add(str2); + } else{ + strs.add(s); + } + } + + return strs.toArray( new String[strs.size()] ); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionSpaceTokenizer.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionSpaceTokenizer.java new file mode 100644 index 0000000..884a2e8 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ExpressionSpaceTokenizer.java @@ -0,0 +1,106 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.List; + +public class ExpressionSpaceTokenizer { + public static String[] tokenize( String str ){ + // String Buffer that builds each part of the array + StringBuffer cur = new StringBuffer(); + + // the list that will be returned in the end + List<String> ret = new ArrayList<String>(); + + // the level of the parenthesis + int parenLevel = 0; + + // loop through the string one by one to split the sections + for( int i = 0;i < str.length(); i++){ + Character ch = str.charAt(i); + // check to see if the character is a whitespace char or not + boolean whitespace = Character.isWhitespace(ch); + + // see if the character is a symbol or not + boolean symbol = isSymbol(ch) ; + + // this will tell the parser if there is a paren that closes a statement + boolean close = false; + + // If the character is '(' then we increase the parenthasis + if(ch == '('){ + parenLevel ++; + } else if(str.charAt(i) == ')'){ + // if it is ')' then mark a closing statement (This will make sense at the end) + close = true; + } + + // if the string is one of these things, then it is time + // to split the string. + if((whitespace || symbol) && parenLevel == 0){ + + // the current string is cut and trimmed + String curstr = cur.toString().trim(); + + // forget adding the string if it is empty + if(curstr.length() > 0) + ret.add(curstr); + + // reset the buffer. + cur = new StringBuffer(); + + // If the character is a symbol, add all following symbols as well + if(symbol){ + + // add all following symbols + while(isSymbol(ch) && i < str.length()){ + // System.out.println("CHAR "+ch); + cur.append(ch); + i++; + ch = str.charAt(i); + } + + // a little redundant, but necessary + if(ch == '('){ + parenLevel ++; + } else if(str.charAt(i) == ')'){ + close = true; + } + + curstr = cur.toString().trim(); + if(curstr.length() > 0) + ret.add(curstr); + cur = new StringBuffer(); + } + + // finally add the current character + cur.append( ch ); + } else{ + cur.append( str.charAt(i) ); + } + + if(parenLevel < 0){ + throw new RuntimeException("Expected '('"); + } + + // here is the part where the close boolean comes in + if(close) + parenLevel --; + + + } + + if(parenLevel > 0) + throw new RuntimeException("Expected ')'"); + + String curstr = cur.toString().trim(); + + if(curstr.length() > 0) + ret.add(curstr); + + return ret.toArray(new String[ret.size()]); + } + + private static boolean isSymbol( char ch ){ + return !Character.isDigit(ch) && !Character.isLetter(ch) && !Character.isWhitespace(ch) && ch != '(' && ch != ')' && ch != '.' && ch != '$'; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/IfThenElseFunctionFactory.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/IfThenElseFunctionFactory.java new file mode 100644 index 0000000..8c7531e --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/IfThenElseFunctionFactory.java @@ -0,0 +1,16 @@ +package com.modulus.qbar.core.parser; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.lang.IfThenElseFunction; + +public class IfThenElseFunctionFactory { + private static ExpressionCompiler compiler = new ExpressionCompiler(); + + public static QBFunction makeIfThenElse(String ifPart, String thenPart, String elsePart){ + ByteOperation[] ifArr = compiler.compile(ifPart); + ByteOperation[] thenArr = compiler.compile(thenPart); + ByteOperation[] elseArr = compiler.compile(elsePart); + + return new IfThenElseFunction(ifArr, thenArr, elseArr); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ListConstructorFactory.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ListConstructorFactory.java new file mode 100644 index 0000000..f6cc787 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/ListConstructorFactory.java @@ -0,0 +1,160 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.exceptions.ExecutionException; +import com.modulus.qbar.lang.QBArrayListConstructor; +import com.modulus.qbar.lang.QBFunctionListConstructor; +import com.modulus.qbar.lang.QBFunctionListFunction; +import com.modulus.qbar.lang.QBLazyRangeListConstructor; + +public abstract class ListConstructorFactory { + private static final ExpressionCompiler compiler = new ExpressionCompiler(); + + // DO NOT CUT OUT THE MIDDLE, THE PASSED STRING SHOUDL STILL HAVE THE BRACKETS + public static QBFunction makeNewQBListConstructor(String code, QBNamespace sup, QBParser parser){ + code = code.substring(1, code.length()-1); + code = ExpressionPuller.pullLists(code, sup, parser); + if(code.contains("..")) + return makeForLazyRangeList(code, sup); + + else if(code.contains("|")){ + if(code.contains("->")){} + else{ + return makeFunctionList(code, sup, parser); + } + } + + return makeForStandardArrayList(code, sup, parser); + } + + private static QBFunction makeFunctionList(String code, QBNamespace sup, QBParser parser) { + String[] split = code.split("\\|"); + + if(split.length != 2) + throw new ExecutionException("Error parsing function list, invalid syntax, expected [index|<something with index here>]"); + + String var = split[0].trim(); + String exp = split[1].trim(); + + + + QBNamespace tmp = parser.getCurrentCompilingNamespace(); + QBFunctionListFunction func = new QBFunctionListFunction(); + parser.setCurrentCompilingNamespace(func); + + ByteOperation[] compiled = compiler.compile(exp); + + parser.setCurrentCompilingNamespace(tmp); + func.setVar(var); + func.setCommand(compiled); + + QBFunction ret = new QBFunctionListConstructor(func); + + if(sup != null) + ret.setSuper(sup); + + return ret; + } + + private static QBFunction makeForStandardArrayList(String code, + QBNamespace sup, QBParser parser) { + QBFunction ret; + // System.out.println("CODE " + code); + if(code.length() > 0){ + String[] exps = splitComma(code); + // System.out.println("EXPS: " + Arrays.toString(exps)); + + ByteOperation[][] operations = new ByteOperation[exps.length][]; + + for(int i = 0;i < exps.length;i++){ + exps[i] = ExpressionPuller.pullLists(exps[i], sup, parser); + operations[i] = compiler.compile(exps[i]); + } + + ret = new QBArrayListConstructor(operations); + } else{ + ret = new QBArrayListConstructor(new ByteOperation[][]{}); + } + if(sup != null) + ret.setSuper(sup); + + return ret; + } + + // NOW THE BRACKETS CAN BE CUT + private static QBFunction makeForLazyRangeList(String code, QBNamespace sup){ + String[] split = code.split("\\s*\\.\\.\\s*"); + + if(split.length > 2 || split.length < 1) + throw new ExecutionException("Error executing, syntax error on list"); + + String[] change = splitComma(split[0]); + String num; + + if(split.length > 1) + num = split[1]; + else + num = ""; + + //System.out.println("SPLIT: " + Arrays.toString(split) + "\nCHANGE: " + Arrays.toString(change) + "\nNUM: " + num); + + ByteOperation[] start = compiler.compile(change[0]); + ByteOperation[] second = change.length > 1 ? compiler.compile(change[1]) : null; + ByteOperation[] end = num.length() > 0 ? compiler.compile(num) : null; + + QBFunction ret = new QBLazyRangeListConstructor(start, second, end); + + if(sup != null) + ret.setSuper(sup); + + return ret; + } + + private static final String[] splitComma(String str){ + int bracket = 0; + int brace = 0; + int paren = 0; + ArrayList<String> ret = new ArrayList<String>(); + + StringBuffer buf = new StringBuffer(); + for(int i = 0;i < str.length();i++){ + if(str.charAt(i) == ','){ + if( bracket == paren && brace == paren && paren == 0){ + ret.add(buf.toString()); + buf = new StringBuffer(); + } else{ + buf.append(str.charAt(i)); + } + } else{ + switch((int)str.charAt(i)){ + case (int)'[': + bracket ++; + break; + case (int)'{': + brace++; + break; + case (int)'(': + paren ++; + break; + case (int)']': + bracket --; + break; + case (int)'}': + brace--; + break; + case (int)')': + paren --; + } + + buf.append(str.charAt(i)); + } + } + ret.add(buf.toString()); + + return ret.toArray(new String[ret.size()]); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBExpressionParser.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBExpressionParser.java new file mode 100644 index 0000000..46fc826 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBExpressionParser.java @@ -0,0 +1,341 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import com.modulus.common.collections.MArrays; +import com.modulus.dataread.expressions.ExpressionParser; +import com.modulus.dataread.expressions.ExpressionPart; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.lang.QBList; + +/** + * This class is most of the guts for compiling the source code + * into a hybrid of interpreted and byte code, this is used to promote + * a high degree of efficiency as well as maintain a high level + * of programming. + * + * From here, the resulting code can then be fed into an interpreter + * to be interpreted using a stack and heap, like most of the other + * programming languages. + * + * This class is the main part of the language. + * + * @author jrahm + * + */ +public class QBExpressionParser implements ExpressionParser{ + private static Map<Integer, List<String> > operatorPrecedence = new HashMap<Integer, List<String>>(); + + /* + * Need to puting some of the `natural` functions + * with their respective precedence related to one and other. + */ + static{ + QBList.init(); + mapOp("#", 9); // POW + mapOp("as", 9); // POW + mapOp("isa", 9); // POW + + mapOp("^", 10); // POW + mapOp("*", 20); // MUL + mapOp("/", 20); // DIV + mapOp("div", 20); // DIVI + mapOp("%", 20); // MOD + mapOp("+", 30); // ADD + mapOp("++", 30); // ADD + mapOp("-", 30); // SUB + + mapOp("<", 128); // STO + mapOp(">", 128); // STO + mapOp("<=", 128); // STO + mapOp(">=", 128); // STO + mapOp("==", 128); // STO + mapOp("!=", 128); // STO + + mapOp("not", 512); // STO + mapOp("xor", 512); // STO + mapOp("or", 512); // STO + mapOp("and", 512); // STO + + mapOp("<-", 1024); // STO + mapOp("->", 1024); // STO + } + + public static void main(String[] args){ + QBExpressionParser parser = new QBExpressionParser(); + ExpressionPart exp = parser.parseExpressions("4 + 5 - (if (5+1) then (4+2) else (3+3))"); + System.out.println(exp.compilePart()); + } + + @Override + public ExpressionPart parseExpressions(String exp) { + String[] strs = ExpressionSpaceTokenizer.tokenize(exp); + return parseExpressions(strs, QBInterpreter.instance().getParser() ); + } + + /** + * This function further parses from a String[], unlike its + * counterpart which uses just a String to parse. + * + * @param exp the expression to parse + * @return an ExpressionPart that represents this code + */ + public ExpressionPart parseExpressions (String[] exp, QBParser parser) { + exp = fixArray(exp); + // System.out.println("EXPS: " + Arrays.toString(exp)); + if(exp[0].startsWith("if")){ + if( (exp[0].length() > 2 && !Character.isLetterOrDigit( exp[0].charAt(2) )) || exp[0].length() == 2){ + String name = ExpressionPuller.pullIfThenElse(exp, parser.getCurrentCompilingNamespace()); + exp = new String[]{name}; + } + } + +// if(exp[0].equals("if")){ +// int thenIdx = MArrays.indexOf(exp, "then"); +// String ifPart = MArrays.concat(exp, 1, thenIdx-1); +// +// int elseIdx = MArrays.indexOf(exp, "else"); +// String thenPart = MArrays.concat(exp, thenIdx+1, elseIdx-thenIdx-1); +// +// String elsePart = MArrays.concat(exp, elseIdx+1); +// +// ExpressionPart ifExpPart = parseExpressions(ifPart); +// ExpressionPart thenExpPart = parseExpressions(thenPart); +// ExpressionPart elseExpPart = parseExpressions(elsePart); +// +// ExpressionPart totalIf = ExpressionPart.makePrimaryExpressionPart(null, "if", new ExpressionPart[]{ifExpPart}); +// ExpressionPart totalThen = ExpressionPart.makePrimaryExpressionPart(totalIf, "then", new ExpressionPart[]{thenExpPart}); +// ExpressionPart total = ExpressionPart.makePrimaryExpressionPart(totalThen, "else", new ExpressionPart[]{elseExpPart}); +// +// return total; +// } + + + // Go though all of the operators in order from their respective order of operations. + for( String[] ops : operators() ){ + + int idx = -1; + // Some operators have the same precedence, so we need to deal with that + for( String op : ops ) { + idx = Math.max(idx, MArrays.lastIndexOf(exp, op)); + } + + // if we found one of these opeartors, then we + // need to deal with it. + if( idx != -1 ){ + // get the function (thats easy, it is what we just found) + String function = exp[idx]; + + // get all stuff before and after this point + // the first is the caller and the second is the + // argument believe me it works because + // 3 * 4 / 6 + 1 * 2 - 3 ^ 2 * 2 = (3 * 4 / 6 + 1 * 2) - (3 ^ 2 * 2) + String[] before = Arrays.copyOfRange(exp, 0, idx); + String[] after = Arrays.copyOfRange(exp, idx + 1, exp.length); + + // now, using recursion we make the expression parts out of them + ExpressionPart part1 = parseExpressions( before, parser ); + ExpressionPart part2 = parseExpressions( after, parser ); + + if(function.equals("->")){ + ExpressionPart tmp = part1; + part1 = part2; + part2 = tmp; + } + // now put the whole thing together, and you now have a mess + return ExpressionPart.makePrimaryExpressionPart(part1, function, new ExpressionPart[]{part2} ); + } + + + } + + // If there are no more "Binary Functions" + // what is left must be grouped or it must be a function + if( exp.length == 1 ){ + String str = exp[0]; + if( completelySurrounded(str) ){ + String middle = str.substring(1, str.length() - 1); + return parseExpressions(middle); + } + // This must then be a function + else if(str.endsWith(")")){ + + // this function will get the last index of a dot ('.') that is outside parenthesis + // the dot is used to determine if the function is being called by an object + int dotIdx = lastDotIndex(str); + + // now we find the index that the arguments start on + int idx = str.indexOf('(',dotIdx); + + // check to make sure there is one. + if( idx < 0 ){ + throw new RuntimeException("Expected '('"); + } + + // from here it is pretty straight forward to get the function, + // caller and parameters. + String function = str.substring(0, idx); + String args = str.substring(idx + 1, str.length() - 1); + String caller = null; + + // if there is not dot, then there is no caller and the function is global + if( dotIdx >= 0 ){ + caller = function.substring( 0, dotIdx ); + function = function.substring( dotIdx + 1 ); + } + + // now use recursion to build the parts and make a new part. + ExpressionPart part1 = caller !=null ? parseExpressions(caller) : null; + ExpressionPart[] parts = parseParams(args); + + return ExpressionPart.makePrimaryExpressionPart(part1, function, parts); + + } + + else{ + // This is the base case, the very bottom of the ladder, this is where all + // that is left is some entity that has no function. + return ExpressionPart.makeExpressionPart(exp[0]); + } + } + + throw new RuntimeException("Syntax Error"); + } + + private ExpressionPart[] parseParams( String params ){ + params = params.trim(); + if(params.length() == 0) + return new ExpressionPart[]{}; + + String[] split = splitParam(params); + ExpressionPart[] parts = new ExpressionPart[split.length]; + + for ( int i = 0;i < split.length; i++ ){ + parts[i] = parseExpressions(split[i]); + } + + // Might need this + //Collections.reverse( Arrays.asList(parts) ); + return parts; + } + + private static String[] splitParam( String params ){ + int paramIdx = 0; + StringBuffer cur = new StringBuffer(); + List<String> ret = new ArrayList<String>(); + + for( int i = 0;i < params.length(); i++){ + char ch = params.charAt(i); + if(ch == '(') + paramIdx ++; + + else if( ch == ')' ) + paramIdx --; + + if( paramIdx < 0 ) + throw new RuntimeException("Expected '('"); + + if( ch == ',' && paramIdx == 0 ){ + ret.add(cur.toString()); + cur = new StringBuffer(); + } else{ + cur.append(ch); + } + } + + ret.add(cur.toString()); + + return ret.toArray(new String[ret.size()]); + } + + private String[] fixArray(String[] exp){ + List<String> arr = new ArrayList<String>(); + boolean last = true; + for(int i = 0;i < exp.length;i ++){ + if( isDigit(exp[i]) ){ + last = true; + } else{ + if(!last && exp[i].equals("-")){ + exp[i+1] = "-" + exp[i+1]; + exp[i] = ""; + } + + last = false; + } + if(exp[i].length() > 0) + arr.add(exp[i]); + } + + return arr.toArray(new String[arr.size()]); + } + + private boolean isDigit(String exp){ + return Pattern.matches("(\\d|\\w|\\.)+",exp); + } + + public static void mapOp(String op, Integer prec){ + List<String> lst = operatorPrecedence.get(prec); + + if(lst == null){ + lst = new ArrayList<String>(); + operatorPrecedence.put(prec, lst); + } + + lst.add(op); + } + + private static List<String[]> operators(){ + List<String[]> lst = new ArrayList<String[]>(); + Collection<Integer> keys = operatorPrecedence.keySet(); + List<Integer> keyList = new ArrayList<Integer>(); + + keyList.addAll(keys); + Collections.sort(keyList); + Collections.reverse(keyList); + + for (Integer i : keyList){ + List<String> temp = operatorPrecedence.get(i); + lst.add( temp.toArray( new String[temp.size()] )); + } + + return lst; + } + + private static boolean completelySurrounded( String str ){ + int paramIdx = 0; + for( int i = 0;i < str.length(); i++ ){ + if(str.charAt(i) == '(') + paramIdx ++; + else if (str.charAt(i) == ')') + paramIdx --; + + if( paramIdx == 0 ) + return false; + } + + return true; + } + + private static int lastDotIndex( String str ){ + int paramIndex = 0; + + for( int i = str.length()-1;i >= 0;i--){ + if(str.charAt(i) == ')') + paramIndex --; + else if(str.charAt(i) == '(') + paramIndex ++; + else if(str.charAt(i) == '.' && paramIndex == 0) + return i; + } + + return -1; + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBFileType.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBFileType.java new file mode 100644 index 0000000..da78219 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBFileType.java @@ -0,0 +1,37 @@ +package com.modulus.qbar.core.parser; + +import com.modulus.qbar.core.interpreter.CompiledReader; +import com.modulus.qbar.core.interpreter.CompressedReader; +import com.modulus.qbar.core.interpreter.QBInterpreterReader; +import com.modulus.qbar.core.interpreter.SourceReader; + +public enum QBFileType { + SOURCE(".qbar", new SourceReader()), + COMPILED(".qbc", new CompiledReader()), + GZIPPED(".qbz", new CompressedReader()); + + private String ext; + private QBInterpreterReader reader; + + QBFileType(String ext, QBInterpreterReader reader){ + this.ext = ext; + this.reader = reader; + } + + public String getExtention(){ + return ext; + } + + public QBInterpreterReader getReader(){ + return this.reader; + } + + public static QBFileType getFileType(String file){ + for( QBFileType type : QBFileType.values() ) + if(file.endsWith(type.getExtention())) + return type; + + + return SOURCE; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java new file mode 100644 index 0000000..5054a1b --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java @@ -0,0 +1,307 @@ +package com.modulus.qbar.core.parser; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; +import com.modulus.dataread.expressions.StatementFormatter; +import com.modulus.dataread.expressions.impl.CBasedParseRules; +import com.modulus.dataread.expressions.impl.SimpleStatementTreeParser; +import com.modulus.qbar.core.QBConstructor; +import com.modulus.qbar.core.QBFile; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.QBSyntheticFunction; +import com.modulus.qbar.core.QBSyntheticStruct; +import com.modulus.qbar.core.QBSyntheticUtilityNamespace; +import com.modulus.qbar.core.QBUtilityNamespace; +import com.modulus.qbar.core.exceptions.ParseException; +import com.modulus.qbar.core.interpreter.Main; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.stmt.QBStatement; +import com.modulus.qbar.core.parser.stmt.QBStatements; +import com.modulus.qbar.integration.QBWrappedClass; +import com.modulus.qbar.integration.QBWrappedUtilityNamespace; + +public class QBParser { + private static Set<Object> alreadyImported = new HashSet<Object>(); + + private Core systemCore = new Core(); + private SimpleStatementTreeParser treeParser; + private static List<AnnotationReader> annotationReaders = new ArrayList<AnnotationReader>(); + private QBNamespace currentCompilingNamespace; + private QBInterpreter thisInterpreter; + private Map<QBStruct, String> waitingListForExtending = new HashMap<QBStruct, String>(); + + public QBParser( QBInterpreter interpreter ){ + thisInterpreter = interpreter; + } + + public static final StatementFormatter formatter = new StatementFormatter() { + private static final long serialVersionUID = 9033830509672123664L; + + @Override + public String formatHeader(String header) { + header = header.replaceAll("\\s+", " "); // only one space in needed + header = header.trim(); // trim it to look better + header = header.replaceAll("\\s+\\(", "("); // remove spaces before parenthasis + + return header; + } + }; + + public static final StatementFactory<QBStatement> PARSER_STATEMENT_FACTORY = new StatementFactory<QBStatement>() { + + @Override + public QBStatement generateStatement(Map<String, Object> params) { + return new QBStatement(formatter); + } + + }; + + + public QBStatement parseCode( String code ){ + // FIXME big use of bandaid + code = "Namespace global{\n" + code + "\n}"; + CBasedParseRules rules = new CBasedParseRules(code){ + @Override + public String getCommentOpen() { + return "-{"; + } + + @Override + public String getCommentClose() { + return "}-"; + } + + @Override + public String getLineCommentDelimeter() { + return "--"; + } + }; + + treeParser = new SimpleStatementTreeParser(rules); + + QBStatement statements = (QBStatement) treeParser.parseStatements( PARSER_STATEMENT_FACTORY); + + for(Statement stmt : statements.getChildren() ){ + if(stmt.getHeader().startsWith("@")){ + readAnnotation( stmt ); + } else{ + readStatement(stmt, systemCore.getGlobalNamespace()); + } + } + + return statements; + } + + public static void readAnnotation(Statement stmt) { + for(AnnotationReader annotReader : annotationReaders) + annotReader.readAnnotation(stmt); + } + + public static void addAnnotationReader(AnnotationReader reader){ + annotationReaders.add(reader); + } + + public void readStatement( Statement stat, QBNamespace nmspce ){ + //System.out.println("HEADER " + stat.getHeader()); + currentCompilingNamespace = nmspce; + + if(stat instanceof QBStatement) + ((QBStatement) stat).compile( this ); + + try{ + if(QBStatements.stmtIsImport(stat)){ + Main.debug(QBParser.class, "Importing Stuff!"); + try { + importStuff(stat, nmspce); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } else if(QBStatements.stmtIsLoad(stat)){ + try { + loadStuff(stat, nmspce); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } else if( QBStatements.stmtIsConstructor(stat) ){ + stat.setHeader( stat.getHeader().replaceAll("new\\s+", "new\\$0x20") ); + QBSyntheticFunction constructor = new QBConstructor((QBStatement) stat, (QBStruct) nmspce, this); + constructor.setSuper(nmspce); + systemCore.getGlobalNamespace().set(constructor.getName(), constructor); + } else if( QBStatements.stmtIsFunction(stat) ){ + QBFunction func = createFunction(stat, nmspce); + + if(nmspce instanceof QBSyntheticFunction) { + ((QBSyntheticFunction) nmspce).addSubObject( func.getName(), func); + } else { + nmspce.set(func.getName(), func); + } + } else if( QBStatements.stmtIsClass(stat) ){ + QBStruct struct = new QBSyntheticStruct(stat, this, nmspce); + + if(nmspce instanceof QBSyntheticFunction) { + ((QBSyntheticFunction) nmspce).addSubObject( struct.getName(), struct); + } else { + nmspce.set(struct.getName(), struct); + } + } else if( QBStatements.stmtIsNamespace(stat)){ + QBUtilityNamespace utilNamespace = new QBSyntheticUtilityNamespace(stat, this, nmspce); + utilNamespace.construct(); + + if(nmspce instanceof QBSyntheticFunction) { + ((QBSyntheticFunction) nmspce).addSubObject( utilNamespace.getName(), utilNamespace); + } else { + nmspce.set(utilNamespace.getName(), utilNamespace); + } + } + } catch(Exception e){ + e.printStackTrace(); + throw new ParseException(stat); + } + } + + public QBFunction createFunction(Statement stat, QBNamespace nmspce) { + QBFunction func = new QBSyntheticFunction((QBStatement) stat, this); + func.setSuper(nmspce); + return func; + } + + public QBFunction createInteractiveFunction(Statement stat, QBNamespace nmspce) { + QBFunction func = new QBSyntheticFunction((QBStatement) stat, this); + func.setSuper(nmspce); + return func; + } + + private void importStuff(Statement importStmt, QBNamespace nmspce) throws IOException, ClassNotFoundException{ + String[] headers = importStmt.getHeader().split("\\s+", 3); + + String next = headers[1]; + if(next.equals("Native")) + importNative( headers[2], nmspce ); + + else + importStandard(headers[1]); + } + + private void loadStuff(Statement importStmt, QBNamespace nmspce) throws IOException, ClassNotFoundException{ + String[] headers = importStmt.getHeader().split("\\s+", 3); + + String next = headers[1]; + if(next.equals("Native")) + loadNative( headers[2], nmspce ); + + else + loadStandard(headers[1], nmspce); + } + + private void loadStandard(String string, QBNamespace ns) { + // System.out.println("Incorporating: " + ns); + ns.incoporate( ns.get(string) ); + } + + private void loadNative(String clazz, QBNamespace nmspce) throws ClassNotFoundException { + QBNamespace tmp = importNative(clazz, nmspce); + + nmspce.incoporate(tmp); + } + + private void importStandard(String file) throws IOException, ClassNotFoundException{ + + + File f = QBFile.getQBFile(file); + + if(alreadyImported.contains(f.getAbsolutePath())){ + Main.debug(this.getClass(), f.getAbsolutePath() + " is already imported!"); + return; + } + alreadyImported.add(f.getAbsolutePath()); + + QBFileType type = QBFileType.getFileType(file); + QBInterpreter interpreter = null; + FileInputStream in = new FileInputStream(f); + + // TODO fix to use enum to read + switch(type){ + case SOURCE: + interpreter = QBInterpreter.readInterpreterFromSource( in ); + break; + + case COMPILED: + interpreter = QBInterpreter.readInterpreter( in ); + break; + + case GZIPPED: + interpreter = QBInterpreter.readInterpreterCompressed( in ); + } + + QBInterpreter.instance().merge(interpreter); + } + + private QBNamespace importNative(String clazz, QBNamespace nmspce) throws ClassNotFoundException{ + Pattern p = Pattern.compile("\\s+as\\s+"); + Matcher m = p.matcher(clazz); + + String name = clazz.substring(clazz.lastIndexOf('.') + 1); + + if( m.find() ){ + String[] split = clazz.split("\\s+as\\s+"); + clazz = split[0]; + + name = split[1]; + } + + Class<?> cls = thisInterpreter.getClassLoader().loadClass(clazz);//Class.forName(clazz); + QBWrappedUtilityNamespace utilityNamespace = new QBWrappedUtilityNamespace( name ); + + QBStruct struct = QBWrappedClass.wrapClass(cls, utilityNamespace); + struct.setSuper(nmspce); + + utilityNamespace.set(struct.getName(), struct); + nmspce.set(utilityNamespace.getName(), utilityNamespace); + + return utilityNamespace; + } + + + public Core getSystemCore(){ + return systemCore; + } + + public void resetCore(){ + systemCore = new Core(); + } + + public void setCurrentCompilingNamespace( + QBNamespace currentCompilingNamespace) { + this.currentCompilingNamespace = currentCompilingNamespace; + } + + public QBNamespace getCurrentCompilingNamespace() { + return currentCompilingNamespace == null ? systemCore.getGlobalNamespace() : currentCompilingNamespace; + } + + public void insertIntoWaiting(QBStruct struct, String other){ + waitingListForExtending.put(struct, other); + } + + public QBInterpreter getInterpreter(){ + return this.thisInterpreter; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java.bak b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java.bak new file mode 100644 index 0000000..09bc3fa --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/QBParser.java.bak @@ -0,0 +1,98 @@ +package com.modulus.qbar.core.parser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.modulus.dataread.expressions.ParseRules; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; +import com.modulus.dataread.expressions.StatementFormatter; +import com.modulus.dataread.expressions.impl.CBasedParseRules; +import com.modulus.dataread.expressions.impl.FormatStatement; +import com.modulus.dataread.expressions.impl.SimpleExpressionParser; +import com.modulus.qbar.core.QBClass; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.exceptions.ExecutionException; + +/** + * This class is responsible for parsing all of the information + * that is held in a single Q-Bar source file. + * + * @author jrahm + * + */ +public class QBParser { + /** + * Formatter that formats all of the statements when they + * are created by the factory + */ + public static final StatementFormatter formatter = new StatementFormatter() { + @Override + public String formatHeader(String header) { + return header.trim(); + } + }; + + /** + * Generates all of the statements to be parsed by the + * ExpressionParser. + */ + public static final StatementFactory<FormatStatement> statementFactory = new StatementFactory<FormatStatement>() { + + @Override + public FormatStatement generateStatement(Map<String, Object> params) { + return new FormatStatement(formatter); + } + }; + + /** + * Parses the code from some source. + * @param code the code from the source + */ + public void parseCode(String code) { + ParseRules cRules = new CBasedParseRules(code); + SimpleExpressionParser parser = new SimpleExpressionParser(cRules); + + Statement node = parser.parseStatements( statementFactory ); + Statement[] stmts = node.getChildren(); + } + + /** + * This method parses a class from a statement + * @param stmt the statement that holds the class + * @return the class that was parsed from this statement + */ + public QBClass parseClass(Statement stmt){ + Statement[] children = stmt.getChildrenByHeader("Struct"); + QBStruct struct = new QBStruct(); + + for(int i = 0;i < children.length;i++){ + Statement child = children[i]; + + String name = child.getHeader(); + struct.addInstanceVariable(name); + + if(name.startsWith("Class")){ + if(!name.endsWith("{")){ + throw new ExecutionException("`Class' is a reserved word and may not be used as a variable name"); + } + + QBClass parsed = parseClass(child); + } + } + + return null; + } + + /** + * Parses a function from a statement. + * + * @param stmt the statement to parse the function from + * @return the function that was parsed from this statement. + */ + public QBFunction parseFunction(Statement stmt){ + return new QBFunction(stmt); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatement.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatement.java new file mode 100644 index 0000000..8c66cef --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatement.java @@ -0,0 +1,127 @@ +package com.modulus.qbar.core.parser.stmt; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; + +import com.modulus.dataread.expressions.FlowStatement; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFormatter; +import com.modulus.dataread.expressions.impl.FormatStatement; +import com.modulus.qbar.core.exceptions.ParseException; +import com.modulus.qbar.core.parser.ByteOperation; +import com.modulus.qbar.core.parser.ExpressionCompiler; +import com.modulus.qbar.core.parser.ExpressionPuller; +import com.modulus.qbar.core.parser.QBParser; + +/** + * This class implements a statement that translates + * itself into more computer-readable code automatically. + * It is guaranteed that all of the children of this + * statement will be QBStatements as well, so it is safe to + * cast. + * + * @author jrahm + * + */ +public class QBStatement extends FormatStatement implements Cloneable{ + /** + * + */ + private static final long serialVersionUID = 1707466197323482810L; + + private static Collection<String> excludedHeaders = Arrays.asList("Struct", "let", "Namespace", "Import", "Incorporate"); + + private ByteOperation[] byteOps; + private FlowStatement flow = FlowStatement.NONE; + + public QBStatement(StatementFormatter format){ + super(format); + } + + public ByteOperation[] getOperations(){ + return byteOps; + } + + public FlowStatement getFlowStatement(){ + return flow; + } + + private void p_compile(QBParser parser){ + try{ + + String header = this.getHeader(); + header = ExpressionPuller.pullStrings(header); + + header = ExpressionPuller.pullLists(header, parser.getCurrentCompilingNamespace(), parser); + + header = header.replaceAll("new\\s+", "new\\$0x20"); + for( FlowStatement stmt : FlowStatement.values() ){ + if( header.startsWith(stmt.toString().toLowerCase()) ){ + if(!(stmt == FlowStatement.IF && header.contains("then"))){ + flow = stmt; + + + header = header.substring(stmt.toString().length()).trim(); + if(stmt == FlowStatement.ELSE){ + byteOps = new ByteOperation[]{}; + return; + } + + break; + } + } + } + + ExpressionCompiler comp = new ExpressionCompiler(); + byteOps = comp.compile(header); + } catch( RuntimeException e ){ + throw new ParseException(e.getMessage(), e, this); + } + } + @Override + public void setLineNumber(int line){ + //System.out.println(this.getHeader() + " : " + line); + super.setLineNumber(line); + } + @Override + public void setHeader( String header ){ + + super.setHeader( header ); + if(this.getHeader().startsWith("}")) + throw new RuntimeException("} as first character of header!"); + + } + + public void compile( QBParser parser ){ + if(shouldCompile()) + p_compile( parser ); + + for(Statement stmt : getChildren()){ + if(stmt instanceof QBStatement){ + QBStatement qbStmt = (QBStatement) stmt; + qbStmt.compile( parser ); + } + } + } + + private boolean shouldCompile(){ + + + for(String s : excludedHeaders) + if(this.getHeader().startsWith(s)) + return false; + return true; + } + + public QBStatement clone(){ + try { + return (QBStatement) super.clone(); + } catch (CloneNotSupportedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new RuntimeException(e); + } + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatements.java b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatements.java new file mode 100644 index 0000000..0047c33 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/parser/stmt/QBStatements.java @@ -0,0 +1,37 @@ +package com.modulus.qbar.core.parser.stmt; + +import com.modulus.dataread.expressions.Statement; + +public class QBStatements { + static public boolean stmtIsNamespace( Statement stmt ){ + return stmt.getHeader().startsWith("Namespace"); + } + static public boolean stmtIsFunction( Statement stmt ){ + return stmt.getHeader().startsWith("let"); + } + + static public boolean stmtIsClass( Statement stmt ){ + return stmt.getHeader().startsWith("Struct"); + } + + static public boolean stmtIsConstructor( Statement stmt ){ + // constructors have the word `new` come after the `let` declaration + // as in let new Object(a,b,c) = do . . . + + // A constructor does not nessecarily have to take the name of the object + if(!stmtIsFunction(stmt)){ + return false; + } + String header = stmt.getHeader(); + header = header.substring(3).trim(); + return header.startsWith("new"); + } + + static public boolean stmtIsImport( Statement stmt ){ + return stmt.getHeader().startsWith("Import"); + } + + static public boolean stmtIsLoad( Statement stmt ){ + return stmt.getHeader().startsWith("Incorporate"); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBChar.java b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBChar.java new file mode 100644 index 0000000..4fe9802 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBChar.java @@ -0,0 +1,69 @@ +package com.modulus.qbar.core.primitive; + +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; + +/** + * Class that represents the + * Q-Bar primitive value char + */ + /* + * this class was generated by the python script + * 'generate_primitives.py + * @PythonGenerated + */ +public class QBChar extends QBPrimitive{ + /** + * + */ + private static final long serialVersionUID = 3811922090207258658L; + private char value; + public final static QBStruct struct = new QBStruct("Character", QBPrimitive.struct) { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public QBObject newInstance() { + // TODO Auto-generated method stub + return null; + } + }; + /** + * Constructs a new QBarChar that wraps + * the type char + */ + public QBChar( char value ){ + this.value = value; + } + + @Override + public int intValue(){ + return (int) this.value; + } + + @Override + public double doubleValue(){ + return (double) this.value; + } + + @Override + public char charValue(){ + return (char) this.value; + } + + public String toString(){ + return Character.toString(value); + } + + public Number getValueNumber(){ + return (int)value; + } + + @Override + public Object getWrapped(){ + return value; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBDouble.java b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBDouble.java new file mode 100644 index 0000000..148b24e --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBDouble.java @@ -0,0 +1,71 @@ +package com.modulus.qbar.core.primitive; + +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; + +/** + * Class that represents the + * Q-Bar primitive value double + */ + /* + * this class was generated by the python script + * 'generate_primitives.py + * @PythonGenerated + */ +public class QBDouble extends QBPrimitive{ + /** + * + */ + private static final long serialVersionUID = -2590117898914328610L; + private double value; + + public final static QBStruct struct = new QBStruct("Double", QBPrimitive.struct) { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public QBObject newInstance() { + // TODO Auto-generated method stub + return null; + } + }; + + /** + * Constructs a new QBarDouble that wraps + * the type double + */ + public QBDouble( double value ){ + this.value = value; + } + + @Override + public int intValue(){ + return (int) this.value; + } + + @Override + public double doubleValue(){ + return (double) this.value; + } + + @Override + public char charValue(){ + return (char) this.value; + } + + public String toString(){ + return Double.toString(value); + } + + public Number getValueNumber(){ + return value; + } + + @Override + public Object getWrapped(){ + return value; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBInt.java b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBInt.java new file mode 100644 index 0000000..c8f5452 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBInt.java @@ -0,0 +1,111 @@ +package com.modulus.qbar.core.primitive; + +import com.modulus.qbar.core.NaturalFunctions; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; + +/** + * Class that represents the + * Q-Bar primitive value int + */ + /* + * this class was generated by the python script + * 'generate_primitives.py + * @PythonGenerated + */ +public class QBInt extends QBPrimitive{ + /** + * + */ + private static final long serialVersionUID = 1L; + private int value; + public final static QBStruct struct = new QBStruct("Integer", QBPrimitive.struct) { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public QBObject newInstance() { + // TODO Auto-generated method stub + return null; + } + }; + public static final QBInt TRUE = new QBInt(1); + public static final QBInt FALSE = new QBInt(0); + static{ + struct.set("and", NaturalFunctions.AND); + struct.set("or", NaturalFunctions.OR); + struct.set("xor", NaturalFunctions.XOR); + + // just adding these to speed up the process, after all + // integers must run as fast as possible, but these would + // still be in the super struct. + struct.set("+", NaturalFunctions.ADDI); + struct.set("-", NaturalFunctions.SUBI); + struct.set("*", NaturalFunctions.MULI); + struct.set("%", NaturalFunctions.MODI); + struct.set("/", NaturalFunctions.DIV); + struct.set("div", NaturalFunctions.DIVI); + struct.set("^", NaturalFunctions.POWI); + + struct.set(">", NaturalFunctions.GT); + struct.set("<", NaturalFunctions.LT); + struct.set("==", NaturalFunctions.EQ); + struct.set("!=", NaturalFunctions.NE); + struct.set(">=", NaturalFunctions.GTE); + struct.set("<=", NaturalFunctions.LTE); + + struct.set("add", NaturalFunctions.ADDI); + struct.set("subtract", NaturalFunctions.SUBI); + struct.set("multiply", NaturalFunctions.MULI); + struct.set("modulo", NaturalFunctions.MODI); + struct.set("divide", NaturalFunctions.DIV); + struct.set("power", NaturalFunctions.POWI); + struct.set("divideInteger", NaturalFunctions.DIVI); + + struct.set("greaterThan", NaturalFunctions.GT); + struct.set("lessThan", NaturalFunctions.LT); + struct.set("equalTo", NaturalFunctions.EQ); + struct.set("notEqualTo", NaturalFunctions.NE); + struct.set("greaterThanOrEqualTo", NaturalFunctions.GTE); + struct.set("lessThanOrEqualTo", NaturalFunctions.LTE); + } + /** + * Constructs a new QBarInt that wraps + * the type int + */ + public QBInt( int value ){ + super(struct); + this.value = value; + } + + @Override + public int intValue(){ + return (int) this.value; + } + + @Override + public double doubleValue(){ + return (double) this.value; + } + + @Override + public char charValue(){ + return (char) this.value; + } + + public String toString(){ + return Integer.toString(value); + } + + public Number getValueNumber(){ + return value; + } + + @Override + public Object getWrapped(){ + return value; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBPrimitive.java b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBPrimitive.java new file mode 100644 index 0000000..d5a7070 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/core/primitive/QBPrimitive.java @@ -0,0 +1,122 @@ +package com.modulus.qbar.core.primitive; + +import java.math.BigDecimal; + +import com.modulus.qbar.core.NaturalFunctions; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.exceptions.ExecutionException; + +/** + * Class that describes very natural and primitive + * objects in the Q-Bar language. + * + * @author jrahm + * + */ +public abstract class QBPrimitive extends QBObject implements Comparable<QBPrimitive>{ + /** + * + */ + private static final long serialVersionUID = -3882060949668211170L; + public static final QBStruct struct = new QBStruct("Primitive") { + + /** + * + */ + private static final long serialVersionUID = -93702214222801325L; + + @Override + public QBObject newInstance() { + // TODO Auto-generated method stub + return null; + } + }; + + static{ + struct.set("+", NaturalFunctions.ADD); + struct.set("-", NaturalFunctions.SUB); + struct.set("*", NaturalFunctions.MUL); + struct.set("%", NaturalFunctions.MOD); + struct.set("/", NaturalFunctions.DIV); + struct.set("^", NaturalFunctions.POW); + + struct.set(">", NaturalFunctions.GT); + struct.set("<", NaturalFunctions.LT); + struct.set("==", NaturalFunctions.EQ); + struct.set("!=", NaturalFunctions.NE); + struct.set(">=", NaturalFunctions.GTE); + struct.set("<=", NaturalFunctions.LTE); + + struct.set("add", NaturalFunctions.ADD); + struct.set("subtract", NaturalFunctions.SUB); + struct.set("multiply", NaturalFunctions.MUL); + struct.set("modulo", NaturalFunctions.MOD); + struct.set("divide", NaturalFunctions.DIV); + struct.set("power", NaturalFunctions.POW); + + struct.set("greateThan", NaturalFunctions.GT); + struct.set("lessThan", NaturalFunctions.LT); + struct.set("equalTo", NaturalFunctions.EQ); + struct.set("notEqualTo", NaturalFunctions.NE); + struct.set("greaterThanOrEqualTo", NaturalFunctions.GTE); + struct.set("lessThanOrEqualTo", NaturalFunctions.LTE); + + struct.set("as", NaturalFunctions.AS); + } + /** + * Constructs a simple new QBPrimitive object + */ + public QBPrimitive() { + super( struct ); + } + + protected QBPrimitive( QBStruct struct ){ + super(struct); + } + + @Override + public void set(String str, QBObject obj){ + throw new ExecutionException("Attempting to assign primitive member"); + } + + protected void setSafe( String str, QBObject obj ){ + super.set(str, obj); + } + + /** + * Gets the integer value of this primitive value + * @return the integer value of this primitive value; + */ + public abstract int intValue(); + + /** + * Gets the double value of this primitive value + * @return the double value of this primitive value + */ + public abstract double doubleValue(); + + /** + * Gets the char value of this primitive value + * @return the char value of this primitive value + */ + public abstract char charValue(); + + /** + * Returns the value of this QBPrimitive as a number + * @return the value of this QBPrimitive as a number + */ + public abstract Number getValueNumber(); + + @Override + public int compareTo(QBPrimitive other){ + return (int) Math.signum( this.getValueNumber().doubleValue() - other.getValueNumber().doubleValue() ); + } + + public static QBPrimitive forNumber(Number num){ + if( num instanceof Double || num instanceof Float || num instanceof BigDecimal ) + return new QBDouble(num.doubleValue()); + + return new QBInt(num.intValue()); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedClass.java b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedClass.java new file mode 100644 index 0000000..01d6a9f --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedClass.java @@ -0,0 +1,68 @@ +package com.modulus.qbar.integration; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; + +public class QBWrappedClass extends QBStruct{ + private static final long serialVersionUID = -4889124451749124731L; + private static final Map<Class<?>, QBWrappedClass> wrappedClasses = new HashMap<Class<?>, QBWrappedClass>(); + + public static QBStruct wrapClass(Class<?> clazz, QBNamespace nmspce){ + QBWrappedClass ret = wrappedClasses.get(clazz); + + + if(ret == null){ + ret = new QBWrappedClass(clazz, nmspce); + wrappedClasses.put(clazz, ret); + } + + return ret; + } + + private QBWrappedClass(Class<?> toWrap, QBNamespace nmspce) { + super(""); + String name = toWrap.getName(); + this.setName(name.substring(name.lastIndexOf('.') + 1)); + + Method[] methods = toWrap.getMethods(); + + for( Method m : methods){ + int mod = m.getModifiers(); + int argc = m.getParameterTypes().length; + if(!Modifier.isStatic(mod)){ + argc += 1; + } + + QBFunction func = new QBWrappedMethod(toWrap, m.getName(), argc); + + + if(Modifier.isStatic(mod)){ + String methodName = m.getName(); + + if(methodName.startsWith("new$0x20")){ + methodName = methodName.substring(8); + methodName = "new$0x20" + methodName; + } + + nmspce.set(methodName, func); + } else { + this.set(m.getName(), func); + } + } + + Constructor<?>[] constructors = toWrap.getConstructors(); + if(constructors.length > 0){ + QBWrappedConstructor toAdd = new QBWrappedConstructor(constructors[0].getParameterTypes().length, toWrap); + nmspce.set( "new$0x20" + this.getName(), toAdd); + } + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedConstructor.java new file mode 100644 index 0000000..354ba2a --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedConstructor.java @@ -0,0 +1,53 @@ +package com.modulus.qbar.integration; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; + +public class QBWrappedConstructor extends QBFunction{ + /** + * + */ + private static final long serialVersionUID = -3025785234264500875L; + private transient Constructor<?> wrapped; + + private Class<?> clazz; + + public QBWrappedConstructor(int argc, Constructor<?> wrapped) { + super(argc); + this.wrapped = wrapped; + } + + public QBWrappedConstructor(int argc, Class<?> clazz){ + super(argc); + this.clazz = clazz; + } + + private void setup(){ + Constructor<?>[] constructors = this.clazz.getConstructors(); + this.wrapped = constructors[0]; + } + + @Override + public QBObject execute(QBObject[] args) { + try{ + if(wrapped == null) + setup(); + + Object[] objs = new Object[args.length]; + + for( int i = 0;i < objs.length; i ++){ + objs[i] = args[i].getWrapped(); + } + + Object ret = wrapped.newInstance( objs ); + return QBWrappedObject.wrap(ret); + } catch( Exception e ){ + throw new RuntimeException("Failed to Create new Instance of " + wrapped.getClass()); + } + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedMethod.java b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedMethod.java new file mode 100644 index 0000000..479e504 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedMethod.java @@ -0,0 +1,95 @@ +package com.modulus.qbar.integration; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; + +public class QBWrappedMethod extends QBFunction{ + private transient Method wrapped; + private boolean isStatic; + + private String methodName; + private Class<?> clazz; + + public QBWrappedMethod(Method toWrap) { + super(toWrap.getParameterTypes().length); + this.wrapped = toWrap; + + isStatic = Modifier.isStatic(toWrap.getModifiers()); + + if(!isStatic){ + this.setArgc(this.getArgc() + 1); + } + } + + public QBWrappedMethod( Class<?> clazz, String methodName, int argc ){ + super( argc ); + + this.clazz = clazz; + this.methodName = methodName; + } + + // since java is sometimes annoying and will not let you serialize Methods, + // we need to send the information and generate them on the fly + private void setup(){ + Method[] methods = this.clazz.getMethods(); + + for(Method method : methods ){ + if(method.getName().equals(methodName)){ + this.wrapped = method; + break; + } + } + + isStatic = Modifier.isStatic(this.wrapped.getModifiers()); + } + + @Override + public QBObject execute(QBObject[] args){ + try { + if(wrapped == null) + setup(); + + if(isStatic){ + return executeStatic(args); + } else{ + Object[] objs = new Object[args.length - 1]; + Object caller =args[args.length - 1].getWrapped(); + + for( int i = 0;i < args.length-1; i++){ + // System.out.println("args["+i+"]: " + args[i] + " wrap: " + args[i].getWrapped()); + objs[i] = args[i].getWrapped(); + } + + // System.out.println("Method " + wrapped + "\nargs: " + Arrays.toString(objs) + "\nargs2: " + Arrays.toString(args)); + return QBWrappedObject.wrap(wrapped.invoke(caller, objs)); + } + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + return null; + } + + private QBObject executeStatic(QBObject[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{ + Object[] objs = new Object[args.length]; + for( int i = 0;i < objs.length; i++){ + objs[i] = args[i].getWrapped(); + } + // System.out.println(Arrays.toString(objs) + " " + this.getArgc() + "\n\t" + wrapped); + + return QBWrappedObject.wrap(wrapped.invoke(null, objs)); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedObject.java b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedObject.java new file mode 100644 index 0000000..29a5641 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedObject.java @@ -0,0 +1,160 @@ +package com.modulus.qbar.integration; + +import java.util.Arrays; +import java.util.List; + +import com.modulus.common.collections.MArrays; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.primitive.QBChar; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; +import com.modulus.qbar.lang.QBArrayList; +import com.modulus.qbar.lang.QBList; +import com.modulus.qbar.lang.QBMaybe; +public class QBWrappedObject extends QBObject{ + /** + * + */ + private static final long serialVersionUID = 400259956418357800L; + private Object wrapped; + + private QBWrappedObject(Object wrapped) { + super( QBWrappedClass.wrapClass(wrapped.getClass(), QBInterpreter.instance().getGlobalNamespace()) ); + this.wrapped = wrapped; + } + + public Object getWrapped(){ + return wrapped; + } + + public static QBObject wrap(Object invoke) { + if(invoke == null){ + return new QBMaybe.Maybe(null); + } + + if(invoke instanceof QBObject) { + return (QBObject) invoke; + } + + if ( invoke instanceof Object[] ){ + return fromList( + Arrays.asList((Object[]) invoke) + ); + } + + if ( invoke instanceof byte[] ){ + List<Byte> lst = MArrays.asList((byte[]) invoke); + return fromList( + lst + ); + } + + if ( invoke instanceof int[] ){ + return fromList( + MArrays.asList((int[]) invoke) + ); + } + + if ( invoke instanceof short[] ){ + return fromList( + MArrays.asList((short[]) invoke) + ); + } + + if ( invoke instanceof long[] ){ + return fromList( + MArrays.asList((long[]) invoke) + ); + } + + if ( invoke instanceof boolean[] ){ + return fromList( + MArrays.asList((boolean[]) invoke) + ); + } + + if ( invoke instanceof char[] ){ + return fromList( + MArrays.asList((char[]) invoke) + ); + } + + if ( invoke instanceof double[] ){ + return fromList( + MArrays.asList((double[]) invoke) + ); + } + + if ( invoke instanceof float[] ){ + return fromList( + MArrays.asList((float[]) invoke) + ); + } + + if( invoke instanceof List<?> ){ + return fromList( (List<?>) invoke ); + } + + if(invoke instanceof Double || invoke instanceof Float){ + return new QBDouble(((Number) invoke).doubleValue()); + } + + if(invoke instanceof Number){ + return new QBInt(((Number) invoke).intValue()); + } + + if(invoke instanceof Boolean){ + return new QBInt(((Boolean) invoke) ? 1 : 0); + } + + if(invoke instanceof Character){ + return new QBChar((Character)invoke); + } + + return new QBWrappedObject(invoke); + } + + public static long timeSpent = 0; + private static QBObject fromList(final List<?> invoke) { + QBList tmp = new QBList() { + + @Override + public double size() { + return invoke.size(); + } + + @Override + public void remove(QBObject obj) { + invoke.remove(obj); + } + + @Override + public QBList realSubList(int off, int len) { + return (QBList) QBWrappedObject.wrap( invoke.subList(off, off+len) ); + } + + @Override + public void insert(int idx, QBObject obj) { + } + + @Override + public QBObject get(int idx) { + return QBWrappedObject.wrap( invoke.get(idx) ); + } + + @Override + public QBObject add(QBObject obj) { + // TODO Auto-generated method stub + return null; + } + }; + // timeSpent += (t2 - t1); + return tmp; + } + + public String toString(){ + return wrapped.toString(); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedUtilityNamespace.java b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedUtilityNamespace.java new file mode 100644 index 0000000..ce14bb2 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/integration/QBWrappedUtilityNamespace.java @@ -0,0 +1,20 @@ +package com.modulus.qbar.integration; + +import com.modulus.qbar.core.QBUtilityNamespace; + +public class QBWrappedUtilityNamespace extends QBUtilityNamespace{ + private static final long serialVersionUID = -2579384501097845702L; + private String name; + + public QBWrappedUtilityNamespace(String name){ + this.name = name; + } + @Override + public String getName() { + return name; + } + + @Override + public void construct() { + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/IfThenElseFunction.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/IfThenElseFunction.java new file mode 100644 index 0000000..8efbc5e --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/IfThenElseFunction.java @@ -0,0 +1,41 @@ +package com.modulus.qbar.lang; + +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.ByteOperation; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class IfThenElseFunction extends QBFunction { + /** + * + */ + private static final long serialVersionUID = 6694512700264765780L; + private ByteOperation[] ifPart, thenPart, elsePart; + + + public IfThenElseFunction(ByteOperation[] ifPart, + ByteOperation[] thenPart, ByteOperation[] elsePart) { + super(0); + this.ifPart = ifPart; + this.thenPart = thenPart; + this.elsePart = elsePart; + } + + + @Override + public QBObject execute(QBObject[] args) { + Stack<QBObject> stack = QBInterpreter.instance().getStack(); + this.exec(ifPart, stack); + + if(returnedValue instanceof QBPrimitive && ((QBPrimitive) returnedValue).intValue() != 0){ + this.exec(thenPart, stack); + return returnedValue; + } else{ + this.exec(elsePart, stack); + return returnedValue; + } + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/ListConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/ListConstructor.java new file mode 100644 index 0000000..2a89159 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/ListConstructor.java @@ -0,0 +1,17 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; + +public abstract class ListConstructor extends QBFunction{ + + public ListConstructor() { + super(0); + } + + public QBList execute(QBObject[] args){ + return makeList(); + } + + protected abstract QBList makeList(); +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayList.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayList.java new file mode 100644 index 0000000..c7ef64a --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayList.java @@ -0,0 +1,98 @@ +package com.modulus.qbar.lang; + +import java.util.ArrayList; +import java.util.List; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; + +public class QBArrayList extends QBList{ + private List<QBObject> values = new ArrayList<QBObject>(); + + public final static QBStruct arrayListStruct = new QBStruct("ArrayList"); + public static final QBFunction APPEND = new QBFunction(2) { + + @Override + public QBObject execute(QBObject[] args) { + QBArrayList lst = (QBArrayList)args[1]; + + return lst.append(args[0]); + } + }; + + static{ + arrayListStruct.addSuperStruct(QBList.list); + arrayListStruct.set("++", APPEND); + } + + + public QBArrayList(QBObject[] objs){ + super(arrayListStruct); + for( QBObject obj : objs ) + values.add(obj); + } + + public QBArrayList(QBObject[] objs, QBStruct struct){ + super(struct); + for( QBObject obj : objs ) + values.add(obj); + } + + public QBArrayList() { + this( new QBObject[]{} ); + } + + public void insert(int index, QBObject element) { + values.add(index, element); + } + + public QBObject add(QBObject e) { + values.add(e); + return this; + } + + public void remove(QBObject arg0) { + values.remove(arg0); + } + + public QBObject get(int idx){ + if(idx < 0) + return values.get(values.size()+idx); + + return values.get(idx); + } + + public double size() { + return values.size(); + } + + public QBArrayList append(QBObject obj){ + QBArrayList ret = new QBArrayList(new QBObject[]{}); + + ret.values.addAll(this.values); + + if(obj instanceof QBArrayList) + ret.values.addAll(((QBArrayList) obj).values); + + return ret; + } + + public String toString(){ + return values.toString(); + } + + public Object getWrapped(){ + return values; + } + + @Override + public QBList realSubList(int off, int len) { + QBArrayList ret = new QBArrayList(); + + for( int i = off, a = 0; a < len;i ++, a ++) + ret.add( this.get(i) ); + + return ret; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayListConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayListConstructor.java new file mode 100644 index 0000000..a67e3a8 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBArrayListConstructor.java @@ -0,0 +1,29 @@ +package com.modulus.qbar.lang; + +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.ByteOperation; + +public class QBArrayListConstructor extends ListConstructor{ + private ByteOperation[][] expressions; + + + public QBArrayListConstructor(ByteOperation[][] exp){ + this.expressions = exp; + } + @Override + protected QBList makeList() { + QBObject[] objs = new QBObject[expressions.length]; + Stack<QBObject> stack = QBInterpreter.instance().getStack(); + + for(int i = 0;i < expressions.length;i++){ + this.exec( expressions[i], stack); + objs[i] = returnedValue; + } + + QBList arr = new QBArrayList(objs); + return arr; + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionList.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionList.java new file mode 100644 index 0000000..1af40ca --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionList.java @@ -0,0 +1,54 @@ +package com.modulus.qbar.lang; + +import java.util.HashMap; +import java.util.Map; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.primitive.QBInt; + +public class QBFunctionList extends QBList{ + private static final long serialVersionUID = -6236925720933913879L; + private Map<Integer, QBObject> listPart = new HashMap<Integer, QBObject>(); + private QBFunction func; + + public QBFunctionList(QBFunction func){ + this.func = func; + } + + @Override + public QBObject add(QBObject obj) { + return this; + } + + @Override + public void remove(QBObject obj) { + + } + + @Override + public QBObject get(int idx) { + QBObject tmp = listPart.get(idx); + + if(tmp == null) + listPart.put(idx, tmp = func.execute(new QBObject[]{new QBInt(idx), this})); + + return tmp; + } + + @Override + public double size() { + return Double.POSITIVE_INFINITY; + } + + @Override + public void insert(int idx, QBObject obj) { + listPart.put(idx, obj); + } + + @Override + public QBList realSubList(int off, int len) { + throw new RuntimeException("Sub-list type not supported for FunctionList."); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListConstructor.java new file mode 100644 index 0000000..cb0a626 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListConstructor.java @@ -0,0 +1,18 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBFunction; + +public class QBFunctionListConstructor extends ListConstructor{ + private static final long serialVersionUID = 5847772733369552908L; + private QBFunction func; + + public QBFunctionListConstructor(QBFunction func){ + this.func = func; + } + + @Override + protected QBList makeList() { + QBList lst = new QBFunctionList(func); + return lst; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListFunction.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListFunction.java new file mode 100644 index 0000000..80d8667 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBFunctionListFunction.java @@ -0,0 +1,66 @@ +package com.modulus.qbar.lang; + +import java.util.HashMap; +import java.util.Map; + +import com.modulus.common.collections.ArrayStack; +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.ByteOperation; + +public class QBFunctionListFunction extends QBFunction{ + private static final long serialVersionUID = 1123773383702904111L; + private ByteOperation[] command; + private String var; + private static Map<String, QBObject> namespaceTemplate = new HashMap<String,QBObject>(); + private Stack<QBNamespace> namespaceCalls = new ArrayStack<QBNamespace>(); + + public QBFunctionListFunction( ){ + super(2); + namespaceCalls.push(new QBNamespace(namespaceTemplate)); + } + + public ByteOperation[] getCommand() { + return command; + } + + public void setCommand(ByteOperation[] command) { + this.command = command; + } + + public String getVar() { + return var; + } + + public void setVar(String var) { + this.var = var; + } + + @Override + public QBObject execute(QBObject[] args){ + QBNamespace tmp = new QBNamespace(new HashMap<String, QBObject>()); + tmp.setSuper(this.getSuper()); + + namespaceCalls.push(tmp); + this.set(var, args[0]); + this.set("this", args[1]); + Stack<QBObject> stack = QBInterpreter.instance().getStack(); + + exec(command, stack); + namespaceCalls.pop(); + return returnedValue; + } + + @Override + public QBObject get(String name){ + return namespaceCalls.peek().get(name); + } + + @Override + public void set(String name, QBObject obj){ + namespaceCalls.peek().set(name, obj); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBIterator.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBIterator.java new file mode 100644 index 0000000..251e6f3 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBIterator.java @@ -0,0 +1,124 @@ +package com.modulus.qbar.lang; + +import java.util.Iterator; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBNamespace; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.primitive.QBInt; + +public abstract class QBIterator<T extends QBObject> extends QBObject implements Iterator<QBObject>{ + /** + * + */ + private static final long serialVersionUID = -8496833881500665535L; + private String variableName; + private T iterable; + + public static final QBStruct ITERATOR = new QBStruct("Iterator"); + + public static final QBFunction hasNext = new QBFunction(1){ + + /** + * + */ + private static final long serialVersionUID = -7059204966992996830L; + + @Override + public QBObject execute(QBObject[] args) { + QBObject obj = args[0]; + QBIterator iter = (QBIterator) obj; + + return iter.hasNext() ? new QBInt(1) : new QBInt(0); + } + + }; + + public static final QBFunction next = new QBFunction(1){ + + /** + * + */ + private static final long serialVersionUID = 9165087060843674645L; + + @Override + public QBObject execute(QBObject[] args) { + QBObject obj = args[0]; + + @SuppressWarnings("unchecked") + QBIterator<QBObject> iter = (QBIterator<QBObject>) obj; + + return iter.next(); + } + + }; + + static{ + ITERATOR.set("hasNext", hasNext); + ITERATOR.set("next", next); + } + + private QBNamespace variableNmspce; + + public QBIterator(T iterable) { + super(ITERATOR); + this.iterable = iterable; + } + + @Override + public QBObject get(String str){ + QBNamespace sup = this.getSuper(); + + if(sup == null) + return null; + + return sup.get(str); + } + + @Override + public void set(String str, QBObject obj){ + QBNamespace sup = this.getSuper(); + + if( this.variableName.equals(str) && sup != null) + variableNmspce.set(str, obj); + + else + super.set(str, obj); + } + + @Override + public void remove() { + throw new RuntimeException("Not Implemented"); + } + + public void setVariableName(String variableName) { + this.variableName = variableName; + } + + public String getVariableName() { + return variableName; + } + + public T getIterable() { + return iterable; + } + + protected abstract QBObject nextObject(); + + public QBObject next(){ + + QBObject ret = nextObject(); + this.set(this.getVariableName(), ret); + + return ret; + } + + public void setVariableNmspce(QBNamespace variableNmspce) { + this.variableNmspce = variableNmspce; + } + + public QBNamespace getVariableNmspce() { + return variableNmspce; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeList.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeList.java new file mode 100644 index 0000000..5f35496 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeList.java @@ -0,0 +1,92 @@ +package com.modulus.qbar.lang; + +import java.util.ArrayList; +import java.util.List; + +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class QBLazyRangeList extends QBList{ + private static final long serialVersionUID = -782755006057179634L; + private QBPrimitive startValue; + private QBPrimitive endValue; + private QBPrimitive changeValue; + + private boolean isIntegers; + private boolean isInfinite; + + //private List<QBPrimitive> items = new ArrayList<QBPrimitive>(); + + public QBLazyRangeList(QBPrimitive startValue, QBPrimitive endValue, + QBPrimitive changeValue) { + super(); + this.startValue = startValue; + this.endValue = endValue; + this.changeValue = changeValue; + + if(endValue == null) + isInfinite = true; + + if(changeValue == null) + this.changeValue = new QBInt(1); + + if(this.changeValue instanceof QBInt && this.startValue instanceof QBInt) + isIntegers = true; + + } + + @Override + public QBObject add(QBObject obj) { + return this; + } + + @Override + public void remove(QBObject obj) { + // TODO Auto-generated method stub + + } + + @Override + public QBPrimitive get(int idx) { + if(idx < 0) + idx = (int) (this.size() + idx); + + if( isIntegers ) + { + int ret = startValue.intValue() + idx * changeValue.intValue(); + if( this.isInfinite || ret <= endValue.intValue() ) + return new QBInt(ret); + else + throw new ArrayIndexOutOfBoundsException("The index: " + idx + " is out of range for " + this + "\nMax value is: " + endValue + " got " + ret); + } else{ + double ret = startValue.doubleValue() + idx * changeValue.doubleValue(); + if( this.isInfinite || ret <= endValue.doubleValue() ) + return new QBDouble(ret); + else + throw new ArrayIndexOutOfBoundsException("The index: " + idx + " is out of range for " + this + "\nMax value is: " + endValue + " got " + ret); + } + } + + @Override + public double size() { + if(isInfinite) + return Double.POSITIVE_INFINITY; + + else + return Math.abs(endValue.doubleValue() - startValue.doubleValue()) / changeValue.doubleValue() + 1; + } + + @Override + public void insert(int idx, QBObject obj) { + // TODO Auto-generated method stub + + } + + @Override + public QBList realSubList(int off, int len) { + return new QBLazyRangeList(get(off), get(off + len), changeValue); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeListConstructor.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeListConstructor.java new file mode 100644 index 0000000..5465515 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBLazyRangeListConstructor.java @@ -0,0 +1,65 @@ +package com.modulus.qbar.lang; + +import com.modulus.common.collections.Stack; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.interpreter.QBInterpreter; +import com.modulus.qbar.core.parser.ByteOperation; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; +import com.modulus.qbar.core.primitive.QBPrimitive; + +public class QBLazyRangeListConstructor extends ListConstructor{ + private static final long serialVersionUID = -3617305937103054888L; + + private ByteOperation[] start; + private ByteOperation[] second; + private ByteOperation[] end; + + public QBLazyRangeListConstructor(ByteOperation[] start, + ByteOperation[] second, ByteOperation[] end) { + super(); + this.start = start; + this.second = second; + this.end = end; + } + + @Override + protected QBList makeList() { + Stack<QBObject> stack = QBInterpreter.instance().getStack(); + + QBPrimitive startValue; + if(start == null){ + startValue = null; + } else{ + exec( start, stack ); + startValue = (QBPrimitive) returnedValue; + } + + QBPrimitive secondValue; + if(second == null){ + secondValue = null; + } else { + exec( second, stack ); + secondValue = (QBPrimitive) returnedValue; + } + + QBPrimitive endValue; + if(end == null){ + endValue = null; + } else{ + exec( end, stack ); + endValue = (QBPrimitive) returnedValue; + } + + double change = secondValue == null ? 1 : secondValue.doubleValue() - startValue.doubleValue(); + + QBPrimitive changeValue; + if(change % 1 == 0 && startValue instanceof QBInt) + changeValue = new QBInt((int)change); + else + changeValue = new QBDouble(change); + + return new QBLazyRangeList(startValue, endValue, changeValue); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBList.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBList.java new file mode 100644 index 0000000..8e3ed8f --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBList.java @@ -0,0 +1,160 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.parser.QBExpressionParser; +import com.modulus.qbar.core.primitive.QBDouble; +import com.modulus.qbar.core.primitive.QBInt; + +public abstract class QBList extends QBObject implements Cloneable{ + /** + * + */ + private static final long serialVersionUID = -3820130303027533210L; + + static final public QBStruct list = new QBStruct("list"); + + static final public QBFunction ADD = new QBFunction(2) { + /** + * + */ + private static final long serialVersionUID = 1966242605460532062L; + + @Override + public QBObject execute(QBObject[] args) { + QBList ths = (QBList)args[1]; + ths.add(args[0]); + return ths; + } + }; + + static final public QBFunction INSERT = new QBFunction(3) { + /** + * + */ + private static final long serialVersionUID = -4254176176696884954L; + + @Override + public QBObject execute(QBObject[] args) { + QBList ths = (QBList)args[2]; + ths.insert( ((QBInt)args[1]).intValue(), args[0] ); + return ths; + } + }; + + static final public QBFunction REMOVE = new QBFunction(2) { + + /** + * + */ + private static final long serialVersionUID = -5952990904494730121L; + + @Override + public QBObject execute(QBObject[] args) { + QBList ths = (QBList)args[1]; + ths.remove( args[0] ); + return ths; + } + }; + + static final public QBFunction GET = new QBFunction(2) { + + /** + * + */ + private static final long serialVersionUID = -4826771802410960653L; + + @Override + public QBObject execute(QBObject[] args) { + QBList ths = (QBList)args[1]; + return ths.get(((QBInt) args[0]).intValue()); + } + }; + + static final public QBFunction ITERATOR = new QBFunction(2) { + + /** + * + */ + private static final long serialVersionUID = 3915900913102253534L; + + @Override + public QBObject execute(QBObject[] args) { + QBIterator<QBList> ret = new QBListIterator( (QBList)args[0] ); + return ret; + } + }; + + static final public QBFunction SUBLIST = new QBFunction(3) { + + /** + * + */ + private static final long serialVersionUID = 3915900913102253534L; + + @Override + public QBObject execute(QBObject[] args) { + QBList ths = (QBList) args[2]; + int off = ((QBInt) args[0]).intValue(); + int len = ((QBInt) args[1]).intValue(); + + return new QBSubList(ths, off, len); + } + }; + + + public static void init(){ + list.set("add", ADD); + list.set("remove", REMOVE); + list.set("insert", INSERT); + list.set("get", GET); + + list.set("#", GET); + list.set("+<", ADD); + list.set("-<", REMOVE); + + list.set("iterator", ITERATOR); + list.set("subList", SUBLIST); + + QBExpressionParser.mapOp("#", 9); + QBExpressionParser.mapOp("+<", 1024); + QBExpressionParser.mapOp("-<", 1024); + } + + public QBList() { + super(list); + } + + public QBList(QBStruct struct) { + super(struct); + } + + @Override + public QBObject get(String name){ + if(name.equals("length")){ + double size = size(); + + if( Double.isInfinite(size) || Double.isNaN(size) || size %1 != 0) + return new QBDouble(size()); + + return new QBInt((int)size()); + } + + return super.get(name); + } + + abstract public QBList realSubList( int off, int len ); + + abstract public QBObject add(QBObject obj); + + abstract public void remove(QBObject obj); + + abstract public QBObject get(int idx); + + abstract public double size(); + + abstract public void insert(int idx, QBObject obj); + +// abstract public QBList concat( QBList other ); +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListFactory.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListFactory.java new file mode 100644 index 0000000..99a5269 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListFactory.java @@ -0,0 +1,5 @@ +package com.modulus.qbar.lang; + +public class QBListFactory { + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListIterator.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListIterator.java new file mode 100644 index 0000000..97a4254 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBListIterator.java @@ -0,0 +1,30 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBObject; + +public class QBListIterator extends QBIterator<QBList> { + private static final long serialVersionUID = 8306618418948706270L; + int index = 0;; + public QBListIterator(QBList lst){ + super(lst); + + if(lst == null) + throw new RuntimeException("How the Hell is this NULL?"); + } + + @Override + public boolean hasNext() { + QBList iterable = this.getIterable(); + return index < iterable.size(); + } + + @Override + protected QBObject nextObject() { + QBList lst = this.getIterable(); + + QBObject ret = lst.get(index ++); + + return ret; + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMath.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMath.java new file mode 100644 index 0000000..33ae016 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMath.java @@ -0,0 +1,243 @@ +package com.modulus.qbar.lang; + +public class QBMath { + public static double abs(double o0){ + return Math.abs(o0); + } + /** + *@see Math#sin + */ + public static double sin(double o0){ + return Math.sin(o0); + } + /** + *@see Math#cos + */ + public static double cos(double o0){ + return Math.cos(o0); + } + /** + *@see Math#tan + */ + public static double tan(double o0){ + return Math.tan(o0); + } + /** + *@see Math#atan2 + */ + public static double atan2(double o0, double o1){ + return Math.atan2(o0, o1); + } + /** + *@see Math#sqrt + */ + public static double sqrt(double o0){ + return Math.sqrt(o0); + } + /** + *@see Math#log + */ + public static double log(double o0){ + return Math.log(o0); + } + /** + *@see Math#log10 + */ + public static double log10(double o0){ + return Math.log10(o0); + } + /** + *@see Math#pow + */ + public static double pow(double o0, double o1){ + return Math.pow(o0, o1); + } + /** + *@see Math#exp + */ + public static double exp(double o0){ + return Math.exp(o0); + } + /** + *@see Math#min + */ + public static double min(double o0, double o1){ + return Math.min(o0, o1); + } + /** + *@see Math#max + */ + public static double max(double o0, double o1){ + return Math.max(o0, o1); + } + /** + *@see Math#scalb + */ + public static double scalb(double o0, int o1){ + return Math.scalb(o0, o1); + } + /** + *@see Math#getExponent + */ + public static int getExponent(double o0){ + return Math.getExponent(o0); + } + /** + *@see Math#signum + */ + public static double signum(double o0){ + return Math.signum(o0); + } + /** + *@see Math#asin + */ + public static double asin(double o0){ + return Math.asin(o0); + } + /** + *@see Math#acos + */ + public static double acos(double o0){ + return Math.acos(o0); + } + /** + *@see Math#atan + */ + public static double atan(double o0){ + return Math.atan(o0); + } + /** + *@see Math#toRadians + */ + public static double toRadians(double o0){ + return Math.toRadians(o0); + } + /** + *@see Math#toDegrees + */ + public static double toDegrees(double o0){ + return Math.toDegrees(o0); + } + /** + *@see Math#cbrt + */ + public static double cbrt(double o0){ + return Math.cbrt(o0); + } + /** + *@see Math#IEEEremainder + */ + public static double IEEEremainder(double o0, double o1){ + return Math.IEEEremainder(o0, o1); + } + /** + *@see Math#ceil + */ + public static double ceil(double o0){ + return Math.ceil(o0); + } + /** + *@see Math#floor + */ + public static double floor(double o0){ + return Math.floor(o0); + } + /** + *@see Math#rint + */ + public static double rint(double o0){ + return Math.rint(o0); + } + /** + *@see Math#round + */ + public static long round(double o0){ + return Math.round(o0); + } + /** + *@see Math#random + */ + public static double random(){ + return Math.random(); + } + /** + *@see Math#ulp + */ + public static double ulp(double o0){ + return Math.ulp(o0); + } + /** + *@see Math#ulp + */ + public static float ulp(float o0){ + return Math.ulp(o0); + } + /** + *@see Math#sinh + */ + public static double sinh(double o0){ + return Math.sinh(o0); + } + /** + *@see Math#cosh + */ + public static double cosh(double o0){ + return Math.cosh(o0); + } + /** + *@see Math#tanh + */ + public static double tanh(double o0){ + return Math.tanh(o0); + } + /** + *@see Math#hypot + */ + public static double hypot(double o0, double o1){ + return Math.hypot(o0, o1); + } + /** + *@see Math#expm1 + */ + public static double expm1(double o0){ + return Math.expm1(o0); + } + /** + *@see Math#log1p + */ + public static double log1p(double o0){ + return Math.log1p(o0); + } + /** + *@see Math#copySign + */ + public static double copySign(double o0, double o1){ + return Math.copySign(o0, o1); + } + /** + *@see Math#nextAfter + */ + public static double nextAfter(double o0, double o1){ + return Math.nextAfter(o0, o1); + } + /** + *@see Math#nextUp + */ + public static double nextUp(double o0){ + return Math.nextUp(o0); + } + + /** + * returns PI + */ + public static double getPI(){ + return Math.PI; + } + + /** + * returns E + */ + public static double getE(){ + return Math.E; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMaybe.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMaybe.java new file mode 100644 index 0000000..c0f4a0c --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBMaybe.java @@ -0,0 +1,59 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.exceptions.ExecutionException; +import com.modulus.qbar.integration.QBWrappedObject; +public class QBMaybe { + public static class Maybe extends QBObject{ + + public static final QBStruct struct = new QBStruct("Maybe"); + + static{ + struct.set("getValue", new QBFunction(1){ + @Override + public QBObject execute(QBObject[] args) { + Maybe ths = (Maybe)args[args.length-1]; + return QBWrappedObject.wrap(ths.getValue()); + } + }); + + struct.set("isNull", new QBFunction(1){ + @Override + public QBObject execute(QBObject[] args) { + Maybe ths = (Maybe)args[args.length-1]; + return QBWrappedObject.wrap(ths.isNull()); + } + }); + } + + public Maybe(QBObject value) { + super(struct); + this.value = value; + } + + private QBObject value; + + + public QBObject getValue(){ + if(isNull()){ + throw new ExecutionException("Attempted te get value of Null Type Maybe!"); + } + + return value; + } + + public boolean isNull(){ + return value == null; + } + } + + public static QBObject new$0x20Maybe(QBObject obj){ + return new Maybe(obj); + } + + public static QBObject new$0x20Null(){ + return new Maybe(null); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBString.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBString.java new file mode 100644 index 0000000..4e931f8 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBString.java @@ -0,0 +1,111 @@ +package com.modulus.qbar.lang; + +import java.util.HashMap; +import java.util.Map; + +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.QBStruct; +import com.modulus.qbar.core.exceptions.ParseException; +import com.modulus.qbar.core.primitive.QBChar; + +public class QBString extends QBArrayList { + + public static final QBStruct string = new QBStruct("String", QBList.list){ + + }; + + private static Map<String, String> escapes = new HashMap<String, String>(); + + static{ + string.addSuperStruct(QBArrayList.arrayListStruct); + + escapes.put("\\n", "\n"); + escapes.put("\\\\", "\\"); + escapes.put("\\r", "\r"); + escapes.put("\\t", "\t"); + escapes.put("\\\"", "\""); + escapes.put("\\'", "'"); + } + + public QBString(QBChar[] objs) { + super(objs, string); + } + + public QBString(String str, boolean parse){ + this( dynamicCast(str,parse) ); + } + + @Override + public String getWrapped(){ + StringBuffer buf = new StringBuffer(); + + for(int i = 0;i < this.size();i++) + buf.append( this.get(i) ); + + return buf.toString(); + } + + private static QBChar[] dynamicCast(String str, boolean parse){ + if(parse) + str = parseString(str); + + char[] chars = str.toCharArray(); + QBChar[] chars2 = new QBChar[chars.length]; + + for(int i =0 ;i < chars.length;i++) + chars2[i] = new QBChar(chars[i]); + + return chars2; + } + + public String toString(){ + return this.getWrapped(); + } + + @Override + public QBArrayList append(QBObject obj){ + String str1 = this.toString(); + String str2 = obj.toString(); + + return new QBString(str1 + str2, false); + } + + @Override + public QBObject add(QBObject obj){ + String str = obj.toString(); + + for(int i = 0;i < str.length();i++){ + super.add( new QBChar(str.charAt(i)) ); + } + + return this; + } + + private static String parseString(String str){ + StringBuffer buf = new StringBuffer(); + boolean escaped = false; + for( int i = 0;i < str.length();i ++){ + if(str.startsWith("\\", i)){ + for ( String key : escapes.keySet() ){ + // System.out.printf("str.startsWith( %s, %s )\n", key, i); + if( str.startsWith(key, i) ){ + buf.append( escapes.get(key) ); + i++; + + escaped = true; + break; + } + } + } + + if(!escaped){ + buf.append(str.charAt(i)); + } else { + escaped = false; + } + } + + return buf.toString(); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSubList.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSubList.java new file mode 100644 index 0000000..45e9a92 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSubList.java @@ -0,0 +1,77 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBObject; + +public class QBSubList extends QBList { + private static final long serialVersionUID = 8841750568883987599L; + private QBList original; + private boolean originalIsOriginal = true; + + private int offset; + private int length; + + public QBSubList(QBList original, int offset, int length) { + super(); + this.original = original; + this.offset = offset; + this.length = length; + } + + private void checkOriginal(){ + if(originalIsOriginal){ + original = original.realSubList(offset, length); + originalIsOriginal = false; + } + } + + @Override + public QBObject add(QBObject obj) { + checkOriginal(); + return original.add(obj); + } + + @Override + public void remove(QBObject obj) { + checkOriginal(); + original.remove(obj); + } + + @Override + public QBObject get(int idx) { + if(originalIsOriginal) { + return original.get(idx + offset); + } else { + return original.get(idx); + } + } + + @Override + public double size() { + if( originalIsOriginal ) + return this.length; + return original.size(); + } + + @Override + public void insert(int idx, QBObject obj) { + checkOriginal(); + original.insert(idx, obj); + } + + @Override + public QBList realSubList(int off, int len) { + return original.realSubList(off + offset, len); + } + + public String toString(){ + StringBuffer buf = new StringBuffer("["); + + for( int i = 0;i < this.size(); i ++) + buf.append( this.get(i).toString() + ", "); + + buf.deleteCharAt(buf.length()-1); + buf.deleteCharAt(buf.length()-1); + + return buf.toString() + "]"; + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSyntheticIterator.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSyntheticIterator.java new file mode 100644 index 0000000..0fdfed5 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSyntheticIterator.java @@ -0,0 +1,31 @@ +package com.modulus.qbar.lang; + +import com.modulus.qbar.core.QBFunction; +import com.modulus.qbar.core.QBObject; +import com.modulus.qbar.core.parser.Core; + +public class QBSyntheticIterator extends QBIterator<QBObject>{ + private static final long serialVersionUID = -1890206471197459684L; + private QBFunction next; + private QBFunction hasNext; + private QBObject wrapped; + + public QBSyntheticIterator(QBObject iterable, QBObject wrapped) { + super(iterable); + + this.wrapped = wrapped; + this.next = (QBFunction) wrapped.get("next"); + this.hasNext = (QBFunction) wrapped.get("hasNext"); + } + + @Override + public boolean hasNext() { + return Core.QBObjectIsTrue( hasNext.execute( new QBObject[]{wrapped} ) ); + } + + @Override + protected QBObject nextObject() { + return next.execute( new QBObject[]{wrapped} ); + } + +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSystem.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSystem.java new file mode 100644 index 0000000..86649a7 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/QBSystem.java @@ -0,0 +1,11 @@ +package com.modulus.qbar.lang; + +public class QBSystem { + public static int time(){ + return (int) System.currentTimeMillis(); + } + + public static void exit( int status ){ + System.exit( status ); + } +} diff --git a/project/QBarInterpreter/src/com/modulus/qbar/lang/Test.java b/project/QBarInterpreter/src/com/modulus/qbar/lang/Test.java new file mode 100644 index 0000000..6935fe1 --- /dev/null +++ b/project/QBarInterpreter/src/com/modulus/qbar/lang/Test.java @@ -0,0 +1,11 @@ +package com.modulus.qbar.lang; + +public class Test { + public static void printNum( Number num ){ + System.out.println(num); + } + + public static void printStrLn(String str){ + System.out.println(str); + } +} diff --git a/qbar-installer.tgz b/qbar-installer.tgz Binary files differnew file mode 100755 index 0000000..2ad6ad3 --- /dev/null +++ b/qbar-installer.tgz |