nomennescio 2019-10-18 15:04:31 +02:00
parent 059c70d1d7
commit 79a60d07cc
60 changed files with 4217 additions and 2116 deletions

View File

@ -1,45 +1,68 @@
./factor/random.factor:! $Id: random.factor,v 1.3 2004/01/09 01:51:30 slava Exp $ ./factor/compiler/StackEffect.java: * $Id: StackEffect.java,v 1.6 2004/02/15 22:24:19 slava Exp $
./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/compiler/LocalAllocator.java: * $Id: LocalAllocator.java,v 1.9 2004/02/17 20:36:09 slava Exp $
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.12 2004/01/06 06:59:38 slava Exp $ ./factor/compiler/FactorCompilerException.java: * $Id: FactorCompilerException.java,v 1.1 2004/01/27 19:55:40 slava Exp $
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.12 2004/01/14 01:58:37 slava Exp $ ./factor/compiler/CompiledDefinition.java:* $Id: CompiledDefinition.java,v 1.4 2004/02/15 22:24:19 slava Exp $
./factor/combinators.factor:! $Id: combinators.factor,v 1.17 2004/01/11 23:00:34 slava Exp $ ./factor/random.factor:! $Id: random.factor,v 1.6 2004/02/18 00:48:47 slava Exp $
./factor/FactorDataStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $ ./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/continuations.factor:! $Id: continuations.factor,v 1.8 2003/12/20 05:31:01 slava Exp $ ./factor/FactorJava.java: * $Id: FactorJava.java,v 1.7 2004/02/15 05:44:54 slava Exp $
./factor/network.factor:! $Id: io.factor,v 1.2 2003/12/20 05:31:01 slava Exp $ ./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.8 2004/02/15 22:24:19 slava Exp $
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.10 2004/01/03 20:58:09 slava Exp $ ./factor/combinators.factor:! $Id: combinators.factor,v 1.4 2004/02/13 23:19:43 slava Exp $
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/FactorDataStack.java: * $Id: FactorDataStack.java,v 1.3 2004/02/15 22:24:19 slava Exp $
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2003/12/16 08:03:08 slava Exp $ ./factor/continuations.factor:! $Id: continuations.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $ ./factor/network.factor:! $Id: network.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/FactorLib.java: * $Id: FactorLib.java,v 1.4 2004/02/15 22:24:19 slava Exp $
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2003/12/09 09:52:26 slava Exp $ ./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/lists.factor:! $Id: lists.factor,v 1.10 2004/01/06 06:59:38 slava Exp $ ./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2003/12/26 00:36:30 slava Exp $ ./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.1 2004/01/15 03:00:18 slava Exp $ ./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorPrimitive.java: * $Id: FactorPrimitive.java,v 1.5 2004/01/11 23:00:34 slava Exp $ ./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorList.java: * $Id: FactorList.java,v 1.9 2004/01/03 20:58:09 slava Exp $ ./factor/lists.factor:! $Id: lists.factor,v 1.7 2004/02/15 22:24:19 slava Exp $
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.10 2004/01/08 04:14:14 slava Exp $ ./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2004/02/05 04:47:05 slava Exp $
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.3 2004/02/13 23:19:43 slava Exp $
./factor/examples.factor:! $Id: examples.factor,v 1.4 2004/01/12 02:07:31 slava Exp $ ./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.4 2004/02/05 04:47:05 slava Exp $
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.2 2004/01/14 01:58:37 slava Exp $ ./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.5 2003/12/19 21:40:00 slava Exp $ ./factor/examples.factor:! $Id: examples.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.13 2004/01/10 23:24:30 slava Exp $ ./factor/Cons.java: * $Id: Cons.java,v 1.4 2004/02/11 03:49:45 slava Exp $
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.7 2003/12/26 00:36:30 slava Exp $ ./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.9 2004/02/15 22:24:19 slava Exp $
./factor/parser.factor:! $Id: parser.factor,v 1.2 2003/12/20 04:30:06 slava Exp $ ./factor/FactorObject.java: * $Id: FactorObject.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorMissingDefinition.java: * $Id: FactorWordDefinition.java,v 1.10 2003/12/18 00:01:39 slava Exp $ ./factor/FactorParser.java: * $Id: FactorParser.java,v 1.3 2004/01/26 03:16:54 slava Exp $
./factor/stream.factor:! $Id: stream.factor,v 1.1 2004/01/03 20:58:09 slava Exp $ ./factor/FactorMath.java: * $Id: FactorMath.java,v 1.3 2004/02/17 20:36:09 slava Exp $
./factor/FactorReflectionForm.java:* $Id: FactorReflectionForm.java,v 1.1 2004/01/14 01:58:37 slava Exp $ ./factor/parser.factor:! $Id: parser.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
./factor/strings.factor:! $Id: strings.factor,v 1.4 2004/01/06 06:59:38 slava Exp $ ./factor/FactorMissingDefinition.java: * $Id: FactorMissingDefinition.java,v 1.7 2004/02/15 22:24:19 slava Exp $
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.32 2004/01/12 02:07:31 slava Exp $ ./factor/stream.factor:! $Id: stream.factor,v 1.3 2004/02/10 05:43:37 slava Exp $
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/strings.factor:! $Id: strings.factor,v 1.9 2004/02/18 00:48:47 slava Exp $
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.10 2004/01/08 04:14:14 slava Exp $ ./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.6 2004/02/17 20:36:09 slava Exp $
./factor/math.factor:! $Id: math.factor,v 1.11 2004/01/11 23:00:34 slava Exp $ ./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.17 2004/01/14 01:58:37 slava Exp $ ./factor/FactorWord.java: * $Id: FactorWord.java,v 1.7 2004/02/15 05:44:54 slava Exp $
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.14 2004/01/11 23:00:34 slava Exp $ ./factor/math.factor:! $Id: math.factor,v 1.5 2004/02/17 20:36:09 slava Exp $
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2003/12/21 05:29:46 slava Exp $ ./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.14 2004/02/15 22:24:19 slava Exp $
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.3 2003/12/20 05:31:01 slava Exp $ ./factor/primitives/CallstackSet.java: * $Id: CallstackSet.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/boot.factor:! $Id: boot.factor,v 1.12 2004/01/12 02:07:31 slava Exp $ ./factor/primitives/JInvokeStatic.java: * $Id: JInvokeStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/primitives/Unwind.java: * $Id: Unwind.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/01/05 05:03:36 slava Exp $ ./factor/primitives/JVarGetStatic.java: * $Id: JVarGetStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/FactorException.java: * $Id: FactorException.java,v 1.3 2003/12/09 09:40:18 slava Exp $ ./factor/primitives/Unstack.java: * $Id: Unstack.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.5 2004/01/14 01:58:37 slava Exp $ ./factor/primitives/JInvoke.java: * $Id: JInvoke.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.6 2004/01/12 02:07:31 slava Exp $ ./factor/primitives/Get.java: * $Id: Get.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Define.java: * $Id: Define.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Clear.java: * $Id: Clear.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Bind.java: * $Id: Bind.java,v 1.3 2004/02/17 20:36:09 slava Exp $
./factor/primitives/Choice.java: * $Id: Choice.java,v 1.3 2004/02/17 03:49:46 slava Exp $
./factor/primitives/JNew.java: * $Id: JNew.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Call.java: * $Id: Call.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/primitives/CallstackGet.java: * $Id: CallstackGet.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/primitives/DatastackGet.java: * $Id: DatastackGet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/JVarSet.java: * $Id: JVarSet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Set.java: * $Id: Set.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Restack.java: * $Id: Restack.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/DatastackSet.java: * $Id: DatastackSet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/JVarSetStatic.java: * $Id: JVarSetStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/JVarGet.java: * $Id: JVarGet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.6 2004/02/10 05:43:37 slava Exp $
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2004/02/15 22:24:19 slava Exp $
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.2 2004/01/26 03:16:54 slava Exp $
./factor/boot.factor:! $Id: boot.factor,v 1.5 2004/02/18 00:48:47 slava Exp $
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/02/10 05:43:37 slava Exp $
./factor/FactorException.java: * $Id: FactorException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.12 2004/02/15 22:24:19 slava Exp $
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.8 2004/02/10 05:43:37 slava Exp $

View File

