summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-04-02 16:34:00 +0000
committerRich Hickey <richhickey@gmail.com>2006-04-02 16:34:00 +0000
commitab3658c3f102d470c146260c87d7ea34b365126f (patch)
tree25af35169d4be51c310372e6788ef4e05ea865c7
parentad76fd174341a19ec4b311c17d3c760637d81724 (diff)
Initial commit of CLI runtime
-rw-r--r--src/cli/runtime/AFn.cs103
-rw-r--r--src/cli/runtime/AMap.cs40
-rw-r--r--src/cli/runtime/BigNum.cs225
-rw-r--r--src/cli/runtime/Box.cs28
-rw-r--r--src/cli/runtime/Cons.cs32
-rw-r--r--src/cli/runtime/DoubleNum.cs242
-rw-r--r--src/cli/runtime/FixNum.cs243
-rw-r--r--src/cli/runtime/FloatNum.cs21
-rw-r--r--src/cli/runtime/IFn.cs37
-rw-r--r--src/cli/runtime/IntegerNum.cs21
-rw-r--r--src/cli/runtime/Keyword.cs49
-rw-r--r--src/cli/runtime/Namespace.cs83
-rw-r--r--src/cli/runtime/Num.cs252
-rw-r--r--src/cli/runtime/RT.cs212
-rw-r--r--src/cli/runtime/RatioNum.cs229
-rw-r--r--src/cli/runtime/RationalNum.cs21
-rw-r--r--src/cli/runtime/RealNum.cs21
-rw-r--r--src/cli/runtime/RestFn0.cs65
-rw-r--r--src/cli/runtime/RestFn1.cs63
-rw-r--r--src/cli/runtime/RestFn2.cs59
-rw-r--r--src/cli/runtime/RestFn3.cs56
-rw-r--r--src/cli/runtime/RestFn4.cs53
-rw-r--r--src/cli/runtime/RestFn5.cs49
-rw-r--r--src/cli/runtime/Symbol.cs96
-rw-r--r--src/cli/runtime/ThreadLocalData.cs86
25 files changed, 2386 insertions, 0 deletions
diff --git a/src/cli/runtime/AFn.cs b/src/cli/runtime/AFn.cs
new file mode 100644
index 00000000..9b1cb05b
--- /dev/null
+++ b/src/cli/runtime/AFn.cs
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 4:05:37 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public class AFn : AMap , IFn
+ {
+
+virtual public Object invoke(ThreadLocalData tld) /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1) /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return throwArity();
+ }
+
+virtual public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ switch(RT.boundedLength(arglist, 5))
+ {
+ case 0:
+ return invoke(tld);
+ case 1:
+ return invoke(tld, arglist.first);
+ case 2:
+ return invoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ );
+ case 3:
+ return invoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ );
+ case 4:
+ return invoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ );
+ case 5:
+ return invoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ );
+ default:
+ return invoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , arglist.rest);
+ }
+ }
+
+protected Object throwArity()
+ {
+ throw new Exception("Wrong number of args passed");
+ }
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/AMap.cs b/src/cli/runtime/AMap.cs
new file mode 100644
index 00000000..76850122
--- /dev/null
+++ b/src/cli/runtime/AMap.cs
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 3:44:58 PM */
+
+using System;
+using System.Collections.Specialized;
+
+namespace org.clojure.runtime
+{
+
+public class AMap
+{
+
+HybridDictionary attrs;
+public static int INITIAL_SIZE = 7;
+
+public Object put(Symbol key, Object val)
+ {
+ if(attrs == null)
+ attrs = new HybridDictionary(INITIAL_SIZE);
+ attrs[key] = val;
+ return val;
+ }
+
+public Object get(Symbol key)
+ {
+ if(attrs == null)
+ return null;
+ return attrs[key];
+ }
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/BigNum.cs b/src/cli/runtime/BigNum.cs
new file mode 100644
index 00000000..629f09de
--- /dev/null
+++ b/src/cli/runtime/BigNum.cs
@@ -0,0 +1,225 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:08:33 AM */
+
+using System;
+using java.math;
+
+namespace org.clojure.runtime
+{
+
+
+public class BigNum : IntegerNum{
+public BigInteger val;
+
+override public Boolean Equals(Object arg0)
+ {
+ return arg0 != null
+ && arg0 is BigNum
+ && ((BigNum) arg0).val == val;
+ }
+
+override public int GetHashCode()
+ {
+ return val.GetHashCode();
+ }
+
+override public String ToString()
+ {
+ return val.ToString();
+ }
+
+public BigNum(long val)
+ {
+ this.val = BigInteger.valueOf(val);
+ }
+
+public BigNum(BigInteger val)
+ {
+ this.val = val;
+ }
+
+override public double doubleValue()
+ {
+ return val.doubleValue();
+ }
+
+override public float floatValue()
+ {
+ return val.floatValue();
+ }
+
+override public int intValue()
+ {
+ return val.intValue();
+ }
+
+override public long longValue()
+ {
+ return val.longValue();
+ }
+
+override public Boolean equiv(Num rhs)
+ {
+ return rhs.equivTo(val);
+ }
+
+override public Boolean equivTo(BigInteger x)
+ {
+ return x.Equals(val);
+ }
+
+override public Boolean equivTo(int x)
+ {
+ //must be outside of range of int or would be one itself
+ return false;
+ }
+
+override public Boolean equivTo(RatioNum x)
+ {
+ //wouldn't still be a RatioNum if it was an integer
+ return false;
+ }
+
+override public Boolean lt(Num rhs)
+ {
+ return rhs.gt(val);
+ }
+
+override public Boolean gt(BigInteger x)
+ {
+ return x.compareTo(val) < 0;
+ }
+
+override public Boolean gt(int x)
+ {
+ return BigInteger.valueOf(x).compareTo(val) < 0;
+ }
+
+override public Boolean gt(RatioNum x)
+ {
+ return x.numerator.lt(x.denominator.multiply(val));
+ }
+
+override public Num add(Num rhs)
+ {
+ return rhs.addTo(val);
+ }
+
+override public Num addTo(BigInteger x)
+ {
+ return Num.from(x.add(val));
+ }
+
+override public Num addTo(int x)
+ {
+ return Num.from(val.add(BigInteger.valueOf(x)));
+ }
+
+override public Num addTo(RatioNum x)
+ {
+ return x.addTo(val);
+ }
+
+override public Num subtractFrom(Num x)
+ {
+ return x.addTo(val.negate());
+ }
+
+override public Num multiplyBy(Num rhs)
+ {
+ return rhs.multiply(val);
+ }
+
+override public Num multiply(BigInteger x)
+ {
+ return Num.from(x.multiply(val));
+ }
+
+override public Num multiply(int x)
+ {
+ return Num.from(val.multiply(BigInteger.valueOf(x)));
+ }
+
+override public Num multiply(RatioNum x)
+ {
+ return x.multiply(val);
+ }
+
+override public Num divideBy(Num rhs)
+ {
+ return rhs.divide(val);
+ }
+
+override public Num divide(BigInteger n)
+ {
+ return Num.divide(n, val);
+ }
+
+override public Num divide(int n)
+ {
+ return Num.divide(BigInteger.valueOf(n), val);
+ }
+
+override public Num divide(RatioNum x)
+ {
+ return Num.divide(x.numerator, x.denominator.multiply(val));
+ }
+
+override public Object truncateDivide(ThreadLocalData tld, Num num)
+ {
+ return num.truncateBy(tld, val);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, int div)
+ {
+ return Num.truncateBigints(tld, val, BigInteger.valueOf(div));
+ }
+
+override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+ {
+ return Num.truncateBigints(tld, val, div);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+ {
+ Num q = (Num) Num.truncate(tld, div.denominator.multiply(val), div.numerator);
+ return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ }
+
+override public Num negate()
+ {
+ return Num.from(val.negate());
+ }
+
+override public Boolean minusp()
+ {
+ return val.signum() < 0;
+ }
+
+override public Boolean plusp()
+ {
+ return val.signum() > 0;
+ }
+
+
+override public Num oneMinus()
+ {
+ return Num.from(val.subtract(BIG_ONE));
+ }
+
+override public Num onePlus()
+ {
+ return Num.from(val.add(BIG_ONE));
+ }
+}
+}
+
diff --git a/src/cli/runtime/Box.cs b/src/cli/runtime/Box.cs
new file mode 100644
index 00000000..37915bd9
--- /dev/null
+++ b/src/cli/runtime/Box.cs
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:40:19 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public class Box
+{
+
+public Object val;
+
+public Box(Object val)
+ {
+ this.val = val;
+ }
+}
+}
diff --git a/src/cli/runtime/Cons.cs b/src/cli/runtime/Cons.cs
new file mode 100644
index 00000000..eec4e475
--- /dev/null
+++ b/src/cli/runtime/Cons.cs
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 11:01:29 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public class Cons : AMap
+ {
+
+public Object first;
+public Cons rest;
+
+public Cons(Object first, Cons rest)
+ {
+ this.first = first;
+ this.rest = rest;
+ }
+
+}
+
+}
diff --git a/src/cli/runtime/DoubleNum.cs b/src/cli/runtime/DoubleNum.cs
new file mode 100644
index 00000000..f3fcc278
--- /dev/null
+++ b/src/cli/runtime/DoubleNum.cs
@@ -0,0 +1,242 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:13:45 AM */
+
+using System;
+using java.math;
+
+namespace org.clojure.runtime
+{
+
+public class DoubleNum : FloatNum{
+double val;
+
+public DoubleNum(double val)
+ {
+ this.val = val;
+ }
+
+override public double doubleValue()
+ {
+ return val;
+ }
+
+override public float floatValue()
+ {
+ return (float) val;
+ }
+
+override public int intValue()
+ {
+ return (int) val;
+ }
+
+override public long longValue()
+ {
+ return (long) val;
+ }
+
+
+public Num toRational()
+ {
+ BigDecimal d = new BigDecimal(val);
+ return Num.divide(d.movePointRight(d.scale()).toBigInteger(), BIGTEN.pow(d.scale()));
+ }
+
+override public Boolean equiv(Num rhs)
+ {
+ if(rhs is RatioNum)
+ return equivTo((RatioNum) rhs);
+ return val == rhs.doubleValue();
+ }
+
+override public Boolean equivTo(BigInteger x)
+ {
+ return val == x.doubleValue();
+ }
+
+override public Boolean equivTo(int x)
+ {
+ return x == val;
+ }
+
+override public Boolean equivTo(RatioNum x)
+ {
+ return toRational().equivTo(x);
+ }
+
+override public Boolean lt(Num rhs)
+ {
+ if(rhs is RatioNum)
+ return toRational().lt(rhs);
+ return val < rhs.doubleValue();
+ }
+
+override public Boolean gt(BigInteger x)
+ {
+ return val > x.doubleValue();
+ }
+
+override public Boolean gt(int x)
+ {
+ return val > x;
+ }
+
+override public Boolean gt(RatioNum x)
+ {
+ return toRational().gt(x);
+ }
+
+override public Num add(Num rhs)
+ {
+ return Num.from(val + rhs.doubleValue());
+ }
+
+override public Num addTo(int x)
+ {
+ return Num.from(val + x);
+ }
+
+override public Num addTo(BigInteger x)
+ {
+ return Num.from(val + x.doubleValue());
+ }
+
+override public Num addTo(RatioNum x)
+ {
+ return Num.from(val + x.doubleValue());
+ }
+
+override public Num subtractFrom(Num x)
+ {
+ return Num.from(x.doubleValue() - val);
+ }
+
+override public Num multiplyBy(Num rhs)
+ {
+ return Num.from(val * rhs.doubleValue());
+ }
+
+override public Num multiply(int x)
+ {
+ return Num.from(val * x);
+ }
+
+override public Num multiply(BigInteger x)
+ {
+ return Num.from(val * x.doubleValue());
+ }
+
+override public Num multiply(RatioNum x)
+ {
+ return Num.from(val * x.doubleValue());
+ }
+
+override public Num divideBy(Num rhs)
+ {
+ return Num.from(val / rhs.doubleValue());
+ }
+
+override public Num divide(int x)
+ {
+ return Num.from(x / val);
+ }
+
+override public Num divide(BigInteger x)
+ {
+ return Num.from(x.doubleValue() / val);
+ }
+
+override public Num divide(RatioNum x)
+ {
+ return Num.from(x.doubleValue() / val);
+ }
+
+static Object truncate(ThreadLocalData tld, double n, double d)
+ {
+ double q = n / d;
+ if(q <= Int32.MaxValue && q >= Int32.MinValue)
+ {
+ return RT.setValues(tld, Num.from((int) q),
+ Num.from(n - ((int) q) * d));
+ }
+ else
+ { //bigint quotient
+ Num bq = Num.from(new BigDecimal(q).toBigInteger());
+ return RT.setValues(tld, bq,
+ Num.from(n - bq.doubleValue() * d));
+ }
+ }
+
+override public Object truncateBy(ThreadLocalData tld, BigInteger x)
+ {
+ return truncate(tld, val, x.doubleValue());
+ }
+
+override public Object truncateBy(ThreadLocalData tld, int x)
+ {
+ return truncate(tld, val, x);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, RatioNum x)
+ {
+ return truncate(tld, val, x.doubleValue());
+ }
+
+override public Object truncateDivide(ThreadLocalData tld, Num num)
+ {
+ return truncate(tld, num.doubleValue(), val);
+ }
+
+override public Num negate()
+ {
+ return Num.from(-val);
+ }
+
+override public Boolean Equals(Object arg0)
+ {
+ return arg0 != null
+ && arg0 is DoubleNum
+ &&((DoubleNum) arg0).val.Equals(val);
+ }
+
+override public int GetHashCode()
+ {
+ return val.GetHashCode();
+ }
+
+override public String ToString()
+ {
+ return val.ToString();
+ }
+
+override public Boolean minusp()
+ {
+ return val < 0;
+ }
+
+override public Boolean plusp()
+ {
+ return val > 0;
+ }
+
+override public Num oneMinus()
+ {
+ return Num.from(val - 1);
+ }
+
+override public Num onePlus()
+ {
+ return Num.from(val + 1);
+ }
+
+}
+}
diff --git a/src/cli/runtime/FixNum.cs b/src/cli/runtime/FixNum.cs
new file mode 100644
index 00000000..99750aa7
--- /dev/null
+++ b/src/cli/runtime/FixNum.cs
@@ -0,0 +1,243 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:09:27 AM */
+
+using System;
+using java.math;
+
+namespace org.clojure.runtime
+{
+
+
+public class FixNum : IntegerNum{
+public int val;
+
+override public Boolean Equals(Object arg0)
+ {
+ return arg0 != null
+ && arg0 is FixNum
+ && ((FixNum) arg0).val == val;
+ }
+
+override public int GetHashCode()
+ {
+ return val;
+ }
+
+override public String ToString()
+ {
+ return val.ToString();
+ }
+
+public FixNum(int val)
+ {
+ this.val = val;
+ }
+
+override public double doubleValue()
+ {
+ return (double) val;
+ }
+
+override public float floatValue()
+ {
+ return (float) val;
+ }
+
+override public int intValue()
+ {
+ return val;
+ }
+
+override public long longValue()
+ {
+ return (long) val;
+ }
+
+override public Boolean equiv(Num rhs)
+ {
+ return rhs.equivTo(val);
+ }
+
+override public Boolean equivTo(BigInteger x)
+ {
+ //wouldn't still be a BigInteger if it fit in int
+ return false;
+ }
+
+override public Boolean equivTo(int x)
+ {
+ return x == val;
+ }
+
+override public Boolean equivTo(RatioNum x)
+ {
+ //wouldn't still be a RatioNum if it was an integer
+ return false;
+ }
+
+override public Boolean lt(Num rhs)
+ {
+ return rhs.gt(val);
+ }
+
+override public Boolean gt(BigInteger x)
+ {
+ return x.compareTo(BigInteger.valueOf(val)) < 0;
+ }
+
+override public Boolean gt(int x)
+ {
+ return x < val;
+ }
+
+override public Boolean gt(RatioNum x)
+ {
+ return x.numerator.lt(x.denominator.multiply(val));
+ }
+
+override public Num add(Num rhs)
+ {
+ return rhs.addTo(val);
+ }
+
+override public Num addTo(BigInteger x)
+ {
+ return Num.from(x.add(BigInteger.valueOf(val)));
+ }
+
+override public Num addTo(int x)
+ {
+ return Num.from((long) x + val);
+ }
+
+override public Num addTo(RatioNum x)
+ {
+ return x.addTo(val);
+ }
+
+override public Num subtractFrom(Num x)
+ {
+ return x.addTo(-val);
+ }
+
+override public Num multiplyBy(Num rhs)
+ {
+ return rhs.multiply(val);
+ }
+
+override public Num multiply(BigInteger x)
+ {
+ return Num.from(x.multiply(BigInteger.valueOf(val)));
+ }
+
+override public Num multiply(int x)
+ {
+ return Num.from((long) x * val);
+ }
+
+override public Num multiply(RatioNum x)
+ {
+ return x.multiply(val);
+ }
+
+override public Object truncateDivide(ThreadLocalData tld, Num num)
+ {
+ return num.truncateBy(tld, val);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, int div)
+ {
+ return RT.setValues(tld, Num.from(val / div), Num.from(val % div));
+ }
+
+override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+ {
+ return Num.truncateBigints(tld, BigInteger.valueOf(val), div);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+ {
+ Num q = (Num) Num.truncate(tld, div.denominator.multiply(val), div.numerator);
+ return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ }
+
+override public Num divideBy(Num rhs)
+ {
+ return rhs.divide(val);
+ }
+
+override public Num divide(BigInteger n)
+ {
+ return Num.divide(n, BigInteger.valueOf(val));
+ }
+
+static int gcdf(int u, int v)
+ {
+ while(v != 0)
+ {
+ int r = u % v;
+ u = v;
+ v = r;
+ }
+ return u;
+ }
+
+override public Num divide(int n)
+ {
+ int gcd = gcdf(n, val);
+ if(gcd == 0)
+ return Num.ZERO;
+
+ n = n / gcd;
+ int d = val / gcd;
+ if(d == 1)
+ return Num.from(n);
+ if(d < 0)
+ {
+ n = -n;
+ d = -d;
+ }
+ return new RatioNum((IntegerNum) Num.from(n), (IntegerNum) Num.from(d));
+ }
+
+override public Num divide(RatioNum x)
+ {
+ return Num.divide(x.numerator, x.denominator.multiply(val));
+ }
+
+override public Num negate()
+ {
+ return Num.from(-val);
+ }
+
+override public Boolean minusp()
+ {
+ return val < 0;
+ }
+
+override public Boolean plusp()
+ {
+ return val > 0;
+ }
+
+override public Num oneMinus()
+ {
+ return Num.from(val - 1);
+ }
+
+override public Num onePlus()
+ {
+ return Num.from(val + 1);
+ }
+
+}
+}
diff --git a/src/cli/runtime/FloatNum.cs b/src/cli/runtime/FloatNum.cs
new file mode 100644
index 00000000..3031e4f6
--- /dev/null
+++ b/src/cli/runtime/FloatNum.cs
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:17:21 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class FloatNum : RealNum {
+
+}
+}
diff --git a/src/cli/runtime/IFn.cs b/src/cli/runtime/IFn.cs
new file mode 100644
index 00000000..e96fd902
--- /dev/null
+++ b/src/cli/runtime/IFn.cs
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 3:54:03 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+public interface IFn{
+
+Object invoke(ThreadLocalData tld) /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1) /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1, Object arg2) /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/;
+
+Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+ Cons args) /*throws Exception*/;
+
+Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/;
+}
+}
diff --git a/src/cli/runtime/IntegerNum.cs b/src/cli/runtime/IntegerNum.cs
new file mode 100644
index 00000000..7e24b1e6
--- /dev/null
+++ b/src/cli/runtime/IntegerNum.cs
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:11:55 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class IntegerNum : RationalNum {
+
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/Keyword.cs b/src/cli/runtime/Keyword.cs
new file mode 100644
index 00000000..8748cdf1
--- /dev/null
+++ b/src/cli/runtime/Keyword.cs
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 29, 2006 10:39:05 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public class Keyword : Symbol
+ {
+/**
+ * Used by Namespace.intern()
+ *
+ * @param name
+ * @param ns
+ */
+internal Keyword(String name, Namespace ns):
+ base(name, ns)
+
+ {
+ this.val = this;
+ this.fn = this;
+ }
+
+override public Object getValue(ThreadLocalData tld)
+ {
+ return this;
+ }
+
+override public Object setValue(ThreadLocalData tld, Object val)
+ {
+ throw new InvalidOperationException("Cannot set the value of a keyword");
+ }
+
+override public String ToString()
+ {
+ return ":" + name;
+ }
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/Namespace.cs b/src/cli/runtime/Namespace.cs
new file mode 100644
index 00000000..0a4acdf6
--- /dev/null
+++ b/src/cli/runtime/Namespace.cs
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 1:29:39 PM */
+
+using System;
+using System.Collections.Specialized;
+
+namespace org.clojure.runtime
+{
+
+public class Namespace
+{
+
+/**
+ * String->Namespace
+ */
+static public HybridDictionary table = new HybridDictionary();
+
+/**
+ * String->Symbol
+ */
+public HybridDictionary symbols = new HybridDictionary();
+public String name;
+
+static public Namespace globalNS = new Namespace("");
+static public Namespace keywordNS = new KeywordNamespace("keyword");
+
+class KeywordNamespace : Namespace{
+ public KeywordNamespace(String name) : base(name)
+ {
+
+ }
+ override public Symbol intern(String name)
+ {
+ Symbol sym = (Symbol) symbols[name];
+ if(sym == null)
+ symbols.Add(name, sym = new Keyword(name, this));
+ return sym;
+ }
+};
+
+Namespace(String name)
+ {
+ this.name = name;
+ table.Add(name, this);
+ }
+
+static public Namespace find(String name)
+ {
+ return (Namespace) table[name];
+ }
+
+static public Namespace findOrCreate(String name)
+ {
+ lock(table)
+ {
+ Namespace ns = find(name);
+ if(ns == null)
+ ns = new Namespace(name);
+ return ns;
+ }
+ }
+
+virtual public Symbol intern(String name)
+ {
+ lock(symbols)
+ {
+ Symbol sym = (Symbol) symbols[name];
+ if(sym == null)
+ symbols.Add(name, sym = new Symbol(name, this));
+ return sym;
+ }
+ }
+}
+}
diff --git a/src/cli/runtime/Num.cs b/src/cli/runtime/Num.cs
new file mode 100644
index 00000000..86120be1
--- /dev/null
+++ b/src/cli/runtime/Num.cs
@@ -0,0 +1,252 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:07:33 AM */
+
+using System;
+using java.math;
+
+namespace org.clojure.runtime
+{
+
+public abstract class Num : IComparable /* TODO: , IConvertible*/
+ {
+
+public static Num ZERO = from(0);
+public static Num ONE = from(1);
+
+static public Num from(int val)
+ {
+ //todo - cache a bunch of small fixnums
+ return new FixNum(val);
+ }
+
+static public Num from(double val)
+ {
+ return new DoubleNum(val);
+ }
+
+static public Num from(long val)
+ {
+ if(val <= Int32.MaxValue && val >= Int32.MinValue)
+ return from((int) val);
+ else
+ return new BigNum(val);
+ }
+
+static public Num from(BigInteger val)
+ {
+ if(val.bitLength() < 32)
+ return from(val.intValue());
+ else
+ return new BigNum(val);
+ }
+
+ internal static BigInteger BIGTEN = BigInteger.valueOf(10);
+
+static public Num from(Object x)
+ {
+ if(x is Num)
+ return (Num) x;
+ else
+ {
+ IConvertible c = x as IConvertible;
+ if(c != null)
+ {
+ switch(c.GetTypeCode())
+ {
+ case TypeCode.Int32:
+ return Num.from((Int32) x);
+ case TypeCode.Double:
+ case TypeCode.Single:
+ return Num.from(Convert.ToDouble(x));
+ case TypeCode.Int64:
+ return Num.from((Int64) x);
+ //TODO: Decimal w/o string conversion
+ case TypeCode.Decimal:
+ BigDecimal d = new BigDecimal(x.ToString());
+ return Num.divide(d.movePointRight(d.scale()).toBigInteger(),
+ BIGTEN.pow(d.scale()));
+ default:
+ return Num.from(Convert.ToInt32(x));
+ }
+ }
+ else if(x is BigInteger)
+ return Num.from((BigInteger) x);
+ else
+ throw new ArgumentException("Cannot convert argument: " + x + " to Num");
+ }
+ }
+
+
+ abstract public double doubleValue();
+
+ abstract public float floatValue();
+
+ abstract public int intValue();
+
+ abstract public long longValue();
+
+static public Num add(Object x, Object y)
+ {
+ //if(x instanceof Num && y instanceof Num)
+ //return ((Num)x).add((Num) y);
+ return Num.from(x).add(Num.from(y));
+ }
+
+abstract public Num add(Num rhs);
+
+abstract public Num addTo(int x);
+
+abstract public Num addTo(BigInteger x);
+
+abstract public Num addTo(RatioNum x);
+
+static public Num subtract(Object x, Object y)
+ {
+ return Num.from(y).subtractFrom(Num.from(x));
+ }
+
+//this double-dispatches to addTo(-self)
+abstract public Num subtractFrom(Num rhs);
+
+static public Num multiply(Object x, Object y)
+ {
+ return Num.from(x).multiplyBy(Num.from(y));
+ }
+
+abstract public Num multiplyBy(Num rhs);
+
+abstract public Num multiply(int x);
+
+abstract public Num multiply(BigInteger x);
+
+abstract public Num multiply(RatioNum x);
+
+static public Num divide(Object x, Object y)
+ {
+ return Num.from(x).divideBy(Num.from(y));
+ }
+
+abstract public Num divideBy(Num rhs);
+
+abstract public Num divide(int x);
+
+abstract public Num divide(BigInteger x);
+
+abstract public Num divide(RatioNum x);
+
+static public Object truncate(ThreadLocalData tld, Object num, Object div)
+ {
+ return Num.from(div).truncateDivide(tld, Num.from(num));
+ }
+
+abstract public Object truncateDivide(ThreadLocalData tld, Num rhs);
+
+abstract public Object truncateBy(ThreadLocalData tld, int x);
+
+abstract public Object truncateBy(ThreadLocalData tld, BigInteger x);
+
+abstract public Object truncateBy(ThreadLocalData tld, RatioNum x);
+
+static public Object truncateBigints(ThreadLocalData tld, BigInteger n, BigInteger d)
+ {
+ BigInteger[] result = n.divideAndRemainder(d);
+ return RT.setValues(tld, Num.from(result[0]), Num.from(result[1]));
+ }
+
+ internal static BigInteger BIG_ONE = BigInteger.valueOf(1);
+ internal static BigInteger BIG_ZERO = BigInteger.valueOf(0);
+
+static public Num divide(BigInteger n, BigInteger d)
+ {
+ BigInteger gcd = n.gcd(d);
+ if(gcd.Equals(BIG_ZERO))
+ return Num.ZERO;
+ n = n.divide(gcd);
+ d = d.divide(gcd);
+ if(d.Equals(BIG_ONE))
+ return Num.from(n);
+ return new RatioNum((IntegerNum) Num.from(d.signum() < 0 ? n.negate() : n),
+ (IntegerNum) Num.from(d.signum() < 0 ? d.negate() : d));
+ }
+
+static public Boolean equiv(Object x, Object y)
+ {
+ return Num.from(x).equiv(Num.from(y));
+ }
+
+abstract public Boolean equiv(Num rhs);
+
+abstract public Boolean equivTo(int x);
+
+abstract public Boolean equivTo(BigInteger x);
+
+abstract public Boolean equivTo(RatioNum x);
+
+static public Boolean lt(Object x, Object y)
+ {
+ return Num.from(x).lt(Num.from(y));
+ }
+
+static public Boolean lte(Object x, Object y)
+ {
+ Num lx = Num.from(x);
+ Num ly = Num.from(y);
+ return lx.lt(ly) || lx.equiv(ly);
+ }
+
+static public Boolean gt(Object x, Object y)
+ {
+ return Num.from(y).lt(Num.from(x));
+ }
+
+static public Boolean gte(Object x, Object y)
+ {
+ Num lx = Num.from(x);
+ Num ly = Num.from(y);
+ return ly.lt(lx) || lx.equiv(ly);
+ }
+
+abstract public Boolean lt(Num rhs);
+
+abstract public Boolean gt(int x);
+
+abstract public Boolean gt(BigInteger x);
+
+abstract public Boolean gt(RatioNum x);
+
+static public Num negate(Object x)
+ {
+ return Num.from(x).negate();
+ }
+
+abstract public Num negate();
+
+abstract public Boolean minusp();
+
+abstract public Boolean plusp();
+
+abstract public Num oneMinus();
+
+abstract public Num onePlus();
+
+public int CompareTo(Object obj)
+ {
+ Num other = Num.from(obj);
+ if(this.equiv(other))
+ return 0;
+ else if(this.lt(other))
+ return -1;
+ else
+ return 1;
+ }
+}
+}
diff --git a/src/cli/runtime/RT.cs b/src/cli/runtime/RT.cs
new file mode 100644
index 00000000..777c1299
--- /dev/null
+++ b/src/cli/runtime/RT.cs
@@ -0,0 +1,212 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 4:28:27 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public class RT
+{
+
+ static Object TRUE = true;
+ static public Object eq(Object arg1, Object arg2) {
+ return (arg1 == arg2)?TRUE:null;
+ }
+
+ static public Object eql(Object arg1, Object arg2) {
+ if(arg1 == arg2)
+ return TRUE;
+ if(arg1 == null || arg2 == null)
+ return null;
+ if(arg1 is Num
+ && arg1.GetType() == arg2.GetType()
+ && arg1.Equals(arg2))
+ return TRUE;
+ if(arg1 is Char
+ && arg2 is Char
+ && arg1.Equals(arg2))
+ return TRUE;
+ return null;
+ }
+
+ static public Object equal(Object arg1, Object arg2) {
+ if(arg1 == null)
+ return arg2 == null ? TRUE : null;
+ else if(arg2 == null)
+ return null;
+ return (eql(arg1,arg2) != null
+ || (arg1 is Cons
+ && arg2 is Cons
+ && equal(((Cons)arg1).first,((Cons)arg2).first)!=null
+ && equal(((Cons)arg1).rest,((Cons)arg2).rest)!=null))
+ ?TRUE:null;
+ }
+
+static public Cons cons(Object x, Cons y)
+ {
+ return new Cons(x, y);
+ }
+
+static public Cons list()
+ {
+ return null;
+ }
+
+static public Cons list(Object arg1)
+ {
+ return cons(arg1, null);
+ }
+
+static public Cons list(Object arg1, Object arg2)
+ {
+ return listStar(arg1, arg2, null);
+ }
+
+static public Cons list(Object arg1, Object arg2, Object arg3)
+ {
+ return listStar(arg1, arg2, arg3, null);
+ }
+
+static public Cons list(Object arg1, Object arg2, Object arg3, Object arg4)
+ {
+ return listStar(arg1, arg2, arg3, arg4, null);
+ }
+
+static public Cons list(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ {
+ return listStar(arg1, arg2, arg3, arg4, arg5, null);
+ }
+
+static public Cons listStar(Object arg1, Cons rest)
+ {
+ return cons(arg1, rest);
+ }
+
+static public Cons listStar(Object arg1, Object arg2, Cons rest)
+ {
+ return cons(arg1, cons(arg2, rest));
+ }
+
+static public Cons listStar(Object arg1, Object arg2, Object arg3, Cons rest)
+ {
+ return cons(arg1, cons(arg2, cons(arg3, rest)));
+ }
+
+static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, Cons rest)
+ {
+ return cons(arg1, cons(arg2, cons(arg3, cons(arg4, rest))));
+ }
+
+static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons rest)
+ {
+ return cons(arg1, cons(arg2, cons(arg3, cons(arg4, cons(arg5, rest)))));
+ }
+
+static public int length(Cons list)
+ {
+ int i = 0;
+ for(Cons c = list; c != null; c = c.rest)
+ {
+ i++;
+ }
+ return i;
+ }
+
+static public int boundedLength(Cons list, int limit)
+ {
+ int i = 0;
+ for(Cons c = list; c != null && i <= limit; c = c.rest)
+ {
+ i++;
+ }
+ return i;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1)
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 1;
+ tld.mvArray[0] = arg1;
+ return arg1;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2)
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 2;
+ tld.mvArray[0] = arg1;
+ tld.mvArray[1] = arg2;
+ return arg1;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3)
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 3;
+ tld.mvArray[0] = arg1;
+ tld.mvArray[1] = arg2;
+ tld.mvArray[2] = arg3;
+ return arg1;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4)
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 4;
+ tld.mvArray[0] = arg1;
+ tld.mvArray[1] = arg2;
+ tld.mvArray[2] = arg3;
+ tld.mvArray[3] = arg4;
+ return arg1;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4,
+ Object arg5)
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 5;
+ tld.mvArray[0] = arg1;
+ tld.mvArray[1] = arg2;
+ tld.mvArray[2] = arg3;
+ tld.mvArray[3] = arg4;
+ tld.mvArray[4] = arg5;
+ return arg1;
+ }
+
+static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4,
+ Object arg5, Cons args) /*throws Exception*/
+ {
+ if(tld == null)
+ tld = ThreadLocalData.get();
+ tld.mvCount = 5;
+ tld.mvArray[0] = arg1;
+ tld.mvArray[1] = arg2;
+ tld.mvArray[2] = arg3;
+ tld.mvArray[3] = arg4;
+ tld.mvArray[4] = arg5;
+ for(int i = 5; args != null && i < ThreadLocalData.MULTIPLE_VALUES_LIMIT; i++, args = args.rest)
+ {
+ tld.mvArray[i] = args.first;
+ }
+ if(args != null)
+ throw new ArgumentException("Too many arguments to values (> ThreadLocalData.MULTIPLE_VALUES_LIMIT)");
+ return arg1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/RatioNum.cs b/src/cli/runtime/RatioNum.cs
new file mode 100644
index 00000000..945a233f
--- /dev/null
+++ b/src/cli/runtime/RatioNum.cs
@@ -0,0 +1,229 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:14:44 AM */
+
+using System;
+using java.math;
+
+namespace org.clojure.runtime
+{
+
+public class RatioNum : RationalNum{
+override public Boolean Equals(Object arg0)
+ {
+ return arg0 != null
+ && arg0 is RatioNum
+ && ((RatioNum) arg0).numerator.Equals(numerator)
+ && ((RatioNum) arg0).denominator.Equals(denominator);
+ }
+
+override public int GetHashCode()
+ {
+ return numerator.GetHashCode() ^ denominator.GetHashCode();
+ }
+
+override public String ToString()
+ {
+ return numerator.ToString() + "/" + denominator.ToString();
+ }
+
+public IntegerNum numerator;
+public IntegerNum denominator;
+
+public RatioNum(IntegerNum n, IntegerNum d)
+ {
+ this.numerator = n;
+ this.denominator = d;
+ }
+
+override public double doubleValue()
+ {
+ return numerator.doubleValue() / denominator.doubleValue();
+ }
+
+override public float floatValue()
+ {
+ return (float) doubleValue();
+ }
+
+override public int intValue()
+ {
+ return (int) doubleValue();
+ }
+
+override public long longValue()
+ {
+ return (long) doubleValue();
+ }
+
+override public Boolean equiv(Num rhs)
+ {
+ return rhs.equivTo(this);
+ }
+
+override public Boolean equivTo(BigInteger x)
+ {
+ return false;
+ }
+
+override public Boolean equivTo(int x)
+ {
+ return false;
+ }
+
+override public Boolean equivTo(RatioNum x)
+ {
+ return numerator.equiv(x.numerator) && denominator.equiv(x.denominator);
+ }
+
+override public Boolean lt(Num rhs)
+ {
+ return rhs.gt(this);
+ }
+
+override public Boolean gt(BigInteger x)
+ {
+ return denominator.multiply(x).lt(numerator);
+ }
+
+override public Boolean gt(int x)
+ {
+ return denominator.multiply(x).lt(numerator);
+ }
+
+override public Boolean gt(RatioNum x)
+ {
+ return x.numerator.multiplyBy(denominator).lt(numerator.multiplyBy(x.denominator));
+ }
+
+override public Num add(Num rhs)
+ {
+ return rhs.addTo(this);
+ }
+
+override public Num addTo(BigInteger x)
+ {
+ return Num.divide(numerator.add(denominator.multiply(x)), denominator);
+ }
+
+override public Num addTo(int x)
+ {
+ return Num.divide(numerator.add(denominator.multiply(x)), denominator);
+ }
+
+override public Num addTo(RatioNum x)
+ {
+ return Num.divide(numerator.multiplyBy(x.denominator)
+ .add(x.numerator.multiplyBy(denominator))
+ , denominator.multiplyBy(x.denominator));
+ }
+
+override public Num subtractFrom(Num x)
+ {
+ return x.add(this.multiply(-1));
+ }
+
+override public Num multiplyBy(Num rhs)
+ {
+ return rhs.multiply(this);
+ }
+
+override public Num multiply(BigInteger x)
+ {
+ return Num.divide(numerator.multiply(x), denominator);
+ }
+
+override public Num multiply(int x)
+ {
+ return Num.divide(numerator.multiply(x), denominator);
+ }
+
+override public Num multiply(RatioNum x)
+ {
+ return Num.divide(numerator.multiplyBy(x.numerator)
+ , denominator.multiplyBy(x.denominator));
+ }
+
+override public Num divideBy(Num rhs)
+ {
+ return rhs.divide(this);
+ }
+
+override public Num divide(BigInteger n)
+ {
+ return Num.divide(denominator.multiply(n), numerator);
+ }
+
+override public Num divide(int n)
+ {
+ return Num.divide(denominator.multiply(n), numerator);
+ }
+
+override public Num divide(RatioNum n)
+ {
+ return Num.divide(denominator.multiplyBy(n.numerator)
+ , numerator.multiplyBy(n.denominator));
+ }
+
+
+override public Object truncateDivide(ThreadLocalData tld, Num num)
+ {
+ return num.truncateBy(tld, this);
+ }
+
+override public Object truncateBy(ThreadLocalData tld, int div)
+ {
+ Num q = (Num) Num.truncate(tld, numerator, denominator.multiply(div));
+ return RT.setValues(tld, q, q.multiply(div).subtractFrom(this));
+ }
+
+override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+ {
+ Num q = (Num) Num.truncate(tld, numerator, denominator.multiply(div));
+ return RT.setValues(tld, q, q.multiply(div).subtractFrom(this));
+ }
+
+override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+ {
+ Num q = (Num) Num.truncate(tld, numerator.multiplyBy(div.denominator),
+ denominator.multiplyBy(div.numerator));
+ return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ }
+
+
+override public Num negate()
+ {
+ return Num.divide(numerator.negate(), denominator);
+ }
+
+override public Boolean minusp()
+ {
+ return numerator.minusp();
+ }
+
+override public Boolean plusp()
+ {
+ return numerator.plusp();
+ }
+
+override public Num oneMinus()
+ {
+ return addTo(-1);
+ }
+
+override public Num onePlus()
+ {
+ return addTo(1);
+ }
+
+}
+}
+
diff --git a/src/cli/runtime/RationalNum.cs b/src/cli/runtime/RationalNum.cs
new file mode 100644
index 00000000..0dc810ae
--- /dev/null
+++ b/src/cli/runtime/RationalNum.cs
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:12:30 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RationalNum : RealNum {
+
+}
+}
diff --git a/src/cli/runtime/RealNum.cs b/src/cli/runtime/RealNum.cs
new file mode 100644
index 00000000..2172199a
--- /dev/null
+++ b/src/cli/runtime/RealNum.cs
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 28, 2006 10:13:00 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RealNum : Num {
+
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/RestFn0.cs b/src/cli/runtime/RestFn0.cs
new file mode 100644
index 00000000..fbd83e46
--- /dev/null
+++ b/src/cli/runtime/RestFn0.cs
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 7:34:25 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn0 : AFn
+ {
+
+protected abstract Object doInvoke(ThreadLocalData tld, Cons rest) /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ return doInvoke(tld, arglist);
+ }
+
+override public Object invoke(ThreadLocalData tld) /*throws Exception*/
+ {
+ return doInvoke(tld, null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1) /*throws Exception*/
+ {
+ return doInvoke(tld, RT.list(arg1));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) /*throws Exception*/
+ {
+ return doInvoke(tld, RT.list(arg1, arg2));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/
+ {
+ return doInvoke(tld, RT.list(arg1, arg2, arg3));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return doInvoke(tld, RT.list(arg1, arg2, arg3, arg4));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, RT.list(arg1, arg2, arg3, arg4, arg5));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, RT.listStar(arg1, arg2, arg3, arg4, arg5, args));
+ }
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/RestFn1.cs b/src/cli/runtime/RestFn1.cs
new file mode 100644
index 00000000..f59fa0d4
--- /dev/null
+++ b/src/cli/runtime/RestFn1.cs
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:00:28 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn1 : AFn{
+
+protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Cons rest) /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ if(arglist == null)
+ throwArity();
+ return doInvoke(tld, arglist.first
+ , arglist.rest);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, RT.list(arg2));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, RT.list(arg2, arg3));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, RT.list(arg2, arg3, arg4));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, RT.list(arg2, arg3, arg4, arg5));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, RT.listStar(arg2, arg3, arg4, arg5, args));
+ }
+}
+
+} \ No newline at end of file
diff --git a/src/cli/runtime/RestFn2.cs b/src/cli/runtime/RestFn2.cs
new file mode 100644
index 00000000..c0cdfe55
--- /dev/null
+++ b/src/cli/runtime/RestFn2.cs
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:05:10 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn2 : AFn{
+
+protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Cons rest) /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ if(RT.boundedLength(arglist, 2) < 2)
+ throwArity();
+ return doInvoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , arglist.rest);
+
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, RT.list(arg3));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, RT.list(arg3, arg4));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, RT.list(arg3, arg4, arg5));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, RT.listStar(arg3, arg4, arg5, args));
+ }
+}
+}
diff --git a/src/cli/runtime/RestFn3.cs b/src/cli/runtime/RestFn3.cs
new file mode 100644
index 00000000..689ee565
--- /dev/null
+++ b/src/cli/runtime/RestFn3.cs
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:19:54 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn3 : AFn{
+
+protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Cons rest) /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ if(RT.boundedLength(arglist, 3) < 3)
+ throwArity();
+ return doInvoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , arglist.rest);
+
+ }
+
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3,null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, RT.list(arg4));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, RT.list(arg4, arg5));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, RT.listStar(arg4, arg5, args));
+ }
+}
+} \ No newline at end of file
diff --git a/src/cli/runtime/RestFn4.cs b/src/cli/runtime/RestFn4.cs
new file mode 100644
index 00000000..9ab6aa93
--- /dev/null
+++ b/src/cli/runtime/RestFn4.cs
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:21:51 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn4 : AFn{
+
+protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Cons rest)
+ /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ if(RT.boundedLength(arglist, 4) < 4)
+ throwArity();
+ return doInvoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , arglist.rest);
+
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, arg4, null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, arg4, RT.list(arg5));
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, arg4, RT.listStar(arg5, args));
+ }
+}
+}
+
diff --git a/src/cli/runtime/RestFn5.cs b/src/cli/runtime/RestFn5.cs
new file mode 100644
index 00000000..b50aeade
--- /dev/null
+++ b/src/cli/runtime/RestFn5.cs
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 27, 2006 8:24:31 PM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+
+public abstract class RestFn5 : AFn{
+
+protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+ Cons rest)
+ /*throws Exception*/;
+
+override public Object applyTo(ThreadLocalData tld, Cons arglist) /*throws Exception*/
+ {
+ if(RT.boundedLength(arglist, 5) < 5)
+ throwArity();
+ return doInvoke(tld, arglist.first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , (arglist = arglist.rest).first
+ , arglist.rest);
+
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, arg4, arg5, null);
+ }
+
+override public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+ /*throws Exception*/
+ {
+ return doInvoke(tld, arg1, arg2, arg3, arg4, arg5, args);
+ }
+}
+}
diff --git a/src/cli/runtime/Symbol.cs b/src/cli/runtime/Symbol.cs
new file mode 100644
index 00000000..6994114b
--- /dev/null
+++ b/src/cli/runtime/Symbol.cs
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 11:42:47 AM */
+
+using System;
+
+namespace org.clojure.runtime
+{
+public class Symbol : AFn{
+
+public static Object UNBOUND = new Object();
+
+public String name; //const is not equivalent to Java final with init elsewhere
+public Namespace ns;
+public Object val = UNBOUND;
+public IFn fn; //todo, bind to throw stub?
+
+public String toString()
+ {
+ if(ns == Namespace.globalNS)
+ return name;
+ if(ns == null)
+ return "#:" + name;
+ return ns.name + ":" + name;
+ }
+
+/**
+ * Used by Namespace.intern()
+ * @param name
+ * @param ns
+ */
+internal Symbol(String name, Namespace ns)
+ {
+ this.ns = ns;
+ this.name = name;
+ }
+
+virtual public Object getValue(ThreadLocalData tld)
+ {
+ Cons binding = tld.getDynamicBinding(this);
+ if(binding != null)
+ return binding.first;
+ if(val == UNBOUND)
+ throw new InvalidOperationException(name + " is unbound.");
+ return val;
+ }
+
+virtual public Object setValue(ThreadLocalData tld, Object val)
+ {
+ Cons binding = tld.getDynamicBinding(this);
+ if(binding != null)
+ return binding.first = val;
+ //allow global set to create binding like this?
+ if(val is IFn)
+ this.fn = (IFn) val;
+ else
+ this.fn = null; //todo, bind to throw stub?
+ return this.val = val;
+ }
+
+/**
+ * Symbol implements IFn for attr access
+ * This single arg version is the getter
+ * @param tld
+ * @param obj - must be AMap
+ * @return the value of the attr or nil if not found
+ * @throws Exception
+ */
+override public Object invoke(ThreadLocalData tld, Object obj) /*throws Exception*/
+ {
+ return ((AMap)obj).get(this);
+ }
+
+/**
+ * Symbol implements IFn for attr access
+ * This two arg version is the setter
+ * @param tld
+ * @param obj - must be AMap
+ * @param val
+ * @return val
+ * @throws Exception
+ */
+override public Object invoke(ThreadLocalData tld, Object obj, Object val) /*throws Exception*/
+ {
+ return ((AMap)obj).put(this,val);
+ }
+}
+}
diff --git a/src/cli/runtime/ThreadLocalData.cs b/src/cli/runtime/ThreadLocalData.cs
new file mode 100644
index 00000000..0f41ecf8
--- /dev/null
+++ b/src/cli/runtime/ThreadLocalData.cs
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+/* rich Mar 25, 2006 11:45:22 AM */
+
+using System;
+using System.Collections.Specialized;
+
+namespace org.clojure.runtime
+{
+public class ThreadLocalData{
+
+public const int MULTIPLE_VALUES_LIMIT = 20;
+public int mvCount = 0;
+public Object[] mvArray = new Object[MULTIPLE_VALUES_LIMIT];
+
+HybridDictionary dynamicBindings = new HybridDictionary();
+
+public Cons getDynamicBinding(Symbol sym)
+ {
+ return (Cons) dynamicBindings[sym];
+ }
+
+public Cons pushDynamicBinding(Symbol sym, Object val)
+ {
+ Cons ret = new Cons(val, getDynamicBinding(sym));
+ dynamicBindings[sym] = ret;
+ return ret;
+ }
+
+
+public Cons popDynamicBinding(Symbol sym)
+ {
+ Cons ret = (Cons) getDynamicBinding(sym).rest;
+ dynamicBindings[sym] = ret;
+ return ret;
+ }
+
+public ThreadLocalData(HybridDictionary dynamicBindings)
+ {
+ this.mvCount = 0;
+ this.mvArray = new Object[MULTIPLE_VALUES_LIMIT];
+ this.dynamicBindings = dynamicBindings;
+ }
+
+public ThreadLocalData():
+ this(new HybridDictionary())
+ {
+ }
+
+public static ThreadLocalData get()
+ {
+ if(tld == null)
+ tld = new ThreadLocalData();
+ return tld;
+ }
+
+/*
+note this is not the same semantics as InheritableThreadLocal - aargh
+might need to make Java side non-inheritable
+*/
+[ThreadStatic]
+ static ThreadLocalData tld;
+ /* was this in Java
+static InheritableThreadLocal tld = new InheritableThreadLocal(){
+ protected Object childValue(Object object)
+ {
+ return new ThreadLocalData((HybridDictionary) ((ThreadLocalData) object).dynamicBindings.clone());
+ }
+
+ protected Object initialValue()
+ {
+ return new ThreadLocalData();
+ }
+};
+*/
+
+}
+}