removed factor db
parent
cb758942aa
commit
88e3ea7ab4
|
@ -4,7 +4,6 @@
|
|||
- minimal use/in for parse-stream
|
||||
- prettyprint-1
|
||||
- {...} vectors
|
||||
- better .s
|
||||
- parsing should be parsing
|
||||
- telnetd: listening on a socket
|
||||
- vocab inspecting ==> worddef>list, assumes . on a list works
|
||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
!a;7528;7528
|
||||
!a;6964;6964
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -160,39 +160,18 @@ public class Cons implements PublicCloneable, FactorExternalizable
|
|||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ unparseDB() method
|
||||
/**
|
||||
* Returns elementsToDBString() enclosed with [ and ].
|
||||
*/
|
||||
public String unparseDB()
|
||||
{
|
||||
return "[ " + elementsToString(true) + " ]";
|
||||
} //}}}
|
||||
|
||||
//{{{ elementsToString() method
|
||||
/**
|
||||
* Returns a whitespace separated string of the unparseObject() of each
|
||||
* item.
|
||||
*/
|
||||
public String elementsToString()
|
||||
{
|
||||
return elementsToString(false);
|
||||
} //}}}
|
||||
|
||||
//{{{ elementsToString() method
|
||||
/**
|
||||
* Returns a whitespace separated string of the unparseObject() of each
|
||||
* item.
|
||||
*/
|
||||
public String elementsToString(boolean dbUnparse)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Cons iter = this;
|
||||
while(iter != null)
|
||||
{
|
||||
buf.append(dbUnparse ?
|
||||
FactorReader.unparseDBObject(iter.car)
|
||||
: FactorReader.unparseObject(iter.car));
|
||||
buf.append(FactorReader.unparseObject(iter.car));
|
||||
if(iter.cdr instanceof Cons)
|
||||
{
|
||||
buf.append(' ');
|
||||
|
@ -204,9 +183,7 @@ public class Cons implements PublicCloneable, FactorExternalizable
|
|||
else
|
||||
{
|
||||
buf.append(" | ");
|
||||
buf.append(dbUnparse ?
|
||||
FactorReader.unparseDBObject(iter.cdr)
|
||||
: FactorReader.unparseObject(iter.cdr));
|
||||
buf.append(FactorReader.unparseObject(iter.cdr));
|
||||
iter = null;
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +197,7 @@ public class Cons implements PublicCloneable, FactorExternalizable
|
|||
*/
|
||||
public String toString()
|
||||
{
|
||||
return "[ " + elementsToString(false) + " ]";
|
||||
return "[ " + elementsToString() + " ]";
|
||||
} //}}}
|
||||
|
||||
//{{{ toArray() method
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
package factor;
|
||||
|
||||
/**
|
||||
* Factor is a stack-based language.
|
||||
* A growable array.
|
||||
* @author Slava Pestov
|
||||
*/
|
||||
public class FactorArray implements PublicCloneable
|
||||
public class FactorArray implements FactorExternalizable, PublicCloneable
|
||||
{
|
||||
public Object[] stack;
|
||||
public int top;
|
||||
|
@ -159,6 +159,22 @@ public class FactorArray implements PublicCloneable
|
|||
return stack.length;
|
||||
} //}}}
|
||||
|
||||
//{{{ toString() method
|
||||
/**
|
||||
* Returns elementsToString() enclosed with [ and ].
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("{ ");
|
||||
for(int i = 0; i < top; i++)
|
||||
{
|
||||
buf.append(FactorReader.unparseObject(stack[i]));
|
||||
buf.append(' ');
|
||||
}
|
||||
|
||||
return buf.append("}").toString();
|
||||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
public Cons toList()
|
||||
{
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.Workspace;
|
||||
import factor.db.PersistenceException;
|
||||
import java.lang.reflect.*;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.*;
|
||||
|
@ -52,29 +50,16 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
* A new definition.
|
||||
*/
|
||||
public FactorCompoundDefinition(FactorWord word, Cons definition,
|
||||
FactorInterpreter interp) throws PersistenceException
|
||||
FactorInterpreter interp)
|
||||
{
|
||||
super(word,interp.workspace);
|
||||
super(word);
|
||||
fromList(definition,interp);
|
||||
|
||||
if(interp.workspace != null)
|
||||
interp.workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorCompoundDefinition constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public FactorCompoundDefinition(Workspace workspace, long id)
|
||||
{
|
||||
super(workspace,id);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
public void eval(FactorInterpreter interp)
|
||||
throws Exception
|
||||
{
|
||||
lazyInit(interp);
|
||||
interp.call(endOfDocs);
|
||||
} //}}}
|
||||
|
||||
|
@ -82,7 +67,6 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
public void getStackEffect(RecursiveState recursiveCheck,
|
||||
FactorCompiler compiler) throws Exception
|
||||
{
|
||||
lazyInit(compiler.interp);
|
||||
RecursiveForm rec = recursiveCheck.get(word);
|
||||
if(rec.active)
|
||||
{
|
||||
|
@ -111,10 +95,8 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
FactorWordDefinition compile(FactorInterpreter interp,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
lazyInit(interp);
|
||||
// Each word has its own class loader
|
||||
FactorClassLoader loader = new FactorClassLoader(
|
||||
interp.workspace);
|
||||
FactorClassLoader loader = new FactorClassLoader();
|
||||
|
||||
StackEffect effect = getStackEffect(interp);
|
||||
|
||||
|
|
|
@ -29,20 +29,13 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.db.*;
|
||||
import factor.parser.*;
|
||||
import factor.primitives.*;
|
||||
import java.io.*;
|
||||
|
||||
public class FactorInterpreter implements FactorObject, Runnable
|
||||
{
|
||||
public static final String VERSION = "0.60.6";
|
||||
|
||||
// we need to call the 'boot' word from the init vocabulary.
|
||||
private static final String INIT_VOCAB = "init";
|
||||
|
||||
// we need to call the 'throw' word from the errors vocabulary.
|
||||
private static final String ERRORS_VOCAB = "errors";
|
||||
public static final String VERSION = "0.60.8";
|
||||
|
||||
// command line arguments are stored here.
|
||||
public Cons args;
|
||||
|
@ -52,8 +45,9 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
public Throwable error;
|
||||
public boolean dump = false;
|
||||
public boolean verboseCompile = false;
|
||||
public boolean firstTime = false;
|
||||
public boolean mini = false;
|
||||
// if this is false and an error occurs, bail out.
|
||||
public boolean startupDone = false;
|
||||
|
||||
public Cons callframe;
|
||||
public FactorArray callstack = new FactorArray();
|
||||
|
@ -87,11 +81,6 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
*/
|
||||
public FactorWord last;
|
||||
|
||||
/**
|
||||
* Persistent store, maybe null.
|
||||
*/
|
||||
public Workspace workspace;
|
||||
|
||||
public FactorNamespace global;
|
||||
|
||||
private FactorNamespace interpNamespace;
|
||||
|
@ -104,8 +93,6 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
FactorInterpreter interp = new FactorInterpreter();
|
||||
interp.init(args,null);
|
||||
interp.run();
|
||||
if(interp.workspace != null)
|
||||
interp.workspace.close();
|
||||
} //}}}
|
||||
|
||||
//{{{ init() method
|
||||
|
@ -115,7 +102,6 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
this.interactive = interp.interactive;
|
||||
this.dump = interp.dump;
|
||||
this.verboseCompile = interp.verboseCompile;
|
||||
this.firstTime = firstTime;
|
||||
this.callframe = interp.callframe;
|
||||
this.callstack = (FactorArray)interp.callstack.clone();
|
||||
this.datastack = (FactorArray)interp.datastack.clone();
|
||||
|
@ -126,7 +112,6 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
this.in = interp.in;
|
||||
this.builtins = interp.builtins;
|
||||
this.last = interp.last;
|
||||
this.workspace = interp.workspace;
|
||||
this.global = interp.global;
|
||||
} //}}}
|
||||
|
||||
|
@ -136,39 +121,8 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
for(int i = 0; i < args.length; i++)
|
||||
{
|
||||
String arg = args[i];
|
||||
if(arg.equals("-no-db"))
|
||||
{
|
||||
workspace = null;
|
||||
args[i] = null;
|
||||
}
|
||||
else if(arg.equals("-db"))
|
||||
{
|
||||
if(workspace != null)
|
||||
workspace.close();
|
||||
workspace = new Workspace(
|
||||
new BTreeStore(new File("factor.db"),
|
||||
(byte)64,false),false,this);
|
||||
}
|
||||
else if(arg.startsWith("-db:"))
|
||||
{
|
||||
if(workspace != null)
|
||||
workspace.close();
|
||||
workspace = parseDBSpec(arg.substring(4));
|
||||
args[i] = null;
|
||||
}
|
||||
// this switch forces a first time init
|
||||
else if(arg.equals("-no-first-time"))
|
||||
{
|
||||
firstTime = false;
|
||||
args[i] = null;
|
||||
}
|
||||
else if(arg.equals("-first-time"))
|
||||
{
|
||||
firstTime = true;
|
||||
args[i] = null;
|
||||
}
|
||||
// this switch forces minimal libraries to be loaded
|
||||
else if(arg.equals("-no-mini"))
|
||||
if(arg.equals("-no-mini"))
|
||||
{
|
||||
mini = false;
|
||||
args[i] = null;
|
||||
|
@ -182,7 +136,7 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
|
||||
this.args = Cons.fromArray(args);
|
||||
|
||||
vocabularies = new Table(workspace);
|
||||
vocabularies = new FactorNamespace();
|
||||
initBuiltinDictionary();
|
||||
initNamespace(root);
|
||||
topLevel();
|
||||
|
@ -190,35 +144,10 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
runBootstrap();
|
||||
} //}}}
|
||||
|
||||
//{{{ parseDBSpec() method
|
||||
private Workspace parseDBSpec(String db) throws Exception
|
||||
{
|
||||
int index = db.indexOf(':');
|
||||
String className = db.substring(0,index);
|
||||
|
||||
String arg = db.substring(index + 1);
|
||||
|
||||
boolean readOnly;
|
||||
if(arg.startsWith("ro:"))
|
||||
{
|
||||
readOnly = true;
|
||||
arg = arg.substring(3);
|
||||
}
|
||||
else
|
||||
readOnly = false;
|
||||
|
||||
Class[] consArgClasses = new Class[] { String.class };
|
||||
Object[] consArgs = new Object[] { arg };
|
||||
|
||||
return new Workspace((Store)Class.forName(className)
|
||||
.getConstructor(consArgClasses)
|
||||
.newInstance(consArgs),readOnly,this);
|
||||
} //}}}
|
||||
|
||||
//{{{ initBuiltinDictionary() method
|
||||
private void initBuiltinDictionary() throws Exception
|
||||
{
|
||||
builtins = new Table(null);
|
||||
builtins = new FactorNamespace();
|
||||
vocabularies.setVariable("builtins",builtins);
|
||||
|
||||
in = "builtins";
|
||||
|
@ -226,129 +155,123 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
|
||||
// parsing words
|
||||
FactorWord lineComment = define("builtins","!");
|
||||
lineComment.parsing = new LineComment(lineComment,false,null);
|
||||
lineComment.parsing = new LineComment(lineComment,false);
|
||||
FactorWord stackComment = define("builtins","(");
|
||||
stackComment.parsing = new StackComment(stackComment,null);
|
||||
stackComment.parsing = new StackComment(stackComment);
|
||||
FactorWord str = define("builtins","\"");
|
||||
str.parsing = new StringLiteral(str,true,null);
|
||||
str.parsing = new StringLiteral(str,true);
|
||||
FactorWord t = define("builtins","t");
|
||||
t.parsing = new T(t,null);
|
||||
t.parsing = new T(t);
|
||||
FactorWord f = define("builtins","f");
|
||||
f.parsing = new F(f,null);
|
||||
f.parsing = new F(f);
|
||||
FactorWord bra = define("builtins","[");
|
||||
bra.parsing = new Bra(bra,null);
|
||||
bra.parsing = new Bra(bra);
|
||||
FactorWord ket = define("builtins","]");
|
||||
ket.parsing = new Ket(bra,ket,null);
|
||||
ket.parsing = new Ket(bra,ket);
|
||||
FactorWord bar = define("builtins","|");
|
||||
bar.parsing = new Bar(bar,null);
|
||||
bar.parsing = new Bar(bar);
|
||||
FactorWord def = define("builtins",":");
|
||||
def.parsing = new Def(def,null);
|
||||
def.parsing = new Def(def);
|
||||
def.getNamespace().setVariable("doc-comments",Boolean.TRUE);
|
||||
FactorWord ine = define("builtins",";");
|
||||
ine.parsing = new Ine(def,ine,null);
|
||||
ine.parsing = new Ine(def,ine);
|
||||
FactorWord shuffle = define("builtins","~<<");
|
||||
shuffle.parsing = new Shuffle(shuffle,">>~",null);
|
||||
shuffle.parsing = new Shuffle(shuffle,">>~");
|
||||
|
||||
FactorWord noParsing = define("builtins","POSTPONE:");
|
||||
noParsing.parsing = new NoParsing(noParsing,null);
|
||||
noParsing.parsing = new NoParsing(noParsing);
|
||||
|
||||
// #X
|
||||
FactorWord dispatch = define("builtins","#");
|
||||
dispatch.parsing = new Dispatch(dispatch,null);
|
||||
FactorWord getPersistentObject = define("builtins","#O");
|
||||
getPersistentObject.parsing = new GetPersistentObject(
|
||||
getPersistentObject,null);
|
||||
dispatch.parsing = new Dispatch(dispatch);
|
||||
FactorWord ch = define("builtins","#\\");
|
||||
ch.parsing = new CharLiteral(ch,null);
|
||||
ch.parsing = new CharLiteral(ch);
|
||||
FactorWord raw = define("builtins","#\"");
|
||||
raw.parsing = new StringLiteral(raw,false,null);
|
||||
raw.parsing = new StringLiteral(raw,false);
|
||||
FactorWord complex = define("builtins","#{");
|
||||
complex.parsing = new ComplexLiteral(complex,"}",null);
|
||||
complex.parsing = new ComplexLiteral(complex,"}");
|
||||
FactorWord docComment = define("builtins","#!");
|
||||
docComment.parsing = new LineComment(docComment,true,null);
|
||||
docComment.parsing = new LineComment(docComment,true);
|
||||
FactorWord unreadable = define("builtins","#<");
|
||||
unreadable.parsing = new Unreadable(unreadable,null);
|
||||
unreadable.parsing = new Unreadable(unreadable);
|
||||
|
||||
// #: is not handled with a special dispatch. instead, when
|
||||
// a word starting with #: is passed to intern(), it creates
|
||||
// a new symbol
|
||||
FactorWord passthru = define("builtins","#:");
|
||||
passthru.parsing = new PassThrough(passthru,null);
|
||||
passthru.parsing = new PassThrough(passthru);
|
||||
|
||||
// vocabulary parsing words
|
||||
FactorWord defer = define("builtins","DEFER:");
|
||||
defer.parsing = new Defer(defer,null);
|
||||
defer.parsing = new Defer(defer);
|
||||
FactorWord in = define("builtins","IN:");
|
||||
in.parsing = new In(in,null);
|
||||
in.parsing = new In(in);
|
||||
FactorWord use = define("builtins","USE:");
|
||||
use.parsing = new Use(use,null);
|
||||
use.parsing = new Use(use);
|
||||
|
||||
FactorWord interpreterGet = define("builtins","interpreter");
|
||||
interpreterGet.def = new InterpreterGet(interpreterGet,null);
|
||||
interpreterGet.def = new InterpreterGet(interpreterGet);
|
||||
interpreterGet.inline = true;
|
||||
|
||||
// reading numbers with another base
|
||||
FactorWord bin = define("builtins","BIN:");
|
||||
bin.parsing = new Base(defer,null,2);
|
||||
bin.parsing = new Base(bin,2);
|
||||
FactorWord oct = define("builtins","OCT:");
|
||||
oct.parsing = new Base(defer,null,8);
|
||||
oct.parsing = new Base(oct,8);
|
||||
FactorWord hex = define("builtins","HEX:");
|
||||
hex.parsing = new Base(defer,null,16);
|
||||
hex.parsing = new Base(hex,16);
|
||||
|
||||
// primitives used by 'expand' and 'map'
|
||||
FactorWord restack = define("builtins","restack");
|
||||
restack.def = new Restack(restack,null);
|
||||
restack.def = new Restack(restack);
|
||||
FactorWord unstack = define("builtins","unstack");
|
||||
unstack.def = new Unstack(unstack,null);
|
||||
unstack.def = new Unstack(unstack);
|
||||
|
||||
// reflection primitives
|
||||
FactorWord jinvoke = define("builtins","jinvoke");
|
||||
jinvoke.def = new JInvoke(jinvoke,null,false);
|
||||
jinvoke.def = new JInvoke(jinvoke,false);
|
||||
jinvoke.inline = true;
|
||||
FactorWord jinvokeStatic = define("builtins","jinvoke-static");
|
||||
jinvokeStatic.def = new JInvoke(jinvokeStatic,null,true);
|
||||
jinvokeStatic.def = new JInvoke(jinvokeStatic,true);
|
||||
jinvokeStatic.inline = true;
|
||||
FactorWord jnew = define("builtins","jnew");
|
||||
jnew.def = new JNew(jnew,null);
|
||||
jnew.def = new JNew(jnew);
|
||||
jnew.inline = true;
|
||||
FactorWord jvarGet = define("builtins","jvar-get");
|
||||
jvarGet.def = new JVarGet(jvarGet,null);
|
||||
jvarGet.def = new JVarGet(jvarGet);
|
||||
jvarGet.inline = true;
|
||||
FactorWord jvarGetStatic = define("builtins","jvar-static-get");
|
||||
jvarGetStatic.def = new JVarGetStatic(jvarGetStatic,null);
|
||||
jvarGetStatic.def = new JVarGetStatic(jvarGetStatic);
|
||||
jvarGetStatic.inline = true;
|
||||
FactorWord jvarSet = define("builtins","jvar-set");
|
||||
jvarSet.def = new JVarSet(jvarSet,null);
|
||||
jvarSet.def = new JVarSet(jvarSet);
|
||||
jvarSet.inline = true;
|
||||
FactorWord jvarSetStatic = define("builtins","jvar-static-set");
|
||||
jvarSetStatic.def = new JVarSetStatic(jvarSetStatic,null);
|
||||
jvarSetStatic.def = new JVarSetStatic(jvarSetStatic);
|
||||
jvarSetStatic.inline = true;
|
||||
FactorWord coerce = define("builtins","coerce");
|
||||
coerce.def = new Coerce(coerce,null);
|
||||
coerce.def = new Coerce(coerce);
|
||||
coerce.inline = true;
|
||||
|
||||
// definition
|
||||
FactorWord define = define("builtins","define");
|
||||
define.def = new Define(define,null);
|
||||
define.def = new Define(define);
|
||||
|
||||
// combinators
|
||||
FactorWord execute = define("builtins","execute");
|
||||
execute.def = new Execute(execute,null);
|
||||
execute.def = new Execute(execute);
|
||||
FactorWord call = define("builtins","call");
|
||||
call.def = new Call(call,null);
|
||||
call.def = new Call(call);
|
||||
call.inline = true;
|
||||
FactorWord ifte = define("builtins","ifte");
|
||||
ifte.def = new Ifte(ifte,null);
|
||||
ifte.def = new Ifte(ifte);
|
||||
ifte.inline = true;
|
||||
} //}}}
|
||||
|
||||
//{{{ initNamespace() method
|
||||
private void initNamespace(Object root) throws Exception
|
||||
{
|
||||
if(workspace == null)
|
||||
global = new FactorNamespace(null,root);
|
||||
else
|
||||
global = workspace.getRoot();
|
||||
global = new FactorNamespace(null,root);
|
||||
|
||||
global.setVariable("interpreter",this);
|
||||
|
||||
|
@ -357,37 +280,14 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
getClass().getField("verboseCompile"),
|
||||
this));
|
||||
|
||||
global.setVariable("global",
|
||||
global.setVariable("startup-done",
|
||||
new FactorNamespace.VarBinding(
|
||||
getClass().getField("global"),
|
||||
getClass().getField("startupDone"),
|
||||
this));
|
||||
|
||||
FactorNamespace newVocabs;
|
||||
try
|
||||
{
|
||||
Object obj = global.getVariable("vocabularies");
|
||||
if(!(obj instanceof FactorNamespace))
|
||||
newVocabs = new Table(workspace);
|
||||
else
|
||||
newVocabs = (FactorNamespace)obj;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.err.println("Vocabularies table corrupt: " + e);
|
||||
newVocabs = new Table(workspace);
|
||||
}
|
||||
|
||||
vocabularies = newVocabs;
|
||||
|
||||
global.setVariable("vocabularies",
|
||||
new FactorNamespace.VarBinding(
|
||||
getClass().getField("vocabularies"),
|
||||
this));
|
||||
|
||||
// Shouldn't have to do this twice!
|
||||
initBuiltinDictionary();
|
||||
|
||||
String[] boundFields = {
|
||||
"global",
|
||||
"vocabularies",
|
||||
"args",
|
||||
"dump",
|
||||
"interactive",
|
||||
|
@ -420,24 +320,16 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
//{{{ runBootstrap() method
|
||||
private void runBootstrap() throws Exception
|
||||
{
|
||||
if(workspace == null || workspace.isFirstTime()
|
||||
|| firstTime)
|
||||
{
|
||||
if(workspace != null)
|
||||
workspace.setFirstTime(false);
|
||||
String initFile = "/library/platform/jvm/boot.factor";
|
||||
FactorReader parser = new FactorReader(
|
||||
initFile,
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
getClass().getResourceAsStream(
|
||||
initFile))),
|
||||
this);
|
||||
|
||||
call(parser.parse());
|
||||
}
|
||||
else
|
||||
eval(searchVocabulary(INIT_VOCAB,"boot"));
|
||||
String initFile = "/library/platform/jvm/boot.factor";
|
||||
FactorReader parser = new FactorReader(
|
||||
initFile,
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
getClass().getResourceAsStream(
|
||||
initFile))),
|
||||
this);
|
||||
|
||||
call(parser.parse());
|
||||
|
||||
run();
|
||||
} //}}}
|
||||
|
@ -479,17 +371,27 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
private boolean handleError(Throwable e)
|
||||
{
|
||||
error = FactorJava.unwrapException(e);
|
||||
if(!startupDone)
|
||||
{
|
||||
error.printStackTrace();
|
||||
topLevel();
|
||||
return true;
|
||||
}
|
||||
|
||||
datastack.push(error);
|
||||
try
|
||||
{
|
||||
eval(searchVocabulary(ERRORS_VOCAB,"throw"));
|
||||
FactorWord throwWord = searchVocabulary(
|
||||
"errors","throw");
|
||||
if(throwWord == null)
|
||||
throw new NullPointerException();
|
||||
eval(throwWord);
|
||||
return false;
|
||||
}
|
||||
catch(Throwable e2)
|
||||
{
|
||||
System.err.println("Exception when calling throw:");
|
||||
e.printStackTrace();
|
||||
|
||||
topLevel();
|
||||
|
||||
return true;
|
||||
|
@ -609,7 +511,7 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
Object value = vocabularies.getVariable(name);
|
||||
if(value == null)
|
||||
{
|
||||
value = new Table(workspace);
|
||||
value = new FactorNamespace();
|
||||
vocabularies.setVariable(name,value);
|
||||
}
|
||||
} //}}}
|
||||
|
@ -680,7 +582,7 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
FactorNamespace v = getVocabulary(vocabulary);
|
||||
if(v == null)
|
||||
{
|
||||
v = new Table(workspace);
|
||||
v = new FactorNamespace();
|
||||
vocabularies.setVariable(vocabulary,v);
|
||||
}
|
||||
Object value = v.getVariable(name);
|
||||
|
@ -688,18 +590,9 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
return (FactorWord)value;
|
||||
else
|
||||
{
|
||||
Workspace workspace;
|
||||
if(v instanceof PersistentObject)
|
||||
{
|
||||
workspace = ((PersistentObject)v)
|
||||
.getWorkspace();
|
||||
}
|
||||
else
|
||||
workspace = null;
|
||||
|
||||
// save to same workspace as vocabulary,
|
||||
// or no workspace if vocabulary is builtins
|
||||
FactorWord word = new FactorWord(workspace,
|
||||
FactorWord word = new FactorWord(
|
||||
vocabulary,name,null);
|
||||
v.setVariable(name,word);
|
||||
return word;
|
||||
|
@ -724,8 +617,11 @@ public class FactorInterpreter implements FactorObject, Runnable
|
|||
namestack.push(global);
|
||||
catchstack.top = 0;
|
||||
// DEFER: the word
|
||||
define(ERRORS_VOCAB,"default-error-handler");
|
||||
catchstack.push(new Cons(searchVocabulary(ERRORS_VOCAB,
|
||||
define("kernel","exit*");
|
||||
catchstack.push(new Cons(new Integer(1),
|
||||
new Cons(searchVocabulary("kernel","exit*"),null)));
|
||||
define("errors","default-error-handler");
|
||||
catchstack.push(new Cons(searchVocabulary("errors",
|
||||
"default-error-handler"),null));
|
||||
callframe = null;
|
||||
} //}}}
|
||||
|
|
|
@ -29,13 +29,12 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A parsing word definition.
|
||||
*/
|
||||
public abstract class FactorParsingDefinition extends SimplePersistentObject
|
||||
public abstract class FactorParsingDefinition
|
||||
{
|
||||
public static final String ENCODING = "UTF8";
|
||||
|
||||
|
@ -45,24 +44,10 @@ public abstract class FactorParsingDefinition extends SimplePersistentObject
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public FactorParsingDefinition(FactorWord word, Workspace workspace)
|
||||
public FactorParsingDefinition(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
this(workspace,workspace == null
|
||||
? 0L : workspace.nextID());
|
||||
this.word = word;
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorParsingDefinition constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public FactorParsingDefinition(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
} //}}}
|
||||
|
||||
public abstract void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -42,22 +41,9 @@ public abstract class FactorPrimitiveDefinition extends FactorWordDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public FactorPrimitiveDefinition(FactorWord word, Workspace workspace)
|
||||
throws Exception
|
||||
public FactorPrimitiveDefinition(FactorWord word)
|
||||
{
|
||||
super(word,workspace);
|
||||
if(workspace != null)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorPrimitiveDefinition constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public FactorPrimitiveDefinition(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ fromList() method
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.db.PersistentIgnore;
|
||||
import factor.db.PersistentObject;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -230,28 +228,6 @@ public class FactorReader
|
|||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ unparseDBObject() method
|
||||
public static String unparseDBObject(Object obj)
|
||||
{
|
||||
if(obj instanceof PersistentIgnore)
|
||||
return "f";
|
||||
else if(obj instanceof PersistentObject)
|
||||
{
|
||||
PersistentObject pobj = (PersistentObject)obj;
|
||||
if(pobj.getWorkspace() != null
|
||||
&& pobj.getID() != 0L)
|
||||
{
|
||||
return "#O" + pobj.getID();
|
||||
}
|
||||
else
|
||||
return unparseObject(obj);
|
||||
}
|
||||
else if(obj instanceof Cons)
|
||||
return ((Cons)obj).unparseDB();
|
||||
else
|
||||
return unparseObject(obj);
|
||||
} //}}}
|
||||
|
||||
//{{{ unparseObject() method
|
||||
public static String unparseObject(Object obj)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.Workspace;
|
||||
import java.util.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
|
@ -59,21 +58,12 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
private int shuffleRstart;
|
||||
private int shuffleRlength;
|
||||
|
||||
//{{{ FactorShuffleDefinition constructor
|
||||
public FactorShuffleDefinition(Workspace workspace, long id)
|
||||
{
|
||||
super(workspace,id);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorShuffleDefinition constructor
|
||||
public FactorShuffleDefinition(FactorWord word, Cons definition,
|
||||
FactorInterpreter interp) throws FactorException
|
||||
{
|
||||
super(word,interp.workspace);
|
||||
super(word);
|
||||
fromList(definition,interp);
|
||||
|
||||
if(interp.workspace != null)
|
||||
interp.workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorShuffleDefinition constructor
|
||||
|
@ -162,8 +152,6 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
FactorArray callstack)
|
||||
throws FactorStackException
|
||||
{
|
||||
lazyInit(interp);
|
||||
|
||||
if(datastack.top < consumeD)
|
||||
throw new FactorStackException(consumeD);
|
||||
|
||||
|
|
|
@ -30,14 +30,12 @@
|
|||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An internalized symbol.
|
||||
*/
|
||||
public class FactorWord extends SimplePersistentObject
|
||||
implements FactorExternalizable
|
||||
public class FactorWord implements FactorExternalizable, FactorObject
|
||||
{
|
||||
private static int gensymCount = 0;
|
||||
|
||||
|
@ -75,32 +73,20 @@ public class FactorWord extends SimplePersistentObject
|
|||
public FactorClassLoader loader;
|
||||
public String className;
|
||||
|
||||
private FactorNamespace namespace;
|
||||
|
||||
//{{{ FactorWord constructor
|
||||
/**
|
||||
* Do not use this constructor unless you're writing a packages
|
||||
* implementation or something. Use an FactorDictionary's
|
||||
* intern() method instead.
|
||||
*/
|
||||
public FactorWord(Workspace workspace, long id) throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWord constructor
|
||||
/**
|
||||
* Do not use this constructor unless you're writing a packages
|
||||
* implementation or something. Use an FactorDictionary's
|
||||
* intern() method instead.
|
||||
*/
|
||||
public FactorWord(Workspace workspace, String vocabulary, String name,
|
||||
public FactorWord(String vocabulary, String name,
|
||||
FactorWordDefinition def) throws Exception
|
||||
{
|
||||
this(workspace,workspace == null ? 0L : workspace.nextID());
|
||||
this.vocabulary = vocabulary;
|
||||
this.name = name;
|
||||
this.def = def;
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWord constructor
|
||||
|
@ -115,6 +101,15 @@ public class FactorWord extends SimplePersistentObject
|
|||
this.name = name;
|
||||
} //}}}
|
||||
|
||||
//{{{ getNamespace() method
|
||||
public FactorNamespace getNamespace()
|
||||
throws Exception
|
||||
{
|
||||
if(namespace == null)
|
||||
namespace = new FactorNamespace(this);
|
||||
return namespace;
|
||||
} //}}}
|
||||
|
||||
//{{{ gensym() method
|
||||
/**
|
||||
* Returns an un-internalized word with a unique name.
|
||||
|
@ -126,7 +121,6 @@ public class FactorWord extends SimplePersistentObject
|
|||
|
||||
//{{{ define() method
|
||||
public synchronized void define(FactorWordDefinition def)
|
||||
throws PersistenceException
|
||||
{
|
||||
if(compileRef)
|
||||
{
|
||||
|
@ -140,20 +134,14 @@ public class FactorWord extends SimplePersistentObject
|
|||
|
||||
loader = null;
|
||||
className = null;
|
||||
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ setCompiledInfo() method
|
||||
synchronized void setCompiledInfo(FactorClassLoader loader,
|
||||
String className) throws PersistenceException
|
||||
String className)
|
||||
{
|
||||
this.loader = loader;
|
||||
this.className = className;
|
||||
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ compile() method
|
||||
|
@ -165,30 +153,6 @@ public class FactorWord extends SimplePersistentObject
|
|||
recursiveCheck.remove(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public synchronized void unpickle(byte[] bytes, int offset,
|
||||
FactorInterpreter interp) throws PersistenceException
|
||||
{
|
||||
super.unpickle(bytes,offset);
|
||||
|
||||
if(loader != null && className != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
def = CompiledDefinition.create(interp,
|
||||
this,loader.loadClass(className));
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
System.err.println("WARNING: cannot unpickle compiled definition");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compile() method
|
||||
public synchronized void compile(FactorInterpreter interp,
|
||||
RecursiveState recursiveCheck)
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.db.*;
|
||||
import factor.compiler.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
@ -37,21 +36,9 @@ import org.objectweb.asm.*;
|
|||
|
||||
/**
|
||||
* A word definition.
|
||||
*
|
||||
* The pickled form is an unparsed list. The car of the list is the word,
|
||||
* the cdr is toList().
|
||||
*/
|
||||
public abstract class FactorWordDefinition
|
||||
implements Constants, PersistentObject
|
||||
public abstract class FactorWordDefinition implements Constants
|
||||
{
|
||||
public static final String ENCODING = "UTF8";
|
||||
|
||||
private String unparsed;
|
||||
private boolean initialized;
|
||||
|
||||
private Workspace workspace;
|
||||
private long id;
|
||||
|
||||
protected FactorWord word;
|
||||
|
||||
public boolean compileFailed;
|
||||
|
@ -60,32 +47,9 @@ public abstract class FactorWordDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public FactorWordDefinition(FactorWord word, Workspace workspace)
|
||||
{
|
||||
this(workspace,workspace == null
|
||||
? 0L : workspace.nextID());
|
||||
this.word = word;
|
||||
initialized = true;
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWordDefinition constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public FactorWordDefinition(Workspace workspace, long id)
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWordDefinition constructor
|
||||
/**
|
||||
* A definition that is not saved in the current workspace.
|
||||
*/
|
||||
public FactorWordDefinition(FactorWord word)
|
||||
{
|
||||
this.word = word;
|
||||
initialized = true;
|
||||
} //}}}
|
||||
|
||||
public abstract void eval(FactorInterpreter interp)
|
||||
|
@ -94,15 +58,14 @@ public abstract class FactorWordDefinition
|
|||
//{{{ getWord() method
|
||||
public FactorWord getWord(FactorInterpreter interp)
|
||||
{
|
||||
lazyInit(interp);
|
||||
return word;
|
||||
} //}}}
|
||||
|
||||
//{{{ fromList() method
|
||||
public void fromList(Cons cons, FactorInterpreter interp)
|
||||
throws FactorRuntimeException, PersistenceException
|
||||
throws FactorRuntimeException
|
||||
{
|
||||
throw new PersistenceException("Cannot unpickle " + this);
|
||||
throw new FactorRuntimeException("Cannot unpickle " + this);
|
||||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
|
@ -123,7 +86,6 @@ public abstract class FactorWordDefinition
|
|||
FactorInterpreter interp) throws Exception
|
||||
{
|
||||
FactorCompiler compiler = new FactorCompiler(interp);
|
||||
lazyInit(interp);
|
||||
recursiveCheck.add(word,new StackEffect(),null,null,null);
|
||||
getStackEffect(recursiveCheck,compiler);
|
||||
recursiveCheck.remove(word);
|
||||
|
@ -134,7 +96,6 @@ public abstract class FactorWordDefinition
|
|||
public void getStackEffect(RecursiveState recursiveCheck,
|
||||
FactorCompiler compiler) throws Exception
|
||||
{
|
||||
lazyInit(compiler.interp);
|
||||
throw new FactorCompilerException("Cannot deduce stack effect of " + word);
|
||||
} //}}}
|
||||
|
||||
|
@ -152,8 +113,6 @@ public abstract class FactorWordDefinition
|
|||
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
lazyInit(compiler.interp);
|
||||
|
||||
// normal word
|
||||
String defclass;
|
||||
String defmethod;
|
||||
|
@ -262,8 +221,6 @@ public abstract class FactorWordDefinition
|
|||
RecursiveState recursiveCheck,
|
||||
StackEffect immediateEffect) throws Exception
|
||||
{
|
||||
lazyInit(compiler.interp);
|
||||
|
||||
Cons definition = toList(compiler.getInterpreter());
|
||||
|
||||
Cons endOfDocs = definition;
|
||||
|
@ -372,98 +329,6 @@ public abstract class FactorWordDefinition
|
|||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getWorkspace() method
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace()
|
||||
{
|
||||
return workspace;
|
||||
} //}}}
|
||||
|
||||
//{{{ getID() method
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID()
|
||||
{
|
||||
return id;
|
||||
} //}}}
|
||||
|
||||
//{{{ lazyInit() method
|
||||
public synchronized void lazyInit(FactorInterpreter interp)
|
||||
{
|
||||
if(initialized)
|
||||
return;
|
||||
|
||||
initialized = true;
|
||||
|
||||
try
|
||||
{
|
||||
Cons pickle = (Cons)FactorReader.parseObject(
|
||||
unparsed,interp);
|
||||
word = (FactorWord)pickle.car;
|
||||
//System.err.println(word + " unpickled");
|
||||
fromList(pickle.next(),interp);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new RuntimeException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ pickle() method
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public byte[] pickle()
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
Cons pickle = new Cons(word,toList(
|
||||
workspace.getInterpreter()));
|
||||
bytes.write((FactorReader.getVocabularyDeclaration(pickle)
|
||||
+ FactorReader.unparseDBObject(pickle))
|
||||
.getBytes(ENCODING));
|
||||
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public void unpickle(byte[] bytes, int offset)
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
unparsed = new String(bytes,offset,
|
||||
bytes.length - offset,ENCODING);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getReferences() method
|
||||
public Cons getReferences()
|
||||
{
|
||||
return toList(workspace.getInterpreter());
|
||||
} //}}}
|
||||
|
||||
//{{{ toString() method
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.objectweb.asm.*;
|
|||
*/
|
||||
public abstract class CompiledDefinition
|
||||
extends FactorWordDefinition
|
||||
implements factor.db.PersistentIgnore
|
||||
{
|
||||
//{{{ CompiledDefinition constructor
|
||||
public CompiledDefinition(FactorWord word)
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
|
||||
package factor.compiler;
|
||||
|
||||
import factor.Cons;
|
||||
import factor.FactorInterpreter;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -40,28 +38,10 @@ import java.util.*;
|
|||
* When compiling a word; add each dependent word to new class loader's
|
||||
* delegates map.
|
||||
*/
|
||||
public class FactorClassLoader extends ClassLoader implements PersistentObject
|
||||
public class FactorClassLoader extends ClassLoader
|
||||
{
|
||||
private Workspace workspace;
|
||||
private long id;
|
||||
private Table table;
|
||||
|
||||
//{{{ FactorClassLoader constructor
|
||||
public FactorClassLoader(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
table = new Table(null,workspace,0L);
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorClassLoader constructor
|
||||
public FactorClassLoader(Workspace workspace) throws Exception
|
||||
{
|
||||
this(workspace,workspace == null ? 0L : workspace.nextID());
|
||||
} //}}}
|
||||
private FactorNamespace table = new FactorNamespace();
|
||||
|
||||
//{{{ addDependency() method
|
||||
public void addDependency(String name, FactorClassLoader loader)
|
||||
|
@ -69,8 +49,6 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
|
|||
try
|
||||
{
|
||||
table.setVariable(name,loader);
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -78,57 +56,9 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
|
|||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getWorkspace() method
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace()
|
||||
{
|
||||
return workspace;
|
||||
} //}}}
|
||||
|
||||
//{{{ getID() method
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID()
|
||||
{
|
||||
return id;
|
||||
} //}}}
|
||||
|
||||
//{{{ pickle() method
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public byte[] pickle()
|
||||
throws PersistenceException
|
||||
{
|
||||
return table.pickle();
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public void unpickle(byte[] bytes, int offset)
|
||||
throws PersistenceException
|
||||
{
|
||||
table.unpickle(bytes,offset);
|
||||
} //}}}
|
||||
|
||||
//{{{ addClass() method
|
||||
public Class addClass(String name, byte[] code, int off, int len)
|
||||
{
|
||||
try
|
||||
{
|
||||
table.setVariable(name,
|
||||
new PersistentBinary(workspace,code));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return defineClass(name,code,off,len);
|
||||
} //}}}
|
||||
|
||||
|
@ -153,16 +83,6 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
|
|||
return ((FactorClassLoader)obj)
|
||||
.loadClass(name,resolve);
|
||||
}
|
||||
else if(obj instanceof PersistentBinary)
|
||||
{
|
||||
byte[] bytes = ((PersistentBinary)obj)
|
||||
.getBytes();
|
||||
c = defineClass(
|
||||
name,bytes,0,bytes.length);
|
||||
if(resolve)
|
||||
resolveClass(c);
|
||||
return c;
|
||||
}
|
||||
else if(obj != null)
|
||||
{
|
||||
System.err.println("WARNING: unknown object in class loader table for " + this + ": " + obj);
|
||||
|
@ -179,10 +99,4 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getReferences() method
|
||||
public Cons getReferences()
|
||||
{
|
||||
return table.getReferences();
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
public class BTreeException extends PersistenceException
|
||||
{
|
||||
public BTreeException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public BTreeException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public BTreeException(String msg, Throwable t)
|
||||
{
|
||||
super(msg,t);
|
||||
}
|
||||
}
|
|
@ -1,277 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A B-tree index node.
|
||||
*
|
||||
* Format on disk is:
|
||||
* - 1 byte: leaf flag for sanity check
|
||||
* - 1 byte: num children
|
||||
* - 8 * order bytes: keys
|
||||
* - 8 * order bytes: pointers
|
||||
*/
|
||||
class BTreeNode
|
||||
{
|
||||
// these two are not saved to disk.
|
||||
byte order;
|
||||
long offset;
|
||||
|
||||
boolean leaf;
|
||||
int children;
|
||||
long[] keys;
|
||||
|
||||
/**
|
||||
* In the nodes a the bottom of the tree, these are pointers inside
|
||||
* the data file; otherwise they are pointers inside the index file.
|
||||
*/
|
||||
long[] pointers;
|
||||
|
||||
/**
|
||||
* Set to true if the node changed and should be saved to disk.
|
||||
*/
|
||||
boolean dirty;
|
||||
|
||||
//{{{ getSize() method
|
||||
/**
|
||||
* Returns the size in bytes of a node with the given order.
|
||||
*/
|
||||
public static int getSize(int order)
|
||||
{
|
||||
return 2 + order * 16;
|
||||
} //}}}
|
||||
|
||||
//{{{ BTreeNode constructor
|
||||
BTreeNode(byte order, long offset)
|
||||
{
|
||||
this.order = order;
|
||||
this.offset = offset;
|
||||
this.keys = new long[order];
|
||||
this.pointers = new long[order];
|
||||
} //}}}
|
||||
|
||||
//{{{ unpackLong() method
|
||||
private long unpackLong(byte[] data, int offset)
|
||||
{
|
||||
return (((long)data[offset + 0] << 56) +
|
||||
((long)(data[offset + 1] & 255) << 48) +
|
||||
((long)(data[offset + 2] & 255) << 40) +
|
||||
((long)(data[offset + 3] & 255) << 32) +
|
||||
((long)(data[offset + 4] & 255) << 24) +
|
||||
((data[offset + 5] & 255) << 16) +
|
||||
((data[offset + 6] & 255) << 8) +
|
||||
((data[offset + 7] & 255) << 0));
|
||||
} //}}}
|
||||
|
||||
//{{{ read() method
|
||||
void read(RandomAccessFile in) throws IOException
|
||||
{
|
||||
in.seek(offset);
|
||||
|
||||
byte[] data = new byte[getSize(order)];
|
||||
in.readFully(data);
|
||||
|
||||
int pos = 0;
|
||||
leaf = (data[pos++] != 0);
|
||||
children = data[pos++];
|
||||
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
keys[i] = unpackLong(data,pos);
|
||||
pos += 8;
|
||||
}
|
||||
|
||||
pos += 8 * (order - children);
|
||||
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
pointers[i] = unpackLong(data,pos);
|
||||
pos += 8;
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ packLong() method
|
||||
private void packLong(long num, byte[] data, int offset)
|
||||
{
|
||||
data[offset + 0] = (byte)(num >>> 56);
|
||||
data[offset + 1] = (byte)(num >>> 48);
|
||||
data[offset + 2] = (byte)(num >>> 40);
|
||||
data[offset + 3] = (byte)(num >>> 32);
|
||||
data[offset + 4] = (byte)(num >>> 24);
|
||||
data[offset + 5] = (byte)(num >>> 16);
|
||||
data[offset + 6] = (byte)(num >>> 8);
|
||||
data[offset + 7] = (byte)(num >>> 0);
|
||||
} //}}}
|
||||
|
||||
//{{{ write() method
|
||||
void write(RandomAccessFile out) throws IOException
|
||||
{
|
||||
byte[] data = new byte[getSize(order)];
|
||||
|
||||
int pos = 0;
|
||||
data[pos++] = (byte)(leaf ? 1 : 0);
|
||||
data[pos++] = (byte)children;
|
||||
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
packLong(keys[i],data,pos);
|
||||
pos += 8;
|
||||
}
|
||||
|
||||
pos += 8 * (order - children);
|
||||
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
packLong(pointers[i],data,pos);
|
||||
pos += 8;
|
||||
}
|
||||
|
||||
out.seek(offset);
|
||||
out.write(data);
|
||||
} //}}}
|
||||
|
||||
//{{{ add() method
|
||||
/**
|
||||
* @exception BTreeException on various errors that should not occur
|
||||
*/
|
||||
void add(long key, long pointer) throws BTreeException
|
||||
{
|
||||
if(BTreeStore.DEBUG)
|
||||
{
|
||||
System.err.println("add " + key + "=" + pointer + " to");
|
||||
System.err.println(this);
|
||||
}
|
||||
|
||||
if(children == order)
|
||||
throw new BTreeException("Node full");
|
||||
|
||||
int position = lookupInternal(key);
|
||||
|
||||
if(keys[position] == key && position != children)
|
||||
throw new BTreeException("Adding twice");
|
||||
|
||||
// shift the keys along
|
||||
for(int i = children - 1; i >= position; i--)
|
||||
{
|
||||
keys[i + 1] = keys[i];
|
||||
pointers[i + 1] = pointers[i];
|
||||
}
|
||||
|
||||
keys[position] = key;
|
||||
pointers[position] = pointer;
|
||||
|
||||
children++;
|
||||
} //}}}
|
||||
|
||||
//{{{ lookupExternal() method
|
||||
int lookupExternal(long key)
|
||||
{
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
if(key == keys[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
} //}}}
|
||||
|
||||
//{{{ lookupInternal() method
|
||||
int lookupInternal(long key)
|
||||
{
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
if(key <= keys[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return children;
|
||||
} //}}}
|
||||
|
||||
//{{{ updateHighest() method
|
||||
void updateHighest(long key)
|
||||
{
|
||||
keys[children - 1] = key;
|
||||
} //}}}
|
||||
|
||||
//{{{ split() method
|
||||
int split(BTreeNode x, BTreeNode y, long key, boolean leaf)
|
||||
{
|
||||
x.leaf = leaf;
|
||||
y.leaf = leaf;
|
||||
|
||||
int median = children / 2;
|
||||
|
||||
x.children = children - median;
|
||||
y.children = median;
|
||||
|
||||
if(order % 2 == 0)
|
||||
median--;
|
||||
|
||||
for(int i = 0; i < x.children; i++)
|
||||
{
|
||||
x.keys[i] = keys[i];
|
||||
x.pointers[i] = pointers[i];
|
||||
}
|
||||
|
||||
for(int i = 0; i < y.children; i++)
|
||||
{
|
||||
y.keys[i] = keys[x.children + i];
|
||||
y.pointers[i] = pointers[x.children + i];
|
||||
}
|
||||
|
||||
return median;
|
||||
} //}}}
|
||||
|
||||
//{{{ toString() method
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(leaf ? "#{ " : "{ ");
|
||||
for(int i = 0; i < children; i++)
|
||||
{
|
||||
buf.append(keys[i]);
|
||||
buf.append("=");
|
||||
buf.append(pointers[i]);
|
||||
buf.append(" ");
|
||||
}
|
||||
return buf.append("}").toString();
|
||||
} //}}}
|
||||
|
||||
//{{{ dump() method
|
||||
public void dump(int indent)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for(int i = 0; i < indent; i++)
|
||||
buf.append(' ');
|
||||
buf.append(toString());
|
||||
System.err.println(buf);
|
||||
} //}}}
|
||||
}
|
|
@ -1,653 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A store that puts all records inside a single file on disk, indexed
|
||||
* by a B-tree.
|
||||
*
|
||||
* B-Tree index header:
|
||||
*
|
||||
* INDEX_MAGIC
|
||||
* 8 bytes - offset of root
|
||||
* 1 byte - order
|
||||
* 1 byte - dirty - set when loading, cleared when closing
|
||||
* 4 bytes - height
|
||||
* 8 bytes - maximum key
|
||||
*
|
||||
* Each record in data file:
|
||||
*
|
||||
* 8 bytes - key
|
||||
* 4 bytes - length
|
||||
* ... data follows
|
||||
*
|
||||
* Records in index file - see BTreeNode
|
||||
*/
|
||||
public class BTreeStore implements Store
|
||||
{
|
||||
public static boolean DEBUG = false;
|
||||
private static final int INDEX_MAGIC = 0xcabba4e4;
|
||||
private static final int DATA_MAGIC = 0xdeadbeef;
|
||||
|
||||
private static final int DEFAULT_ORDER = 64;
|
||||
|
||||
private File indexFile;
|
||||
private RandomAccessFile index;
|
||||
private File dataFile;
|
||||
private RandomAccessFile data;
|
||||
|
||||
// header has INDEX_MAGIC + these 3 values packed
|
||||
private long rootPointer;
|
||||
private byte order;
|
||||
private byte dirty; // non-zero if dirty
|
||||
private int height; // height of the tree
|
||||
private long maximumKey = -1;
|
||||
|
||||
// root is always in memory
|
||||
private BTreeNode root;
|
||||
|
||||
private BTreeNode[] lookup;
|
||||
|
||||
// next offset in the index file
|
||||
private long nextOffset;
|
||||
|
||||
//{{{ BTreeStore() method
|
||||
/**
|
||||
* Constructor used by FactorInterpreter when parsing -db parameter.
|
||||
*/
|
||||
public BTreeStore(String spec)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
int index = spec.lastIndexOf(':');
|
||||
byte order;
|
||||
if(index == -1)
|
||||
order = DEFAULT_ORDER;
|
||||
else
|
||||
{
|
||||
order = Byte.parseByte(spec.substring(index + 1));
|
||||
spec = spec.substring(0,index);
|
||||
}
|
||||
|
||||
init(new File(spec),order,spec.startsWith("ro:"));
|
||||
} //}}}
|
||||
|
||||
//{{{ BTreeStore() method
|
||||
public BTreeStore(File dataFile, byte order, boolean readOnly)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
init(dataFile,order,readOnly);
|
||||
} //}}}
|
||||
|
||||
//{{{ init() method
|
||||
private void init(File dataFile, byte order, boolean readOnly)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(order <= 3)
|
||||
throw new BTreeException("order must be > 3, < 127");
|
||||
|
||||
this.indexFile = new File(dataFile.getParent(),
|
||||
dataFile.getName() + ".index");
|
||||
this.dataFile = dataFile;
|
||||
|
||||
boolean indexFileExists = indexFile.exists();
|
||||
boolean dataFileExists = dataFile.exists();
|
||||
|
||||
index = new RandomAccessFile(indexFile,
|
||||
readOnly ? "r" : "rw");
|
||||
data = new RandomAccessFile(dataFile,
|
||||
readOnly ? "r" : "rw");
|
||||
|
||||
try
|
||||
{
|
||||
if(!indexFileExists || !dataFileExists)
|
||||
{
|
||||
this.order = order;
|
||||
writeHeader();
|
||||
nextOffset = index.length();
|
||||
if(dataFileExists)
|
||||
createIndex();
|
||||
}
|
||||
else
|
||||
{
|
||||
readHeader();
|
||||
if(rootPointer != 0)
|
||||
root = readNode(rootPointer);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
index.close();
|
||||
data.close();
|
||||
throw e;
|
||||
}
|
||||
catch(PersistenceException e)
|
||||
{
|
||||
index.close();
|
||||
data.close();
|
||||
throw e;
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ writeHeader() method
|
||||
private void writeHeader() throws IOException
|
||||
{
|
||||
index.seek(0);
|
||||
index.writeInt(INDEX_MAGIC);
|
||||
index.writeByte(dirty);
|
||||
index.writeLong(rootPointer);
|
||||
index.writeByte(order);
|
||||
index.writeInt(height);
|
||||
} //}}}
|
||||
|
||||
//{{{ readHeader() method
|
||||
private void readHeader() throws IOException, PersistenceException
|
||||
{
|
||||
index.seek(0);
|
||||
if(index.readInt() != INDEX_MAGIC)
|
||||
throw new BTreeException("Bad magic number in index file");
|
||||
dirty = index.readByte();
|
||||
rootPointer = index.readLong();
|
||||
order = index.readByte();
|
||||
if(order < 3)
|
||||
throw new BTreeException("Bad order");
|
||||
height = index.readInt();
|
||||
|
||||
nextOffset = index.length();
|
||||
} //}}}
|
||||
|
||||
//{{{ createIndex() method
|
||||
private void createIndex() throws IOException, PersistenceException
|
||||
{
|
||||
System.err.println("Re-creating index...");
|
||||
|
||||
data.seek(0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
long offset = data.getFilePointer();
|
||||
|
||||
if(offset == data.length())
|
||||
{
|
||||
// we're done
|
||||
break;
|
||||
}
|
||||
|
||||
int magic = data.readInt();
|
||||
if(magic != DATA_MAGIC)
|
||||
throw new BTreeException(magic + " != " + DATA_MAGIC);
|
||||
|
||||
long key = data.readLong();
|
||||
int length = data.readInt();
|
||||
|
||||
saveToIndex(key,offset);
|
||||
|
||||
data.skipBytes(length);
|
||||
}
|
||||
|
||||
System.err.println("... done");
|
||||
} //}}}
|
||||
|
||||
//{{{ readNode() method
|
||||
private BTreeNode readNode(long offset) throws IOException
|
||||
{
|
||||
BTreeNode node = new BTreeNode(order,offset);
|
||||
node.read(index);
|
||||
return node;
|
||||
} //}}}
|
||||
|
||||
//{{{ writeNode() method
|
||||
private void writeNode(BTreeNode node)
|
||||
throws IOException, BTreeException
|
||||
{
|
||||
if(DEBUG)
|
||||
{
|
||||
System.err.println("node.offset=" + node.offset
|
||||
+ ",index.length()=" + index.length());
|
||||
if(node.offset < index.length())
|
||||
{
|
||||
BTreeNode existing = readNode(node.offset);
|
||||
if(existing.leaf != node.leaf
|
||||
// if children is zero, empty space!
|
||||
&& existing.children != 0)
|
||||
{
|
||||
throw new BTreeException("Overwriting "
|
||||
+ existing + " with "
|
||||
+ node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.dirty = false;
|
||||
node.write(index);
|
||||
} //}}}
|
||||
|
||||
//{{{ dump() method
|
||||
private void dump(BTreeNode node, int indent)
|
||||
throws IOException
|
||||
{
|
||||
node.dump(indent);
|
||||
if(node.leaf)
|
||||
return;
|
||||
|
||||
indent++;
|
||||
|
||||
for(int i = 0; i < node.children; i++)
|
||||
dump(readNode(node.pointers[i]),indent);
|
||||
} //}}}
|
||||
|
||||
//{{{ dump() method
|
||||
private void dump()
|
||||
throws IOException
|
||||
{
|
||||
System.err.println("<<<< dump");
|
||||
if(root != null)
|
||||
dump(root,0);
|
||||
System.err.println(">>>>");
|
||||
} //}}}
|
||||
|
||||
//{{{ checkOffset() method
|
||||
private void checkOffset(long offset)
|
||||
throws IOException, BTreeException
|
||||
{
|
||||
if(offset > nextOffset)
|
||||
throw new BTreeException("Invalid pointer: " + offset + " > " + nextOffset);
|
||||
} //}}}
|
||||
|
||||
//{{{ lookup() method
|
||||
/**
|
||||
* Look up the given key, traversing down the tree. Returns an array
|
||||
* of all nodes, from the root down, that were traversed.
|
||||
*
|
||||
* Note that when adding nodes to the B-tree, I 'cheat' by splitting on
|
||||
* the way down any nodes with order == children. While this ends up
|
||||
* splitting a few more nodes than strictly necessary, it avoids a
|
||||
* second traversal up the tree, and simplifies the code.
|
||||
|
||||
* @param add in add mode, nodes along the way are split if they would
|
||||
* overflow.
|
||||
* @param newMaximum if add is true *and* this is true, a new maximal
|
||||
* node is being added, so the rightmost key in each node along the way
|
||||
* needs to be updated.
|
||||
*/
|
||||
private void lookup(long key, boolean add, boolean newMaximum)
|
||||
throws IOException, BTreeException
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("HEIGHT = " + height);
|
||||
|
||||
if(lookup == null || lookup.length != height)
|
||||
{
|
||||
saveLookup();
|
||||
lookup = new BTreeNode[height];
|
||||
}
|
||||
|
||||
if(height != 0)
|
||||
{
|
||||
|
||||
/*
|
||||
if this is true, a new level has been added (ie, the
|
||||
root was split). we return this value instead of
|
||||
incrementing the levels variable directly, since the old
|
||||
value of 'levels' is needed until the end of the method.
|
||||
*/
|
||||
boolean newLevel = false;
|
||||
|
||||
lookup[0] = root;
|
||||
|
||||
if(add)
|
||||
{
|
||||
if(possiblySplitAndUpdateMax(0,newMaximum,key))
|
||||
newLevel = true;
|
||||
}
|
||||
|
||||
for(int i = 1; i < height; i++)
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("Level " + i);
|
||||
BTreeNode node = lookup[i - 1];
|
||||
if(node.leaf)
|
||||
throw new BTreeException("A leaf: " + node);
|
||||
int next = node.lookupInternal(key);
|
||||
if(next == node.children)
|
||||
next--;
|
||||
|
||||
// read this node, and split it if we need to.
|
||||
long offset = node.pointers[next];
|
||||
checkOffset(offset);
|
||||
|
||||
// is the node already loaded?
|
||||
if(lookup[i] == null)
|
||||
lookup[i] = readNode(offset);
|
||||
else if(lookup[i].offset != offset)
|
||||
{
|
||||
if(lookup[i].dirty)
|
||||
writeNode(lookup[i]);
|
||||
lookup[i] = readNode(offset);
|
||||
}
|
||||
|
||||
if(add)
|
||||
{
|
||||
if(possiblySplitAndUpdateMax(i,newMaximum,key))
|
||||
newLevel = true;
|
||||
}
|
||||
}
|
||||
|
||||
// now that the above loop (indexed by 'levels') is
|
||||
// done, we can increment the variable, and update the
|
||||
// index header on disk.
|
||||
if(newLevel)
|
||||
{
|
||||
height++;
|
||||
writeHeader();
|
||||
}
|
||||
}
|
||||
|
||||
BTreeNode last = lookup[lookup.length - 1];
|
||||
|
||||
if(!last.leaf)
|
||||
throw new BTreeException("Not a leaf: " + last);
|
||||
|
||||
if(DEBUG)
|
||||
System.err.println("NOW height=" + height);
|
||||
} //}}}
|
||||
|
||||
//{{{ nextOffset() method
|
||||
private long nextOffset()
|
||||
{
|
||||
long ret = nextOffset;
|
||||
nextOffset += BTreeNode.getSize(order);
|
||||
return ret;
|
||||
} //}}}
|
||||
|
||||
//{{{ possiblySplitAndUpdateMax() method
|
||||
/**
|
||||
* The most important method of the B-tree class.
|
||||
* If the number of keys in the node is equal to the order, split the
|
||||
* node, and update the maximum key if necessary.
|
||||
*/
|
||||
private boolean possiblySplitAndUpdateMax(
|
||||
int level,
|
||||
boolean newMaximum,
|
||||
long key)
|
||||
throws IOException, BTreeException
|
||||
{
|
||||
BTreeNode node = lookup[level];
|
||||
long offset = node.offset;
|
||||
|
||||
// see comment in findLeaf() to see why this is needed.
|
||||
boolean newLevel = false;
|
||||
|
||||
// will we split?
|
||||
boolean split = (node.children == order);
|
||||
|
||||
if(split)
|
||||
{
|
||||
BTreeNode left = new BTreeNode(order,0);
|
||||
BTreeNode right = new BTreeNode(order,0);
|
||||
|
||||
// split the node along the median into left and right
|
||||
// side of median. store the left side in a new index
|
||||
// record.
|
||||
int median = node.split(left,right,key,
|
||||
level == height - 1);
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
System.err.println("Splitting " + node);
|
||||
System.err.println("==> left = " + left);
|
||||
System.err.println("==> right = " + right);
|
||||
}
|
||||
|
||||
long medianKey = node.keys[median];
|
||||
long highestInLeft = medianKey;
|
||||
|
||||
long leftOffset = nextOffset();
|
||||
if(DEBUG)
|
||||
System.err.println("leftOffset=" + leftOffset);
|
||||
|
||||
// the key we're adding might be in the left or right
|
||||
// side of the split, so act accordingly.
|
||||
if(key < medianKey)
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("node=left");
|
||||
node = left;
|
||||
right.offset = offset;
|
||||
writeNode(right);
|
||||
offset = leftOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("node=right");
|
||||
left.offset = leftOffset;
|
||||
writeNode(left);
|
||||
node = right;
|
||||
}
|
||||
|
||||
if(level == 0)
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("ROOT SPLIT");
|
||||
// we just split the root. create a new root
|
||||
BTreeNode newRoot = new BTreeNode(order,
|
||||
nextOffset());
|
||||
checkOffset(leftOffset);
|
||||
newRoot.add(highestInLeft,leftOffset);
|
||||
checkOffset(rootPointer);
|
||||
newRoot.add(maximumKey,rootPointer);
|
||||
writeNode(newRoot);
|
||||
rootPointer = newRoot.offset;
|
||||
root = newRoot;
|
||||
newLevel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println("NODE SPLIT");
|
||||
// we just split a non-root node, update its
|
||||
// parent.
|
||||
BTreeNode parent = lookup[level - 1];
|
||||
// note that this will never fail, since if the
|
||||
// parent previously had order == numKeys, it
|
||||
// will already have been split
|
||||
checkOffset(leftOffset);
|
||||
parent.add(highestInLeft,leftOffset);
|
||||
parent.dirty = true;
|
||||
}
|
||||
|
||||
node.dirty = true;
|
||||
}
|
||||
|
||||
// is this key we're adding a new maximum?
|
||||
if(newMaximum && level != height - 1)
|
||||
{
|
||||
node.dirty = true;
|
||||
node.updateHighest(key);
|
||||
}
|
||||
|
||||
// store node back in the 'nodes' array, after any changes have
|
||||
// been made.
|
||||
lookup[level] = node;
|
||||
node.offset = offset;
|
||||
|
||||
return newLevel;
|
||||
} //}}}
|
||||
|
||||
//{{{ exists() method
|
||||
public boolean exists(long key) throws IOException, BTreeException
|
||||
{
|
||||
// empty tree?
|
||||
if(height == 0)
|
||||
return false;
|
||||
|
||||
lookup(key,false,false);
|
||||
return lookup[height - 1].lookupExternal(key) != -1;
|
||||
} //}}}
|
||||
|
||||
//{{{ loadFromData() method
|
||||
/**
|
||||
* Load a record from the data file.
|
||||
*/
|
||||
private byte[] loadFromData(long offset, long key)
|
||||
throws IOException, BTreeException
|
||||
{
|
||||
data.seek(offset);
|
||||
|
||||
int magic = data.readInt();
|
||||
if(magic != DATA_MAGIC)
|
||||
throw new BTreeException(magic + " != " + DATA_MAGIC);
|
||||
|
||||
if(data.readLong() != key)
|
||||
throw new BTreeException("Record " + key + " not stored at " + offset);
|
||||
int length = data.readInt();
|
||||
byte[] value = new byte[length];
|
||||
data.readFully(value);
|
||||
return value;
|
||||
} //}}}
|
||||
|
||||
//{{{ loadFromStore() method
|
||||
/**
|
||||
* Load a record from the database with the given ID.
|
||||
*/
|
||||
public byte[] loadFromStore(long key)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
lookup(key,false,false);
|
||||
BTreeNode last = lookup[height - 1];
|
||||
int index = last.lookupExternal(key);
|
||||
if(index == -1)
|
||||
throw new NoSuchRecordException(key);
|
||||
long offset = last.pointers[index];
|
||||
return loadFromData(offset,key);
|
||||
} //}}}
|
||||
|
||||
//{{{ saveToData() method
|
||||
/**
|
||||
* Append a record to the data file.
|
||||
*/
|
||||
private long saveToData(long key, byte[] value) throws IOException
|
||||
{
|
||||
long offset = data.length();
|
||||
data.seek(offset);
|
||||
data.writeInt(DATA_MAGIC);
|
||||
data.writeLong(key);
|
||||
data.writeInt(value.length);
|
||||
data.write(value);
|
||||
return offset;
|
||||
} //}}}
|
||||
|
||||
//{{{ saveToIndex() method
|
||||
private void saveToIndex(long key, long offset)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(DEBUG)
|
||||
dump();
|
||||
|
||||
// Do we need to update the maximum keys as we go along?
|
||||
boolean newMaximum = (key > maximumKey);
|
||||
if(newMaximum)
|
||||
maximumKey = key;
|
||||
|
||||
BTreeNode leaf;
|
||||
|
||||
if(rootPointer == 0)
|
||||
{
|
||||
rootPointer = nextOffset();
|
||||
root = new BTreeNode(order,rootPointer);
|
||||
root.leaf = true;
|
||||
leaf = root;
|
||||
height = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int last = height - 1;
|
||||
lookup(key,true,newMaximum);
|
||||
leaf = lookup[last];
|
||||
}
|
||||
|
||||
// add the node to the leaf, write the leaf back to disk.
|
||||
int existing = leaf.lookupExternal(key);
|
||||
if(existing == -1)
|
||||
{
|
||||
// new record
|
||||
leaf.add(key,offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// updating existing record
|
||||
leaf.pointers[existing] = offset;
|
||||
}
|
||||
|
||||
leaf.dirty = true;
|
||||
writeNode(leaf);
|
||||
} //}}}
|
||||
|
||||
//{{{ saveToStore() method
|
||||
/**
|
||||
* Save a record to the database with the given ID.
|
||||
*/
|
||||
public void saveToStore(long key, byte[] value)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
long offset = saveToData(key,value);
|
||||
|
||||
saveToIndex(key,offset);
|
||||
} //}}}
|
||||
|
||||
//{{{ saveLookup() method
|
||||
/**
|
||||
* Save all nodes in the lookup array.
|
||||
*/
|
||||
private void saveLookup() throws IOException, BTreeException
|
||||
{
|
||||
if(lookup == null)
|
||||
return;
|
||||
|
||||
for(int i = 0; i < lookup.length; i++)
|
||||
{
|
||||
if(lookup[i].dirty)
|
||||
writeNode(lookup[i]);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ close() method
|
||||
/**
|
||||
* Close the store.
|
||||
*/
|
||||
public void close() throws IOException, BTreeException
|
||||
{
|
||||
saveLookup();
|
||||
index.close();
|
||||
data.close();
|
||||
} //}}}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A store that puts all records as files inside a directory.
|
||||
*/
|
||||
public class FileStore implements Store
|
||||
{
|
||||
private File directory;
|
||||
|
||||
//{{{ FileStore() method
|
||||
public FileStore(String directory)
|
||||
{
|
||||
this(new File(directory));
|
||||
} //}}}
|
||||
|
||||
//{{{ FileStore() method
|
||||
public FileStore(File directory)
|
||||
{
|
||||
this.directory = directory;
|
||||
directory.mkdirs();
|
||||
} //}}}
|
||||
|
||||
//{{{ exists() method
|
||||
public boolean exists(long id)
|
||||
{
|
||||
return new File(directory,String.valueOf(id)).exists();
|
||||
} //}}}
|
||||
|
||||
//{{{ loadFromStore() method
|
||||
/**
|
||||
* Load a record from the database with the given ID.
|
||||
*/
|
||||
public byte[] loadFromStore(long key)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(!exists(key))
|
||||
throw new NoSuchRecordException(key);
|
||||
return readFile(new File(directory,String.valueOf(key)));
|
||||
} //}}}
|
||||
|
||||
//{{{ readFile() method
|
||||
private byte[] readFile(File file) throws IOException
|
||||
{
|
||||
DataInputStream in = new DataInputStream(
|
||||
new FileInputStream(file));
|
||||
byte[] buf = new byte[(int)file.length()];
|
||||
try
|
||||
{
|
||||
in.readFully(buf);
|
||||
}
|
||||
finally
|
||||
{
|
||||
in.close();
|
||||
}
|
||||
return buf;
|
||||
} //}}}
|
||||
|
||||
//{{{ saveToStore() method
|
||||
/**
|
||||
* Save a record to the database with the given ID.
|
||||
*/
|
||||
public void saveToStore(long key, byte[] value) throws IOException
|
||||
{
|
||||
writeFile(new File(directory,String.valueOf(key)),value);
|
||||
} //}}}
|
||||
|
||||
//{{{ writeFile() method
|
||||
private void writeFile(File file, byte[] content) throws IOException
|
||||
{
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
try
|
||||
{
|
||||
out.write(content,0,content.length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ close() method
|
||||
/**
|
||||
* Close the store.
|
||||
*/
|
||||
public void close() throws IOException, PersistenceException
|
||||
{
|
||||
} //}}}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
public class NoSuchRecordException extends PersistenceException
|
||||
{
|
||||
public NoSuchRecordException(long id)
|
||||
{
|
||||
super("No such record: " + id);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.FactorException;
|
||||
|
||||
public class PersistenceException extends FactorException
|
||||
{
|
||||
public PersistenceException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public PersistenceException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public PersistenceException(String msg, Throwable t)
|
||||
{
|
||||
super(msg,t);
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.Cons;
|
||||
import factor.FactorInterpreter;
|
||||
|
||||
/**
|
||||
* A simple wrapper around a byte array stored in the object database.
|
||||
*/
|
||||
public class PersistentBinary implements PersistentObject
|
||||
{
|
||||
private Workspace workspace;
|
||||
private long id;
|
||||
private byte[] bytes;
|
||||
|
||||
//{{{ PersistentBinary constructor
|
||||
public PersistentBinary(Workspace workspace, byte[] bytes)
|
||||
throws Exception
|
||||
{
|
||||
this(workspace,workspace == null ? 0L : workspace.nextID());
|
||||
this.bytes = bytes;
|
||||
} //}}}
|
||||
|
||||
//{{{ PersistentBinary constructor
|
||||
public PersistentBinary(Workspace workspace, long id) throws Exception
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ getBytes() method
|
||||
public byte[] getBytes()
|
||||
{
|
||||
return bytes;
|
||||
} //}}}
|
||||
|
||||
//{{{ getWorkspace() method
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace()
|
||||
{
|
||||
return workspace;
|
||||
} //}}}
|
||||
|
||||
//{{{ getID() method
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID()
|
||||
{
|
||||
return id;
|
||||
} //}}}
|
||||
|
||||
//{{{ pickle() method
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public byte[] pickle()
|
||||
{
|
||||
return bytes;
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public void unpickle(byte[] bytes, int offset)
|
||||
{
|
||||
if(offset == 0)
|
||||
this.bytes = bytes;
|
||||
else
|
||||
{
|
||||
int len = bytes.length - offset;
|
||||
this.bytes = new byte[len];
|
||||
System.arraycopy(bytes,offset,this.bytes,0,len);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getReferences() method
|
||||
public Cons getReferences()
|
||||
{
|
||||
return null;
|
||||
} //}}}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.FactorInterpreter;
|
||||
|
||||
/**
|
||||
* Any objects implementing this interface are written to the database
|
||||
* as f.
|
||||
*/
|
||||
public interface PersistentIgnore {}
|
|
@ -1,63 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.Cons;
|
||||
import factor.FactorInterpreter;
|
||||
|
||||
public interface PersistentObject
|
||||
{
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace();
|
||||
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID();
|
||||
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public byte[] pickle()
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public void unpickle(byte[] bytes, int offset)
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Used for storage compaction.
|
||||
*/
|
||||
public Cons getReferences();
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.FactorLib;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A store that reads records from the class path.
|
||||
*/
|
||||
public class ResourceStore implements Store
|
||||
{
|
||||
private String directory;
|
||||
|
||||
//{{{ ResourceStore() method
|
||||
public ResourceStore(String directory)
|
||||
{
|
||||
this.directory = directory;
|
||||
} //}}}
|
||||
|
||||
//{{{ exists() method
|
||||
public boolean exists(long key)
|
||||
{
|
||||
return getClass().getResource(directory + key) != null;
|
||||
} //}}}
|
||||
|
||||
//{{{ loadFromStore() method
|
||||
/**
|
||||
* Load a record from the database with the given ID.
|
||||
*/
|
||||
public byte[] loadFromStore(long key)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(!exists(key))
|
||||
throw new NoSuchRecordException(key);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
FactorLib.copy(getClass().getResourceAsStream(
|
||||
directory + key),out);
|
||||
return out.toByteArray();
|
||||
} //}}}
|
||||
|
||||
//{{{ saveToStore() method
|
||||
/**
|
||||
* Save a record to the database with the given ID.
|
||||
*/
|
||||
public void saveToStore(long key, byte[] value) throws IOException
|
||||
{
|
||||
throw new IOException("Read only store");
|
||||
} //}}}
|
||||
|
||||
//{{{ close() method
|
||||
/**
|
||||
* Close the store.
|
||||
*/
|
||||
public void close()
|
||||
{
|
||||
} //}}}
|
||||
}
|
|
@ -1,124 +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.db;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An object that persists to a name/value list.
|
||||
*/
|
||||
public class SimplePersistentObject implements FactorObject,
|
||||
PersistentObject
|
||||
{
|
||||
protected Workspace workspace;
|
||||
protected long id;
|
||||
protected Table table;
|
||||
|
||||
//{{{ SimplePersistentObject constructor
|
||||
public SimplePersistentObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
table = new Table(this);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ SimplePersistentObject constructor
|
||||
public SimplePersistentObject(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
table = new Table(this,workspace,0L);
|
||||
} //}}}
|
||||
|
||||
//{{{ SimplePersistentObject constructor
|
||||
public SimplePersistentObject(Workspace workspace) throws Exception
|
||||
{
|
||||
this(workspace,workspace == null ? 0L : workspace.nextID());
|
||||
} //}}}
|
||||
|
||||
//{{{ getWorkspace() method
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace()
|
||||
{
|
||||
return workspace;
|
||||
} //}}}
|
||||
|
||||
//{{{ getID() method
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID()
|
||||
{
|
||||
return id;
|
||||
} //}}}
|
||||
|
||||
//{{{ pickle() method
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public byte[] pickle()
|
||||
throws PersistenceException
|
||||
{
|
||||
return table.pickle();
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public void unpickle(byte[] bytes, int offset)
|
||||
throws PersistenceException
|
||||
{
|
||||
table.unpickle(bytes,offset);
|
||||
} //}}}
|
||||
|
||||
//{{{ getNamespace() method
|
||||
public FactorNamespace getNamespace()
|
||||
throws Exception
|
||||
{
|
||||
return table;
|
||||
} //}}}
|
||||
|
||||
//{{{ getReferences() method
|
||||
public Cons getReferences()
|
||||
{
|
||||
return table.getReferences();
|
||||
} //}}}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The low-level interface to a persistent store.
|
||||
* It can retreive and store string values, keyed by string identifiers.
|
||||
*/
|
||||
public interface Store
|
||||
{
|
||||
public boolean exists(long id)
|
||||
throws IOException, PersistenceException;
|
||||
|
||||
/**
|
||||
* Load a record from the database with the given ID.
|
||||
*/
|
||||
public byte[] loadFromStore(long key)
|
||||
throws IOException, PersistenceException;
|
||||
|
||||
/**
|
||||
* Save a record to the database with the given ID.
|
||||
*/
|
||||
public void saveToStore(long key, byte[] value)
|
||||
throws IOException, PersistenceException;
|
||||
|
||||
/**
|
||||
* Close the store.
|
||||
*/
|
||||
public void close() throws IOException, PersistenceException;
|
||||
}
|
|
@ -1,381 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.*;
|
||||
import java.io.*;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* A table is a persistent namespace.
|
||||
*
|
||||
* The picked format is as follows:
|
||||
*
|
||||
* 4 bytes -- number of rows
|
||||
* Each row:
|
||||
* 4 bytes -- length of name
|
||||
* x bytes -- name
|
||||
* 4 bytes -- length of value
|
||||
* x bytes -- unparsed value
|
||||
* 1 byte -- newline
|
||||
*
|
||||
* All strings are stored as UTF8.
|
||||
*/
|
||||
public class Table extends FactorNamespace implements PersistentObject
|
||||
{
|
||||
public static boolean DEBUG = false;
|
||||
public static final String ENCODING = "UTF8";
|
||||
|
||||
private Workspace workspace;
|
||||
private long id;
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table()
|
||||
{
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table(Workspace workspace) throws Exception
|
||||
{
|
||||
this(workspace,workspace == null ? 0L : workspace.nextID());
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table(Workspace workspace, long id) throws Exception
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table(Object obj) throws Exception
|
||||
{
|
||||
super(obj);
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table(Object obj, Workspace workspace) throws Exception
|
||||
{
|
||||
this(obj,workspace,workspace == null ? 0L : workspace.nextID());
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
public Table(Object obj, Workspace workspace, long id) throws Exception
|
||||
{
|
||||
super(obj);
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ Table constructor
|
||||
/**
|
||||
* Cloning constructor.
|
||||
*/
|
||||
public Table(Map words, Object obj, Workspace workspace)
|
||||
throws Exception
|
||||
{
|
||||
super(words,obj);
|
||||
|
||||
this.workspace = workspace;
|
||||
|
||||
if(workspace != null)
|
||||
{
|
||||
this.id = workspace.nextID();
|
||||
workspace.put(this);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getWorkspace() method
|
||||
/**
|
||||
* Each persistent object is stored in one workspace only.
|
||||
*/
|
||||
public Workspace getWorkspace()
|
||||
{
|
||||
return workspace;
|
||||
} //}}}
|
||||
|
||||
//{{{ getID() method
|
||||
/**
|
||||
* Each persistent object has an associated ID.
|
||||
*/
|
||||
public long getID()
|
||||
{
|
||||
return id;
|
||||
} //}}}
|
||||
|
||||
//{{{ pickleValue() method
|
||||
private synchronized String pickleValue(String name)
|
||||
throws Exception
|
||||
{
|
||||
Object valueObj = words.get(name);
|
||||
|
||||
if(valueObj == null)
|
||||
{
|
||||
lazyFieldInit(name);
|
||||
valueObj = words.get(name);
|
||||
}
|
||||
|
||||
String value;
|
||||
|
||||
if(valueObj instanceof Pickled)
|
||||
{
|
||||
value = ((Pickled)valueObj)
|
||||
.getUnparsed();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = FactorReader.unparseDBObject(
|
||||
getVariable(name));
|
||||
}
|
||||
|
||||
return value;
|
||||
} //}}}
|
||||
|
||||
//{{{ pickle() method
|
||||
/**
|
||||
* Each persistent object can turn itself into a byte array.
|
||||
*/
|
||||
public synchronized byte[] pickle()
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bytes);
|
||||
|
||||
Cons values = toVarList();
|
||||
|
||||
if(values == null)
|
||||
out.writeInt(0);
|
||||
else
|
||||
out.writeInt(values.length());
|
||||
|
||||
while(values != null)
|
||||
{
|
||||
String name = (String)values.car;
|
||||
out.writeInt(name.length());
|
||||
byte[] nameBytes = name.getBytes(ENCODING);
|
||||
out.write(nameBytes);
|
||||
|
||||
String value = pickleValue(name);
|
||||
|
||||
out.writeInt(value.length());
|
||||
byte[] valueBytes = value.getBytes(ENCODING);
|
||||
out.write(valueBytes);
|
||||
|
||||
out.write('\n');
|
||||
|
||||
values = values.next();
|
||||
}
|
||||
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ unpickle() method
|
||||
/**
|
||||
* Each persistent object can set its state to that in a byte array.
|
||||
*/
|
||||
public synchronized void unpickle(byte[] bytes, int offset)
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
|
||||
bin.skip(offset);
|
||||
DataInputStream in = new DataInputStream(bin);
|
||||
|
||||
int count = in.readInt();
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
int nameLength = in.readInt();
|
||||
byte[] nameBytes = new byte[nameLength];
|
||||
in.readFully(nameBytes);
|
||||
|
||||
String name = new String(nameBytes,ENCODING);
|
||||
|
||||
int valueLength = in.readInt();
|
||||
|
||||
byte[] valueBytes = new byte[valueLength];
|
||||
in.readFully(valueBytes);
|
||||
|
||||
// skip newline at the end
|
||||
in.readByte();
|
||||
|
||||
String value = new String(valueBytes,ENCODING);
|
||||
|
||||
Object obj = words.get(name);
|
||||
if(obj == null)
|
||||
{
|
||||
lazyFieldInit(name);
|
||||
obj = words.get(name);
|
||||
}
|
||||
|
||||
if(obj instanceof VarBinding)
|
||||
{
|
||||
try
|
||||
{
|
||||
setVariable(name,FactorReader.parseObject(
|
||||
value,workspace.getInterpreter()));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//XXX: what to do here
|
||||
System.err.println("Unexpected error when setting " + name + " to " + value);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// super becaue we don't want this to add the
|
||||
// table to the save queue
|
||||
super.setVariable(name,new Pickled(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getVariable() method
|
||||
public synchronized Object getVariable(String name) throws Exception
|
||||
{
|
||||
Object value = super.getVariable(name);
|
||||
if(value instanceof Pickled)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(DEBUG)
|
||||
System.err.println(this + ".getVariable(" + name + "): "
|
||||
+ value);
|
||||
|
||||
value = FactorReader.parseObject(((Pickled)value)
|
||||
.getUnparsed(),workspace.getInterpreter());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new FactorRuntimeException("Table " + getID() + " has unreadable values",e);
|
||||
}
|
||||
|
||||
// super becaue we don't want this to add the table
|
||||
// to the save queue
|
||||
super.setVariable(name,value);
|
||||
}
|
||||
return value;
|
||||
} //}}}
|
||||
|
||||
//{{{ setVariable() method
|
||||
public synchronized void setVariable(String name, Object value)
|
||||
throws Exception
|
||||
{
|
||||
super.setVariable(name,value);
|
||||
if(workspace != null && id != 0L)
|
||||
workspace.put(this);
|
||||
} //}}}
|
||||
|
||||
//{{{ clone() method
|
||||
public FactorNamespace clone(Object rebind)
|
||||
{
|
||||
if(rebind.getClass() != obj.getClass())
|
||||
throw new RuntimeException("Cannot rebind to different type");
|
||||
|
||||
try
|
||||
{
|
||||
return new Table(words,rebind,workspace);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new InternalError();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ clone() method
|
||||
public Object clone()
|
||||
{
|
||||
if(obj != null)
|
||||
throw new RuntimeException("Cannot clone namespace that's bound to an object");
|
||||
|
||||
try
|
||||
{
|
||||
return new Table(new TreeMap(words),null,workspace);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new InternalError();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ Pickled class
|
||||
/**
|
||||
* We lazily parse values in tables. An unparsed value is represented
|
||||
* by an instance of this class.
|
||||
*/
|
||||
static class Pickled
|
||||
{
|
||||
private String unparsed;
|
||||
|
||||
Pickled(String unparsed)
|
||||
{
|
||||
this.unparsed = unparsed;
|
||||
}
|
||||
|
||||
String getUnparsed()
|
||||
{
|
||||
return unparsed;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return unparsed;
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getReferences() method
|
||||
public synchronized Cons getReferences()
|
||||
{
|
||||
return new Cons(getThis(),toVarList());
|
||||
} //}}}
|
||||
}
|
|
@ -1,517 +0,0 @@
|
|||
/* :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.db;
|
||||
|
||||
import factor.*;
|
||||
import java.io.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A workspace is an orthogonal persistence store.
|
||||
*
|
||||
* Record format is:
|
||||
* - 1 byte: name length
|
||||
* - n bytes: class name
|
||||
* - remainder: bytes passed to new instance unpickle()
|
||||
*/
|
||||
public class Workspace
|
||||
{
|
||||
/**
|
||||
* A map of WeakReferences. All instances of this class are stored
|
||||
* here.
|
||||
*/
|
||||
private static Map instances = new WeakHashMap();
|
||||
|
||||
private static WorkspaceSaveDaemon flushThread = new WorkspaceSaveDaemon();
|
||||
public static boolean LOAD_DEBUG = false;
|
||||
public static boolean SAVE_DEBUG = false;
|
||||
|
||||
/**
|
||||
* The ID of the header record. A value never returned by
|
||||
* nextID().
|
||||
*/
|
||||
public static final long HEADER = -1;
|
||||
|
||||
public static final String DB_VERSION = "1.0";
|
||||
public static int flushInterval = 5000;
|
||||
|
||||
/**
|
||||
* In a read-only workspace, changes are silently discarded on
|
||||
* shutdown.
|
||||
*/
|
||||
private boolean readOnly;
|
||||
|
||||
private Store store;
|
||||
private FactorInterpreter interp;
|
||||
private HashSet saveQueue;
|
||||
|
||||
/**
|
||||
* Floating objects are currently in-memory.
|
||||
* This map maps IDs to WeakReferences.
|
||||
*/
|
||||
private Map floating;
|
||||
|
||||
/**
|
||||
* Table containing important values. Always in memory.
|
||||
*/
|
||||
private Table header;
|
||||
|
||||
/**
|
||||
* For resolving circular references, currently loading objects.
|
||||
*/
|
||||
private Map loading;
|
||||
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* Track all IDs handed out with nextID(), and make sure they
|
||||
* eventually reach the store.
|
||||
*/
|
||||
private Set pendingIDs = new TreeSet();
|
||||
|
||||
//{{{ Workspace constructor
|
||||
public Workspace(Store store, boolean readOnly,
|
||||
FactorInterpreter interp)
|
||||
throws Exception
|
||||
{
|
||||
this.store = store;
|
||||
this.readOnly = readOnly;
|
||||
this.interp = interp;
|
||||
floating = new HashMap();
|
||||
saveQueue = new HashSet();
|
||||
loading = new HashMap();
|
||||
|
||||
if(store.exists(HEADER))
|
||||
header = (Table)get(HEADER);
|
||||
else
|
||||
{
|
||||
header = new Table(this,HEADER);
|
||||
initHeader();
|
||||
}
|
||||
|
||||
instances.put(this,Boolean.TRUE);
|
||||
} //}}}
|
||||
|
||||
//{{{ isFirstTime() method
|
||||
public boolean isFirstTime()
|
||||
{
|
||||
try
|
||||
{
|
||||
return header.getVariable("first-time") != null;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ setFirstTime() method
|
||||
public void setFirstTime(boolean firstTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
header.setVariable("first-time",firstTime
|
||||
? Boolean.TRUE : null);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ isReadOnly() method
|
||||
/**
|
||||
* In a 'read only' workspace, changes are silently discarded when
|
||||
* the workspace is closed.
|
||||
*/
|
||||
public boolean isReadOnly()
|
||||
{
|
||||
return readOnly;
|
||||
} //}}}
|
||||
|
||||
//{{{ initHeader() method
|
||||
public void initHeader() throws Exception
|
||||
{
|
||||
header.setVariable("nextID",new Long(0));
|
||||
header.setVariable("root",new Table(this));
|
||||
header.setVariable("version",DB_VERSION);
|
||||
header.setVariable("first-time",Boolean.TRUE);
|
||||
} //}}}
|
||||
|
||||
//{{{ getRoot() method
|
||||
/**
|
||||
* Returns the workspace root.
|
||||
*/
|
||||
public Table getRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Table)header.getVariable("root");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getInterpreter() method
|
||||
public FactorInterpreter getInterpreter()
|
||||
{
|
||||
return interp;
|
||||
} //}}}
|
||||
|
||||
//{{{ nextID() method
|
||||
public synchronized long nextID()// throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
long nextID = FactorJava.toLong(
|
||||
header.getVariable("nextID"));
|
||||
if(nextID == Long.MAX_VALUE)
|
||||
throw new RuntimeException("FIXME!");
|
||||
|
||||
nextID++;
|
||||
|
||||
Long nextIDboxed = new Long(nextID);
|
||||
header.setVariable("nextID",nextIDboxed);
|
||||
pendingIDs.add(nextIDboxed);
|
||||
return nextID;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ load() method
|
||||
/**
|
||||
* Load an object.
|
||||
*/
|
||||
private PersistentObject load(long id)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
PersistentObject circularRef = (PersistentObject)
|
||||
loading.get(new Long(id));
|
||||
|
||||
if(circularRef != null)
|
||||
return circularRef;
|
||||
|
||||
if(LOAD_DEBUG)
|
||||
System.err.println("Loading from store: " + id);
|
||||
byte[] data = store.loadFromStore(id);
|
||||
byte len = data[0];
|
||||
String className = new String(data,1,len,"ASCII");
|
||||
|
||||
// hack :-)
|
||||
try
|
||||
{
|
||||
PersistentObject obj = (PersistentObject)
|
||||
Class.forName(className)
|
||||
.getConstructor(new Class[] {
|
||||
Workspace.class, long.class
|
||||
}).newInstance(new Object[] {
|
||||
this, new Long(id)
|
||||
});
|
||||
|
||||
loading.put(new Long(id),obj);
|
||||
|
||||
obj.unpickle(data,len + 1);
|
||||
return obj;
|
||||
}
|
||||
catch(PersistenceException p)
|
||||
{
|
||||
throw p;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
loading.remove(new Long(id));
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ loadToCache() method
|
||||
/**
|
||||
* Load an object with given ID and store it in the floating map.
|
||||
*/
|
||||
private PersistentObject loadToCache(long id)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
PersistentObject obj = load(id);
|
||||
WeakReference ref = new WeakReference(obj);
|
||||
floating.put(new Long(id),ref);
|
||||
return obj;
|
||||
} //}}}
|
||||
|
||||
//{{{ get() method
|
||||
/**
|
||||
* If an object is already loaded, return that instance, otherwise
|
||||
* load it.
|
||||
*/
|
||||
public synchronized PersistentObject get(long id)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(closed)
|
||||
throw new PersistenceException();
|
||||
|
||||
WeakReference ref = (WeakReference)floating.get(new Long(id));
|
||||
if(ref == null)
|
||||
return loadToCache(id);
|
||||
else
|
||||
{
|
||||
PersistentObject obj = (PersistentObject)ref.get();
|
||||
if(obj == null)
|
||||
return loadToCache(id);
|
||||
else
|
||||
{
|
||||
if(LOAD_DEBUG)
|
||||
System.err.println("Found cached: " + id);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ addToCache() method
|
||||
private void addToCache(PersistentObject obj)
|
||||
throws PersistenceException
|
||||
{
|
||||
if(obj.getWorkspace() != this)
|
||||
throw new PersistenceException("Object from another workspace");
|
||||
|
||||
Long id = new Long(obj.getID());
|
||||
|
||||
WeakReference ref = (WeakReference)floating.get(id);
|
||||
if(ref == null)
|
||||
floating.put(id,new WeakReference(obj));
|
||||
else
|
||||
{
|
||||
Object referenced = ref.get();
|
||||
if(referenced != obj)
|
||||
throw new PersistenceException(referenced + " != " + obj);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ save() method
|
||||
/**
|
||||
* Store an object.
|
||||
*/
|
||||
private void save(PersistentObject obj)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
save(obj,store);
|
||||
} //}}}
|
||||
|
||||
//{{{ save() method
|
||||
/**
|
||||
* Store an object.
|
||||
*/
|
||||
private void save(PersistentObject obj, Store store)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(SAVE_DEBUG)
|
||||
System.err.println("Saving object " + obj.getID());
|
||||
|
||||
if(readOnly)
|
||||
throw new RuntimeException();
|
||||
|
||||
pendingIDs.remove(new Long(obj.getID()));
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
String className = obj.getClass().getName();
|
||||
bout.write((byte)className.length());
|
||||
bout.write(className.getBytes("ASCII"));
|
||||
bout.write(obj.pickle());
|
||||
store.saveToStore(obj.getID(),bout.toByteArray());
|
||||
} //}}}
|
||||
|
||||
//{{{ put() method
|
||||
/**
|
||||
* Add an object to the save queue.
|
||||
*/
|
||||
public synchronized void put(PersistentObject obj)
|
||||
throws PersistenceException
|
||||
{
|
||||
if(closed)
|
||||
throw new PersistenceException();
|
||||
|
||||
addToCache(obj);
|
||||
saveQueue.add(obj);
|
||||
} //}}}
|
||||
|
||||
//{{{ flush() method
|
||||
/**
|
||||
* Write all pending unsaved objects to the store.
|
||||
*/
|
||||
public synchronized void flush()
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
if(closed || readOnly)
|
||||
return;
|
||||
|
||||
Iterator iter = saveQueue.iterator();
|
||||
while(iter.hasNext())
|
||||
{
|
||||
PersistentObject obj = (PersistentObject)iter.next();
|
||||
save(obj);
|
||||
iter.remove();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compact() method
|
||||
/**
|
||||
* Write all referencable objects to the given store.
|
||||
*/
|
||||
private void compact(Store store)
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
Set open = new HashSet();
|
||||
Set closed = new HashSet();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(open.isEmpty())
|
||||
break;
|
||||
|
||||
Iterator iter = open.iterator();
|
||||
Object obj = iter.next();
|
||||
iter.remove();
|
||||
|
||||
closed.add(obj);
|
||||
|
||||
Cons references;
|
||||
if(obj instanceof PersistentObject)
|
||||
{
|
||||
PersistentObject pobj = (PersistentObject)obj;
|
||||
save(pobj,store);
|
||||
references = pobj.getReferences();
|
||||
}
|
||||
else
|
||||
references = (Cons)obj;
|
||||
|
||||
while(references != null)
|
||||
{
|
||||
Object ref = references.car;
|
||||
if((references.car instanceof PersistentObject
|
||||
|| references.car instanceof Cons)
|
||||
&& !closed.contains(references.car))
|
||||
{
|
||||
open.add(references.car);
|
||||
}
|
||||
if(references.cdr instanceof Cons)
|
||||
references = references.next();
|
||||
else
|
||||
{
|
||||
if(references.cdr != null
|
||||
&&
|
||||
!closed.contains(references.car))
|
||||
{
|
||||
open.add(references.cdr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ close() method
|
||||
/**
|
||||
* Close the workspace.
|
||||
*/
|
||||
public synchronized void close()
|
||||
throws IOException, PersistenceException
|
||||
{
|
||||
flush();
|
||||
|
||||
closed = true;
|
||||
|
||||
if(pendingIDs.size() != 0)
|
||||
{
|
||||
System.err.println("The following IDs did not get saved:");
|
||||
System.err.println(pendingIDs);
|
||||
}
|
||||
|
||||
store.close();
|
||||
} //}}}
|
||||
|
||||
//{{{ finalize() method
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
super.finalize();
|
||||
close();
|
||||
} //}}}
|
||||
|
||||
//{{{ WorkspaceSaveDaemon class
|
||||
static class WorkspaceSaveDaemon extends Thread
|
||||
{
|
||||
WorkspaceSaveDaemon()
|
||||
{
|
||||
setDaemon(true);
|
||||
start();
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
Iterator workspaces = instances.keySet().iterator();
|
||||
while(workspaces.hasNext())
|
||||
{
|
||||
Workspace workspace = (Workspace)
|
||||
workspaces.next();
|
||||
try
|
||||
{
|
||||
workspace.flush();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.err.println("ERROR WHILE SAVING WORKSPACE.");
|
||||
System.err.println("Workspace will be closed.");
|
||||
synchronized(workspace)
|
||||
{
|
||||
workspace.closed = true;
|
||||
}
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(flushInterval);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
}
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Bar extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class Bar extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Bar(FactorWord word, Workspace workspace)
|
||||
public Bar(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Base extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -40,10 +39,10 @@ public class Base extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Base(FactorWord word, Workspace workspace, int base)
|
||||
public Base(FactorWord word, int base)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.base = base;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Bra extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class Bra extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Bra(FactorWord word, Workspace workspace)
|
||||
public Bra(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CharLiteral extends FactorParsingDefinition
|
||||
|
@ -39,20 +38,10 @@ public class CharLiteral extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public CharLiteral(FactorWord word, Workspace workspace)
|
||||
public CharLiteral(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ CharLiteral constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public CharLiteral(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import factor.math.*;
|
||||
|
||||
public class ComplexLiteral extends FactorParsingDefinition
|
||||
|
@ -41,11 +40,10 @@ public class ComplexLiteral extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public ComplexLiteral(FactorWord word,
|
||||
String end, Workspace workspace)
|
||||
public ComplexLiteral(FactorWord word, String end)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.end = end;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Def extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class Def extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Def(FactorWord word, Workspace workspace)
|
||||
public Def(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Defer extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class Defer extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Defer(FactorWord word, Workspace workspace)
|
||||
public Defer(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Dispatch extends FactorParsingDefinition
|
||||
|
@ -39,10 +38,10 @@ public class Dispatch extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Dispatch(FactorWord word, Workspace workspace)
|
||||
public Dispatch(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class F extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class F extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public F(FactorWord word, Workspace workspace)
|
||||
public F(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/* :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.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class GetPersistentObject extends FactorParsingDefinition
|
||||
{
|
||||
//{{{ GetPersistentObject constructor
|
||||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public GetPersistentObject(FactorWord word, Workspace workspace)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
throws Exception
|
||||
{
|
||||
long id = FactorJava.toLong(reader.next(true,false));
|
||||
|
||||
if(interp.workspace == null)
|
||||
reader.getScanner().error("No workspace");
|
||||
else
|
||||
reader.append(interp.workspace.get(id));
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class In extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class In extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public In(FactorWord word, Workspace workspace)
|
||||
public In(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Ine extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -40,10 +39,10 @@ public class Ine extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Ine(FactorWord start, FactorWord end, Workspace workspace)
|
||||
public Ine(FactorWord start, FactorWord end)
|
||||
throws Exception
|
||||
{
|
||||
super(end,workspace);
|
||||
super(end);
|
||||
this.start = start;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Ket extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -40,10 +39,10 @@ public class Ket extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Ket(FactorWord start, FactorWord end, Workspace workspace)
|
||||
public Ket(FactorWord start, FactorWord end)
|
||||
throws Exception
|
||||
{
|
||||
super(end,workspace);
|
||||
super(end);
|
||||
this.start = start;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LineComment extends FactorParsingDefinition
|
||||
|
@ -41,10 +40,10 @@ public class LineComment extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public LineComment(FactorWord word, boolean doc, Workspace workspace)
|
||||
public LineComment(FactorWord word, boolean doc)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.doc = doc;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class NoParsing extends FactorParsingDefinition
|
||||
|
@ -39,10 +38,10 @@ public class NoParsing extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public NoParsing(FactorWord word, Workspace workspace)
|
||||
public NoParsing(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PassThrough extends FactorParsingDefinition
|
||||
|
@ -39,10 +38,10 @@ public class PassThrough extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public PassThrough(FactorWord word, Workspace workspace)
|
||||
public PassThrough(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Shuffle extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -40,10 +39,10 @@ public class Shuffle extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Shuffle(FactorWord word, String end, Workspace workspace)
|
||||
public Shuffle(FactorWord word, String end)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.end = end;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class StackComment extends FactorParsingDefinition
|
||||
|
@ -39,10 +38,10 @@ public class StackComment extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public StackComment(FactorWord word, Workspace workspace)
|
||||
public StackComment(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class StringLiteral extends FactorParsingDefinition
|
||||
|
@ -41,11 +40,10 @@ public class StringLiteral extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public StringLiteral(FactorWord word, boolean escapes,
|
||||
Workspace workspace)
|
||||
public StringLiteral(FactorWord word, boolean escapes)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.escapes = escapes;
|
||||
} //}}}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class T extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class T extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public T(FactorWord word, Workspace workspace)
|
||||
public T(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Unreadable extends FactorParsingDefinition
|
||||
|
@ -39,10 +38,10 @@ public class Unreadable extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Unreadable(FactorWord word, Workspace workspace)
|
||||
public Unreadable(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
public void eval(FactorInterpreter interp, FactorReader reader)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.parser;
|
||||
|
||||
import factor.*;
|
||||
import factor.db.*;
|
||||
|
||||
public class Use extends FactorParsingDefinition
|
||||
{
|
||||
|
@ -38,10 +37,10 @@ public class Use extends FactorParsingDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Use(FactorWord word, Workspace workspace)
|
||||
public Use(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -1 +1 @@
|
|||
!a;1592;1592
|
||||
!a;1572;1572
|
||||
|
|
|
@ -1 +1 @@
|
|||
!a;1536;1536
|
||||
!a;1494;1494
|
||||
|
|
|
@ -1 +1 @@
|
|||
!a;1592;1592
|
||||
!a;1572;1572
|
||||
|
|
|
@ -1 +1 @@
|
|||
!a;1592;1592
|
||||
!a;1572;1572
|
||||
|
|
|
@ -1 +1 @@
|
|||
!a;1592;1592
|
||||
!a;1572;1572
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,9 @@ public class Call extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Call(FactorWord word, Workspace workspace)
|
||||
throws Exception
|
||||
public Call(FactorWord word)
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Call constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Call(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,9 +30,7 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class Coerce extends FactorPrimitiveDefinition
|
||||
|
@ -41,20 +39,10 @@ public class Coerce extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Coerce(FactorWord word, Workspace workspace)
|
||||
public Coerce(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Coerce constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Coerce(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,9 +30,7 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class Define extends FactorPrimitiveDefinition
|
||||
{
|
||||
|
@ -40,20 +38,10 @@ public class Define extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Define(FactorWord word, Workspace workspace)
|
||||
public Define(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Define constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Define(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Set;
|
||||
|
@ -42,20 +41,10 @@ public class Execute extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Execute(FactorWord word, Workspace workspace)
|
||||
public Execute(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Execute constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Execute(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
|
@ -40,20 +39,10 @@ public class Ifte extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Ifte(FactorWord word, Workspace workspace)
|
||||
public Ifte(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Ifte constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Ifte(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.*;
|
||||
|
@ -41,20 +40,10 @@ public class InterpreterGet extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public InterpreterGet(FactorWord word, Workspace workspace)
|
||||
public InterpreterGet(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ InterpreterGet constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public InterpreterGet(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -44,24 +43,13 @@ public class JInvoke extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JInvoke(FactorWord word, Workspace workspace,
|
||||
boolean staticMethod)
|
||||
public JInvoke(FactorWord word, boolean staticMethod)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
super(word);
|
||||
this.staticMethod = staticMethod;
|
||||
} //}}}
|
||||
|
||||
//{{{ JInvoke constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JInvoke(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
} //}}}
|
||||
|
||||
//{{{ checkStatic() method
|
||||
private void checkStatic(Method method) throws FactorRuntimeException
|
||||
{
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,10 @@ public class JNew extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JNew(FactorWord word, Workspace workspace)
|
||||
public JNew(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ JNew constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JNew(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,10 @@ public class JVarGet extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JVarGet(FactorWord word, Workspace workspace)
|
||||
public JVarGet(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ JVarGet constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JVarGet(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,10 @@ public class JVarGetStatic extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JVarGetStatic(FactorWord word, Workspace workspace)
|
||||
public JVarGetStatic(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ JVarGetStatic constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JVarGetStatic(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,10 @@ public class JVarSet extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JVarSet(FactorWord word, Workspace workspace)
|
||||
public JVarSet(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ JVarSet constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JVarSet(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
@ -42,20 +41,10 @@ public class JVarSetStatic extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public JVarSetStatic(FactorWord word, Workspace workspace)
|
||||
public JVarSetStatic(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ JVarSetStatic constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public JVarSetStatic(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -40,20 +39,10 @@ public class Restack extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Restack(FactorWord word, Workspace workspace)
|
||||
public Restack(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Restack constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Restack(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.db.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -40,20 +39,10 @@ public class Unstack extends FactorPrimitiveDefinition
|
|||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public Unstack(FactorWord word, Workspace workspace)
|
||||
public Unstack(FactorWord word)
|
||||
throws Exception
|
||||
{
|
||||
super(word,workspace);
|
||||
} //}}}
|
||||
|
||||
//{{{ Unstack constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public Unstack(Workspace workspace, long id)
|
||||
throws Exception
|
||||
{
|
||||
super(workspace,id);
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ eval() method
|
||||
|
|
|
@ -29,9 +29,9 @@ IN: errors
|
|||
USE: combinators
|
||||
USE: continuations
|
||||
USE: kernel
|
||||
USE: inspector
|
||||
USE: logic
|
||||
USE: namespaces
|
||||
USE: prettyprint
|
||||
USE: stack
|
||||
USE: stdio
|
||||
USE: strings
|
||||
|
@ -65,14 +65,7 @@ USE: unparser
|
|||
|
||||
suspend ;
|
||||
|
||||
: ?describe-stack ( stack -- )
|
||||
dup [
|
||||
describe-stack
|
||||
] [
|
||||
drop "No stack" print
|
||||
] ifte ;
|
||||
|
||||
: :s ( -- ) "error-datastack" get ?describe-stack ;
|
||||
: :r ( -- ) "error-callstack" get ?describe-stack ;
|
||||
: :n ( -- ) "error-namestack" get ?describe-stack ;
|
||||
: :c ( -- ) "error-catchstack" get ?describe-stack ;
|
||||
: :s ( -- ) "error-datastack" get prettyprint ;
|
||||
: :r ( -- ) "error-callstack" get prettyprint ;
|
||||
: :n ( -- ) "error-namestack" get prettyprint ;
|
||||
: :c ( -- ) "error-catchstack" get prettyprint ;
|
||||
|
|
|
@ -36,18 +36,11 @@ USE: stack
|
|||
USE: strings
|
||||
USE: vectors
|
||||
|
||||
: >c ( catch -- )
|
||||
#! Push a catch block on the catchstack. Use the catch word
|
||||
#! instead of invoking this word directly.
|
||||
catchstack* vector-push ;
|
||||
|
||||
: c> ( catch -- )
|
||||
#! Pop a catch block from the catchstack. Use the catch word
|
||||
#! instead of invoking this word directly.
|
||||
catchstack* vector-pop ;
|
||||
: >c ( catch -- ) catchstack* vector-push ;
|
||||
: c> ( catch -- ) catchstack* vector-pop ;
|
||||
|
||||
: save-error ( error -- )
|
||||
#! Save the stacks for most-mortem inspection after an
|
||||
#! Save the stacks for post-mortem inspection after an
|
||||
#! error.
|
||||
global [
|
||||
"error" set
|
||||
|
@ -58,18 +51,14 @@ USE: vectors
|
|||
] bind ;
|
||||
|
||||
: catch ( try catch -- )
|
||||
#! Call the try quotation, restore the datastack to its
|
||||
#! state before the try quotation, push the error (or f if
|
||||
#! no error occurred) and call the catch quotation.
|
||||
[ >c >r call c> drop f r> f ] callcc1
|
||||
( try catch error ) rot drop swap ( error catch ) call ;
|
||||
#! Call the try quotation. If an error occurs restore the
|
||||
#! datastack, push the error, and call the catch block.
|
||||
#! If no error occurs, push f and call the catch block.
|
||||
[ >c >r call c> drop f r> f ] callcc1 rot drop swap call ;
|
||||
|
||||
: rethrow ( error -- )
|
||||
#! Use rethrow when passing an error on from a catch block.
|
||||
#! For convinience, this word is a no-op if error is f.
|
||||
[ c> call ] when* ;
|
||||
|
||||
: throw ( error -- )
|
||||
#! Throw an error. If no catch handlers are installed, the
|
||||
#! default-error-handler is called.
|
||||
dup save-error rethrow ;
|
||||
: throw ( error -- ) dup save-error rethrow ;
|
||||
|
|
|
@ -37,7 +37,7 @@ USE: wiki-responder
|
|||
: default-responders ( -- )
|
||||
#! Remove all existing responders, and create a blank
|
||||
#! responder table.
|
||||
<table> [
|
||||
<namespace> [
|
||||
<responder> [
|
||||
"test" "responder" set
|
||||
[ test-responder ] "get" set
|
||||
|
@ -63,7 +63,7 @@ USE: wiki-responder
|
|||
"wiki" "responder" set
|
||||
[ wiki-get-responder ] "get" set
|
||||
[ wiki-post-responder ] "post" set
|
||||
<table> "wiki" set
|
||||
<namespace> "wiki" set
|
||||
"WikiHome" "default-argument" set
|
||||
] extend "wiki" set
|
||||
] extend "httpd-responders" set ;
|
||||
|
|
|
@ -39,7 +39,7 @@ USE: strings
|
|||
USE: httpd
|
||||
|
||||
: <responder> ( -- responder )
|
||||
<table> [
|
||||
<namespace> [
|
||||
[
|
||||
drop "GET method not implemented" httpd-error
|
||||
] "get" set
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
IN: inspector
|
||||
USE: combinators
|
||||
USE: errors
|
||||
USE: format
|
||||
USE: kernel
|
||||
USE: lists
|
||||
|
@ -82,14 +81,6 @@ USE: vocabularies
|
|||
[ prettyprint terpri ]
|
||||
] cond ;
|
||||
|
||||
: describe-stack ( vector -- )
|
||||
stack>list [.] ;
|
||||
|
||||
: .n namestack describe-stack ;
|
||||
: .s datastack describe-stack ;
|
||||
: .r callstack describe-stack ;
|
||||
: .c catchstack describe-stack ;
|
||||
|
||||
: describe-object-path ( string -- )
|
||||
<namespace> [
|
||||
dup "object-path" set
|
||||
|
|
|
@ -69,7 +69,6 @@ USE: parser
|
|||
"/library/stdio.factor" run-resource ! stdio
|
||||
"/library/platform/jvm/unparser.factor" run-resource ! unparser
|
||||
"/library/platform/jvm/parser.factor" run-resource ! parser
|
||||
"/library/platform/jvm/workspace.factor" run-resource ! workspace
|
||||
"/library/styles.factor" run-resource ! styles
|
||||
|
||||
!!! Math library.
|
||||
|
|
|
@ -70,7 +70,6 @@ USE: parser
|
|||
"/library/stdio.factor" run-resource ! stdio
|
||||
"/library/platform/jvm/unparser.factor" run-resource ! unparser
|
||||
"/library/platform/jvm/parser.factor" run-resource ! parser
|
||||
"/library/platform/jvm/workspace.factor" run-resource ! workspace
|
||||
"/library/styles.factor" run-resource ! styles
|
||||
"/library/platform/jvm/threads.factor" run-resource ! threads
|
||||
"/library/logging.factor" run-resource ! logging
|
||||
|
|
|
@ -118,5 +118,7 @@ USE: strings
|
|||
compile-all
|
||||
] when
|
||||
|
||||
t "startup-done" set
|
||||
|
||||
print-banner
|
||||
init-interpreter ;
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
!:folding=indent: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.
|
||||
|
||||
!!! A "store" is a flat-file database that identifies byte
|
||||
!!! arrays with 8-byte keys. Several implementations are
|
||||
!!! available. There are several low-level words for creating
|
||||
!!! and working with your own stores, but usually these words
|
||||
!!! are only used for testing.
|
||||
!!!
|
||||
!!! A "workspace" sits on top of a store and implements
|
||||
!!! picking/unpickling of persistent objects in the store.
|
||||
!!!
|
||||
!!! Each persistent object has an 8-byte ID; this is the same
|
||||
!!! ID used to save/load the object in the store.
|
||||
!!!
|
||||
!!! Additinally, each persistent object knows how to
|
||||
!!! pickle/unpickle itself.
|
||||
|
||||
IN: workspace
|
||||
USE: combinators
|
||||
USE: namespaces
|
||||
USE: stack
|
||||
USE: streams
|
||||
|
||||
: workspace ( -- workspace )
|
||||
#! Push the current workspace.
|
||||
interpreter [ "workspace" get ] bind ;
|
||||
|
||||
: <btree-store> ( filename order readonly -- store )
|
||||
#! Create a B-tree store. The B-tree store puts all records
|
||||
#! inside a single file, using an auxiliary file holding a
|
||||
#! B-tree to implement fast searches.
|
||||
[ <file> ] 2dip
|
||||
[ "java.io.File" "byte" "boolean" ]
|
||||
"factor.db.BTreeStore" jnew ;
|
||||
|
||||
: <file-store> ( filename -- store )
|
||||
#! Create a file store. The file store puts all records
|
||||
#! inside individual files in a directory.
|
||||
[ "java.lang.String" ] "factor.db.FileStore" jnew ;
|
||||
|
||||
: store-get ( id store -- )
|
||||
#! Retreive a value from the store.
|
||||
[ "long" ] "factor.db.Store" "loadFromStore"
|
||||
jinvoke ;
|
||||
|
||||
: store-set ( id value store -- )
|
||||
#! Put a value in the store.
|
||||
[ "long" [ "byte" ] ] "factor.db.Store" "saveToStore"
|
||||
jinvoke ;
|
||||
|
||||
: in-store? ( id store -- ? )
|
||||
#! Check if a value is in the store.
|
||||
[ "long" ] "factor.db.Store" "exists" jinvoke ;
|
||||
|
||||
: close-store ( store -- )
|
||||
#! Close a store, completing all pending transactions.
|
||||
[ ] "factor.db.Store" "close" jinvoke ;
|
||||
|
||||
: save-workspace ( -- )
|
||||
#! Complete all pending transactions in the workspace.
|
||||
workspace [ ] "factor.db.Workspace" "flush" jinvoke ;
|
||||
|
||||
IN: namespaces
|
||||
|
||||
: <table> ( -- table )
|
||||
#! A table is a persistent namespace.
|
||||
workspace
|
||||
[ "factor.db.Workspace" ] "factor.db.Table" jnew ;
|
||||
|
||||
: alist>table ( alist -- table )
|
||||
<table> tuck alist> ;
|
|
@ -85,6 +85,3 @@ DEFER: >n
|
|||
: namespace-of ;
|
||||
: this namespace ;
|
||||
: has-namespace? hashtable? ;
|
||||
|
||||
! We don't have a workspace in native Factor.
|
||||
: <table> <namespace> ;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
IN: prettyprint
|
||||
USE: arithmetic
|
||||
USE: combinators
|
||||
USE: errors
|
||||
USE: format
|
||||
USE: kernel
|
||||
USE: logic
|
||||
|
@ -39,6 +40,7 @@ USE: stdio
|
|||
USE: strings
|
||||
USE: styles
|
||||
USE: unparser
|
||||
USE: vectors
|
||||
USE: vocabularies
|
||||
USE: words
|
||||
|
||||
|
@ -75,6 +77,22 @@ DEFER: prettyprint*
|
|||
: prettyprint-[] ( indent list -- indent )
|
||||
swap prettyprint-[ swap prettyprint-list prettyprint-] ;
|
||||
|
||||
: prettyprint-{ ( indent -- indent )
|
||||
"{" write
|
||||
tab-size + dup prettyprint-newline ;
|
||||
|
||||
: prettyprint-} ( indent -- indent )
|
||||
tab-size - dup prettyprint-newline
|
||||
"}" write
|
||||
prettyprint-space ;
|
||||
|
||||
: prettyprint-vector ( indent list -- indent )
|
||||
#! Pretty-print a vector, without { and }.
|
||||
[ prettyprint* ] vector-each ;
|
||||
|
||||
: prettyprint-{} ( indent list -- indent )
|
||||
swap prettyprint-{ swap prettyprint-vector prettyprint-} ;
|
||||
|
||||
: write-comment ( comment -- )
|
||||
[ "comments" ] get-style [ write-attr ] bind ;
|
||||
|
||||
|
@ -112,6 +130,7 @@ DEFER: prettyprint*
|
|||
[
|
||||
[ not ] [ prettyprint-object ]
|
||||
[ list? ] [ prettyprint-[] ]
|
||||
[ vector? ] [ prettyprint-{} ]
|
||||
[ comment? ] [ prettyprint-comment ]
|
||||
[ word? ] [ prettyprint-word ]
|
||||
[ drop t ] [ prettyprint-object ]
|
||||
|
@ -131,3 +150,8 @@ DEFER: prettyprint*
|
|||
: prettyprint-:; ( indent word list -- indent )
|
||||
[ [ prettyprint-: ] dip prettyprint-word ] dip
|
||||
prettyprint-list prettyprint-; ;
|
||||
|
||||
: .n namestack prettyprint ;
|
||||
: .s datastack prettyprint ;
|
||||
: .r callstack prettyprint ;
|
||||
: .c catchstack prettyprint ;
|
||||
|
|
|
@ -67,9 +67,9 @@ USE: stack
|
|||
|
||||
: init-styles ( -- )
|
||||
|
||||
<table> "styles" set
|
||||
<namespace> "styles" set
|
||||
"styles" get [
|
||||
<table> [
|
||||
<namespace> [
|
||||
f "ansi-fg" set
|
||||
f "ansi-bg" set
|
||||
f "fg" set
|
||||
|
@ -82,7 +82,7 @@ USE: stack
|
|||
] extend "default" set
|
||||
|
||||
! A paragraph break
|
||||
<table> [
|
||||
<namespace> [
|
||||
t "paragraph" set
|
||||
] extend "paragraph" set
|
||||
] bind
|
||||
|
|
|
@ -2,7 +2,6 @@ IN: scratchpad
|
|||
USE: arithmetic
|
||||
USE: combinators
|
||||
USE: compiler
|
||||
USE: inspector
|
||||
USE: kernel
|
||||
USE: lists
|
||||
USE: logic
|
||||
|
|
|
@ -44,8 +44,6 @@ USE: vocabularies
|
|||
|
||||
[ [ 5 1 0 0 ] ] [ [ >=< ] ] [ balance>list ] test-word
|
||||
|
||||
[ [ 1 0 0 0 ] ] [ [ throw ] ] [ balance>list ] test-word
|
||||
|
||||
[ [ 1 0 0 0 ] ] [ [ exit* ] ] [ balance>list ] test-word
|
||||
|
||||
[ [ 0 1 0 0 ] ] [ [ millis ] ] [ balance>list ] test-word
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
!"Reboot test." print
|
||||
!
|
||||
!"reboot-test" get [
|
||||
! t "reboot-test" set
|
||||
!
|
||||
! <namespace> [
|
||||
! 1024 <string-output-stream> "stdio" set
|
||||
!
|
||||
! words [ worddef primitive? not ] subset [ see ] each
|
||||
!
|
||||
! "stdio" get stream>str dup parse
|
||||
! ] bind
|
||||
!
|
||||
! call
|
||||
!
|
||||
! "compile" get [ compile-all ] when
|
||||
!
|
||||
! all-tests
|
||||
!
|
||||
! f "reboot-test" set
|
||||
!] unless
|
||||
!
|
||||
!"Reboot test done." print
|
|
@ -1,31 +0,0 @@
|
|||
IN: scratchpad
|
||||
USE: arithmetic
|
||||
USE: kernel
|
||||
USE: stack
|
||||
USE: stdio
|
||||
USE: streams
|
||||
USE: test
|
||||
USE: workspace
|
||||
|
||||
! Now do a little benchmark.
|
||||
|
||||
: store-benchmark ( count store -- )
|
||||
over [ over dupd store-set ] times*
|
||||
over [ over store-get drop ] times*
|
||||
2drop ; word must-compile
|
||||
|
||||
"Time to read/write a million entries with B-tree/127: " write
|
||||
|
||||
"btree-store-test" fdelete drop
|
||||
"btree-store-test.index" fdelete drop
|
||||
|
||||
1000000 "btree-store-test" 127 f <btree-store>
|
||||
|
||||
[ store-benchmark ] time
|
||||
|
||||
!"Time to read/write a million entries with file store: " write
|
||||
!
|
||||
![ "rm" "-rf" "file-store-test" ] exec
|
||||
!1000000 "file-store-test" <file-store>
|
||||
!
|
||||
![ store-benchmark ] time
|
|
@ -1,92 +0,0 @@
|
|||
IN: scratchpad
|
||||
USE: arithmetic
|
||||
USE: combinators
|
||||
USE: kernel
|
||||
USE: lists
|
||||
USE: random
|
||||
USE: stack
|
||||
USE: stdio
|
||||
USE: streams
|
||||
USE: strings
|
||||
USE: test
|
||||
USE: workspace
|
||||
|
||||
: bytes>string ( bytes -- string )
|
||||
"ASCII" [ [ "byte" ] "java.lang.String" ]
|
||||
"java.lang.String" jnew ; word must-compile
|
||||
|
||||
: store-num ( x store -- )
|
||||
2dup in-store? [
|
||||
2drop
|
||||
] [
|
||||
dupd store-set
|
||||
] ifte ; word must-compile
|
||||
|
||||
: check-num ( x store -- )
|
||||
! Check that it exists first
|
||||
2dup in-store? assert
|
||||
! Now check that its value is correct
|
||||
[ dup >str swap ] dip store-get bytes>string assert= ;
|
||||
|
||||
: random-list ( count -- list )
|
||||
[ ] swap [ 0 10000000 random-int swons ] times ; word must-compile
|
||||
|
||||
: test-store ( store list -- )
|
||||
2dup
|
||||
[ over store-num ] each drop
|
||||
[ over check-num ] each close-store ;
|
||||
|
||||
!"File store test" print
|
||||
!
|
||||
![ "rm" "-rf" "file-store-test" ] exec
|
||||
!"file-store-test" <file-store> test-store
|
||||
|
||||
"B-tree store test" print
|
||||
|
||||
: delete-btree-test ( -- )
|
||||
"btree-store-test" fdelete drop
|
||||
"btree-store-test.index" fdelete drop ;
|
||||
|
||||
: create-btree-test ( order -- store )
|
||||
delete-btree-test
|
||||
"btree-store-test" swap f <btree-store> ;
|
||||
|
||||
: btree-test ( order list -- )
|
||||
[ create-btree-test ] dip test-store ;
|
||||
|
||||
: btree-random-test ( order count -- )
|
||||
"B-tree test #1: " write 2dup " " swap cat3 print
|
||||
random-list [ btree-test ] time ;
|
||||
|
||||
4 2000 btree-random-test
|
||||
5 2000 btree-random-test
|
||||
6 2000 btree-random-test
|
||||
7 2000 btree-random-test
|
||||
8 2000 btree-random-test
|
||||
48 5000 btree-random-test
|
||||
127 10000 btree-random-test
|
||||
|
||||
: test-add-or-get ( x store -- )
|
||||
random-boolean [
|
||||
store-num
|
||||
] [
|
||||
in-store? drop
|
||||
] ifte ; word must-compile
|
||||
|
||||
: test-store-2 ( store list -- )
|
||||
[ over test-add-or-get ] each close-store ; word must-compile
|
||||
|
||||
: btree-test-2 ( order list -- )
|
||||
[ create-btree-test ] dip test-store-2 ;
|
||||
|
||||
: btree-random-test-2 ( order count -- )
|
||||
"B-tree test #2: " write 2dup " " swap cat3 print
|
||||
random-list [ btree-test-2 ] time ;
|
||||
|
||||
4 2000 btree-random-test-2
|
||||
5 2000 btree-random-test-2
|
||||
6 2000 btree-random-test-2
|
||||
7 2000 btree-random-test-2
|
||||
8 2000 btree-random-test-2
|
||||
48 5000 btree-random-test-2
|
||||
127 10000 btree-random-test-2
|
|
@ -81,8 +81,6 @@ USE: vocabularies
|
|||
"tail"
|
||||
"types"
|
||||
"vectors"
|
||||
!"store"
|
||||
!"reboot"
|
||||
] [
|
||||
test
|
||||
] each
|
||||
|
|
|
@ -51,7 +51,7 @@ USE: words
|
|||
] ifte ;
|
||||
|
||||
: init-vocab-styles ( -- )
|
||||
"styles" get [ <table> "vocabularies" set ] bind
|
||||
"styles" get [ <namespace> "vocabularies" set ] bind
|
||||
|
||||
[
|
||||
[ "ansi-fg" | "1" ]
|
||||
|
|
Loading…
Reference in New Issue