@ -3,7 +3,7 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (C) 2003 Slava Pestov. * Copyright (C) 2003, 2004 Slava Pestov.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -29,20 +29,18 @@
package factor; package factor;
import java.util.LinkedList;
import java.util.List;
/** /**
* Used to build up linked lists. * Used to build up linked lists.
*/ */
public class FactorList implements PublicCloneable, FactorExternalizable public class Cons implements PublicCloneable, FactorExternalizable
{ {
public static int COUNT; public static int COUNT;
public Object car; public Object car;
public Object cdr; public Object cdr;
//{{{ FactorList constructor //{{{ Cons constructor
public FactorList(Object car, Object cdr) public Cons(Object car, Object cdr)
{ {
this.car = car; this.car = car;
this.cdr = cdr; this.cdr = cdr;
@ -63,9 +61,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}} } //}}}
//{{{ next() method //{{{ next() method
public FactorList next() public Cons next()
{ {
return (FactorList)cdr; return (Cons)cdr;
} //}}} } //}}}
//{{{ get() method //{{{ get() method
@ -75,12 +73,12 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}} } //}}}
//{{{ _get() method //{{{ _get() method
public FactorList _get(int index) public Cons _get(int index)
{ {
FactorList iter = this; Cons iter = this;
while(index != 0) while(index != 0)
{ {
iter = (FactorList)iter.cdr; iter = (Cons)iter.cdr;
index--; index--;
} }
return iter; return iter;
@ -89,7 +87,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ contains() method //{{{ contains() method
public boolean contains(Object obj) public boolean contains(Object obj)
{ {
FactorList iter = this; Cons iter = this;
while(iter != null) while(iter != null)
{ {
if(FactorLib.objectsEqual(obj,iter.car)) if(FactorLib.objectsEqual(obj,iter.car))
@ -99,100 +97,33 @@ public class FactorList implements PublicCloneable, FactorExternalizable
return false; return false;
} //}}} } //}}}
//{{{ set() method //{{{ contains() method
/** public static boolean contains(Cons list, Object obj)
* Returns a new list where the item at the given index is changed.
*/
public FactorList set(int index, Object car, Object cdr)
{ {
if(index == 0) if(list == null)
return new FactorList(car,cdr); return false;
else else
{ return list.contains(obj);
return new FactorList(this.car,
this.next().set(index - 1,car,cdr));
}
} //}}}
//{{{ set() method
/**
* Returns a new list containing the first n elements of this list.
*/
public FactorList head(int n)
{
if(n == 0)
return null;
else if(cdr == null && n == 1)
return this;
else
{
FactorList head = next().head(n - 1);
if(head == cdr)
return this;
else
return new FactorList(car,head);
}
} //}}} } //}}}
//{{{ length() method //{{{ length() method
public int length() public int length()
{ {
int size = 0; int size = 0;
FactorList iter = this; Cons iter = this;
while(iter != null) while(iter != null)
{ {
iter = (FactorList)iter.cdr; iter = (Cons)iter.cdr;
size++; size++;
} }
return size; return size;
} //}}} } //}}}
//{{{ append() method
public FactorList append(FactorList list)
{
if(list == null)
return this;
FactorList returnValue = null;
FactorList end = null;
FactorList iter = this;
for(;;)
{
FactorList cons = new FactorList(iter.car,null);
if(end != null)
end.cdr = cons;
end = cons;
if(returnValue == null)
returnValue = cons;
if(iter.cdr == null)
{
end.cdr = list;
break;
}
else
iter = iter.next();
}
return returnValue;
} //}}}
//{{{ reverse() method
public FactorList reverse()
{
FactorList returnValue = null;
FactorList iter = this;
while(iter != null)
{
returnValue = new FactorList(iter.car,returnValue);
iter = iter.next();
}
return returnValue;
} //}}}
//{{{ isProperList() method //{{{ isProperList() method
public boolean isProperList() public boolean isProperList()
{ {
return cdr == null || (cdr instanceof FactorList return cdr == null || (cdr instanceof Cons
&& ((FactorList)cdr).isProperList()); && ((Cons)cdr).isProperList());
} //}}} } //}}}
//{{{ elementsToString() method //{{{ elementsToString() method
@ -203,17 +134,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
public String elementsToString() public String elementsToString()
{ {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
FactorList iter = this; Cons iter = this;
while(iter != null) while(iter != null)
{ {
if(iter.car == this) if(iter.car == this)
buf.append("<circular reference>"); buf.append("<circular reference>");
else else
buf.append(FactorJava.factorTypeToString(iter.car)); buf.append(FactorJava.factorTypeToString(iter.car));
if(iter.cdr instanceof FactorList) if(iter.cdr instanceof Cons)
{ {
buf.append(' '); buf.append(' ');
iter = (FactorList)iter.cdr; iter = (Cons)iter.cdr;
continue; continue;
} }
else if(iter.cdr == null) else if(iter.cdr == null)
@ -238,19 +169,6 @@ public class FactorList implements PublicCloneable, FactorExternalizable
return "[ " + elementsToString() + " ]"; return "[ " + elementsToString() + " ]";
} //}}} } //}}}
//{{{ toJavaList() method
public List toJavaList()
{
LinkedList returnValue = new LinkedList();
FactorList iter = this;
while(iter != null)
{
returnValue.add(iter.car);
iter = (FactorList)iter.cdr;
}
return returnValue;
} //}}}
//{{{ toArray() method //{{{ toArray() method
/** /**
* Note that unlike Java list toArray(), the given array must already * Note that unlike Java list toArray(), the given array must already
@ -259,7 +177,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
public Object[] toArray(Object[] returnValue) public Object[] toArray(Object[] returnValue)
{ {
int i = 0; int i = 0;
FactorList iter = this; Cons iter = this;
while(iter != null) while(iter != null)
{ {
returnValue[i++] = iter.car; returnValue[i++] = iter.car;
@ -269,17 +187,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}} } //}}}
//{{{ fromArray() method //{{{ fromArray() method
public static FactorList fromArray(Object[] array) public static Cons fromArray(Object[] array)
{ {
if(array == null || array.length == 0) if(array == null || array.length == 0)
return null; return null;
else else
{ {
FactorList first = new FactorList(array[0],null); Cons first = new Cons(array[0],null);
FactorList last = first; Cons last = first;
for(int i = 1; i < array.length; i++) for(int i = 1; i < array.length; i++)
{ {
FactorList cons = new FactorList(array[i],null); Cons cons = new Cons(array[i],null);
last.cdr = cons; last.cdr = cons;
last = cons; last = cons;
} }
@ -290,9 +208,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ equals() method //{{{ equals() method
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof FactorList) if(o instanceof Cons)
{ {
FactorList l = (FactorList)o; Cons l = (Cons)o;
return FactorLib.objectsEqual(car,l.car) return FactorLib.objectsEqual(car,l.car)
&& FactorLib.objectsEqual(cdr,l.cdr); && FactorLib.objectsEqual(cdr,l.cdr);
} }
@ -312,10 +230,10 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ clone() method //{{{ clone() method
public Object clone() public Object clone()
{ {
if(cdr instanceof FactorList) if(cdr instanceof Cons)
return new FactorList(car,((FactorList)cdr).clone()); return new Cons(car,((Cons)cdr).clone());
else else
return new FactorList(car,cdr); return new Cons(car,cdr);
} //}}} } //}}}
//{{{ deepClone() method //{{{ deepClone() method
@ -326,13 +244,13 @@ public class FactorList implements PublicCloneable, FactorExternalizable
ccar = ((PublicCloneable)car).clone(); ccar = ((PublicCloneable)car).clone();
else else
ccar = car; ccar = car;
if(cdr instanceof FactorList) if(cdr instanceof Cons)
{ {
return new FactorList(ccar,next().deepClone()); return new Cons(ccar,next().deepClone());
} }
else if(cdr == null) else if(cdr == null)
{ {
return new FactorList(ccar,null); return new Cons(ccar,null);
} }
else else
{ {
@ -341,7 +259,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
ccdr = ((PublicCloneable)cdr).clone(); ccdr = ((PublicCloneable)cdr).clone();
else else
ccdr = cdr; ccdr = cdr;
return new FactorList(ccar,ccdr); return new Cons(ccar,ccdr);
} }
} //}}} } //}}}
} }

View File

@ -44,7 +44,7 @@ public abstract class FactorArrayStack implements FactorExternalizable
} //}}} } //}}}
//{{{ FactorArrayStack constructor //{{{ FactorArrayStack constructor
public FactorArrayStack(FactorList list) public FactorArrayStack(Cons list)
{ {
if(list != null) if(list != null)
{ {
@ -126,12 +126,12 @@ public abstract class FactorArrayStack implements FactorExternalizable
} //}}} } //}}}
//{{{ toList() method //{{{ toList() method
public FactorList toList() public Cons toList()
{ {
FactorList first = null, last = null; Cons first = null, last = null;
for(int i = 0; i < top; i++) for(int i = 0; i < top; i++)
{ {
FactorList cons = new FactorList(stack[i],null); Cons cons = new Cons(stack[i],null);
if(first == null) if(first == null)
first = cons; first = cons;
else else

View File

@ -44,13 +44,18 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
/** /**
* Next word to be evaluated. * Next word to be evaluated.
*/ */
public FactorList ip; public Cons ip;
/** /**
* Collapsed tail calls? See call(). * Collapsed tail calls? See call().
*/ */
public boolean collapsed; public boolean collapsed;
/**
* Compiled code?
*/
public boolean compiled;
//{{{ FactorCallFrame constructor //{{{ FactorCallFrame constructor
public FactorCallFrame() public FactorCallFrame()
{ {
@ -59,7 +64,7 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
//{{{ FactorCallFrame constructor //{{{ FactorCallFrame constructor
public FactorCallFrame(FactorWord word, public FactorCallFrame(FactorWord word,
FactorNamespace namespace, FactorNamespace namespace,
FactorList ip) Cons ip)
{ {
this.word = word; this.word = word;
this.namespace = namespace; this.namespace = namespace;
@ -90,12 +95,17 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
buf.append("at ").append(word); buf.append("at ").append(word);
if(compiled)
buf.append(" ( compiled )");
else if(ip != null)
{
buf.append(" ( ip: ").append(ip.elementsToString())
.append(" )");
}
buf.append('\n').append(indent); buf.append('\n').append(indent);
buf.append(" namespace: ").append(namespace) buf.append(namespace);
.append('\n').append(indent);
buf.append(" ip: ").append(ip);
return buf.toString(); return buf.toString();
} //}}} } //}}}

View File

@ -60,6 +60,12 @@ public class FactorCallStack extends FactorArrayStack implements PublicCloneable
//{{{ clone() method //{{{ clone() method
public Object clone() public Object clone()
{ {
return new FactorCallStack(FactorLib.deepCloneArray(stack),top); if(stack == null)
return new FactorCallStack();
else
{
return new FactorCallStack(
FactorLib.deepCloneArray(stack),top);
}
} //}}} } //}}}
} }

View File

@ -29,289 +29,356 @@
package factor; package factor;
import factor.compiler.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.io.FileOutputStream;
import java.util.*;
import org.objectweb.asm.*; import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/** /**
* : name ... ; * : name ... ;
*/ */
public class FactorCompoundDefinition extends FactorWordDefinition public class FactorCompoundDefinition extends FactorWordDefinition
{ {
public FactorList definition; private static int compileCount;
public FactorCompoundDefinition(FactorList definition) public Cons definition;
//{{{ FactorCompiledDefinition constructor
public FactorCompoundDefinition(FactorWord word, Cons definition)
{ {
super(word);
this.definition = definition; this.definition = definition;
} } //}}}
public void eval(FactorWord word, FactorInterpreter interp) //{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception throws Exception
{ {
interp.call(word,definition); interp.call(word,definition);
} } //}}}
//{{{ canCompile() method //{{{ getStackEffect() method
boolean canCompile() public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{ {
return true; if(recursiveCheck.contains(this))
return null;
try
{
recursiveCheck.add(this);
return StackEffect.getStackEffect(definition,
recursiveCheck,state);
}
finally
{
recursiveCheck.remove(this);
}
} //}}}
//{{{ getSanitizedName() method
private String getSanitizedName(String name)
{
StringBuffer sanitizedName = new StringBuffer();
for(int i = 0; i < name.length(); i++)
{
char ch = name.charAt(i);
if(!Character.isJavaIdentifierStart(ch))
sanitizedName.append("_");
else
sanitizedName.append(ch);
}
return "factor/compiler/gen/" + sanitizedName
+ "_" + (compileCount++);
} //}}} } //}}}
//{{{ compile() method //{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorInterpreter interp,
Set recursiveCheck) throws Exception
{
StackEffect effect = getStackEffect(
recursiveCheck,new LocalAllocator());
if(effect == null)
throw new FactorCompilerException("Cannot deduce stack effect of " + word);
if(effect.outD > 1)
throw new FactorCompilerException("Cannot compile word that returns more than 1 value");
/* StringBuffer buf = new StringBuffer();
for(int i = 0; i < recursiveCheck.size(); i++)
{
buf.append(' ');
}
buf.append("Compiling ").append(word);
System.err.println(buf); */
String className = getSanitizedName(word.name);
ClassWriter cw = new ClassWriter(false);
cw.visit(ACC_PUBLIC, className,
"factor/compiler/CompiledDefinition", null, null);
compileConstructor(cw,className);
CompileResult result = compileEval(interp,cw,
className,effect,recursiveCheck);
compileToString(cw,effect);
// Generate fields for storing literals and word references
result.allocator.generateFields(cw);
// gets the bytecode of the class, and loads it dynamically
byte[] code = cw.toByteArray();
if(interp.compileDump)
{
FileOutputStream fos = new FileOutputStream(className + ".class");
fos.write(code);
fos.close();
}
Class compiledWordClass = loader._defineClass(
className.replace('/','.'),
code, 0, code.length);
result.allocator.setFields(compiledWordClass);
Constructor constructor = compiledWordClass.getConstructor(
new Class[] { FactorWord.class, StackEffect.class });
FactorWordDefinition compiledWord = (FactorWordDefinition)
constructor.newInstance(new Object[] { word, effect });
// store disassembly for the 'asm' word.
compiledWord.getNamespace(interp).setVariable("asm",
result.asm);
return compiledWord;
} //}}}
//{{{ compileConstructor() method
private void compileConstructor(ClassVisitor cw, String className)
{
// creates a MethodWriter for the constructor
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"<init>",
"(Lfactor/FactorWord;Lfactor/compiler/StackEffect;)V",
null, null);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// pushes the word parameter
mw.visitVarInsn(ALOAD, 1);
// pushes the stack effect parameter
mw.visitVarInsn(ALOAD, 2);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/compiler/CompiledDefinition", "<init>",
"(Lfactor/FactorWord;Lfactor/compiler/StackEffect;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(3, 3);
} //}}}
//{{{ compileToString() method
private void compileToString(ClassVisitor cw, StackEffect effect)
{
// creates a MethodWriter for the 'toString' method
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"toString", "()Ljava/lang/String;", null, null);
mw.visitLdcInsn("( compiled: " + effect + " ) " + toString());
mw.visitInsn(ARETURN);
mw.visitMaxs(1, 1);
} //}}}
//{{{ compileEval() method
static class CompileResult
{
LocalAllocator allocator;
String asm;
CompileResult(LocalAllocator allocator, String asm)
{
this.allocator = allocator;
this.asm = asm;
}
}
/** /**
* Write the definition of the eval() method in the compiled word. * Write the definition of the eval() method in the compiled word.
* Local 0 -- this * Local 0 -- this
* Local 1 -- word * Local 1 -- interpreter
* Local 2 -- interpreter
*/ */
boolean compile(FactorWord word, FactorInterpreter interp, protected CompileResult compileEval(FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw) ClassWriter cw, String className, StackEffect effect,
throws Exception Set recursiveCheck) throws Exception
{
if(definition == null)
{ {
// creates a MethodWriter for the 'eval' method
CodeVisitor _mw = cw.visitMethod(ACC_PUBLIC,
"eval", "(Lfactor/FactorInterpreter;)V",
null, null);
TraceCodeVisitor mw = new TraceCodeVisitor(_mw);
// eval() method calls core
mw.visitVarInsn(ALOAD,1);
compileDataStackToJVMStack(effect,mw);
String signature = effect.getCorePrototype();
mw.visitMethodInsn(INVOKESTATIC,
className,"core",signature);
compileJVMStackToDataStack(effect,mw);
mw.visitInsn(RETURN); mw.visitInsn(RETURN);
// Max stack and locals mw.visitMaxs(Math.max(4,2 + effect.inD),4);
mw.visitMaxs(1,1);
return true;
}
FactorList fdef = compilePass1(interp,definition); String evalAsm = getDisassembly(mw);
if(fdef.car instanceof FactorReflectionForm
&& fdef.cdr == null)
{
return ((FactorReflectionForm)fdef.car).compile(
word,interp,cw,mw);
}
/* else
System.err.println("WARNING: cannot compile reflection & more"); */
return false; // generate core
} //}}} _mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
"core",signature,null,null);
//{{{ compilePass1() method mw = new TraceCodeVisitor(_mw);
/**
* Turn reflection calls into ReflectionForm objects.
*/
private FactorList compilePass1(FactorInterpreter interp, FactorList def)
{
if(!def.isProperList())
return def;
FactorList rdef = def.reverse(); LocalAllocator allocator = new LocalAllocator(interp,
className,1,effect.inD);
FactorDictionary dict = interp.dict; int maxJVMStack = allocator.compile(definition,mw,
recursiveCheck);
// A list of words and Java reflection forms if(effect.outD == 0)
FactorList fdef = null; mw.visitInsn(RETURN);
while(rdef != null)
{
Object car = rdef.car;
if(car == dict.jvarGet
|| car == dict.jvarSet
|| car == dict.jvarGetStatic
|| car == dict.jvarSetStatic
|| car == dict.jnew)
{
FactorList form = rdef;
rdef = form._get(3);
fdef = new FactorList(new FactorReflectionForm(form),
fdef);
}
else if(car == dict.jinvoke
|| car == dict.jinvokeStatic)
{
FactorList form = rdef;
rdef = form._get(4);
fdef = new FactorList(new FactorReflectionForm(form),
fdef);
}
else if(car instanceof FactorList)
{
fdef = new FactorList(compilePass1(
interp,((FactorList)car)),fdef);
}
else
fdef = new FactorList(car,fdef);
rdef = rdef.next();
}
return fdef;
} //}}}
//{{{ precompile() method
void precompile(FactorWord newWord, FactorInterpreter interp)
throws Exception
{
FactorDictionary dict = interp.dict;
if(definition != null)
{
FactorList before = definition;
FactorList fed = definition.reverse();
precompile(interp,newWord,fed);
definition = fed.reverse();
/* if(!def.equals(before))
{
System.out.println("BEFORE: " + before);
System.out.println("AFTER: " + def);
} */
}
} //}}}
//{{{ precompile() method
/**
* Precompiling turns jconstructor, jfield and jmethod calls
* with all-literal arguments into inline
* Constructor/Field/Method literals. This improves performance.
*/
private void precompile(FactorInterpreter interp,
FactorWord newWord, FactorList list)
throws Exception
{
if(interp.compile)
return;
FactorDictionary dict = interp.dict;
while(list != null)
{
Object o = list.car;
if(o instanceof FactorWord)
{
FactorWord word = (FactorWord)o;
if(word.def != FactorMissingDefinition.INSTANCE)
{
word.def.references++;
}
else else
{ {
/*System.err.println( allocator.pop(mw);
"WARNING: " mw.visitInsn(ARETURN);
+ newWord maxJVMStack = Math.max(maxJVMStack,1);
+ " references "
+ o
+ " before its defined");*/
} }
if(o == dict.jconstructor) mw.visitMaxs(maxJVMStack,allocator.maxLocals());
String coreAsm = getDisassembly(mw);
return new CompileResult(allocator,
"eval(Lfactor/FactorInterpreter;)V:\n" + evalAsm
+ "core" + signature + "\n" + coreAsm);
} //}}}
//{{{ getDisassembly() method
protected String getDisassembly(TraceCodeVisitor mw)
{ {
jconstructorPrecompile( // Save the disassembly of the eval() method
interp,list); StringBuffer buf = new StringBuffer();
} Iterator bytecodes = mw.getText().iterator();
else if(o == dict.jmethod) while(bytecodes.hasNext())
{ {
jmethodPrecompile( buf.append(bytecodes.next());
interp,list);
} }
else if(o == dict.jfield) return buf.toString();
} //}}}
//{{{ compileDataStackToJVMStack() method
private void compileDataStackToJVMStack(StackEffect effect,
CodeVisitor mw)
{ {
jfieldPrecompile( if(effect.inD != 0)
interp,list);
}
}
else if(o instanceof FactorList)
{ {
if(((FactorList)o).isProperList()) mw.visitVarInsn(ALOAD,1);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
// ensure the stack has enough elements
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,effect.inD);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
// datastack.stack -> 2
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,2);
// datastack.top-args.length -> 3
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitIntInsn(BIPUSH,effect.inD);
mw.visitInsn(ISUB);
// datastack.top -= args.length
mw.visitInsn(DUP_X1);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitVarInsn(ISTORE,3);
for(int i = 0; i < effect.inD; i++)
{ {
FactorList l = (FactorList)o; mw.visitVarInsn(ALOAD,2);
FactorList _l = l.reverse(); mw.visitVarInsn(ILOAD,3);
precompile(interp,newWord,_l); mw.visitInsn(AALOAD);
list.car = _l.reverse(); if(i != effect.inD - 1)
mw.visitIincInsn(3,1);
} }
} }
list = list.next();
}
} //}}} } //}}}
//{{{ jconstructorPrecompile() method //{{{ compileJVMStackToDataStack() method
private void jconstructorPrecompile( private void compileJVMStackToDataStack(StackEffect effect,
FactorInterpreter interp, FactorList list) CodeVisitor mw)
throws Exception
{ {
FactorList cdr = list.next(); if(effect.outD == 1)
if(cdr == null) {
return; // ( datastack )
if(!(cdr.car instanceof String)) mw.visitVarInsn(ALOAD,1);
return; mw.visitFieldInsn(GETFIELD,
String clazz = (String)cdr.car; "factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
FactorList cddr = cdr.next(); mw.visitInsn(SWAP);
if(cddr == null) mw.visitMethodInsn(INVOKEVIRTUAL,
return; "factor/FactorArrayStack", "push",
if(!(cddr.car instanceof FactorList)) "(Ljava/lang/Object;)V");
return; }
FactorList args = (FactorList)cddr.car;
Constructor c = FactorJava.jconstructor(clazz,args);
list.car = c;
list.cdr = cddr.next();
} //}}} } //}}}
//{{{ jfieldPrecompile() method //{{{ compileImmediate() method
private void jfieldPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String field = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof String))
return;
String clazz = (String)cddr.car;
Field f = FactorJava.jfield(field,clazz);
list.car = f;
list.cdr = cddr.next();
} //}}}
//{{{ jmethodPrecompile() method
/** /**
* Check if this jmethod has all-literal arguments, and if so, * Compile a call to this word. Returns maximum JVM stack use.
* inline the result.
*/ */
private void jmethodPrecompile( public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
FactorInterpreter interp, FactorList list) Set recursiveCheck) throws Exception
throws Exception
{ {
FactorList cdr = list.next(); return allocator.compile(definition,mw,recursiveCheck);
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String method = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof String))
return;
String clazz = (String)cddr.car;
FactorList cdddr = cddr.next();
if(cdddr == null)
return;
if(!(cdddr.car instanceof FactorList))
return;
FactorList args = (FactorList)cdddr.car;
Method m = FactorJava.jmethod(method,clazz,args);
list.car = m;
list.cdr = cdddr.next();
} //}}} } //}}}
//{{{ toString() method
public String toString() public String toString()
{ {
return definition.elementsToString(); return definition.elementsToString();
} //}}}
private static SimpleClassLoader loader = new SimpleClassLoader();
//{{{ SimpleClassLoader class
static class SimpleClassLoader extends ClassLoader
{
public Class _defineClass(String name,
byte[] code, int off, int len)
{
return defineClass(name,code,off,len);
} }
} //}}}
} }

View File

@ -41,7 +41,7 @@ public class FactorDataStack extends FactorArrayStack implements PublicCloneable
} //}}} } //}}}
//{{{ FactorDataStack constructor //{{{ FactorDataStack constructor
public FactorDataStack(FactorList list) public FactorDataStack(Cons list)
{ {
super(list); super(list);
} //}}} } //}}}
@ -66,6 +66,12 @@ public class FactorDataStack extends FactorArrayStack implements PublicCloneable
//{{{ clone() method //{{{ clone() method
public Object clone() public Object clone()
{ {
return new FactorDataStack(FactorLib.cloneArray(stack),top); if(stack == null)
return new FactorDataStack();
else
{
return new FactorDataStack(
FactorLib.cloneArray(stack),top);
}
} //}}} } //}}}
} }

View File

@ -3,7 +3,7 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (C) 2003 Slava Pestov. * Copyright (C) 2003, 2004 Slava Pestov.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -29,23 +29,36 @@
package factor; package factor;
import factor.primitives.*;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
public class FactorDictionary public class FactorDictionary
{ {
// these are defined here for use by the precompiler public FactorWord last;
FactorWord jconstructor;
FactorWord datastackGet;
FactorWord datastackSet;
FactorWord clear;
FactorWord callstackGet;
FactorWord callstackSet;
FactorWord restack;
FactorWord unstack;
FactorWord unwind;
FactorWord jnew; FactorWord jnew;
FactorWord jfield;
FactorWord jvarGet; FactorWord jvarGet;
FactorWord jvarSet; FactorWord jvarSet;
FactorWord jvarGetStatic; FactorWord jvarGetStatic;
FactorWord jvarSetStatic; FactorWord jvarSetStatic;
FactorWord jmethod;
FactorWord jinvoke; FactorWord jinvoke;
FactorWord jinvokeStatic; FactorWord jinvokeStatic;
FactorWord get;
FactorWord set;
FactorWord define;
FactorWord call;
FactorWord bind;
FactorWord choice;
private Map intern; private Map intern;
@ -55,50 +68,65 @@ public class FactorDictionary
intern = new TreeMap(); intern = new TreeMap();
// data stack primitives // data stack primitives
intern("datastack$").def = new FactorPrimitive.P_datastackGet(); datastackGet = intern("datastack$");
intern("datastack@").def = new FactorPrimitive.P_datastackSet(); datastackGet.def = new DatastackGet(
intern("clear").def = new FactorPrimitive.P_clear(); datastackGet);
datastackSet = intern("datastack@");
datastackSet.def = new DatastackSet(
datastackSet);
clear = intern("clear");
clear.def = new Clear(clear);
// call stack primitives // call stack primitives
intern("callstack$").def = new FactorPrimitive.P_callstackGet(); callstackGet = intern("callstack$");
intern("callstack@").def = new FactorPrimitive.P_callstackSet(); callstackGet.def = new CallstackGet(
intern("restack").def = new FactorPrimitive.P_restack(); callstackGet);
intern("unstack").def = new FactorPrimitive.P_unstack(); callstackSet = intern("callstack@");
intern("unwind").def = new FactorPrimitive.P_unwind(); callstackSet.def = new CallstackSet(
callstackSet);
restack = intern("restack");
restack.def = new Restack(restack);
unstack = intern("unstack");
unstack.def = new Unstack(unstack);
unwind = intern("unwind");
unwind.def = new Unwind(unwind);
// reflection primitives // reflection primitives
jconstructor = intern("jconstructor");
jconstructor.def = new FactorPrimitive.P_jconstructor();
jfield = intern("jfield");
jfield.def = new FactorPrimitive.P_jfield();
jinvoke = intern("jinvoke"); jinvoke = intern("jinvoke");
jinvoke.def = new FactorPrimitive.P_jinvoke(); jinvoke.def = new JInvoke(jinvoke);
jinvokeStatic = intern("jinvokeStatic"); jinvokeStatic = intern("jinvoke-static");
jinvokeStatic.def = new FactorPrimitive.P_jinvokeStatic(); jinvokeStatic.def = new JInvokeStatic(
jmethod = intern("jmethod"); jinvokeStatic);
jmethod.def = new FactorPrimitive.P_jmethod();
jnew = intern("jnew"); jnew = intern("jnew");
jnew.def = new FactorPrimitive.P_jnew(); jnew.def = new JNew(jnew);
jvarGet = intern("jvar$"); jvarGet = intern("jvar$");
jvarGet.def = new FactorPrimitive.P_jvarGet(); jvarGet.def = new JVarGet(jvarGet);
jvarGetStatic = intern("jvarStatic$"); jvarGetStatic = intern("jvar-static$");
jvarGetStatic.def = new FactorPrimitive.P_jvarGetStatic(); jvarGetStatic.def = new JVarGetStatic(
jvarGetStatic);
jvarSet = intern("jvar@"); jvarSet = intern("jvar@");
jvarSet.def = new FactorPrimitive.P_jvarSet(); jvarSet.def = new JVarSet(jvarSet);
jvarSetStatic = intern("jvarStatic@"); jvarSetStatic = intern("jvar-static@");
jvarSetStatic.def = new FactorPrimitive.P_jvarSetStatic(); jvarSetStatic.def = new JVarSetStatic(
jvarSetStatic);
// namespaces // namespaces
intern("$").def = new FactorPrimitive.P_get(); get = intern("$");
intern("@").def = new FactorPrimitive.P_set(); get.def = new Get(get);
intern("s@").def = new FactorPrimitive.P_swap_set(); set = intern("@");
set.def = new Set(set);
// definition // definition
intern("define").def = new FactorPrimitive.P_define(); define = intern("define");
define.def = new Define(define);
// combinators // combinators
intern("call").def = new FactorPrimitive.P_call(); call = intern("call");
intern("bind").def = new FactorPrimitive.P_bind(); call.def = new Call(call);
bind = intern("bind");
bind.def = new Bind(bind);
choice = intern("?");
choice.def = new Choice(choice);
} //}}} } //}}}
//{{{ intern() method //{{{ intern() method
@ -114,17 +142,17 @@ public class FactorDictionary
} //}}} } //}}}
//{{{ toWordList() method //{{{ toWordList() method
public FactorList toWordList() public Cons toWordList()
{ {
FactorList first = null; Cons first = null;
FactorList last = null; Cons last = null;
Iterator iter = intern.values().iterator(); Iterator iter = intern.values().iterator();
while(iter.hasNext()) while(iter.hasNext())
{ {
FactorWord word = (FactorWord)iter.next(); FactorWord word = (FactorWord)iter.next();
if(word.def != FactorMissingDefinition.INSTANCE) if(!(word.def instanceof FactorMissingDefinition))
{ {
FactorList cons = new FactorList(word,null); Cons cons = new Cons(word,null);
if(first == null) if(first == null)
first = cons; first = cons;
else else

View File

@ -33,15 +33,15 @@ import java.io.*;
public class FactorInterpreter public class FactorInterpreter
{ {
/** // command line arguments are stored here.
* boot.factor checks this, if its true, an interpreter is run on public Cons args;
* standard input.
*/
public boolean interactive = false;
// boot.factor sets these.
public boolean interactive = true;
public boolean trace = false; public boolean trace = false;
public boolean errorFlag = false; public boolean errorFlag = false;
public boolean compile = true; public boolean compile = true;
public boolean compileDump = false;
public FactorCallFrame callframe; public FactorCallFrame callframe;
public FactorCallStack callstack = new FactorCallStack(); public FactorCallStack callstack = new FactorCallStack();
@ -57,21 +57,9 @@ public class FactorInterpreter
{ {
FactorInterpreter interp = new FactorInterpreter(); FactorInterpreter interp = new FactorInterpreter();
boolean virgin = false; interp.init(args,null);
for(int i = 0; i < args.length; i++) /* if(virgin)
{
if(args[i].equals("-trace"))
interp.trace = true;
else if(args[i].equals("-virgin"))
virgin = true;
else if(args[i].equals("-interp"))
interp.compile = false;
}
interp.interactive = true;
interp.init(null,!virgin);
if(virgin)
{ {
System.out.println("Mini-interpreter"); System.out.println("Mini-interpreter");
BufferedReader in = new BufferedReader( BufferedReader in = new BufferedReader(
@ -89,7 +77,7 @@ public class FactorInterpreter
FactorParser parser = new FactorParser( FactorParser parser = new FactorParser(
"<mini>",new StringReader(line), "<mini>",new StringReader(line),
interp.dict); interp.dict);
FactorList parsed = parser.parse(); Cons parsed = parser.parse();
interp.call(parsed); interp.call(parsed);
interp.run(); interp.run();
System.out.println(interp.datastack); System.out.println(interp.datastack);
@ -98,20 +86,21 @@ public class FactorInterpreter
else else
{ {
interp.run(); interp.run();
} } */
System.exit(0); System.exit(0);
} //}}} } //}}}
//{{{ init() method //{{{ init() method
public void init(Object root, boolean bootstrap) throws Exception public void init(String[] args, Object root) throws Exception
{ {
this.args = Cons.fromArray(args);
callstack.top = 0; callstack.top = 0;
datastack.top = 0; datastack.top = 0;
dict.init(); dict.init();
initNamespace(root); initNamespace(root);
topLevel(); topLevel();
if(bootstrap)
runBootstrap(); runBootstrap();
} //}}} } //}}}
@ -122,8 +111,9 @@ public class FactorInterpreter
global.setVariable("interpreter",this); global.setVariable("interpreter",this);
String[] boundFields = { "compile", "interactive", "trace", String[] boundFields = { "compile", "compileDump",
"dict", "errorFlag" }; "interactive", "trace",
"dict", "errorFlag", "args" };
for(int i = 0; i < boundFields.length; i++) for(int i = 0; i < boundFields.length; i++)
{ {
global.setVariable(boundFields[i], global.setVariable(boundFields[i],
@ -160,7 +150,7 @@ public class FactorInterpreter
if(callframe == null) if(callframe == null)
break; break;
FactorList ip = callframe.ip; Cons ip = callframe.ip;
if(ip == null) if(ip == null)
{ {
@ -213,6 +203,8 @@ public class FactorInterpreter
System.err.println("Factor callstack:"); System.err.println("Factor callstack:");
System.err.println(callstack); System.err.println(callstack);
topLevel();
return true; return true;
} }
else else
@ -231,6 +223,8 @@ public class FactorInterpreter
System.err.println("Factor callstack:"); System.err.println("Factor callstack:");
System.err.println(callstack); System.err.println(callstack);
topLevel();
return true; return true;
} }
} }
@ -240,7 +234,7 @@ public class FactorInterpreter
/** /**
* Pushes the given list of code onto the callstack. * Pushes the given list of code onto the callstack.
*/ */
public final void call(FactorList code) public final void call(Cons code)
{ {
call(dict.intern("call"),code); call(dict.intern("call"),code);
} //}}} } //}}}
@ -249,7 +243,7 @@ public class FactorInterpreter
/** /**
* Pushes the given list of code onto the callstack. * Pushes the given list of code onto the callstack.
*/ */
public final void call(FactorWord word, FactorList code) public final void call(FactorWord word, Cons code)
{ {
if(callframe == null) if(callframe == null)
call(word,global,code); call(word,global,code);
@ -261,7 +255,7 @@ public class FactorInterpreter
/** /**
* Pushes the given list of code onto the callstack. * Pushes the given list of code onto the callstack.
*/ */
public final void call(FactorWord word, FactorNamespace namespace, FactorList code) public final void call(FactorWord word, FactorNamespace namespace, Cons code)
{ {
FactorCallFrame newcf; FactorCallFrame newcf;
@ -321,17 +315,15 @@ public class FactorInterpreter
if(obj instanceof FactorWord) if(obj instanceof FactorWord)
{ {
FactorWord w = (FactorWord)obj;
try try
{ {
w.def.eval(w,this); ((FactorWord)obj).def.eval(this);
} }
catch(Exception e) catch(Exception e)
{ {
callstack.push(callframe); callstack.push(callframe);
callframe = new FactorCallFrame( callframe = new FactorCallFrame(
w, (FactorWord)obj,
callframe.namespace, callframe.namespace,
null); null);
throw e; throw e;

View File

@ -29,22 +29,24 @@
package factor; package factor;
import factor.compiler.LocalAllocator;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.objectweb.asm.*;
/** /**
* A few methods for converting between Java types, and making reflection calls. * A few methods for converting between Java types, and making reflection calls.
* Note that the compiler incorporates calls to some of these methods in * Note that the compiler incorporates calls to some of these methods in
* generated bytecode. * generated bytecode.
*/ */
public class FactorJava public class FactorJava implements Constants
{ {
public static final Class[] EMPTY_ARRAY = new Class[0]; public static final Class[] EMPTY_ARRAY = new Class[0];
//{{{ classNameToClassList() method //{{{ classNameToClassList() method
public static Class[] classNameToClassList(FactorList classes) public static Class[] classNameToClassList(Cons classes)
throws Exception throws Exception
{ {
if(classes == null) if(classes == null)
@ -54,7 +56,31 @@ public class FactorJava
int i = 0; int i = 0;
while(classes != null) while(classes != null)
{ {
_classes[i++] = (Class)classes.car(Class.class); Object car = classes.car;
if(car instanceof Cons)
{
Cons classSpec = (Cons)car;
if(classSpec.cdr != null)
{
throw new FactorRuntimeException(
"Bad class spec: " + car);
}
Class clazz = (Class)classSpec.car(Class.class);
if(clazz.isPrimitive())
{
_classes[i] = getClass("["
+ javaClassToVMClass(clazz));
}
else
{
_classes[i] = getClass("[L"
+ clazz.getName() + ";");
}
}
else
_classes[i] = (Class)classes.car(Class.class);
i++;
classes = classes.next(); classes = classes.next();
} }
@ -183,6 +209,29 @@ public class FactorJava
} }
} //}}} } //}}}
//{{{ toNamespace() method
public static FactorNamespace toNamespace(Object obj,
FactorInterpreter interp) throws Exception
{
if(obj instanceof FactorNamespace)
return (FactorNamespace)obj;
else if(obj instanceof FactorObject)
{
FactorNamespace ns = ((FactorObject)obj)
.getNamespace(interp);
if(ns == null)
throw new FactorRuntimeException(
obj + " has a null"
+ " namespace");
return ns;
}
else
{
throw new FactorDomainException(obj,
FactorObject.class);
}
} //}}}
//{{{ toArray() method //{{{ toArray() method
public static Object[] toArray(Object arg) public static Object[] toArray(Object arg)
throws FactorDomainException throws FactorDomainException
@ -194,9 +243,9 @@ public class FactorJava
public static Object[] toArray(Object arg, Class clas) public static Object[] toArray(Object arg, Class clas)
throws FactorDomainException throws FactorDomainException
{ {
if(arg instanceof FactorList) if(arg instanceof Cons)
{ {
FactorList list = (FactorList)arg; Cons list = (Cons)arg;
Object[] array = (Object[]) Object[] array = (Object[])
Array.newInstance( Array.newInstance(
clas.getComponentType(), clas.getComponentType(),
@ -205,7 +254,21 @@ public class FactorJava
return array; return array;
} }
else if(arg.getClass().isArray()) else if(arg.getClass().isArray())
{
if(arg.getClass() == clas)
return (Object[])arg; return (Object[])arg;
else
{
Object[] _arg = (Object[])arg;
Object[] array = (Object[])
Array.newInstance(
clas.getComponentType(),
_arg.length);
System.arraycopy(arg,0,array,0,
_arg.length);
return array;
}
}
else else
throw new FactorDomainException(arg,Object[].class); throw new FactorDomainException(arg,Object[].class);
} //}}} } //}}}
@ -387,7 +450,7 @@ public class FactorJava
} //}}} } //}}}
//{{{ jconstructor() method //{{{ jconstructor() method
public static Constructor jconstructor(String inClass, FactorList args) public static Constructor jconstructor(String inClass, Cons args)
throws Exception throws Exception
{ {
return Class.forName(inClass).getConstructor( return Class.forName(inClass).getConstructor(
@ -458,7 +521,7 @@ public class FactorJava
//{{{ jmethod() method //{{{ jmethod() method
public static Method jmethod(String method, String inClass, public static Method jmethod(String method, String inClass,
FactorList args) throws Exception Cons args) throws Exception
{ {
return Class.forName(inClass).getMethod(method, return Class.forName(inClass).getMethod(method,
classNameToClassList(args)); classNameToClassList(args));
@ -519,4 +582,126 @@ public class FactorJava
else else
return e; return e;
} //}}} } //}}}
//{{{ generateFromConversion() method
/**
* Unbox value at top of the stack.
*/
public static void generateFromConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == Object.class)
return;
String methodName = null;
boolean interpArg = false;
if(type == Number.class)
methodName = "toNumber";
else if(type == String.class)
methodName = "toString";
else if(type == boolean.class)
methodName = "toBoolean";
else if(type == char.class)
methodName = "toChar";
else if(type == int.class)
methodName = "toInt";
else if(type == long.class)
methodName = "toLong";
else if(type == float.class)
methodName = "toFloat";
else if(type == double.class)
methodName = "toDouble";
else if(type == Class.class)
methodName = "toClass";
else if(type == FactorNamespace.class)
{
methodName = "toNamespace";
interpArg = true;
}
else if(type.isArray())
methodName = "toArray";
if(methodName == null)
{
mw.visitTypeInsn(CHECKCAST,
type.getName()
.replace('.','/'));
}
else
{
if(interpArg)
{
mw.visitVarInsn(ALOAD,0);
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
methodName,
"(Ljava/lang/Object;Lfactor/FactorInterpreter;)"
+ FactorJava.javaClassToVMClass(type));
}
else
{
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
methodName,
"(Ljava/lang/Object;)"
+ FactorJava.javaClassToVMClass(type));
}
}
} //}}}
//{{{ generateToConversionPre() method
/**
* Avoid having to deal with category 1/2 computational type
* distinction.
*/
public static boolean generateToConversionPre(CodeVisitor mw,
Class type) throws Exception
{
if(type != boolean.class)
{
Class boxingType = FactorJava.javaBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitTypeInsn(NEW,boxingName);
mw.visitInsn(DUP);
return true;
}
}
return false;
} //}}}
//{{{ generateToConversion() method
/**
* Box return value, if needed.
*/
public static void generateToConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == boolean.class)
{
// this case is handled specially
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
"fromBoolean",
"(Z)Ljava/lang/Object;");
}
else
{
Class boxingType = FactorJava.javaBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitMethodInsn(INVOKESPECIAL,boxingName,
"<init>",
"(" + FactorJava.javaClassToVMClass(
type) + ")V");
}
}
} //}}}
} }

View File

@ -36,12 +36,6 @@ import java.io.*;
*/ */
public class FactorLib public class FactorLib
{ {
//{{{ branch2() method
public static Object branch2(boolean condition, Object o1, Object o2)
{
return (condition ? o1 : o2);
} //}}}
//{{{ branch3() method //{{{ branch3() method
public static Object branch3(float x, float y, public static Object branch3(float x, float y,
Object o1, Object o2, Object o3) Object o1, Object o2, Object o3)
@ -54,36 +48,6 @@ public class FactorLib
return o3; return o3;
} //}}} } //}}}
//{{{ cat() method
public static String cat(FactorList list)
{
StringBuffer buf = new StringBuffer();
while(list != null)
{
if(list.car instanceof FactorList)
buf.append(cat((FactorList)list.car));
else
buf.append(list.car);
list = list.next();
}
return buf.toString();
} //}}}
//{{{ cat2() method
public static String cat2(Object str1, Object str2)
{
return new StringBuffer().append(str1).append(str2).toString();
} //}}}
//{{{ cat3() method
public static String cat3(Object str1, Object str2, Object str3)
{
return new StringBuffer().append(str1).append(str2).append(str3)
.toString();
} //}}}
//{{{ cloneArray() method //{{{ cloneArray() method
public static Object[] cloneArray(Object[] array) public static Object[] cloneArray(Object[] array)
{ {

View File

@ -3,7 +3,7 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (C) 2003 Slava Pestov. * Copyright (C) 2003,2004 Slava Pestov.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -282,6 +282,12 @@ public class FactorMath
return min + Math.abs(nextInt % (max - min + 1)); return min + Math.abs(nextInt % (max - min + 1));
} //}}} } //}}}
//{{{ randomFloat() method
public static float randomFloat(int min, int max, float scale)
{
return randomInt(min,max) / scale;
} //}}}
//{{{ sgn() method //{{{ sgn() method
public static int sgn(float num) public static int sgn(float num)
{ {

View File

@ -3,7 +3,7 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (C) 2003 Slava Pestov. * Copyright (C) 2003, 2004 Slava Pestov.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -29,16 +29,22 @@
package factor; package factor;
import factor.compiler.*;
import java.util.Set;
/** /**
* A placeholder for an undefined word. * A placeholder for an undefined word.
*/ */
public class FactorMissingDefinition extends FactorWordDefinition public class FactorMissingDefinition extends FactorWordDefinition
{ {
public static final FactorMissingDefinition INSTANCE //{{{ FactorMissingDefinition constructor
= new FactorMissingDefinition(); public FactorMissingDefinition(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method //{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp) public void eval(FactorInterpreter interp)
throws FactorUndefinedWordException throws FactorUndefinedWordException
{ {
throw new FactorUndefinedWordException(word); throw new FactorUndefinedWordException(word);

View File

@ -115,7 +115,7 @@ public class FactorNamespace implements PublicCloneable
/** /**
* Defines a variable bound to a Java field. * Defines a variable bound to a Java field.
*/ */
public void importVars(String clazz, FactorList vars) public void importVars(String clazz, Cons vars)
throws Exception throws Exception
{ {
Class clas = Class.forName(clazz); Class clas = Class.forName(clazz);
@ -157,16 +157,6 @@ public class FactorNamespace implements PublicCloneable
return o; return o;
} //}}} } //}}}
//{{{ _setVariable() method
/**
* Alternative form for bindings.
*/
public void _setVariable(Object value, String name)
throws Exception
{
setVariable(name,value);
} //}}}
//{{{ setVariable() method //{{{ setVariable() method
public void setVariable(String name, Object value) public void setVariable(String name, Object value)
throws Exception throws Exception
@ -214,10 +204,10 @@ public class FactorNamespace implements PublicCloneable
/** /**
* Returns a list of variable and word names defined in this namespace. * Returns a list of variable and word names defined in this namespace.
*/ */
public FactorList toVarList() public Cons toVarList()
{ {
FactorList first = null; Cons first = null;
FactorList last = null; Cons last = null;
Iterator iter = words.entrySet().iterator(); Iterator iter = words.entrySet().iterator();
while(iter.hasNext()) while(iter.hasNext())
{ {
@ -226,7 +216,7 @@ public class FactorNamespace implements PublicCloneable
continue; continue;
String name = (String)entry.getKey(); String name = (String)entry.getKey();
FactorList cons = new FactorList(name,null); Cons cons = new Cons(name,null);
if(first == null) if(first == null)
first = last = cons; first = last = cons;
else else
@ -243,10 +233,10 @@ public class FactorNamespace implements PublicCloneable
/** /**
* Returns a list of pairs of variable and word names, and their values. * Returns a list of pairs of variable and word names, and their values.
*/ */
public FactorList toValueList() public Cons toValueList()
{ {
FactorList first = null; Cons first = null;
FactorList last = null; Cons last = null;
Iterator iter = words.entrySet().iterator(); Iterator iter = words.entrySet().iterator();
while(iter.hasNext()) while(iter.hasNext())
{ {
@ -254,8 +244,8 @@ public class FactorNamespace implements PublicCloneable
if(entry.getValue() == CHECK_PARENT) if(entry.getValue() == CHECK_PARENT)
continue; continue;
FactorList cons = new FactorList( Cons cons = new Cons(
new FactorList(entry.getKey(), new Cons(entry.getKey(),
entry.getValue()),null); entry.getValue()),null);
if(first == null) if(first == null)
first = last = cons; first = last = cons;
@ -299,7 +289,13 @@ public class FactorNamespace implements PublicCloneable
//{{{ toString() method //{{{ toString() method
public String toString() public String toString()
{ {
return "Namespace[" + obj + "]"; if(obj == null)
{
return "( Namespace #" + Integer.toString(hashCode(),16)
+ " )";
}
else
return "( Namespace: " + obj + " #" + hashCode() + " )";
} //}}} } //}}}
//{{{ clone() method //{{{ clone() method

View File

@ -108,10 +108,10 @@ public class FactorParser
* Reads the file being parsed, and returns a list of all tokens that * Reads the file being parsed, and returns a list of all tokens that
* were read in. This list can be evaluated to run the file. * were read in. This list can be evaluated to run the file.
*/ */
public FactorList parse() throws IOException, FactorParseException public Cons parse() throws IOException, FactorParseException
{ {
FactorList first = null; Cons first = null;
FactorList last = null; Cons last = null;
try try
{ {
@ -131,12 +131,15 @@ public class FactorParser
error("Expected word name after " + next); error("Expected word name after " + next);
} }
FactorWordDefinition def = readDef(); FactorWord word = (FactorWord)obj;
FactorList l = new FactorList(DEFINE,null); FactorWordDefinition def
FactorList cons = new FactorList( = readDef(word);
((FactorWord)obj).name,
new FactorList(def,l)); Cons l = new Cons(DEFINE,null);
Cons cons = new Cons(
word.name,
new Cons(def,l));
if(first == null) if(first == null)
first = cons; first = cons;
else else
@ -152,12 +155,15 @@ public class FactorParser
error("Expected word name after " + next); error("Expected word name after " + next);
} }
FactorWordDefinition def = readShuffle(); FactorWord word = (FactorWord)obj;
FactorList l = new FactorList(DEFINE,null); FactorWordDefinition def
FactorList cons = new FactorList( = readShuffle(word);
((FactorWord)obj).name,
new FactorList(def,l)); Cons l = new Cons(DEFINE,null);
Cons cons = new Cons(
word.name,
new Cons(def,l));
if(first == null) if(first == null)
first = cons; first = cons;
else else
@ -166,7 +172,7 @@ public class FactorParser
} }
else if(next == BRA) else if(next == BRA)
{ {
FactorList cons = new FactorList( Cons cons = new Cons(
readList(),null); readList(),null);
if(first == null) if(first == null)
first = cons; first = cons;
@ -180,7 +186,7 @@ public class FactorParser
} }
else else
{ {
FactorList cons = new FactorList(next,null); Cons cons = new Cons(next,null);
if(first == null) if(first == null)
first = cons; first = cons;
else else
@ -323,10 +329,10 @@ public class FactorParser
/** /**
* Read list until ;. * Read list until ;.
*/ */
private FactorWordDefinition readDef() private FactorWordDefinition readDef(FactorWord word)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
return new FactorCompoundDefinition(readList(INE,false)); return new FactorCompoundDefinition(word,readList(INE,false));
} //}}} } //}}}
//{{{ readShuffle() method //{{{ readShuffle() method
@ -336,7 +342,7 @@ public class FactorParser
* On the left is inputs, on the right is their arrangement on the * On the left is inputs, on the right is their arrangement on the
* stack. * stack.
*/ */
private FactorWordDefinition readShuffle() private FactorWordDefinition readShuffle(FactorWord word)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
// 0 in consume map is last consumed, n is first consumed. // 0 in consume map is last consumed, n is first consumed.
@ -377,13 +383,14 @@ public class FactorParser
} }
} }
FactorList _shuffle = readList(FLE,false); Cons _shuffle = readList(FLE,false);
int consume = consumeMap.size(); int consume = consumeMap.size();
if(_shuffle == null) if(_shuffle == null)
{ {
return new FactorShuffleDefinition(consumeD,consumeR, return new FactorShuffleDefinition(word,
consumeD,consumeR,
null,0,null,0); null,0,null,0);
} }
@ -397,12 +404,12 @@ public class FactorParser
{ {
if(_shuffle.car instanceof FactorWord) if(_shuffle.car instanceof FactorWord)
{ {
FactorWord word = ((FactorWord)_shuffle.car); FactorWord w = ((FactorWord)_shuffle.car);
String name = word.name; String name = w.name;
if(name.startsWith("r:")) if(name.startsWith("r:"))
word = dict.intern(name.substring(2)); w = dict.intern(name.substring(2));
Integer _index = (Integer)consumeMap.get(word); Integer _index = (Integer)consumeMap.get(w);
if(_index == null) if(_index == null)
error("Does not appear in shuffle LHS: " + _shuffle.car); error("Does not appear in shuffle LHS: " + _shuffle.car);
int index = _index.intValue(); int index = _index.intValue();
@ -445,7 +452,7 @@ public class FactorParser
shuffleD[k++] = index; shuffleD[k++] = index;
} }
return new FactorShuffleDefinition(consumeD,consumeR, return new FactorShuffleDefinition(word,consumeD,consumeR,
shuffleD,shuffleDlength,shuffleR,shuffleRlength); shuffleD,shuffleDlength,shuffleR,shuffleRlength);
} //}}} } //}}}
@ -453,7 +460,7 @@ public class FactorParser
/** /**
* Read list until ]. * Read list until ].
*/ */
private FactorList readList() private Cons readList()
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
return readList(KET,true); return readList(KET,true);
@ -463,11 +470,11 @@ public class FactorParser
/** /**
* Read list until a given word. * Read list until a given word.
*/ */
private FactorList readList(FactorWord until, boolean allowCommaPair) private Cons readList(FactorWord until, boolean allowCommaPair)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
FactorList first = null; Cons first = null;
FactorList last = null; Cons last = null;
for(;;) for(;;)
{ {
@ -509,12 +516,12 @@ public class FactorParser
} }
else if(next == BRA) else if(next == BRA)
{ {
FactorList list = readList(); Cons list = readList();
if(first == null) if(first == null)
first = last = new FactorList(list,null); first = last = new Cons(list,null);
else else
{ {
FactorList nextList = new FactorList(list,null); Cons nextList = new Cons(list,null);
last.cdr = nextList; last.cdr = nextList;
last = nextList; last = nextList;
} }
@ -522,10 +529,10 @@ public class FactorParser
else if(isParsingWord(next)) else if(isParsingWord(next))
error("Unexpected " + next); error("Unexpected " + next);
else if(first == null) else if(first == null)
first = last = new FactorList(next,null); first = last = new Cons(next,null);
else else
{ {
FactorList nextList = new FactorList(next,null); Cons nextList = new Cons(next,null);
last.cdr = nextList; last.cdr = nextList;
last = nextList; last = nextList;
} }

View File

@ -1,374 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor;
import java.lang.reflect.*;
public abstract class FactorPrimitive extends FactorWordDefinition
{
//{{{ P_callstackGet class
static class P_callstackGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.callstack.clone());
}
} //}}}
//{{{ P_callstackSet class
static class P_callstackSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.callstack = (FactorCallStack)((FactorCallStack)
interp.datastack.pop(FactorCallStack.class))
.clone();
}
} //}}}
//{{{ P_datastackGet class
static class P_datastackGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.datastack.clone());
}
} //}}}
//{{{ P_datastackSet class
static class P_datastackSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack = (FactorDataStack)((FactorDataStack)
interp.datastack.pop(FactorDataStack.class))
.clone();
}
} //}}}
//{{{ P_clear class
static class P_clear extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.top = 0;
}
} //}}}
//{{{ P_restack class
static class P_restack extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorList list = (FactorList)datastack.pop(FactorList.class);
interp.callstack.push(datastack);
interp.datastack = new FactorDataStack(list);
}
} //}}}
//{{{ P_unstack class
static class P_unstack extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorList unstack = interp.datastack.toList();
interp.datastack = (FactorDataStack)interp.callstack.pop();
interp.datastack.push(unstack);
}
} //}}}
//{{{ P_unwind class
static class P_unwind extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.callstack.top = 0;
}
} //}}}
//{{{ P_jconstructor class
static class P_jconstructor extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jconstructor(
(String)datastack.pop(String.class),
(FactorList)datastack.pop(FactorList.class)));
}
} //}}}
//{{{ P_jfield class
static class P_jfield extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class)));
}
} //}}}
//{{{ P_jinvoke class
static class P_jinvoke extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jinvoke(datastack,
(Method)datastack.pop(),
datastack.pop());
}
} //}}}
//{{{ P_jinvokeStatic class
static class P_jinvokeStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jinvokeStatic(datastack,
(Method)datastack.pop());
}
} //}}}
//{{{ P_jmethod class
static class P_jmethod extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jmethod(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class),
(FactorList)datastack.pop(FactorList.class)));
}
} //}}}
//{{{ P_jnew class
static class P_jnew extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jnew(datastack,
(Constructor)datastack.pop());
}
} //}}}
//{{{ P_jvarGet class
static class P_jvarGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jvarGet(
(Field)datastack.pop(Field.class),
datastack.pop()));
}
} //}}}
//{{{ P_jvarGetStatic class
static class P_jvarGetStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jvarGetStatic(
(Field)datastack.pop(Field.class)));
}
} //}}}
//{{{ P_jvarSet class
static class P_jvarSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jvarSet(
(Field)datastack.pop(Field.class),
datastack.pop(),
datastack.pop());
}
} //}}}
//{{{ P_jvarSetStatic class
static class P_jvarSetStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jvarSetStatic(
(Field)datastack.pop(Field.class),
datastack.pop());
}
} //}}}
//{{{ P_get class
static class P_get extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(interp.callframe.namespace.getVariable(
(String)datastack.pop(String.class)));
}
} //}}}
//{{{ P_set class
static class P_set extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
interp.callframe.namespace.setVariable(
(String)datastack.pop(String.class),
datastack.pop());
}
} //}}}
//{{{ P_swap_set class
static class P_swap_set extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
interp.callframe.namespace._setVariable(datastack.pop(),
(String)datastack.pop(String.class));
}
} //}}}
//{{{ P_define class
static class P_define extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorDictionary dict = interp.dict;
// handle old define syntax
Object obj = datastack.pop();
if(obj instanceof FactorList)
obj = new FactorCompoundDefinition((FactorList)obj);
FactorWordDefinition def = (FactorWordDefinition)obj;
FactorWord newWord = interp.dict.intern(
(String)datastack.pop(String.class));
def.precompile(newWord,interp);
try
{
if(interp.compile)
def = def.compile(newWord,interp);
}
catch(Throwable t)
{
System.err.println("WARNING: cannot compile " + newWord);
t.printStackTrace();
}
if(newWord.def != FactorMissingDefinition.INSTANCE)
{
System.err.println("WARNING: redefining " + newWord);
newWord.history = new FactorList(newWord.def,
newWord.history);
}
newWord.def = def;
}
} //}}}
//{{{ P_call class
static class P_call extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.call(word,(FactorList)interp.datastack.pop(
FactorList.class));
}
} //}}}
//{{{ P_bind class
static class P_bind extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorList code = (FactorList)datastack.pop(FactorList.class);
Object obj = datastack.pop();
FactorNamespace ns;
if(obj instanceof FactorNamespace)
ns = (FactorNamespace)obj;
else if(obj instanceof FactorObject)
{
ns = ((FactorObject)obj).getNamespace(interp);
if(ns == null)
throw new FactorRuntimeException(
obj + " has a null"
+ " namespace");
}
else
{
throw new FactorDomainException(obj,
FactorObject.class);
}
interp.call(word,ns,code);
}
} //}}}
}

