removed factor db

cvs
Slava Pestov 2004-07-19 20:10:18 +00:00
parent cb758942aa
commit 88e3ea7ab4
91 changed files with 252 additions and 3776 deletions

View File

@ -4,7 +4,6 @@
- minimal use/in for parse-stream - minimal use/in for parse-stream
- prettyprint-1 - prettyprint-1
- {...} vectors - {...} vectors
- better .s
- parsing should be parsing - parsing should be parsing
- telnetd: listening on a socket - telnetd: listening on a socket
- vocab inspecting ==> worddef>list, assumes . on a list works - vocab inspecting ==> worddef>list, assumes . on a list works

Binary file not shown.

View File

@ -1 +1 @@
!a;7528;7528 !a;6964;6964

View File

@ -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 //{{{ elementsToString() method
/** /**
* Returns a whitespace separated string of the unparseObject() of each * Returns a whitespace separated string of the unparseObject() of each
* item. * item.
*/ */
public String elementsToString() 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(); StringBuffer buf = new StringBuffer();
Cons iter = this; Cons iter = this;
while(iter != null) while(iter != null)
{ {
buf.append(dbUnparse ? buf.append(FactorReader.unparseObject(iter.car));
FactorReader.unparseDBObject(iter.car)
: FactorReader.unparseObject(iter.car));
if(iter.cdr instanceof Cons) if(iter.cdr instanceof Cons)
{ {
buf.append(' '); buf.append(' ');
@ -204,9 +183,7 @@ public class Cons implements PublicCloneable, FactorExternalizable
else else
{ {
buf.append(" | "); buf.append(" | ");
buf.append(dbUnparse ? buf.append(FactorReader.unparseObject(iter.cdr));
FactorReader.unparseDBObject(iter.cdr)
: FactorReader.unparseObject(iter.cdr));
iter = null; iter = null;
} }
} }
@ -220,7 +197,7 @@ public class Cons implements PublicCloneable, FactorExternalizable
*/ */
public String toString() public String toString()
{ {
return "[ " + elementsToString(false) + " ]"; return "[ " + elementsToString() + " ]";
} //}}} } //}}}
//{{{ toArray() method //{{{ toArray() method

View File

@ -30,10 +30,10 @@
package factor; package factor;
/** /**
* Factor is a stack-based language. * A growable array.
* @author Slava Pestov * @author Slava Pestov
*/ */
public class FactorArray implements PublicCloneable public class FactorArray implements FactorExternalizable, PublicCloneable
{ {
public Object[] stack; public Object[] stack;
public int top; public int top;
@ -159,6 +159,22 @@ public class FactorArray implements PublicCloneable
return stack.length; 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 //{{{ toList() method
public Cons toList() public Cons toList()
{ {

View File

@ -30,8 +30,6 @@
package factor; package factor;
import factor.compiler.*; import factor.compiler.*;
import factor.db.Workspace;
import factor.db.PersistenceException;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.*; import java.util.*;
@ -52,29 +50,16 @@ public class FactorCompoundDefinition extends FactorWordDefinition
* A new definition. * A new definition.
*/ */
public FactorCompoundDefinition(FactorWord word, Cons definition, public FactorCompoundDefinition(FactorWord word, Cons definition,
FactorInterpreter interp) throws PersistenceException FactorInterpreter interp)
{ {
super(word,interp.workspace); super(word);
fromList(definition,interp); 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 //{{{ eval() method
public void eval(FactorInterpreter interp) public void eval(FactorInterpreter interp)
throws Exception throws Exception
{ {
lazyInit(interp);
interp.call(endOfDocs); interp.call(endOfDocs);
} //}}} } //}}}
@ -82,7 +67,6 @@ public class FactorCompoundDefinition extends FactorWordDefinition
public void getStackEffect(RecursiveState recursiveCheck, public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception FactorCompiler compiler) throws Exception
{ {
lazyInit(compiler.interp);
RecursiveForm rec = recursiveCheck.get(word); RecursiveForm rec = recursiveCheck.get(word);
if(rec.active) if(rec.active)
{ {
@ -111,10 +95,8 @@ public class FactorCompoundDefinition extends FactorWordDefinition
FactorWordDefinition compile(FactorInterpreter interp, FactorWordDefinition compile(FactorInterpreter interp,
RecursiveState recursiveCheck) throws Exception RecursiveState recursiveCheck) throws Exception
{ {
lazyInit(interp);
// Each word has its own class loader // Each word has its own class loader
FactorClassLoader loader = new FactorClassLoader( FactorClassLoader loader = new FactorClassLoader();
interp.workspace);
StackEffect effect = getStackEffect(interp); StackEffect effect = getStackEffect(interp);

View File

@ -29,20 +29,13 @@
package factor; package factor;
import factor.db.*;
import factor.parser.*; import factor.parser.*;
import factor.primitives.*; import factor.primitives.*;
import java.io.*; import java.io.*;
public class FactorInterpreter implements FactorObject, Runnable public class FactorInterpreter implements FactorObject, Runnable
{ {
public static final String VERSION = "0.60.6"; public static final String VERSION = "0.60.8";
// 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";
// command line arguments are stored here. // command line arguments are stored here.
public Cons args; public Cons args;
@ -52,8 +45,9 @@ public class FactorInterpreter implements FactorObject, Runnable
public Throwable error; public Throwable error;
public boolean dump = false; public boolean dump = false;
public boolean verboseCompile = false; public boolean verboseCompile = false;
public boolean firstTime = false;
public boolean mini = false; public boolean mini = false;
// if this is false and an error occurs, bail out.
public boolean startupDone = false;
public Cons callframe; public Cons callframe;
public FactorArray callstack = new FactorArray(); public FactorArray callstack = new FactorArray();
@ -87,11 +81,6 @@ public class FactorInterpreter implements FactorObject, Runnable
*/ */
public FactorWord last; public FactorWord last;
/**
* Persistent store, maybe null.
*/
public Workspace workspace;
public FactorNamespace global; public FactorNamespace global;
private FactorNamespace interpNamespace; private FactorNamespace interpNamespace;
@ -104,8 +93,6 @@ public class FactorInterpreter implements FactorObject, Runnable
FactorInterpreter interp = new FactorInterpreter(); FactorInterpreter interp = new FactorInterpreter();
interp.init(args,null); interp.init(args,null);
interp.run(); interp.run();
if(interp.workspace != null)
interp.workspace.close();
} //}}} } //}}}
//{{{ init() method //{{{ init() method
@ -115,7 +102,6 @@ public class FactorInterpreter implements FactorObject, Runnable
this.interactive = interp.interactive; this.interactive = interp.interactive;
this.dump = interp.dump; this.dump = interp.dump;
this.verboseCompile = interp.verboseCompile; this.verboseCompile = interp.verboseCompile;
this.firstTime = firstTime;
this.callframe = interp.callframe; this.callframe = interp.callframe;
this.callstack = (FactorArray)interp.callstack.clone(); this.callstack = (FactorArray)interp.callstack.clone();
this.datastack = (FactorArray)interp.datastack.clone(); this.datastack = (FactorArray)interp.datastack.clone();
@ -126,7 +112,6 @@ public class FactorInterpreter implements FactorObject, Runnable
this.in = interp.in; this.in = interp.in;
this.builtins = interp.builtins; this.builtins = interp.builtins;
this.last = interp.last; this.last = interp.last;
this.workspace = interp.workspace;
this.global = interp.global; this.global = interp.global;
} //}}} } //}}}
@ -136,39 +121,8 @@ public class FactorInterpreter implements FactorObject, Runnable
for(int i = 0; i < args.length; i++) for(int i = 0; i < args.length; i++)
{ {
String arg = args[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 // this switch forces minimal libraries to be loaded
else if(arg.equals("-no-mini")) if(arg.equals("-no-mini"))
{ {
mini = false; mini = false;
args[i] = null; args[i] = null;
@ -182,7 +136,7 @@ public class FactorInterpreter implements FactorObject, Runnable
this.args = Cons.fromArray(args); this.args = Cons.fromArray(args);
vocabularies = new Table(workspace); vocabularies = new FactorNamespace();
initBuiltinDictionary(); initBuiltinDictionary();
initNamespace(root); initNamespace(root);
topLevel(); topLevel();
@ -190,35 +144,10 @@ public class FactorInterpreter implements FactorObject, Runnable
runBootstrap(); 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 //{{{ initBuiltinDictionary() method
private void initBuiltinDictionary() throws Exception private void initBuiltinDictionary() throws Exception
{ {
builtins = new Table(null); builtins = new FactorNamespace();
vocabularies.setVariable("builtins",builtins); vocabularies.setVariable("builtins",builtins);
in = "builtins"; in = "builtins";
@ -226,129 +155,123 @@ public class FactorInterpreter implements FactorObject, Runnable
// parsing words // parsing words
FactorWord lineComment = define("builtins","!"); FactorWord lineComment = define("builtins","!");
lineComment.parsing = new LineComment(lineComment,false,null); lineComment.parsing = new LineComment(lineComment,false);
FactorWord stackComment = define("builtins","("); FactorWord stackComment = define("builtins","(");
stackComment.parsing = new StackComment(stackComment,null); stackComment.parsing = new StackComment(stackComment);
FactorWord str = define("builtins","\""); FactorWord str = define("builtins","\"");
str.parsing = new StringLiteral(str,true,null); str.parsing = new StringLiteral(str,true);
FactorWord t = define("builtins","t"); FactorWord t = define("builtins","t");
t.parsing = new T(t,null); t.parsing = new T(t);
FactorWord f = define("builtins","f"); FactorWord f = define("builtins","f");
f.parsing = new F(f,null); f.parsing = new F(f);
FactorWord bra = define("builtins","["); FactorWord bra = define("builtins","[");
bra.parsing = new Bra(bra,null); bra.parsing = new Bra(bra);
FactorWord ket = define("builtins","]"); FactorWord ket = define("builtins","]");
ket.parsing = new Ket(bra,ket,null); ket.parsing = new Ket(bra,ket);
FactorWord bar = define("builtins","|"); FactorWord bar = define("builtins","|");
bar.parsing = new Bar(bar,null); bar.parsing = new Bar(bar);
FactorWord def = define("builtins",":"); FactorWord def = define("builtins",":");
def.parsing = new Def(def,null); def.parsing = new Def(def);
def.getNamespace().setVariable("doc-comments",Boolean.TRUE); def.getNamespace().setVariable("doc-comments",Boolean.TRUE);
FactorWord ine = define("builtins",";"); FactorWord ine = define("builtins",";");
ine.parsing = new Ine(def,ine,null); ine.parsing = new Ine(def,ine);
FactorWord shuffle = define("builtins","~<<"); FactorWord shuffle = define("builtins","~<<");
shuffle.parsing = new Shuffle(shuffle,">>~",null); shuffle.parsing = new Shuffle(shuffle,">>~");
FactorWord noParsing = define("builtins","POSTPONE:"); FactorWord noParsing = define("builtins","POSTPONE:");
noParsing.parsing = new NoParsing(noParsing,null); noParsing.parsing = new NoParsing(noParsing);
// #X // #X
FactorWord dispatch = define("builtins","#"); FactorWord dispatch = define("builtins","#");
dispatch.parsing = new Dispatch(dispatch,null); dispatch.parsing = new Dispatch(dispatch);
FactorWord getPersistentObject = define("builtins","#O");
getPersistentObject.parsing = new GetPersistentObject(
getPersistentObject,null);
FactorWord ch = define("builtins","#\\"); FactorWord ch = define("builtins","#\\");
ch.parsing = new CharLiteral(ch,null); ch.parsing = new CharLiteral(ch);
FactorWord raw = define("builtins","#\""); FactorWord raw = define("builtins","#\"");
raw.parsing = new StringLiteral(raw,false,null); raw.parsing = new StringLiteral(raw,false);
FactorWord complex = define("builtins","#{"); FactorWord complex = define("builtins","#{");
complex.parsing = new ComplexLiteral(complex,"}",null); complex.parsing = new ComplexLiteral(complex,"}");
FactorWord docComment = define("builtins","#!"); FactorWord docComment = define("builtins","#!");
docComment.parsing = new LineComment(docComment,true,null); docComment.parsing = new LineComment(docComment,true);
FactorWord unreadable = define("builtins","#<"); FactorWord unreadable = define("builtins","#<");
unreadable.parsing = new Unreadable(unreadable,null); unreadable.parsing = new Unreadable(unreadable);
// #: is not handled with a special dispatch. instead, when // #: is not handled with a special dispatch. instead, when
// a word starting with #: is passed to intern(), it creates // a word starting with #: is passed to intern(), it creates
// a new symbol // a new symbol
FactorWord passthru = define("builtins","#:"); FactorWord passthru = define("builtins","#:");
passthru.parsing = new PassThrough(passthru,null); passthru.parsing = new PassThrough(passthru);
// vocabulary parsing words // vocabulary parsing words
FactorWord defer = define("builtins","DEFER:"); FactorWord defer = define("builtins","DEFER:");
defer.parsing = new Defer(defer,null); defer.parsing = new Defer(defer);
FactorWord in = define("builtins","IN:"); FactorWord in = define("builtins","IN:");
in.parsing = new In(in,null); in.parsing = new In(in);
FactorWord use = define("builtins","USE:"); FactorWord use = define("builtins","USE:");
use.parsing = new Use(use,null); use.parsing = new Use(use);
FactorWord interpreterGet = define("builtins","interpreter"); FactorWord interpreterGet = define("builtins","interpreter");
interpreterGet.def = new InterpreterGet(interpreterGet,null); interpreterGet.def = new InterpreterGet(interpreterGet);
interpreterGet.inline = true; interpreterGet.inline = true;
// reading numbers with another base // reading numbers with another base
FactorWord bin = define("builtins","BIN:"); FactorWord bin = define("builtins","BIN:");
bin.parsing = new Base(defer,null,2); bin.parsing = new Base(bin,2);
FactorWord oct = define("builtins","OCT:"); FactorWord oct = define("builtins","OCT:");
oct.parsing = new Base(defer,null,8); oct.parsing = new Base(oct,8);
FactorWord hex = define("builtins","HEX:"); FactorWord hex = define("builtins","HEX:");
hex.parsing = new Base(defer,null,16); hex.parsing = new Base(hex,16);
// primitives used by 'expand' and 'map' // primitives used by 'expand' and 'map'
FactorWord restack = define("builtins","restack"); FactorWord restack = define("builtins","restack");
restack.def = new Restack(restack,null); restack.def = new Restack(restack);
FactorWord unstack = define("builtins","unstack"); FactorWord unstack = define("builtins","unstack");
unstack.def = new Unstack(unstack,null); unstack.def = new Unstack(unstack);
// reflection primitives // reflection primitives
FactorWord jinvoke = define("builtins","jinvoke"); FactorWord jinvoke = define("builtins","jinvoke");
jinvoke.def = new JInvoke(jinvoke,null,false); jinvoke.def = new JInvoke(jinvoke,false);
jinvoke.inline = true; jinvoke.inline = true;
FactorWord jinvokeStatic = define("builtins","jinvoke-static"); FactorWord jinvokeStatic = define("builtins","jinvoke-static");
jinvokeStatic.def = new JInvoke(jinvokeStatic,null,true); jinvokeStatic.def = new JInvoke(jinvokeStatic,true);
jinvokeStatic.inline = true; jinvokeStatic.inline = true;
FactorWord jnew = define("builtins","jnew"); FactorWord jnew = define("builtins","jnew");
jnew.def = new JNew(jnew,null); jnew.def = new JNew(jnew);
jnew.inline = true; jnew.inline = true;
FactorWord jvarGet = define("builtins","jvar-get"); FactorWord jvarGet = define("builtins","jvar-get");
jvarGet.def = new JVarGet(jvarGet,null); jvarGet.def = new JVarGet(jvarGet);
jvarGet.inline = true; jvarGet.inline = true;
FactorWord jvarGetStatic = define("builtins","jvar-static-get"); FactorWord jvarGetStatic = define("builtins","jvar-static-get");
jvarGetStatic.def = new JVarGetStatic(jvarGetStatic,null); jvarGetStatic.def = new JVarGetStatic(jvarGetStatic);
jvarGetStatic.inline = true; jvarGetStatic.inline = true;
FactorWord jvarSet = define("builtins","jvar-set"); FactorWord jvarSet = define("builtins","jvar-set");
jvarSet.def = new JVarSet(jvarSet,null); jvarSet.def = new JVarSet(jvarSet);
jvarSet.inline = true; jvarSet.inline = true;
FactorWord jvarSetStatic = define("builtins","jvar-static-set"); FactorWord jvarSetStatic = define("builtins","jvar-static-set");
jvarSetStatic.def = new JVarSetStatic(jvarSetStatic,null); jvarSetStatic.def = new JVarSetStatic(jvarSetStatic);
jvarSetStatic.inline = true; jvarSetStatic.inline = true;
FactorWord coerce = define("builtins","coerce"); FactorWord coerce = define("builtins","coerce");
coerce.def = new Coerce(coerce,null); coerce.def = new Coerce(coerce);
coerce.inline = true; coerce.inline = true;
// definition // definition
FactorWord define = define("builtins","define"); FactorWord define = define("builtins","define");
define.def = new Define(define,null); define.def = new Define(define);
// combinators // combinators
FactorWord execute = define("builtins","execute"); FactorWord execute = define("builtins","execute");
execute.def = new Execute(execute,null); execute.def = new Execute(execute);
FactorWord call = define("builtins","call"); FactorWord call = define("builtins","call");
call.def = new Call(call,null); call.def = new Call(call);
call.inline = true; call.inline = true;
FactorWord ifte = define("builtins","ifte"); FactorWord ifte = define("builtins","ifte");
ifte.def = new Ifte(ifte,null); ifte.def = new Ifte(ifte);
ifte.inline = true; ifte.inline = true;
} //}}} } //}}}
//{{{ initNamespace() method //{{{ initNamespace() method
private void initNamespace(Object root) throws Exception private void initNamespace(Object root) throws Exception
{ {
if(workspace == null)
global = new FactorNamespace(null,root); global = new FactorNamespace(null,root);
else
global = workspace.getRoot();
global.setVariable("interpreter",this); global.setVariable("interpreter",this);
@ -357,37 +280,14 @@ public class FactorInterpreter implements FactorObject, Runnable
getClass().getField("verboseCompile"), getClass().getField("verboseCompile"),
this)); this));
global.setVariable("global", global.setVariable("startup-done",
new FactorNamespace.VarBinding( new FactorNamespace.VarBinding(
getClass().getField("global"), getClass().getField("startupDone"),
this)); 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 = { String[] boundFields = {
"global",
"vocabularies",
"args", "args",
"dump", "dump",
"interactive", "interactive",
@ -420,11 +320,6 @@ public class FactorInterpreter implements FactorObject, Runnable
//{{{ runBootstrap() method //{{{ runBootstrap() method
private void runBootstrap() throws Exception private void runBootstrap() throws Exception
{ {
if(workspace == null || workspace.isFirstTime()
|| firstTime)
{
if(workspace != null)
workspace.setFirstTime(false);
String initFile = "/library/platform/jvm/boot.factor"; String initFile = "/library/platform/jvm/boot.factor";
FactorReader parser = new FactorReader( FactorReader parser = new FactorReader(
initFile, initFile,
@ -435,9 +330,6 @@ public class FactorInterpreter implements FactorObject, Runnable
this); this);
call(parser.parse()); call(parser.parse());
}
else
eval(searchVocabulary(INIT_VOCAB,"boot"));
run(); run();
} //}}} } //}}}
@ -479,17 +371,27 @@ public class FactorInterpreter implements FactorObject, Runnable
private boolean handleError(Throwable e) private boolean handleError(Throwable e)
{ {
error = FactorJava.unwrapException(e); error = FactorJava.unwrapException(e);
if(!startupDone)
{
error.printStackTrace();
topLevel();
return true;
}
datastack.push(error); datastack.push(error);
try try
{ {
eval(searchVocabulary(ERRORS_VOCAB,"throw")); FactorWord throwWord = searchVocabulary(
"errors","throw");
if(throwWord == null)
throw new NullPointerException();
eval(throwWord);
return false; return false;
} }
catch(Throwable e2) catch(Throwable e2)
{ {
System.err.println("Exception when calling throw:"); System.err.println("Exception when calling throw:");
e.printStackTrace(); e.printStackTrace();
topLevel(); topLevel();
return true; return true;
@ -609,7 +511,7 @@ public class FactorInterpreter implements FactorObject, Runnable
Object value = vocabularies.getVariable(name); Object value = vocabularies.getVariable(name);
if(value == null) if(value == null)
{ {
value = new Table(workspace); value = new FactorNamespace();
vocabularies.setVariable(name,value); vocabularies.setVariable(name,value);
} }
} //}}} } //}}}
@ -680,7 +582,7 @@ public class FactorInterpreter implements FactorObject, Runnable
FactorNamespace v = getVocabulary(vocabulary); FactorNamespace v = getVocabulary(vocabulary);
if(v == null) if(v == null)
{ {
v = new Table(workspace); v = new FactorNamespace();
vocabularies.setVariable(vocabulary,v); vocabularies.setVariable(vocabulary,v);
} }
Object value = v.getVariable(name); Object value = v.getVariable(name);
@ -688,18 +590,9 @@ public class FactorInterpreter implements FactorObject, Runnable
return (FactorWord)value; return (FactorWord)value;
else else
{ {
Workspace workspace;
if(v instanceof PersistentObject)
{
workspace = ((PersistentObject)v)
.getWorkspace();
}
else
workspace = null;
// save to same workspace as vocabulary, // save to same workspace as vocabulary,
// or no workspace if vocabulary is builtins // or no workspace if vocabulary is builtins
FactorWord word = new FactorWord(workspace, FactorWord word = new FactorWord(
vocabulary,name,null); vocabulary,name,null);
v.setVariable(name,word); v.setVariable(name,word);
return word; return word;
@ -724,8 +617,11 @@ public class FactorInterpreter implements FactorObject, Runnable
namestack.push(global); namestack.push(global);
catchstack.top = 0; catchstack.top = 0;
// DEFER: the word // DEFER: the word
define(ERRORS_VOCAB,"default-error-handler"); define("kernel","exit*");
catchstack.push(new Cons(searchVocabulary(ERRORS_VOCAB, 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)); "default-error-handler"),null));
callframe = null; callframe = null;
} //}}} } //}}}

View File

@ -29,13 +29,12 @@
package factor; package factor;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
/** /**
* A parsing word definition. * A parsing word definition.
*/ */
public abstract class FactorParsingDefinition extends SimplePersistentObject public abstract class FactorParsingDefinition
{ {
public static final String ENCODING = "UTF8"; public static final String ENCODING = "UTF8";
@ -45,24 +44,10 @@ public abstract class FactorParsingDefinition extends SimplePersistentObject
/** /**
* A new definition. * A new definition.
*/ */
public FactorParsingDefinition(FactorWord word, Workspace workspace) public FactorParsingDefinition(FactorWord word)
throws Exception throws Exception
{ {
this(workspace,workspace == null
? 0L : workspace.nextID());
this.word = word; 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) public abstract void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor; package factor;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import java.util.Set; import java.util.Set;
/** /**
@ -42,22 +41,9 @@ public abstract class FactorPrimitiveDefinition extends FactorWordDefinition
/** /**
* A new definition. * A new definition.
*/ */
public FactorPrimitiveDefinition(FactorWord word, Workspace workspace) public FactorPrimitiveDefinition(FactorWord word)
throws Exception
{ {
super(word,workspace); super(word);
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);
} //}}} } //}}}
//{{{ fromList() method //{{{ fromList() method

View File

@ -29,8 +29,6 @@
package factor; package factor;
import factor.db.PersistentIgnore;
import factor.db.PersistentObject;
import java.io.*; import java.io.*;
import java.util.*; 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 //{{{ unparseObject() method
public static String unparseObject(Object obj) public static String unparseObject(Object obj)
{ {

View File

@ -30,7 +30,6 @@
package factor; package factor;
import factor.compiler.*; import factor.compiler.*;
import factor.db.Workspace;
import java.util.*; import java.util.*;
import org.objectweb.asm.*; import org.objectweb.asm.*;
@ -59,21 +58,12 @@ public class FactorShuffleDefinition extends FactorWordDefinition
private int shuffleRstart; private int shuffleRstart;
private int shuffleRlength; private int shuffleRlength;
//{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(Workspace workspace, long id)
{
super(workspace,id);
} //}}}
//{{{ FactorShuffleDefinition constructor //{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(FactorWord word, Cons definition, public FactorShuffleDefinition(FactorWord word, Cons definition,
FactorInterpreter interp) throws FactorException FactorInterpreter interp) throws FactorException
{ {
super(word,interp.workspace); super(word);
fromList(definition,interp); fromList(definition,interp);
if(interp.workspace != null)
interp.workspace.put(this);
} //}}} } //}}}
//{{{ FactorShuffleDefinition constructor //{{{ FactorShuffleDefinition constructor
@ -162,8 +152,6 @@ public class FactorShuffleDefinition extends FactorWordDefinition
FactorArray callstack) FactorArray callstack)
throws FactorStackException throws FactorStackException
{ {
lazyInit(interp);
if(datastack.top < consumeD) if(datastack.top < consumeD)
throw new FactorStackException(consumeD); throw new FactorStackException(consumeD);

View File

@ -30,14 +30,12 @@
package factor; package factor;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import java.util.*; import java.util.*;
/** /**
* An internalized symbol. * An internalized symbol.
*/ */
public class FactorWord extends SimplePersistentObject public class FactorWord implements FactorExternalizable, FactorObject
implements FactorExternalizable
{ {
private static int gensymCount = 0; private static int gensymCount = 0;
@ -75,16 +73,7 @@ public class FactorWord extends SimplePersistentObject
public FactorClassLoader loader; public FactorClassLoader loader;
public String className; public String className;
//{{{ FactorWord constructor private FactorNamespace namespace;
/**
* 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 //{{{ FactorWord constructor
/** /**
@ -92,15 +81,12 @@ public class FactorWord extends SimplePersistentObject
* implementation or something. Use an FactorDictionary's * implementation or something. Use an FactorDictionary's
* intern() method instead. * intern() method instead.
*/ */
public FactorWord(Workspace workspace, String vocabulary, String name, public FactorWord(String vocabulary, String name,
FactorWordDefinition def) throws Exception FactorWordDefinition def) throws Exception
{ {
this(workspace,workspace == null ? 0L : workspace.nextID());
this.vocabulary = vocabulary; this.vocabulary = vocabulary;
this.name = name; this.name = name;
this.def = def; this.def = def;
if(workspace != null && id != 0L)
workspace.put(this);
} //}}} } //}}}
//{{{ FactorWord constructor //{{{ FactorWord constructor
@ -115,6 +101,15 @@ public class FactorWord extends SimplePersistentObject
this.name = name; this.name = name;
} //}}} } //}}}
//{{{ getNamespace() method
public FactorNamespace getNamespace()
throws Exception
{
if(namespace == null)
namespace = new FactorNamespace(this);
return namespace;
} //}}}
//{{{ gensym() method //{{{ gensym() method
/** /**
* Returns an un-internalized word with a unique name. * Returns an un-internalized word with a unique name.
@ -126,7 +121,6 @@ public class FactorWord extends SimplePersistentObject
//{{{ define() method //{{{ define() method
public synchronized void define(FactorWordDefinition def) public synchronized void define(FactorWordDefinition def)
throws PersistenceException
{ {
if(compileRef) if(compileRef)
{ {
@ -140,20 +134,14 @@ public class FactorWord extends SimplePersistentObject
loader = null; loader = null;
className = null; className = null;
if(workspace != null && id != 0L)
workspace.put(this);
} //}}} } //}}}
//{{{ setCompiledInfo() method //{{{ setCompiledInfo() method
synchronized void setCompiledInfo(FactorClassLoader loader, synchronized void setCompiledInfo(FactorClassLoader loader,
String className) throws PersistenceException String className)
{ {
this.loader = loader; this.loader = loader;
this.className = className; this.className = className;
if(workspace != null && id != 0L)
workspace.put(this);
} //}}} } //}}}
//{{{ compile() method //{{{ compile() method
@ -165,30 +153,6 @@ public class FactorWord extends SimplePersistentObject
recursiveCheck.remove(this); 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 //{{{ compile() method
public synchronized void compile(FactorInterpreter interp, public synchronized void compile(FactorInterpreter interp,
RecursiveState recursiveCheck) RecursiveState recursiveCheck)

View File

@ -29,7 +29,6 @@
package factor; package factor;
import factor.db.*;
import factor.compiler.*; import factor.compiler.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
@ -37,21 +36,9 @@ import org.objectweb.asm.*;
/** /**
* A word definition. * 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 public abstract class FactorWordDefinition implements Constants
implements Constants, PersistentObject
{ {
public static final String ENCODING = "UTF8";
private String unparsed;
private boolean initialized;
private Workspace workspace;
private long id;
protected FactorWord word; protected FactorWord word;
public boolean compileFailed; public boolean compileFailed;
@ -60,32 +47,9 @@ public abstract class FactorWordDefinition
/** /**
* A new definition. * 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) public FactorWordDefinition(FactorWord word)
{ {
this.word = word; this.word = word;
initialized = true;
} //}}} } //}}}
public abstract void eval(FactorInterpreter interp) public abstract void eval(FactorInterpreter interp)
@ -94,15 +58,14 @@ public abstract class FactorWordDefinition
//{{{ getWord() method //{{{ getWord() method
public FactorWord getWord(FactorInterpreter interp) public FactorWord getWord(FactorInterpreter interp)
{ {
lazyInit(interp);
return word; return word;
} //}}} } //}}}
//{{{ fromList() method //{{{ fromList() method
public void fromList(Cons cons, FactorInterpreter interp) 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 //{{{ toList() method
@ -123,7 +86,6 @@ public abstract class FactorWordDefinition
FactorInterpreter interp) throws Exception FactorInterpreter interp) throws Exception
{ {
FactorCompiler compiler = new FactorCompiler(interp); FactorCompiler compiler = new FactorCompiler(interp);
lazyInit(interp);
recursiveCheck.add(word,new StackEffect(),null,null,null); recursiveCheck.add(word,new StackEffect(),null,null,null);
getStackEffect(recursiveCheck,compiler); getStackEffect(recursiveCheck,compiler);
recursiveCheck.remove(word); recursiveCheck.remove(word);
@ -134,7 +96,6 @@ public abstract class FactorWordDefinition
public void getStackEffect(RecursiveState recursiveCheck, public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception FactorCompiler compiler) throws Exception
{ {
lazyInit(compiler.interp);
throw new FactorCompilerException("Cannot deduce stack effect of " + word); throw new FactorCompilerException("Cannot deduce stack effect of " + word);
} //}}} } //}}}
@ -152,8 +113,6 @@ public abstract class FactorWordDefinition
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler, public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
RecursiveState recursiveCheck) throws Exception RecursiveState recursiveCheck) throws Exception
{ {
lazyInit(compiler.interp);
// normal word // normal word
String defclass; String defclass;
String defmethod; String defmethod;
@ -262,8 +221,6 @@ public abstract class FactorWordDefinition
RecursiveState recursiveCheck, RecursiveState recursiveCheck,
StackEffect immediateEffect) throws Exception StackEffect immediateEffect) throws Exception
{ {
lazyInit(compiler.interp);
Cons definition = toList(compiler.getInterpreter()); Cons definition = toList(compiler.getInterpreter());
Cons endOfDocs = definition; 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 //{{{ toString() method
public String toString() public String toString()
{ {

View File

@ -39,7 +39,6 @@ import org.objectweb.asm.*;
*/ */
public abstract class CompiledDefinition public abstract class CompiledDefinition
extends FactorWordDefinition extends FactorWordDefinition
implements factor.db.PersistentIgnore
{ {
//{{{ CompiledDefinition constructor //{{{ CompiledDefinition constructor
public CompiledDefinition(FactorWord word) public CompiledDefinition(FactorWord word)

View File

@ -29,9 +29,7 @@
package factor.compiler; package factor.compiler;
import factor.Cons; import factor.*;
import factor.FactorInterpreter;
import factor.db.*;
import java.util.*; import java.util.*;
/** /**
@ -40,28 +38,10 @@ import java.util.*;
* When compiling a word; add each dependent word to new class loader's * When compiling a word; add each dependent word to new class loader's
* delegates map. * delegates map.
*/ */
public class FactorClassLoader extends ClassLoader implements PersistentObject public class FactorClassLoader extends ClassLoader
{ {
private Workspace workspace;
private long id; private long id;
private Table table; private FactorNamespace table = new FactorNamespace();
//{{{ 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());
} //}}}
//{{{ addDependency() method //{{{ addDependency() method
public void addDependency(String name, FactorClassLoader loader) public void addDependency(String name, FactorClassLoader loader)
@ -69,8 +49,6 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
try try
{ {
table.setVariable(name,loader); table.setVariable(name,loader);
if(workspace != null && id != 0L)
workspace.put(this);
} }
catch(Exception e) 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 //{{{ addClass() method
public Class addClass(String name, byte[] code, int off, int len) 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); return defineClass(name,code,off,len);
} //}}} } //}}}
@ -153,16 +83,6 @@ public class FactorClassLoader extends ClassLoader implements PersistentObject
return ((FactorClassLoader)obj) return ((FactorClassLoader)obj)
.loadClass(name,resolve); .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) else if(obj != null)
{ {
System.err.println("WARNING: unknown object in class loader table for " + this + ": " + obj); 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); throw new RuntimeException(e);
} }
} //}}} } //}}}
//{{{ getReferences() method
public Cons getReferences()
{
return table.getReferences();
} //}}}
} }

View File

@ -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);
}
}

View File

@ -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);
} //}}}
}

View File

@ -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();
} //}}}
}

View File

@ -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
{
} //}}}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
} //}}}
}

View File

@ -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 {}

View File

@ -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();
}

View File

@ -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()
{
} //}}}
}

View File

@ -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();
} //}}}
}

View File

@ -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;
}

View File

@ -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());
} //}}}
}

View File

@ -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)
{
}
}
}
} //}}}
}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Bar extends FactorParsingDefinition public class Bar extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class Bar extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Bar(FactorWord word, Workspace workspace) public Bar(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Base extends FactorParsingDefinition public class Base extends FactorParsingDefinition
{ {
@ -40,10 +39,10 @@ public class Base extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Base(FactorWord word, Workspace workspace, int base) public Base(FactorWord word, int base)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.base = base; this.base = base;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Bra extends FactorParsingDefinition public class Bra extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class Bra extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Bra(FactorWord word, Workspace workspace) public Bra(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class CharLiteral extends FactorParsingDefinition public class CharLiteral extends FactorParsingDefinition
@ -39,20 +38,10 @@ public class CharLiteral extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public CharLiteral(FactorWord word, Workspace workspace) public CharLiteral(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ CharLiteral constructor
/**
* A blank definition, about to be unpickled.
*/
public CharLiteral(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import factor.math.*; import factor.math.*;
public class ComplexLiteral extends FactorParsingDefinition public class ComplexLiteral extends FactorParsingDefinition
@ -41,11 +40,10 @@ public class ComplexLiteral extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public ComplexLiteral(FactorWord word, public ComplexLiteral(FactorWord word, String end)
String end, Workspace workspace)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.end = end; this.end = end;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Def extends FactorParsingDefinition public class Def extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class Def extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Def(FactorWord word, Workspace workspace) public Def(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Defer extends FactorParsingDefinition public class Defer extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class Defer extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Defer(FactorWord word, Workspace workspace) public Defer(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class Dispatch extends FactorParsingDefinition public class Dispatch extends FactorParsingDefinition
@ -39,10 +38,10 @@ public class Dispatch extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Dispatch(FactorWord word, Workspace workspace) public Dispatch(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class F extends FactorParsingDefinition public class F extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class F extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public F(FactorWord word, Workspace workspace) public F(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -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));
}
}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class In extends FactorParsingDefinition public class In extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class In extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public In(FactorWord word, Workspace workspace) public In(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Ine extends FactorParsingDefinition public class Ine extends FactorParsingDefinition
{ {
@ -40,10 +39,10 @@ public class Ine extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Ine(FactorWord start, FactorWord end, Workspace workspace) public Ine(FactorWord start, FactorWord end)
throws Exception throws Exception
{ {
super(end,workspace); super(end);
this.start = start; this.start = start;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Ket extends FactorParsingDefinition public class Ket extends FactorParsingDefinition
{ {
@ -40,10 +39,10 @@ public class Ket extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Ket(FactorWord start, FactorWord end, Workspace workspace) public Ket(FactorWord start, FactorWord end)
throws Exception throws Exception
{ {
super(end,workspace); super(end);
this.start = start; this.start = start;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class LineComment extends FactorParsingDefinition public class LineComment extends FactorParsingDefinition
@ -41,10 +40,10 @@ public class LineComment extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public LineComment(FactorWord word, boolean doc, Workspace workspace) public LineComment(FactorWord word, boolean doc)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.doc = doc; this.doc = doc;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class NoParsing extends FactorParsingDefinition public class NoParsing extends FactorParsingDefinition
@ -39,10 +38,10 @@ public class NoParsing extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public NoParsing(FactorWord word, Workspace workspace) public NoParsing(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class PassThrough extends FactorParsingDefinition public class PassThrough extends FactorParsingDefinition
@ -39,10 +38,10 @@ public class PassThrough extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public PassThrough(FactorWord word, Workspace workspace) public PassThrough(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Shuffle extends FactorParsingDefinition public class Shuffle extends FactorParsingDefinition
{ {
@ -40,10 +39,10 @@ public class Shuffle extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Shuffle(FactorWord word, String end, Workspace workspace) public Shuffle(FactorWord word, String end)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.end = end; this.end = end;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class StackComment extends FactorParsingDefinition public class StackComment extends FactorParsingDefinition
@ -39,10 +38,10 @@ public class StackComment extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public StackComment(FactorWord word, Workspace workspace) public StackComment(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class StringLiteral extends FactorParsingDefinition public class StringLiteral extends FactorParsingDefinition
@ -41,11 +40,10 @@ public class StringLiteral extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public StringLiteral(FactorWord word, boolean escapes, public StringLiteral(FactorWord word, boolean escapes)
Workspace workspace)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.escapes = escapes; this.escapes = escapes;
} //}}} } //}}}

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class T extends FactorParsingDefinition public class T extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class T extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public T(FactorWord word, Workspace workspace) public T(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
import java.io.IOException; import java.io.IOException;
public class Unreadable extends FactorParsingDefinition public class Unreadable extends FactorParsingDefinition
@ -39,10 +38,10 @@ public class Unreadable extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Unreadable(FactorWord word, Workspace workspace) public Unreadable(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)

View File

@ -30,7 +30,6 @@
package factor.parser; package factor.parser;
import factor.*; import factor.*;
import factor.db.*;
public class Use extends FactorParsingDefinition public class Use extends FactorParsingDefinition
{ {
@ -38,10 +37,10 @@ public class Use extends FactorParsingDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Use(FactorWord word, Workspace workspace) public Use(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -1 +1 @@
!a;1592;1592 !a;1572;1572

View File

@ -1 +1 @@
!a;1536;1536 !a;1494;1494

View File

@ -1 +1 @@
!a;1592;1592 !a;1572;1572

View File

@ -1 +1 @@
!a;1592;1592 !a;1572;1572

View File

@ -1 +1 @@
!a;1592;1592 !a;1572;1572

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,9 @@ public class Call extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Call(FactorWord word, Workspace workspace) public Call(FactorWord word)
throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Call constructor
/**
* A blank definition, about to be unpickled.
*/
public Call(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,9 +30,7 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.util.Set;
import org.objectweb.asm.*; import org.objectweb.asm.*;
public class Coerce extends FactorPrimitiveDefinition public class Coerce extends FactorPrimitiveDefinition
@ -41,20 +39,10 @@ public class Coerce extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Coerce(FactorWord word, Workspace workspace) public Coerce(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Coerce constructor
/**
* A blank definition, about to be unpickled.
*/
public Coerce(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,9 +30,7 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.util.Map;
public class Define extends FactorPrimitiveDefinition public class Define extends FactorPrimitiveDefinition
{ {
@ -40,20 +38,10 @@ public class Define extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Define(FactorWord word, Workspace workspace) public Define(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Define constructor
/**
* A blank definition, about to be unpickled.
*/
public Define(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Set; import java.util.Set;
@ -42,20 +41,10 @@ public class Execute extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Execute(FactorWord word, Workspace workspace) public Execute(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Execute constructor
/**
* A blank definition, about to be unpickled.
*/
public Execute(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import org.objectweb.asm.*; import org.objectweb.asm.*;
@ -40,20 +39,10 @@ public class Ifte extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Ifte(FactorWord word, Workspace workspace) public Ifte(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Ifte constructor
/**
* A blank definition, about to be unpickled.
*/
public Ifte(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.util.Set; import java.util.Set;
import org.objectweb.asm.*; import org.objectweb.asm.*;
@ -41,20 +40,10 @@ public class InterpreterGet extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public InterpreterGet(FactorWord word, Workspace workspace) public InterpreterGet(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ InterpreterGet constructor
/**
* A blank definition, about to be unpickled.
*/
public InterpreterGet(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -44,24 +43,13 @@ public class JInvoke extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JInvoke(FactorWord word, Workspace workspace, public JInvoke(FactorWord word, boolean staticMethod)
boolean staticMethod)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
this.staticMethod = staticMethod; 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 //{{{ checkStatic() method
private void checkStatic(Method method) throws FactorRuntimeException private void checkStatic(Method method) throws FactorRuntimeException
{ {

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,10 @@ public class JNew extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JNew(FactorWord word, Workspace workspace) public JNew(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ JNew constructor
/**
* A blank definition, about to be unpickled.
*/
public JNew(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,10 @@ public class JVarGet extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JVarGet(FactorWord word, Workspace workspace) public JVarGet(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ JVarGet constructor
/**
* A blank definition, about to be unpickled.
*/
public JVarGet(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,10 @@ public class JVarGetStatic extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JVarGetStatic(FactorWord word, Workspace workspace) public JVarGetStatic(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ JVarGetStatic constructor
/**
* A blank definition, about to be unpickled.
*/
public JVarGetStatic(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,10 @@ public class JVarSet extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JVarSet(FactorWord word, Workspace workspace) public JVarSet(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ JVarSet constructor
/**
* A blank definition, about to be unpickled.
*/
public JVarSet(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Map; import java.util.Map;
@ -42,20 +41,10 @@ public class JVarSetStatic extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public JVarSetStatic(FactorWord word, Workspace workspace) public JVarSetStatic(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ JVarSetStatic constructor
/**
* A blank definition, about to be unpickled.
*/
public JVarSetStatic(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.util.Set; import java.util.Set;
@ -40,20 +39,10 @@ public class Restack extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Restack(FactorWord word, Workspace workspace) public Restack(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Restack constructor
/**
* A blank definition, about to be unpickled.
*/
public Restack(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -30,7 +30,6 @@
package factor.primitives; package factor.primitives;
import factor.compiler.*; import factor.compiler.*;
import factor.db.*;
import factor.*; import factor.*;
import java.util.Set; import java.util.Set;
@ -40,20 +39,10 @@ public class Unstack extends FactorPrimitiveDefinition
/** /**
* A new definition. * A new definition.
*/ */
public Unstack(FactorWord word, Workspace workspace) public Unstack(FactorWord word)
throws Exception throws Exception
{ {
super(word,workspace); super(word);
} //}}}
//{{{ Unstack constructor
/**
* A blank definition, about to be unpickled.
*/
public Unstack(Workspace workspace, long id)
throws Exception
{
super(workspace,id);
} //}}} } //}}}
//{{{ eval() method //{{{ eval() method

View File

@ -29,9 +29,9 @@ IN: errors
USE: combinators USE: combinators
USE: continuations USE: continuations
USE: kernel USE: kernel
USE: inspector
USE: logic USE: logic
USE: namespaces USE: namespaces
USE: prettyprint
USE: stack USE: stack
USE: stdio USE: stdio
USE: strings USE: strings
@ -65,14 +65,7 @@ USE: unparser
suspend ; suspend ;
: ?describe-stack ( stack -- ) : :s ( -- ) "error-datastack" get prettyprint ;
dup [ : :r ( -- ) "error-callstack" get prettyprint ;
describe-stack : :n ( -- ) "error-namestack" get prettyprint ;
] [ : :c ( -- ) "error-catchstack" get prettyprint ;
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 ;

View File

@ -36,18 +36,11 @@ USE: stack
USE: strings USE: strings
USE: vectors USE: vectors
: >c ( catch -- ) : >c ( catch -- ) catchstack* vector-push ;
#! Push a catch block on the catchstack. Use the catch word : c> ( catch -- ) catchstack* vector-pop ;
#! 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 ;
: save-error ( error -- ) : save-error ( error -- )
#! Save the stacks for most-mortem inspection after an #! Save the stacks for post-mortem inspection after an
#! error. #! error.
global [ global [
"error" set "error" set
@ -58,18 +51,14 @@ USE: vectors
] bind ; ] bind ;
: catch ( try catch -- ) : catch ( try catch -- )
#! Call the try quotation, restore the datastack to its #! Call the try quotation. If an error occurs restore the
#! state before the try quotation, push the error (or f if #! datastack, push the error, and call the catch block.
#! no error occurred) and call the catch quotation. #! If no error occurs, push f and call the catch block.
[ >c >r call c> drop f r> f ] callcc1 [ >c >r call c> drop f r> f ] callcc1 rot drop swap call ;
( try catch error ) rot drop swap ( error catch ) call ;
: rethrow ( error -- ) : rethrow ( error -- )
#! Use rethrow when passing an error on from a catch block. #! Use rethrow when passing an error on from a catch block.
#! For convinience, this word is a no-op if error is f. #! For convinience, this word is a no-op if error is f.
[ c> call ] when* ; [ c> call ] when* ;
: throw ( error -- ) : throw ( error -- ) dup save-error rethrow ;
#! Throw an error. If no catch handlers are installed, the
#! default-error-handler is called.
dup save-error rethrow ;

View File

@ -37,7 +37,7 @@ USE: wiki-responder
: default-responders ( -- ) : default-responders ( -- )
#! Remove all existing responders, and create a blank #! Remove all existing responders, and create a blank
#! responder table. #! responder table.
<table> [ <namespace> [
<responder> [ <responder> [
"test" "responder" set "test" "responder" set
[ test-responder ] "get" set [ test-responder ] "get" set
@ -63,7 +63,7 @@ USE: wiki-responder
"wiki" "responder" set "wiki" "responder" set
[ wiki-get-responder ] "get" set [ wiki-get-responder ] "get" set
[ wiki-post-responder ] "post" set [ wiki-post-responder ] "post" set
<table> "wiki" set <namespace> "wiki" set
"WikiHome" "default-argument" set "WikiHome" "default-argument" set
] extend "wiki" set ] extend "wiki" set
] extend "httpd-responders" set ; ] extend "httpd-responders" set ;

View File

@ -39,7 +39,7 @@ USE: strings
USE: httpd USE: httpd
: <responder> ( -- responder ) : <responder> ( -- responder )
<table> [ <namespace> [
[ [
drop "GET method not implemented" httpd-error drop "GET method not implemented" httpd-error
] "get" set ] "get" set

View File

@ -27,7 +27,6 @@
IN: inspector IN: inspector
USE: combinators USE: combinators
USE: errors
USE: format USE: format
USE: kernel USE: kernel
USE: lists USE: lists
@ -82,14 +81,6 @@ USE: vocabularies
[ prettyprint terpri ] [ prettyprint terpri ]
] cond ; ] 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 -- ) : describe-object-path ( string -- )
<namespace> [ <namespace> [
dup "object-path" set dup "object-path" set

View File

@ -69,7 +69,6 @@ USE: parser
"/library/stdio.factor" run-resource ! stdio "/library/stdio.factor" run-resource ! stdio
"/library/platform/jvm/unparser.factor" run-resource ! unparser "/library/platform/jvm/unparser.factor" run-resource ! unparser
"/library/platform/jvm/parser.factor" run-resource ! parser "/library/platform/jvm/parser.factor" run-resource ! parser
"/library/platform/jvm/workspace.factor" run-resource ! workspace
"/library/styles.factor" run-resource ! styles "/library/styles.factor" run-resource ! styles
!!! Math library. !!! Math library.

View File

@ -70,7 +70,6 @@ USE: parser
"/library/stdio.factor" run-resource ! stdio "/library/stdio.factor" run-resource ! stdio
"/library/platform/jvm/unparser.factor" run-resource ! unparser "/library/platform/jvm/unparser.factor" run-resource ! unparser
"/library/platform/jvm/parser.factor" run-resource ! parser "/library/platform/jvm/parser.factor" run-resource ! parser
"/library/platform/jvm/workspace.factor" run-resource ! workspace
"/library/styles.factor" run-resource ! styles "/library/styles.factor" run-resource ! styles
"/library/platform/jvm/threads.factor" run-resource ! threads "/library/platform/jvm/threads.factor" run-resource ! threads
"/library/logging.factor" run-resource ! logging "/library/logging.factor" run-resource ! logging

View File

@ -118,5 +118,7 @@ USE: strings
compile-all compile-all
] when ] when
t "startup-done" set
print-banner print-banner
init-interpreter ; init-interpreter ;

View File

@ -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> ;

View File

@ -85,6 +85,3 @@ DEFER: >n
: namespace-of ; : namespace-of ;
: this namespace ; : this namespace ;
: has-namespace? hashtable? ; : has-namespace? hashtable? ;
! We don't have a workspace in native Factor.
: <table> <namespace> ;

View File

@ -28,6 +28,7 @@
IN: prettyprint IN: prettyprint
USE: arithmetic USE: arithmetic
USE: combinators USE: combinators
USE: errors
USE: format USE: format
USE: kernel USE: kernel
USE: logic USE: logic
@ -39,6 +40,7 @@ USE: stdio
USE: strings USE: strings
USE: styles USE: styles
USE: unparser USE: unparser
USE: vectors
USE: vocabularies USE: vocabularies
USE: words USE: words
@ -75,6 +77,22 @@ DEFER: prettyprint*
: prettyprint-[] ( indent list -- indent ) : prettyprint-[] ( indent list -- indent )
swap prettyprint-[ swap prettyprint-list prettyprint-] ; 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 -- ) : write-comment ( comment -- )
[ "comments" ] get-style [ write-attr ] bind ; [ "comments" ] get-style [ write-attr ] bind ;
@ -112,6 +130,7 @@ DEFER: prettyprint*
[ [
[ not ] [ prettyprint-object ] [ not ] [ prettyprint-object ]
[ list? ] [ prettyprint-[] ] [ list? ] [ prettyprint-[] ]
[ vector? ] [ prettyprint-{} ]
[ comment? ] [ prettyprint-comment ] [ comment? ] [ prettyprint-comment ]
[ word? ] [ prettyprint-word ] [ word? ] [ prettyprint-word ]
[ drop t ] [ prettyprint-object ] [ drop t ] [ prettyprint-object ]
@ -131,3 +150,8 @@ DEFER: prettyprint*
: prettyprint-:; ( indent word list -- indent ) : prettyprint-:; ( indent word list -- indent )
[ [ prettyprint-: ] dip prettyprint-word ] dip [ [ prettyprint-: ] dip prettyprint-word ] dip
prettyprint-list prettyprint-; ; prettyprint-list prettyprint-; ;
: .n namestack prettyprint ;
: .s datastack prettyprint ;
: .r callstack prettyprint ;
: .c catchstack prettyprint ;

View File

@ -67,9 +67,9 @@ USE: stack
: init-styles ( -- ) : init-styles ( -- )
<table> "styles" set <namespace> "styles" set
"styles" get [ "styles" get [
<table> [ <namespace> [
f "ansi-fg" set f "ansi-fg" set
f "ansi-bg" set f "ansi-bg" set
f "fg" set f "fg" set
@ -82,7 +82,7 @@ USE: stack
] extend "default" set ] extend "default" set
! A paragraph break ! A paragraph break
<table> [ <namespace> [
t "paragraph" set t "paragraph" set
] extend "paragraph" set ] extend "paragraph" set
] bind ] bind

View File

@ -2,7 +2,6 @@ IN: scratchpad
USE: arithmetic USE: arithmetic
USE: combinators USE: combinators
USE: compiler USE: compiler
USE: inspector
USE: kernel USE: kernel
USE: lists USE: lists
USE: logic USE: logic

View File

@ -44,8 +44,6 @@ USE: vocabularies
[ [ 5 1 0 0 ] ] [ [ >=< ] ] [ balance>list ] test-word [ [ 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 [ [ 1 0 0 0 ] ] [ [ exit* ] ] [ balance>list ] test-word
[ [ 0 1 0 0 ] ] [ [ millis ] ] [ balance>list ] test-word [ [ 0 1 0 0 ] ] [ [ millis ] ] [ balance>list ] test-word

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -81,8 +81,6 @@ USE: vocabularies
"tail" "tail"
"types" "types"
"vectors" "vectors"
!"store"
!"reboot"
] [ ] [
test test
] each ] each

View File

@ -51,7 +51,7 @@ USE: words
] ifte ; ] ifte ;
: init-vocab-styles ( -- ) : init-vocab-styles ( -- )
"styles" get [ <table> "vocabularies" set ] bind "styles" get [ <namespace> "vocabularies" set ] bind
[ [
[ "ansi-fg" | "1" ] [ "ansi-fg" | "1" ]