release
import-0.36
parent
059c70d1d7
commit
79a60d07cc
113
.cvskeywords
113
.cvskeywords
|
@ -1,45 +1,68 @@
|
||||||
./factor/random.factor:! $Id: random.factor,v 1.3 2004/01/09 01:51:30 slava Exp $
|
./factor/compiler/StackEffect.java: * $Id: StackEffect.java,v 1.6 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/compiler/LocalAllocator.java: * $Id: LocalAllocator.java,v 1.9 2004/02/17 20:36:09 slava Exp $
|
||||||
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.12 2004/01/06 06:59:38 slava Exp $
|
./factor/compiler/FactorCompilerException.java: * $Id: FactorCompilerException.java,v 1.1 2004/01/27 19:55:40 slava Exp $
|
||||||
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.12 2004/01/14 01:58:37 slava Exp $
|
./factor/compiler/CompiledDefinition.java:* $Id: CompiledDefinition.java,v 1.4 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/combinators.factor:! $Id: combinators.factor,v 1.17 2004/01/11 23:00:34 slava Exp $
|
./factor/random.factor:! $Id: random.factor,v 1.6 2004/02/18 00:48:47 slava Exp $
|
||||||
./factor/FactorDataStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
|
./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/continuations.factor:! $Id: continuations.factor,v 1.8 2003/12/20 05:31:01 slava Exp $
|
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.7 2004/02/15 05:44:54 slava Exp $
|
||||||
./factor/network.factor:! $Id: io.factor,v 1.2 2003/12/20 05:31:01 slava Exp $
|
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.8 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.10 2004/01/03 20:58:09 slava Exp $
|
./factor/combinators.factor:! $Id: combinators.factor,v 1.4 2004/02/13 23:19:43 slava Exp $
|
||||||
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/FactorDataStack.java: * $Id: FactorDataStack.java,v 1.3 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2003/12/16 08:03:08 slava Exp $
|
./factor/continuations.factor:! $Id: continuations.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
|
./factor/network.factor:! $Id: network.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
|
||||||
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.4 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2003/12/09 09:52:26 slava Exp $
|
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/lists.factor:! $Id: lists.factor,v 1.10 2004/01/06 06:59:38 slava Exp $
|
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2003/12/26 00:36:30 slava Exp $
|
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.2 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.1 2004/01/15 03:00:18 slava Exp $
|
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorPrimitive.java: * $Id: FactorPrimitive.java,v 1.5 2004/01/11 23:00:34 slava Exp $
|
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorList.java: * $Id: FactorList.java,v 1.9 2004/01/03 20:58:09 slava Exp $
|
./factor/lists.factor:! $Id: lists.factor,v 1.7 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.10 2004/01/08 04:14:14 slava Exp $
|
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2004/02/05 04:47:05 slava Exp $
|
||||||
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.3 2004/02/13 23:19:43 slava Exp $
|
||||||
./factor/examples.factor:! $Id: examples.factor,v 1.4 2004/01/12 02:07:31 slava Exp $
|
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.4 2004/02/05 04:47:05 slava Exp $
|
||||||
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.2 2004/01/14 01:58:37 slava Exp $
|
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.5 2003/12/19 21:40:00 slava Exp $
|
./factor/examples.factor:! $Id: examples.factor,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.13 2004/01/10 23:24:30 slava Exp $
|
./factor/Cons.java: * $Id: Cons.java,v 1.4 2004/02/11 03:49:45 slava Exp $
|
||||||
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.7 2003/12/26 00:36:30 slava Exp $
|
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.9 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/parser.factor:! $Id: parser.factor,v 1.2 2003/12/20 04:30:06 slava Exp $
|
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorMissingDefinition.java: * $Id: FactorWordDefinition.java,v 1.10 2003/12/18 00:01:39 slava Exp $
|
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.3 2004/01/26 03:16:54 slava Exp $
|
||||||
./factor/stream.factor:! $Id: stream.factor,v 1.1 2004/01/03 20:58:09 slava Exp $
|
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.3 2004/02/17 20:36:09 slava Exp $
|
||||||
./factor/FactorReflectionForm.java:* $Id: FactorReflectionForm.java,v 1.1 2004/01/14 01:58:37 slava Exp $
|
./factor/parser.factor:! $Id: parser.factor,v 1.2 2004/02/10 05:43:37 slava Exp $
|
||||||
./factor/strings.factor:! $Id: strings.factor,v 1.4 2004/01/06 06:59:38 slava Exp $
|
./factor/FactorMissingDefinition.java: * $Id: FactorMissingDefinition.java,v 1.7 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.32 2004/01/12 02:07:31 slava Exp $
|
./factor/stream.factor:! $Id: stream.factor,v 1.3 2004/02/10 05:43:37 slava Exp $
|
||||||
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/strings.factor:! $Id: strings.factor,v 1.9 2004/02/18 00:48:47 slava Exp $
|
||||||
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.10 2004/01/08 04:14:14 slava Exp $
|
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.6 2004/02/17 20:36:09 slava Exp $
|
||||||
./factor/math.factor:! $Id: math.factor,v 1.11 2004/01/11 23:00:34 slava Exp $
|
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.17 2004/01/14 01:58:37 slava Exp $
|
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.7 2004/02/15 05:44:54 slava Exp $
|
||||||
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.14 2004/01/11 23:00:34 slava Exp $
|
./factor/math.factor:! $Id: math.factor,v 1.5 2004/02/17 20:36:09 slava Exp $
|
||||||
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2003/12/21 05:29:46 slava Exp $
|
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.14 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.3 2003/12/20 05:31:01 slava Exp $
|
./factor/primitives/CallstackSet.java: * $Id: CallstackSet.java,v 1.2 2004/02/15 22:24:19 slava Exp $
|
||||||
./factor/boot.factor:! $Id: boot.factor,v 1.12 2004/01/12 02:07:31 slava Exp $
|
./factor/primitives/JInvokeStatic.java: * $Id: JInvokeStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/primitives/Unwind.java: * $Id: Unwind.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/01/05 05:03:36 slava Exp $
|
./factor/primitives/JVarGetStatic.java: * $Id: JVarGetStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
./factor/FactorException.java: * $Id: FactorException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
|
./factor/primitives/Unstack.java: * $Id: Unstack.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.5 2004/01/14 01:58:37 slava Exp $
|
./factor/primitives/JInvoke.java: * $Id: JInvoke.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.6 2004/01/12 02:07:31 slava Exp $
|
./factor/primitives/Get.java: * $Id: Get.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Define.java: * $Id: Define.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Clear.java: * $Id: Clear.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Bind.java: * $Id: Bind.java,v 1.3 2004/02/17 20:36:09 slava Exp $
|
||||||
|
./factor/primitives/Choice.java: * $Id: Choice.java,v 1.3 2004/02/17 03:49:46 slava Exp $
|
||||||
|
./factor/primitives/JNew.java: * $Id: JNew.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Call.java: * $Id: Call.java,v 1.2 2004/02/15 22:24:19 slava Exp $
|
||||||
|
./factor/primitives/CallstackGet.java: * $Id: CallstackGet.java,v 1.2 2004/02/15 22:24:19 slava Exp $
|
||||||
|
./factor/primitives/DatastackGet.java: * $Id: DatastackGet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/JVarSet.java: * $Id: JVarSet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Set.java: * $Id: Set.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/Restack.java: * $Id: Restack.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/DatastackSet.java: * $Id: DatastackSet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/JVarSetStatic.java: * $Id: JVarSetStatic.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/primitives/JVarGet.java: * $Id: JVarGet.java,v 1.2 2004/02/15 22:24:20 slava Exp $
|
||||||
|
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.6 2004/02/10 05:43:37 slava Exp $
|
||||||
|
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2004/02/15 22:24:19 slava Exp $
|
||||||
|
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.2 2004/01/26 03:16:54 slava Exp $
|
||||||
|
./factor/boot.factor:! $Id: boot.factor,v 1.5 2004/02/18 00:48:47 slava Exp $
|
||||||
|
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
|
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/02/10 05:43:37 slava Exp $
|
||||||
|
./factor/FactorException.java: * $Id: FactorException.java,v 1.1 2004/01/25 19:55:39 slava Exp $
|
||||||
|
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.12 2004/02/15 22:24:19 slava Exp $
|
||||||
|
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.8 2004/02/10 05:43:37 slava Exp $
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/*
|
/*
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Slava Pestov.
|
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -29,20 +29,18 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
/**
|
/**
|
||||||
* Used to build up linked lists.
|
* Used to build up linked lists.
|
||||||
*/
|
*/
|
||||||
public class FactorList implements PublicCloneable, FactorExternalizable
|
public class Cons implements PublicCloneable, FactorExternalizable
|
||||||
{
|
{
|
||||||
public static int COUNT;
|
public static int COUNT;
|
||||||
|
|
||||||
public Object car;
|
public Object car;
|
||||||
public Object cdr;
|
public Object cdr;
|
||||||
|
|
||||||
//{{{ FactorList constructor
|
//{{{ Cons constructor
|
||||||
public FactorList(Object car, Object cdr)
|
public Cons(Object car, Object cdr)
|
||||||
{
|
{
|
||||||
this.car = car;
|
this.car = car;
|
||||||
this.cdr = cdr;
|
this.cdr = cdr;
|
||||||
|
@ -63,9 +61,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ next() method
|
//{{{ next() method
|
||||||
public FactorList next()
|
public Cons next()
|
||||||
{
|
{
|
||||||
return (FactorList)cdr;
|
return (Cons)cdr;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ get() method
|
//{{{ get() method
|
||||||
|
@ -75,12 +73,12 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ _get() method
|
//{{{ _get() method
|
||||||
public FactorList _get(int index)
|
public Cons _get(int index)
|
||||||
{
|
{
|
||||||
FactorList iter = this;
|
Cons iter = this;
|
||||||
while(index != 0)
|
while(index != 0)
|
||||||
{
|
{
|
||||||
iter = (FactorList)iter.cdr;
|
iter = (Cons)iter.cdr;
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
return iter;
|
return iter;
|
||||||
|
@ -89,7 +87,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
//{{{ contains() method
|
//{{{ contains() method
|
||||||
public boolean contains(Object obj)
|
public boolean contains(Object obj)
|
||||||
{
|
{
|
||||||
FactorList iter = this;
|
Cons iter = this;
|
||||||
while(iter != null)
|
while(iter != null)
|
||||||
{
|
{
|
||||||
if(FactorLib.objectsEqual(obj,iter.car))
|
if(FactorLib.objectsEqual(obj,iter.car))
|
||||||
|
@ -99,100 +97,33 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
return false;
|
return false;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ set() method
|
//{{{ contains() method
|
||||||
/**
|
public static boolean contains(Cons list, Object obj)
|
||||||
* Returns a new list where the item at the given index is changed.
|
|
||||||
*/
|
|
||||||
public FactorList set(int index, Object car, Object cdr)
|
|
||||||
{
|
{
|
||||||
if(index == 0)
|
if(list == null)
|
||||||
return new FactorList(car,cdr);
|
return false;
|
||||||
else
|
else
|
||||||
{
|
return list.contains(obj);
|
||||||
return new FactorList(this.car,
|
|
||||||
this.next().set(index - 1,car,cdr));
|
|
||||||
}
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ set() method
|
|
||||||
/**
|
|
||||||
* Returns a new list containing the first n elements of this list.
|
|
||||||
*/
|
|
||||||
public FactorList head(int n)
|
|
||||||
{
|
|
||||||
if(n == 0)
|
|
||||||
return null;
|
|
||||||
else if(cdr == null && n == 1)
|
|
||||||
return this;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FactorList head = next().head(n - 1);
|
|
||||||
if(head == cdr)
|
|
||||||
return this;
|
|
||||||
else
|
|
||||||
return new FactorList(car,head);
|
|
||||||
}
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ length() method
|
//{{{ length() method
|
||||||
public int length()
|
public int length()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
FactorList iter = this;
|
Cons iter = this;
|
||||||
while(iter != null)
|
while(iter != null)
|
||||||
{
|
{
|
||||||
iter = (FactorList)iter.cdr;
|
iter = (Cons)iter.cdr;
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ append() method
|
|
||||||
public FactorList append(FactorList list)
|
|
||||||
{
|
|
||||||
if(list == null)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
FactorList returnValue = null;
|
|
||||||
FactorList end = null;
|
|
||||||
FactorList iter = this;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
FactorList cons = new FactorList(iter.car,null);
|
|
||||||
if(end != null)
|
|
||||||
end.cdr = cons;
|
|
||||||
end = cons;
|
|
||||||
if(returnValue == null)
|
|
||||||
returnValue = cons;
|
|
||||||
if(iter.cdr == null)
|
|
||||||
{
|
|
||||||
end.cdr = list;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iter = iter.next();
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ reverse() method
|
|
||||||
public FactorList reverse()
|
|
||||||
{
|
|
||||||
FactorList returnValue = null;
|
|
||||||
FactorList iter = this;
|
|
||||||
while(iter != null)
|
|
||||||
{
|
|
||||||
returnValue = new FactorList(iter.car,returnValue);
|
|
||||||
iter = iter.next();
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ isProperList() method
|
//{{{ isProperList() method
|
||||||
public boolean isProperList()
|
public boolean isProperList()
|
||||||
{
|
{
|
||||||
return cdr == null || (cdr instanceof FactorList
|
return cdr == null || (cdr instanceof Cons
|
||||||
&& ((FactorList)cdr).isProperList());
|
&& ((Cons)cdr).isProperList());
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ elementsToString() method
|
//{{{ elementsToString() method
|
||||||
|
@ -203,17 +134,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
public String elementsToString()
|
public String elementsToString()
|
||||||
{
|
{
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
FactorList iter = this;
|
Cons iter = this;
|
||||||
while(iter != null)
|
while(iter != null)
|
||||||
{
|
{
|
||||||
if(iter.car == this)
|
if(iter.car == this)
|
||||||
buf.append("<circular reference>");
|
buf.append("<circular reference>");
|
||||||
else
|
else
|
||||||
buf.append(FactorJava.factorTypeToString(iter.car));
|
buf.append(FactorJava.factorTypeToString(iter.car));
|
||||||
if(iter.cdr instanceof FactorList)
|
if(iter.cdr instanceof Cons)
|
||||||
{
|
{
|
||||||
buf.append(' ');
|
buf.append(' ');
|
||||||
iter = (FactorList)iter.cdr;
|
iter = (Cons)iter.cdr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(iter.cdr == null)
|
else if(iter.cdr == null)
|
||||||
|
@ -238,19 +169,6 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
return "[ " + elementsToString() + " ]";
|
return "[ " + elementsToString() + " ]";
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ toJavaList() method
|
|
||||||
public List toJavaList()
|
|
||||||
{
|
|
||||||
LinkedList returnValue = new LinkedList();
|
|
||||||
FactorList iter = this;
|
|
||||||
while(iter != null)
|
|
||||||
{
|
|
||||||
returnValue.add(iter.car);
|
|
||||||
iter = (FactorList)iter.cdr;
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ toArray() method
|
//{{{ toArray() method
|
||||||
/**
|
/**
|
||||||
* Note that unlike Java list toArray(), the given array must already
|
* Note that unlike Java list toArray(), the given array must already
|
||||||
|
@ -259,7 +177,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
public Object[] toArray(Object[] returnValue)
|
public Object[] toArray(Object[] returnValue)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
FactorList iter = this;
|
Cons iter = this;
|
||||||
while(iter != null)
|
while(iter != null)
|
||||||
{
|
{
|
||||||
returnValue[i++] = iter.car;
|
returnValue[i++] = iter.car;
|
||||||
|
@ -269,17 +187,17 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ fromArray() method
|
//{{{ fromArray() method
|
||||||
public static FactorList fromArray(Object[] array)
|
public static Cons fromArray(Object[] array)
|
||||||
{
|
{
|
||||||
if(array == null || array.length == 0)
|
if(array == null || array.length == 0)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FactorList first = new FactorList(array[0],null);
|
Cons first = new Cons(array[0],null);
|
||||||
FactorList last = first;
|
Cons last = first;
|
||||||
for(int i = 1; i < array.length; i++)
|
for(int i = 1; i < array.length; i++)
|
||||||
{
|
{
|
||||||
FactorList cons = new FactorList(array[i],null);
|
Cons cons = new Cons(array[i],null);
|
||||||
last.cdr = cons;
|
last.cdr = cons;
|
||||||
last = cons;
|
last = cons;
|
||||||
}
|
}
|
||||||
|
@ -290,9 +208,9 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
//{{{ equals() method
|
//{{{ equals() method
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if(o instanceof FactorList)
|
if(o instanceof Cons)
|
||||||
{
|
{
|
||||||
FactorList l = (FactorList)o;
|
Cons l = (Cons)o;
|
||||||
return FactorLib.objectsEqual(car,l.car)
|
return FactorLib.objectsEqual(car,l.car)
|
||||||
&& FactorLib.objectsEqual(cdr,l.cdr);
|
&& FactorLib.objectsEqual(cdr,l.cdr);
|
||||||
}
|
}
|
||||||
|
@ -312,10 +230,10 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
//{{{ clone() method
|
//{{{ clone() method
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
if(cdr instanceof FactorList)
|
if(cdr instanceof Cons)
|
||||||
return new FactorList(car,((FactorList)cdr).clone());
|
return new Cons(car,((Cons)cdr).clone());
|
||||||
else
|
else
|
||||||
return new FactorList(car,cdr);
|
return new Cons(car,cdr);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ deepClone() method
|
//{{{ deepClone() method
|
||||||
|
@ -326,13 +244,13 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
ccar = ((PublicCloneable)car).clone();
|
ccar = ((PublicCloneable)car).clone();
|
||||||
else
|
else
|
||||||
ccar = car;
|
ccar = car;
|
||||||
if(cdr instanceof FactorList)
|
if(cdr instanceof Cons)
|
||||||
{
|
{
|
||||||
return new FactorList(ccar,next().deepClone());
|
return new Cons(ccar,next().deepClone());
|
||||||
}
|
}
|
||||||
else if(cdr == null)
|
else if(cdr == null)
|
||||||
{
|
{
|
||||||
return new FactorList(ccar,null);
|
return new Cons(ccar,null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -341,7 +259,7 @@ public class FactorList implements PublicCloneable, FactorExternalizable
|
||||||
ccdr = ((PublicCloneable)cdr).clone();
|
ccdr = ((PublicCloneable)cdr).clone();
|
||||||
else
|
else
|
||||||
ccdr = cdr;
|
ccdr = cdr;
|
||||||
return new FactorList(ccar,ccdr);
|
return new Cons(ccar,ccdr);
|
||||||
}
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
}
|
}
|
|
@ -44,7 +44,7 @@ public abstract class FactorArrayStack implements FactorExternalizable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ FactorArrayStack constructor
|
//{{{ FactorArrayStack constructor
|
||||||
public FactorArrayStack(FactorList list)
|
public FactorArrayStack(Cons list)
|
||||||
{
|
{
|
||||||
if(list != null)
|
if(list != null)
|
||||||
{
|
{
|
||||||
|
@ -126,12 +126,12 @@ public abstract class FactorArrayStack implements FactorExternalizable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ toList() method
|
//{{{ toList() method
|
||||||
public FactorList toList()
|
public Cons toList()
|
||||||
{
|
{
|
||||||
FactorList first = null, last = null;
|
Cons first = null, last = null;
|
||||||
for(int i = 0; i < top; i++)
|
for(int i = 0; i < top; i++)
|
||||||
{
|
{
|
||||||
FactorList cons = new FactorList(stack[i],null);
|
Cons cons = new Cons(stack[i],null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
else
|
else
|
||||||
|
|
|
@ -44,13 +44,18 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
|
||||||
/**
|
/**
|
||||||
* Next word to be evaluated.
|
* Next word to be evaluated.
|
||||||
*/
|
*/
|
||||||
public FactorList ip;
|
public Cons ip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collapsed tail calls? See call().
|
* Collapsed tail calls? See call().
|
||||||
*/
|
*/
|
||||||
public boolean collapsed;
|
public boolean collapsed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiled code?
|
||||||
|
*/
|
||||||
|
public boolean compiled;
|
||||||
|
|
||||||
//{{{ FactorCallFrame constructor
|
//{{{ FactorCallFrame constructor
|
||||||
public FactorCallFrame()
|
public FactorCallFrame()
|
||||||
{
|
{
|
||||||
|
@ -59,7 +64,7 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
|
||||||
//{{{ FactorCallFrame constructor
|
//{{{ FactorCallFrame constructor
|
||||||
public FactorCallFrame(FactorWord word,
|
public FactorCallFrame(FactorWord word,
|
||||||
FactorNamespace namespace,
|
FactorNamespace namespace,
|
||||||
FactorList ip)
|
Cons ip)
|
||||||
{
|
{
|
||||||
this.word = word;
|
this.word = word;
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
|
@ -90,12 +95,17 @@ public class FactorCallFrame implements PublicCloneable, FactorExternalizable
|
||||||
|
|
||||||
buf.append("at ").append(word);
|
buf.append("at ").append(word);
|
||||||
|
|
||||||
|
if(compiled)
|
||||||
|
buf.append(" ( compiled )");
|
||||||
|
else if(ip != null)
|
||||||
|
{
|
||||||
|
buf.append(" ( ip: ").append(ip.elementsToString())
|
||||||
|
.append(" )");
|
||||||
|
}
|
||||||
|
|
||||||
buf.append('\n').append(indent);
|
buf.append('\n').append(indent);
|
||||||
|
|
||||||
buf.append(" namespace: ").append(namespace)
|
buf.append(namespace);
|
||||||
.append('\n').append(indent);
|
|
||||||
|
|
||||||
buf.append(" ip: ").append(ip);
|
|
||||||
|
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
|
@ -60,6 +60,12 @@ public class FactorCallStack extends FactorArrayStack implements PublicCloneable
|
||||||
//{{{ clone() method
|
//{{{ clone() method
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
return new FactorCallStack(FactorLib.deepCloneArray(stack),top);
|
if(stack == null)
|
||||||
|
return new FactorCallStack();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new FactorCallStack(
|
||||||
|
FactorLib.deepCloneArray(stack),top);
|
||||||
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,289 +29,356 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
|
import factor.compiler.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.*;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
import org.objectweb.asm.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* : name ... ;
|
* : name ... ;
|
||||||
*/
|
*/
|
||||||
public class FactorCompoundDefinition extends FactorWordDefinition
|
public class FactorCompoundDefinition extends FactorWordDefinition
|
||||||
{
|
{
|
||||||
public FactorList definition;
|
private static int compileCount;
|
||||||
|
|
||||||
public FactorCompoundDefinition(FactorList definition)
|
public Cons definition;
|
||||||
|
|
||||||
|
//{{{ FactorCompiledDefinition constructor
|
||||||
|
public FactorCompoundDefinition(FactorWord word, Cons definition)
|
||||||
{
|
{
|
||||||
|
super(word);
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
}
|
} //}}}
|
||||||
|
|
||||||
public void eval(FactorWord word, FactorInterpreter interp)
|
//{{{ eval() method
|
||||||
|
public void eval(FactorInterpreter interp)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
interp.call(word,definition);
|
interp.call(word,definition);
|
||||||
}
|
} //}}}
|
||||||
|
|
||||||
//{{{ canCompile() method
|
//{{{ getStackEffect() method
|
||||||
boolean canCompile()
|
public StackEffect getStackEffect(Set recursiveCheck,
|
||||||
|
LocalAllocator state) throws Exception
|
||||||
{
|
{
|
||||||
return true;
|
if(recursiveCheck.contains(this))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
recursiveCheck.add(this);
|
||||||
|
|
||||||
|
return StackEffect.getStackEffect(definition,
|
||||||
|
recursiveCheck,state);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
recursiveCheck.remove(this);
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ getSanitizedName() method
|
||||||
|
private String getSanitizedName(String name)
|
||||||
|
{
|
||||||
|
StringBuffer sanitizedName = new StringBuffer();
|
||||||
|
for(int i = 0; i < name.length(); i++)
|
||||||
|
{
|
||||||
|
char ch = name.charAt(i);
|
||||||
|
if(!Character.isJavaIdentifierStart(ch))
|
||||||
|
sanitizedName.append("_");
|
||||||
|
else
|
||||||
|
sanitizedName.append(ch);
|
||||||
|
}
|
||||||
|
return "factor/compiler/gen/" + sanitizedName
|
||||||
|
+ "_" + (compileCount++);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ compile() method
|
//{{{ compile() method
|
||||||
|
/**
|
||||||
|
* Compile the given word, returning a new word definition.
|
||||||
|
*/
|
||||||
|
FactorWordDefinition compile(FactorInterpreter interp,
|
||||||
|
Set recursiveCheck) throws Exception
|
||||||
|
{
|
||||||
|
StackEffect effect = getStackEffect(
|
||||||
|
recursiveCheck,new LocalAllocator());
|
||||||
|
if(effect == null)
|
||||||
|
throw new FactorCompilerException("Cannot deduce stack effect of " + word);
|
||||||
|
if(effect.outD > 1)
|
||||||
|
throw new FactorCompilerException("Cannot compile word that returns more than 1 value");
|
||||||
|
|
||||||
|
/* StringBuffer buf = new StringBuffer();
|
||||||
|
for(int i = 0; i < recursiveCheck.size(); i++)
|
||||||
|
{
|
||||||
|
buf.append(' ');
|
||||||
|
}
|
||||||
|
buf.append("Compiling ").append(word);
|
||||||
|
System.err.println(buf); */
|
||||||
|
|
||||||
|
String className = getSanitizedName(word.name);
|
||||||
|
|
||||||
|
ClassWriter cw = new ClassWriter(false);
|
||||||
|
cw.visit(ACC_PUBLIC, className,
|
||||||
|
"factor/compiler/CompiledDefinition", null, null);
|
||||||
|
|
||||||
|
compileConstructor(cw,className);
|
||||||
|
|
||||||
|
CompileResult result = compileEval(interp,cw,
|
||||||
|
className,effect,recursiveCheck);
|
||||||
|
|
||||||
|
compileToString(cw,effect);
|
||||||
|
|
||||||
|
// Generate fields for storing literals and word references
|
||||||
|
result.allocator.generateFields(cw);
|
||||||
|
|
||||||
|
// gets the bytecode of the class, and loads it dynamically
|
||||||
|
byte[] code = cw.toByteArray();
|
||||||
|
|
||||||
|
if(interp.compileDump)
|
||||||
|
{
|
||||||
|
FileOutputStream fos = new FileOutputStream(className + ".class");
|
||||||
|
fos.write(code);
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Class compiledWordClass = loader._defineClass(
|
||||||
|
className.replace('/','.'),
|
||||||
|
code, 0, code.length);
|
||||||
|
|
||||||
|
result.allocator.setFields(compiledWordClass);
|
||||||
|
|
||||||
|
Constructor constructor = compiledWordClass.getConstructor(
|
||||||
|
new Class[] { FactorWord.class, StackEffect.class });
|
||||||
|
|
||||||
|
FactorWordDefinition compiledWord = (FactorWordDefinition)
|
||||||
|
constructor.newInstance(new Object[] { word, effect });
|
||||||
|
|
||||||
|
// store disassembly for the 'asm' word.
|
||||||
|
compiledWord.getNamespace(interp).setVariable("asm",
|
||||||
|
result.asm);
|
||||||
|
|
||||||
|
return compiledWord;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileConstructor() method
|
||||||
|
private void compileConstructor(ClassVisitor cw, String className)
|
||||||
|
{
|
||||||
|
// creates a MethodWriter for the constructor
|
||||||
|
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
|
||||||
|
"<init>",
|
||||||
|
"(Lfactor/FactorWord;Lfactor/compiler/StackEffect;)V",
|
||||||
|
null, null);
|
||||||
|
// pushes the 'this' variable
|
||||||
|
mw.visitVarInsn(ALOAD, 0);
|
||||||
|
// pushes the word parameter
|
||||||
|
mw.visitVarInsn(ALOAD, 1);
|
||||||
|
// pushes the stack effect parameter
|
||||||
|
mw.visitVarInsn(ALOAD, 2);
|
||||||
|
// invokes the super class constructor
|
||||||
|
mw.visitMethodInsn(INVOKESPECIAL,
|
||||||
|
"factor/compiler/CompiledDefinition", "<init>",
|
||||||
|
"(Lfactor/FactorWord;Lfactor/compiler/StackEffect;)V");
|
||||||
|
mw.visitInsn(RETURN);
|
||||||
|
mw.visitMaxs(3, 3);
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileToString() method
|
||||||
|
private void compileToString(ClassVisitor cw, StackEffect effect)
|
||||||
|
{
|
||||||
|
// creates a MethodWriter for the 'toString' method
|
||||||
|
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
|
||||||
|
"toString", "()Ljava/lang/String;", null, null);
|
||||||
|
mw.visitLdcInsn("( compiled: " + effect + " ) " + toString());
|
||||||
|
mw.visitInsn(ARETURN);
|
||||||
|
mw.visitMaxs(1, 1);
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileEval() method
|
||||||
|
static class CompileResult
|
||||||
|
{
|
||||||
|
LocalAllocator allocator;
|
||||||
|
String asm;
|
||||||
|
|
||||||
|
CompileResult(LocalAllocator allocator, String asm)
|
||||||
|
{
|
||||||
|
this.allocator = allocator;
|
||||||
|
this.asm = asm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the definition of the eval() method in the compiled word.
|
* Write the definition of the eval() method in the compiled word.
|
||||||
* Local 0 -- this
|
* Local 0 -- this
|
||||||
* Local 1 -- word
|
* Local 1 -- interpreter
|
||||||
* Local 2 -- interpreter
|
|
||||||
*/
|
*/
|
||||||
boolean compile(FactorWord word, FactorInterpreter interp,
|
protected CompileResult compileEval(FactorInterpreter interp,
|
||||||
ClassWriter cw, CodeVisitor mw)
|
ClassWriter cw, String className, StackEffect effect,
|
||||||
throws Exception
|
Set recursiveCheck) throws Exception
|
||||||
{
|
{
|
||||||
if(definition == null)
|
// creates a MethodWriter for the 'eval' method
|
||||||
{
|
CodeVisitor _mw = cw.visitMethod(ACC_PUBLIC,
|
||||||
|
"eval", "(Lfactor/FactorInterpreter;)V",
|
||||||
|
null, null);
|
||||||
|
|
||||||
|
TraceCodeVisitor mw = new TraceCodeVisitor(_mw);
|
||||||
|
|
||||||
|
// eval() method calls core
|
||||||
|
mw.visitVarInsn(ALOAD,1);
|
||||||
|
|
||||||
|
compileDataStackToJVMStack(effect,mw);
|
||||||
|
|
||||||
|
String signature = effect.getCorePrototype();
|
||||||
|
|
||||||
|
mw.visitMethodInsn(INVOKESTATIC,
|
||||||
|
className,"core",signature);
|
||||||
|
|
||||||
|
compileJVMStackToDataStack(effect,mw);
|
||||||
|
|
||||||
|
mw.visitInsn(RETURN);
|
||||||
|
mw.visitMaxs(Math.max(4,2 + effect.inD),4);
|
||||||
|
|
||||||
|
String evalAsm = getDisassembly(mw);
|
||||||
|
|
||||||
|
// generate core
|
||||||
|
_mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
|
||||||
|
"core",signature,null,null);
|
||||||
|
|
||||||
|
mw = new TraceCodeVisitor(_mw);
|
||||||
|
|
||||||
|
LocalAllocator allocator = new LocalAllocator(interp,
|
||||||
|
className,1,effect.inD);
|
||||||
|
|
||||||
|
int maxJVMStack = allocator.compile(definition,mw,
|
||||||
|
recursiveCheck);
|
||||||
|
|
||||||
|
if(effect.outD == 0)
|
||||||
mw.visitInsn(RETURN);
|
mw.visitInsn(RETURN);
|
||||||
// Max stack and locals
|
else
|
||||||
mw.visitMaxs(1,1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FactorList fdef = compilePass1(interp,definition);
|
|
||||||
if(fdef.car instanceof FactorReflectionForm
|
|
||||||
&& fdef.cdr == null)
|
|
||||||
{
|
{
|
||||||
return ((FactorReflectionForm)fdef.car).compile(
|
allocator.pop(mw);
|
||||||
word,interp,cw,mw);
|
mw.visitInsn(ARETURN);
|
||||||
|
maxJVMStack = Math.max(maxJVMStack,1);
|
||||||
}
|
}
|
||||||
/* else
|
|
||||||
System.err.println("WARNING: cannot compile reflection & more"); */
|
|
||||||
|
|
||||||
return false;
|
mw.visitMaxs(maxJVMStack,allocator.maxLocals());
|
||||||
|
|
||||||
|
String coreAsm = getDisassembly(mw);
|
||||||
|
|
||||||
|
return new CompileResult(allocator,
|
||||||
|
"eval(Lfactor/FactorInterpreter;)V:\n" + evalAsm
|
||||||
|
+ "core" + signature + "\n" + coreAsm);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ compilePass1() method
|
//{{{ getDisassembly() method
|
||||||
|
protected String getDisassembly(TraceCodeVisitor mw)
|
||||||
|
{
|
||||||
|
// Save the disassembly of the eval() method
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
Iterator bytecodes = mw.getText().iterator();
|
||||||
|
while(bytecodes.hasNext())
|
||||||
|
{
|
||||||
|
buf.append(bytecodes.next());
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileDataStackToJVMStack() method
|
||||||
|
private void compileDataStackToJVMStack(StackEffect effect,
|
||||||
|
CodeVisitor mw)
|
||||||
|
{
|
||||||
|
if(effect.inD != 0)
|
||||||
|
{
|
||||||
|
mw.visitVarInsn(ALOAD,1);
|
||||||
|
mw.visitFieldInsn(GETFIELD,
|
||||||
|
"factor/FactorInterpreter", "datastack",
|
||||||
|
"Lfactor/FactorDataStack;");
|
||||||
|
|
||||||
|
// ensure the stack has enough elements
|
||||||
|
mw.visitInsn(DUP);
|
||||||
|
mw.visitIntInsn(BIPUSH,effect.inD);
|
||||||
|
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||||
|
"factor/FactorArrayStack", "ensurePop",
|
||||||
|
"(I)V");
|
||||||
|
|
||||||
|
// datastack.stack -> 2
|
||||||
|
mw.visitInsn(DUP);
|
||||||
|
mw.visitFieldInsn(GETFIELD,
|
||||||
|
"factor/FactorArrayStack", "stack",
|
||||||
|
"[Ljava/lang/Object;");
|
||||||
|
mw.visitVarInsn(ASTORE,2);
|
||||||
|
// datastack.top-args.length -> 3
|
||||||
|
mw.visitInsn(DUP);
|
||||||
|
mw.visitFieldInsn(GETFIELD,
|
||||||
|
"factor/FactorArrayStack", "top",
|
||||||
|
"I");
|
||||||
|
mw.visitIntInsn(BIPUSH,effect.inD);
|
||||||
|
mw.visitInsn(ISUB);
|
||||||
|
|
||||||
|
// datastack.top -= args.length
|
||||||
|
mw.visitInsn(DUP_X1);
|
||||||
|
mw.visitFieldInsn(PUTFIELD,
|
||||||
|
"factor/FactorArrayStack", "top",
|
||||||
|
"I");
|
||||||
|
|
||||||
|
mw.visitVarInsn(ISTORE,3);
|
||||||
|
|
||||||
|
for(int i = 0; i < effect.inD; i++)
|
||||||
|
{
|
||||||
|
mw.visitVarInsn(ALOAD,2);
|
||||||
|
mw.visitVarInsn(ILOAD,3);
|
||||||
|
mw.visitInsn(AALOAD);
|
||||||
|
if(i != effect.inD - 1)
|
||||||
|
mw.visitIincInsn(3,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileJVMStackToDataStack() method
|
||||||
|
private void compileJVMStackToDataStack(StackEffect effect,
|
||||||
|
CodeVisitor mw)
|
||||||
|
{
|
||||||
|
if(effect.outD == 1)
|
||||||
|
{
|
||||||
|
// ( datastack )
|
||||||
|
mw.visitVarInsn(ALOAD,1);
|
||||||
|
mw.visitFieldInsn(GETFIELD,
|
||||||
|
"factor/FactorInterpreter", "datastack",
|
||||||
|
"Lfactor/FactorDataStack;");
|
||||||
|
|
||||||
|
mw.visitInsn(SWAP);
|
||||||
|
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||||
|
"factor/FactorArrayStack", "push",
|
||||||
|
"(Ljava/lang/Object;)V");
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileImmediate() method
|
||||||
/**
|
/**
|
||||||
* Turn reflection calls into ReflectionForm objects.
|
* Compile a call to this word. Returns maximum JVM stack use.
|
||||||
*/
|
*/
|
||||||
private FactorList compilePass1(FactorInterpreter interp, FactorList def)
|
public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
|
||||||
|
Set recursiveCheck) throws Exception
|
||||||
{
|
{
|
||||||
if(!def.isProperList())
|
return allocator.compile(definition,mw,recursiveCheck);
|
||||||
return def;
|
|
||||||
|
|
||||||
FactorList rdef = def.reverse();
|
|
||||||
|
|
||||||
FactorDictionary dict = interp.dict;
|
|
||||||
|
|
||||||
// A list of words and Java reflection forms
|
|
||||||
FactorList fdef = null;
|
|
||||||
while(rdef != null)
|
|
||||||
{
|
|
||||||
Object car = rdef.car;
|
|
||||||
if(car == dict.jvarGet
|
|
||||||
|| car == dict.jvarSet
|
|
||||||
|| car == dict.jvarGetStatic
|
|
||||||
|| car == dict.jvarSetStatic
|
|
||||||
|| car == dict.jnew)
|
|
||||||
{
|
|
||||||
FactorList form = rdef;
|
|
||||||
rdef = form._get(3);
|
|
||||||
fdef = new FactorList(new FactorReflectionForm(form),
|
|
||||||
fdef);
|
|
||||||
}
|
|
||||||
else if(car == dict.jinvoke
|
|
||||||
|| car == dict.jinvokeStatic)
|
|
||||||
{
|
|
||||||
FactorList form = rdef;
|
|
||||||
rdef = form._get(4);
|
|
||||||
fdef = new FactorList(new FactorReflectionForm(form),
|
|
||||||
fdef);
|
|
||||||
}
|
|
||||||
else if(car instanceof FactorList)
|
|
||||||
{
|
|
||||||
fdef = new FactorList(compilePass1(
|
|
||||||
interp,((FactorList)car)),fdef);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fdef = new FactorList(car,fdef);
|
|
||||||
|
|
||||||
rdef = rdef.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return fdef;
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ precompile() method
|
|
||||||
void precompile(FactorWord newWord, FactorInterpreter interp)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
FactorDictionary dict = interp.dict;
|
|
||||||
|
|
||||||
if(definition != null)
|
|
||||||
{
|
|
||||||
FactorList before = definition;
|
|
||||||
FactorList fed = definition.reverse();
|
|
||||||
precompile(interp,newWord,fed);
|
|
||||||
definition = fed.reverse();
|
|
||||||
/* if(!def.equals(before))
|
|
||||||
{
|
|
||||||
System.out.println("BEFORE: " + before);
|
|
||||||
System.out.println("AFTER: " + def);
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ precompile() method
|
|
||||||
/**
|
|
||||||
* Precompiling turns jconstructor, jfield and jmethod calls
|
|
||||||
* with all-literal arguments into inline
|
|
||||||
* Constructor/Field/Method literals. This improves performance.
|
|
||||||
*/
|
|
||||||
private void precompile(FactorInterpreter interp,
|
|
||||||
FactorWord newWord, FactorList list)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
if(interp.compile)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FactorDictionary dict = interp.dict;
|
|
||||||
|
|
||||||
while(list != null)
|
|
||||||
{
|
|
||||||
Object o = list.car;
|
|
||||||
if(o instanceof FactorWord)
|
|
||||||
{
|
|
||||||
FactorWord word = (FactorWord)o;
|
|
||||||
if(word.def != FactorMissingDefinition.INSTANCE)
|
|
||||||
{
|
|
||||||
word.def.references++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*System.err.println(
|
|
||||||
"WARNING: "
|
|
||||||
+ newWord
|
|
||||||
+ " references "
|
|
||||||
+ o
|
|
||||||
+ " before its defined");*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if(o == dict.jconstructor)
|
|
||||||
{
|
|
||||||
jconstructorPrecompile(
|
|
||||||
interp,list);
|
|
||||||
}
|
|
||||||
else if(o == dict.jmethod)
|
|
||||||
{
|
|
||||||
jmethodPrecompile(
|
|
||||||
interp,list);
|
|
||||||
}
|
|
||||||
else if(o == dict.jfield)
|
|
||||||
{
|
|
||||||
jfieldPrecompile(
|
|
||||||
interp,list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(o instanceof FactorList)
|
|
||||||
{
|
|
||||||
if(((FactorList)o).isProperList())
|
|
||||||
{
|
|
||||||
FactorList l = (FactorList)o;
|
|
||||||
FactorList _l = l.reverse();
|
|
||||||
precompile(interp,newWord,_l);
|
|
||||||
list.car = _l.reverse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = list.next();
|
|
||||||
}
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ jconstructorPrecompile() method
|
|
||||||
private void jconstructorPrecompile(
|
|
||||||
FactorInterpreter interp, FactorList list)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
FactorList cdr = list.next();
|
|
||||||
if(cdr == null)
|
|
||||||
return;
|
|
||||||
if(!(cdr.car instanceof String))
|
|
||||||
return;
|
|
||||||
String clazz = (String)cdr.car;
|
|
||||||
|
|
||||||
FactorList cddr = cdr.next();
|
|
||||||
if(cddr == null)
|
|
||||||
return;
|
|
||||||
if(!(cddr.car instanceof FactorList))
|
|
||||||
return;
|
|
||||||
FactorList args = (FactorList)cddr.car;
|
|
||||||
|
|
||||||
Constructor c = FactorJava.jconstructor(clazz,args);
|
|
||||||
|
|
||||||
list.car = c;
|
|
||||||
list.cdr = cddr.next();
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ jfieldPrecompile() method
|
|
||||||
private void jfieldPrecompile(
|
|
||||||
FactorInterpreter interp, FactorList list)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
FactorList cdr = list.next();
|
|
||||||
if(cdr == null)
|
|
||||||
return;
|
|
||||||
if(!(cdr.car instanceof String))
|
|
||||||
return;
|
|
||||||
String field = (String)cdr.car;
|
|
||||||
|
|
||||||
FactorList cddr = cdr.next();
|
|
||||||
if(cddr == null)
|
|
||||||
return;
|
|
||||||
if(!(cddr.car instanceof String))
|
|
||||||
return;
|
|
||||||
String clazz = (String)cddr.car;
|
|
||||||
|
|
||||||
Field f = FactorJava.jfield(field,clazz);
|
|
||||||
|
|
||||||
list.car = f;
|
|
||||||
list.cdr = cddr.next();
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ jmethodPrecompile() method
|
|
||||||
/**
|
|
||||||
* Check if this jmethod has all-literal arguments, and if so,
|
|
||||||
* inline the result.
|
|
||||||
*/
|
|
||||||
private void jmethodPrecompile(
|
|
||||||
FactorInterpreter interp, FactorList list)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
FactorList cdr = list.next();
|
|
||||||
if(cdr == null)
|
|
||||||
return;
|
|
||||||
if(!(cdr.car instanceof String))
|
|
||||||
return;
|
|
||||||
String method = (String)cdr.car;
|
|
||||||
|
|
||||||
FactorList cddr = cdr.next();
|
|
||||||
if(cddr == null)
|
|
||||||
return;
|
|
||||||
if(!(cddr.car instanceof String))
|
|
||||||
return;
|
|
||||||
String clazz = (String)cddr.car;
|
|
||||||
|
|
||||||
FactorList cdddr = cddr.next();
|
|
||||||
if(cdddr == null)
|
|
||||||
return;
|
|
||||||
if(!(cdddr.car instanceof FactorList))
|
|
||||||
return;
|
|
||||||
FactorList args = (FactorList)cdddr.car;
|
|
||||||
|
|
||||||
Method m = FactorJava.jmethod(method,clazz,args);
|
|
||||||
|
|
||||||
list.car = m;
|
|
||||||
list.cdr = cdddr.next();
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ toString() method
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return definition.elementsToString();
|
return definition.elementsToString();
|
||||||
}
|
} //}}}
|
||||||
|
|
||||||
|
private static SimpleClassLoader loader = new SimpleClassLoader();
|
||||||
|
|
||||||
|
//{{{ SimpleClassLoader class
|
||||||
|
static class SimpleClassLoader extends ClassLoader
|
||||||
|
{
|
||||||
|
public Class _defineClass(String name,
|
||||||
|
byte[] code, int off, int len)
|
||||||
|
{
|
||||||
|
return defineClass(name,code,off,len);
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class FactorDataStack extends FactorArrayStack implements PublicCloneable
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ FactorDataStack constructor
|
//{{{ FactorDataStack constructor
|
||||||
public FactorDataStack(FactorList list)
|
public FactorDataStack(Cons list)
|
||||||
{
|
{
|
||||||
super(list);
|
super(list);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
@ -66,6 +66,12 @@ public class FactorDataStack extends FactorArrayStack implements PublicCloneable
|
||||||
//{{{ clone() method
|
//{{{ clone() method
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
return new FactorDataStack(FactorLib.cloneArray(stack),top);
|
if(stack == null)
|
||||||
|
return new FactorDataStack();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new FactorDataStack(
|
||||||
|
FactorLib.cloneArray(stack),top);
|
||||||
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/*
|
/*
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Slava Pestov.
|
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -29,23 +29,36 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
|
import factor.primitives.*;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
public class FactorDictionary
|
public class FactorDictionary
|
||||||
{
|
{
|
||||||
// these are defined here for use by the precompiler
|
public FactorWord last;
|
||||||
FactorWord jconstructor;
|
|
||||||
|
FactorWord datastackGet;
|
||||||
|
FactorWord datastackSet;
|
||||||
|
FactorWord clear;
|
||||||
|
FactorWord callstackGet;
|
||||||
|
FactorWord callstackSet;
|
||||||
|
FactorWord restack;
|
||||||
|
FactorWord unstack;
|
||||||
|
FactorWord unwind;
|
||||||
FactorWord jnew;
|
FactorWord jnew;
|
||||||
FactorWord jfield;
|
|
||||||
FactorWord jvarGet;
|
FactorWord jvarGet;
|
||||||
FactorWord jvarSet;
|
FactorWord jvarSet;
|
||||||
FactorWord jvarGetStatic;
|
FactorWord jvarGetStatic;
|
||||||
FactorWord jvarSetStatic;
|
FactorWord jvarSetStatic;
|
||||||
FactorWord jmethod;
|
|
||||||
FactorWord jinvoke;
|
FactorWord jinvoke;
|
||||||
FactorWord jinvokeStatic;
|
FactorWord jinvokeStatic;
|
||||||
|
FactorWord get;
|
||||||
|
FactorWord set;
|
||||||
|
FactorWord define;
|
||||||
|
FactorWord call;
|
||||||
|
FactorWord bind;
|
||||||
|
FactorWord choice;
|
||||||
|
|
||||||
private Map intern;
|
private Map intern;
|
||||||
|
|
||||||
|
@ -55,50 +68,65 @@ public class FactorDictionary
|
||||||
intern = new TreeMap();
|
intern = new TreeMap();
|
||||||
|
|
||||||
// data stack primitives
|
// data stack primitives
|
||||||
intern("datastack$").def = new FactorPrimitive.P_datastackGet();
|
datastackGet = intern("datastack$");
|
||||||
intern("datastack@").def = new FactorPrimitive.P_datastackSet();
|
datastackGet.def = new DatastackGet(
|
||||||
intern("clear").def = new FactorPrimitive.P_clear();
|
datastackGet);
|
||||||
|
datastackSet = intern("datastack@");
|
||||||
|
datastackSet.def = new DatastackSet(
|
||||||
|
datastackSet);
|
||||||
|
clear = intern("clear");
|
||||||
|
clear.def = new Clear(clear);
|
||||||
|
|
||||||
// call stack primitives
|
// call stack primitives
|
||||||
intern("callstack$").def = new FactorPrimitive.P_callstackGet();
|
callstackGet = intern("callstack$");
|
||||||
intern("callstack@").def = new FactorPrimitive.P_callstackSet();
|
callstackGet.def = new CallstackGet(
|
||||||
intern("restack").def = new FactorPrimitive.P_restack();
|
callstackGet);
|
||||||
intern("unstack").def = new FactorPrimitive.P_unstack();
|
callstackSet = intern("callstack@");
|
||||||
intern("unwind").def = new FactorPrimitive.P_unwind();
|
callstackSet.def = new CallstackSet(
|
||||||
|
callstackSet);
|
||||||
|
restack = intern("restack");
|
||||||
|
restack.def = new Restack(restack);
|
||||||
|
unstack = intern("unstack");
|
||||||
|
unstack.def = new Unstack(unstack);
|
||||||
|
unwind = intern("unwind");
|
||||||
|
unwind.def = new Unwind(unwind);
|
||||||
|
|
||||||
// reflection primitives
|
// reflection primitives
|
||||||
jconstructor = intern("jconstructor");
|
|
||||||
jconstructor.def = new FactorPrimitive.P_jconstructor();
|
|
||||||
jfield = intern("jfield");
|
|
||||||
jfield.def = new FactorPrimitive.P_jfield();
|
|
||||||
jinvoke = intern("jinvoke");
|
jinvoke = intern("jinvoke");
|
||||||
jinvoke.def = new FactorPrimitive.P_jinvoke();
|
jinvoke.def = new JInvoke(jinvoke);
|
||||||
jinvokeStatic = intern("jinvokeStatic");
|
jinvokeStatic = intern("jinvoke-static");
|
||||||
jinvokeStatic.def = new FactorPrimitive.P_jinvokeStatic();
|
jinvokeStatic.def = new JInvokeStatic(
|
||||||
jmethod = intern("jmethod");
|
jinvokeStatic);
|
||||||
jmethod.def = new FactorPrimitive.P_jmethod();
|
|
||||||
jnew = intern("jnew");
|
jnew = intern("jnew");
|
||||||
jnew.def = new FactorPrimitive.P_jnew();
|
jnew.def = new JNew(jnew);
|
||||||
jvarGet = intern("jvar$");
|
jvarGet = intern("jvar$");
|
||||||
jvarGet.def = new FactorPrimitive.P_jvarGet();
|
jvarGet.def = new JVarGet(jvarGet);
|
||||||
jvarGetStatic = intern("jvarStatic$");
|
jvarGetStatic = intern("jvar-static$");
|
||||||
jvarGetStatic.def = new FactorPrimitive.P_jvarGetStatic();
|
jvarGetStatic.def = new JVarGetStatic(
|
||||||
|
jvarGetStatic);
|
||||||
jvarSet = intern("jvar@");
|
jvarSet = intern("jvar@");
|
||||||
jvarSet.def = new FactorPrimitive.P_jvarSet();
|
jvarSet.def = new JVarSet(jvarSet);
|
||||||
jvarSetStatic = intern("jvarStatic@");
|
jvarSetStatic = intern("jvar-static@");
|
||||||
jvarSetStatic.def = new FactorPrimitive.P_jvarSetStatic();
|
jvarSetStatic.def = new JVarSetStatic(
|
||||||
|
jvarSetStatic);
|
||||||
|
|
||||||
// namespaces
|
// namespaces
|
||||||
intern("$").def = new FactorPrimitive.P_get();
|
get = intern("$");
|
||||||
intern("@").def = new FactorPrimitive.P_set();
|
get.def = new Get(get);
|
||||||
intern("s@").def = new FactorPrimitive.P_swap_set();
|
set = intern("@");
|
||||||
|
set.def = new Set(set);
|
||||||
|
|
||||||
// definition
|
// definition
|
||||||
intern("define").def = new FactorPrimitive.P_define();
|
define = intern("define");
|
||||||
|
define.def = new Define(define);
|
||||||
|
|
||||||
// combinators
|
// combinators
|
||||||
intern("call").def = new FactorPrimitive.P_call();
|
call = intern("call");
|
||||||
intern("bind").def = new FactorPrimitive.P_bind();
|
call.def = new Call(call);
|
||||||
|
bind = intern("bind");
|
||||||
|
bind.def = new Bind(bind);
|
||||||
|
choice = intern("?");
|
||||||
|
choice.def = new Choice(choice);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ intern() method
|
//{{{ intern() method
|
||||||
|
@ -114,17 +142,17 @@ public class FactorDictionary
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ toWordList() method
|
//{{{ toWordList() method
|
||||||
public FactorList toWordList()
|
public Cons toWordList()
|
||||||
{
|
{
|
||||||
FactorList first = null;
|
Cons first = null;
|
||||||
FactorList last = null;
|
Cons last = null;
|
||||||
Iterator iter = intern.values().iterator();
|
Iterator iter = intern.values().iterator();
|
||||||
while(iter.hasNext())
|
while(iter.hasNext())
|
||||||
{
|
{
|
||||||
FactorWord word = (FactorWord)iter.next();
|
FactorWord word = (FactorWord)iter.next();
|
||||||
if(word.def != FactorMissingDefinition.INSTANCE)
|
if(!(word.def instanceof FactorMissingDefinition))
|
||||||
{
|
{
|
||||||
FactorList cons = new FactorList(word,null);
|
Cons cons = new Cons(word,null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
else
|
else
|
||||||
|
|
|
@ -33,15 +33,15 @@ import java.io.*;
|
||||||
|
|
||||||
public class FactorInterpreter
|
public class FactorInterpreter
|
||||||
{
|
{
|
||||||
/**
|
// command line arguments are stored here.
|
||||||
* boot.factor checks this, if its true, an interpreter is run on
|
public Cons args;
|
||||||
* standard input.
|
|
||||||
*/
|
|
||||||
public boolean interactive = false;
|
|
||||||
|
|
||||||
|
// boot.factor sets these.
|
||||||
|
public boolean interactive = true;
|
||||||
public boolean trace = false;
|
public boolean trace = false;
|
||||||
public boolean errorFlag = false;
|
public boolean errorFlag = false;
|
||||||
public boolean compile = true;
|
public boolean compile = true;
|
||||||
|
public boolean compileDump = false;
|
||||||
|
|
||||||
public FactorCallFrame callframe;
|
public FactorCallFrame callframe;
|
||||||
public FactorCallStack callstack = new FactorCallStack();
|
public FactorCallStack callstack = new FactorCallStack();
|
||||||
|
@ -57,21 +57,9 @@ public class FactorInterpreter
|
||||||
{
|
{
|
||||||
FactorInterpreter interp = new FactorInterpreter();
|
FactorInterpreter interp = new FactorInterpreter();
|
||||||
|
|
||||||
boolean virgin = false;
|
interp.init(args,null);
|
||||||
|
|
||||||
for(int i = 0; i < args.length; i++)
|
/* if(virgin)
|
||||||
{
|
|
||||||
if(args[i].equals("-trace"))
|
|
||||||
interp.trace = true;
|
|
||||||
else if(args[i].equals("-virgin"))
|
|
||||||
virgin = true;
|
|
||||||
else if(args[i].equals("-interp"))
|
|
||||||
interp.compile = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
interp.interactive = true;
|
|
||||||
interp.init(null,!virgin);
|
|
||||||
if(virgin)
|
|
||||||
{
|
{
|
||||||
System.out.println("Mini-interpreter");
|
System.out.println("Mini-interpreter");
|
||||||
BufferedReader in = new BufferedReader(
|
BufferedReader in = new BufferedReader(
|
||||||
|
@ -89,7 +77,7 @@ public class FactorInterpreter
|
||||||
FactorParser parser = new FactorParser(
|
FactorParser parser = new FactorParser(
|
||||||
"<mini>",new StringReader(line),
|
"<mini>",new StringReader(line),
|
||||||
interp.dict);
|
interp.dict);
|
||||||
FactorList parsed = parser.parse();
|
Cons parsed = parser.parse();
|
||||||
interp.call(parsed);
|
interp.call(parsed);
|
||||||
interp.run();
|
interp.run();
|
||||||
System.out.println(interp.datastack);
|
System.out.println(interp.datastack);
|
||||||
|
@ -98,21 +86,22 @@ public class FactorInterpreter
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
interp.run();
|
interp.run();
|
||||||
}
|
} */
|
||||||
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ init() method
|
//{{{ init() method
|
||||||
public void init(Object root, boolean bootstrap) throws Exception
|
public void init(String[] args, Object root) throws Exception
|
||||||
{
|
{
|
||||||
|
this.args = Cons.fromArray(args);
|
||||||
|
|
||||||
callstack.top = 0;
|
callstack.top = 0;
|
||||||
datastack.top = 0;
|
datastack.top = 0;
|
||||||
dict.init();
|
dict.init();
|
||||||
initNamespace(root);
|
initNamespace(root);
|
||||||
topLevel();
|
topLevel();
|
||||||
if(bootstrap)
|
runBootstrap();
|
||||||
runBootstrap();
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ initNamespace() method
|
//{{{ initNamespace() method
|
||||||
|
@ -122,8 +111,9 @@ public class FactorInterpreter
|
||||||
|
|
||||||
global.setVariable("interpreter",this);
|
global.setVariable("interpreter",this);
|
||||||
|
|
||||||
String[] boundFields = { "compile", "interactive", "trace",
|
String[] boundFields = { "compile", "compileDump",
|
||||||
"dict", "errorFlag" };
|
"interactive", "trace",
|
||||||
|
"dict", "errorFlag", "args" };
|
||||||
for(int i = 0; i < boundFields.length; i++)
|
for(int i = 0; i < boundFields.length; i++)
|
||||||
{
|
{
|
||||||
global.setVariable(boundFields[i],
|
global.setVariable(boundFields[i],
|
||||||
|
@ -160,7 +150,7 @@ public class FactorInterpreter
|
||||||
if(callframe == null)
|
if(callframe == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
FactorList ip = callframe.ip;
|
Cons ip = callframe.ip;
|
||||||
|
|
||||||
if(ip == null)
|
if(ip == null)
|
||||||
{
|
{
|
||||||
|
@ -213,6 +203,8 @@ public class FactorInterpreter
|
||||||
System.err.println("Factor callstack:");
|
System.err.println("Factor callstack:");
|
||||||
System.err.println(callstack);
|
System.err.println(callstack);
|
||||||
|
|
||||||
|
topLevel();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -231,6 +223,8 @@ public class FactorInterpreter
|
||||||
System.err.println("Factor callstack:");
|
System.err.println("Factor callstack:");
|
||||||
System.err.println(callstack);
|
System.err.println(callstack);
|
||||||
|
|
||||||
|
topLevel();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +234,7 @@ public class FactorInterpreter
|
||||||
/**
|
/**
|
||||||
* Pushes the given list of code onto the callstack.
|
* Pushes the given list of code onto the callstack.
|
||||||
*/
|
*/
|
||||||
public final void call(FactorList code)
|
public final void call(Cons code)
|
||||||
{
|
{
|
||||||
call(dict.intern("call"),code);
|
call(dict.intern("call"),code);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
@ -249,7 +243,7 @@ public class FactorInterpreter
|
||||||
/**
|
/**
|
||||||
* Pushes the given list of code onto the callstack.
|
* Pushes the given list of code onto the callstack.
|
||||||
*/
|
*/
|
||||||
public final void call(FactorWord word, FactorList code)
|
public final void call(FactorWord word, Cons code)
|
||||||
{
|
{
|
||||||
if(callframe == null)
|
if(callframe == null)
|
||||||
call(word,global,code);
|
call(word,global,code);
|
||||||
|
@ -261,7 +255,7 @@ public class FactorInterpreter
|
||||||
/**
|
/**
|
||||||
* Pushes the given list of code onto the callstack.
|
* Pushes the given list of code onto the callstack.
|
||||||
*/
|
*/
|
||||||
public final void call(FactorWord word, FactorNamespace namespace, FactorList code)
|
public final void call(FactorWord word, FactorNamespace namespace, Cons code)
|
||||||
{
|
{
|
||||||
FactorCallFrame newcf;
|
FactorCallFrame newcf;
|
||||||
|
|
||||||
|
@ -321,17 +315,15 @@ public class FactorInterpreter
|
||||||
|
|
||||||
if(obj instanceof FactorWord)
|
if(obj instanceof FactorWord)
|
||||||
{
|
{
|
||||||
FactorWord w = (FactorWord)obj;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
w.def.eval(w,this);
|
((FactorWord)obj).def.eval(this);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
callstack.push(callframe);
|
callstack.push(callframe);
|
||||||
callframe = new FactorCallFrame(
|
callframe = new FactorCallFrame(
|
||||||
w,
|
(FactorWord)obj,
|
||||||
callframe.namespace,
|
callframe.namespace,
|
||||||
null);
|
null);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -29,22 +29,24 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
|
import factor.compiler.LocalAllocator;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A few methods for converting between Java types, and making reflection calls.
|
* A few methods for converting between Java types, and making reflection calls.
|
||||||
* Note that the compiler incorporates calls to some of these methods in
|
* Note that the compiler incorporates calls to some of these methods in
|
||||||
* generated bytecode.
|
* generated bytecode.
|
||||||
*/
|
*/
|
||||||
public class FactorJava
|
public class FactorJava implements Constants
|
||||||
{
|
{
|
||||||
public static final Class[] EMPTY_ARRAY = new Class[0];
|
public static final Class[] EMPTY_ARRAY = new Class[0];
|
||||||
|
|
||||||
//{{{ classNameToClassList() method
|
//{{{ classNameToClassList() method
|
||||||
public static Class[] classNameToClassList(FactorList classes)
|
public static Class[] classNameToClassList(Cons classes)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
if(classes == null)
|
if(classes == null)
|
||||||
|
@ -54,7 +56,31 @@ public class FactorJava
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(classes != null)
|
while(classes != null)
|
||||||
{
|
{
|
||||||
_classes[i++] = (Class)classes.car(Class.class);
|
Object car = classes.car;
|
||||||
|
if(car instanceof Cons)
|
||||||
|
{
|
||||||
|
Cons classSpec = (Cons)car;
|
||||||
|
if(classSpec.cdr != null)
|
||||||
|
{
|
||||||
|
throw new FactorRuntimeException(
|
||||||
|
"Bad class spec: " + car);
|
||||||
|
}
|
||||||
|
Class clazz = (Class)classSpec.car(Class.class);
|
||||||
|
if(clazz.isPrimitive())
|
||||||
|
{
|
||||||
|
_classes[i] = getClass("["
|
||||||
|
+ javaClassToVMClass(clazz));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_classes[i] = getClass("[L"
|
||||||
|
+ clazz.getName() + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_classes[i] = (Class)classes.car(Class.class);
|
||||||
|
|
||||||
|
i++;
|
||||||
classes = classes.next();
|
classes = classes.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +209,29 @@ public class FactorJava
|
||||||
}
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ toNamespace() method
|
||||||
|
public static FactorNamespace toNamespace(Object obj,
|
||||||
|
FactorInterpreter interp) throws Exception
|
||||||
|
{
|
||||||
|
if(obj instanceof FactorNamespace)
|
||||||
|
return (FactorNamespace)obj;
|
||||||
|
else if(obj instanceof FactorObject)
|
||||||
|
{
|
||||||
|
FactorNamespace ns = ((FactorObject)obj)
|
||||||
|
.getNamespace(interp);
|
||||||
|
if(ns == null)
|
||||||
|
throw new FactorRuntimeException(
|
||||||
|
obj + " has a null"
|
||||||
|
+ " namespace");
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new FactorDomainException(obj,
|
||||||
|
FactorObject.class);
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ toArray() method
|
//{{{ toArray() method
|
||||||
public static Object[] toArray(Object arg)
|
public static Object[] toArray(Object arg)
|
||||||
throws FactorDomainException
|
throws FactorDomainException
|
||||||
|
@ -194,9 +243,9 @@ public class FactorJava
|
||||||
public static Object[] toArray(Object arg, Class clas)
|
public static Object[] toArray(Object arg, Class clas)
|
||||||
throws FactorDomainException
|
throws FactorDomainException
|
||||||
{
|
{
|
||||||
if(arg instanceof FactorList)
|
if(arg instanceof Cons)
|
||||||
{
|
{
|
||||||
FactorList list = (FactorList)arg;
|
Cons list = (Cons)arg;
|
||||||
Object[] array = (Object[])
|
Object[] array = (Object[])
|
||||||
Array.newInstance(
|
Array.newInstance(
|
||||||
clas.getComponentType(),
|
clas.getComponentType(),
|
||||||
|
@ -205,7 +254,21 @@ public class FactorJava
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
else if(arg.getClass().isArray())
|
else if(arg.getClass().isArray())
|
||||||
return (Object[])arg;
|
{
|
||||||
|
if(arg.getClass() == clas)
|
||||||
|
return (Object[])arg;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Object[] _arg = (Object[])arg;
|
||||||
|
Object[] array = (Object[])
|
||||||
|
Array.newInstance(
|
||||||
|
clas.getComponentType(),
|
||||||
|
_arg.length);
|
||||||
|
System.arraycopy(arg,0,array,0,
|
||||||
|
_arg.length);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw new FactorDomainException(arg,Object[].class);
|
throw new FactorDomainException(arg,Object[].class);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
@ -296,7 +359,7 @@ public class FactorJava
|
||||||
else if(obj instanceof Character)
|
else if(obj instanceof Character)
|
||||||
return "#\\" + ((Character)obj).charValue();
|
return "#\\" + ((Character)obj).charValue();
|
||||||
else
|
else
|
||||||
return "(" + obj + ")";
|
return "( " + obj + " )";
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ javaClassToVMClass() method
|
//{{{ javaClassToVMClass() method
|
||||||
|
@ -387,7 +450,7 @@ public class FactorJava
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ jconstructor() method
|
//{{{ jconstructor() method
|
||||||
public static Constructor jconstructor(String inClass, FactorList args)
|
public static Constructor jconstructor(String inClass, Cons args)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
return Class.forName(inClass).getConstructor(
|
return Class.forName(inClass).getConstructor(
|
||||||
|
@ -458,7 +521,7 @@ public class FactorJava
|
||||||
|
|
||||||
//{{{ jmethod() method
|
//{{{ jmethod() method
|
||||||
public static Method jmethod(String method, String inClass,
|
public static Method jmethod(String method, String inClass,
|
||||||
FactorList args) throws Exception
|
Cons args) throws Exception
|
||||||
{
|
{
|
||||||
return Class.forName(inClass).getMethod(method,
|
return Class.forName(inClass).getMethod(method,
|
||||||
classNameToClassList(args));
|
classNameToClassList(args));
|
||||||
|
@ -519,4 +582,126 @@ public class FactorJava
|
||||||
else
|
else
|
||||||
return e;
|
return e;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ generateFromConversion() method
|
||||||
|
/**
|
||||||
|
* Unbox value at top of the stack.
|
||||||
|
*/
|
||||||
|
public static void generateFromConversion(CodeVisitor mw, Class type)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if(type == Object.class)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String methodName = null;
|
||||||
|
boolean interpArg = false;
|
||||||
|
|
||||||
|
if(type == Number.class)
|
||||||
|
methodName = "toNumber";
|
||||||
|
else if(type == String.class)
|
||||||
|
methodName = "toString";
|
||||||
|
else if(type == boolean.class)
|
||||||
|
methodName = "toBoolean";
|
||||||
|
else if(type == char.class)
|
||||||
|
methodName = "toChar";
|
||||||
|
else if(type == int.class)
|
||||||
|
methodName = "toInt";
|
||||||
|
else if(type == long.class)
|
||||||
|
methodName = "toLong";
|
||||||
|
else if(type == float.class)
|
||||||
|
methodName = "toFloat";
|
||||||
|
else if(type == double.class)
|
||||||
|
methodName = "toDouble";
|
||||||
|
else if(type == Class.class)
|
||||||
|
methodName = "toClass";
|
||||||
|
else if(type == FactorNamespace.class)
|
||||||
|
{
|
||||||
|
methodName = "toNamespace";
|
||||||
|
interpArg = true;
|
||||||
|
}
|
||||||
|
else if(type.isArray())
|
||||||
|
methodName = "toArray";
|
||||||
|
|
||||||
|
if(methodName == null)
|
||||||
|
{
|
||||||
|
mw.visitTypeInsn(CHECKCAST,
|
||||||
|
type.getName()
|
||||||
|
.replace('.','/'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(interpArg)
|
||||||
|
{
|
||||||
|
mw.visitVarInsn(ALOAD,0);
|
||||||
|
mw.visitMethodInsn(INVOKESTATIC,
|
||||||
|
"factor/FactorJava",
|
||||||
|
methodName,
|
||||||
|
"(Ljava/lang/Object;Lfactor/FactorInterpreter;)"
|
||||||
|
+ FactorJava.javaClassToVMClass(type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mw.visitMethodInsn(INVOKESTATIC,
|
||||||
|
"factor/FactorJava",
|
||||||
|
methodName,
|
||||||
|
"(Ljava/lang/Object;)"
|
||||||
|
+ FactorJava.javaClassToVMClass(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ generateToConversionPre() method
|
||||||
|
/**
|
||||||
|
* Avoid having to deal with category 1/2 computational type
|
||||||
|
* distinction.
|
||||||
|
*/
|
||||||
|
public static boolean generateToConversionPre(CodeVisitor mw,
|
||||||
|
Class type) throws Exception
|
||||||
|
{
|
||||||
|
if(type != boolean.class)
|
||||||
|
{
|
||||||
|
Class boxingType = FactorJava.javaBoxingType(type);
|
||||||
|
if(boxingType != null)
|
||||||
|
{
|
||||||
|
String boxingName = boxingType.getName()
|
||||||
|
.replace('.','/');
|
||||||
|
mw.visitTypeInsn(NEW,boxingName);
|
||||||
|
mw.visitInsn(DUP);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ generateToConversion() method
|
||||||
|
/**
|
||||||
|
* Box return value, if needed.
|
||||||
|
*/
|
||||||
|
public static void generateToConversion(CodeVisitor mw, Class type)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if(type == boolean.class)
|
||||||
|
{
|
||||||
|
// this case is handled specially
|
||||||
|
mw.visitMethodInsn(INVOKESTATIC,
|
||||||
|
"factor/FactorJava",
|
||||||
|
"fromBoolean",
|
||||||
|
"(Z)Ljava/lang/Object;");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Class boxingType = FactorJava.javaBoxingType(type);
|
||||||
|
if(boxingType != null)
|
||||||
|
{
|
||||||
|
String boxingName = boxingType.getName()
|
||||||
|
.replace('.','/');
|
||||||
|
mw.visitMethodInsn(INVOKESPECIAL,boxingName,
|
||||||
|
"<init>",
|
||||||
|
"(" + FactorJava.javaClassToVMClass(
|
||||||
|
type) + ")V");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,6 @@ import java.io.*;
|
||||||
*/
|
*/
|
||||||
public class FactorLib
|
public class FactorLib
|
||||||
{
|
{
|
||||||
//{{{ branch2() method
|
|
||||||
public static Object branch2(boolean condition, Object o1, Object o2)
|
|
||||||
{
|
|
||||||
return (condition ? o1 : o2);
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ branch3() method
|
//{{{ branch3() method
|
||||||
public static Object branch3(float x, float y,
|
public static Object branch3(float x, float y,
|
||||||
Object o1, Object o2, Object o3)
|
Object o1, Object o2, Object o3)
|
||||||
|
@ -54,36 +48,6 @@ public class FactorLib
|
||||||
return o3;
|
return o3;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ cat() method
|
|
||||||
public static String cat(FactorList list)
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
|
|
||||||
while(list != null)
|
|
||||||
{
|
|
||||||
if(list.car instanceof FactorList)
|
|
||||||
buf.append(cat((FactorList)list.car));
|
|
||||||
else
|
|
||||||
buf.append(list.car);
|
|
||||||
list = list.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.toString();
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ cat2() method
|
|
||||||
public static String cat2(Object str1, Object str2)
|
|
||||||
{
|
|
||||||
return new StringBuffer().append(str1).append(str2).toString();
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ cat3() method
|
|
||||||
public static String cat3(Object str1, Object str2, Object str3)
|
|
||||||
{
|
|
||||||
return new StringBuffer().append(str1).append(str2).append(str3)
|
|
||||||
.toString();
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ cloneArray() method
|
//{{{ cloneArray() method
|
||||||
public static Object[] cloneArray(Object[] array)
|
public static Object[] cloneArray(Object[] array)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/*
|
/*
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Slava Pestov.
|
* Copyright (C) 2003,2004 Slava Pestov.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -282,6 +282,12 @@ public class FactorMath
|
||||||
return min + Math.abs(nextInt % (max - min + 1));
|
return min + Math.abs(nextInt % (max - min + 1));
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ randomFloat() method
|
||||||
|
public static float randomFloat(int min, int max, float scale)
|
||||||
|
{
|
||||||
|
return randomInt(min,max) / scale;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ sgn() method
|
//{{{ sgn() method
|
||||||
public static int sgn(float num)
|
public static int sgn(float num)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/*
|
/*
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Slava Pestov.
|
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -29,16 +29,22 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
|
import factor.compiler.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A placeholder for an undefined word.
|
* A placeholder for an undefined word.
|
||||||
*/
|
*/
|
||||||
public class FactorMissingDefinition extends FactorWordDefinition
|
public class FactorMissingDefinition extends FactorWordDefinition
|
||||||
{
|
{
|
||||||
public static final FactorMissingDefinition INSTANCE
|
//{{{ FactorMissingDefinition constructor
|
||||||
= new FactorMissingDefinition();
|
public FactorMissingDefinition(FactorWord word)
|
||||||
|
{
|
||||||
|
super(word);
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ eval() method
|
//{{{ eval() method
|
||||||
public void eval(FactorWord word, FactorInterpreter interp)
|
public void eval(FactorInterpreter interp)
|
||||||
throws FactorUndefinedWordException
|
throws FactorUndefinedWordException
|
||||||
{
|
{
|
||||||
throw new FactorUndefinedWordException(word);
|
throw new FactorUndefinedWordException(word);
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class FactorNamespace implements PublicCloneable
|
||||||
/**
|
/**
|
||||||
* Defines a variable bound to a Java field.
|
* Defines a variable bound to a Java field.
|
||||||
*/
|
*/
|
||||||
public void importVars(String clazz, FactorList vars)
|
public void importVars(String clazz, Cons vars)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
Class clas = Class.forName(clazz);
|
Class clas = Class.forName(clazz);
|
||||||
|
@ -157,16 +157,6 @@ public class FactorNamespace implements PublicCloneable
|
||||||
return o;
|
return o;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ _setVariable() method
|
|
||||||
/**
|
|
||||||
* Alternative form for bindings.
|
|
||||||
*/
|
|
||||||
public void _setVariable(Object value, String name)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
setVariable(name,value);
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ setVariable() method
|
//{{{ setVariable() method
|
||||||
public void setVariable(String name, Object value)
|
public void setVariable(String name, Object value)
|
||||||
throws Exception
|
throws Exception
|
||||||
|
@ -214,10 +204,10 @@ public class FactorNamespace implements PublicCloneable
|
||||||
/**
|
/**
|
||||||
* Returns a list of variable and word names defined in this namespace.
|
* Returns a list of variable and word names defined in this namespace.
|
||||||
*/
|
*/
|
||||||
public FactorList toVarList()
|
public Cons toVarList()
|
||||||
{
|
{
|
||||||
FactorList first = null;
|
Cons first = null;
|
||||||
FactorList last = null;
|
Cons last = null;
|
||||||
Iterator iter = words.entrySet().iterator();
|
Iterator iter = words.entrySet().iterator();
|
||||||
while(iter.hasNext())
|
while(iter.hasNext())
|
||||||
{
|
{
|
||||||
|
@ -226,7 +216,7 @@ public class FactorNamespace implements PublicCloneable
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String name = (String)entry.getKey();
|
String name = (String)entry.getKey();
|
||||||
FactorList cons = new FactorList(name,null);
|
Cons cons = new Cons(name,null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = last = cons;
|
first = last = cons;
|
||||||
else
|
else
|
||||||
|
@ -243,10 +233,10 @@ public class FactorNamespace implements PublicCloneable
|
||||||
/**
|
/**
|
||||||
* Returns a list of pairs of variable and word names, and their values.
|
* Returns a list of pairs of variable and word names, and their values.
|
||||||
*/
|
*/
|
||||||
public FactorList toValueList()
|
public Cons toValueList()
|
||||||
{
|
{
|
||||||
FactorList first = null;
|
Cons first = null;
|
||||||
FactorList last = null;
|
Cons last = null;
|
||||||
Iterator iter = words.entrySet().iterator();
|
Iterator iter = words.entrySet().iterator();
|
||||||
while(iter.hasNext())
|
while(iter.hasNext())
|
||||||
{
|
{
|
||||||
|
@ -254,8 +244,8 @@ public class FactorNamespace implements PublicCloneable
|
||||||
if(entry.getValue() == CHECK_PARENT)
|
if(entry.getValue() == CHECK_PARENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FactorList cons = new FactorList(
|
Cons cons = new Cons(
|
||||||
new FactorList(entry.getKey(),
|
new Cons(entry.getKey(),
|
||||||
entry.getValue()),null);
|
entry.getValue()),null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = last = cons;
|
first = last = cons;
|
||||||
|
@ -299,7 +289,13 @@ public class FactorNamespace implements PublicCloneable
|
||||||
//{{{ toString() method
|
//{{{ toString() method
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "Namespace[" + obj + "]";
|
if(obj == null)
|
||||||
|
{
|
||||||
|
return "( Namespace #" + Integer.toString(hashCode(),16)
|
||||||
|
+ " )";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "( Namespace: " + obj + " #" + hashCode() + " )";
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ clone() method
|
//{{{ clone() method
|
||||||
|
|
|
@ -108,10 +108,10 @@ public class FactorParser
|
||||||
* Reads the file being parsed, and returns a list of all tokens that
|
* Reads the file being parsed, and returns a list of all tokens that
|
||||||
* were read in. This list can be evaluated to run the file.
|
* were read in. This list can be evaluated to run the file.
|
||||||
*/
|
*/
|
||||||
public FactorList parse() throws IOException, FactorParseException
|
public Cons parse() throws IOException, FactorParseException
|
||||||
{
|
{
|
||||||
FactorList first = null;
|
Cons first = null;
|
||||||
FactorList last = null;
|
Cons last = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -131,12 +131,15 @@ public class FactorParser
|
||||||
error("Expected word name after " + next);
|
error("Expected word name after " + next);
|
||||||
}
|
}
|
||||||
|
|
||||||
FactorWordDefinition def = readDef();
|
FactorWord word = (FactorWord)obj;
|
||||||
|
|
||||||
FactorList l = new FactorList(DEFINE,null);
|
FactorWordDefinition def
|
||||||
FactorList cons = new FactorList(
|
= readDef(word);
|
||||||
((FactorWord)obj).name,
|
|
||||||
new FactorList(def,l));
|
Cons l = new Cons(DEFINE,null);
|
||||||
|
Cons cons = new Cons(
|
||||||
|
word.name,
|
||||||
|
new Cons(def,l));
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
else
|
else
|
||||||
|
@ -152,12 +155,15 @@ public class FactorParser
|
||||||
error("Expected word name after " + next);
|
error("Expected word name after " + next);
|
||||||
}
|
}
|
||||||
|
|
||||||
FactorWordDefinition def = readShuffle();
|
FactorWord word = (FactorWord)obj;
|
||||||
|
|
||||||
FactorList l = new FactorList(DEFINE,null);
|
FactorWordDefinition def
|
||||||
FactorList cons = new FactorList(
|
= readShuffle(word);
|
||||||
((FactorWord)obj).name,
|
|
||||||
new FactorList(def,l));
|
Cons l = new Cons(DEFINE,null);
|
||||||
|
Cons cons = new Cons(
|
||||||
|
word.name,
|
||||||
|
new Cons(def,l));
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
else
|
else
|
||||||
|
@ -166,7 +172,7 @@ public class FactorParser
|
||||||
}
|
}
|
||||||
else if(next == BRA)
|
else if(next == BRA)
|
||||||
{
|
{
|
||||||
FactorList cons = new FactorList(
|
Cons cons = new Cons(
|
||||||
readList(),null);
|
readList(),null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
|
@ -180,7 +186,7 @@ public class FactorParser
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FactorList cons = new FactorList(next,null);
|
Cons cons = new Cons(next,null);
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = cons;
|
first = cons;
|
||||||
else
|
else
|
||||||
|
@ -323,10 +329,10 @@ public class FactorParser
|
||||||
/**
|
/**
|
||||||
* Read list until ;.
|
* Read list until ;.
|
||||||
*/
|
*/
|
||||||
private FactorWordDefinition readDef()
|
private FactorWordDefinition readDef(FactorWord word)
|
||||||
throws IOException, FactorParseException
|
throws IOException, FactorParseException
|
||||||
{
|
{
|
||||||
return new FactorCompoundDefinition(readList(INE,false));
|
return new FactorCompoundDefinition(word,readList(INE,false));
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ readShuffle() method
|
//{{{ readShuffle() method
|
||||||
|
@ -336,7 +342,7 @@ public class FactorParser
|
||||||
* On the left is inputs, on the right is their arrangement on the
|
* On the left is inputs, on the right is their arrangement on the
|
||||||
* stack.
|
* stack.
|
||||||
*/
|
*/
|
||||||
private FactorWordDefinition readShuffle()
|
private FactorWordDefinition readShuffle(FactorWord word)
|
||||||
throws IOException, FactorParseException
|
throws IOException, FactorParseException
|
||||||
{
|
{
|
||||||
// 0 in consume map is last consumed, n is first consumed.
|
// 0 in consume map is last consumed, n is first consumed.
|
||||||
|
@ -377,13 +383,14 @@ public class FactorParser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FactorList _shuffle = readList(FLE,false);
|
Cons _shuffle = readList(FLE,false);
|
||||||
|
|
||||||
int consume = consumeMap.size();
|
int consume = consumeMap.size();
|
||||||
|
|
||||||
if(_shuffle == null)
|
if(_shuffle == null)
|
||||||
{
|
{
|
||||||
return new FactorShuffleDefinition(consumeD,consumeR,
|
return new FactorShuffleDefinition(word,
|
||||||
|
consumeD,consumeR,
|
||||||
null,0,null,0);
|
null,0,null,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,12 +404,12 @@ public class FactorParser
|
||||||
{
|
{
|
||||||
if(_shuffle.car instanceof FactorWord)
|
if(_shuffle.car instanceof FactorWord)
|
||||||
{
|
{
|
||||||
FactorWord word = ((FactorWord)_shuffle.car);
|
FactorWord w = ((FactorWord)_shuffle.car);
|
||||||
String name = word.name;
|
String name = w.name;
|
||||||
if(name.startsWith("r:"))
|
if(name.startsWith("r:"))
|
||||||
word = dict.intern(name.substring(2));
|
w = dict.intern(name.substring(2));
|
||||||
|
|
||||||
Integer _index = (Integer)consumeMap.get(word);
|
Integer _index = (Integer)consumeMap.get(w);
|
||||||
if(_index == null)
|
if(_index == null)
|
||||||
error("Does not appear in shuffle LHS: " + _shuffle.car);
|
error("Does not appear in shuffle LHS: " + _shuffle.car);
|
||||||
int index = _index.intValue();
|
int index = _index.intValue();
|
||||||
|
@ -445,7 +452,7 @@ public class FactorParser
|
||||||
shuffleD[k++] = index;
|
shuffleD[k++] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FactorShuffleDefinition(consumeD,consumeR,
|
return new FactorShuffleDefinition(word,consumeD,consumeR,
|
||||||
shuffleD,shuffleDlength,shuffleR,shuffleRlength);
|
shuffleD,shuffleDlength,shuffleR,shuffleRlength);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
@ -453,7 +460,7 @@ public class FactorParser
|
||||||
/**
|
/**
|
||||||
* Read list until ].
|
* Read list until ].
|
||||||
*/
|
*/
|
||||||
private FactorList readList()
|
private Cons readList()
|
||||||
throws IOException, FactorParseException
|
throws IOException, FactorParseException
|
||||||
{
|
{
|
||||||
return readList(KET,true);
|
return readList(KET,true);
|
||||||
|
@ -463,11 +470,11 @@ public class FactorParser
|
||||||
/**
|
/**
|
||||||
* Read list until a given word.
|
* Read list until a given word.
|
||||||
*/
|
*/
|
||||||
private FactorList readList(FactorWord until, boolean allowCommaPair)
|
private Cons readList(FactorWord until, boolean allowCommaPair)
|
||||||
throws IOException, FactorParseException
|
throws IOException, FactorParseException
|
||||||
{
|
{
|
||||||
FactorList first = null;
|
Cons first = null;
|
||||||
FactorList last = null;
|
Cons last = null;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
@ -509,12 +516,12 @@ public class FactorParser
|
||||||
}
|
}
|
||||||
else if(next == BRA)
|
else if(next == BRA)
|
||||||
{
|
{
|
||||||
FactorList list = readList();
|
Cons list = readList();
|
||||||
if(first == null)
|
if(first == null)
|
||||||
first = last = new FactorList(list,null);
|
first = last = new Cons(list,null);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FactorList nextList = new FactorList(list,null);
|
Cons nextList = new Cons(list,null);
|
||||||
last.cdr = nextList;
|
last.cdr = nextList;
|
||||||
last = nextList;
|
last = nextList;
|
||||||
}
|
}
|
||||||
|
@ -522,10 +529,10 @@ public class FactorParser
|
||||||
else if(isParsingWord(next))
|
else if(isParsingWord(next))
|
||||||
error("Unexpected " + next);
|
error("Unexpected " + next);
|
||||||
else if(first == null)
|
else if(first == null)
|
||||||
first = last = new FactorList(next,null);
|
first = last = new Cons(next,null);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FactorList nextList = new FactorList(next,null);
|
Cons nextList = new Cons(next,null);
|
||||||
last.cdr = nextList;
|
last.cdr = nextList;
|
||||||
last = nextList;
|
last = nextList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
} //}}}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
} //}}}
|
|
||||||
}
|
|
|
@ -29,7 +29,10 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
|
import factor.compiler.*;
|
||||||
|
import java.util.Set;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
import org.objectweb.asm.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ~<< name ... -- >>~
|
* ~<< name ... -- >>~
|
||||||
|
@ -63,10 +66,13 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
||||||
private Object[] temporaryR;
|
private Object[] temporaryR;
|
||||||
|
|
||||||
//{{{ FactorShuffleDefinition constructor
|
//{{{ FactorShuffleDefinition constructor
|
||||||
public FactorShuffleDefinition(int consumeD, int consumeR,
|
public FactorShuffleDefinition(FactorWord word,
|
||||||
|
int consumeD, int consumeR,
|
||||||
int[] shuffleD, int shuffleDlength,
|
int[] shuffleD, int shuffleDlength,
|
||||||
int[] shuffleR, int shuffleRlength)
|
int[] shuffleR, int shuffleRlength)
|
||||||
{
|
{
|
||||||
|
super(word);
|
||||||
|
|
||||||
this.consumeD = consumeD;
|
this.consumeD = consumeD;
|
||||||
this.consumeR = consumeR;
|
this.consumeR = consumeR;
|
||||||
this.shuffleD = shuffleD;
|
this.shuffleD = shuffleD;
|
||||||
|
@ -102,295 +108,49 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
||||||
}
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ canCompile() method
|
//{{{ getStackEffect() method
|
||||||
boolean canCompile()
|
public StackEffect getStackEffect(Set recursiveCheck,
|
||||||
|
LocalAllocator state) throws FactorStackException
|
||||||
{
|
{
|
||||||
return true;
|
state.ensure(state.datastack,consumeD);
|
||||||
|
state.ensure(state.callstack,consumeR);
|
||||||
|
eval(state.datastack,state.callstack);
|
||||||
|
return new StackEffect(consumeD,shuffleDlength,
|
||||||
|
consumeR,shuffleRlength);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ compile() method
|
//{{{ compile() method
|
||||||
/**
|
/**
|
||||||
* Write the definition of the eval() method in the compiled word.
|
* Compile the given word, returning a new word definition.
|
||||||
* Local 0 -- this
|
|
||||||
* Local 1 -- word
|
|
||||||
* Local 2 -- interpreter
|
|
||||||
*/
|
*/
|
||||||
boolean compile(FactorWord word, FactorInterpreter interp,
|
FactorWordDefinition compile(FactorInterpreter interp,
|
||||||
ClassWriter cw, CodeVisitor mw)
|
Set recursiveCheck) throws Exception
|
||||||
throws Exception
|
|
||||||
{
|
{
|
||||||
boolean fromD = false;
|
return this;
|
||||||
boolean fromR = false;
|
} //}}}
|
||||||
for(int i = 0; i < shuffleDlength; i++)
|
|
||||||
{
|
|
||||||
fromD = true;
|
|
||||||
if((shuffleD[i] & FROM_R_MASK) == FROM_R_MASK)
|
|
||||||
{
|
|
||||||
fromR = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < shuffleRlength; i++)
|
|
||||||
{
|
|
||||||
fromR = true;
|
|
||||||
if((shuffleR[i] & FROM_R_MASK) == FROM_R_MASK)
|
|
||||||
{
|
|
||||||
fromR = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Local 3 -- datastack
|
//{{{ compileCallTo() method
|
||||||
// Local 4 -- datastack top-consumeD
|
/**
|
||||||
// Local 5 -- datastack array
|
* Compile a call to this word. Returns maximum JVM stack use.
|
||||||
if(consumeD != 0 || fromD)
|
*/
|
||||||
{
|
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
|
||||||
// (datastack datastack datastack)
|
Set recursiveCheck) throws FactorStackException
|
||||||
mw.visitVarInsn(ALOAD,2);
|
{
|
||||||
mw.visitFieldInsn(GETFIELD,
|
eval(allocator.datastack,allocator.callstack);
|
||||||
"factor/FactorInterpreter", "datastack",
|
return 0;
|
||||||
"Lfactor/FactorDataStack;");
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
if(consumeD != 0)
|
|
||||||
{
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
mw.visitIntInsn(BIPUSH,consumeD);
|
|
||||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
|
||||||
"factor/FactorArrayStack", "ensurePop",
|
|
||||||
"(I)V");
|
|
||||||
}
|
|
||||||
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
// datastack -> 3
|
|
||||||
mw.visitVarInsn(ASTORE,3);
|
|
||||||
// datastack.top-consumeD -> 4
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
if(consumeD != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,consumeD);
|
|
||||||
mw.visitInsn(ISUB);
|
|
||||||
}
|
|
||||||
mw.visitVarInsn(ISTORE,4);
|
|
||||||
// datastack.stack -> 5
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "stack",
|
|
||||||
"[Ljava/lang/Object;");
|
|
||||||
mw.visitVarInsn(ASTORE,5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Local 6 -- callstack
|
|
||||||
// Local 7 -- callstack top-consumeR
|
|
||||||
// Local 8 -- callstack array
|
|
||||||
if(consumeR != 0 || fromR)
|
|
||||||
{
|
|
||||||
// (callstack callstack)
|
|
||||||
mw.visitVarInsn(ALOAD,2);
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorInterpreter", "callstack",
|
|
||||||
"Lfactor/FactorCallStack;");
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
if(consumeR != 0)
|
|
||||||
{
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
mw.visitIntInsn(BIPUSH,consumeR);
|
|
||||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
|
||||||
"factor/FactorArrayStack", "ensurePop",
|
|
||||||
"(I)V");
|
|
||||||
}
|
|
||||||
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
// callstack -> 6
|
|
||||||
mw.visitVarInsn(ASTORE,6);
|
|
||||||
// callstack.top-consumeR -> 7
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
if(consumeR != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,consumeR);
|
|
||||||
mw.visitInsn(ISUB);
|
|
||||||
}
|
|
||||||
mw.visitVarInsn(ISTORE,7);
|
|
||||||
// callstack.stack -> 8
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "stack",
|
|
||||||
"[Ljava/lang/Object;");
|
|
||||||
mw.visitVarInsn(ASTORE,8);
|
|
||||||
}
|
|
||||||
|
|
||||||
int locals = 9;
|
|
||||||
|
|
||||||
if(shuffleD != null)
|
|
||||||
{
|
|
||||||
for(int i = shuffleDstart; i < shuffleDlength; i++)
|
|
||||||
{
|
|
||||||
// stack[top-consumeD+shuffleD[i]] -> 9+i
|
|
||||||
int index = shuffleD[i];
|
|
||||||
if((index & FROM_R_MASK) == FROM_R_MASK)
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,8);
|
|
||||||
mw.visitVarInsn(ILOAD,7);
|
|
||||||
index &= ~FROM_R_MASK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,5);
|
|
||||||
mw.visitVarInsn(ILOAD,4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,index);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
}
|
|
||||||
|
|
||||||
mw.visitInsn(AALOAD);
|
|
||||||
mw.visitVarInsn(ASTORE,9 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
locals += shuffleDlength;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shuffleR != null)
|
|
||||||
{
|
|
||||||
for(int i = shuffleRstart; i < shuffleRlength; i++)
|
|
||||||
{
|
|
||||||
// stack[top-consumeR+shuffleR[i]] -> 9+i
|
|
||||||
int index = shuffleR[i];
|
|
||||||
if((index & FROM_R_MASK) == FROM_R_MASK)
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,8);
|
|
||||||
mw.visitVarInsn(ILOAD,7);
|
|
||||||
index &= ~FROM_R_MASK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,5);
|
|
||||||
mw.visitVarInsn(ILOAD,4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,index);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
}
|
|
||||||
|
|
||||||
mw.visitInsn(AALOAD);
|
|
||||||
mw.visitVarInsn(ASTORE,locals + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shuffleD != null)
|
|
||||||
{
|
|
||||||
// ensure that the stack array has enough space.
|
|
||||||
mw.visitVarInsn(ALOAD,3);
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
mw.visitIntInsn(BIPUSH,shuffleDlength);
|
|
||||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
|
||||||
"factor/FactorArrayStack", "ensurePush", "(I)V");
|
|
||||||
// the datastack.stack array might have changed.
|
|
||||||
// reload it.
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "stack",
|
|
||||||
"[Ljava/lang/Object;");
|
|
||||||
mw.visitVarInsn(ASTORE,5);
|
|
||||||
|
|
||||||
for(int i = shuffleDstart; i < shuffleDlength; i++)
|
|
||||||
{
|
|
||||||
// stack[top - consumeD + i] <- 9+i
|
|
||||||
mw.visitVarInsn(ALOAD,5);
|
|
||||||
mw.visitVarInsn(ILOAD,4);
|
|
||||||
if(i != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,i);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
}
|
|
||||||
mw.visitVarInsn(ALOAD,9 + i);
|
|
||||||
mw.visitInsn(AASTORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment the 'top' field.
|
|
||||||
mw.visitVarInsn(ALOAD,3);
|
|
||||||
mw.visitVarInsn(ILOAD,4);
|
|
||||||
mw.visitIntInsn(BIPUSH,shuffleDlength);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
mw.visitFieldInsn(PUTFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
}
|
|
||||||
else if(consumeD != 0)
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,3);
|
|
||||||
mw.visitVarInsn(ILOAD,4);
|
|
||||||
mw.visitFieldInsn(PUTFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shuffleR != null)
|
|
||||||
{
|
|
||||||
// ensure that the stack array has enough space.
|
|
||||||
mw.visitVarInsn(ALOAD,6);
|
|
||||||
mw.visitInsn(DUP);
|
|
||||||
mw.visitIntInsn(BIPUSH,shuffleDlength);
|
|
||||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
|
||||||
"factor/FactorArrayStack", "ensurePush", "(I)V");
|
|
||||||
// the callstack.stack array might have changed.
|
|
||||||
// reload it.
|
|
||||||
mw.visitFieldInsn(GETFIELD,
|
|
||||||
"factor/FactorArrayStack", "stack",
|
|
||||||
"[Ljava/lang/Object;");
|
|
||||||
mw.visitVarInsn(ASTORE,8);
|
|
||||||
|
|
||||||
for(int i = shuffleRstart; i < shuffleRlength; i++)
|
|
||||||
{
|
|
||||||
// stack[top - consumeD + i] <- locals+i
|
|
||||||
mw.visitVarInsn(ALOAD,8);
|
|
||||||
mw.visitVarInsn(ILOAD,7);
|
|
||||||
if(i != 0)
|
|
||||||
{
|
|
||||||
mw.visitIntInsn(BIPUSH,i);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
}
|
|
||||||
mw.visitVarInsn(ALOAD,locals + i);
|
|
||||||
mw.visitInsn(AASTORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment the 'top' field.
|
|
||||||
mw.visitVarInsn(ALOAD,6);
|
|
||||||
mw.visitVarInsn(ILOAD,7);
|
|
||||||
mw.visitIntInsn(BIPUSH,shuffleRlength);
|
|
||||||
mw.visitInsn(IADD);
|
|
||||||
mw.visitFieldInsn(PUTFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
}
|
|
||||||
else if(consumeR != 0)
|
|
||||||
{
|
|
||||||
mw.visitVarInsn(ALOAD,6);
|
|
||||||
mw.visitVarInsn(ILOAD,7);
|
|
||||||
mw.visitFieldInsn(PUTFIELD,
|
|
||||||
"factor/FactorArrayStack", "top",
|
|
||||||
"I");
|
|
||||||
}
|
|
||||||
|
|
||||||
mw.visitInsn(RETURN);
|
|
||||||
|
|
||||||
// Max stack and locals
|
|
||||||
mw.visitMaxs(4,9 + shuffleDlength + shuffleRlength);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ eval() method
|
//{{{ eval() method
|
||||||
public void eval(FactorWord word, FactorInterpreter interp)
|
public void eval(FactorInterpreter interp)
|
||||||
throws FactorStackException
|
throws FactorStackException
|
||||||
{
|
{
|
||||||
FactorArrayStack datastack = interp.datastack;
|
eval(interp.datastack,interp.callstack);
|
||||||
FactorArrayStack callstack = interp.callstack;
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ eval() method
|
||||||
|
public void eval(FactorArrayStack datastack, FactorArrayStack callstack)
|
||||||
|
throws FactorStackException
|
||||||
|
{
|
||||||
if(datastack.top < consumeD)
|
if(datastack.top < consumeD)
|
||||||
throw new FactorStackException(consumeD);
|
throw new FactorStackException(consumeD);
|
||||||
|
|
||||||
|
@ -398,10 +158,16 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
||||||
throw new FactorStackException(consumeR);
|
throw new FactorStackException(consumeR);
|
||||||
|
|
||||||
if(shuffleD != null)
|
if(shuffleD != null)
|
||||||
shuffle(interp,datastack,consumeD,consumeR,shuffleD,temporaryD);
|
{
|
||||||
|
shuffle(datastack,callstack,datastack,consumeD,consumeR,
|
||||||
|
shuffleD,temporaryD);
|
||||||
|
}
|
||||||
|
|
||||||
if(shuffleR != null)
|
if(shuffleR != null)
|
||||||
shuffle(interp,callstack,consumeD,consumeR,shuffleR,temporaryR);
|
{
|
||||||
|
shuffle(datastack,callstack,callstack,consumeD,consumeR,
|
||||||
|
shuffleR,temporaryR);
|
||||||
|
}
|
||||||
|
|
||||||
datastack.top -= consumeD;
|
datastack.top -= consumeD;
|
||||||
if(temporaryD != null)
|
if(temporaryD != null)
|
||||||
|
@ -414,8 +180,14 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ shuffle() method
|
//{{{ shuffle() method
|
||||||
private void shuffle(FactorInterpreter interp, FactorArrayStack stack,
|
private void shuffle(
|
||||||
int consumeD, int consumeR, int[] shuffle, Object[] temporary)
|
FactorArrayStack datastack,
|
||||||
|
FactorArrayStack callstack,
|
||||||
|
FactorArrayStack stack,
|
||||||
|
int consumeD,
|
||||||
|
int consumeR,
|
||||||
|
int[] shuffle,
|
||||||
|
Object[] temporary)
|
||||||
throws FactorStackException
|
throws FactorStackException
|
||||||
{
|
{
|
||||||
for(int i = 0; i < temporary.length; i++)
|
for(int i = 0; i < temporary.length; i++)
|
||||||
|
@ -426,15 +198,15 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
||||||
int consume;
|
int consume;
|
||||||
if((index & FROM_R_MASK) == FROM_R_MASK)
|
if((index & FROM_R_MASK) == FROM_R_MASK)
|
||||||
{
|
{
|
||||||
array = interp.callstack.stack;
|
array = callstack.stack;
|
||||||
top = interp.callstack.top;
|
top = callstack.top;
|
||||||
index = (index & ~FROM_R_MASK);
|
index = (index & ~FROM_R_MASK);
|
||||||
consume = consumeR;
|
consume = consumeR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
array = interp.datastack.stack;
|
array = datastack.stack;
|
||||||
top = interp.datastack.top;
|
top = datastack.top;
|
||||||
consume = consumeD;
|
consume = consumeD;
|
||||||
}
|
}
|
||||||
temporary[i] = array[top - consume + index];
|
temporary[i] = array[top - consume + index];
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import factor.compiler.FactorCompilerException;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An internalized symbol.
|
* An internalized symbol.
|
||||||
|
@ -44,10 +44,20 @@ public class FactorWord implements FactorExternalizable
|
||||||
*/
|
*/
|
||||||
public FactorWordDefinition def;
|
public FactorWordDefinition def;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition before compiling.
|
||||||
|
*/
|
||||||
|
public FactorWordDefinition uncompiled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "define" pushes previous definitions onto this list, like a stack.
|
* "define" pushes previous definitions onto this list, like a stack.
|
||||||
*/
|
*/
|
||||||
public FactorList history;
|
public Cons history;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this word referenced from a compiled word?
|
||||||
|
*/
|
||||||
|
public boolean compileRef;
|
||||||
|
|
||||||
//{{{ FactorWord constructor
|
//{{{ FactorWord constructor
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +68,64 @@ public class FactorWord implements FactorExternalizable
|
||||||
public FactorWord(String name)
|
public FactorWord(String name)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
def = FactorMissingDefinition.INSTANCE;
|
def = new FactorMissingDefinition(this);
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ define() method
|
||||||
|
public void define(FactorWordDefinition def)
|
||||||
|
{
|
||||||
|
if(compileRef)
|
||||||
|
{
|
||||||
|
System.err.println("WARNING: " + this
|
||||||
|
+ " is used in one or more compiled words; old definition will remain until full recompile");
|
||||||
|
}
|
||||||
|
else if(!(this.def instanceof FactorMissingDefinition))
|
||||||
|
{
|
||||||
|
System.err.println("WARNING: redefining " + this);
|
||||||
|
history = new Cons(this.def,history);
|
||||||
|
}
|
||||||
|
|
||||||
|
uncompiled = this.def = def;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compile() method
|
||||||
|
public void compile(FactorInterpreter interp)
|
||||||
|
{
|
||||||
|
compile(interp,new HashSet());
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compile() method
|
||||||
|
public void compile(FactorInterpreter interp, Set recursiveCheck)
|
||||||
|
{
|
||||||
|
if(def.compileFailed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
System.err.println("Compiling " + this);
|
||||||
|
if(recursiveCheck.contains(this))
|
||||||
|
System.err.println("WARNING: cannot compile recursive calls: " + this);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
recursiveCheck.add(this);
|
||||||
|
|
||||||
|
def = def.compile(interp,recursiveCheck);
|
||||||
|
}
|
||||||
|
catch(FactorCompilerException e)
|
||||||
|
{
|
||||||
|
def.compileFailed = true;
|
||||||
|
System.err.println("WARNING: cannot compile " + this);
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
}
|
||||||
|
catch(Throwable t)
|
||||||
|
{
|
||||||
|
def.compileFailed = true;
|
||||||
|
System.err.println("WARNING: cannot compile " + this);
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
recursiveCheck.remove(this);
|
||||||
|
}
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ toString() method
|
//{{{ toString() method
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/*
|
/*
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Slava Pestov.
|
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
|
|
||||||
package factor;
|
package factor;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import factor.compiler.*;
|
||||||
import java.util.Iterator;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
import org.objectweb.asm.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A word definition.
|
* A word definition.
|
||||||
|
@ -40,152 +40,89 @@ import org.objectweb.asm.util.*;
|
||||||
public abstract class FactorWordDefinition implements FactorObject, Constants
|
public abstract class FactorWordDefinition implements FactorObject, Constants
|
||||||
{
|
{
|
||||||
private FactorNamespace namespace;
|
private FactorNamespace namespace;
|
||||||
|
protected FactorWord word;
|
||||||
|
|
||||||
/**
|
public boolean compileFailed;
|
||||||
* Number of times this word has been referenced from a
|
|
||||||
* compound word (incremented by the precompiler).
|
|
||||||
*/
|
|
||||||
public int references;
|
|
||||||
|
|
||||||
public abstract void eval(FactorWord word, FactorInterpreter interp)
|
public FactorWordDefinition(FactorWord word)
|
||||||
|
{
|
||||||
|
this.word = word;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void eval(FactorInterpreter interp)
|
||||||
throws Exception;
|
throws Exception;
|
||||||
|
|
||||||
void precompile(FactorWord word, FactorInterpreter interp)
|
//{{{ getNamespace() method
|
||||||
throws Exception {}
|
|
||||||
|
|
||||||
public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception
|
public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception
|
||||||
{
|
{
|
||||||
if(namespace == null)
|
if(namespace == null)
|
||||||
namespace = new FactorNamespace(interp.global,this);
|
namespace = new FactorNamespace(interp.global,this);
|
||||||
|
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
|
||||||
|
|
||||||
//{{{ canCompile() method
|
|
||||||
boolean canCompile()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
private static int compileCount;
|
//{{{ getStackEffect() method
|
||||||
|
public final StackEffect getStackEffect() throws Exception
|
||||||
//{{{ compile() method
|
|
||||||
/**
|
|
||||||
* Compile the given word, returning a new word definition.
|
|
||||||
*/
|
|
||||||
FactorWordDefinition compile(FactorWord word, FactorInterpreter interp)
|
|
||||||
throws Exception
|
|
||||||
{
|
{
|
||||||
if(!canCompile())
|
return getStackEffect(new HashSet(),new LocalAllocator());
|
||||||
return this;
|
} //}}}
|
||||||
|
|
||||||
//System.out.println("Compiling " + word);
|
//{{{ getStackEffect() method
|
||||||
|
public StackEffect getStackEffect(Set recursiveCheck,
|
||||||
StringBuffer sanitizedName = new StringBuffer();
|
LocalAllocator state) throws Exception
|
||||||
for(int i = 0; i < word.name.length(); i++)
|
{
|
||||||
{
|
return null;
|
||||||
char ch = word.name.charAt(i);
|
|
||||||
if(!Character.isJavaIdentifierStart(ch))
|
|
||||||
sanitizedName.append("_");
|
|
||||||
else
|
|
||||||
sanitizedName.append(ch);
|
|
||||||
}
|
|
||||||
String className = "factor/__compiler__/" + sanitizedName
|
|
||||||
+ "_" + (compileCount++);
|
|
||||||
|
|
||||||
ClassWriter cw = new ClassWriter(false);
|
|
||||||
cw.visit(ACC_PUBLIC, className,
|
|
||||||
"factor/FactorWordDefinition", null, null);
|
|
||||||
|
|
||||||
// creates a MethodWriter for the (implicit) constructor
|
|
||||||
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
|
|
||||||
"<init>", "()V", null, null);
|
|
||||||
// pushes the 'this' variable
|
|
||||||
mw.visitVarInsn(ALOAD, 0);
|
|
||||||
// invokes the super class constructor
|
|
||||||
mw.visitMethodInsn(INVOKESPECIAL,
|
|
||||||
"factor/FactorWordDefinition", "<init>", "()V");
|
|
||||||
mw.visitInsn(RETURN);
|
|
||||||
// this code uses a maximum of one stack element and one local
|
|
||||||
// variable
|
|
||||||
mw.visitMaxs(1, 1);
|
|
||||||
|
|
||||||
// creates a MethodWriter for the 'toString' method
|
|
||||||
mw = cw.visitMethod(ACC_PUBLIC,
|
|
||||||
"toString", "()Ljava/lang/String;", null, null);
|
|
||||||
mw.visitLdcInsn("( compiled ) " + toString());
|
|
||||||
mw.visitInsn(ARETURN);
|
|
||||||
mw.visitMaxs(1, 1);
|
|
||||||
|
|
||||||
// pushes the 'this' variable
|
|
||||||
mw.visitVarInsn(ALOAD, 0);
|
|
||||||
// invokes the super class constructor
|
|
||||||
mw.visitMethodInsn(INVOKESPECIAL,
|
|
||||||
"factor/FactorWordDefinition", "<init>", "()V");
|
|
||||||
mw.visitInsn(RETURN);
|
|
||||||
// this code uses a maximum of one stack element and one local
|
|
||||||
// variable
|
|
||||||
mw.visitMaxs(1, 1);
|
|
||||||
|
|
||||||
// creates a MethodWriter for the 'eval' method
|
|
||||||
mw = cw.visitMethod(ACC_PUBLIC,
|
|
||||||
"eval", "(Lfactor/FactorWord;Lfactor/FactorInterpreter;)V",
|
|
||||||
null, null);
|
|
||||||
|
|
||||||
// We store a string with disassembly for debugging
|
|
||||||
// purposes.
|
|
||||||
TraceCodeVisitor disasm = new TraceCodeVisitor(mw);
|
|
||||||
if(!compile(word,interp,cw,disasm))
|
|
||||||
return this;
|
|
||||||
|
|
||||||
// Save the disassembly
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
Iterator bytecodes = disasm.getText().iterator();
|
|
||||||
while(bytecodes.hasNext())
|
|
||||||
{
|
|
||||||
buf.append(bytecodes.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the bytecode of the class, and loads it dynamically
|
|
||||||
byte[] code = cw.toByteArray();
|
|
||||||
|
|
||||||
/* FileOutputStream fos = new FileOutputStream(className + ".class");
|
|
||||||
fos.write(code);
|
|
||||||
fos.close(); */
|
|
||||||
|
|
||||||
SimpleClassLoader loader = new SimpleClassLoader();
|
|
||||||
Class compiledWordClass = loader._defineClass(className,
|
|
||||||
code, 0, code.length);
|
|
||||||
|
|
||||||
FactorWordDefinition compiledWord = (FactorWordDefinition)
|
|
||||||
compiledWordClass.newInstance();
|
|
||||||
|
|
||||||
compiledWord.getNamespace(interp).setVariable("asm",buf.toString());
|
|
||||||
|
|
||||||
return compiledWord;
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ compile() method
|
//{{{ compile() method
|
||||||
/**
|
FactorWordDefinition compile(FactorInterpreter interp,
|
||||||
* Write the definition of the eval() method in the compiled word.
|
Set recursiveCheck) throws Exception
|
||||||
* Local 0 -- this
|
|
||||||
* Local 1 -- word
|
|
||||||
* Local 2 -- interpreter
|
|
||||||
*/
|
|
||||||
boolean compile(FactorWord word, FactorInterpreter interp,
|
|
||||||
ClassWriter cw, CodeVisitor mw)
|
|
||||||
throws Exception
|
|
||||||
{
|
{
|
||||||
throw new FactorRuntimeException("Don't know how to compile " + word);
|
return this;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ SimpleClassLoader class
|
//{{{ compileCallTo() method
|
||||||
static class SimpleClassLoader extends ClassLoader
|
/**
|
||||||
|
* Compile a call to this word. Returns maximum JVM stack use.
|
||||||
|
*/
|
||||||
|
public int compileCallTo(CodeVisitor mw, LocalAllocator allocator,
|
||||||
|
Set recursiveCheck) throws Exception
|
||||||
{
|
{
|
||||||
public Class _defineClass(String name,
|
StackEffect effect = getStackEffect();
|
||||||
byte[] code, int off, int len)
|
if(effect == null)
|
||||||
{
|
{
|
||||||
return defineClass(name,code,off,len);
|
// combinator; inline
|
||||||
|
return compileImmediate(mw,allocator,recursiveCheck);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// normal word
|
||||||
|
mw.visitVarInsn(ALOAD,0);
|
||||||
|
|
||||||
|
allocator.generateArgs(mw,effect.inD,null);
|
||||||
|
|
||||||
|
String defclass = getClass().getName().replace('.','/');
|
||||||
|
|
||||||
|
String signature = effect.getCorePrototype();
|
||||||
|
|
||||||
|
mw.visitMethodInsn(INVOKESTATIC,defclass,"core",signature);
|
||||||
|
|
||||||
|
if(effect.outD > 1)
|
||||||
|
throw new FactorCompilerException("Cannot compile word with non-0/1-out factors");
|
||||||
|
if(effect.outD == 1)
|
||||||
|
allocator.push(mw);
|
||||||
|
|
||||||
|
return effect.inD + 1;
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ compileImmediate() method
|
||||||
|
/**
|
||||||
|
* Compile a call to this word. Returns maximum JVM stack use.
|
||||||
|
*/
|
||||||
|
public int compileImmediate(CodeVisitor mw, LocalAllocator allocator,
|
||||||
|
Set recursiveCheck) throws Exception
|
||||||
|
{
|
||||||
|
throw new FactorCompilerException("Cannot compile " + word + " in immediate mode");
|
||||||
} //}}}
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,28 +28,30 @@
|
||||||
!!! The stack operators are defined using shuffle notation. This saves several
|
!!! The stack operators are defined using shuffle notation. This saves several
|
||||||
!!! hundred lines of code!
|
!!! hundred lines of code!
|
||||||
|
|
||||||
~<< drop A -- >>~
|
~<< drop A -- >>~
|
||||||
~<< 2drop A B -- >>~
|
~<< 2drop A B -- >>~
|
||||||
~<< dup A -- A A >>~
|
~<< dup A -- A A >>~
|
||||||
~<< 2dup A B -- A B A B >>~
|
~<< 2dup A B -- A B A B >>~
|
||||||
~<< dupd A B -- A A B >>~
|
~<< dupd A B -- A A B >>~
|
||||||
~<< 2dupd A B C D -- A B A B C D >>~
|
~<< 2dupd A B C D -- A B A B C D >>~
|
||||||
~<< nip A B -- B >>~
|
~<< nip A B -- B >>~
|
||||||
~<< 2nip A B C D -- C D >>~
|
~<< 2nip A B C D -- C D >>~
|
||||||
~<< nop -- >>~ ! Does nothing!
|
~<< nop -- >>~ ! Does nothing!
|
||||||
~<< over A B -- A B A >>~
|
~<< over A B -- A B A >>~
|
||||||
~<< 2over A B C D -- A B C D A B >>~
|
~<< 2over A B C D -- A B C D A B >>~
|
||||||
~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
|
~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
|
||||||
~<< rot A B C -- B C A >>~
|
~<< rot A B C -- B C A >>~
|
||||||
~<< 2rot A B C D E F -- C D E F A B >>~
|
~<< 2rot A B C D E F -- C D E F A B >>~
|
||||||
~<< -rot A B C -- C A B >>~
|
~<< -rot A B C -- C A B >>~
|
||||||
~<< 2-rot A B C D E F -- E F A B C D >>~
|
~<< 2-rot A B C D E F -- E F A B C D >>~
|
||||||
~<< swap A B -- B A >>~
|
~<< swap A B -- B A >>~
|
||||||
~<< 2swap A B C D -- C D A B >>~
|
~<< 2swap A B C D -- C D A B >>~
|
||||||
~<< swapd A B C -- B A C >>~
|
~<< swapd A B C -- B A C >>~
|
||||||
~<< 2swapd A B C D E F -- C D A B E F >>~
|
~<< 2swapd A B C D E F -- C D A B E F >>~
|
||||||
~<< tuck A B -- B A B >>~
|
~<< transp A B C -- C B A >>~
|
||||||
~<< 2tuck A B C D -- C D A B C D >>~
|
~<< 2transp A B C D E F -- E F C D A B >>~
|
||||||
|
~<< tuck A B -- B A B >>~
|
||||||
|
~<< 2tuck A B C D -- C D A B C D >>~
|
||||||
|
|
||||||
~<< rdrop r:A -- >>~
|
~<< rdrop r:A -- >>~
|
||||||
~<< >r A -- r:A >>~
|
~<< >r A -- r:A >>~
|
||||||
|
@ -60,21 +62,21 @@
|
||||||
!!! Minimum amount of I/O words needed to be able to read other resources.
|
!!! Minimum amount of I/O words needed to be able to read other resources.
|
||||||
!!! Remaining I/O operations are defined in io.factor and parser.factor.
|
!!! Remaining I/O operations are defined in io.factor and parser.factor.
|
||||||
: <breader> (reader -- breader)
|
: <breader> (reader -- breader)
|
||||||
[ |java.io.Reader ] |java.io.BufferedReader jconstructor jnew ;
|
[ |java.io.Reader ] |java.io.BufferedReader jnew ;
|
||||||
|
|
||||||
: <ireader> (inputstream -- breader)
|
: <ireader> (inputstream -- breader)
|
||||||
[ |java.io.InputStream ] |java.io.InputStreamReader jconstructor jnew ;
|
[ |java.io.InputStream ] |java.io.InputStreamReader jnew ;
|
||||||
|
|
||||||
: <rreader> (path -- inputstream)
|
: <rreader> (path -- inputstream)
|
||||||
|factor.FactorInterpreter
|
|factor.FactorInterpreter
|
||||||
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jmethod jinvoke
|
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jinvoke
|
||||||
<ireader> <breader> ;
|
<ireader> <breader> ;
|
||||||
|
|
||||||
: parse* (filename reader -- list)
|
: parse* (filename reader -- list)
|
||||||
$dict
|
$dict
|
||||||
[ |java.lang.String |java.io.Reader |factor.FactorDictionary ]
|
[ |java.lang.String |java.io.Reader |factor.FactorDictionary ]
|
||||||
|factor.FactorParser jconstructor jnew
|
|factor.FactorParser jnew
|
||||||
[ ] |factor.FactorParser |parse jmethod jinvoke ;
|
[ ] |factor.FactorParser |parse jinvoke ;
|
||||||
|
|
||||||
: runResource (path --)
|
: runResource (path --)
|
||||||
dup <rreader> parse* call ;
|
dup <rreader> parse* call ;
|
||||||
|
@ -98,5 +100,20 @@
|
||||||
"/factor/stream.factor" runResource
|
"/factor/stream.factor" runResource
|
||||||
"/factor/strings.factor" runResource
|
"/factor/strings.factor" runResource
|
||||||
|
|
||||||
|
: cli-param ( param -- )
|
||||||
|
dup "no-" str-head? dup [
|
||||||
|
f s@ drop
|
||||||
|
] [
|
||||||
|
drop t s@
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: cli-arg ( argument -- boolean )
|
||||||
|
"-" str-head? [ cli-param ] when* ;
|
||||||
|
|
||||||
|
$args [ cli-arg ] each
|
||||||
|
|
||||||
|
! Compile all words now
|
||||||
|
$compile [ compileAll ] when
|
||||||
|
|
||||||
! If we're run stand-alone, start the interpreter in the current tty.
|
! If we're run stand-alone, start the interpreter in the current tty.
|
||||||
$interactive [ initialInterpreterLoop ] when
|
$interactive [ initialInterpreterLoop ] when
|
||||||
|
|
|
@ -90,18 +90,20 @@
|
||||||
! [ [ condition 1 ] [ code 1 ]
|
! [ [ condition 1 ] [ code 1 ]
|
||||||
! [ condition 2 ] [ code 2 ]
|
! [ condition 2 ] [ code 2 ]
|
||||||
! ... ]
|
! ... ]
|
||||||
! Each condition is evaluated in turn. If it returns true, the code
|
! Each condition is evaluated in turn. If it returns true,
|
||||||
! is evaluated. If it returns false, the next condition is checked.
|
! the code is evaluated. If it returns false, the next
|
||||||
[
|
! condition is checked. Before evaluating each condition,
|
||||||
uncons >r
|
! the top of the stack is duplicated. After the last
|
||||||
call
|
! condition is evaluated, the top of the stack is popped.
|
||||||
r>
|
dup [
|
||||||
swap [
|
uncons [ over [ call ] dip ] dip rot [
|
||||||
car call
|
car call
|
||||||
] [
|
] [
|
||||||
cdr cond
|
cdr cond
|
||||||
] ifte
|
] ifte
|
||||||
] when* ;
|
] [
|
||||||
|
2drop
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
: dip (a [ b ] -- b a)
|
: dip (a [ b ] -- b a)
|
||||||
! Calls b as if b was not even present on the stack -- b has no way of
|
! Calls b as if b was not even present on the stack -- b has no way of
|
||||||
|
@ -122,14 +124,7 @@
|
||||||
: each ([ list ] [ code ] --)
|
: each ([ list ] [ code ] --)
|
||||||
! Applies the code to each element of the list.
|
! Applies the code to each element of the list.
|
||||||
over [
|
over [
|
||||||
>r
|
[ uncons ] dip tuck [ call ] 2dip each
|
||||||
uncons
|
|
||||||
r>
|
|
||||||
tuck
|
|
||||||
2>r
|
|
||||||
call
|
|
||||||
2r>
|
|
||||||
each
|
|
||||||
] [
|
] [
|
||||||
2drop
|
2drop
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
@ -143,6 +138,9 @@
|
||||||
call
|
call
|
||||||
unstack ;
|
unstack ;
|
||||||
|
|
||||||
|
: ifte (cond [if true] [if false] --)
|
||||||
|
? call ;
|
||||||
|
|
||||||
: interleave ( X list -- ... )
|
: interleave ( X list -- ... )
|
||||||
! Evaluate each element of the list with X on top of the
|
! Evaluate each element of the list with X on top of the
|
||||||
! stack.
|
! stack.
|
||||||
|
@ -152,9 +150,6 @@
|
||||||
2drop
|
2drop
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: ifte (cond [if true] [if false] --)
|
|
||||||
? call ;
|
|
||||||
|
|
||||||
: linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- )
|
: linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- )
|
||||||
! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse,
|
! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse,
|
||||||
! and evaluate R2. This combinator is similar to the linrec combinator in
|
! and evaluate R2. This combinator is similar to the linrec combinator in
|
||||||
|
@ -168,13 +163,10 @@
|
||||||
r> call
|
r> call
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: map ([ items ] [ initial ] [ code ] -- [ mapping ])
|
: map ( [ items ] [ code ] -- [ mapping ] )
|
||||||
! Applies the code to each item, returns a list that begins with the initial
|
! Applies the code to each item, returns a list that
|
||||||
! list and contains the result of each application.
|
! contains the result of each application.
|
||||||
swapd 2list append
|
2list restack each unstack ;
|
||||||
restack
|
|
||||||
each
|
|
||||||
unstack ;
|
|
||||||
|
|
||||||
: push ([ a b c ... ] -- a b c ...)
|
: push ([ a b c ... ] -- a b c ...)
|
||||||
! Pushes values onto the stack literally (even if they are words).
|
! Pushes values onto the stack literally (even if they are words).
|
||||||
|
|
|
@ -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;
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -25,43 +25,75 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
! Undefined words's def field is equal to this.
|
: asm ( word -- assembly )
|
||||||
"factor.FactorMissingDefinition" "INSTANCE" jfield jvarStatic$ @undefinedWord
|
|
||||||
|
|
||||||
: asm. (word -- assembly)
|
|
||||||
! Prints JVM bytecode disassembly of the given word.
|
! Prints JVM bytecode disassembly of the given word.
|
||||||
worddef [ $asm ] bind dup [
|
worddef compiled? dup [
|
||||||
print
|
print
|
||||||
] [
|
] [
|
||||||
drop "Not a compiled word." print
|
drop "Not a compiled word." print
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: word? (obj -- boolean)
|
: compile* ( word -- )
|
||||||
"factor.FactorWord" is ;
|
$interpreter swap
|
||||||
|
[ "factor.FactorInterpreter" ] "factor.FactorWord" "compile"
|
||||||
|
jinvoke ;
|
||||||
|
|
||||||
: str>word ("word" -- word)
|
: compile ( word -- )
|
||||||
! Returns the top of the stack if it already been interned.
|
dup worddef compiled? [
|
||||||
dup word? [
|
drop
|
||||||
$dict [ "java.lang.String" ] "factor.FactorDictionary" "intern"
|
] [
|
||||||
jmethod jinvoke
|
intern compile*
|
||||||
] unless ;
|
] ifte ;
|
||||||
|
|
||||||
: worddef? (obj -- boolean)
|
: compileAll ( -- )
|
||||||
"factor.FactorWordDefinition" is ;
|
"Compiling..." write
|
||||||
|
words [ compile ] each
|
||||||
|
" done" print ;
|
||||||
|
|
||||||
|
: compiled? ( obj -- boolean )
|
||||||
|
[ $asm ] bind ;
|
||||||
|
|
||||||
: compound? (obj -- boolean)
|
: compound? (obj -- boolean)
|
||||||
"factor.FactorCompoundDefinition" is ;
|
"factor.FactorCompoundDefinition" is ;
|
||||||
|
|
||||||
|
: missing>f ( word -- word/f )
|
||||||
|
! Is it the missing word placeholder? Then push f.
|
||||||
|
dup undefined? [ drop f ] when ;
|
||||||
|
|
||||||
: shuffle? (obj -- boolean)
|
: shuffle? (obj -- boolean)
|
||||||
"factor.FactorShuffleDefinition" is ;
|
"factor.FactorShuffleDefinition" is ;
|
||||||
|
|
||||||
: worddef (word -- worddef)
|
: intern ("word" -- word)
|
||||||
str>word
|
! Returns the top of the stack if it already been interned.
|
||||||
! Get the 'def' field
|
dup word? [
|
||||||
"factor.FactorWord" "def" jfield jvar$
|
$dict [ "java.lang.String" ]
|
||||||
! Is it equal to the missing word placeholder? Then push f.
|
"factor.FactorDictionary" "intern"
|
||||||
dup $undefinedWord = [ drop f ] when ;
|
jinvoke
|
||||||
|
] unless ;
|
||||||
|
|
||||||
|
: undefined? ( obj -- boolean )
|
||||||
|
"factor.FactorMissingDefinition" is ;
|
||||||
|
|
||||||
|
: word? (obj -- boolean)
|
||||||
|
"factor.FactorWord" is ;
|
||||||
|
|
||||||
|
: word ( -- word )
|
||||||
|
! Pushes most recently defined word.
|
||||||
|
$dict "factor.FactorDictionary" "last" jvar$ ;
|
||||||
|
|
||||||
|
: worddef? (obj -- boolean)
|
||||||
|
"factor.FactorWordDefinition" is ;
|
||||||
|
|
||||||
|
: worddef ( word -- worddef )
|
||||||
|
intern
|
||||||
|
"factor.FactorWord" "def" jvar$
|
||||||
|
missing>f ;
|
||||||
|
|
||||||
|
: worddefUncompiled ( word -- worddef )
|
||||||
|
intern
|
||||||
|
"factor.FactorWord" "uncompiled" jvar$
|
||||||
|
missing>f ;
|
||||||
|
|
||||||
: words (-- list)
|
: words (-- list)
|
||||||
! Pushes a list of all defined words.
|
! Pushes a list of all defined words.
|
||||||
$dict [ ] "factor.FactorDictionary" "toWordList" jmethod jinvoke ;
|
$dict [ ] "factor.FactorDictionary" "toWordList" jinvoke ;
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
! - implement an LSP that does an "apropos" search
|
! - implement an LSP that does an "apropos" search
|
||||||
|
|
||||||
: httpdGetPath ( request -- file )
|
: httpdGetPath ( request -- file )
|
||||||
dup ".*\\.\\.*" matches [
|
dup ".*\\.\\.*" re-matches [
|
||||||
f
|
f
|
||||||
] [
|
] [
|
||||||
dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when
|
dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when
|
||||||
|
@ -58,12 +58,12 @@
|
||||||
|
|
||||||
: httpdFiletype (filename -- mime-type)
|
: httpdFiletype (filename -- mime-type)
|
||||||
[
|
[
|
||||||
[ dup ".*\.gif" matches ] [ drop "image/gif" ]
|
[ ".*\.gif" re-matches ] [ drop "image/gif" ]
|
||||||
[ dup ".*\.png" matches ] [ drop "image/png" ]
|
[ ".*\.png" re-matches ] [ drop "image/png" ]
|
||||||
[ dup ".*\.html" matches ] [ drop "text/html" ]
|
[ ".*\.html" re-matches ] [ drop "text/html" ]
|
||||||
[ dup ".*\.txt" matches ] [ drop "text/plain" ]
|
[ ".*\.txt" re-matches ] [ drop "text/plain" ]
|
||||||
[ dup ".*\.lsd" matches ] [ drop "text/plain" ]
|
[ ".*\.lsd" re-matches ] [ drop "text/plain" ]
|
||||||
[ t ] [ drop "application/octet-stream" ]
|
[ t ] [ drop "application/octet-stream" ]
|
||||||
] cond ;
|
] cond ;
|
||||||
|
|
||||||
: httpdUriToPath (uri -- path)
|
: httpdUriToPath (uri -- path)
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
dup directory? [
|
dup directory? [
|
||||||
httpdServeDirectory
|
httpdServeDirectory
|
||||||
] [
|
] [
|
||||||
dup ".*\.lhtml" matches [
|
dup ".*\.lhtml" re-matches [
|
||||||
httpdServeScript
|
httpdServeScript
|
||||||
] [
|
] [
|
||||||
httpdServeFile
|
httpdServeFile
|
||||||
|
|
|
@ -29,13 +29,13 @@
|
||||||
"java.lang.Throwable" is ;
|
"java.lang.Throwable" is ;
|
||||||
|
|
||||||
: printStackTrace (exception --)
|
: printStackTrace (exception --)
|
||||||
[ ] "java.lang.Throwable" "printStackTrace" jmethod jinvoke ;
|
[ ] "java.lang.Throwable" "printStackTrace" jinvoke ;
|
||||||
|
|
||||||
: exception. (exception --)
|
: exception. (exception --)
|
||||||
! If this is an Factor exception, just print the message, otherwise print
|
! If this is an Factor exception, just print the message, otherwise print
|
||||||
! the entire exception as a string.
|
! the entire exception as a string.
|
||||||
dup "factor.FactorException" is [
|
dup "factor.FactorException" is [
|
||||||
[ ] "java.lang.Throwable" "getMessage" jmethod jinvoke
|
[ ] "java.lang.Throwable" "getMessage" jinvoke
|
||||||
] [
|
] [
|
||||||
>str
|
>str
|
||||||
] ifte print ;
|
] ifte print ;
|
||||||
|
@ -53,6 +53,7 @@
|
||||||
":g continues execution (but expect another error)." print
|
":g continues execution (but expect another error)." print
|
||||||
"" print
|
"" print
|
||||||
"ERROR: " write exception.
|
"ERROR: " write exception.
|
||||||
|
:w
|
||||||
callstack$ @errorCallStack
|
callstack$ @errorCallStack
|
||||||
[
|
[
|
||||||
@errorContinuation
|
@errorContinuation
|
||||||
|
@ -131,9 +132,11 @@
|
||||||
words [ . ] each ;
|
words [ . ] each ;
|
||||||
|
|
||||||
: see (word --)
|
: see (word --)
|
||||||
dup worddef [
|
dup worddefUncompiled [
|
||||||
(word -- worddef word)
|
(word -- worddef word)
|
||||||
dup [ worddef dup shuffle? "~<< " ": " ? write ] dip
|
dup [
|
||||||
|
worddefUncompiled dup shuffle? "~<< " ": " ? write
|
||||||
|
] dip
|
||||||
|
|
||||||
(worddef word -- worddef)
|
(worddef word -- worddef)
|
||||||
write "\n " write
|
write "\n " write
|
||||||
|
@ -153,6 +156,22 @@
|
||||||
! Prints the contents of the data stack
|
! Prints the contents of the data stack
|
||||||
datastack$ . ;
|
datastack$ . ;
|
||||||
|
|
||||||
|
: stats ( -- )
|
||||||
|
"Cons: " write
|
||||||
|
"factor.Cons" "COUNT" jvar-static$ .
|
||||||
|
"Words: " write
|
||||||
|
words length .
|
||||||
|
"Compiled: " write
|
||||||
|
words [ worddef compiled? ] subset length . ;
|
||||||
|
|
||||||
|
: gc ( -- )
|
||||||
|
[ ] "java.lang.System" "gc" jinvoke-static ;
|
||||||
|
|
||||||
|
: balance ( code -- effect )
|
||||||
|
! Push stack effect of the given code quotation.
|
||||||
|
[ "factor.Cons" ] "factor.compiler.StackEffect"
|
||||||
|
"getStackEffect" jinvoke-static ;
|
||||||
|
|
||||||
: help
|
: help
|
||||||
"" print
|
"" print
|
||||||
"= Dynamic, interpreted, stack-based scripting language" print
|
"= Dynamic, interpreted, stack-based scripting language" print
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
! $Id$
|
! $Id$
|
||||||
!
|
!
|
||||||
! Copyright (C) 2003 Slava Pestov.
|
! Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
!
|
!
|
||||||
! Redistribution and use in source and binary forms, with or without
|
! Redistribution and use in source and binary forms, with or without
|
||||||
! modification, are permitted provided that the following conditions are met:
|
! modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -31,8 +31,8 @@
|
||||||
: 2rlist (a b -- [ b a ])
|
: 2rlist (a b -- [ b a ])
|
||||||
swap unit cons ;
|
swap unit cons ;
|
||||||
|
|
||||||
: append ([ list1 ] [ list2 ] -- [ list1 list2 ])
|
: append ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
|
||||||
swap rappend ;
|
over [ [ uncons ] dip append cons ] [ nip ] ifte ;
|
||||||
|
|
||||||
: add ([ list1 ] elem -- [ list1 elem ])
|
: add ([ list1 ] elem -- [ list1 elem ])
|
||||||
unit append ;
|
unit append ;
|
||||||
|
@ -42,7 +42,8 @@
|
||||||
dup [ $ swap append ] dip @ ;
|
dup [ $ swap append ] dip @ ;
|
||||||
|
|
||||||
: array>list ( array -- list )
|
: array>list ( array -- list )
|
||||||
[ "[Ljava.lang.Object;" ] "factor.FactorList" "fromArray" jmethod jinvokeStatic ;
|
[ [ "java.lang.Object" ] ] "factor.Cons" "fromArray"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
: add@ (elem variable --)
|
: add@ (elem variable --)
|
||||||
! Adds the element to the end of the list stored in the given variable.
|
! Adds the element to the end of the list stored in the given variable.
|
||||||
|
@ -63,10 +64,10 @@
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: car ([ car , cdr ] -- car)
|
: car ([ car , cdr ] -- car)
|
||||||
|factor.FactorList |car jfield jvar$ ;
|
|factor.Cons |car jvar$ ;
|
||||||
|
|
||||||
: cdr ([ car , cdr ] -- cdr)
|
: cdr ([ car , cdr ] -- cdr)
|
||||||
|factor.FactorList |cdr jfield jvar$ ;
|
|factor.Cons |cdr jvar$ ;
|
||||||
|
|
||||||
: caar (list -- caar)
|
: caar (list -- caar)
|
||||||
car car ;
|
car car ;
|
||||||
|
@ -83,10 +84,10 @@
|
||||||
: cloneList (list -- list)
|
: cloneList (list -- list)
|
||||||
! Returns a new list where each element is a clone of the elements of
|
! Returns a new list where each element is a clone of the elements of
|
||||||
! the given list.
|
! the given list.
|
||||||
dup [ [ ] "factor.FactorList" "deepClone" jmethod jinvoke ] when ;
|
dup [ [ ] "factor.Cons" "deepClone" jinvoke ] when ;
|
||||||
|
|
||||||
: cons (car cdr -- [ car , cdr ])
|
: cons (car cdr -- [ car , cdr ])
|
||||||
[ |java.lang.Object |java.lang.Object ] |factor.FactorList jconstructor jnew ;
|
[ |java.lang.Object |java.lang.Object ] |factor.Cons jnew ;
|
||||||
|
|
||||||
: contains (elem list -- boolean)
|
: contains (elem list -- boolean)
|
||||||
dup [
|
dup [
|
||||||
|
@ -113,9 +114,13 @@
|
||||||
: get (list n -- list[n])
|
: get (list n -- list[n])
|
||||||
[ cdr ] times car ;
|
[ cdr ] times car ;
|
||||||
|
|
||||||
: last (list -- last)
|
: last* ( list -- last )
|
||||||
|
! Pushes last cons of the list.
|
||||||
|
[ dup cdr ] [ cdr ] while ;
|
||||||
|
|
||||||
|
: last ( list -- last )
|
||||||
! Pushes last element of the list.
|
! Pushes last element of the list.
|
||||||
[ dup cdr ] [ cdr ] while car ;
|
last* car ;
|
||||||
|
|
||||||
: length (list -- length)
|
: length (list -- length)
|
||||||
0 swap [ drop succ ] each ;
|
0 swap [ drop succ ] each ;
|
||||||
|
@ -126,18 +131,27 @@
|
||||||
: list? (list -- boolean)
|
: list? (list -- boolean)
|
||||||
dup pair? [ cdr list? ] [ f ] ifte ;
|
dup pair? [ cdr list? ] [ f ] ifte ;
|
||||||
|
|
||||||
: pair? (list -- boolean)
|
: nappend ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
|
||||||
|factor.FactorList is ;
|
! Destructive on list1!
|
||||||
|
over [ last* rplacd ] when* ;
|
||||||
|
|
||||||
: rappend ([ list2 ] [ list1 ] -- [ list1 list2 ])
|
: pair? (list -- boolean)
|
||||||
[ [ |factor.FactorList ] |factor.FactorList |append jmethod jinvoke ] when* ;
|
|factor.Cons is ;
|
||||||
|
|
||||||
: reverse (list -- list)
|
: reverse (list -- list)
|
||||||
[ ] swap [ swons ] each ;
|
[ ] swap [ swons ] each ;
|
||||||
|
|
||||||
|
: rplaca ( A [ B , C ] -- [ A , C ] )
|
||||||
|
! Destructive!
|
||||||
|
"factor.Cons" "car" jvar@ ;
|
||||||
|
|
||||||
|
: rplacd ( A [ B , C ] -- [ B , A ] )
|
||||||
|
! Destructive!
|
||||||
|
"factor.Cons" "cdr" jvar@ ;
|
||||||
|
|
||||||
: swons (cdr car -- [ car , cdr ])
|
: swons (cdr car -- [ car , cdr ])
|
||||||
swap [ |java.lang.Object |java.lang.Object ]
|
swap [ |java.lang.Object |java.lang.Object ]
|
||||||
|factor.FactorList jconstructor jnew ;
|
|factor.Cons jnew ;
|
||||||
|
|
||||||
: uncons ([ car , cdr ] -- car cdr)
|
: uncons ([ car , cdr ] -- car cdr)
|
||||||
dup car swap cdr ;
|
dup car swap cdr ;
|
||||||
|
|
|
@ -35,76 +35,64 @@
|
||||||
"java.lang.Integer" is ;
|
"java.lang.Integer" is ;
|
||||||
|
|
||||||
: >fixnum (num -- fixnum)
|
: >fixnum (num -- fixnum)
|
||||||
[ ] "java.lang.Number" "intValue" jmethod jinvoke ;
|
[ ] "java.lang.Number" "intValue" jinvoke ;
|
||||||
|
|
||||||
: bignum? (obj -- boolean)
|
: bignum? (obj -- boolean)
|
||||||
"java.math.BigInteger" is ;
|
"java.math.BigInteger" is ;
|
||||||
|
|
||||||
: >bignum (num -- bignum)
|
: >bignum (num -- bignum)
|
||||||
[ ] "java.lang.Number" "longValue" jmethod jinvoke
|
[ ] "java.lang.Number" "longValue" jinvoke
|
||||||
[ "long" ] "java.math.BigInteger" "valueOf" jmethod jinvokeStatic ;
|
[ "long" ] "java.math.BigInteger" "valueOf" jinvoke-static ;
|
||||||
|
|
||||||
: realnum? (obj -- boolean)
|
: realnum? (obj -- boolean)
|
||||||
dup "java.lang.Float" is
|
dup "java.lang.Float" is
|
||||||
swap "java.lang.Double" is or ;
|
swap "java.lang.Double" is or ;
|
||||||
|
|
||||||
: >realnum (num -- realnum)
|
: >realnum (num -- realnum)
|
||||||
[ ] "java.lang.Number" "doubleValue" jmethod jinvoke ;
|
[ ] "java.lang.Number" "doubleValue" jinvoke ;
|
||||||
|
|
||||||
: ratio? (obj -- boolean)
|
: ratio? (obj -- boolean)
|
||||||
"factor.FactorRatio" is ;
|
"factor.FactorRatio" is ;
|
||||||
|
|
||||||
: + (a b -- a+b)
|
: + (a b -- a+b)
|
||||||
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "add"
|
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "add"
|
||||||
jmethod jinvokeStatic ;
|
jinvoke-static ;
|
||||||
|
|
||||||
: +@ (num var --)
|
: +@ (num var --)
|
||||||
dup [ $ + ] dip @ ;
|
dup [ $ + ] dip @ ;
|
||||||
|
|
||||||
: - (a b -- a-b)
|
: - (a b -- a-b)
|
||||||
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "subtract"
|
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "subtract"
|
||||||
jmethod jinvokeStatic ;
|
jinvoke-static ;
|
||||||
|
|
||||||
: -@ (num var --)
|
: -@ (num var --)
|
||||||
dup [ $ -- ] dip @ ;
|
dup [ $ swap - ] dip @ ;
|
||||||
|
|
||||||
: -- (a b -- b-a)
|
|
||||||
swap - ;
|
|
||||||
|
|
||||||
: --@ (var num --)
|
|
||||||
[ dup $ - ] dip s@ ;
|
|
||||||
|
|
||||||
: * (a b -- a*b)
|
: * (a b -- a*b)
|
||||||
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "multiply"
|
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "multiply"
|
||||||
jmethod jinvokeStatic ;
|
jinvoke-static ;
|
||||||
|
|
||||||
: *@ (num var --)
|
: *@ (num var --)
|
||||||
dup [ $ * ] dip @ ;
|
dup [ $ * ] dip @ ;
|
||||||
|
|
||||||
: / (a b -- a/b)
|
: / (a b -- a/b)
|
||||||
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "divide"
|
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "divide"
|
||||||
jmethod jinvokeStatic ;
|
jinvoke-static ;
|
||||||
|
|
||||||
: /@ (num var --)
|
: /@ (num var --)
|
||||||
dup [ $ / ] dip @ ;
|
dup [ $ / ] dip @ ;
|
||||||
|
|
||||||
: // (a b -- b/a)
|
|
||||||
swap / ;
|
|
||||||
|
|
||||||
: //@ (num var --)
|
|
||||||
[ dup $ / ] dip s@ ;
|
|
||||||
|
|
||||||
: > (a b -- boolean)
|
: > (a b -- boolean)
|
||||||
[ "float" "float" ] "factor.FactorMath" "greater" jmethod jinvokeStatic ;
|
[ "float" "float" ] "factor.FactorMath" "greater" jinvoke-static ;
|
||||||
|
|
||||||
: >= (a b -- boolean)
|
: >= (a b -- boolean)
|
||||||
[ "float" "float" ] "factor.FactorMath" "greaterEqual" jmethod jinvokeStatic ;
|
[ "float" "float" ] "factor.FactorMath" "greaterEqual" jinvoke-static ;
|
||||||
|
|
||||||
: < (a b -- boolean)
|
: < (a b -- boolean)
|
||||||
[ "float" "float" ] "factor.FactorMath" "less" jmethod jinvokeStatic ;
|
[ "float" "float" ] "factor.FactorMath" "less" jinvoke-static ;
|
||||||
|
|
||||||
: <= (a b -- boolean)
|
: <= (a b -- boolean)
|
||||||
[ "float" "float" ] "factor.FactorMath" "lessEqual" jmethod jinvokeStatic ;
|
[ "float" "float" ] "factor.FactorMath" "lessEqual" jinvoke-static ;
|
||||||
|
|
||||||
: and (a b -- a&b)
|
: and (a b -- a&b)
|
||||||
f ? ;
|
f ? ;
|
||||||
|
@ -126,9 +114,15 @@
|
||||||
: not@ (boolean -- boolean)
|
: not@ (boolean -- boolean)
|
||||||
dup $ not s@ ;
|
dup $ not s@ ;
|
||||||
|
|
||||||
|
: pow ( x y -- x^y )
|
||||||
|
[ "double" "double" ] "java.lang.Math" "pow" jinvoke-static ;
|
||||||
|
|
||||||
: pred (n -- n-1)
|
: pred (n -- n-1)
|
||||||
1 - ;
|
1 - ;
|
||||||
|
|
||||||
|
: round ( x y -- x^y )
|
||||||
|
[ "double" "double" ] "java.lang.Math" "pow" jinvoke-static ;
|
||||||
|
|
||||||
: succ (n -- nsucc)
|
: succ (n -- nsucc)
|
||||||
1 + ;
|
1 + ;
|
||||||
|
|
||||||
|
@ -139,13 +133,13 @@
|
||||||
t swap ? ;
|
t swap ? ;
|
||||||
|
|
||||||
: recip (x -- 1/x)
|
: recip (x -- 1/x)
|
||||||
1 // ;
|
1 swap / ;
|
||||||
|
|
||||||
: sq (x -- x^2)
|
: sq (x -- x^2)
|
||||||
dup * ;
|
dup * ;
|
||||||
|
|
||||||
: sqrt (x -- sqrt x)
|
: sqrt (x -- sqrt x)
|
||||||
[ "double" ] "java.lang.Math" "sqrt" jmethod jinvokeStatic ;
|
[ "double" ] "java.lang.Math" "sqrt" jinvoke-static ;
|
||||||
|
|
||||||
: succ@ (var --)
|
: succ@ (var --)
|
||||||
dup $ 1 + s@ ;
|
dup $ 1 + s@ ;
|
||||||
|
|
|
@ -25,30 +25,28 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
: >str (obj -- string)
|
|
||||||
! Returns the Java string representation of this object.
|
|
||||||
[ ] "java.lang.Object" "toString" jmethod jinvoke ;
|
|
||||||
|
|
||||||
: = (a b -- boolean)
|
: = (a b -- boolean)
|
||||||
! Returns true if a = b.
|
! Returns true if a = b.
|
||||||
[ "java.lang.Object" "java.lang.Object" ]
|
[ "java.lang.Object" "java.lang.Object" ]
|
||||||
"factor.FactorLib" "equal" jmethod jinvokeStatic ;
|
"factor.FactorLib" "equal" jinvoke-static ;
|
||||||
|
|
||||||
: clone (obj -- obj)
|
: clone (obj -- obj)
|
||||||
[ ] "factor.PublicCloneable" "clone" jmethod jinvoke ;
|
[ ] "factor.PublicCloneable" "clone" jinvoke ;
|
||||||
|
|
||||||
: cloneArray (obj -- obj)
|
: cloneArray (obj -- obj)
|
||||||
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "cloneArray"
|
[ [ "java.lang.Object" ] ]
|
||||||
jmethod jinvokeStatic ;
|
"factor.FactorLib" "cloneArray"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
: deepCloneArray (obj -- obj)
|
: deepCloneArray (obj -- obj)
|
||||||
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "deepCloneArray"
|
[ [ "java.lang.Object" ] ]
|
||||||
jmethod jinvokeStatic ;
|
"factor.FactorLib" "deepCloneArray"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
: is (obj class -- boolean)
|
: is (obj class -- boolean)
|
||||||
! Like "instanceof" in Java.
|
! Like "instanceof" in Java.
|
||||||
[ "java.lang.Object" ] "java.lang.Class" "isInstance"
|
[ "java.lang.Object" ] "java.lang.Class" "isInstance"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: not= (a b -- boolean)
|
: not= (a b -- boolean)
|
||||||
= not ;
|
= not ;
|
||||||
|
@ -57,36 +55,31 @@
|
||||||
! Returns true if a = c, b = d.
|
! Returns true if a = c, b = d.
|
||||||
swapd = [ = ] dip and ;
|
swapd = [ = ] dip and ;
|
||||||
|
|
||||||
: ? (cond obj1 obj2 -- obj)
|
|
||||||
! Pushes obj1 if cond is true, obj2 if cond is false.
|
|
||||||
[ "boolean" "java.lang.Object" "java.lang.Object" ]
|
|
||||||
"factor.FactorLib" "branch2" jmethod jinvokeStatic ;
|
|
||||||
|
|
||||||
: >=< (x y obj1 obj2 obj3 -- obj)
|
: >=< (x y obj1 obj2 obj3 -- obj)
|
||||||
! If x > y, pushes obj1, if x = y, pushes obj2, else obj3.
|
! If x > y, pushes obj1, if x = y, pushes obj2, else obj3.
|
||||||
[
|
[
|
||||||
"float" "float"
|
"float" "float"
|
||||||
"java.lang.Object" "java.lang.Object" "java.lang.Object"
|
"java.lang.Object" "java.lang.Object" "java.lang.Object"
|
||||||
]
|
]
|
||||||
"factor.FactorLib" "branch3" jmethod jinvokeStatic ;
|
"factor.FactorLib" "branch3" jinvoke-static ;
|
||||||
|
|
||||||
: error (msg --)
|
: error (msg --)
|
||||||
[ "java.lang.String" ] "factor.FactorLib" "error" jmethod jinvokeStatic ;
|
[ "java.lang.String" ] "factor.FactorLib" "error" jinvoke-static ;
|
||||||
|
|
||||||
: exit* (code --)
|
: exit* (code --)
|
||||||
[ |int ] |java.lang.System |exit jmethod jinvokeStatic ;
|
[ |int ] |java.lang.System |exit jinvoke-static ;
|
||||||
|
|
||||||
: exit (--)
|
: exit (--)
|
||||||
0 exit* ;
|
0 exit* ;
|
||||||
|
|
||||||
: millis (-- millis)
|
: millis (-- millis)
|
||||||
! Pushes the current time, in milliseconds.
|
! Pushes the current time, in milliseconds.
|
||||||
[ ] |java.lang.System |currentTimeMillis jmethod jinvokeStatic
|
[ ] |java.lang.System |currentTimeMillis jinvoke-static
|
||||||
>bignum ;
|
>bignum ;
|
||||||
|
|
||||||
: stack>list (stack -- list)
|
: stack>list (stack -- list)
|
||||||
! Turns a callstack or datastack object into a list.
|
! Turns a callstack or datastack object into a list.
|
||||||
[ ] "factor.FactorArrayStack" "toList" jmethod jinvoke ;
|
[ ] "factor.FactorArrayStack" "toList" jinvoke ;
|
||||||
|
|
||||||
: time (code --)
|
: time (code --)
|
||||||
! Evaluates the given code and prints the time taken to execute it.
|
! Evaluates the given code and prints the time taken to execute it.
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
: s@ ( variable value -- )
|
||||||
|
swap @ ;
|
||||||
|
|
||||||
: lazy (var [ a ] -- value)
|
: lazy (var [ a ] -- value)
|
||||||
! If the value of the variable is f, set the value to the result of
|
! If the value of the variable is f, set the value to the result of
|
||||||
! evaluating [ a ].
|
! evaluating [ a ].
|
||||||
|
@ -35,12 +38,12 @@
|
||||||
|
|
||||||
: <namespace> (-- namespace)
|
: <namespace> (-- namespace)
|
||||||
$namespace [ |factor.FactorNamespace ] |factor.FactorNamespace
|
$namespace [ |factor.FactorNamespace ] |factor.FactorNamespace
|
||||||
jconstructor jnew ;
|
jnew ;
|
||||||
|
|
||||||
: <objnamespace> ( object -- namespace )
|
: <objnamespace> ( object -- namespace )
|
||||||
$namespace swap
|
$namespace swap
|
||||||
[ "factor.FactorNamespace" "java.lang.Object" ]
|
[ "factor.FactorNamespace" "java.lang.Object" ]
|
||||||
"factor.FactorNamespace" jconstructor jnew ;
|
"factor.FactorNamespace" jnew ;
|
||||||
|
|
||||||
: extend (object code -- object)
|
: extend (object code -- object)
|
||||||
! Used in code like this:
|
! Used in code like this:
|
||||||
|
@ -52,12 +55,12 @@
|
||||||
|
|
||||||
: import (class pairs --)
|
: import (class pairs --)
|
||||||
! Import some static variables from a Java class into the current namespace.
|
! Import some static variables from a Java class into the current namespace.
|
||||||
$namespace [ |java.lang.String |factor.FactorList ]
|
$namespace [ |java.lang.String |factor.Cons ]
|
||||||
|factor.FactorNamespace |importVars
|
|factor.FactorNamespace |importVars
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: vars (-- list)
|
: vars (-- list)
|
||||||
$namespace [ ] |factor.FactorNamespace |toVarList jmethod jinvoke ;
|
$namespace [ ] |factor.FactorNamespace |toVarList jinvoke ;
|
||||||
|
|
||||||
: uvar? (name --)
|
: uvar? (name --)
|
||||||
[ "namespace" "parent" ] contains not ;
|
[ "namespace" "parent" ] contains not ;
|
||||||
|
|
|
@ -28,21 +28,21 @@
|
||||||
: <server> ( port -- stream )
|
: <server> ( port -- stream )
|
||||||
! Starts listening on localhost:port. Returns a stream that you can close
|
! Starts listening on localhost:port. Returns a stream that you can close
|
||||||
! with fclose. No other stream operations are supported.
|
! with fclose. No other stream operations are supported.
|
||||||
[ "int" ] "java.net.ServerSocket" jconstructor jnew
|
[ "int" ] "java.net.ServerSocket" jnew
|
||||||
<stream> [
|
<stream> [
|
||||||
@socket
|
@socket
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
[
|
[
|
||||||
$socket [ ] "java.net.ServerSocket" "close" jmethod jinvoke
|
$socket [ ] "java.net.ServerSocket" "close" jinvoke
|
||||||
] @fclose
|
] @fclose
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
: <socketstream> ( socket -- stream )
|
: <socketstream> ( socket -- stream )
|
||||||
! Wraps a socket inside a bytestream.
|
! Wraps a socket inside a bytestream.
|
||||||
dup
|
dup
|
||||||
[ [ ] "java.net.Socket" "getInputStream" jmethod jinvoke ]
|
[ [ ] "java.net.Socket" "getInputStream" jinvoke ]
|
||||||
[ [ ] "java.net.Socket" "getOutputStream" jmethod jinvoke ]
|
[ [ ] "java.net.Socket" "getOutputStream" jinvoke ]
|
||||||
cleave
|
cleave
|
||||||
<bytestream> [
|
<bytestream> [
|
||||||
@socket
|
@socket
|
||||||
|
@ -50,11 +50,11 @@
|
||||||
! We "extend" bytestream's fclose.
|
! We "extend" bytestream's fclose.
|
||||||
( -- )
|
( -- )
|
||||||
$fclose [
|
$fclose [
|
||||||
$socket [ ] "java.net.Socket" "close" jmethod jinvoke
|
$socket [ ] "java.net.Socket" "close" jinvoke
|
||||||
] append @fclose
|
] append @fclose
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
: accept ( server -- client )
|
: accept ( server -- client )
|
||||||
! Accept a connection from a server socket.
|
! Accept a connection from a server socket.
|
||||||
[ $socket ] bind
|
[ $socket ] bind
|
||||||
[ ] "java.net.ServerSocket" "accept" jmethod jinvoke <socketstream> ;
|
[ ] "java.net.ServerSocket" "accept" jinvoke <socketstream> ;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
: unparse (X -- "X")
|
: unparse (X -- "X")
|
||||||
[ |java.lang.Object ] |factor.FactorJava |factorTypeToString
|
[ |java.lang.Object ] |factor.FactorJava |factorTypeToString
|
||||||
jmethod jinvokeStatic ;
|
jinvoke-static ;
|
||||||
|
|
||||||
: . (expr --)
|
: . (expr --)
|
||||||
unparse print ;
|
unparse print ;
|
||||||
|
|
|
@ -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;
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
} */ //}}}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
} //}}}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
! $Id$
|
! $Id$
|
||||||
!
|
!
|
||||||
! Copyright (C) 2003 Slava Pestov.
|
! Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
!
|
!
|
||||||
! Redistribution and use in source and binary forms, with or without
|
! Redistribution and use in source and binary forms, with or without
|
||||||
! modification, are permitted provided that the following conditions are met:
|
! modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -25,64 +25,76 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
: randomAngle (-- theta)
|
: random-angle ( -- theta )
|
||||||
[ ] "factor.FactorMath" "randomAngle" jmethod jinvokeStatic ;
|
[ ] "factor.FactorMath"
|
||||||
|
"randomAngle" jinvoke-static ;
|
||||||
|
|
||||||
: randomBoolean (-- boolean)
|
: random-boolean ( -- boolean )
|
||||||
[ ] "factor.FactorMath" "randomBoolean" jmethod jinvokeStatic ;
|
[ ] "factor.FactorMath"
|
||||||
|
"randomBoolean" jinvoke-static ;
|
||||||
|
|
||||||
: randomInt (min max -- random)
|
: random-digit ( -- digit )
|
||||||
[ "int" "int" ] "factor.FactorMath" "randomInt" jmethod jinvokeStatic ;
|
0 9 random-int ;
|
||||||
|
|
||||||
: randomSymmetricInt (max -- random)
|
: random-float ( min max scale -- random )
|
||||||
|
[ "int" "int" "float" ] "factor.FactorMath"
|
||||||
|
"randomFloat" jinvoke-static ;
|
||||||
|
|
||||||
|
: random-int ( min max -- random )
|
||||||
|
[ "int" "int" ] "factor.FactorMath"
|
||||||
|
"randomInt" jinvoke-static ;
|
||||||
|
|
||||||
|
: random-symmetric-int ( max -- random )
|
||||||
! Return a random integer between -max and max.
|
! Return a random integer between -max and max.
|
||||||
dup neg swap randomInt ;
|
dup neg swap random-int ;
|
||||||
|
|
||||||
: chance (n -- boolean)
|
: chance ( n -- boolean )
|
||||||
! Returns true with a 1/n probability, false with a (n-1)/n probability.
|
! Returns true with a 1/n probability, false with a (n-1)/n
|
||||||
1 swap randomInt 1 = ;
|
|
||||||
|
|
||||||
: randomElement (list -- random)
|
|
||||||
! Returns a random element from the given list.
|
|
||||||
dup length pred 0 swap randomInt get ;
|
|
||||||
|
|
||||||
: randomSubset (list -- list)
|
|
||||||
! Returns a random subset of the given list. Each item is chosen with a 50%
|
|
||||||
! probability.
|
! probability.
|
||||||
[ ] [ randomBoolean [ drop ] when ] map ;
|
1 swap random-int 1 = ;
|
||||||
|
|
||||||
: car+ (list -- sum)
|
: random-element ( list -- random )
|
||||||
|
! Returns a random element from the given list.
|
||||||
|
dup length pred 0 swap random-int get ;
|
||||||
|
|
||||||
|
: random-subset ( list -- list )
|
||||||
|
! Returns a random subset of the given list. Each item is
|
||||||
|
! chosen with a 50%
|
||||||
|
! probability.
|
||||||
|
[ random-boolean [ drop ] when ] map ;
|
||||||
|
|
||||||
|
: car+ ( list -- sum )
|
||||||
! Adds the car of each element of the given list.
|
! Adds the car of each element of the given list.
|
||||||
0 swap [ car + ] each ;
|
0 swap [ car + ] each ;
|
||||||
|
|
||||||
: randomProbability (list -- sum)
|
: random-probability ( list -- sum )
|
||||||
! Adds the car of each element of the given list, and returns a random
|
! Adds the car of each element of the given list, and
|
||||||
! number between 1 and this sum.
|
! returns a random number between 1 and this sum.
|
||||||
1 swap car+ randomInt ;
|
1 swap car+ random-int ;
|
||||||
|
|
||||||
: randomElementIter (list index -- elem)
|
: random-element-iter ( list index -- elem )
|
||||||
! Used by randomElement*. Do not call directly.
|
! Used by random-element*. Do not call directly.
|
||||||
[ unswons unswons ] dip (list elem probability index)
|
[ unswons unswons ] dip (list elem probability index)
|
||||||
-- (list elem index)
|
swap - (list elem index)
|
||||||
dup 0 <= [
|
dup 0 <= [
|
||||||
drop nip
|
drop nip
|
||||||
] [
|
] [
|
||||||
nip randomElementIter
|
nip random-element-iter
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: randomElement* (list -- elem)
|
: random-element* ( list -- elem )
|
||||||
! Returns a random element of the given list of comma pairs. The
|
! Returns a random element of the given list of comma pairs.
|
||||||
! car of each pair is a probability, the cdr is the item itself.
|
! The car of each pair is a probability, the cdr is the item
|
||||||
! Only the cdr of the comma pair is returned.
|
! itself. Only the cdr of the comma pair is returned.
|
||||||
dup 1 swap car+ randomInt randomElementIter ;
|
dup 1 swap car+ random-int random-element-iter ;
|
||||||
|
|
||||||
: randomSubset* (list -- list)
|
: random-subset* ( list -- list )
|
||||||
! Returns a random subset of the given list of comma pairs. The
|
! Returns a random subset of the given list of comma pairs.
|
||||||
! car of each pair is a probability, the cdr is the item itself.
|
! The car of each pair is a probability, the cdr is the item
|
||||||
! Only the cdr of the comma pair is returned.
|
! itself. Only the cdr of the comma pair is returned.
|
||||||
dup [ [ [ ] ] dip car+ ] dip ([ ] probabilitySum list)
|
dup [ [ [ ] ] dip car+ ] dip ([ ] probabilitySum list)
|
||||||
[
|
[
|
||||||
[ 1 over randomInt ] dip ([ ] probabilitySum probability elem)
|
[ 1 over random-int ] dip ([ ] probabilitySum probability elem)
|
||||||
uncons ([ ] probabilitySum probability elema elemd)
|
uncons ([ ] probabilitySum probability elema elemd)
|
||||||
-rot ([ ] probabilitySum elemd probability elema)
|
-rot ([ ] probabilitySum elemd probability elema)
|
||||||
> ([ ] probabilitySum elemd boolean)
|
> ([ ] probabilitySum elemd boolean)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
! $Id$
|
! $Id$
|
||||||
!
|
!
|
||||||
! Copyright (C) 2003 Slava Pestov.
|
! Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
!
|
!
|
||||||
! Redistribution and use in source and binary forms, with or without
|
! Redistribution and use in source and binary forms, with or without
|
||||||
! modification, are permitted provided that the following conditions are met:
|
! modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -26,18 +26,18 @@
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
: <stream> ( -- stream )
|
: <stream> ( -- stream )
|
||||||
! Create a stream object. A stream is a namespace with the following
|
! Create a stream object. A stream is a namespace with the
|
||||||
! entries:
|
! following entries:
|
||||||
! - fflush
|
! - fflush
|
||||||
! - freadln -- you must provide an implementation!
|
! - freadln -- you must provide an implementation!
|
||||||
! - fwriteln
|
! - fwriteln
|
||||||
! - fwrite -- you must provide an implementation!
|
! - fwrite -- you must provide an implementation!
|
||||||
! - fclose
|
! - fclose
|
||||||
! Note that you must extend this object and provide your own implementations
|
! Note that you must extend this object and provide your own
|
||||||
! of all entries except for fwriteln, which is defined to fwrite the string
|
! implementations of all entries except for fwriteln, which
|
||||||
! followed by the newline by default.
|
! is defined to fwrite the string followed by the newline by
|
||||||
|
! default.
|
||||||
<namespace> [
|
<namespace> [
|
||||||
|
|
||||||
( -- string )
|
( -- string )
|
||||||
[ "freadln not implemented." break ] @freadln
|
[ "freadln not implemented." break ] @freadln
|
||||||
( string -- )
|
( string -- )
|
||||||
|
@ -50,91 +50,99 @@
|
||||||
[ $namespace fwrite "\n" $namespace fwrite ] @fwriteln
|
[ $namespace fwrite "\n" $namespace fwrite ] @fwriteln
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
|
! These are in separate words so that they can be compiled.
|
||||||
|
! Do not call them directly.
|
||||||
|
|
||||||
|
: <bytestream>/freadln ( -- string )
|
||||||
|
$in [ "java.io.InputStream" ] "factor.FactorLib" "readLine"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
|
: <bytestream>/fwrite ( string -- )
|
||||||
|
>bytes
|
||||||
|
$out [ [ "byte" ] ]
|
||||||
|
"java.io.OutputStream" "write" jinvoke ;
|
||||||
|
|
||||||
|
: <bytestream>/fflush ( -- )
|
||||||
|
$out [ ] "java.io.OutputStream" "flush" jinvoke ;
|
||||||
|
|
||||||
|
: <bytestream>/fclose ( -- )
|
||||||
|
$in [ ] "java.io.InputStream" "close" jinvoke
|
||||||
|
$out [ ] "java.io.OutputStream" "close" jinvoke ;
|
||||||
|
|
||||||
: <bytestream> ( in out -- stream )
|
: <bytestream> ( in out -- stream )
|
||||||
! Creates a new stream for reading from the java.io.InputStream in, and
|
! Creates a new stream for reading from the
|
||||||
! writing to the java.io.OutputStream out.
|
! java.io.InputStream in, and writing to the
|
||||||
|
! java.io.OutputStream out.
|
||||||
<stream> [
|
<stream> [
|
||||||
@out
|
@out
|
||||||
@in
|
@in
|
||||||
|
|
||||||
( -- string )
|
( -- string )
|
||||||
[
|
[ <bytestream>/freadln ] @freadln
|
||||||
$in [ "java.io.InputStream" ] "factor.FactorLib" "readLine"
|
|
||||||
jmethod jinvokeStatic
|
|
||||||
] @freadln
|
|
||||||
|
|
||||||
( string -- )
|
( string -- )
|
||||||
[
|
[ <bytestream>/fwrite ] @fwrite
|
||||||
>bytes
|
|
||||||
$out [ "[B" ] "java.io.OutputStream" "write" jmethod jinvoke
|
|
||||||
] @fwrite
|
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
[
|
[ <bytestream>/fflush ] @fflush
|
||||||
$out [ ] "java.io.OutputStream" "flush" jmethod jinvoke
|
|
||||||
] @fflush
|
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
[
|
[ <bytestream>/fclose ] @fclose
|
||||||
$in [ ] "java.io.InputStream" "close" jmethod jinvoke
|
|
||||||
$out [ ] "java.io.OutputStream" "close" jmethod jinvoke
|
|
||||||
] @fclose
|
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
|
: <charstream>/freadln ( -- string )
|
||||||
|
$in [ ] "java.io.BufferedReader" "readLine"
|
||||||
|
jinvoke ;
|
||||||
|
|
||||||
|
: <charstream>/fwrite ( string -- )
|
||||||
|
$out [ "java.lang.String" ] "java.io.Writer" "write"
|
||||||
|
jinvoke ;
|
||||||
|
|
||||||
|
: <charstream>/fflush ( -- )
|
||||||
|
$out [ ] "java.io.Writer" "flush" jinvoke ;
|
||||||
|
|
||||||
|
: <charstream>/fclose ( -- )
|
||||||
|
$in [ ] "java.io.Reader" "close" jinvoke
|
||||||
|
$out [ ] "java.io.Writer" "close" jinvoke ;
|
||||||
|
|
||||||
: <charstream> ( in out -- stream )
|
: <charstream> ( in out -- stream )
|
||||||
! Creates a new stream for reading from the java.io.BufferedReader in, and
|
! Creates a new stream for reading from the
|
||||||
! writing to the java.io.Reader out.
|
! java.io.BufferedReader in, and writing to the
|
||||||
|
! java.io.Reader out.
|
||||||
<stream> [
|
<stream> [
|
||||||
@out
|
@out
|
||||||
@in
|
@in
|
||||||
|
|
||||||
( -- string )
|
( -- string )
|
||||||
[
|
[ <charstream>/freadln ] @freadln
|
||||||
$in [ ] "java.io.BufferedReader" "readLine" jmethod jinvoke
|
|
||||||
] @freadln
|
|
||||||
|
|
||||||
( string -- )
|
( string -- )
|
||||||
[
|
[ <charstream>/fwrite ] @fwrite
|
||||||
$out [ "java.lang.String" ] "java.io.Writer" "write" jmethod jinvoke
|
|
||||||
] @fwrite
|
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
[
|
[ <charstream>/fflush ] @fflush
|
||||||
$out [ ] "java.io.Writer" "flush" jmethod jinvoke
|
|
||||||
] @fflush
|
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
[
|
[ <charstream>/fclose ] @fclose
|
||||||
$in [ ] "java.io.Reader" "close" jmethod jinvoke
|
|
||||||
$out [ ] "java.io.Writer" "close" jmethod jinvoke
|
|
||||||
] @fclose
|
|
||||||
] extend ;
|
] extend ;
|
||||||
|
|
||||||
: <filecr> ( path -- stream )
|
: <filecr> ( path -- stream )
|
||||||
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader>
|
[ |java.lang.String ] |java.io.FileReader jnew <breader>
|
||||||
f
|
f
|
||||||
<charstream> ;
|
<charstream> ;
|
||||||
|
|
||||||
: <filecw> ( path -- stream )
|
: <filecw> ( path -- stream )
|
||||||
f
|
f
|
||||||
[ |java.lang.String ] |java.io.FileWriter jconstructor jnew <bwriter>
|
[ |java.lang.String ] |java.io.FileWriter jnew <bwriter>
|
||||||
<charstream> ;
|
<charstream> ;
|
||||||
|
|
||||||
: <filebr> ( path -- stream )
|
: <filebr> ( path -- stream )
|
||||||
[ |java.lang.String ] |java.io.FileInputStream jconstructor jnew
|
[ |java.lang.String ] |java.io.FileInputStream jnew
|
||||||
f
|
f
|
||||||
<bytestream> ;
|
<bytestream> ;
|
||||||
|
|
||||||
: <filebw> ( path -- stream )
|
: <filebw> ( path -- stream )
|
||||||
f
|
f
|
||||||
[ |java.lang.String ] |java.io.FileOutputStream jconstructor jnew
|
[ |java.lang.String ] |java.io.FileOutputStream jnew
|
||||||
<bytestream> ;
|
<bytestream> ;
|
||||||
|
|
||||||
: <bwriter> (writer -- bwriter)
|
: <bwriter> (writer -- bwriter)
|
||||||
[ |java.io.Writer ] |java.io.BufferedWriter jconstructor jnew ;
|
[ |java.io.Writer ] |java.io.BufferedWriter jnew ;
|
||||||
|
|
||||||
: <owriter> (outputstream -- owriter)
|
: <owriter> (outputstream -- owriter)
|
||||||
[ |java.io.OutputStream ] |java.io.OutputStreamWriter jconstructor jnew ;
|
[ |java.io.OutputStream ] |java.io.OutputStreamWriter jnew ;
|
||||||
|
|
||||||
: read ( -- string )
|
: read ( -- string )
|
||||||
$stdio freadln ;
|
$stdio freadln ;
|
||||||
|
@ -165,30 +173,30 @@
|
||||||
[ [ $in ] bind ] dip
|
[ [ $in ] bind ] dip
|
||||||
[ $out ] bind
|
[ $out ] bind
|
||||||
[ "java.io.InputStream" "java.io.OutputStream" ]
|
[ "java.io.InputStream" "java.io.OutputStream" ]
|
||||||
"factor.FactorLib" "copy" jmethod jinvokeStatic ;
|
"factor.FactorLib" "copy" jinvoke-static ;
|
||||||
|
|
||||||
"java.lang.System" "in" jfield jvarStatic$ <ireader> <breader> @stdin
|
"java.lang.System" "in" jvar-static$ <ireader> <breader> @stdin
|
||||||
"java.lang.System" "out" jfield jvarStatic$ <owriter> @stdout
|
"java.lang.System" "out" jvar-static$ <owriter> @stdout
|
||||||
$stdin $stdout <charstream> @stdio
|
$stdin $stdout <charstream> @stdio
|
||||||
|
|
||||||
!(file -- freader)
|
!(file -- freader)
|
||||||
|<freader> [
|
|<freader> [
|
||||||
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader>
|
[ |java.lang.String ] |java.io.FileReader jnew <breader>
|
||||||
] define
|
] define
|
||||||
|
|
||||||
: <file> (path -- file)
|
: <file> (path -- file)
|
||||||
dup "java.io.File" is not [
|
dup "java.io.File" is not [
|
||||||
[ "java.lang.String" ] "java.io.File" jconstructor jnew
|
[ "java.lang.String" ] "java.io.File" jnew
|
||||||
] when ;
|
] when ;
|
||||||
|
|
||||||
: exists? (file -- boolean)
|
: exists? (file -- boolean)
|
||||||
<file> [ ] "java.io.File" "exists" jmethod jinvoke ;
|
<file> [ ] "java.io.File" "exists" jinvoke ;
|
||||||
|
|
||||||
: directory? (file -- boolean)
|
: directory? (file -- boolean)
|
||||||
<file> [ ] "java.io.File" "isDirectory" jmethod jinvoke ;
|
<file> [ ] "java.io.File" "isDirectory" jinvoke ;
|
||||||
|
|
||||||
: directory ( file -- listing )
|
: directory ( file -- listing )
|
||||||
<file> [ ] "java.io.File" "list" jmethod jinvoke
|
<file> [ ] "java.io.File" "list" jinvoke
|
||||||
array>list ;
|
array>list ;
|
||||||
|
|
||||||
: rename ( from to -- )
|
: rename ( from to -- )
|
||||||
|
@ -196,26 +204,27 @@ $stdin $stdout <charstream> @stdio
|
||||||
! java.io.File instances.
|
! java.io.File instances.
|
||||||
<file> swap <file>
|
<file> swap <file>
|
||||||
[ "java.io.File" ] "java.io.File" "renameTo"
|
[ "java.io.File" ] "java.io.File" "renameTo"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
!(string -- reader)
|
!(string -- reader)
|
||||||
|<sreader> [
|
|<sreader> [
|
||||||
[ |java.lang.String ] |java.io.StringReader jconstructor jnew
|
[ |java.lang.String ] |java.io.StringReader jnew
|
||||||
] define
|
] define
|
||||||
|
|
||||||
: close (stream --)
|
: close (stream --)
|
||||||
dup "java.io.Reader" is
|
dup "java.io.Reader" is [
|
||||||
[ ] "java.io.Reader" "close" jmethod
|
[ ] "java.io.Reader" "close" jinvoke
|
||||||
[ ] "java.io.Writer" "close" jmethod
|
] [
|
||||||
?
|
[ ] "java.io.Writer" "close" jinvoke
|
||||||
jinvoke ;
|
] ifte ;
|
||||||
|
|
||||||
: exec (args -- exitCode)
|
: exec ( args -- exitCode )
|
||||||
[ "[Ljava.lang.String;" ] "factor.FactorLib" "exec" jmethod jinvokeStatic ;
|
[ [ "java.lang.String" ] ] "factor.FactorLib" "exec"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
!(stream -- string)
|
!(stream -- string)
|
||||||
|read* [
|
|read* [
|
||||||
[ ] |java.io.BufferedReader |readLine jmethod jinvoke
|
[ ] |java.io.BufferedReader |readLine jinvoke
|
||||||
] define
|
] define
|
||||||
|
|
||||||
: print* (string stream --)
|
: print* (string stream --)
|
||||||
|
@ -225,6 +234,6 @@ $stdin $stdout <charstream> @stdio
|
||||||
!(string stream --)
|
!(string stream --)
|
||||||
|write* [
|
|write* [
|
||||||
tuck
|
tuck
|
||||||
[ |java.lang.String ] |java.io.Writer |write jmethod jinvoke
|
[ |java.lang.String ] |java.io.Writer |write jinvoke
|
||||||
[ ] |java.io.Writer |flush jmethod jinvoke
|
[ ] |java.io.Writer |flush jinvoke
|
||||||
] define
|
] define
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
! $Id$
|
! $Id$
|
||||||
!
|
!
|
||||||
! Copyright (C) 2003 Slava Pestov.
|
! Copyright (C) 2003, 2004 Slava Pestov.
|
||||||
!
|
!
|
||||||
! Redistribution and use in source and binary forms, with or without
|
! Redistribution and use in source and binary forms, with or without
|
||||||
! modification, are permitted provided that the following conditions are met:
|
! modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -35,103 +35,186 @@
|
||||||
! [ #\" , """ ]
|
! [ #\" , """ ]
|
||||||
] @entities
|
] @entities
|
||||||
|
|
||||||
|
: >str ( obj -- string )
|
||||||
|
! Returns the Java string representation of this object.
|
||||||
|
[ ] "java.lang.Object" "toString" jinvoke ;
|
||||||
|
|
||||||
: >bytes ( string -- array )
|
: >bytes ( string -- array )
|
||||||
! Converts a string to an array of ASCII bytes. An exception is thrown
|
! Converts a string to an array of ASCII bytes. An exception
|
||||||
! if the string contains non-ASCII characters.
|
! is thrown if the string contains non-ASCII characters.
|
||||||
"ASCII" swap
|
"ASCII" swap
|
||||||
[ "java.lang.String" ] "java.lang.String" "getBytes" jmethod jinvoke ;
|
[ "java.lang.String" ] "java.lang.String" "getBytes"
|
||||||
|
jinvoke ;
|
||||||
|
|
||||||
: cat ([ "a" "b" "c" ] -- "abc")
|
: <sbuf> ( -- StringBuffer )
|
||||||
[ "factor.FactorList" ] "factor.FactorLib" "cat" jmethod jinvokeStatic ;
|
[ ] "java.lang.StringBuffer" jnew ;
|
||||||
|
|
||||||
: cat2 ("a" "b" -- "ab")
|
: sbuf-append ( str buf -- buf )
|
||||||
[ "java.lang.Object" "java.lang.Object" ]
|
[ "java.lang.String" ] "java.lang.StringBuffer" "append"
|
||||||
"factor.FactorLib" "cat2" jmethod jinvokeStatic ;
|
jinvoke ;
|
||||||
|
|
||||||
: cat3 ("a" "b" "c" -- "abc")
|
: cat ( [ "a" "b" "c" ] -- "abc" )
|
||||||
[ "java.lang.Object" "java.lang.Object" "java.lang.Object" ]
|
! If f appears in the list, it is not appended to the
|
||||||
"factor.FactorLib" "cat3" jmethod jinvokeStatic ;
|
! string.
|
||||||
|
<sbuf> swap [ [ swap sbuf-append ] when* ] each >str ;
|
||||||
|
|
||||||
: cat4 ("a" "b" "c" "d" -- "abcd")
|
: cat2 ( "a" "b" -- "ab" )
|
||||||
cat2 cat3 ;
|
swap <sbuf> sbuf-append sbuf-append >str ;
|
||||||
|
|
||||||
: chars>entities (str -- str)
|
: cat3 ( "a" "b" "c" -- "abc" )
|
||||||
|
[ ] cons cons cons cat ;
|
||||||
|
|
||||||
|
: cat4 ( "a" "b" "c" "d" -- "abcd" )
|
||||||
|
[ ] cons cons cons cons cat ;
|
||||||
|
|
||||||
|
: char? ( obj -- boolean )
|
||||||
|
"java.lang.Character" is ;
|
||||||
|
|
||||||
|
: chars>entities ( str -- str )
|
||||||
! Convert <, >, &, ' and " to HTML entities.
|
! Convert <, >, &, ' and " to HTML entities.
|
||||||
"" [ dup $entities assoc dup [ nip ] [ drop ] ifte ] strmap ;
|
[ dup $entities assoc dup [ nip ] [ drop ] ifte ] strmap ;
|
||||||
|
|
||||||
: group (index match --)
|
: group ( index match -- )
|
||||||
[ "int" ] "java.util.regex.Matcher" "group"
|
[ "int" ] "java.util.regex.Matcher" "group"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: groupCount (matcher -- count)
|
: group-count ( matcher -- count )
|
||||||
[ ] "java.util.regex.Matcher" "groupCount"
|
[ ] "java.util.regex.Matcher" "groupCount"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: groups* (matcher -- list)
|
: groups* ( matcher -- list )
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
dup groupCount [
|
dup group-count [
|
||||||
succ over group swap
|
succ over group swap
|
||||||
] times* drop
|
] times* drop
|
||||||
] cons expand
|
] cons expand
|
||||||
] [matches] ;
|
] [re-matches] ;
|
||||||
|
|
||||||
: groups (input regex -- list)
|
: groups ( input regex -- list )
|
||||||
<regex> <matcher> groups* ;
|
<regex> <matcher> groups* ;
|
||||||
|
|
||||||
: [matches] ( matcher code -- boolean )
|
: index-of* ( index string substring -- index )
|
||||||
! If the matcher's matches* function returns true,
|
dup char? [
|
||||||
|
-rot
|
||||||
|
! Why is the first parameter an int and not a char?
|
||||||
|
[ "int" "int" ]
|
||||||
|
"java.lang.String" "indexOf"
|
||||||
|
jinvoke
|
||||||
|
] [
|
||||||
|
-rot
|
||||||
|
[ "java.lang.String" "int" ]
|
||||||
|
"java.lang.String" "indexOf"
|
||||||
|
jinvoke
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: index-of ( string substring -- index )
|
||||||
|
0 -rot index-of* ;
|
||||||
|
|
||||||
|
: [re-matches] ( matcher code -- boolean )
|
||||||
|
! If the matcher's re-matches* function returns true,
|
||||||
! evaluate the code with the matcher at the top of the
|
! evaluate the code with the matcher at the top of the
|
||||||
! stack. Otherwise, pop the matcher off the stack and
|
! stack. Otherwise, pop the matcher off the stack and
|
||||||
! push f.
|
! push f.
|
||||||
[ dup matches* ] dip [ drop f ] ifte ;
|
[ dup re-matches* ] dip [ drop f ] ifte ;
|
||||||
|
|
||||||
: <matcher> (string pattern -- matcher)
|
: <matcher> ( string pattern -- matcher )
|
||||||
[ "java.lang.CharSequence" ]
|
[ "java.lang.CharSequence" ]
|
||||||
"java.util.regex.Pattern" "matcher"
|
"java.util.regex.Pattern" "matcher"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: matches* (matcher -- boolean)
|
: re-matches* ( matcher -- boolean )
|
||||||
[ ] "java.util.regex.Matcher" "matches"
|
[ ] "java.util.regex.Matcher" "matches"
|
||||||
jmethod jinvoke ;
|
jinvoke ;
|
||||||
|
|
||||||
: matches (input regex -- boolean)
|
: re-matches ( input regex -- boolean )
|
||||||
<regex> <matcher> matches* ;
|
<regex> <matcher> re-matches* ;
|
||||||
|
|
||||||
: replace* ( replace matcher -- string )
|
: re-replace* ( replace matcher -- string )
|
||||||
[ "java.lang.String" ] "java.util.regex.Matcher"
|
[ "java.lang.String" ] "java.util.regex.Matcher"
|
||||||
"replaceAll" jmethod jinvoke ;
|
"replaceAll" jinvoke ;
|
||||||
|
|
||||||
: replace ( input regex replace -- string )
|
: re-replace ( input regex replace -- string )
|
||||||
! Replaces all occurrences of the regex in the input string
|
! Replaces all occurrences of the regex in the input string
|
||||||
! with the replace string.
|
! with the replace string.
|
||||||
-rot <regex> <matcher> replace* ;
|
-rot <regex> <matcher> re-replace* ;
|
||||||
|
|
||||||
|
: re-split ( string split -- list )
|
||||||
|
<regex> [ "java.lang.CharSequence" ]
|
||||||
|
"java.util.regex.Pattern" "split" jinvoke array>list ;
|
||||||
|
|
||||||
: <regex> (pattern -- regex)
|
: <regex> (pattern -- regex)
|
||||||
! Compile the regex, if its not already compiled.
|
! Compile the regex, if its not already compiled.
|
||||||
dup "java.util.regex.Pattern" is not [
|
dup "java.util.regex.Pattern" is not [
|
||||||
[ "java.lang.String" ] "java.util.regex.Pattern" "compile"
|
[ "java.lang.String" ]
|
||||||
jmethod jinvokeStatic
|
"java.util.regex.Pattern" "compile"
|
||||||
|
jinvoke-static
|
||||||
] when ;
|
] when ;
|
||||||
|
|
||||||
: strget (index str -- char)
|
: split ( string split -- list )
|
||||||
[ "int" ] "java.lang.String" "charAt" jmethod jinvoke ;
|
2dup index-of dup -1 = [
|
||||||
|
2drop unit
|
||||||
|
] [
|
||||||
|
swap [ str// ] dip split cons
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
: strlen (str -- length)
|
: str/ ( str index -- str str )
|
||||||
[ ] "java.lang.String" "length" jmethod jinvoke ;
|
! Returns 2 strings, that when concatenated yield the
|
||||||
|
! original string.
|
||||||
|
2dup strtail [ str-head ] dip ;
|
||||||
|
|
||||||
: streach (str [ code ] --)
|
: str// ( str index -- str str )
|
||||||
! Execute the code, with each character of the string pushed onto the
|
! Returns 2 strings, that when concatenated yield the
|
||||||
! stack.
|
! original string, without the character at the given
|
||||||
over strlen [
|
! index.
|
||||||
-rot 2dup [ [ strget ] dip call ] 2dip
|
2dup succ strtail [ str-head ] dip ;
|
||||||
|
|
||||||
|
: str-each ( str [ code ] -- )
|
||||||
|
! Execute the code, with each character of the string pushed
|
||||||
|
! onto the stack.
|
||||||
|
over str-length [
|
||||||
|
-rot 2dup [ [ str-get ] dip call ] 2dip
|
||||||
] times* 2drop ;
|
] times* 2drop ;
|
||||||
|
|
||||||
: strmap (str initial [ code ] -- [ mapping ])
|
: str-expand ( [ code ] -- str )
|
||||||
! If the 'initial' parameter is f, turn it into "".
|
expand cat ;
|
||||||
! Maybe cat should handle this instead?
|
|
||||||
[ dup [ drop "" ] unless ] dip
|
: str-get (index str -- char)
|
||||||
swapd [ ] cons cons cons
|
[ "int" ] "java.lang.String" "charAt" jinvoke ;
|
||||||
restack
|
|
||||||
streach
|
: str-head ( str index -- str )
|
||||||
unstack cat ;
|
! Returns a new string, from the beginning of the string
|
||||||
|
! until the given index.
|
||||||
|
0 transp substring ;
|
||||||
|
|
||||||
|
: str-headcut ( str begin -- str str )
|
||||||
|
str-length str/ ;
|
||||||
|
|
||||||
|
: str-head? ( str begin -- str )
|
||||||
|
! If the string starts with begin, return the rest of the
|
||||||
|
! string after begin. Otherwise, return f.
|
||||||
|
2dup str-length> [
|
||||||
|
tuck str-headcut
|
||||||
|
[ = ] dip f ?
|
||||||
|
] [
|
||||||
|
2drop f
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: str-length ( str -- length )
|
||||||
|
[ ] "java.lang.String" "length" jinvoke ;
|
||||||
|
|
||||||
|
: str-length> ( str str -- boolean )
|
||||||
|
! Compare string lengths.
|
||||||
|
[ str-length ] apply2 > ;
|
||||||
|
|
||||||
|
: str-map ( str [ code ] -- [ mapping ] )
|
||||||
|
2list restack str-each unstack cat ;
|
||||||
|
|
||||||
|
: strtail ( str index -- str )
|
||||||
|
! Returns a new string, from the given index until the end
|
||||||
|
! of the string.
|
||||||
|
over str-length rot substring ;
|
||||||
|
|
||||||
|
: substring ( start end str -- str )
|
||||||
|
[ "int" "int" ] "java.lang.String" "substring"
|
||||||
|
jinvoke ;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"0.29" @version
|
"0.36" @version
|
||||||
|
|
Loading…
Reference in New Issue