View File

@ -1,394 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor;
import java.lang.reflect.*;
import org.objectweb.asm.*;
class FactorReflectionForm implements Constants
{
private FactorList form;
//{{{ FactorReflectionForm constructor
FactorReflectionForm(FactorList form)
{
this.form = form;
} //}}}
//{{{ compile() method
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car == dict.jvarGet)
{
return compileVarGet(word,interp,cw,mw,
form.next(),false);
}
else if(form.car == dict.jvarGetStatic)
{
return compileVarGet(word,interp,cw,mw,
form.next(),true);
}
else if(form.car == dict.jinvoke)
{
return compileInvoke(word,interp,cw,mw,
form.next(),false);
}
else if(form.car == dict.jinvokeStatic)
{
return compileInvoke(word,interp,cw,mw,
form.next(),true);
}
else if(form.car == dict.jnew)
{
return compileNew(word,interp,cw,mw,
form.next());
}
else
throw new FactorRuntimeException("Cannot compile " + form.car);
} //}}}
//{{{ compileVarGet() method
private boolean compileVarGet(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form,
boolean staticGet) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jfield)
return false;
form = form.next();
String field = (String)form.car;
String clazz = (String)form.next().car;
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
if(!staticGet)
{
mw.visitInsn(DUP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "pop",
"()Ljava/lang/Object;");
}
Class cls = FactorJava.getClass(clazz);
generateFromConversion(mw,cls);
Field fld = cls.getField(field);
clazz = clazz.replace('.','/');
mw.visitFieldInsn(staticGet ? GETSTATIC : GETFIELD,
clazz,
field,
FactorJava.javaClassToVMClass(fld.getType()));
generateToConversion(mw,fld.getType());
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(3,3);
return true;
} //}}}
//{{{ compileInvoke() method
private boolean compileInvoke(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form,
boolean staticInvoke) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jmethod)
return false;
form = form.next();
String method = (String)form.car;
String clazz = (String)form.next().car;
Class[] args = FactorJava.classNameToClassList(
(FactorList)form.next().next().car);
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
if(!staticInvoke)
{
mw.visitInsn(DUP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "pop",
"()Ljava/lang/Object;");
generateFromConversion(mw,cls);
if(args.length != 0)
mw.visitInsn(SWAP);
}
generateArgs(mw,args,!staticInvoke);
Method mth = cls.getMethod(method,args);
Class returnType = mth.getReturnType();
int opcode;
if(staticInvoke)
opcode = INVOKESTATIC;
else if(cls.isInterface())
opcode = INVOKEINTERFACE;
else
opcode = INVOKEVIRTUAL;
mw.visitMethodInsn(opcode,
clazz,
method,
FactorJava.javaSignatureToVMSignature(
args,returnType));
if(returnType != Void.TYPE)
{
generateToConversion(mw,returnType);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
}
else
mw.visitInsn(POP);
mw.visitInsn(RETURN);
mw.visitMaxs(4 + args.length,5);
return true;
} //}}}
//{{{ compileNew() method
private boolean compileNew(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jconstructor)
return false;
form = form.next();
String clazz = (String)form.car;
Class[] args = FactorJava.classNameToClassList(
(FactorList)form.next().car);
clazz = clazz.replace('.','/');
mw.visitTypeInsn(NEW,clazz);
mw.visitInsn(DUP);
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
generateArgs(mw,args,true);
mw.visitMethodInsn(INVOKESPECIAL,
clazz,
"<init>",
FactorJava.javaSignatureToVMSignature(
args,void.class));
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(5 + args.length,5);
return true;
} //}}}
//{{{ generateArgs() method
/**
* Generate instructions for copying arguments from the Factor
* datastack to the JVM stack. The types array is used to
* perform type conversions.
*/
private void generateArgs(CodeVisitor mw, Class[] args,
boolean generateSwap) throws Exception
{
if(args.length != 0)
{
// ensure the stack has enough elements
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,args.length);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
// datastack.stack -> 3
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,3);
// datastack.top-args.length -> 4
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitIntInsn(BIPUSH,args.length);
mw.visitInsn(ISUB);
// datastack.top -= args.length
mw.visitInsn(DUP2);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitVarInsn(ISTORE,4);
if(generateSwap)
mw.visitInsn(SWAP);
for(int i = 0; i < args.length; i++)
{
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitInsn(AALOAD);
generateFromConversion(mw,args[i]);
if(i != args.length - 1)
mw.visitIincInsn(4,1);
}
}
} //}}}
//{{{ generateFromConversion() method
/**
* Unbox value at top of the stack.
*/
private void generateFromConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == Object.class)
return;
String methodName = null;
if(type == Number.class)
methodName = "toNumber";
else if(type == String.class)
methodName = "toString";
else if(type == boolean.class)
methodName = "toBoolean";
else if(type == char.class)
methodName = "toChar";
else if(type == int.class)
methodName = "toInt";
else if(type == long.class)
methodName = "toLong";
else if(type == float.class)
methodName = "toFloat";
else if(type == double.class)
methodName = "toDouble";
else if(type == Class.class)
methodName = "toClass";
else if(type.isArray())
methodName = "toArray";
if(methodName == null)
{
mw.visitTypeInsn(CHECKCAST,
type.getName()
.replace('.','/'));
}
else
{
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
methodName,
"(Ljava/lang/Object;)"
+ FactorJava.javaClassToVMClass(type));
}
} //}}}
//{{{ generateToConversion() method
/**
* Box return value, if needed.
*/
private void generateToConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == boolean.class)
{
// this case is handled specially
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
"fromBoolean",
"(Z)Ljava/lang/Object;");
}
else
{
Class boxingType = FactorJava.javaBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitTypeInsn(NEW,boxingName);
mw.visitInsn(DUP_X1);
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKESPECIAL,boxingName,
"<init>",
"(" + FactorJava.javaClassToVMClass(
type) + ")V");
}
}
} //}}}
//{{{ toString() method
public String toString()
{
return form.toString();
} //}}}
}

