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/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.12 2004/01/06 06:59:38 slava Exp $
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.12 2004/01/14 01:58:37 slava Exp $
./factor/combinators.factor:! $Id: combinators.factor,v 1.17 2004/01/11 23:00:34 slava Exp $
./factor/FactorDataStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
./factor/continuations.factor:! $Id: continuations.factor,v 1.8 2003/12/20 05:31:01 slava Exp $
./factor/network.factor:! $Id: io.factor,v 1.2 2003/12/20 05:31:01 slava Exp $
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.10 2004/01/03 20:58:09 slava Exp $
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2003/12/16 08:03:08 slava Exp $
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2003/12/09 09:52:26 slava Exp $
./factor/lists.factor:! $Id: lists.factor,v 1.10 2004/01/06 06:59:38 slava Exp $
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2003/12/26 00:36:30 slava Exp $
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.1 2004/01/15 03:00:18 slava Exp $
./factor/FactorPrimitive.java: * $Id: FactorPrimitive.java,v 1.5 2004/01/11 23:00:34 slava Exp $
./factor/FactorList.java: * $Id: FactorList.java,v 1.9 2004/01/03 20:58:09 slava Exp $
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.10 2004/01/08 04:14:14 slava Exp $
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/examples.factor:! $Id: examples.factor,v 1.4 2004/01/12 02:07:31 slava Exp $
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.2 2004/01/14 01:58:37 slava Exp $
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.5 2003/12/19 21:40:00 slava Exp $
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.13 2004/01/10 23:24:30 slava Exp $
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.7 2003/12/26 00:36:30 slava Exp $
./factor/parser.factor:! $Id: parser.factor,v 1.2 2003/12/20 04:30:06 slava Exp $
./factor/FactorMissingDefinition.java: * $Id: FactorWordDefinition.java,v 1.10 2003/12/18 00:01:39 slava Exp $
./factor/stream.factor:! $Id: stream.factor,v 1.1 2004/01/03 20:58:09 slava Exp $
./factor/FactorReflectionForm.java:* $Id: FactorReflectionForm.java,v 1.1 2004/01/14 01:58:37 slava Exp $
./factor/strings.factor:! $Id: strings.factor,v 1.4 2004/01/06 06:59:38 slava Exp $
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.32 2004/01/12 02:07:31 slava Exp $
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.10 2004/01/08 04:14:14 slava Exp $
./factor/math.factor:! $Id: math.factor,v 1.11 2004/01/11 23:00:34 slava Exp $
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.17 2004/01/14 01:58:37 slava Exp $
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.14 2004/01/11 23:00:34 slava Exp $
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2003/12/21 05:29:46 slava Exp $
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.3 2003/12/20 05:31:01 slava Exp $
./factor/boot.factor:! $Id: boot.factor,v 1.12 2004/01/12 02:07:31 slava Exp $
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/01/05 05:03:36 slava Exp $
./factor/FactorException.java: * $Id: FactorException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.5 2004/01/14 01:58:37 slava Exp $
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.6 2004/01/12 02:07:31 slava Exp $
./factor/compiler/StackEffect.java: * $Id: StackEffect.java,v 1.6 2004/02/15 22:24:19 slava Exp $
./factor/compiler/LocalAllocator.java: * $Id: LocalAllocator.java,v 1.9 2004/02/17 20:36:09 slava Exp $
./factor/compiler/FactorCompilerException.java: * $Id: FactorCompilerException.java,v 1.1 2004/01/27 19:55:40 slava Exp $
./factor/compiler/CompiledDefinition.java:* $Id: CompiledDefinition.java,v 1.4 2004/02/15 22:24:19 slava Exp $
./factor/random.factor:! $Id: random.factor,v 1.6 2004/02/18 00:48:47 slava Exp $
./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.7 2004/02/15 05:44:54 slava Exp $
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.8 2004/02/15 22:24:19 slava Exp $
./factor/combinators.factor:! $Id: combinators.factor,v 1.4 2004/02/13 23:19:43 slava Exp $
./factor/FactorDataStack.java: * $Id: FactorDataStack.java,v 1.3 2004/02/15 22:24:19 slava Exp $
./factor/continuations.factor:! $Id: continuations.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/network.factor:! $Id: network.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.4 2004/02/15 22:24:19 slava Exp $
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/lists.factor:! $Id: lists.factor,v 1.7 2004/02/15 22:24:19 slava Exp $
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2004/02/05 04:47:05 slava Exp $
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.3 2004/02/13 23:19:43 slava Exp $
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.4 2004/02/05 04:47:05 slava Exp $
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/examples.factor:! $Id: examples.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/Cons.java: * $Id: Cons.java,v 1.4 2004/02/11 03:49:45 slava Exp $
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.9 2004/02/15 22:24:19 slava Exp $
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.3 2004/01/26 03:16:54 slava Exp $
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.3 2004/02/17 20:36:09 slava Exp $
./factor/parser.factor:! $Id: parser.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
./factor/FactorMissingDefinition.java: * $Id: FactorMissingDefinition.java,v 1.7 2004/02/15 22:24:19 slava Exp $
./factor/stream.factor:! $Id: stream.factor,v 1.3 2004/02/10 05:43:37 slava Exp $
./factor/strings.factor:! $Id: strings.factor,v 1.9 2004/02/18 00:48:47 slava Exp $
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.6 2004/02/17 20:36:09 slava Exp $
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.7 2004/02/15 05:44:54 slava Exp $
./factor/math.factor:! $Id: math.factor,v 1.5 2004/02/17 20:36:09 slava Exp $
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.14 2004/02/15 22:24:19 slava Exp $
./factor/primitives/CallstackSet.java: * $Id: CallstackSet.java,v 1.2 2004/02/15 22:24:19 slava Exp $
./factor/primitives/JInvokeStatic.java: * $Id: JInvokeStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Unwind.java: * $Id: Unwind.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/JVarGetStatic.java: * $Id: JVarGetStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/Unstack.java: * $Id: Unstack.java,v 1.2 2004/02/15 22:24:20 slava Exp $
./factor/primitives/JInvoke.java: * $Id: JInvoke.java,v 1.2 2004/02/15 22:24:20 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$
*
* Copyright (C) 2003 Slava Pestov.
* 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:
@ -29,20 +29,18 @@
package factor;
import java.util.LinkedList;
import java.util.List;
/**
* Used to build up linked lists.
*/
public class FactorList implements PublicCloneable, FactorExternalizable
public class Cons implements PublicCloneable, FactorExternalizable
{
public static int COUNT;
public Object car;
public Object cdr;
//{{{ FactorList constructor
public FactorList(Object car, Object cdr)
//{{{ Cons constructor
public Cons(Object car, Object cdr)
{
this.car = car;
this.cdr = cdr;
@ -63,9 +61,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}}
//{{{ next() method
public FactorList next()
public Cons next()
{
return (FactorList)cdr;
return (Cons)cdr;
} //}}}
//{{{ get() method
@ -75,12 +73,12 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}}
//{{{ _get() method
public FactorList _get(int index)
public Cons _get(int index)
{
FactorList iter = this;
Cons iter = this;
while(index != 0)
{
iter = (FactorList)iter.cdr;
iter = (Cons)iter.cdr;
index--;
}
return iter;
@ -89,7 +87,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ contains() method
public boolean contains(Object obj)
{
FactorList iter = this;
Cons iter = this;
while(iter != null)
{
if(FactorLib.objectsEqual(obj,iter.car))
@ -99,100 +97,33 @@ public class FactorList implements PublicCloneable, FactorExternalizable
return false;
} //}}}
//{{{ set() method
/**
* Returns a new list where the item at the given index is changed.
*/
public FactorList set(int index, Object car, Object cdr)
//{{{ contains() method
public static boolean contains(Cons list, Object obj)
{
if(index == 0)
return new FactorList(car,cdr);
if(list == null)
return false;
else
{
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);
}
return list.contains(obj);
} //}}}
//{{{ length() method
public int length()
{
int size = 0;
FactorList iter = this;
Cons iter = this;
while(iter != null)
{
iter = (FactorList)iter.cdr;
iter = (Cons)iter.cdr;
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
public boolean isProperList()
{
return cdr == null || (cdr instanceof FactorList
&& ((FactorList)cdr).isProperList());
return cdr == null || (cdr instanceof Cons
&& ((Cons)cdr).isProperList());
} //}}}
//{{{ elementsToString() method
@ -203,17 +134,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
public String elementsToString()
{
StringBuffer buf = new StringBuffer();
FactorList iter = this;
Cons iter = this;
while(iter != null)
{
if(iter.car == this)
buf.append("<circular reference>");
else
buf.append(FactorJava.factorTypeToString(iter.car));
if(iter.cdr instanceof FactorList)
if(iter.cdr instanceof Cons)
{
buf.append(' ');
iter = (FactorList)iter.cdr;
iter = (Cons)iter.cdr;
continue;
}
else if(iter.cdr == null)
@ -238,19 +169,6 @@ public class FactorList implements PublicCloneable, FactorExternalizable
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
/**
* 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)
{
int i = 0;
FactorList iter = this;
Cons iter = this;
while(iter != null)
{
returnValue[i++] = iter.car;
@ -269,17 +187,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
} //}}}
//{{{ fromArray() method
public static FactorList fromArray(Object[] array)
public static Cons fromArray(Object[] array)
{
if(array == null || array.length == 0)
return null;
else
{
FactorList first = new FactorList(array[0],null);
FactorList last = first;
Cons first = new Cons(array[0],null);
Cons last = first;
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 = cons;
}
@ -290,9 +208,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ equals() method
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)
&& FactorLib.objectsEqual(cdr,l.cdr);
}
@ -312,10 +230,10 @@ public class FactorList implements PublicCloneable, FactorExternalizable
//{{{ clone() method
public Object clone()
{
if(cdr instanceof FactorList)
return new FactorList(car,((FactorList)cdr).clone());
if(cdr instanceof Cons)
return new Cons(car,((Cons)cdr).clone());
else
return new FactorList(car,cdr);
return new Cons(car,cdr);
} //}}}
//{{{ deepClone() method
@ -326,13 +244,13 @@ public class FactorList implements PublicCloneable, FactorExternalizable
ccar = ((PublicCloneable)car).clone();
else
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)
{
return new FactorList(ccar,null);
return new Cons(ccar,null);
}
else
{
@ -341,7 +259,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
ccdr = ((PublicCloneable)cdr).clone();
else
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
public FactorArrayStack(FactorList list)
public FactorArrayStack(Cons list)
{
if(list != null)
{
@ -126,12 +126,12 @@ public abstract class FactorArrayStack implements FactorExternalizable
} //}}}
//{{{ 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++)
{
FactorList cons = new FactorList(stack[i],null);
Cons cons = new Cons(stack[i],null);
if(first == null)
first = cons;
else

View File

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

View File

@ -60,6 +60,12 @@ public class FactorCallStack extends FactorArrayStack implements PublicCloneable
//{{{ clone() method
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;
import factor.compiler.*;
import java.lang.reflect.*;
import java.io.FileOutputStream;
import java.util.*;
import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/**
* : name ... ;
*/
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;
}
} //}}}
public void eval(FactorWord word, FactorInterpreter interp)
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws Exception
{
interp.call(word,definition);
}
} //}}}
//{{{ canCompile() method
boolean canCompile()
//{{{ getStackEffect() method
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 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.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
* Local 1 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
protected CompileResult compileEval(FactorInterpreter interp,
ClassWriter cw, String className, StackEffect effect,
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);
// Max stack and locals
mw.visitMaxs(1,1);
return true;
}
FactorList fdef = compilePass1(interp,definition);
if(fdef.car instanceof FactorReflectionForm
&& fdef.cdr == null)
else
{
return ((FactorReflectionForm)fdef.car).compile(
word,interp,cw,mw);
allocator.pop(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 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();
return allocator.compile(definition,mw,recursiveCheck);
} //}}}
//{{{ toString() method
public String toString()
{
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
public FactorDataStack(FactorList list)
public FactorDataStack(Cons list)
{
super(list);
} //}}}
@ -66,6 +66,12 @@ public class FactorDataStack extends FactorArrayStack implements PublicCloneable
//{{{ clone() method
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$
*
* Copyright (C) 2003 Slava Pestov.
* 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:
@ -29,23 +29,36 @@
package factor;
import factor.primitives.*;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class FactorDictionary
{
// these are defined here for use by the precompiler
FactorWord jconstructor;
public FactorWord last;
FactorWord datastackGet;
FactorWord datastackSet;
FactorWord clear;
FactorWord callstackGet;
FactorWord callstackSet;
FactorWord restack;
FactorWord unstack;
FactorWord unwind;
FactorWord jnew;
FactorWord jfield;
FactorWord jvarGet;
FactorWord jvarSet;
FactorWord jvarGetStatic;
FactorWord jvarSetStatic;
FactorWord jmethod;
FactorWord jinvoke;
FactorWord jinvokeStatic;
FactorWord get;
FactorWord set;
FactorWord define;
FactorWord call;
FactorWord bind;
FactorWord choice;
private Map intern;
@ -55,50 +68,65 @@ public class FactorDictionary
intern = new TreeMap();
// data stack primitives
intern("datastack$").def = new FactorPrimitive.P_datastackGet();
intern("datastack@").def = new FactorPrimitive.P_datastackSet();
intern("clear").def = new FactorPrimitive.P_clear();
datastackGet = intern("datastack$");
datastackGet.def = new DatastackGet(
datastackGet);
datastackSet = intern("datastack@");
datastackSet.def = new DatastackSet(
datastackSet);
clear = intern("clear");
clear.def = new Clear(clear);
// call stack primitives
intern("callstack$").def = new FactorPrimitive.P_callstackGet();
intern("callstack@").def = new FactorPrimitive.P_callstackSet();
intern("restack").def = new FactorPrimitive.P_restack();
intern("unstack").def = new FactorPrimitive.P_unstack();
intern("unwind").def = new FactorPrimitive.P_unwind();
callstackGet = intern("callstack$");
callstackGet.def = new CallstackGet(
callstackGet);
callstackSet = intern("callstack@");
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
jconstructor = intern("jconstructor");
jconstructor.def = new FactorPrimitive.P_jconstructor();
jfield = intern("jfield");
jfield.def = new FactorPrimitive.P_jfield();
jinvoke = intern("jinvoke");
jinvoke.def = new FactorPrimitive.P_jinvoke();
jinvokeStatic = intern("jinvokeStatic");
jinvokeStatic.def = new FactorPrimitive.P_jinvokeStatic();
jmethod = intern("jmethod");
jmethod.def = new FactorPrimitive.P_jmethod();
jinvoke.def = new JInvoke(jinvoke);
jinvokeStatic = intern("jinvoke-static");
jinvokeStatic.def = new JInvokeStatic(
jinvokeStatic);
jnew = intern("jnew");
jnew.def = new FactorPrimitive.P_jnew();
jnew.def = new JNew(jnew);
jvarGet = intern("jvar$");
jvarGet.def = new FactorPrimitive.P_jvarGet();
jvarGetStatic = intern("jvarStatic$");
jvarGetStatic.def = new FactorPrimitive.P_jvarGetStatic();
jvarGet.def = new JVarGet(jvarGet);
jvarGetStatic = intern("jvar-static$");
jvarGetStatic.def = new JVarGetStatic(
jvarGetStatic);
jvarSet = intern("jvar@");
jvarSet.def = new FactorPrimitive.P_jvarSet();
jvarSetStatic = intern("jvarStatic@");
jvarSetStatic.def = new FactorPrimitive.P_jvarSetStatic();
jvarSet.def = new JVarSet(jvarSet);
jvarSetStatic = intern("jvar-static@");
jvarSetStatic.def = new JVarSetStatic(
jvarSetStatic);
// namespaces
intern("$").def = new FactorPrimitive.P_get();
intern("@").def = new FactorPrimitive.P_set();
intern("s@").def = new FactorPrimitive.P_swap_set();
get = intern("$");
get.def = new Get(get);
set = intern("@");
set.def = new Set(set);
// definition
intern("define").def = new FactorPrimitive.P_define();
define = intern("define");
define.def = new Define(define);
// combinators
intern("call").def = new FactorPrimitive.P_call();
intern("bind").def = new FactorPrimitive.P_bind();
call = intern("call");
call.def = new Call(call);
bind = intern("bind");
bind.def = new Bind(bind);
choice = intern("?");
choice.def = new Choice(choice);
} //}}}
//{{{ intern() method
@ -114,17 +142,17 @@ public class FactorDictionary
} //}}}
//{{{ toWordList() method
public FactorList toWordList()
public Cons toWordList()
{
FactorList first = null;
FactorList last = null;
Cons first = null;
Cons last = null;
Iterator iter = intern.values().iterator();
while(iter.hasNext())
{
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)
first = cons;
else

View File

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

View File

@ -29,22 +29,24 @@
package factor;
import factor.compiler.LocalAllocator;
import java.lang.reflect.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.objectweb.asm.*;
/**
* A few methods for converting between Java types, and making reflection calls.
* Note that the compiler incorporates calls to some of these methods in
* generated bytecode.
*/
public class FactorJava
public class FactorJava implements Constants
{
public static final Class[] EMPTY_ARRAY = new Class[0];
//{{{ classNameToClassList() method
public static Class[] classNameToClassList(FactorList classes)
public static Class[] classNameToClassList(Cons classes)
throws Exception
{
if(classes == null)
@ -54,7 +56,31 @@ public class FactorJava
int i = 0;
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();
}
@ -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
public static Object[] toArray(Object arg)
throws FactorDomainException
@ -194,9 +243,9 @@ public class FactorJava
public static Object[] toArray(Object arg, Class clas)
throws FactorDomainException
{
if(arg instanceof FactorList)
if(arg instanceof Cons)
{
FactorList list = (FactorList)arg;
Cons list = (Cons)arg;
Object[] array = (Object[])
Array.newInstance(
clas.getComponentType(),
@ -205,7 +254,21 @@ public class FactorJava
return array;
}
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
throw new FactorDomainException(arg,Object[].class);
} //}}}
@ -296,7 +359,7 @@ public class FactorJava
else if(obj instanceof Character)
return "#\\" + ((Character)obj).charValue();
else
return "(" + obj + ")";
return "( " + obj + " )";
} //}}}
//{{{ javaClassToVMClass() method
@ -387,7 +450,7 @@ public class FactorJava
} //}}}
//{{{ jconstructor() method
public static Constructor jconstructor(String inClass, FactorList args)
public static Constructor jconstructor(String inClass, Cons args)
throws Exception
{
return Class.forName(inClass).getConstructor(
@ -458,7 +521,7 @@ public class FactorJava
//{{{ jmethod() method
public static Method jmethod(String method, String inClass,
FactorList args) throws Exception
Cons args) throws Exception
{
return Class.forName(inClass).getMethod(method,
classNameToClassList(args));
@ -519,4 +582,126 @@ public class FactorJava
else
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
{
//{{{ branch2() method
public static Object branch2(boolean condition, Object o1, Object o2)
{
return (condition ? o1 : o2);
} //}}}
//{{{ branch3() method
public static Object branch3(float x, float y,
Object o1, Object o2, Object o3)
@ -54,36 +48,6 @@ public class FactorLib
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
public static Object[] cloneArray(Object[] array)
{

View File

@ -3,7 +3,7 @@
/*
* $Id$
*
* Copyright (C) 2003 Slava Pestov.
* 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:
@ -282,6 +282,12 @@ public class FactorMath
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
public static int sgn(float num)
{

View File

@ -3,7 +3,7 @@
/*
* $Id$
*
* Copyright (C) 2003 Slava Pestov.
* 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:
@ -29,16 +29,22 @@
package factor;
import factor.compiler.*;
import java.util.Set;
/**
* A placeholder for an undefined word.
*/
public class FactorMissingDefinition extends FactorWordDefinition
{
public static final FactorMissingDefinition INSTANCE
= new FactorMissingDefinition();
//{{{ FactorMissingDefinition constructor
public FactorMissingDefinition(FactorWord word)
{
super(word);
} //}}}
//{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp)
public void eval(FactorInterpreter interp)
throws FactorUndefinedWordException
{
throw new FactorUndefinedWordException(word);

View File

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

View File

@ -108,10 +108,10 @@ public class FactorParser
* 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.
*/
public FactorList parse() throws IOException, FactorParseException
public Cons parse() throws IOException, FactorParseException
{
FactorList first = null;
FactorList last = null;
Cons first = null;
Cons last = null;
try
{
@ -131,12 +131,15 @@ public class FactorParser
error("Expected word name after " + next);
}
FactorWordDefinition def = readDef();
FactorWord word = (FactorWord)obj;
FactorList l = new FactorList(DEFINE,null);
FactorList cons = new FactorList(
((FactorWord)obj).name,
new FactorList(def,l));
FactorWordDefinition def
= readDef(word);
Cons l = new Cons(DEFINE,null);
Cons cons = new Cons(
word.name,
new Cons(def,l));
if(first == null)
first = cons;
else
@ -152,12 +155,15 @@ public class FactorParser
error("Expected word name after " + next);
}
FactorWordDefinition def = readShuffle();
FactorWord word = (FactorWord)obj;
FactorList l = new FactorList(DEFINE,null);
FactorList cons = new FactorList(
((FactorWord)obj).name,
new FactorList(def,l));
FactorWordDefinition def
= readShuffle(word);
Cons l = new Cons(DEFINE,null);
Cons cons = new Cons(
word.name,
new Cons(def,l));
if(first == null)
first = cons;
else
@ -166,7 +172,7 @@ public class FactorParser
}
else if(next == BRA)
{
FactorList cons = new FactorList(
Cons cons = new Cons(
readList(),null);
if(first == null)
first = cons;
@ -180,7 +186,7 @@ public class FactorParser
}
else
{
FactorList cons = new FactorList(next,null);
Cons cons = new Cons(next,null);
if(first == null)
first = cons;
else
@ -323,10 +329,10 @@ public class FactorParser
/**
* Read list until ;.
*/
private FactorWordDefinition readDef()
private FactorWordDefinition readDef(FactorWord word)
throws IOException, FactorParseException
{
return new FactorCompoundDefinition(readList(INE,false));
return new FactorCompoundDefinition(word,readList(INE,false));
} //}}}
//{{{ readShuffle() method
@ -336,7 +342,7 @@ public class FactorParser
* On the left is inputs, on the right is their arrangement on the
* stack.
*/
private FactorWordDefinition readShuffle()
private FactorWordDefinition readShuffle(FactorWord word)
throws IOException, FactorParseException
{
// 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();
if(_shuffle == null)
{
return new FactorShuffleDefinition(consumeD,consumeR,
return new FactorShuffleDefinition(word,
consumeD,consumeR,
null,0,null,0);
}
@ -397,12 +404,12 @@ public class FactorParser
{
if(_shuffle.car instanceof FactorWord)
{
FactorWord word = ((FactorWord)_shuffle.car);
String name = word.name;
FactorWord w = ((FactorWord)_shuffle.car);
String name = w.name;
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)
error("Does not appear in shuffle LHS: " + _shuffle.car);
int index = _index.intValue();
@ -445,7 +452,7 @@ public class FactorParser
shuffleD[k++] = index;
}
return new FactorShuffleDefinition(consumeD,consumeR,
return new FactorShuffleDefinition(word,consumeD,consumeR,
shuffleD,shuffleDlength,shuffleR,shuffleRlength);
} //}}}
@ -453,7 +460,7 @@ public class FactorParser
/**
* Read list until ].
*/
private FactorList readList()
private Cons readList()
throws IOException, FactorParseException
{
return readList(KET,true);
@ -463,11 +470,11 @@ public class FactorParser
/**
* Read list until a given word.
*/
private FactorList readList(FactorWord until, boolean allowCommaPair)
private Cons readList(FactorWord until, boolean allowCommaPair)
throws IOException, FactorParseException
{
FactorList first = null;
FactorList last = null;
Cons first = null;
Cons last = null;
for(;;)
{
@ -509,12 +516,12 @@ public class FactorParser
}
else if(next == BRA)
{
FactorList list = readList();
Cons list = readList();
if(first == null)
first = last = new FactorList(list,null);
first = last = new Cons(list,null);
else
{
FactorList nextList = new FactorList(list,null);
Cons nextList = new Cons(list,null);
last.cdr = nextList;
last = nextList;
}
@ -522,10 +529,10 @@ public class FactorParser
else if(isParsingWord(next))
error("Unexpected " + next);
else if(first == null)
first = last = new FactorList(next,null);
first = last = new Cons(next,null);
else
{
FactorList nextList = new FactorList(next,null);
Cons nextList = new Cons(next,null);
last.cdr = 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;
import factor.compiler.*;
import java.util.Set;
import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/**
* ~<< name ... -- >>~
@ -63,10 +66,13 @@ public class FactorShuffleDefinition extends FactorWordDefinition
private Object[] temporaryR;
//{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(int consumeD, int consumeR,
public FactorShuffleDefinition(FactorWord word,
int consumeD, int consumeR,
int[] shuffleD, int shuffleDlength,
int[] shuffleR, int shuffleRlength)
{
super(word);
this.consumeD = consumeD;
this.consumeR = consumeR;
this.shuffleD = shuffleD;
@ -102,295 +108,49 @@ public class FactorShuffleDefinition extends FactorWordDefinition
}
} //}}}
//{{{ canCompile() method
boolean canCompile()
//{{{ getStackEffect() method
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
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
* Compile the given word, returning a new word definition.
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
FactorWordDefinition compile(FactorInterpreter interp,
Set recursiveCheck) throws Exception
{
boolean fromD = false;
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;
}
}
return this;
} //}}}
// Local 3 -- datastack
// Local 4 -- datastack top-consumeD
// Local 5 -- datastack array
if(consumeD != 0 || fromD)
{
// (datastack datastack datastack)
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
mw.visitInsn(DUP);
if(consumeD != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// datastack -> 3
mw.visitVarInsn(ASTORE,3);
// datastack.top-consumeD -> 4
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeD != 0)
{
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,4);
// datastack.stack -> 5
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
}
// Local 6 -- callstack
// Local 7 -- callstack top-consumeR
// Local 8 -- callstack array
if(consumeR != 0 || fromR)
{
// (callstack callstack)
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "callstack",
"Lfactor/FactorCallStack;");
mw.visitInsn(DUP);
if(consumeR != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// callstack -> 6
mw.visitVarInsn(ASTORE,6);
// callstack.top-consumeR -> 7
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeR != 0)
{
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,7);
// callstack.stack -> 8
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
}
int locals = 9;
if(shuffleD != null)
{
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top-consumeD+shuffleD[i]] -> 9+i
int index = shuffleD[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,9 + i);
}
locals += shuffleDlength;
}
if(shuffleR != null)
{
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top-consumeR+shuffleR[i]] -> 9+i
int index = shuffleR[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,locals + i);
}
}
if(shuffleD != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,3);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the datastack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top - consumeD + i] <- 9+i
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,9 + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeD != 0)
{
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
if(shuffleR != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,6);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the callstack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top - consumeD + i] <- locals+i
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,locals + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitIntInsn(BIPUSH,shuffleRlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeR != 0)
{
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
mw.visitInsn(RETURN);
// Max stack and locals
mw.visitMaxs(4,9 + shuffleDlength + shuffleRlength);
return true;
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
Set recursiveCheck) throws FactorStackException
{
eval(allocator.datastack,allocator.callstack);
return 0;
} //}}}
//{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp)
public void eval(FactorInterpreter interp)
throws FactorStackException
{
FactorArrayStack datastack = interp.datastack;
FactorArrayStack callstack = interp.callstack;
eval(interp.datastack,interp.callstack);
} //}}}
//{{{ eval() method
public void eval(FactorArrayStack datastack, FactorArrayStack callstack)
throws FactorStackException
{
if(datastack.top < consumeD)
throw new FactorStackException(consumeD);
@ -398,10 +158,16 @@ public class FactorShuffleDefinition extends FactorWordDefinition
throw new FactorStackException(consumeR);
if(shuffleD != null)
shuffle(interp,datastack,consumeD,consumeR,shuffleD,temporaryD);
{
shuffle(datastack,callstack,datastack,consumeD,consumeR,
shuffleD,temporaryD);
}
if(shuffleR != null)
shuffle(interp,callstack,consumeD,consumeR,shuffleR,temporaryR);
{
shuffle(datastack,callstack,callstack,consumeD,consumeR,
shuffleR,temporaryR);
}
datastack.top -= consumeD;
if(temporaryD != null)
@ -414,8 +180,14 @@ public class FactorShuffleDefinition extends FactorWordDefinition
} //}}}
//{{{ shuffle() method
private void shuffle(FactorInterpreter interp, FactorArrayStack stack,
int consumeD, int consumeR, int[] shuffle, Object[] temporary)
private void shuffle(
FactorArrayStack datastack,
FactorArrayStack callstack,
FactorArrayStack stack,
int consumeD,
int consumeR,
int[] shuffle,
Object[] temporary)
throws FactorStackException
{
for(int i = 0; i < temporary.length; i++)
@ -426,15 +198,15 @@ public class FactorShuffleDefinition extends FactorWordDefinition
int consume;
if((index & FROM_R_MASK) == FROM_R_MASK)
{
array = interp.callstack.stack;
top = interp.callstack.top;
array = callstack.stack;
top = callstack.top;
index = (index & ~FROM_R_MASK);
consume = consumeR;
}
else
{
array = interp.datastack.stack;
top = interp.datastack.top;
array = datastack.stack;
top = datastack.top;
consume = consumeD;
}
temporary[i] = array[top - consume + index];

View File

@ -29,8 +29,8 @@
package factor;
import java.util.HashMap;
import java.util.Map;
import factor.compiler.FactorCompilerException;
import java.util.*;
/**
* An internalized symbol.
@ -44,10 +44,20 @@ public class FactorWord implements FactorExternalizable
*/
public FactorWordDefinition def;
/**
* Definition before compiling.
*/
public FactorWordDefinition uncompiled;
/**
* "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
/**
@ -58,7 +68,64 @@ public class FactorWord implements FactorExternalizable
public FactorWord(String 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

View File

@ -3,7 +3,7 @@
/*
* $Id$
*
* Copyright (C) 2003 Slava Pestov.
* 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:
@ -29,10 +29,10 @@
package factor;
import java.io.FileOutputStream;
import java.util.Iterator;
import factor.compiler.*;
import java.util.HashSet;
import java.util.Set;
import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/**
* A word definition.
@ -40,152 +40,89 @@ import org.objectweb.asm.util.*;
public abstract class FactorWordDefinition implements FactorObject, Constants
{
private FactorNamespace namespace;
protected FactorWord word;
/**
* Number of times this word has been referenced from a
* compound word (incremented by the precompiler).
*/
public int references;
public boolean compileFailed;
public abstract void eval(FactorWord word, FactorInterpreter interp)
public FactorWordDefinition(FactorWord word)
{
this.word = word;
}
public abstract void eval(FactorInterpreter interp)
throws Exception;
void precompile(FactorWord word, FactorInterpreter interp)
throws Exception {}
//{{{ getNamespace() method
public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception
{
if(namespace == null)
namespace = new FactorNamespace(interp.global,this);
return namespace;
}
//{{{ canCompile() method
boolean canCompile()
{
return false;
} //}}}
private static int compileCount;
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorWord word, FactorInterpreter interp)
throws Exception
//{{{ getStackEffect() method
public final StackEffect getStackEffect() throws Exception
{
if(!canCompile())
return this;
return getStackEffect(new HashSet(),new LocalAllocator());
} //}}}
//System.out.println("Compiling " + word);
StringBuffer sanitizedName = new StringBuffer();
for(int i = 0; i < word.name.length(); i++)
{
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;
//{{{ getStackEffect() method
public StackEffect getStackEffect(Set recursiveCheck,
LocalAllocator state) throws Exception
{
return null;
} //}}}
//{{{ compile() method
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
FactorWordDefinition compile(FactorInterpreter interp,
Set recursiveCheck) throws Exception
{
throw new FactorRuntimeException("Don't know how to compile " + word);
return this;
} //}}}
//{{{ SimpleClassLoader class
static class SimpleClassLoader extends ClassLoader
//{{{ compileCallTo() method
/**
* 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,
byte[] code, int off, int len)
StackEffect effect = getStackEffect();
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
!!! hundred lines of code!
~<< drop A -- >>~
~<< 2drop A B -- >>~
~<< dup A -- A A >>~
~<< 2dup A B -- A B A B >>~
~<< dupd A B -- A A B >>~
~<< 2dupd A B C D -- A B A B C D >>~
~<< nip A B -- B >>~
~<< 2nip A B C D -- C D >>~
~<< nop -- >>~ ! Does nothing!
~<< over A B -- A B A >>~
~<< 2over A B C D -- A B C D A B >>~
~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
~<< rot A B C -- B C A >>~
~<< 2rot A B C D E F -- C D E F A B >>~
~<< -rot A B C -- C A B >>~
~<< 2-rot A B C D E F -- E F A B C D >>~
~<< swap A B -- B A >>~
~<< 2swap A B C D -- C D A B >>~
~<< swapd A B C -- B A C >>~
~<< 2swapd A B C D E F -- C D A B E F >>~
~<< tuck A B -- B A B >>~
~<< 2tuck A B C D -- C D A B C D >>~
~<< drop A -- >>~
~<< 2drop A B -- >>~
~<< dup A -- A A >>~
~<< 2dup A B -- A B A B >>~
~<< dupd A B -- A A B >>~
~<< 2dupd A B C D -- A B A B C D >>~
~<< nip A B -- B >>~
~<< 2nip A B C D -- C D >>~
~<< nop -- >>~ ! Does nothing!
~<< over A B -- A B A >>~
~<< 2over A B C D -- A B C D A B >>~
~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
~<< rot A B C -- B C A >>~
~<< 2rot A B C D E F -- C D E F A B >>~
~<< -rot A B C -- C A B >>~
~<< 2-rot A B C D E F -- E F A B C D >>~
~<< swap A B -- B A >>~
~<< 2swap A B C D -- C D A B >>~
~<< swapd A B C -- B A C >>~
~<< 2swapd A B C D E F -- C D A B E F >>~
~<< transp A B C -- C B A >>~
~<< 2transp A B C D E F -- E F C D A B >>~
~<< tuck A B -- B A B >>~
~<< 2tuck A B C D -- C D A B C D >>~
~<< rdrop r:A -- >>~
~<< >r A -- r:A >>~
@ -60,21 +62,21 @@
!!! 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.
: <breader> (reader -- breader)
[ |java.io.Reader ] |java.io.BufferedReader jconstructor jnew ;
[ |java.io.Reader ] |java.io.BufferedReader jnew ;
: <ireader> (inputstream -- breader)
[ |java.io.InputStream ] |java.io.InputStreamReader jconstructor jnew ;
[ |java.io.InputStream ] |java.io.InputStreamReader jnew ;
: <rreader> (path -- inputstream)
|factor.FactorInterpreter
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jmethod jinvoke
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jinvoke
<ireader> <breader> ;
: parse* (filename reader -- list)
$dict
[ |java.lang.String |java.io.Reader |factor.FactorDictionary ]
|factor.FactorParser jconstructor jnew
[ ] |factor.FactorParser |parse jmethod jinvoke ;
|factor.FactorParser jnew
[ ] |factor.FactorParser |parse jinvoke ;
: runResource (path --)
dup <rreader> parse* call ;
@ -98,5 +100,20 @@
"/factor/stream.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.
$interactive [ initialInterpreterLoop ] when

View File

@ -90,18 +90,20 @@
! [ [ condition 1 ] [ code 1 ]
! [ condition 2 ] [ code 2 ]
! ... ]
! Each condition is evaluated in turn. If it returns true, the code
! is evaluated. If it returns false, the next condition is checked.
[
uncons >r
call
r>
swap [
! Each condition is evaluated in turn. If it returns true,
! the code is evaluated. If it returns false, the next
! condition is checked. Before evaluating each condition,
! the top of the stack is duplicated. After the last
! condition is evaluated, the top of the stack is popped.
dup [
uncons [ over [ call ] dip ] dip rot [
car call
] [
cdr cond
] ifte
] when* ;
] [
2drop
] ifte ;
: dip (a [ b ] -- b a)
! Calls b as if b was not even present on the stack -- b has no way of
@ -122,14 +124,7 @@
: each ([ list ] [ code ] --)
! Applies the code to each element of the list.
over [
>r
uncons
r>
tuck
2>r
call
2r>
each
[ uncons ] dip tuck [ call ] 2dip each
] [
2drop
] ifte ;
@ -143,6 +138,9 @@
call
unstack ;
: ifte (cond [if true] [if false] --)
? call ;
: interleave ( X list -- ... )
! Evaluate each element of the list with X on top of the
! stack.
@ -152,9 +150,6 @@
2drop
] ifte ;
: ifte (cond [if true] [if false] --)
? call ;
: linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- )
! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse,
! and evaluate R2. This combinator is similar to the linrec combinator in
@ -168,13 +163,10 @@
r> call
] ifte ;
: map ([ items ] [ initial ] [ code ] -- [ mapping ])
! Applies the code to each item, returns a list that begins with the initial
! list and contains the result of each application.
swapd 2list append
restack
each
unstack ;
: map ( [ items ] [ code ] -- [ mapping ] )
! Applies the code to each item, returns a list that
! contains the result of each application.
2list restack each unstack ;
: push ([ a b c ... ] -- a b c ...)
! 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
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! Undefined words's def field is equal to this.
"factor.FactorMissingDefinition" "INSTANCE" jfield jvarStatic$ @undefinedWord
: asm. (word -- assembly)
: asm ( word -- assembly )
! Prints JVM bytecode disassembly of the given word.
worddef [ $asm ] bind dup [
worddef compiled? dup [
print
] [
drop "Not a compiled word." print
] ifte ;
: word? (obj -- boolean)
"factor.FactorWord" is ;
: compile* ( word -- )
$interpreter swap
[ "factor.FactorInterpreter" ] "factor.FactorWord" "compile"
jinvoke ;
: str>word ("word" -- word)
! Returns the top of the stack if it already been interned.
dup word? [
$dict [ "java.lang.String" ] "factor.FactorDictionary" "intern"
jmethod jinvoke
] unless ;
: compile ( word -- )
dup worddef compiled? [
drop
] [
intern compile*
] ifte ;
: worddef? (obj -- boolean)
"factor.FactorWordDefinition" is ;
: compileAll ( -- )
"Compiling..." write
words [ compile ] each
" done" print ;
: compiled? ( obj -- boolean )
[ $asm ] bind ;
: compound? (obj -- boolean)
"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)
"factor.FactorShuffleDefinition" is ;
: worddef (word -- worddef)
str>word
! Get the 'def' field
"factor.FactorWord" "def" jfield jvar$
! Is it equal to the missing word placeholder? Then push f.
dup $undefinedWord = [ drop f ] when ;
: intern ("word" -- word)
! Returns the top of the stack if it already been interned.
dup word? [
$dict [ "java.lang.String" ]
"factor.FactorDictionary" "intern"
jinvoke
] unless ;
: undefined? ( obj -- boolean )
"factor.FactorMissingDefinition" is ;
: word? (obj -- boolean)
"factor.FactorWord" is ;
: word ( -- word )
! Pushes most recently defined word.
$dict "factor.FactorDictionary" "last" jvar$ ;
: worddef? (obj -- boolean)
"factor.FactorWordDefinition" is ;
: worddef ( word -- worddef )
intern
"factor.FactorWord" "def" jvar$
missing>f ;
: worddefUncompiled ( word -- worddef )
intern
"factor.FactorWord" "uncompiled" jvar$
missing>f ;
: words (-- list)
! 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
: httpdGetPath ( request -- file )
dup ".*\\.\\.*" matches [
dup ".*\\.\\.*" re-matches [
f
] [
dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when
@ -58,12 +58,12 @@
: httpdFiletype (filename -- mime-type)
[
[ dup ".*\.gif" matches ] [ drop "image/gif" ]
[ dup ".*\.png" matches ] [ drop "image/png" ]
[ dup ".*\.html" matches ] [ drop "text/html" ]
[ dup ".*\.txt" matches ] [ drop "text/plain" ]
[ dup ".*\.lsd" matches ] [ drop "text/plain" ]
[ t ] [ drop "application/octet-stream" ]
[ ".*\.gif" re-matches ] [ drop "image/gif" ]
[ ".*\.png" re-matches ] [ drop "image/png" ]
[ ".*\.html" re-matches ] [ drop "text/html" ]
[ ".*\.txt" re-matches ] [ drop "text/plain" ]
[ ".*\.lsd" re-matches ] [ drop "text/plain" ]
[ t ] [ drop "application/octet-stream" ]
] cond ;
: httpdUriToPath (uri -- path)
@ -123,7 +123,7 @@
dup directory? [
httpdServeDirectory
] [
dup ".*\.lhtml" matches [
dup ".*\.lhtml" re-matches [
httpdServeScript
] [
httpdServeFile

View File

@ -29,13 +29,13 @@
"java.lang.Throwable" is ;
: printStackTrace (exception --)
[ ] "java.lang.Throwable" "printStackTrace" jmethod jinvoke ;
[ ] "java.lang.Throwable" "printStackTrace" jinvoke ;
: exception. (exception --)
! If this is an Factor exception, just print the message, otherwise print
! the entire exception as a string.
dup "factor.FactorException" is [
[ ] "java.lang.Throwable" "getMessage" jmethod jinvoke
[ ] "java.lang.Throwable" "getMessage" jinvoke
] [
>str
] ifte print ;
@ -53,6 +53,7 @@
":g continues execution (but expect another error)." print
"" print
"ERROR: " write exception.
:w
callstack$ @errorCallStack
[
@errorContinuation
@ -131,9 +132,11 @@
words [ . ] each ;
: see (word --)
dup worddef [
dup worddefUncompiled [
(word -- worddef word)
dup [ worddef dup shuffle? "~<< " ": " ? write ] dip
dup [
worddefUncompiled dup shuffle? "~<< " ": " ? write
] dip
(worddef word -- worddef)
write "\n " write
@ -153,6 +156,22 @@
! Prints the contents of the data stack
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
"" print
"= Dynamic, interpreted, stack-based scripting language" print

View File

@ -2,7 +2,7 @@
! $Id$
!
! Copyright (C) 2003 Slava Pestov.
! 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:
@ -31,8 +31,8 @@
: 2rlist (a b -- [ b a ])
swap unit cons ;
: append ([ list1 ] [ list2 ] -- [ list1 list2 ])
swap rappend ;
: append ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
over [ [ uncons ] dip append cons ] [ nip ] ifte ;
: add ([ list1 ] elem -- [ list1 elem ])
unit append ;
@ -42,7 +42,8 @@
dup [ $ swap append ] dip @ ;
: array>list ( array -- list )
[ "[Ljava.lang.Object;" ] "factor.FactorList" "fromArray" jmethod jinvokeStatic ;
[ [ "java.lang.Object" ] ] "factor.Cons" "fromArray"
jinvoke-static ;
: add@ (elem variable --)
! Adds the element to the end of the list stored in the given variable.
@ -63,10 +64,10 @@
] ifte ;
: car ([ car , cdr ] -- car)
|factor.FactorList |car jfield jvar$ ;
|factor.Cons |car jvar$ ;
: cdr ([ car , cdr ] -- cdr)
|factor.FactorList |cdr jfield jvar$ ;
|factor.Cons |cdr jvar$ ;
: caar (list -- caar)
car car ;
@ -83,10 +84,10 @@
: cloneList (list -- list)
! Returns a new list where each element is a clone of the elements of
! the given list.
dup [ [ ] "factor.FactorList" "deepClone" jmethod jinvoke ] when ;
dup [ [ ] "factor.Cons" "deepClone" jinvoke ] when ;
: 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)
dup [
@ -113,9 +114,13 @@
: get (list n -- list[n])
[ 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.
[ dup cdr ] [ cdr ] while car ;
last* car ;
: length (list -- length)
0 swap [ drop succ ] each ;
@ -126,18 +131,27 @@
: list? (list -- boolean)
dup pair? [ cdr list? ] [ f ] ifte ;
: pair? (list -- boolean)
|factor.FactorList is ;
: nappend ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
! Destructive on list1!
over [ last* rplacd ] when* ;
: rappend ([ list2 ] [ list1 ] -- [ list1 list2 ])
[ [ |factor.FactorList ] |factor.FactorList |append jmethod jinvoke ] when* ;
: pair? (list -- boolean)
|factor.Cons is ;
: reverse (list -- list)
[ ] 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 ])
swap [ |java.lang.Object |java.lang.Object ]
|factor.FactorList jconstructor jnew ;
|factor.Cons jnew ;
: uncons ([ car , cdr ] -- car cdr)
dup car swap cdr ;

View File

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

View File

@ -25,30 +25,28 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 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)
! Returns true if a = b.
[ "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "equal" jmethod jinvokeStatic ;
"factor.FactorLib" "equal" jinvoke-static ;
: clone (obj -- obj)
[ ] "factor.PublicCloneable" "clone" jmethod jinvoke ;
[ ] "factor.PublicCloneable" "clone" jinvoke ;
: cloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "cloneArray"
jmethod jinvokeStatic ;
[ [ "java.lang.Object" ] ]
"factor.FactorLib" "cloneArray"
jinvoke-static ;
: deepCloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "deepCloneArray"
jmethod jinvokeStatic ;
[ [ "java.lang.Object" ] ]
"factor.FactorLib" "deepCloneArray"
jinvoke-static ;
: is (obj class -- boolean)
! Like "instanceof" in Java.
[ "java.lang.Object" ] "java.lang.Class" "isInstance"
jmethod jinvoke ;
jinvoke ;
: not= (a b -- boolean)
= not ;
@ -57,36 +55,31 @@
! Returns true if a = c, b = d.
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)
! If x > y, pushes obj1, if x = y, pushes obj2, else obj3.
[
"float" "float"
"java.lang.Object" "java.lang.Object" "java.lang.Object"
]
"factor.FactorLib" "branch3" jmethod jinvokeStatic ;
"factor.FactorLib" "branch3" jinvoke-static ;
: error (msg --)
[ "java.lang.String" ] "factor.FactorLib" "error" jmethod jinvokeStatic ;
[ "java.lang.String" ] "factor.FactorLib" "error" jinvoke-static ;
: exit* (code --)
[ |int ] |java.lang.System |exit jmethod jinvokeStatic ;
[ |int ] |java.lang.System |exit jinvoke-static ;
: exit (--)
0 exit* ;
: millis (-- millis)
! Pushes the current time, in milliseconds.
[ ] |java.lang.System |currentTimeMillis jmethod jinvokeStatic
[ ] |java.lang.System |currentTimeMillis jinvoke-static
>bignum ;
: stack>list (stack -- list)
! Turns a callstack or datastack object into a list.
[ ] "factor.FactorArrayStack" "toList" jmethod jinvoke ;
[ ] "factor.FactorArrayStack" "toList" jinvoke ;
: time (code --)
! 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
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: s@ ( variable value -- )
swap @ ;
: lazy (var [ a ] -- value)
! If the value of the variable is f, set the value to the result of
! evaluating [ a ].
@ -35,12 +38,12 @@
: <namespace> (-- namespace)
$namespace [ |factor.FactorNamespace ] |factor.FactorNamespace
jconstructor jnew ;
jnew ;
: <objnamespace> ( object -- namespace )
$namespace swap
[ "factor.FactorNamespace" "java.lang.Object" ]
"factor.FactorNamespace" jconstructor jnew ;
"factor.FactorNamespace" jnew ;
: extend (object code -- object)
! Used in code like this:
@ -52,12 +55,12 @@
: import (class pairs --)
! 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
jmethod jinvoke ;
jinvoke ;
: vars (-- list)
$namespace [ ] |factor.FactorNamespace |toVarList jmethod jinvoke ;
$namespace [ ] |factor.FactorNamespace |toVarList jinvoke ;
: uvar? (name --)
[ "namespace" "parent" ] contains not ;

View File

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

View File

@ -36,7 +36,7 @@
: unparse (X -- "X")
[ |java.lang.Object ] |factor.FactorJava |factorTypeToString
jmethod jinvokeStatic ;
jinvoke-static ;
: . (expr --)
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$
!
! Copyright (C) 2003 Slava Pestov.
! 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:
@ -25,64 +25,76 @@
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
: randomAngle (-- theta)
[ ] "factor.FactorMath" "randomAngle" jmethod jinvokeStatic ;
: random-angle ( -- theta )
[ ] "factor.FactorMath"
"randomAngle" jinvoke-static ;
: randomBoolean (-- boolean)
[ ] "factor.FactorMath" "randomBoolean" jmethod jinvokeStatic ;
: random-boolean ( -- boolean )
[ ] "factor.FactorMath"
"randomBoolean" jinvoke-static ;
: randomInt (min max -- random)
[ "int" "int" ] "factor.FactorMath" "randomInt" jmethod jinvokeStatic ;
: random-digit ( -- digit )
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.
dup neg swap randomInt ;
dup neg swap random-int ;
: chance (n -- boolean)
! Returns true with a 1/n probability, false with a (n-1)/n probability.
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%
: chance ( n -- boolean )
! Returns true with a 1/n probability, false with a (n-1)/n
! 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.
0 swap [ car + ] each ;
: randomProbability (list -- sum)
! Adds the car of each element of the given list, and returns a random
! number between 1 and this sum.
1 swap car+ randomInt ;
: random-probability ( list -- sum )
! Adds the car of each element of the given list, and
! returns a random number between 1 and this sum.
1 swap car+ random-int ;
: randomElementIter (list index -- elem)
! Used by randomElement*. Do not call directly.
: random-element-iter ( list index -- elem )
! Used by random-element*. Do not call directly.
[ unswons unswons ] dip (list elem probability index)
-- (list elem index)
swap - (list elem index)
dup 0 <= [
drop nip
] [
nip randomElementIter
nip random-element-iter
] ifte ;
: randomElement* (list -- elem)
! Returns a random element of the given list of comma pairs. The
! car of each pair is a probability, the cdr is the item itself.
! Only the cdr of the comma pair is returned.
dup 1 swap car+ randomInt randomElementIter ;
: random-element* ( list -- elem )
! Returns a random element of the given list of comma pairs.
! The car of each pair is a probability, the cdr is the item
! itself. Only the cdr of the comma pair is returned.
dup 1 swap car+ random-int random-element-iter ;
: randomSubset* (list -- list)
! Returns a random subset of the given list of comma pairs. The
! car of each pair is a probability, the cdr is the item itself.
! Only the cdr of the comma pair is returned.
: random-subset* ( list -- list )
! Returns a random subset of the given list of comma pairs.
! The car of each pair is a probability, the cdr is the item
! itself. Only the cdr of the comma pair is returned.
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)
-rot ([ ] probabilitySum elemd probability elema)
> ([ ] probabilitySum elemd boolean)

View File

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

View File

@ -2,7 +2,7 @@
! $Id$
!
! Copyright (C) 2003 Slava Pestov.
! 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:
@ -35,103 +35,186 @@
! [ #\" , "&quot;" ]
] @entities
: >str ( obj -- string )
! Returns the Java string representation of this object.
[ ] "java.lang.Object" "toString" jinvoke ;
: >bytes ( string -- array )
! Converts a string to an array of ASCII bytes. An exception is thrown
! if the string contains non-ASCII characters.
! Converts a string to an array of ASCII bytes. An exception
! is thrown if the string contains non-ASCII characters.
"ASCII" swap
[ "java.lang.String" ] "java.lang.String" "getBytes" jmethod jinvoke ;
[ "java.lang.String" ] "java.lang.String" "getBytes"
jinvoke ;
: cat ([ "a" "b" "c" ] -- "abc")
[ "factor.FactorList" ] "factor.FactorLib" "cat" jmethod jinvokeStatic ;
: <sbuf> ( -- StringBuffer )
[ ] "java.lang.StringBuffer" jnew ;
: cat2 ("a" "b" -- "ab")
[ "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "cat2" jmethod jinvokeStatic ;
: sbuf-append ( str buf -- buf )
[ "java.lang.String" ] "java.lang.StringBuffer" "append"
jinvoke ;
: cat3 ("a" "b" "c" -- "abc")
[ "java.lang.Object" "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "cat3" jmethod jinvokeStatic ;
: cat ( [ "a" "b" "c" ] -- "abc" )
! If f appears in the list, it is not appended to the
! string.
<sbuf> swap [ [ swap sbuf-append ] when* ] each >str ;
: cat4 ("a" "b" "c" "d" -- "abcd")
cat2 cat3 ;
: cat2 ( "a" "b" -- "ab" )
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.
"" [ 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"
jmethod jinvoke ;
jinvoke ;
: groupCount (matcher -- count)
: group-count ( matcher -- count )
[ ] "java.util.regex.Matcher" "groupCount"
jmethod jinvoke ;
jinvoke ;
: groups* (matcher -- list)
: groups* ( matcher -- list )
[
[
dup groupCount [
dup group-count [
succ over group swap
] times* drop
] cons expand
] [matches] ;
] [re-matches] ;
: groups (input regex -- list)
: groups ( input regex -- list )
<regex> <matcher> groups* ;
: [matches] ( matcher code -- boolean )
! If the matcher's matches* function returns true,
: index-of* ( index string substring -- index )
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
! stack. Otherwise, pop the matcher off the stack and
! 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.util.regex.Pattern" "matcher"
jmethod jinvoke ;
jinvoke ;
: matches* (matcher -- boolean)
: re-matches* ( matcher -- boolean )
[ ] "java.util.regex.Matcher" "matches"
jmethod jinvoke ;
jinvoke ;
: matches (input regex -- boolean)
<regex> <matcher> matches* ;
: re-matches ( input regex -- boolean )
<regex> <matcher> re-matches* ;
: replace* ( replace matcher -- string )
: re-replace* ( replace matcher -- string )
[ "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
! 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)
! Compile the regex, if its not already compiled.
dup "java.util.regex.Pattern" is not [
[ "java.lang.String" ] "java.util.regex.Pattern" "compile"
jmethod jinvokeStatic
[ "java.lang.String" ]
"java.util.regex.Pattern" "compile"
jinvoke-static
] when ;
: strget (index str -- char)
[ "int" ] "java.lang.String" "charAt" jmethod jinvoke ;
: split ( string split -- list )
2dup index-of dup -1 = [
2drop unit
] [
swap [ str// ] dip split cons
] ifte ;
: strlen (str -- length)
[ ] "java.lang.String" "length" jmethod jinvoke ;
: str/ ( str index -- str str )
! Returns 2 strings, that when concatenated yield the
! original string.
2dup strtail [ str-head ] dip ;
: streach (str [ code ] --)
! Execute the code, with each character of the string pushed onto the
! stack.
over strlen [
-rot 2dup [ [ strget ] dip call ] 2dip
: str// ( str index -- str str )
! Returns 2 strings, that when concatenated yield the
! original string, without the character at the given
! index.
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 ;
: strmap (str initial [ code ] -- [ mapping ])
! If the 'initial' parameter is f, turn it into "".
! Maybe cat should handle this instead?
[ dup [ drop "" ] unless ] dip
swapd [ ] cons cons cons
restack
streach
unstack cat ;
: str-expand ( [ code ] -- str )
expand cat ;
: str-get (index str -- char)
[ "int" ] "java.lang.String" "charAt" jinvoke ;
: str-head ( str index -- str )
! 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