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.visitMaxs(Math.max(4,2 + effect.inD),4);
String evalAsm = getDisassembly(mw);
// generate core
_mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
"core",signature,null,null);
mw = new TraceCodeVisitor(_mw);
LocalAllocator allocator = new LocalAllocator(interp,
className,1,effect.inD);
int maxJVMStack = allocator.compile(definition,mw,
recursiveCheck);
if(effect.outD == 0)
mw.visitInsn(RETURN); mw.visitInsn(RETURN);
// Max stack and locals else
mw.visitMaxs(1,1);
return true;
}
FactorList fdef = compilePass1(interp,definition);
if(fdef.car instanceof FactorReflectionForm
&& fdef.cdr == null)
{ {
return ((FactorReflectionForm)fdef.car).compile( allocator.pop(mw);
word,interp,cw,mw); mw.visitInsn(ARETURN);
maxJVMStack = Math.max(maxJVMStack,1);
} }
/* else
System.err.println("WARNING: cannot compile reflection & more"); */
return false; mw.visitMaxs(maxJVMStack,allocator.maxLocals());
String coreAsm = getDisassembly(mw);
return new CompileResult(allocator,
"eval(Lfactor/FactorInterpreter;)V:\n" + evalAsm
+ "core" + signature + "\n" + coreAsm);
} //}}} } //}}}
//{{{ compilePass1() method //{{{ getDisassembly() method
protected String getDisassembly(TraceCodeVisitor mw)
{
// Save the disassembly of the eval() method
StringBuffer buf = new StringBuffer();
Iterator bytecodes = mw.getText().iterator();
while(bytecodes.hasNext())
{
buf.append(bytecodes.next());
}
return buf.toString();
} //}}}
//{{{ compileDataStackToJVMStack() method
private void compileDataStackToJVMStack(StackEffect effect,
CodeVisitor mw)
{
if(effect.inD != 0)
{
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++)
{
mw.visitVarInsn(ALOAD,2);
mw.visitVarInsn(ILOAD,3);
mw.visitInsn(AALOAD);
if(i != effect.inD - 1)
mw.visitIincInsn(3,1);
}
}
} //}}}
//{{{ compileJVMStackToDataStack() method
private void compileJVMStackToDataStack(StackEffect effect,
CodeVisitor mw)
{
if(effect.outD == 1)
{
// ( datastack )
mw.visitVarInsn(ALOAD,1);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
}
} //}}}
//{{{ compileImmediate() method
/** /**
* Turn reflection calls into ReflectionForm objects. * Compile a call to this word. Returns maximum JVM stack use.
*/ */
private FactorList compilePass1(FactorInterpreter interp, FactorList def) public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws Exception
{ {
if(!def.isProperList()) return allocator.compile(definition,mw,recursiveCheck);
return def;
FactorList rdef = def.reverse();
FactorDictionary dict = interp.dict;
// A list of words and Java reflection forms
FactorList fdef = null;
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
{
/*System.err.println(
"WARNING: "
+ newWord
+ " references "
+ o
+ " before its defined");*/
}
if(o == dict.jconstructor)
{
jconstructorPrecompile(
interp,list);
}
else if(o == dict.jmethod)
{
jmethodPrecompile(
interp,list);
}
else if(o == dict.jfield)
{
jfieldPrecompile(
interp,list);
}
}
else if(o instanceof FactorList)
{
if(((FactorList)o).isProperList())
{
FactorList l = (FactorList)o;
FactorList _l = l.reverse();
precompile(interp,newWord,_l);
list.car = _l.reverse();
}
}
list = list.next();
}
} //}}}
//{{{ jconstructorPrecompile() method
private void jconstructorPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String clazz = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof FactorList))
return;
FactorList args = (FactorList)cddr.car;
Constructor c = FactorJava.jconstructor(clazz,args);
list.car = c;
list.cdr = cddr.next();
} //}}}
//{{{ jfieldPrecompile() 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,
* inline the result.
*/
private void jmethodPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
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,21 +86,22 @@ 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();
} //}}} } //}}}
//{{{ initNamespace() method //{{{ initNamespace() method
@ -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())
return (Object[])arg; {
if(arg.getClass() == clas)
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);
} //}}} } //}}}
@ -296,7 +359,7 @@ public class FactorJava
else if(obj instanceof Character) else if(obj instanceof Character)
return "#\\" + ((Character)obj).charValue(); return "#\\" + ((Character)obj).charValue();
else else
return "(" + obj + ")"; return "( " + obj + " )";
} //}}} } //}}}
//{{{ javaClassToVMClass() method //{{{ javaClassToVMClass() method
@ -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,
// (datastack datastack datastack) Set recursiveCheck) throws FactorStackException
mw.visitVarInsn(ALOAD,2); {
mw.visitFieldInsn(GETFIELD, eval(allocator.datastack,allocator.callstack);
"factor/FactorInterpreter", "datastack", return 0;
"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
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorWord word, FactorInterpreter interp)
throws Exception
{ {
if(!canCompile()) return getStackEffect(new HashSet(),new LocalAllocator());
return this; } //}}}
//System.out.println("Compiling " + word); //{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
StringBuffer sanitizedName = new StringBuffer(); LocalAllocator state) throws Exception
for(int i = 0; i < word.name.length(); i++) {
{ return null;
char ch = word.name.charAt(i);
if(!Character.isJavaIdentifierStart(ch))
sanitizedName.append("_");
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());
}
// 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 //{{{ compile() method
/** FactorWordDefinition compile(FactorInterpreter interp,
* Write the definition of the eval() method in the compiled word. Set recursiveCheck) throws Exception
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{ {
throw new FactorRuntimeException("Don't know how to compile " + word); return this;
} //}}} } //}}}
//{{{ SimpleClassLoader class //{{{ compileCallTo() method
static class SimpleClassLoader extends ClassLoader /**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws Exception
{ {
public Class _defineClass(String name, StackEffect effect = getStackEffect();
byte[] code, int off, int len) if(effect == null)
{ {
return defineClass(name,code,off,len); // combinator; inline
return compileImmediate(mw,allocator,recursiveCheck);
} }
else
{
// 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;
}
} //}}}
//{{{ compileImmediate() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws Exception
{
throw new FactorCompilerException("Cannot compile " + word + " in immediate mode");
} //}}} } //}}}
} }

View File

@ -28,28 +28,30 @@
!!! The stack operators are defined using shuffle notation. This saves several !!! The stack operators are defined using shuffle notation. This saves several
!!! hundred lines of code! !!! hundred lines of code!
~<< drop A -- >>~ ~<< drop A -- >>~
~<< 2drop A B -- >>~ ~<< 2drop A B -- >>~
~<< dup A -- A A >>~ ~<< dup A -- A A >>~
~<< 2dup A B -- A B A B >>~ ~<< 2dup A B -- A B A B >>~
~<< dupd A B -- A A B >>~ ~<< dupd A B -- A A B >>~
~<< 2dupd A B C D -- A B A B C D >>~ ~<< 2dupd A B C D -- A B A B C D >>~
~<< nip A B -- B >>~ ~<< nip A B -- B >>~
~<< 2nip A B C D -- C D >>~ ~<< 2nip A B C D -- C D >>~
~<< nop -- >>~ ! Does nothing! ~<< nop -- >>~ ! Does nothing!
~<< over A B -- A B A >>~ ~<< over A B -- A B A >>~
~<< 2over A B C D -- A B C D A B >>~ ~<< 2over A B C D -- A B C D A B >>~
~<< pick A B C -- A B C A >>~ ! Not the Forth pick! ~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
~<< rot A B C -- B C A >>~ ~<< rot A B C -- B C A >>~
~<< 2rot A B C D E F -- C D E F A B >>~ ~<< 2rot A B C D E F -- C D E F A B >>~
~<< -rot A B C -- C A B >>~ ~<< -rot A B C -- C A B >>~
~<< 2-rot A B C D E F -- E F A B C D >>~ ~<< 2-rot A B C D E F -- E F A B C D >>~
~<< swap A B -- B A >>~ ~<< swap A B -- B A >>~
~<< 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 >>~
~<< tuck A B -- B A B >>~ ~<< transp A B C -- C B A >>~
~<< 2tuck A B C D -- C D A B C D >>~ ~<< 2transp A B C D E F -- E F C D A B >>~
~<< tuck A B -- B A B >>~
~<< 2tuck A B C D -- C D A B C D >>~
~<< rdrop r:A -- >>~ ~<< rdrop r:A -- >>~
~<< >r A -- r:A >>~ ~<< >r A -- r:A >>~
@ -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 ;
: worddef (word -- worddef) : intern ("word" -- word)
str>word ! Returns the top of the stack if it already been interned.
! Get the 'def' field dup word? [
"factor.FactorWord" "def" jfield jvar$ $dict [ "java.lang.String" ]
! Is it equal to the missing word placeholder? Then push f. "factor.FactorDictionary" "intern"
dup $undefinedWord = [ drop f ] when ; 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 )
intern
"factor.FactorWord" "def" jvar$
missing>f ;
: 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,12 +58,12 @@
: 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 ;
: httpdUriToPath (uri -- path) : httpdUriToPath (uri -- path)
@ -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:
@ -31,8 +31,8 @@
: 2rlist (a b -- [ b a ]) : 2rlist (a b -- [ b a ])
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) : last* ( list -- last )
! Pushes last cons of the list.
[ dup cdr ] [ cdr ] while ;
: 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 = ;
: car+ (list -- sum) : 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 )
! 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 ;
: cat ([ "a" "b" "c" ] -- "abc") : <sbuf> ( -- StringBuffer )
[ "factor.FactorList" ] "factor.FactorLib" "cat" jmethod jinvokeStatic ; [ ] "java.lang.StringBuffer" jnew ;
: cat2 ("a" "b" -- "ab") : sbuf-append ( str buf -- buf )
[ "java.lang.Object" "java.lang.Object" ] [ "java.lang.String" ] "java.lang.StringBuffer" "append"
"factor.FactorLib" "cat2" jmethod jinvokeStatic ; jinvoke ;
: cat3 ("a" "b" "c" -- "abc") : cat ( [ "a" "b" "c" ] -- "abc" )
[ "java.lang.Object" "java.lang.Object" "java.lang.Object" ] ! If f appears in the list, it is not appended to the
"factor.FactorLib" "cat3" jmethod jinvokeStatic ; ! string.
<sbuf> swap [ [ swap sbuf-append ] when* ] each >str ;
: cat4 ("a" "b" "c" "d" -- "abcd") : cat2 ( "a" "b" -- "ab" )
cat2 cat3 ; swap <sbuf> sbuf-append sbuf-append >str ;
: chars>entities (str -- str) : cat3 ( "a" "b" "c" -- "abc" )
[ ] cons cons cons cat ;
: cat4 ( "a" "b" "c" "d" -- "abcd" )
[ ] cons cons cons cons cat ;
: char? ( obj -- boolean )
"java.lang.Character" is ;
: 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