View File

@ -29,7 +29,10 @@
package factor; package factor;
import factor.compiler.*;
import java.util.Set;
import org.objectweb.asm.*; import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/** /**
* ~<< name ... -- >>~ * ~<< name ... -- >>~
@ -63,10 +66,13 @@ public class FactorShuffleDefinition extends FactorWordDefinition
private Object[] temporaryR; private Object[] temporaryR;
//{{{ FactorShuffleDefinition constructor //{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(int consumeD, int consumeR, public FactorShuffleDefinition(FactorWord word,
int consumeD, int consumeR,
int[] shuffleD, int shuffleDlength, int[] shuffleD, int shuffleDlength,
int[] shuffleR, int shuffleRlength) int[] shuffleR, int shuffleRlength)
{ {
super(word);
this.consumeD = consumeD; this.consumeD = consumeD;
this.consumeR = consumeR; this.consumeR = consumeR;
this.shuffleD = shuffleD; this.shuffleD = shuffleD;
@ -102,295 +108,49 @@ public class FactorShuffleDefinition extends FactorWordDefinition
} }
} //}}} } //}}}
//{{{ canCompile() method //{{{ getStackEffect() method
boolean canCompile() public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{ {
return true; state.ensure(state.datastack,consumeD);
state.ensure(state.callstack,consumeR);
eval(state.datastack,state.callstack);
return new StackEffect(consumeD,shuffleDlength,
consumeR,shuffleRlength);
} //}}} } //}}}
//{{{ compile() method //{{{ compile() method
/** /**
* Write the definition of the eval() method in the compiled word. * Compile the given word, returning a new word definition.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/ */
boolean compile(FactorWord word, FactorInterpreter interp, FactorWordDefinition compile(FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw) Set recursiveCheck) throws Exception
throws Exception
{ {
boolean fromD = false; return this;
boolean fromR = false; } //}}}
for(int i = 0; i < shuffleDlength; i++)
{
fromD = true;
if((shuffleD[i] & FROM_R_MASK) == FROM_R_MASK)
{
fromR = true;
break;
}
}
for(int i = 0; i < shuffleRlength; i++)
{
fromR = true;
if((shuffleR[i] & FROM_R_MASK) == FROM_R_MASK)
{
fromR = true;
break;
}
}
// Local 3 -- datastack //{{{ compileCallTo() method
// Local 4 -- datastack top-consumeD /**
// Local 5 -- datastack array * Compile a call to this word. Returns maximum JVM stack use.
if(consumeD != 0 || fromD) */
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws FactorStackException
{ {
// (datastack datastack datastack) eval(allocator.datastack,allocator.callstack);
mw.visitVarInsn(ALOAD,2); return 0;
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
mw.visitInsn(DUP);
if(consumeD != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// datastack -> 3
mw.visitVarInsn(ASTORE,3);
// datastack.top-consumeD -> 4
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeD != 0)
{
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,4);
// datastack.stack -> 5
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
}
// Local 6 -- callstack
// Local 7 -- callstack top-consumeR
// Local 8 -- callstack array
if(consumeR != 0 || fromR)
{
// (callstack callstack)
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "callstack",
"Lfactor/FactorCallStack;");
mw.visitInsn(DUP);
if(consumeR != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// callstack -> 6
mw.visitVarInsn(ASTORE,6);
// callstack.top-consumeR -> 7
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeR != 0)
{
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,7);
// callstack.stack -> 8
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
}
int locals = 9;
if(shuffleD != null)
{
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top-consumeD+shuffleD[i]] -> 9+i
int index = shuffleD[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,9 + i);
}
locals += shuffleDlength;
}
if(shuffleR != null)
{
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top-consumeR+shuffleR[i]] -> 9+i
int index = shuffleR[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,locals + i);
}
}
if(shuffleD != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,3);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the datastack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top - consumeD + i] <- 9+i
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,9 + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeD != 0)
{
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
if(shuffleR != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,6);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the callstack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top - consumeD + i] <- locals+i
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,locals + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitIntInsn(BIPUSH,shuffleRlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeR != 0)
{
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
mw.visitInsn(RETURN);
// Max stack and locals
mw.visitMaxs(4,9 + shuffleDlength + shuffleRlength);
return true;
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp) public void eval(FactorInterpreter interp)
throws FactorStackException throws FactorStackException
{ {
FactorArrayStack datastack = interp.datastack; eval(interp.datastack,interp.callstack);
FactorArrayStack callstack = interp.callstack; } //}}}
//{{{ eval() method
public void eval(FactorArrayStack datastack, FactorArrayStack callstack)
throws FactorStackException
{
if(datastack.top < consumeD) if(datastack.top < consumeD)
throw new FactorStackException(consumeD); throw new FactorStackException(consumeD);
@ -398,10 +158,16 @@ public class FactorShuffleDefinition extends FactorWordDefinition
throw new FactorStackException(consumeR); throw new FactorStackException(consumeR);
if(shuffleD != null) if(shuffleD != null)
shuffle(interp,datastack,consumeD,consumeR,shuffleD,temporaryD); {
shuffle(datastack,callstack,datastack,consumeD,consumeR,
shuffleD,temporaryD);
}
if(shuffleR != null) if(shuffleR != null)
shuffle(interp,callstack,consumeD,consumeR,shuffleR,temporaryR); {
shuffle(datastack,callstack,callstack,consumeD,consumeR,
shuffleR,temporaryR);
}
datastack.top -= consumeD; datastack.top -= consumeD;
if(temporaryD != null) if(temporaryD != null)
@ -414,8 +180,14 @@ public class FactorShuffleDefinition extends FactorWordDefinition
} //}}} } //}}}
//{{{ shuffle() method //{{{ shuffle() method
private void shuffle(FactorInterpreter interp, FactorArrayStack stack, private void shuffle(
int consumeD, int consumeR, int[] shuffle, Object[] temporary) FactorArrayStack datastack,
FactorArrayStack callstack,
FactorArrayStack stack,
int consumeD,
int consumeR,
int[] shuffle,
Object[] temporary)
throws FactorStackException throws FactorStackException
{ {
for(int i = 0; i < temporary.length; i++) for(int i = 0; i < temporary.length; i++)
@ -426,15 +198,15 @@ public class FactorShuffleDefinition extends FactorWordDefinition
int consume; int consume;
if((index & FROM_R_MASK) == FROM_R_MASK) if((index & FROM_R_MASK) == FROM_R_MASK)
{ {
array = interp.callstack.stack; array = callstack.stack;
top = interp.callstack.top; top = callstack.top;
index = (index & ~FROM_R_MASK); index = (index & ~FROM_R_MASK);
consume = consumeR; consume = consumeR;
} }
else else
{ {
array = interp.datastack.stack; array = datastack.stack;
top = interp.datastack.top; top = datastack.top;
consume = consumeD; consume = consumeD;
} }
temporary[i] = array[top - consume + index]; temporary[i] = array[top - consume + index];

View File

@ -29,8 +29,8 @@
package factor; package factor;
import java.util.HashMap; import factor.compiler.FactorCompilerException;
import java.util.Map; import java.util.*;
/** /**
* An internalized symbol. * An internalized symbol.
@ -44,10 +44,20 @@ public class FactorWord implements FactorExternalizable
*/ */
public FactorWordDefinition def; public FactorWordDefinition def;
/**
* Definition before compiling.
*/
public FactorWordDefinition uncompiled;
/** /**
* "define" pushes previous definitions onto this list, like a stack. * "define" pushes previous definitions onto this list, like a stack.
*/ */
public FactorList history; public Cons history;
/**
* Is this word referenced from a compiled word?
*/
public boolean compileRef;
//{{{ FactorWord constructor //{{{ FactorWord constructor
/** /**
@ -58,7 +68,64 @@ public class FactorWord implements FactorExternalizable
public FactorWord(String name) public FactorWord(String name)
{ {
this.name = name; this.name = name;
def = FactorMissingDefinition.INSTANCE; def = new FactorMissingDefinition(this);
} //}}}
//{{{ define() method
public void define(FactorWordDefinition def)
{
if(compileRef)
{
System.err.println("WARNING: " + this
+ " is used in one or more compiled words; old definition will remain until full recompile");
}
else if(!(this.def instanceof FactorMissingDefinition))
{
System.err.println("WARNING: redefining " + this);
history = new Cons(this.def,history);
}
uncompiled = this.def = def;
} //}}}
//{{{ compile() method
public void compile(FactorInterpreter interp)
{
compile(interp,new HashSet());
} //}}}
//{{{ compile() method
public void compile(FactorInterpreter interp, Set recursiveCheck)
{
if(def.compileFailed)
return;
System.err.println("Compiling " + this);
if(recursiveCheck.contains(this))
System.err.println("WARNING: cannot compile recursive calls: " + this);
try
{
recursiveCheck.add(this);
def = def.compile(interp,recursiveCheck);
}
catch(FactorCompilerException e)
{
def.compileFailed = true;
System.err.println("WARNING: cannot compile " + this);
System.err.println(e.getMessage());
}
catch(Throwable t)
{
def.compileFailed = true;
System.err.println("WARNING: cannot compile " + this);
t.printStackTrace();
}
finally
{
recursiveCheck.remove(this);
}
} //}}} } //}}}
//{{{ toString() method //{{{ toString() method

View File

@ -3,7 +3,7 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (C) 2003 Slava Pestov. * Copyright (C) 2003, 2004 Slava Pestov.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -29,10 +29,10 @@
package factor; package factor;
import java.io.FileOutputStream; import factor.compiler.*;
import java.util.Iterator; import java.util.HashSet;
import java.util.Set;
import org.objectweb.asm.*; import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/** /**
* A word definition. * A word definition.
@ -40,152 +40,89 @@ import org.objectweb.asm.util.*;
public abstract class FactorWordDefinition implements FactorObject, Constants public abstract class FactorWordDefinition implements FactorObject, Constants
{ {
private FactorNamespace namespace; private FactorNamespace namespace;
protected FactorWord word;
/** public boolean compileFailed;
* Number of times this word has been referenced from a
* compound word (incremented by the precompiler).
*/
public int references;
public abstract void eval(FactorWord word, FactorInterpreter interp) public FactorWordDefinition(FactorWord word)
{
this.word = word;
}
public abstract void eval(FactorInterpreter interp)
throws Exception; throws Exception;
void precompile(FactorWord word, FactorInterpreter interp) //{{{ getNamespace() method
throws Exception {}
public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception
{ {
if(namespace == null) if(namespace == null)
namespace = new FactorNamespace(interp.global,this); namespace = new FactorNamespace(interp.global,this);
return namespace; return namespace;
}
//{{{ canCompile() method
boolean canCompile()
{
return false;
} //}}} } //}}}
private static int compileCount; //{{{ getStackEffect() method
public final StackEffect getStackEffect() throws Exception
{
return getStackEffect(new HashSet(),new LocalAllocator());
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
return null;
} //}}}
//{{{ compile() method //{{{ compile() method
/** FactorWordDefinition compile(FactorInterpreter interp,
* Compile the given word, returning a new word definition. Set recursiveCheck) throws Exception
*/
FactorWordDefinition compile(FactorWord word, FactorInterpreter interp)
throws Exception
{ {
if(!canCompile())
return this; return this;
} //}}}
//System.out.println("Compiling " + word); //{{{ compileCallTo() method
/**
StringBuffer sanitizedName = new StringBuffer(); * Compile a call to this word. Returns maximum JVM stack use.
for(int i = 0; i < word.name.length(); i++) */
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws Exception
{ {
char ch = word.name.charAt(i); StackEffect effect = getStackEffect();
if(!Character.isJavaIdentifierStart(ch)) if(effect == null)
sanitizedName.append("_"); {
// combinator; inline
return compileImmediate(mw,allocator,recursiveCheck);
}
else else
sanitizedName.append(ch);
}
String className = "factor/__compiler__/" + sanitizedName
+ "_" + (compileCount++);
ClassWriter cw = new ClassWriter(false);
cw.visit(ACC_PUBLIC, className,
"factor/FactorWordDefinition", null, null);
// creates a MethodWriter for the (implicit) constructor
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"<init>", "()V", null, null);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/FactorWordDefinition", "<init>", "()V");
mw.visitInsn(RETURN);
// this code uses a maximum of one stack element and one local
// variable
mw.visitMaxs(1, 1);
// creates a MethodWriter for the 'toString' method
mw = cw.visitMethod(ACC_PUBLIC,
"toString", "()Ljava/lang/String;", null, null);
mw.visitLdcInsn("( compiled ) " + toString());
mw.visitInsn(ARETURN);
mw.visitMaxs(1, 1);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/FactorWordDefinition", "<init>", "()V");
mw.visitInsn(RETURN);
// this code uses a maximum of one stack element and one local
// variable
mw.visitMaxs(1, 1);
// creates a MethodWriter for the 'eval' method
mw = cw.visitMethod(ACC_PUBLIC,
"eval", "(Lfactor/FactorWord;Lfactor/FactorInterpreter;)V",
null, null);
// We store a string with disassembly for debugging
// purposes.
TraceCodeVisitor disasm = new TraceCodeVisitor(mw);
if(!compile(word,interp,cw,disasm))
return this;
// Save the disassembly
StringBuffer buf = new StringBuffer();
Iterator bytecodes = disasm.getText().iterator();
while(bytecodes.hasNext())
{ {
buf.append(bytecodes.next()); // normal word
mw.visitVarInsn(ALOAD,0);
allocator.generateArgs(mw,effect.inD,null);
String defclass = getClass().getName().replace('.','/');
String signature = effect.getCorePrototype();
mw.visitMethodInsn(INVOKESTATIC,defclass,"core",signature);
if(effect.outD > 1)
throw new FactorCompilerException("Cannot compile word with non-0/1-out factors");
if(effect.outD == 1)
allocator.push(mw);
return effect.inD + 1;
} }
// gets the bytecode of the class, and loads it dynamically
byte[] code = cw.toByteArray();
/* FileOutputStream fos = new FileOutputStream(className + ".class");
fos.write(code);
fos.close(); */
SimpleClassLoader loader = new SimpleClassLoader();
Class compiledWordClass = loader._defineClass(className,
code, 0, code.length);
FactorWordDefinition compiledWord = (FactorWordDefinition)
compiledWordClass.newInstance();
compiledWord.getNamespace(interp).setVariable("asm",buf.toString());
return compiledWord;
} //}}} } //}}}
//{{{ compile() method //{{{ compileImmediate() method
/** /**
* Write the definition of the eval() method in the compiled word. * Compile a call to this word. Returns maximum JVM stack use.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/ */
boolean compile(FactorWord word, FactorInterpreter interp, public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
ClassWriter cw, CodeVisitor mw) Set recursiveCheck) throws Exception
throws Exception
{ {
throw new FactorRuntimeException("Don't know how to compile " + word); throw new FactorCompilerException("Cannot compile " + word + " in immediate mode");
} //}}}
//{{{ SimpleClassLoader class
static class SimpleClassLoader extends ClassLoader
{
public Class _defineClass(String name,
byte[] code, int off, int len)
{
return defineClass(name,code,off,len);
}
} //}}} } //}}}
} }

View File

@ -48,6 +48,8 @@
~<< 2swap A B C D -- C D A B >>~ ~<< 2swap A B C D -- C D A B >>~
~<< swapd A B C -- B A C >>~ ~<< swapd A B C -- B A C >>~
~<< 2swapd A B C D E F -- C D A B E F >>~ ~<< 2swapd A B C D E F -- C D A B E F >>~
~<< transp A B C -- C B A >>~
~<< 2transp A B C D E F -- E F C D A B >>~
~<< tuck A B -- B A B >>~ ~<< tuck A B -- B A B >>~
~<< 2tuck A B C D -- C D A B C D >>~ ~<< 2tuck A B C D -- C D A B C D >>~
@ -60,21 +62,21 @@
!!! Minimum amount of I/O words needed to be able to read other resources. !!! Minimum amount of I/O words needed to be able to read other resources.
!!! Remaining I/O operations are defined in io.factor and parser.factor. !!! Remaining I/O operations are defined in io.factor and parser.factor.
: <breader> (reader -- breader) : <breader> (reader -- breader)
[ |java.io.Reader ] |java.io.BufferedReader jconstructor jnew ; [ |java.io.Reader ] |java.io.BufferedReader jnew ;
: <ireader> (inputstream -- breader) : <ireader> (inputstream -- breader)
[ |java.io.InputStream ] |java.io.InputStreamReader jconstructor jnew ; [ |java.io.InputStream ] |java.io.InputStreamReader jnew ;
: <rreader> (path -- inputstream) : <rreader> (path -- inputstream)
|factor.FactorInterpreter |factor.FactorInterpreter
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jmethod jinvoke [ |java.lang.String ] |java.lang.Class |getResourceAsStream jinvoke
<ireader> <breader> ; <ireader> <breader> ;
: parse* (filename reader -- list) : parse* (filename reader -- list)
$dict $dict
[ |java.lang.String |java.io.Reader |factor.FactorDictionary ] [ |java.lang.String |java.io.Reader |factor.FactorDictionary ]
|factor.FactorParser jconstructor jnew |factor.FactorParser jnew
[ ] |factor.FactorParser |parse jmethod jinvoke ; [ ] |factor.FactorParser |parse jinvoke ;
: runResource (path --) : runResource (path --)
dup <rreader> parse* call ; dup <rreader> parse* call ;
@ -98,5 +100,20 @@
"/factor/stream.factor" runResource "/factor/stream.factor" runResource
"/factor/strings.factor" runResource "/factor/strings.factor" runResource
: cli-param ( param -- )
dup "no-" str-head? dup [
f s@ drop
] [
drop t s@
] ifte ;
: cli-arg ( argument -- boolean )
"-" str-head? [ cli-param ] when* ;
$args [ cli-arg ] each
! Compile all words now
$compile [ compileAll ] when
! If we're run stand-alone, start the interpreter in the current tty. ! If we're run stand-alone, start the interpreter in the current tty.
$interactive [ initialInterpreterLoop ] when $interactive [ initialInterpreterLoop ] when

View File

@ -90,18 +90,20 @@
! [ [ condition 1 ] [ code 1 ] ! [ [ condition 1 ] [ code 1 ]
! [ condition 2 ] [ code 2 ] ! [ condition 2 ] [ code 2 ]
! ... ] ! ... ]
! Each condition is evaluated in turn. If it returns true, the code ! Each condition is evaluated in turn. If it returns true,
! is evaluated. If it returns false, the next condition is checked. ! the code is evaluated. If it returns false, the next
[ ! condition is checked. Before evaluating each condition,
uncons >r ! the top of the stack is duplicated. After the last
call ! condition is evaluated, the top of the stack is popped.
r> dup [
swap [ uncons [ over [ call ] dip ] dip rot [
car call car call
] [ ] [
cdr cond cdr cond
] ifte ] ifte
] when* ; ] [
2drop
] ifte ;
: dip (a [ b ] -- b a) : dip (a [ b ] -- b a)
! Calls b as if b was not even present on the stack -- b has no way of ! Calls b as if b was not even present on the stack -- b has no way of
@ -122,14 +124,7 @@
: each ([ list ] [ code ] --) : each ([ list ] [ code ] --)
! Applies the code to each element of the list. ! Applies the code to each element of the list.
over [ over [
>r [ uncons ] dip tuck [ call ] 2dip each
uncons
r>
tuck
2>r
call
2r>
each
] [ ] [
2drop 2drop
] ifte ; ] ifte ;
@ -143,6 +138,9 @@
call call
unstack ; unstack ;
: ifte (cond [if true] [if false] --)
? call ;
: interleave ( X list -- ... ) : interleave ( X list -- ... )
! Evaluate each element of the list with X on top of the ! Evaluate each element of the list with X on top of the
! stack. ! stack.
@ -152,9 +150,6 @@
2drop 2drop
] ifte ; ] ifte ;
: ifte (cond [if true] [if false] --)
? call ;
: linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- ) : linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- )
! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse, ! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse,
! and evaluate R2. This combinator is similar to the linrec combinator in ! and evaluate R2. This combinator is similar to the linrec combinator in
@ -168,13 +163,10 @@
r> call r> call
] ifte ; ] ifte ;
: map ([ items ] [ initial ] [ code ] -- [ mapping ]) : map ( [ items ] [ code ] -- [ mapping ] )
! Applies the code to each item, returns a list that begins with the initial ! Applies the code to each item, returns a list that
! list and contains the result of each application. ! contains the result of each application.
swapd 2list append 2list restack each unstack ;
restack
each
unstack ;
: push ([ a b c ... ] -- a b c ...) : push ([ a b c ... ] -- a b c ...)
! Pushes values onto the stack literally (even if they are words). ! Pushes values onto the stack literally (even if they are words).

View File

@ -0,0 +1,58 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
/**
* : name ... ;
*/
public abstract class CompiledDefinition
extends FactorWordDefinition
{
private StackEffect effect;
//{{{ CompiledDefinition constructor
public CompiledDefinition(FactorWord word, StackEffect effect)
{
super(word);
this.effect = effect;
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state)
{
return effect;
} //}}}
}

View File

@ -0,0 +1,45 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
public class FactorCompilerException extends FactorRuntimeException
{
public FactorCompilerException(String str)
{
super(str);
}
public FactorCompilerException(String str, Throwable t)
{
super(str,t);
}
}

View File

@ -0,0 +1,677 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class LocalAllocator implements Constants
{
private FactorInterpreter interp;
private String className;
private int base;
private int max;
public FactorDataStack datastack;
public FactorCallStack callstack;
private int literalCount;
private int wordCount;
private Map literals = new HashMap();
private Map words = new HashMap();
//{{{ LocalAllocator constructor
/**
* For balancing.
*/
public LocalAllocator()
{
this(null,null,0,0);
} //}}}
//{{{ LocalAllocator constructor
/**
* For compiling.
*/
public LocalAllocator(FactorInterpreter interp, String className,
int base, int allot)
{
this.interp = interp;
this.className = className;
this.base = base;
datastack = new FactorDataStack();
callstack = new FactorCallStack();
for(int i = 0; i < allot; i++)
{
datastack.push(new Result(base + i));
}
max = base + allot;
} //}}}
//{{{ ensure() method
/**
* Ensure stack has at least 'count' elements.
* Eg, if count is 4 and stack is A B,
* stack will become RESULT RESULT A B.
* Used when deducing stack effects.
*/
public void ensure(FactorArrayStack stack, int count)
{
int top = stack.top;
if(top < count)
{
stack.ensurePush(count - top);
System.arraycopy(stack.stack,0,stack.stack,
count - top,top);
for(int i = 0; i < count - top; i++)
{
stack.stack[i] = new Result(allocate());
}
stack.top = count;
}
} //}}}
//{{{ compile() method
/**
* Compiles a quotation and returns the maximum JVM stack depth.
*/
public int compile(Cons definition, CodeVisitor mw,
Set recursiveCheck) throws Exception
{
int maxJVMStack = 0;
while(definition != null)
{
Object obj = definition.car;
if(obj instanceof FactorWord)
{
FactorWord w = (FactorWord)obj;
FactorWordDefinition d = w.def;
if(d instanceof FactorCompoundDefinition
&& d.getStackEffect(recursiveCheck,
new LocalAllocator()) != null)
{
// compile first.
w.compile(interp,recursiveCheck);
if(w.def == d)
{
// didn't compile
throw new FactorCompilerException(w + " cannot be compiled");
}
}
maxJVMStack = Math.max(maxJVMStack,
w.def.compileCallTo(mw,this,recursiveCheck));
}
else if(obj == null)
{
pushNull();
}
else if(obj instanceof String)
{
pushString((String)obj);
}
else
{
pushLiteral(obj);
}
definition = definition.next();
}
return maxJVMStack;
} //}}}
//{{{ push() method
/**
* Generates code for pushing the top of the JVM stack onto the
* data stack.
*/
public void push(CodeVisitor mw)
{
int local = allocate();
datastack.push(new Result(local));
if(mw != null)
mw.visitVarInsn(ASTORE,local);
} //}}}
//{{{ pushR() method
/**
* Generates code for pushing the top of the JVM stack onto the
* call stack.
*/
public void pushR(CodeVisitor mw)
{
int local = allocate();
callstack.push(new Result(local));
if(mw != null)
mw.visitVarInsn(ASTORE,local);
} //}}}
//{{{ pushLiteral() method
public void pushLiteral(Object literal)
{
datastack.push(new Literal(literal));
} //}}}
//{{{ pushString() method
public void pushString(String literal)
{
datastack.push(new ConstantPoolString(literal));
} //}}}
//{{{ pushNull() method
public void pushNull()
{
datastack.push(new Null());
} //}}}
//{{{ pushChoice() method
public void pushChoice() throws FactorStackException
{
FlowObject f = (FlowObject)datastack.pop();
FlowObject t = (FlowObject)datastack.pop();
FlowObject cond = (FlowObject)datastack.pop();
datastack.push(new Choice(cond,t,f));
} //}}}
//{{{ pop() method
/**
* Generates code for popping the top of the data stack onto
* the JVM stack.
*/
public void pop(CodeVisitor mw) throws FactorStackException
{
FlowObject obj = (FlowObject)datastack.pop();
if(mw != null)
obj.generate(mw);
} //}}}
//{{{ popR() method
/**
* Generates code for popping the top of the call stack onto
* the JVM stack.
*/
public void popR(CodeVisitor mw) throws FactorStackException
{
FlowObject obj = (FlowObject)callstack.pop();
if(mw != null)
obj.generate(mw);
} //}}}
//{{{ popLiteral() method
/**
* Pops a literal off the datastack or throws an exception.
*/
public Object popLiteral() throws FactorException
{
FlowObject obj = (FlowObject)datastack.pop();
return obj.getLiteral();
} //}}}
//{{{ allocate() method
/**
* Allocate a local variable.
*/
private int allocate()
{
// inefficient!
int limit = base + datastack.top + callstack.top;
for(int i = base; i <= limit; i++)
{
if(allocate(i,datastack) && allocate(i,callstack))
{
max = Math.max(max,i + 1);
return i;
}
}
// this is impossible
throw new RuntimeException("allocator failed");
} //}}}
//{{{ allocate() method
/**
* Return true if not in use, false if in use.
*/
private boolean allocate(int local, FactorArrayStack stack)
{
for(int i = 0; i < stack.top; i++)
{
FlowObject obj = (FlowObject)stack.stack[i];
if(obj.usingLocal(local))
return false;
}
return true;
} //}}}
//{{{ maxLocals() method
public int maxLocals()
{
return max;
} //}}}
//{{{ literal() method
private String literal(Object obj)
{
Integer i = (Integer)literals.get(obj);
int literal;
if(i == null)
{
literal = literalCount++;
literals.put(obj,new Integer(literal));
}
else
literal = i.intValue();
return "literal_" + literal;
} //}}}
//{{{ generateArgs() method
/**
* Generate instructions for copying arguments from the allocated
* local variables to the JVM stack, doing type conversion in the
* process.
*/
public void generateArgs(CodeVisitor mw, int num, Class[] args)
throws Exception
{
for(int i = 0; i < num; i++)
{
FlowObject obj = (FlowObject)datastack.stack[
datastack.top - num + i];
obj.generate(mw);
if(args != null)
FactorJava.generateFromConversion(mw,args[i]);
}
datastack.top -= num;
} //}}}
//{{{ generateFields() method
public void generateFields(ClassWriter cw)
throws Exception
{
for(int i = 0; i < literalCount; i++)
{
cw.visitField(ACC_PUBLIC | ACC_STATIC,"literal_" + i,
"Ljava/lang/Object;",null,null);
}
Iterator entries = words.entrySet().iterator();
while(entries.hasNext())
{
Map.Entry entry = (Map.Entry)entries.next();
FactorWord word = (FactorWord)entry.getKey();
int index = ((Integer)entry.getValue()).intValue();
cw.visitField(ACC_PUBLIC | ACC_STATIC,"word_" + index,
FactorJava.javaClassToVMClass(word.def.getClass()),
null,null);
}
} //}}}
//{{{ setFields() method
public void setFields(Class def)
throws Exception
{
Iterator entries = literals.entrySet().iterator();
while(entries.hasNext())
{
Map.Entry entry = (Map.Entry)entries.next();
Object literal = entry.getKey();
int index = ((Integer)entry.getValue()).intValue();
Field f = def.getField("literal_" + index);
f.set(null,literal);
}
entries = words.entrySet().iterator();
while(entries.hasNext())
{
Map.Entry entry = (Map.Entry)entries.next();
FactorWord word = (FactorWord)entry.getKey();
int index = ((Integer)entry.getValue()).intValue();
Field f = def.getField("word_" + index);
System.err.println(word.def.getClass() + " ==> " + "word_" + index);
f.set(null,word.def);
}
} //}}}
//{{{ FlowObject
public abstract class FlowObject
{
abstract void generate(CodeVisitor mw);
boolean usingLocal(int local)
{
return false;
}
Object getLiteral()
throws FactorCompilerException
{
throw new FactorCompilerException("Cannot compile unless literal on stack");
}
/**
* Stack effect of evaluating this -- only used for lists
* and conditionals!
*/
public StackEffect getStackEffect(Set recursiveCheck)
throws Exception
{
return null;
}
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public int compileCallTo(CodeVisitor mw, Set recursiveCheck)
throws Exception
{
throw new FactorCompilerException("Cannot compile call to non-literal quotation");
}
} //}}}
//{{{ Result
class Result extends FlowObject
{
private int local;
Result(int local)
{
this.local = local;
}
void generate(CodeVisitor mw)
{
mw.visitVarInsn(ALOAD,local);
}
boolean usingLocal(int local)
{
return (this.local == local);
}
} //}}}
//{{{ Literal
class Literal extends FlowObject
{
private Object literal;
Literal(Object literal)
{
this.literal = literal;
}
void generate(CodeVisitor mw)
{
mw.visitFieldInsn(GETSTATIC,className,
literal(literal),"Ljava/lang/Object;");
}
Object getLiteral()
{
return literal;
}
/**
* Stack effect of executing this -- only used for lists
* and conditionals!
*/
public StackEffect getStackEffect(Set recursiveCheck)
throws Exception
{
if(literal instanceof Cons
|| literal == null)
{
return StackEffect.getStackEffect(
(Cons)literal,recursiveCheck,
LocalAllocator.this);
}
else
return null;
}
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public int compileCallTo(CodeVisitor mw, Set recursiveCheck)
throws Exception
{
if(literal instanceof Cons || literal == null)
return compile((Cons)literal,mw,recursiveCheck);
else
throw new FactorCompilerException("Not a quotation: " + literal);
}
} //}}}
//{{{ ConstantPoolString
class ConstantPoolString extends FlowObject
{
private String str;
ConstantPoolString(String str)
{
this.str = str;
}
void generate(CodeVisitor mw)
{
mw.visitLdcInsn(str);
}
Object getLiteral()
{
return str;
}
} //}}}
//{{{ Null
class Null extends FlowObject
{
void generate(CodeVisitor mw)
{
mw.visitInsn(ACONST_NULL);
}
Object getLiteral()
{
return null;
}
/**
* Stack effect of executing this -- only used for lists
* and conditionals!
*/
public StackEffect getStackEffect(Set recursiveCheck)
{
return new StackEffect(0,0,0,0);
}
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public int compileCallTo(CodeVisitor mw, Set recursiveCheck)
throws Exception
{
return 0;
}
} //}}}
//{{{ Choice
class Choice extends FlowObject
{
FlowObject cond, t, f;
Choice(FlowObject cond, FlowObject t, FlowObject f)
{
this.cond = cond;
this.t = t;
this.f = f;
}
void generate(CodeVisitor mw)
{
// if null jump to F
// T
// jump END
// F: F
// END: ...
Label fl = new Label();
Label endl = new Label();
cond.generate(mw);
mw.visitJumpInsn(IFNULL,fl);
t.generate(mw);
mw.visitJumpInsn(GOTO,endl);
mw.visitLabel(fl);
f.generate(mw);
mw.visitLabel(endl);
}
boolean usingLocal(int local)
{
return cond.usingLocal(local)
|| t.usingLocal(local)
|| f.usingLocal(local);
}
/**
* Stack effect of executing this -- only used for lists
* and conditionals!
*/
public StackEffect getStackEffect(Set recursiveCheck)
throws Exception
{
FactorDataStack datastackCopy = (FactorDataStack)
datastack.clone();
FactorCallStack callstackCopy = (FactorCallStack)
callstack.clone();
StackEffect te = t.getStackEffect(recursiveCheck);
datastack = datastackCopy;
callstack = callstackCopy;
StackEffect fe = f.getStackEffect(recursiveCheck);
if(te == null || fe == null)
return null;
// we can only balance out a conditional if
// both sides leave the same amount of elements
// on the stack.
// eg, 1/1 -vs- 2/2 is ok, 3/1 -vs- 4/2 is ok,
// but 1/2 -vs- 2/1 is not.
int balanceTD = te.outD - te.inD;
int balanceTR = te.outR - te.inR;
int balanceFD = fe.outD - fe.inD;
int balanceFR = fe.outR - fe.inR;
if(balanceTD == balanceFD
&& balanceTR == balanceFR)
{
// replace results from the f branch with
// dummy values so that subsequent code
// doesn't assume these values always
// result from this
datastack.top -= te.outD;
for(int i = 0; i < te.outD; i++)
{
push(null);
}
callstack.top -= te.outR;
for(int i = 0; i < te.outR; i++)
{
pushR(null);
}
return new StackEffect(
Math.max(te.inD,fe.inD),
Math.max(te.outD,fe.outD),
Math.max(te.inR,fe.inR),
Math.max(te.outR,fe.outR)
);
}
else
return null;
}
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public int compileCallTo(CodeVisitor mw, Set recursiveCheck)
throws Exception
{
// if null jump to F
// T
// jump END
// F: F
// END: ...
Label fl = new Label();
Label endl = new Label();
cond.generate(mw);
mw.visitJumpInsn(IFNULL,fl);
FactorDataStack datastackCopy = (FactorDataStack)
datastack.clone();
FactorCallStack callstackCopy = (FactorCallStack)
callstack.clone();
int maxJVMStack = t.compileCallTo(mw,recursiveCheck);
mw.visitJumpInsn(GOTO,endl);
mw.visitLabel(fl);
datastack = datastackCopy;
callstack = callstackCopy;
maxJVMStack = Math.max(f.compileCallTo(
mw,recursiveCheck),maxJVMStack);
mw.visitLabel(endl);
return Math.max(maxJVMStack,1);
}
} //}}}
}

View File

@ -0,0 +1,168 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.util.*;
public class StackEffect
{
public final int inD;
public final int outD;
public final int inR;
public final int outR;
//{{{ StackEffect constructor
public StackEffect(int inD, int outD, int inR, int outR)
{
this.inD = inD;
this.outD = outD;
this.inR = inR;
this.outR = outR;
} //}}}
//{{{ getStackEffect() method
public static StackEffect getStackEffect(Cons definition)
throws Exception
{
return getStackEffect(definition,new HashSet(),
new LocalAllocator());
} //}}}
//{{{ getStackEffect() method
public static StackEffect getStackEffect(Cons definition,
Set recursiveCheck, LocalAllocator state)
throws Exception
{
int inD = 0;
int outD = 0;
int inR = 0;
int outR = 0;
Cons iter = definition;
while(iter != null)
{
Object obj = iter.car;
if(obj instanceof FactorWord)
{
StackEffect se = ((FactorWord)obj).def
.getStackEffect(
recursiveCheck,
state);
if(se == null)
return null;
if(se.inD <= outD)
outD -= se.inD;
else
{
inD += (se.inD - outD);
outD = 0;
}
if(se.inR <= outR)
outR -= se.inR;
else
{
inR += (se.inR - outR);
outR = 0;
}
outD += se.outD;
outR += se.outR;
}
else
{
outD++;
state.pushLiteral(obj);
}
iter = iter.next();
}
return new StackEffect(inD,outD,inR,outR);
} //}}}
//{{{ getCorePrototype() method
public String getCorePrototype()
{
StringBuffer signatureBuf = new StringBuffer(
"(Lfactor/FactorInterpreter;");
for(int i = 0; i < inD; i++)
{
signatureBuf.append("Ljava/lang/Object;");
}
if(outD == 0)
signatureBuf.append(")V");
else
signatureBuf.append(")Ljava/lang/Object;");
return signatureBuf.toString();
} //}}}
//{{{ equals() method
public boolean equals(Object o)
{
if(!(o instanceof StackEffect))
return false;
StackEffect effect = (StackEffect)o;
return effect.inD == inD
&& effect.outD == outD
&& effect.inR == inR
&& effect.outR == outR;
} //}}}
//{{{ toString() method
public String toString()
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < inD; i++)
{
buf.append("I ");
}
for(int i = 0; i < inR; i++)
{
buf.append("r:I ");
}
buf.append("--");
for(int i = 0; i < outD; i++)
{
buf.append(" O");
}
for(int i = 0; i < outR; i++)
{
buf.append(" r:O");
}
return buf.toString();
} //}}}
}

View File

@ -25,43 +25,75 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! Undefined words's def field is equal to this. : asm ( word -- assembly )
"factor.FactorMissingDefinition" "INSTANCE" jfield jvarStatic$ @undefinedWord
: asm. (word -- assembly)
! Prints JVM bytecode disassembly of the given word. ! Prints JVM bytecode disassembly of the given word.
worddef [ $asm ] bind dup [ worddef compiled? dup [
print print
] [ ] [
drop "Not a compiled word." print drop "Not a compiled word." print
] ifte ; ] ifte ;
: word? (obj -- boolean) : compile* ( word -- )
"factor.FactorWord" is ; $interpreter swap
[ "factor.FactorInterpreter" ] "factor.FactorWord" "compile"
jinvoke ;
: str>word ("word" -- word) : compile ( word -- )
! Returns the top of the stack if it already been interned. dup worddef compiled? [
dup word? [ drop
$dict [ "java.lang.String" ] "factor.FactorDictionary" "intern" ] [
jmethod jinvoke intern compile*
] unless ; ] ifte ;
: worddef? (obj -- boolean) : compileAll ( -- )
"factor.FactorWordDefinition" is ; "Compiling..." write
words [ compile ] each
" done" print ;
: compiled? ( obj -- boolean )
[ $asm ] bind ;
: compound? (obj -- boolean) : compound? (obj -- boolean)
"factor.FactorCompoundDefinition" is ; "factor.FactorCompoundDefinition" is ;
: missing>f ( word -- word/f )
! Is it the missing word placeholder? Then push f.
dup undefined? [ drop f ] when ;
: shuffle? (obj -- boolean) : shuffle? (obj -- boolean)
"factor.FactorShuffleDefinition" is ; "factor.FactorShuffleDefinition" is ;
: intern ("word" -- word)
! Returns the top of the stack if it already been interned.
dup word? [
$dict [ "java.lang.String" ]
"factor.FactorDictionary" "intern"
jinvoke
] unless ;
: undefined? ( obj -- boolean )
"factor.FactorMissingDefinition" is ;
: word? (obj -- boolean)
"factor.FactorWord" is ;
: word ( -- word )
! Pushes most recently defined word.
$dict "factor.FactorDictionary" "last" jvar$ ;
: worddef? (obj -- boolean)
"factor.FactorWordDefinition" is ;
: worddef ( word -- worddef ) : worddef ( word -- worddef )
str>word intern
! Get the 'def' field "factor.FactorWord" "def" jvar$
"factor.FactorWord" "def" jfield jvar$ missing>f ;
! Is it equal to the missing word placeholder? Then push f.
dup $undefinedWord = [ drop f ] when ; : worddefUncompiled ( word -- worddef )
intern
"factor.FactorWord" "uncompiled" jvar$
missing>f ;
: words (-- list) : words (-- list)
! Pushes a list of all defined words. ! Pushes a list of all defined words.
$dict [ ] "factor.FactorDictionary" "toWordList" jmethod jinvoke ; $dict [ ] "factor.FactorDictionary" "toWordList" jinvoke ;

View File

@ -40,7 +40,7 @@
! - implement an LSP that does an "apropos" search ! - implement an LSP that does an "apropos" search
: httpdGetPath ( request -- file ) : httpdGetPath ( request -- file )
dup ".*\\.\\.*" matches [ dup ".*\\.\\.*" re-matches [
f f
] [ ] [
dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when
@ -58,11 +58,11 @@
: httpdFiletype (filename -- mime-type) : httpdFiletype (filename -- mime-type)
[ [
[ dup ".*\.gif" matches ] [ drop "image/gif" ] [ ".*\.gif" re-matches ] [ drop "image/gif" ]
[ dup ".*\.png" matches ] [ drop "image/png" ] [ ".*\.png" re-matches ] [ drop "image/png" ]
[ dup ".*\.html" matches ] [ drop "text/html" ] [ ".*\.html" re-matches ] [ drop "text/html" ]
[ dup ".*\.txt" matches ] [ drop "text/plain" ] [ ".*\.txt" re-matches ] [ drop "text/plain" ]
[ dup ".*\.lsd" matches ] [ drop "text/plain" ] [ ".*\.lsd" re-matches ] [ drop "text/plain" ]
[ t ] [ drop "application/octet-stream" ] [ t ] [ drop "application/octet-stream" ]
] cond ; ] cond ;
@ -123,7 +123,7 @@
dup directory? [ dup directory? [
httpdServeDirectory httpdServeDirectory
] [ ] [
dup ".*\.lhtml" matches [ dup ".*\.lhtml" re-matches [
httpdServeScript httpdServeScript
] [ ] [
httpdServeFile httpdServeFile

View File

@ -29,13 +29,13 @@
"java.lang.Throwable" is ; "java.lang.Throwable" is ;
: printStackTrace (exception --) : printStackTrace (exception --)
[ ] "java.lang.Throwable" "printStackTrace" jmethod jinvoke ; [ ] "java.lang.Throwable" "printStackTrace" jinvoke ;
: exception. (exception --) : exception. (exception --)
! If this is an Factor exception, just print the message, otherwise print ! If this is an Factor exception, just print the message, otherwise print
! the entire exception as a string. ! the entire exception as a string.
dup "factor.FactorException" is [ dup "factor.FactorException" is [
[ ] "java.lang.Throwable" "getMessage" jmethod jinvoke [ ] "java.lang.Throwable" "getMessage" jinvoke
] [ ] [
>str >str
] ifte print ; ] ifte print ;
@ -53,6 +53,7 @@
":g continues execution (but expect another error)." print ":g continues execution (but expect another error)." print
"" print "" print
"ERROR: " write exception. "ERROR: " write exception.
:w
callstack$ @errorCallStack callstack$ @errorCallStack
[ [
@errorContinuation @errorContinuation
@ -131,9 +132,11 @@
words [ . ] each ; words [ . ] each ;
: see (word --) : see (word --)
dup worddef [ dup worddefUncompiled [
(word -- worddef word) (word -- worddef word)
dup [ worddef dup shuffle? "~<< " ": " ? write ] dip dup [
worddefUncompiled dup shuffle? "~<< " ": " ? write
] dip
(worddef word -- worddef) (worddef word -- worddef)
write "\n " write write "\n " write
@ -153,6 +156,22 @@
! Prints the contents of the data stack ! Prints the contents of the data stack
datastack$ . ; datastack$ . ;
: stats ( -- )
"Cons: " write
"factor.Cons" "COUNT" jvar-static$ .
"Words: " write
words length .
"Compiled: " write
words [ worddef compiled? ] subset length . ;
: gc ( -- )
[ ] "java.lang.System" "gc" jinvoke-static ;
: balance ( code -- effect )
! Push stack effect of the given code quotation.
[ "factor.Cons" ] "factor.compiler.StackEffect"
"getStackEffect" jinvoke-static ;
: help : help
"" print "" print
"= Dynamic, interpreted, stack-based scripting language" print "= Dynamic, interpreted, stack-based scripting language" print

View File

@ -2,7 +2,7 @@
! $Id$ ! $Id$
! !
! Copyright (C) 2003 Slava Pestov. ! Copyright (C) 2003, 2004 Slava Pestov.
! !
! Redistribution and use in source and binary forms, with or without ! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met: ! modification, are permitted provided that the following conditions are met:
@ -32,7 +32,7 @@
swap unit cons ; swap unit cons ;
: append ( [ list1 ] [ list2 ] -- [ list1 list2 ] ) : append ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
swap rappend ; over [ [ uncons ] dip append cons ] [ nip ] ifte ;
: add ([ list1 ] elem -- [ list1 elem ]) : add ([ list1 ] elem -- [ list1 elem ])
unit append ; unit append ;
@ -42,7 +42,8 @@
dup [ $ swap append ] dip @ ; dup [ $ swap append ] dip @ ;
: array>list ( array -- list ) : array>list ( array -- list )
[ "[Ljava.lang.Object;" ] "factor.FactorList" "fromArray" jmethod jinvokeStatic ; [ [ "java.lang.Object" ] ] "factor.Cons" "fromArray"
jinvoke-static ;
: add@ (elem variable --) : add@ (elem variable --)
! Adds the element to the end of the list stored in the given variable. ! Adds the element to the end of the list stored in the given variable.
@ -63,10 +64,10 @@
] ifte ; ] ifte ;
: car ([ car , cdr ] -- car) : car ([ car , cdr ] -- car)
|factor.FactorList |car jfield jvar$ ; |factor.Cons |car jvar$ ;
: cdr ([ car , cdr ] -- cdr) : cdr ([ car , cdr ] -- cdr)
|factor.FactorList |cdr jfield jvar$ ; |factor.Cons |cdr jvar$ ;
: caar (list -- caar) : caar (list -- caar)
car car ; car car ;
@ -83,10 +84,10 @@
: cloneList (list -- list) : cloneList (list -- list)
! Returns a new list where each element is a clone of the elements of ! Returns a new list where each element is a clone of the elements of
! the given list. ! the given list.
dup [ [ ] "factor.FactorList" "deepClone" jmethod jinvoke ] when ; dup [ [ ] "factor.Cons" "deepClone" jinvoke ] when ;
: cons (car cdr -- [ car , cdr ]) : cons (car cdr -- [ car , cdr ])
[ |java.lang.Object |java.lang.Object ] |factor.FactorList jconstructor jnew ; [ |java.lang.Object |java.lang.Object ] |factor.Cons jnew ;
: contains (elem list -- boolean) : contains (elem list -- boolean)
dup [ dup [
@ -113,9 +114,13 @@
: get (list n -- list[n]) : get (list n -- list[n])
[ cdr ] times car ; [ cdr ] times car ;
: last* ( list -- last )
! Pushes last cons of the list.
[ dup cdr ] [ cdr ] while ;
: last ( list -- last ) : last ( list -- last )
! Pushes last element of the list. ! Pushes last element of the list.
[ dup cdr ] [ cdr ] while car ; last* car ;
: length (list -- length) : length (list -- length)
0 swap [ drop succ ] each ; 0 swap [ drop succ ] each ;
@ -126,18 +131,27 @@
: list? (list -- boolean) : list? (list -- boolean)
dup pair? [ cdr list? ] [ f ] ifte ; dup pair? [ cdr list? ] [ f ] ifte ;
: pair? (list -- boolean) : nappend ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
|factor.FactorList is ; ! Destructive on list1!
over [ last* rplacd ] when* ;
: rappend ([ list2 ] [ list1 ] -- [ list1 list2 ]) : pair? (list -- boolean)
[ [ |factor.FactorList ] |factor.FactorList |append jmethod jinvoke ] when* ; |factor.Cons is ;
: reverse (list -- list) : reverse (list -- list)
[ ] swap [ swons ] each ; [ ] swap [ swons ] each ;
: rplaca ( A [ B , C ] -- [ A , C ] )
! Destructive!
"factor.Cons" "car" jvar@ ;
: rplacd ( A [ B , C ] -- [ B , A ] )
! Destructive!
"factor.Cons" "cdr" jvar@ ;
: swons (cdr car -- [ car , cdr ]) : swons (cdr car -- [ car , cdr ])
swap [ |java.lang.Object |java.lang.Object ] swap [ |java.lang.Object |java.lang.Object ]
|factor.FactorList jconstructor jnew ; |factor.Cons jnew ;
: uncons ([ car , cdr ] -- car cdr) : uncons ([ car , cdr ] -- car cdr)
dup car swap cdr ; dup car swap cdr ;

View File

@ -35,76 +35,64 @@
"java.lang.Integer" is ; "java.lang.Integer" is ;
: >fixnum (num -- fixnum) : >fixnum (num -- fixnum)
[ ] "java.lang.Number" "intValue" jmethod jinvoke ; [ ] "java.lang.Number" "intValue" jinvoke ;
: bignum? (obj -- boolean) : bignum? (obj -- boolean)
"java.math.BigInteger" is ; "java.math.BigInteger" is ;
: >bignum (num -- bignum) : >bignum (num -- bignum)
[ ] "java.lang.Number" "longValue" jmethod jinvoke [ ] "java.lang.Number" "longValue" jinvoke
[ "long" ] "java.math.BigInteger" "valueOf" jmethod jinvokeStatic ; [ "long" ] "java.math.BigInteger" "valueOf" jinvoke-static ;
: realnum? (obj -- boolean) : realnum? (obj -- boolean)
dup "java.lang.Float" is dup "java.lang.Float" is
swap "java.lang.Double" is or ; swap "java.lang.Double" is or ;
: >realnum (num -- realnum) : >realnum (num -- realnum)
[ ] "java.lang.Number" "doubleValue" jmethod jinvoke ; [ ] "java.lang.Number" "doubleValue" jinvoke ;
: ratio? (obj -- boolean) : ratio? (obj -- boolean)
"factor.FactorRatio" is ; "factor.FactorRatio" is ;
: + (a b -- a+b) : + (a b -- a+b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "add" [ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "add"
jmethod jinvokeStatic ; jinvoke-static ;
: +@ (num var --) : +@ (num var --)
dup [ $ + ] dip @ ; dup [ $ + ] dip @ ;
: - (a b -- a-b) : - (a b -- a-b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "subtract" [ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "subtract"
jmethod jinvokeStatic ; jinvoke-static ;
: -@ (num var --) : -@ (num var --)
dup [ $ -- ] dip @ ; dup [ $ swap - ] dip @ ;
: -- (a b -- b-a)
swap - ;
: --@ (var num --)
[ dup $ - ] dip s@ ;
: * (a b -- a*b) : * (a b -- a*b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "multiply" [ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "multiply"
jmethod jinvokeStatic ; jinvoke-static ;
: *@ (num var --) : *@ (num var --)
dup [ $ * ] dip @ ; dup [ $ * ] dip @ ;
: / (a b -- a/b) : / (a b -- a/b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "divide" [ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "divide"
jmethod jinvokeStatic ; jinvoke-static ;
: /@ (num var --) : /@ (num var --)
dup [ $ / ] dip @ ; dup [ $ / ] dip @ ;
: // (a b -- b/a)
swap / ;
: //@ (num var --)
[ dup $ / ] dip s@ ;
: > (a b -- boolean) : > (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "greater" jmethod jinvokeStatic ; [ "float" "float" ] "factor.FactorMath" "greater" jinvoke-static ;
: >= (a b -- boolean) : >= (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "greaterEqual" jmethod jinvokeStatic ; [ "float" "float" ] "factor.FactorMath" "greaterEqual" jinvoke-static ;
: < (a b -- boolean) : < (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "less" jmethod jinvokeStatic ; [ "float" "float" ] "factor.FactorMath" "less" jinvoke-static ;
: <= (a b -- boolean) : <= (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "lessEqual" jmethod jinvokeStatic ; [ "float" "float" ] "factor.FactorMath" "lessEqual" jinvoke-static ;
: and (a b -- a&b) : and (a b -- a&b)
f ? ; f ? ;
@ -126,9 +114,15 @@
: not@ (boolean -- boolean) : not@ (boolean -- boolean)
dup $ not s@ ; dup $ not s@ ;
: pow ( x y -- x^y )
[ "double" "double" ] "java.lang.Math" "pow" jinvoke-static ;
: pred (n -- n-1) : pred (n -- n-1)
1 - ; 1 - ;
: round ( x y -- x^y )
[ "double" "double" ] "java.lang.Math" "pow" jinvoke-static ;
: succ (n -- nsucc) : succ (n -- nsucc)
1 + ; 1 + ;
@ -139,13 +133,13 @@
t swap ? ; t swap ? ;
: recip (x -- 1/x) : recip (x -- 1/x)
1 // ; 1 swap / ;
: sq (x -- x^2) : sq (x -- x^2)
dup * ; dup * ;
: sqrt (x -- sqrt x) : sqrt (x -- sqrt x)
[ "double" ] "java.lang.Math" "sqrt" jmethod jinvokeStatic ; [ "double" ] "java.lang.Math" "sqrt" jinvoke-static ;
: succ@ (var --) : succ@ (var --)
dup $ 1 + s@ ; dup $ 1 + s@ ;

View File

@ -25,30 +25,28 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: >str (obj -- string)
! Returns the Java string representation of this object.
[ ] "java.lang.Object" "toString" jmethod jinvoke ;
: = (a b -- boolean) : = (a b -- boolean)
! Returns true if a = b. ! Returns true if a = b.
[ "java.lang.Object" "java.lang.Object" ] [ "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "equal" jmethod jinvokeStatic ; "factor.FactorLib" "equal" jinvoke-static ;
: clone (obj -- obj) : clone (obj -- obj)
[ ] "factor.PublicCloneable" "clone" jmethod jinvoke ; [ ] "factor.PublicCloneable" "clone" jinvoke ;
: cloneArray (obj -- obj) : cloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "cloneArray" [ [ "java.lang.Object" ] ]
jmethod jinvokeStatic ; "factor.FactorLib" "cloneArray"
jinvoke-static ;
: deepCloneArray (obj -- obj) : deepCloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "deepCloneArray" [ [ "java.lang.Object" ] ]
jmethod jinvokeStatic ; "factor.FactorLib" "deepCloneArray"
jinvoke-static ;
: is (obj class -- boolean) : is (obj class -- boolean)
! Like "instanceof" in Java. ! Like "instanceof" in Java.
[ "java.lang.Object" ] "java.lang.Class" "isInstance" [ "java.lang.Object" ] "java.lang.Class" "isInstance"
jmethod jinvoke ; jinvoke ;
: not= (a b -- boolean) : not= (a b -- boolean)
= not ; = not ;
@ -57,36 +55,31 @@
! Returns true if a = c, b = d. ! Returns true if a = c, b = d.
swapd = [ = ] dip and ; swapd = [ = ] dip and ;
: ? (cond obj1 obj2 -- obj)
! Pushes obj1 if cond is true, obj2 if cond is false.
[ "boolean" "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "branch2" jmethod jinvokeStatic ;
: >=< (x y obj1 obj2 obj3 -- obj) : >=< (x y obj1 obj2 obj3 -- obj)
! If x > y, pushes obj1, if x = y, pushes obj2, else obj3. ! If x > y, pushes obj1, if x = y, pushes obj2, else obj3.
[ [
"float" "float" "float" "float"
"java.lang.Object" "java.lang.Object" "java.lang.Object" "java.lang.Object" "java.lang.Object" "java.lang.Object"
] ]
"factor.FactorLib" "branch3" jmethod jinvokeStatic ; "factor.FactorLib" "branch3" jinvoke-static ;
: error (msg --) : error (msg --)
[ "java.lang.String" ] "factor.FactorLib" "error" jmethod jinvokeStatic ; [ "java.lang.String" ] "factor.FactorLib" "error" jinvoke-static ;
: exit* (code --) : exit* (code --)
[ |int ] |java.lang.System |exit jmethod jinvokeStatic ; [ |int ] |java.lang.System |exit jinvoke-static ;
: exit (--) : exit (--)
0 exit* ; 0 exit* ;
: millis (-- millis) : millis (-- millis)
! Pushes the current time, in milliseconds. ! Pushes the current time, in milliseconds.
[ ] |java.lang.System |currentTimeMillis jmethod jinvokeStatic [ ] |java.lang.System |currentTimeMillis jinvoke-static
>bignum ; >bignum ;
: stack>list (stack -- list) : stack>list (stack -- list)
! Turns a callstack or datastack object into a list. ! Turns a callstack or datastack object into a list.
[ ] "factor.FactorArrayStack" "toList" jmethod jinvoke ; [ ] "factor.FactorArrayStack" "toList" jinvoke ;
: time (code --) : time (code --)
! Evaluates the given code and prints the time taken to execute it. ! Evaluates the given code and prints the time taken to execute it.

View File

@ -25,6 +25,9 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: s@ ( variable value -- )
swap @ ;
: lazy (var [ a ] -- value) : lazy (var [ a ] -- value)
! If the value of the variable is f, set the value to the result of ! If the value of the variable is f, set the value to the result of
! evaluating [ a ]. ! evaluating [ a ].
@ -35,12 +38,12 @@
: <namespace> (-- namespace) : <namespace> (-- namespace)
$namespace [ |factor.FactorNamespace ] |factor.FactorNamespace $namespace [ |factor.FactorNamespace ] |factor.FactorNamespace
jconstructor jnew ; jnew ;
: <objnamespace> ( object -- namespace ) : <objnamespace> ( object -- namespace )
$namespace swap $namespace swap
[ "factor.FactorNamespace" "java.lang.Object" ] [ "factor.FactorNamespace" "java.lang.Object" ]
"factor.FactorNamespace" jconstructor jnew ; "factor.FactorNamespace" jnew ;
: extend (object code -- object) : extend (object code -- object)
! Used in code like this: ! Used in code like this:
@ -52,12 +55,12 @@
: import (class pairs --) : import (class pairs --)
! Import some static variables from a Java class into the current namespace. ! Import some static variables from a Java class into the current namespace.
$namespace [ |java.lang.String |factor.FactorList ] $namespace [ |java.lang.String |factor.Cons ]
|factor.FactorNamespace |importVars |factor.FactorNamespace |importVars
jmethod jinvoke ; jinvoke ;
: vars (-- list) : vars (-- list)
$namespace [ ] |factor.FactorNamespace |toVarList jmethod jinvoke ; $namespace [ ] |factor.FactorNamespace |toVarList jinvoke ;
: uvar? (name --) : uvar? (name --)
[ "namespace" "parent" ] contains not ; [ "namespace" "parent" ] contains not ;

View File

@ -28,21 +28,21 @@
: <server> ( port -- stream ) : <server> ( port -- stream )
! Starts listening on localhost:port. Returns a stream that you can close ! Starts listening on localhost:port. Returns a stream that you can close
! with fclose. No other stream operations are supported. ! with fclose. No other stream operations are supported.
[ "int" ] "java.net.ServerSocket" jconstructor jnew [ "int" ] "java.net.ServerSocket" jnew
<stream> [ <stream> [
@socket @socket
( -- ) ( -- )
[ [
$socket [ ] "java.net.ServerSocket" "close" jmethod jinvoke $socket [ ] "java.net.ServerSocket" "close" jinvoke
] @fclose ] @fclose
] extend ; ] extend ;
: <socketstream> ( socket -- stream ) : <socketstream> ( socket -- stream )
! Wraps a socket inside a bytestream. ! Wraps a socket inside a bytestream.
dup dup
[ [ ] "java.net.Socket" "getInputStream" jmethod jinvoke ] [ [ ] "java.net.Socket" "getInputStream" jinvoke ]
[ [ ] "java.net.Socket" "getOutputStream" jmethod jinvoke ] [ [ ] "java.net.Socket" "getOutputStream" jinvoke ]
cleave cleave
<bytestream> [ <bytestream> [
@socket @socket
@ -50,11 +50,11 @@
! We "extend" bytestream's fclose. ! We "extend" bytestream's fclose.
( -- ) ( -- )
$fclose [ $fclose [
$socket [ ] "java.net.Socket" "close" jmethod jinvoke $socket [ ] "java.net.Socket" "close" jinvoke
] append @fclose ] append @fclose
] extend ; ] extend ;
: accept ( server -- client ) : accept ( server -- client )
! Accept a connection from a server socket. ! Accept a connection from a server socket.
[ $socket ] bind [ $socket ] bind
[ ] "java.net.ServerSocket" "accept" jmethod jinvoke <socketstream> ; [ ] "java.net.ServerSocket" "accept" jinvoke <socketstream> ;

View File

@ -36,7 +36,7 @@
: unparse (X -- "X") : unparse (X -- "X")
[ |java.lang.Object ] |factor.FactorJava |factorTypeToString [ |java.lang.Object ] |factor.FactorJava |factorTypeToString
jmethod jinvokeStatic ; jinvoke-static ;
: . (expr --) : . (expr --)
unparse print ; unparse print ;

126
factor/primitives/Bind.java Normal file
View File

@ -0,0 +1,126 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class Bind extends FactorWordDefinition
{
//{{{ Bind constructor
public Bind(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Cons code = (Cons)datastack.pop(Cons.class);
Object obj = datastack.pop();
FactorNamespace ns = FactorJava.toNamespace(obj,interp);
interp.call(word,ns,code);
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
state.ensure(state.datastack,2);
LocalAllocator.FlowObject quot
= (LocalAllocator.FlowObject)
state.datastack.pop();
state.pop(null);
StackEffect effect = quot.getStackEffect(recursiveCheck);
if(effect != null)
{
// add 2 to inD since we consume the
// quotation and the object
return new StackEffect(effect.inD + 2,
effect.outD,
effect.inR,
effect.outR);
}
else
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
LocalAllocator.FlowObject quot = (LocalAllocator.FlowObject)
allocator.datastack.pop();
// store namespace on callstack
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter",
"callframe",
"Lfactor/FactorCallFrame;");
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorCallFrame",
"namespace",
"Lfactor/FactorNamespace;");
allocator.pushR(mw);
// set new namespace
mw.visitInsn(DUP);
allocator.pop(mw);
FactorJava.generateFromConversion(mw,FactorNamespace.class);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorCallFrame",
"namespace",
"Lfactor/FactorNamespace;");
int maxJVMStack = quot.compileCallTo(mw,recursiveCheck);
// restore namespace from callstack
allocator.popR(mw);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorCallFrame",
"namespace",
"Lfactor/FactorNamespace;");
return maxJVMStack + 3;
} //}}}
}

View File

@ -0,0 +1,90 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class Call extends FactorWordDefinition
{
//{{{ Call constructor
public Call(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.call(word,(Cons)interp.datastack.pop(
Cons.class));
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
state.ensure(state.datastack,1);
LocalAllocator.FlowObject quot
= (LocalAllocator.FlowObject)
state.datastack.pop();
StackEffect effect = quot.getStackEffect(recursiveCheck);
if(effect != null)
{
// add 1 to inD since we consume the
// quotation
return new StackEffect(effect.inD + 1,
effect.outD,
effect.inR,
effect.outR);
}
else
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
LocalAllocator.FlowObject quot = (LocalAllocator.FlowObject)
allocator.datastack.pop();
return quot.compileCallTo(mw,recursiveCheck);
} //}}}
}

View File

@ -0,0 +1,51 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
import org.objectweb.asm.*;
public class CallstackGet extends FactorWordDefinition
{
//{{{ CallstackGet constructor
public CallstackGet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.callstack.clone());
} //}}}
}

View File

@ -0,0 +1,52 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class CallstackSet extends FactorWordDefinition
{
//{{{ CallstackSet constructor
public CallstackSet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.callstack = (FactorCallStack)((FactorCallStack)
interp.datastack.pop(FactorCallStack.class))
.clone();
} //}}}
}

View File

@ -0,0 +1,85 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import org.objectweb.asm.*;
public class Choice extends FactorWordDefinition
{
//{{{ Choice constructor
public Choice(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Object f = datastack.pop();
Object t = datastack.pop();
Object cond = datastack.pop();
datastack.push(core(interp,cond,t,f));
} //}}}
//{{{ core() method
public static Object core(FactorInterpreter interp,
Object cond, Object t, Object f) throws Exception
{
return FactorJava.toBoolean(cond) ? t : f;
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(java.util.Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,3);
state.pushChoice();
return new StackEffect(3,1,0,0);
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
/* public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
java.util.Set recursiveCheck)
throws Exception
{
allocator.pushChoice();
return 0;
} */ //}}}
}

View File

@ -0,0 +1,50 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Clear extends FactorWordDefinition
{
//{{{ Clear constructor
public Clear(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.datastack.top = 0;
} //}}}
}

View File

@ -0,0 +1,50 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class DatastackGet extends FactorWordDefinition
{
//{{{ DatastackGet constructor
public DatastackGet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.datastack.clone());
} //}}}
}

View File

@ -0,0 +1,52 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class DatastackSet extends FactorWordDefinition
{
//{{{ DatastackSet constructor
public DatastackSet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.datastack = (FactorDataStack)((FactorDataStack)
interp.datastack.pop(FactorDataStack.class))
.clone();
} //}}}
}

View File

@ -0,0 +1,77 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Define extends FactorWordDefinition
{
//{{{ Define constructor
public Define(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorDictionary dict = interp.dict;
// handle old define syntax
Object obj = datastack.pop();
FactorWord newWord = interp.dict.intern(
(String)datastack.pop(String.class));
if(obj instanceof Cons)
{
obj = new FactorCompoundDefinition(
newWord,(Cons)obj);
}
FactorWordDefinition def = (FactorWordDefinition)obj;
newWord.define(def);
dict.last = newWord;
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,2);
state.pop(null);
state.pop(null);
return new StackEffect(2,0,0,0);
} //}}}
}

View File

@ -0,0 +1,69 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Get extends FactorWordDefinition
{
//{{{ Get constructor
public Get(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(core(interp,datastack.pop()));
} //}}}
//{{{ core() method
public static Object core(FactorInterpreter interp,
Object name) throws Exception
{
return interp.callframe.namespace.getVariable(
FactorJava.toString(name));
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,1);
state.pop(null);
state.push(null);
return new StackEffect(1,1,0,0);
} //}}}
}

View File

@ -0,0 +1,146 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JInvoke extends FactorWordDefinition
{
//{{{ JInvoke constructor
public JInvoke(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Method method = FactorJava.jmethod(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class),
(Cons)datastack.pop(Cons.class));
FactorJava.jinvoke(datastack,
method,datastack.pop());
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
state.ensure(state.datastack,4);
Object clazz = state.popLiteral();
Object name = state.popLiteral();
Object args = state.popLiteral();
state.pop(null);
if(clazz instanceof String &&
name instanceof String &&
(args == null || args instanceof Cons))
{
Method method = FactorJava.jmethod(
(String)clazz,
(String)name,
(Cons)args);
boolean returnValue = method.getReturnType() == Void.TYPE;
if(returnValue)
state.push(null);
return new StackEffect(
4 + method.getParameterTypes().length,
returnValue ? 0 : 1,0,0);
}
else
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _method = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
Object _args = allocator.popLiteral();
if(_method instanceof String &&
_clazz instanceof String &&
(_args == null || _args instanceof Cons))
{
String method = (String)_method;
String clazz = (String)_clazz;
Class[] args = FactorJava.classNameToClassList(
(Cons)_args);
Class cls = FactorJava.getClass(clazz);
Method mth = cls.getMethod(method,args);
Class returnType = mth.getReturnType();
clazz = clazz.replace('.','/');
FactorJava.generateToConversionPre(mw,returnType);
allocator.pop(mw);
FactorJava.generateFromConversion(mw,cls);
allocator.generateArgs(mw,args.length,args);
int opcode;
if(cls.isInterface())
opcode = INVOKEINTERFACE;
else
opcode = INVOKEVIRTUAL;
mw.visitMethodInsn(opcode,
clazz,
method,
FactorJava.javaSignatureToVMSignature(
args,returnType));
if(returnType != Void.TYPE)
{
FactorJava.generateToConversion(mw,returnType);
allocator.push(mw);
}
return 4 + args.length;
}
else
throw new FactorCompilerException("Cannot compile jinvoke with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,136 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JInvokeStatic extends FactorWordDefinition
{
//{{{ JInvokeStatic constructor
public JInvokeStatic(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Method method = FactorJava.jmethod(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class),
(Cons)datastack.pop(Cons.class));
FactorJava.jinvokeStatic(datastack,method);
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
state.ensure(state.datastack,3);
Object clazz = state.popLiteral();
Object name = state.popLiteral();
Object args = state.popLiteral();
if(clazz instanceof String &&
name instanceof String &&
(args == null || args instanceof Cons))
{
Method method = FactorJava.jmethod(
(String)clazz,
(String)name,
(Cons)args);
boolean returnValue = method.getReturnType() == Void.TYPE;
if(returnValue)
state.push(null);
return new StackEffect(
3 + method.getParameterTypes().length,
returnValue ? 0 : 1,0,0);
}
else
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _method = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
Object _args = allocator.popLiteral();
if(_method instanceof String &&
_clazz instanceof String &&
(_args == null || _args instanceof Cons))
{
String method = (String)_method;
String clazz = (String)_clazz;
Class[] args = FactorJava.classNameToClassList(
(Cons)_args);
Class cls = FactorJava.getClass(clazz);
Method mth = cls.getMethod(method,args);
Class returnType = mth.getReturnType();
clazz = clazz.replace('.','/');
FactorJava.generateToConversionPre(mw,returnType);
allocator.generateArgs(mw,args.length,args);
mw.visitMethodInsn(INVOKESTATIC,
clazz,
method,
FactorJava.javaSignatureToVMSignature(
args,returnType));
if(returnType != Void.TYPE)
{
FactorJava.generateToConversion(mw,returnType);
allocator.push(mw);
}
return 4 + args.length;
}
else
throw new FactorCompilerException("Cannot compile jinvoke with non-literal parameters");
} //}}}
}

125
factor/primitives/JNew.java Normal file
View File

@ -0,0 +1,125 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JNew extends FactorWordDefinition
{
//{{{ JNew constructor
public JNew(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
String name = (String)datastack.pop(String.class);
Cons args = (Cons)datastack.pop(Cons.class);
Constructor constructor = FactorJava.jconstructor(
name,args);
FactorJava.jnew(datastack,constructor);
} //}}}
//{{{ getStackEffect() method
/**
* XXX: does not use factor type system conversions.
*/
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
state.ensure(state.datastack,2);
Object clazz = state.popLiteral();
Object args = state.popLiteral();
if(clazz instanceof String &&
(args == null || args instanceof Cons))
{
Constructor constructor
= FactorJava.jconstructor(
(String)clazz,
(Cons)args);
state.push(null);
return new StackEffect(
2 + constructor.getParameterTypes()
.length,1,0,0);
}
else
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _clazz = allocator.popLiteral();
Object _args = allocator.popLiteral();
if(_clazz instanceof String &&
(_args == null || _args instanceof Cons))
{
String clazz = ((String)_clazz)
.replace('.','/');
Class[] args = FactorJava.classNameToClassList(
(Cons)_args);
mw.visitTypeInsn(NEW,clazz);
mw.visitInsn(DUP);
allocator.generateArgs(mw,args.length,args);
mw.visitMethodInsn(INVOKESPECIAL,
clazz,
"<init>",
FactorJava.javaSignatureToVMSignature(
args,void.class));
allocator.push(mw);
return 3 + args.length;
}
else
throw new FactorCompilerException("Cannot compile jnew with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,110 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JVarGet extends FactorWordDefinition
{
//{{{ JVarGet constructor
public JVarGet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Field field = FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class));
datastack.push(
FactorJava.jvarGet(
field,datastack.pop()));
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,3);
state.pop(null);
state.pop(null);
state.pop(null);
state.push(null);
return new StackEffect(3,1,0,0);
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _field = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
if(_clazz instanceof String &&
_field instanceof String)
{
String field = (String)_field;
String clazz = (String)_clazz;
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
Field fld = cls.getField(field);
FactorJava.generateToConversionPre(mw,fld.getType());
allocator.pop(mw);
FactorJava.generateFromConversion(mw,cls);
mw.visitFieldInsn(GETFIELD,clazz,field,
FactorJava.javaClassToVMClass(fld.getType()));
FactorJava.generateToConversion(mw,fld.getType());
allocator.push(mw);
return 2;
}
else
throw new FactorCompilerException("Cannot compile jvar$ with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,105 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JVarGetStatic extends FactorWordDefinition
{
//{{{ JVarGetStatic constructor
public JVarGetStatic(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Field field = FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class));
datastack.push(
FactorJava.jvarGetStatic(field));
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,2);
state.pop(null);
state.pop(null);
state.push(null);
return new StackEffect(2,1,0,0);
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _field = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
if(_clazz instanceof String &&
_field instanceof String)
{
String field = (String)_field;
String clazz = (String)_clazz;
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
Field fld = cls.getField(field);
FactorJava.generateToConversionPre(mw,fld.getType());
mw.visitFieldInsn(GETSTATIC,clazz,field,
FactorJava.javaClassToVMClass(fld.getType()));
FactorJava.generateToConversion(mw,fld.getType());
allocator.push(mw);
return 2;
}
else
throw new FactorCompilerException("Cannot compile jvar-static$ with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,110 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JVarSet extends FactorWordDefinition
{
//{{{ JVarSet constructor
public JVarSet(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Field field = FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class));
FactorJava.jvarSet(
field,
datastack.pop(),
datastack.pop());
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,4);
state.pop(null);
state.pop(null);
state.pop(null);
state.pop(null);
return new StackEffect(4,0,0,0);
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _field = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
if(_clazz instanceof String &&
_field instanceof String)
{
String field = (String)_field;
String clazz = (String)_clazz;
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
Field fld = cls.getField(field);
allocator.pop(mw);
FactorJava.generateFromConversion(mw,cls);
allocator.pop(mw);
FactorJava.generateFromConversion(mw,fld.getType());
mw.visitFieldInsn(PUTFIELD,
clazz,
field,
FactorJava.javaClassToVMClass(fld.getType()));
return 2;
}
else
throw new FactorCompilerException("Cannot compile jvar@ with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,104 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
import org.objectweb.asm.*;
public class JVarSetStatic extends FactorWordDefinition
{
//{{{ JVarSetStatic constructor
public JVarSetStatic(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Field field = FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class));
FactorJava.jvarSetStatic(
field,datastack.pop());
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,3);
state.pop(null);
state.pop(null);
state.pop(null);
return new StackEffect(3,0,0,0);
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
* XXX: does not use factor type system conversions.
*/
public int compileCallTo(
CodeVisitor mw,
LocalAllocator allocator,
Set recursiveCheck)
throws Exception
{
Object _field = allocator.popLiteral();
Object _clazz = allocator.popLiteral();
if(_clazz instanceof String &&
_field instanceof String)
{
String field = (String)_field;
String clazz = (String)_clazz;
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
Field fld = cls.getField(field);
allocator.pop(mw);
FactorJava.generateFromConversion(mw,fld.getType());
mw.visitFieldInsn(PUTSTATIC,
clazz,
field,
FactorJava.javaClassToVMClass(fld.getType()));
return 2;
}
else
throw new FactorCompilerException("Cannot compile jvar-static@ with non-literal parameters");
} //}}}
}

View File

@ -0,0 +1,53 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Restack extends FactorWordDefinition
{
//{{{ Restack constructor
public Restack(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Cons list = (Cons)datastack.pop(Cons.class);
interp.callstack.push(datastack);
interp.datastack = new FactorDataStack(list);
} //}}}
}

View File

@ -0,0 +1,70 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
public class Set extends FactorWordDefinition
{
//{{{ Set constructor
public Set(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
Object name = datastack.pop();
Object value = datastack.pop();
core(interp,value,name);
} //}}}
//{{{ core() method
public static void core(FactorInterpreter interp,
Object value, Object name) throws Exception
{
interp.callframe.namespace.setVariable(
FactorJava.toString(name),value);
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect(java.util.Set recursiveCheck,
LocalAllocator state) throws FactorStackException
{
state.ensure(state.datastack,2);
state.pop(null);
state.pop(null);
return new StackEffect(2,0,0,0);
} //}}}
}

View File

@ -0,0 +1,52 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Unstack extends FactorWordDefinition
{
//{{{ Unstack constructor
public Unstack(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
Cons unstack = interp.datastack.toList();
interp.datastack = (FactorDataStack)interp.callstack.pop();
interp.datastack.push(unstack);
} //}}}
}

View File

@ -0,0 +1,50 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
public class Unwind extends FactorWordDefinition
{
//{{{ Unwind constructor
public Unwind(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.callstack.top = 0;
} //}}}
}

View File

@ -2,7 +2,7 @@
! $Id$ ! $Id$
! !
! Copyright (C) 2003 Slava Pestov. ! Copyright (C) 2003, 2004 Slava Pestov.
! !
! Redistribution and use in source and binary forms, with or without ! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met: ! modification, are permitted provided that the following conditions are met:
@ -25,64 +25,76 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: randomAngle (-- theta) : random-angle ( -- theta )
[ ] "factor.FactorMath" "randomAngle" jmethod jinvokeStatic ; [ ] "factor.FactorMath"
"randomAngle" jinvoke-static ;
: randomBoolean (-- boolean) : random-boolean ( -- boolean )
[ ] "factor.FactorMath" "randomBoolean" jmethod jinvokeStatic ; [ ] "factor.FactorMath"
"randomBoolean" jinvoke-static ;
: randomInt (min max -- random) : random-digit ( -- digit )
[ "int" "int" ] "factor.FactorMath" "randomInt" jmethod jinvokeStatic ; 0 9 random-int ;
: randomSymmetricInt (max -- random) : random-float ( min max scale -- random )
[ "int" "int" "float" ] "factor.FactorMath"
"randomFloat" jinvoke-static ;
: random-int ( min max -- random )
[ "int" "int" ] "factor.FactorMath"
"randomInt" jinvoke-static ;
: random-symmetric-int ( max -- random )
! Return a random integer between -max and max. ! Return a random integer between -max and max.
dup neg swap randomInt ; dup neg swap random-int ;
: chance ( n -- boolean ) : chance ( n -- boolean )
! Returns true with a 1/n probability, false with a (n-1)/n probability. ! Returns true with a 1/n probability, false with a (n-1)/n
1 swap randomInt 1 = ;
: randomElement (list -- random)
! Returns a random element from the given list.
dup length pred 0 swap randomInt get ;
: randomSubset (list -- list)
! Returns a random subset of the given list. Each item is chosen with a 50%
! probability. ! probability.
[ ] [ randomBoolean [ drop ] when ] map ; 1 swap random-int 1 = ;
: random-element ( list -- random )
! Returns a random element from the given list.
dup length pred 0 swap random-int get ;
: random-subset ( list -- list )
! Returns a random subset of the given list. Each item is
! chosen with a 50%
! probability.
[ random-boolean [ drop ] when ] map ;
: car+ ( list -- sum ) : car+ ( list -- sum )
! Adds the car of each element of the given list. ! Adds the car of each element of the given list.
0 swap [ car + ] each ; 0 swap [ car + ] each ;
: randomProbability (list -- sum) : random-probability ( list -- sum )
! Adds the car of each element of the given list, and returns a random ! Adds the car of each element of the given list, and
! number between 1 and this sum. ! returns a random number between 1 and this sum.
1 swap car+ randomInt ; 1 swap car+ random-int ;
: randomElementIter (list index -- elem) : random-element-iter ( list index -- elem )
! Used by randomElement*. Do not call directly. ! Used by random-element*. Do not call directly.
[ unswons unswons ] dip (list elem probability index) [ unswons unswons ] dip (list elem probability index)
-- (list elem index) swap - (list elem index)
dup 0 <= [ dup 0 <= [
drop nip drop nip
] [ ] [
nip randomElementIter nip random-element-iter
] ifte ; ] ifte ;
: randomElement* (list -- elem) : random-element* ( list -- elem )
! Returns a random element of the given list of comma pairs. The ! Returns a random element of the given list of comma pairs.
! car of each pair is a probability, the cdr is the item itself. ! The car of each pair is a probability, the cdr is the item
! Only the cdr of the comma pair is returned. ! itself. Only the cdr of the comma pair is returned.
dup 1 swap car+ randomInt randomElementIter ; dup 1 swap car+ random-int random-element-iter ;
: randomSubset* (list -- list) : random-subset* ( list -- list )
! Returns a random subset of the given list of comma pairs. The ! Returns a random subset of the given list of comma pairs.
! car of each pair is a probability, the cdr is the item itself. ! The car of each pair is a probability, the cdr is the item
! Only the cdr of the comma pair is returned. ! itself. Only the cdr of the comma pair is returned.
dup [ [ [ ] ] dip car+ ] dip ([ ] probabilitySum list) dup [ [ [ ] ] dip car+ ] dip ([ ] probabilitySum list)
[ [
[ 1 over randomInt ] dip ([ ] probabilitySum probability elem) [ 1 over random-int ] dip ([ ] probabilitySum probability elem)
uncons ([ ] probabilitySum probability elema elemd) uncons ([ ] probabilitySum probability elema elemd)
-rot ([ ] probabilitySum elemd probability elema) -rot ([ ] probabilitySum elemd probability elema)
> ([ ] probabilitySum elemd boolean) > ([ ] probabilitySum elemd boolean)

View File

@ -2,7 +2,7 @@
! $Id$ ! $Id$
! !
! Copyright (C) 2003 Slava Pestov. ! Copyright (C) 2003, 2004 Slava Pestov.
! !
! Redistribution and use in source and binary forms, with or without ! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met: ! modification, are permitted provided that the following conditions are met:
@ -26,18 +26,18 @@
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: <stream> ( -- stream ) : <stream> ( -- stream )
! Create a stream object. A stream is a namespace with the following ! Create a stream object. A stream is a namespace with the
! entries: ! following entries:
! - fflush ! - fflush
! - freadln -- you must provide an implementation! ! - freadln -- you must provide an implementation!
! - fwriteln ! - fwriteln
! - fwrite -- you must provide an implementation! ! - fwrite -- you must provide an implementation!
! - fclose ! - fclose
! Note that you must extend this object and provide your own implementations ! Note that you must extend this object and provide your own
! of all entries except for fwriteln, which is defined to fwrite the string ! implementations of all entries except for fwriteln, which
! followed by the newline by default. ! is defined to fwrite the string followed by the newline by
! default.
<namespace> [ <namespace> [
( -- string ) ( -- string )
[ "freadln not implemented." break ] @freadln [ "freadln not implemented." break ] @freadln
( string -- ) ( string -- )
@ -50,91 +50,99 @@
[ $namespace fwrite "\n" $namespace fwrite ] @fwriteln [ $namespace fwrite "\n" $namespace fwrite ] @fwriteln
] extend ; ] extend ;
! These are in separate words so that they can be compiled.
! Do not call them directly.
: <bytestream>/freadln ( -- string )
$in [ "java.io.InputStream" ] "factor.FactorLib" "readLine"
jinvoke-static ;
: <bytestream>/fwrite ( string -- )
>bytes
$out [ [ "byte" ] ]
"java.io.OutputStream" "write" jinvoke ;
: <bytestream>/fflush ( -- )
$out [ ] "java.io.OutputStream" "flush" jinvoke ;
: <bytestream>/fclose ( -- )
$in [ ] "java.io.InputStream" "close" jinvoke
$out [ ] "java.io.OutputStream" "close" jinvoke ;
: <bytestream> ( in out -- stream ) : <bytestream> ( in out -- stream )
! Creates a new stream for reading from the java.io.InputStream in, and ! Creates a new stream for reading from the
! writing to the java.io.OutputStream out. ! java.io.InputStream in, and writing to the
! java.io.OutputStream out.
<stream> [ <stream> [
@out @out
@in @in
( -- string ) ( -- string )
[ [ <bytestream>/freadln ] @freadln
$in [ "java.io.InputStream" ] "factor.FactorLib" "readLine"
jmethod jinvokeStatic
] @freadln
( string -- ) ( string -- )
[ [ <bytestream>/fwrite ] @fwrite
>bytes
$out [ "[B" ] "java.io.OutputStream" "write" jmethod jinvoke
] @fwrite
( -- ) ( -- )
[ [ <bytestream>/fflush ] @fflush
$out [ ] "java.io.OutputStream" "flush" jmethod jinvoke
] @fflush
( -- ) ( -- )
[ [ <bytestream>/fclose ] @fclose
$in [ ] "java.io.InputStream" "close" jmethod jinvoke
$out [ ] "java.io.OutputStream" "close" jmethod jinvoke
] @fclose
] extend ; ] extend ;
: <charstream>/freadln ( -- string )
$in [ ] "java.io.BufferedReader" "readLine"
jinvoke ;
: <charstream>/fwrite ( string -- )
$out [ "java.lang.String" ] "java.io.Writer" "write"
jinvoke ;
: <charstream>/fflush ( -- )
$out [ ] "java.io.Writer" "flush" jinvoke ;
: <charstream>/fclose ( -- )
$in [ ] "java.io.Reader" "close" jinvoke
$out [ ] "java.io.Writer" "close" jinvoke ;
: <charstream> ( in out -- stream ) : <charstream> ( in out -- stream )
! Creates a new stream for reading from the java.io.BufferedReader in, and ! Creates a new stream for reading from the
! writing to the java.io.Reader out. ! java.io.BufferedReader in, and writing to the
! java.io.Reader out.
<stream> [ <stream> [
@out @out
@in @in
( -- string ) ( -- string )
[ [ <charstream>/freadln ] @freadln
$in [ ] "java.io.BufferedReader" "readLine" jmethod jinvoke
] @freadln
( string -- ) ( string -- )
[ [ <charstream>/fwrite ] @fwrite
$out [ "java.lang.String" ] "java.io.Writer" "write" jmethod jinvoke
] @fwrite
( -- ) ( -- )
[ [ <charstream>/fflush ] @fflush
$out [ ] "java.io.Writer" "flush" jmethod jinvoke
] @fflush
( -- ) ( -- )
[ [ <charstream>/fclose ] @fclose
$in [ ] "java.io.Reader" "close" jmethod jinvoke
$out [ ] "java.io.Writer" "close" jmethod jinvoke
] @fclose
] extend ; ] extend ;
: <filecr> ( path -- stream ) : <filecr> ( path -- stream )
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader> [ |java.lang.String ] |java.io.FileReader jnew <breader>
f f
<charstream> ; <charstream> ;
: <filecw> ( path -- stream ) : <filecw> ( path -- stream )
f f
[ |java.lang.String ] |java.io.FileWriter jconstructor jnew <bwriter> [ |java.lang.String ] |java.io.FileWriter jnew <bwriter>
<charstream> ; <charstream> ;
: <filebr> ( path -- stream ) : <filebr> ( path -- stream )
[ |java.lang.String ] |java.io.FileInputStream jconstructor jnew [ |java.lang.String ] |java.io.FileInputStream jnew
f f
<bytestream> ; <bytestream> ;
: <filebw> ( path -- stream ) : <filebw> ( path -- stream )
f f
[ |java.lang.String ] |java.io.FileOutputStream jconstructor jnew [ |java.lang.String ] |java.io.FileOutputStream jnew
<bytestream> ; <bytestream> ;
: <bwriter> (writer -- bwriter) : <bwriter> (writer -- bwriter)
[ |java.io.Writer ] |java.io.BufferedWriter jconstructor jnew ; [ |java.io.Writer ] |java.io.BufferedWriter jnew ;
: <owriter> (outputstream -- owriter) : <owriter> (outputstream -- owriter)
[ |java.io.OutputStream ] |java.io.OutputStreamWriter jconstructor jnew ; [ |java.io.OutputStream ] |java.io.OutputStreamWriter jnew ;
: read ( -- string ) : read ( -- string )
$stdio freadln ; $stdio freadln ;
@ -165,30 +173,30 @@
[ [ $in ] bind ] dip [ [ $in ] bind ] dip
[ $out ] bind [ $out ] bind
[ "java.io.InputStream" "java.io.OutputStream" ] [ "java.io.InputStream" "java.io.OutputStream" ]
"factor.FactorLib" "copy" jmethod jinvokeStatic ; "factor.FactorLib" "copy" jinvoke-static ;
"java.lang.System" "in" jfield jvarStatic$ <ireader> <breader> @stdin "java.lang.System" "in" jvar-static$ <ireader> <breader> @stdin
"java.lang.System" "out" jfield jvarStatic$ <owriter> @stdout "java.lang.System" "out" jvar-static$ <owriter> @stdout
$stdin $stdout <charstream> @stdio $stdin $stdout <charstream> @stdio
!(file -- freader) !(file -- freader)
|<freader> [ |<freader> [
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader> [ |java.lang.String ] |java.io.FileReader jnew <breader>
] define ] define
: <file> (path -- file) : <file> (path -- file)
dup "java.io.File" is not [ dup "java.io.File" is not [
[ "java.lang.String" ] "java.io.File" jconstructor jnew [ "java.lang.String" ] "java.io.File" jnew
] when ; ] when ;
: exists? (file -- boolean) : exists? (file -- boolean)
<file> [ ] "java.io.File" "exists" jmethod jinvoke ; <file> [ ] "java.io.File" "exists" jinvoke ;
: directory? (file -- boolean) : directory? (file -- boolean)
<file> [ ] "java.io.File" "isDirectory" jmethod jinvoke ; <file> [ ] "java.io.File" "isDirectory" jinvoke ;
: directory ( file -- listing ) : directory ( file -- listing )
<file> [ ] "java.io.File" "list" jmethod jinvoke <file> [ ] "java.io.File" "list" jinvoke
array>list ; array>list ;
: rename ( from to -- ) : rename ( from to -- )
@ -196,26 +204,27 @@ $stdin $stdout <charstream> @stdio
! java.io.File instances. ! java.io.File instances.
<file> swap <file> <file> swap <file>
[ "java.io.File" ] "java.io.File" "renameTo" [ "java.io.File" ] "java.io.File" "renameTo"
jmethod jinvoke ; jinvoke ;
!(string -- reader) !(string -- reader)
|<sreader> [ |<sreader> [
[ |java.lang.String ] |java.io.StringReader jconstructor jnew [ |java.lang.String ] |java.io.StringReader jnew
] define ] define
: close (stream --) : close (stream --)
dup "java.io.Reader" is dup "java.io.Reader" is [
[ ] "java.io.Reader" "close" jmethod [ ] "java.io.Reader" "close" jinvoke
[ ] "java.io.Writer" "close" jmethod ] [
? [ ] "java.io.Writer" "close" jinvoke
jinvoke ; ] ifte ;
: exec ( args -- exitCode ) : exec ( args -- exitCode )
[ "[Ljava.lang.String;" ] "factor.FactorLib" "exec" jmethod jinvokeStatic ; [ [ "java.lang.String" ] ] "factor.FactorLib" "exec"
jinvoke-static ;
!(stream -- string) !(stream -- string)
|read* [ |read* [
[ ] |java.io.BufferedReader |readLine jmethod jinvoke [ ] |java.io.BufferedReader |readLine jinvoke
] define ] define
: print* (string stream --) : print* (string stream --)
@ -225,6 +234,6 @@ $stdin $stdout <charstream> @stdio
!(string stream --) !(string stream --)
|write* [ |write* [
tuck tuck
[ |java.lang.String ] |java.io.Writer |write jmethod jinvoke [ |java.lang.String ] |java.io.Writer |write jinvoke
[ ] |java.io.Writer |flush jmethod jinvoke [ ] |java.io.Writer |flush jinvoke
] define ] define

View File

@ -2,7 +2,7 @@
! $Id$ ! $Id$
! !
! Copyright (C) 2003 Slava Pestov. ! Copyright (C) 2003, 2004 Slava Pestov.
! !
! Redistribution and use in source and binary forms, with or without ! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met: ! modification, are permitted provided that the following conditions are met:
@ -35,103 +35,186 @@
! [ #\" , "&quot;" ] ! [ #\" , "&quot;" ]
] @entities ] @entities
: >str ( obj -- string )
! Returns the Java string representation of this object.
[ ] "java.lang.Object" "toString" jinvoke ;
: >bytes ( string -- array ) : >bytes ( string -- array )
! Converts a string to an array of ASCII bytes. An exception is thrown ! Converts a string to an array of ASCII bytes. An exception
! if the string contains non-ASCII characters. ! is thrown if the string contains non-ASCII characters.
"ASCII" swap "ASCII" swap
[ "java.lang.String" ] "java.lang.String" "getBytes" jmethod jinvoke ; [ "java.lang.String" ] "java.lang.String" "getBytes"
jinvoke ;
: <sbuf> ( -- StringBuffer )
[ ] "java.lang.StringBuffer" jnew ;
: sbuf-append ( str buf -- buf )
[ "java.lang.String" ] "java.lang.StringBuffer" "append"
jinvoke ;
: cat ( [ "a" "b" "c" ] -- "abc" ) : cat ( [ "a" "b" "c" ] -- "abc" )
[ "factor.FactorList" ] "factor.FactorLib" "cat" jmethod jinvokeStatic ; ! If f appears in the list, it is not appended to the
! string.
<sbuf> swap [ [ swap sbuf-append ] when* ] each >str ;
: cat2 ( "a" "b" -- "ab" ) : cat2 ( "a" "b" -- "ab" )
[ "java.lang.Object" "java.lang.Object" ] swap <sbuf> sbuf-append sbuf-append >str ;
"factor.FactorLib" "cat2" jmethod jinvokeStatic ;
: cat3 ( "a" "b" "c" -- "abc" ) : cat3 ( "a" "b" "c" -- "abc" )
[ "java.lang.Object" "java.lang.Object" "java.lang.Object" ] [ ] cons cons cons cat ;
"factor.FactorLib" "cat3" jmethod jinvokeStatic ;
: cat4 ( "a" "b" "c" "d" -- "abcd" ) : cat4 ( "a" "b" "c" "d" -- "abcd" )
cat2 cat3 ; [ ] cons cons cons cons cat ;
: char? ( obj -- boolean )
"java.lang.Character" is ;
: chars>entities ( str -- str ) : chars>entities ( str -- str )
! Convert <, >, &, ' and " to HTML entities. ! Convert <, >, &, ' and " to HTML entities.
"" [ dup $entities assoc dup [ nip ] [ drop ] ifte ] strmap ; [ dup $entities assoc dup [ nip ] [ drop ] ifte ] strmap ;
: group ( index match -- ) : group ( index match -- )
[ "int" ] "java.util.regex.Matcher" "group" [ "int" ] "java.util.regex.Matcher" "group"
jmethod jinvoke ; jinvoke ;
: groupCount (matcher -- count) : group-count ( matcher -- count )
[ ] "java.util.regex.Matcher" "groupCount" [ ] "java.util.regex.Matcher" "groupCount"
jmethod jinvoke ; jinvoke ;
: groups* ( matcher -- list ) : groups* ( matcher -- list )
[ [
[ [
dup groupCount [ dup group-count [
succ over group swap succ over group swap
] times* drop ] times* drop
] cons expand ] cons expand
] [matches] ; ] [re-matches] ;
: groups ( input regex -- list ) : groups ( input regex -- list )
<regex> <matcher> groups* ; <regex> <matcher> groups* ;
: [matches] ( matcher code -- boolean ) : index-of* ( index string substring -- index )
! If the matcher's matches* function returns true, dup char? [
-rot
! Why is the first parameter an int and not a char?
[ "int" "int" ]
"java.lang.String" "indexOf"
jinvoke
] [
-rot
[ "java.lang.String" "int" ]
"java.lang.String" "indexOf"
jinvoke
] ifte ;
: index-of ( string substring -- index )
0 -rot index-of* ;
: [re-matches] ( matcher code -- boolean )
! If the matcher's re-matches* function returns true,
! evaluate the code with the matcher at the top of the ! evaluate the code with the matcher at the top of the
! stack. Otherwise, pop the matcher off the stack and ! stack. Otherwise, pop the matcher off the stack and
! push f. ! push f.
[ dup matches* ] dip [ drop f ] ifte ; [ dup re-matches* ] dip [ drop f ] ifte ;
: <matcher> ( string pattern -- matcher ) : <matcher> ( string pattern -- matcher )
[ "java.lang.CharSequence" ] [ "java.lang.CharSequence" ]
"java.util.regex.Pattern" "matcher" "java.util.regex.Pattern" "matcher"
jmethod jinvoke ; jinvoke ;
: matches* (matcher -- boolean) : re-matches* ( matcher -- boolean )
[ ] "java.util.regex.Matcher" "matches" [ ] "java.util.regex.Matcher" "matches"
jmethod jinvoke ; jinvoke ;
: matches (input regex -- boolean) : re-matches ( input regex -- boolean )
<regex> <matcher> matches* ; <regex> <matcher> re-matches* ;
: replace* ( replace matcher -- string ) : re-replace* ( replace matcher -- string )
[ "java.lang.String" ] "java.util.regex.Matcher" [ "java.lang.String" ] "java.util.regex.Matcher"
"replaceAll" jmethod jinvoke ; "replaceAll" jinvoke ;
: replace ( input regex replace -- string ) : re-replace ( input regex replace -- string )
! Replaces all occurrences of the regex in the input string ! Replaces all occurrences of the regex in the input string
! with the replace string. ! with the replace string.
-rot <regex> <matcher> replace* ; -rot <regex> <matcher> re-replace* ;
: re-split ( string split -- list )
<regex> [ "java.lang.CharSequence" ]
"java.util.regex.Pattern" "split" jinvoke array>list ;
: <regex> (pattern -- regex) : <regex> (pattern -- regex)
! Compile the regex, if its not already compiled. ! Compile the regex, if its not already compiled.
dup "java.util.regex.Pattern" is not [ dup "java.util.regex.Pattern" is not [
[ "java.lang.String" ] "java.util.regex.Pattern" "compile" [ "java.lang.String" ]
jmethod jinvokeStatic "java.util.regex.Pattern" "compile"
jinvoke-static
] when ; ] when ;
: strget (index str -- char) : split ( string split -- list )
[ "int" ] "java.lang.String" "charAt" jmethod jinvoke ; 2dup index-of dup -1 = [
2drop unit
] [
swap [ str// ] dip split cons
] ifte ;
: strlen (str -- length) : str/ ( str index -- str str )
[ ] "java.lang.String" "length" jmethod jinvoke ; ! Returns 2 strings, that when concatenated yield the
! original string.
2dup strtail [ str-head ] dip ;
: streach (str [ code ] --) : str// ( str index -- str str )
! Execute the code, with each character of the string pushed onto the ! Returns 2 strings, that when concatenated yield the
! stack. ! original string, without the character at the given
over strlen [ ! index.
-rot 2dup [ [ strget ] dip call ] 2dip 2dup succ strtail [ str-head ] dip ;
: str-each ( str [ code ] -- )
! Execute the code, with each character of the string pushed
! onto the stack.
over str-length [
-rot 2dup [ [ str-get ] dip call ] 2dip
] times* 2drop ; ] times* 2drop ;
: strmap (str initial [ code ] -- [ mapping ]) : str-expand ( [ code ] -- str )
! If the 'initial' parameter is f, turn it into "". expand cat ;
! Maybe cat should handle this instead?
[ dup [ drop "" ] unless ] dip : str-get (index str -- char)
swapd [ ] cons cons cons [ "int" ] "java.lang.String" "charAt" jinvoke ;
restack
streach : str-head ( str index -- str )
unstack cat ; ! Returns a new string, from the beginning of the string
! until the given index.
0 transp substring ;
: str-headcut ( str begin -- str str )
str-length str/ ;
: str-head? ( str begin -- str )
! If the string starts with begin, return the rest of the
! string after begin. Otherwise, return f.
2dup str-length> [
tuck str-headcut
[ = ] dip f ?
] [
2drop f
] ifte ;
: str-length ( str -- length )
[ ] "java.lang.String" "length" jinvoke ;
: str-length> ( str str -- boolean )
! Compare string lengths.
[ str-length ] apply2 > ;
: str-map ( str [ code ] -- [ mapping ] )
2list restack str-each unstack cat ;
: strtail ( str index -- str )
! Returns a new string, from the given index until the end
! of the string.
over str-length rot substring ;
: substring ( start end str -- str )
[ "int" "int" ] "java.lang.String" "substring"
jinvoke ;

View File

@ -1 +1 @@
"0.29" @version "0.36" @version