communicates stack effect from socket
parent
84d1667fdf
commit
cf75abc247
|
@ -135,7 +135,11 @@ public class ExternalFactor extends DefaultVocabularyLookup
|
|||
return null;
|
||||
|
||||
result = (Cons)result.car;
|
||||
return new FactorWord((String)result.car,(String)result.next().car);
|
||||
w = new FactorWord(
|
||||
(String)result.car,
|
||||
(String)result.next().car);
|
||||
w.stackEffect = (String)result.next().next().car;
|
||||
return w;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
|
|
@ -38,7 +38,6 @@ import java.util.*;
|
|||
public class FactorCompoundDefinition extends FactorWordDefinition
|
||||
{
|
||||
public Cons definition;
|
||||
private Cons endOfDocs;
|
||||
|
||||
//{{{ FactorCompoundDefinition constructor
|
||||
/**
|
||||
|
@ -48,15 +47,6 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
{
|
||||
super(word);
|
||||
this.definition = definition;
|
||||
if(definition == null)
|
||||
endOfDocs = null;
|
||||
else
|
||||
{
|
||||
endOfDocs = definition;
|
||||
while(endOfDocs != null
|
||||
&& endOfDocs.car instanceof FactorDocComment)
|
||||
endOfDocs = endOfDocs.next();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
|
|
|
@ -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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class FactorDocComment implements FactorExternalizable
|
||||
{
|
||||
private String msg;
|
||||
private boolean stack;
|
||||
|
||||
public FactorDocComment(String msg, boolean stack)
|
||||
{
|
||||
if(stack)
|
||||
msg = msg.trim();
|
||||
this.msg = msg;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if(stack)
|
||||
return "( " + msg + " )\n";
|
||||
else
|
||||
return "#! " + msg + "\n";
|
||||
}
|
||||
|
||||
public boolean isStackComment()
|
||||
{
|
||||
return stack;
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* :folding=explicit:collapseFolds=1: */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package factor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* All primitive words extend this.
|
||||
*/
|
||||
public abstract class FactorPrimitiveDefinition extends FactorWordDefinition
|
||||
{
|
||||
//{{{ FactorPrimitiveDefinition constructor
|
||||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public FactorPrimitiveDefinition(FactorWord word)
|
||||
{
|
||||
super(word);
|
||||
} //}}}
|
||||
|
||||
//{{{ fromList() method
|
||||
public void fromList(Cons cons)
|
||||
{
|
||||
} //}}}
|
||||
}
|
|
@ -269,6 +269,8 @@ public class FactorReader
|
|||
w.line = line;
|
||||
w.col = col;
|
||||
w.file = scanner.getFileName();
|
||||
w.stackEffect = null;
|
||||
w.documentation = null;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
@ -313,8 +315,7 @@ public class FactorReader
|
|||
return true;
|
||||
else if(next instanceof String)
|
||||
{
|
||||
FactorWord word = intern((String)next,
|
||||
!getCurrentState().warnUndefined);
|
||||
FactorWord word = intern((String)next,false);
|
||||
if(word == null)
|
||||
{
|
||||
/* We're ignoring errors */
|
||||
|
@ -341,24 +342,22 @@ public class FactorReader
|
|||
* An exclusive state can only happen at the top level.
|
||||
* For example, : ... ; definitions cannot be nested so they
|
||||
* are exclusive.
|
||||
*
|
||||
* @param args Parsing words can use this to store arbitrary info
|
||||
*/
|
||||
public void pushExclusiveState(FactorWord start, Object args)
|
||||
public void pushExclusiveState(FactorWord start, FactorWord defining)
|
||||
throws FactorParseException
|
||||
{
|
||||
if(getCurrentState().start != toplevel)
|
||||
scanner.error(start + " cannot be nested");
|
||||
pushState(start,args);
|
||||
pushState(start,defining);
|
||||
} //}}}
|
||||
|
||||
//{{{ pushState() method
|
||||
/**
|
||||
* Push a parser state, for example reading of a list.
|
||||
*/
|
||||
public void pushState(FactorWord start, Object args)
|
||||
public void pushState(FactorWord start, FactorWord defining)
|
||||
{
|
||||
states = new Cons(new ParseState(start,args),states);
|
||||
states = new Cons(new ParseState(start,defining),states);
|
||||
} //}}}
|
||||
|
||||
//{{{ popState() method
|
||||
|
@ -391,6 +390,18 @@ public class FactorReader
|
|||
getCurrentState().append(obj);
|
||||
} //}}}
|
||||
|
||||
//{{{ setStackComment() method
|
||||
public void setStackComment(String comment)
|
||||
{
|
||||
getCurrentState().setStackComment(comment);
|
||||
} //}}}
|
||||
|
||||
//{{{ addDocComment() method
|
||||
public void addDocComment(String comment)
|
||||
{
|
||||
getCurrentState().addDocComment(comment);
|
||||
} //}}}
|
||||
|
||||
//{{{ bar() method
|
||||
/**
|
||||
* Sets the current parser state's cdr to the given object.
|
||||
|
@ -410,39 +421,24 @@ public class FactorReader
|
|||
public class ParseState
|
||||
{
|
||||
public FactorWord start;
|
||||
public Object arg;
|
||||
public FactorWord defining;
|
||||
public Cons first;
|
||||
public Cons last;
|
||||
public boolean warnUndefined;
|
||||
private boolean comma;
|
||||
private boolean bar;
|
||||
private boolean docComment;
|
||||
|
||||
ParseState(FactorWord start, Object arg)
|
||||
ParseState(FactorWord start, FactorWord defining)
|
||||
{
|
||||
docComment = start.docComment;
|
||||
warnUndefined = true;
|
||||
this.start = start;
|
||||
this.arg = arg;
|
||||
this.defining = defining;
|
||||
}
|
||||
|
||||
void append(Object obj) throws FactorParseException
|
||||
{
|
||||
boolean docComment = (this.docComment || alwaysDocComments);
|
||||
// In a doc comment context, first object is always
|
||||
// a word, then followed by doc comments, then followed
|
||||
// by code.
|
||||
if(docComment && !(obj instanceof FactorDocComment)
|
||||
&& first != null)
|
||||
{
|
||||
this.docComment = false;
|
||||
}
|
||||
else if(!docComment && obj instanceof FactorDocComment)
|
||||
{
|
||||
//scanner.error("Documentation comment not allowed here");
|
||||
return;
|
||||
}
|
||||
docComment = false;
|
||||
|
||||
if(comma)
|
||||
if(bar)
|
||||
{
|
||||
if(last.cdr != null)
|
||||
scanner.error("Only one token allowed after |");
|
||||
|
@ -459,6 +455,27 @@ public class FactorReader
|
|||
}
|
||||
}
|
||||
|
||||
void setStackComment(String comment)
|
||||
{
|
||||
if(defining != null && defining.stackEffect == null)
|
||||
defining.stackEffect = comment;
|
||||
}
|
||||
|
||||
void addDocComment(String comment)
|
||||
{
|
||||
if(defining != null && (docComment || alwaysDocComments))
|
||||
{
|
||||
if(defining.documentation == null)
|
||||
defining.documentation = comment;
|
||||
else
|
||||
{
|
||||
/* Its O(n^2). Big deal. */
|
||||
defining.documentation = defining.documentation
|
||||
.concat(comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bar() throws FactorParseException
|
||||
{
|
||||
if(last.cdr != null)
|
||||
|
@ -468,7 +485,7 @@ public class FactorReader
|
|||
scanner.error("Only one token allowed after |");
|
||||
}
|
||||
|
||||
comma = true;
|
||||
bar = true;
|
||||
}
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -1,43 +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;
|
||||
|
||||
public class FactorRuntimeException extends FactorException
|
||||
{
|
||||
public FactorRuntimeException(String str)
|
||||
{
|
||||
super(str);
|
||||
}
|
||||
|
||||
public FactorRuntimeException(String str, Throwable t)
|
||||
{
|
||||
super(str,t);
|
||||
}
|
||||
}
|
|
@ -36,21 +36,21 @@ import java.util.*;
|
|||
*/
|
||||
public class FactorWord implements FactorExternalizable
|
||||
{
|
||||
private static int gensymCount = 0;
|
||||
|
||||
public String vocabulary;
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Interpreted/compiled word definition.
|
||||
*/
|
||||
public FactorWordDefinition def;
|
||||
public String stackEffect;
|
||||
public String documentation;
|
||||
|
||||
/**
|
||||
* Parsing word definition.
|
||||
*/
|
||||
public FactorParsingDefinition parsing;
|
||||
|
||||
/**
|
||||
* Stub for interpreter definitin.
|
||||
*/
|
||||
public FactorWordDefinition def;
|
||||
|
||||
/**
|
||||
* Should the parser keep doc comments?
|
||||
*/
|
||||
|
@ -64,37 +64,12 @@ public class FactorWord implements FactorExternalizable
|
|||
public int col;
|
||||
|
||||
//{{{ FactorWord constructor
|
||||
/**
|
||||
* Do not use this constructor unless you're writing a packages
|
||||
* implementation or something. Use an FactorDictionary's
|
||||
* intern() method instead.
|
||||
*/
|
||||
public FactorWord(String vocabulary, String name,
|
||||
FactorWordDefinition def)
|
||||
{
|
||||
this.vocabulary = vocabulary;
|
||||
this.name = name;
|
||||
this.def = def;
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWord constructor
|
||||
/**
|
||||
* Do not use this constructor unless you're writing a packages
|
||||
* implementation or something. Use an FactorDictionary's
|
||||
* intern() method instead.
|
||||
*/
|
||||
public FactorWord(String vocabulary, String name)
|
||||
{
|
||||
this.vocabulary = vocabulary;
|
||||
this.name = name;
|
||||
} //}}}
|
||||
|
||||
//{{{ define() method
|
||||
public void define(FactorWordDefinition def)
|
||||
{
|
||||
this.def = def;
|
||||
} //}}}
|
||||
|
||||
//{{{ toString() method
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -1,444 +0,0 @@
|
|||
/* :folding=explicit:collapseFolds=1: */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Slava Pestov.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package factor;
|
||||
|
||||
import factor.db.*;
|
||||
import factor.compiler.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
/**
|
||||
* A word definition.
|
||||
*
|
||||
* The pickled form is an unparsed list. The car of the list is the word,
|
||||
* the cdr is toList().
|
||||
*/
|
||||
public abstract class FactorWordDefinition
|
||||
implements Constants, PersistentObject
|
||||
{
|
||||
public static final String ENCODING = "UTF8";
|
||||
|
||||
private Workspace workspace;
|
||||
private long id;
|
||||
|
||||
public FactorWord word;
|
||||
|
||||
public boolean compileFailed;
|
||||
|
||||
//{{{ FactorWordDefinition constructor
|
||||
/**
|
||||
* A new definition.
|
||||
*/
|
||||
public FactorWordDefinition(FactorWord word, Workspace workspace)
|
||||
{
|
||||
this(workspace,workspace == null
|
||||
? 0L : workspace.nextID());
|
||||
this.word = word;
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWordDefinition constructor
|
||||
/**
|
||||
* A blank definition, about to be unpickled.
|
||||
*/
|
||||
public FactorWordDefinition(Workspace workspace, long id)
|
||||
{
|
||||
this.workspace = workspace;
|
||||
this.id = id;
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorWordDefinition constructor
|
||||
/**
|
||||
* A definition that is not saved in the current workspace.
|
||||
*/
|
||||
public FactorWordDefinition(FactorWord word)
|
||||
{
|
||||
this.word = word;
|
||||
} //}}}
|
||||
|
||||
public abstract void eval(FactorInterpreter interp)
|
||||
throws Exception;
|
||||
|
||||
//{{{ fromList() method
|
||||
public void fromList(Cons cons, FactorInterpreter interp)
|
||||
throws FactorRuntimeException, PersistenceException
|
||||
{
|
||||
throw new PersistenceException("Cannot unpickle " + this);
|
||||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
public Cons toList(FactorInterpreter interp)
|
||||
{
|
||||
return new Cons(new FactorWord(null,getClass().getName()),null);
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffect() method
|
||||
public final StackEffect getStackEffect(FactorInterpreter interp)
|
||||
throws Exception
|
||||
{
|
||||
return getStackEffect(interp,new RecursiveState());
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffect() method
|
||||
public final StackEffect getStackEffect(FactorInterpreter interp,
|
||||
RecursiveState recursiveCheck)
|
||||
throws Exception
|
||||
{
|
||||
FactorCompiler compiler = new FactorCompiler(interp);
|
||||
recursiveCheck.add(word,new StackEffect(),null,null,null);
|
||||
compileCallTo(null,compiler,recursiveCheck);
|
||||
recursiveCheck.remove(word);
|
||||
return compiler.getStackEffect();
|
||||
} //}}}
|
||||
/*
|
||||
//{{{ getStackEffect() method
|
||||
public void getStackEffect(RecursiveState recursiveCheck,
|
||||
FactorCompiler compiler) throws Exception
|
||||
{
|
||||
compileCallTo(null,compiler,recursiveCheck);
|
||||
} //}}}
|
||||
*/
|
||||
//{{{ compile() method
|
||||
FactorWordDefinition compile(FactorInterpreter interp,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
return this;
|
||||
} //}}}
|
||||
|
||||
//{{{ getDefinition() method
|
||||
protected Cons getDefinition(FactorInterpreter interp)
|
||||
throws FactorCompilerException
|
||||
{
|
||||
Cons definition = toList(interp);
|
||||
|
||||
while(definition != null
|
||||
&& definition.car instanceof FactorDocComment)
|
||||
definition = definition.next();
|
||||
|
||||
return definition;
|
||||
} //}}}
|
||||
|
||||
//{{{ compileCallTo() method
|
||||
/**
|
||||
* Compile a call to this word. Returns maximum JVM stack use.
|
||||
*/
|
||||
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
// normal word
|
||||
String defclass;
|
||||
String defmethod;
|
||||
StackEffect effect;
|
||||
|
||||
FactorClassLoader loader;
|
||||
|
||||
RecursiveForm rec = recursiveCheck.get(word);
|
||||
if(rec != null && rec.active)
|
||||
{
|
||||
if(compiler.interp.verboseCompile)
|
||||
System.err.println("Recursive call to " + rec);
|
||||
effect = StackEffect.decompose(rec.effect,rec.baseCase);
|
||||
|
||||
// are we recursing back on a form inside the current
|
||||
// method?
|
||||
RecursiveForm last = recursiveCheck.last();
|
||||
if(mw != null
|
||||
&& recursiveCheck.allTails(rec)
|
||||
&& last.className.equals(rec.className)
|
||||
&& last.method.equals(rec.method))
|
||||
{
|
||||
if(compiler.interp.verboseCompile)
|
||||
System.err.println(word + " is tail recursive");
|
||||
// GOTO instad of INVOKEVIRTUAL; ie a loop!
|
||||
compiler.normalizeStacks(mw);
|
||||
mw.visitJumpInsn(GOTO,rec.label);
|
||||
compiler.apply(effect);
|
||||
return;
|
||||
}
|
||||
|
||||
/* recursive method call! */
|
||||
defclass = rec.className;
|
||||
defmethod = rec.method;
|
||||
loader = rec.loader;
|
||||
|
||||
if(mw != null && !defclass.equals(compiler.className))
|
||||
compiler.loader.addDependency(defclass,loader);
|
||||
}
|
||||
else if(mw == null)
|
||||
{
|
||||
Cons definition = getDefinition(compiler.interp);
|
||||
compiler.getStackEffect(definition,recursiveCheck);
|
||||
return;
|
||||
}
|
||||
// not a recursive call but we're still not compiled
|
||||
// its a bug in the compiler.
|
||||
else if(this instanceof FactorCompoundDefinition)
|
||||
{
|
||||
throw new FactorCompilerException("You are an idiot!");
|
||||
}
|
||||
/* ordinary method call! */
|
||||
else
|
||||
{
|
||||
defclass = getClass().getName().replace('.','/');
|
||||
defmethod = "core";
|
||||
effect = getStackEffect(compiler.interp,
|
||||
new RecursiveState());
|
||||
ClassLoader l = getClass().getClassLoader();
|
||||
if(l instanceof FactorClassLoader)
|
||||
{
|
||||
loader = (FactorClassLoader)l;
|
||||
compiler.loader.addDependency(
|
||||
getClass().getName(),loader);
|
||||
}
|
||||
else
|
||||
loader = null;
|
||||
}
|
||||
|
||||
if(mw == null)
|
||||
compiler.apply(effect);
|
||||
else
|
||||
{
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
compiler.generateArgs(mw,effect.inD,effect.inR,null);
|
||||
String signature = effect.getCorePrototype();
|
||||
mw.visitMethodInsn(INVOKESTATIC,defclass,defmethod,signature);
|
||||
compiler.generateReturn(mw,effect.outD,effect.outR);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compileNonRecursiveImmediate() method
|
||||
/**
|
||||
* Non-recursive immediate words are inlined.
|
||||
*/
|
||||
protected void compileNonRecursiveImmediate(CodeVisitor mw,
|
||||
FactorCompiler compiler,
|
||||
RecursiveState recursiveCheck,
|
||||
StackEffect immediateEffect) throws Exception
|
||||
{
|
||||
Cons definition = toList(compiler.getInterpreter());
|
||||
|
||||
Cons endOfDocs = definition;
|
||||
while(endOfDocs != null
|
||||
&& endOfDocs.car instanceof FactorDocComment)
|
||||
endOfDocs = endOfDocs.next();
|
||||
|
||||
compiler.compile(endOfDocs,mw,recursiveCheck);
|
||||
} //}}}
|
||||
|
||||
//{{{ compileRecursiveImmediate() method
|
||||
/**
|
||||
* Recursive immediate words are compiled to an auxiliary method
|
||||
* inside the compiled class definition.
|
||||
*
|
||||
* This must be done so that recursion has something to jump to.
|
||||
*/
|
||||
protected void compileRecursiveImmediate(CodeVisitor mw,
|
||||
FactorCompiler compiler,
|
||||
RecursiveState recursiveCheck,
|
||||
StackEffect immediateEffect) throws Exception
|
||||
{
|
||||
Cons definition = toList(compiler.getInterpreter());
|
||||
|
||||
Cons endOfDocs = definition;
|
||||
while(endOfDocs != null
|
||||
&& endOfDocs.car instanceof FactorDocComment)
|
||||
endOfDocs = endOfDocs.next();
|
||||
|
||||
String method = compiler.auxiliary(word,
|
||||
endOfDocs,immediateEffect,recursiveCheck);
|
||||
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
|
||||
compiler.generateArgs(mw,immediateEffect.inD,
|
||||
immediateEffect.inR,null);
|
||||
|
||||
String signature = immediateEffect.getCorePrototype();
|
||||
|
||||
mw.visitMethodInsn(INVOKESTATIC,compiler.className,
|
||||
method,signature);
|
||||
|
||||
compiler.generateReturn(mw,
|
||||
immediateEffect.outD,
|
||||
immediateEffect.outR);
|
||||
} //}}}
|
||||
|
||||
//{{{ compileImmediate() method
|
||||
/**
|
||||
* Compile a call to this word. Returns maximum JVM stack use.
|
||||
*/
|
||||
public void compileImmediate(CodeVisitor mw, FactorCompiler compiler,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
Cons definition = getDefinition(compiler.interp);
|
||||
|
||||
if(mw == null)
|
||||
{
|
||||
compiler.compile(definition,null,recursiveCheck);
|
||||
return;
|
||||
}
|
||||
|
||||
// determine stack effect of this instantiation, and if its
|
||||
// recursive.
|
||||
|
||||
FactorArrayStack savedDatastack = (FactorArrayStack)
|
||||
compiler.datastack.clone();
|
||||
FactorCallStack savedCallstack = (FactorCallStack)
|
||||
compiler.callstack.clone();
|
||||
StackEffect savedEffect = compiler.getStackEffect();
|
||||
|
||||
RecursiveState _recursiveCheck = (RecursiveState)
|
||||
recursiveCheck.clone();
|
||||
_recursiveCheck.last().effect = compiler.getStackEffect();
|
||||
compileImmediate(null,compiler,_recursiveCheck);
|
||||
|
||||
boolean recursive = (_recursiveCheck.last().baseCase != null);
|
||||
|
||||
StackEffect effect = compiler.getStackEffect();
|
||||
|
||||
StackEffect immediateEffect = StackEffect.decompose(
|
||||
savedEffect,compiler.getStackEffect());
|
||||
|
||||
// restore previous state.
|
||||
|
||||
FactorArrayStack afterDatastack = (FactorArrayStack)
|
||||
compiler.datastack.clone();
|
||||
FactorCallStack afterCallstack = (FactorCallStack)
|
||||
compiler.callstack.clone();
|
||||
|
||||
compiler.datastack = (FactorArrayStack)savedDatastack.clone();
|
||||
compiler.callstack = (FactorCallStack)savedCallstack.clone();
|
||||
compiler.effect = savedEffect;
|
||||
|
||||
if(!recursive)
|
||||
{
|
||||
// not recursive; inline.
|
||||
compileNonRecursiveImmediate(mw,compiler,recursiveCheck,
|
||||
immediateEffect);
|
||||
}
|
||||
else
|
||||
{
|
||||
// recursive; must generate auxiliary method.
|
||||
compileRecursiveImmediate(mw,compiler,recursiveCheck,
|
||||
immediateEffect);
|
||||
|
||||
mergeStacks(savedDatastack,afterDatastack,compiler.datastack);
|
||||
mergeStacks(savedCallstack,afterCallstack,compiler.callstack);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ mergeStacks() method
|
||||
private void mergeStacks(FactorArrayStack s1, FactorArrayStack s2,
|
||||
FactorArrayStack into)
|
||||
{
|
||||
for(int i = 0; i < s2.top; i++)
|
||||
{
|
||||
if(s1.top <= i)
|
||||
break;
|
||||
|
||||
if(FactorLib.objectsEqual(s1.stack[i],
|
||||
s2.stack[i]))
|
||||
{
|
||||
into.stack[i] = s1.stack[i];
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ 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(FactorInterpreter interp)
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
Cons pickle = new Cons(word,toList(interp));
|
||||
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, FactorInterpreter interp)
|
||||
throws PersistenceException
|
||||
{
|
||||
try
|
||||
{
|
||||
String unparsed = new String(bytes,offset,
|
||||
bytes.length - offset,ENCODING);
|
||||
Cons pickle = (Cons)FactorReader.parseObject(unparsed,
|
||||
interp);
|
||||
word = (FactorWord)pickle.car;
|
||||
fromList(pickle.next(),interp);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// should not happen with byte array stream
|
||||
throw new PersistenceException("Unexpected error",e);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ toString() method
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getName() + ": " + word;
|
||||
} //}}}
|
||||
}
|
|
@ -1,35 +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;
|
||||
|
||||
public interface PublicCloneable extends Cloneable
|
||||
{
|
||||
Object clone();
|
||||
}
|
|
@ -1,983 +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.compiler;
|
||||
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class FactorCompiler implements Constants
|
||||
{
|
||||
public final FactorInterpreter interp;
|
||||
|
||||
public final FactorWord word;
|
||||
public final String className;
|
||||
public final FactorClassLoader loader;
|
||||
public String method;
|
||||
|
||||
private int base;
|
||||
private int allotD;
|
||||
private int allotR;
|
||||
|
||||
public FactorArrayStack datastack;
|
||||
public FactorCallStack callstack;
|
||||
|
||||
private int literalCount;
|
||||
|
||||
private Map literals;
|
||||
|
||||
public StackEffect effect;
|
||||
|
||||
/**
|
||||
* getStackEffect() turns these into arrays and places them in the
|
||||
* returned object.
|
||||
*/
|
||||
private Cons inDtypes, inRtypes;
|
||||
|
||||
private Cons aux;
|
||||
private int auxCount;
|
||||
|
||||
//{{{ FactorCompiler constructor
|
||||
/**
|
||||
* For balancing.
|
||||
*/
|
||||
public FactorCompiler(FactorInterpreter interp)
|
||||
{
|
||||
this(interp,null,null,null);
|
||||
init(0,0,0,null);
|
||||
} //}}}
|
||||
|
||||
//{{{ FactorCompiler constructor
|
||||
/**
|
||||
* For compiling.
|
||||
*/
|
||||
public FactorCompiler(FactorInterpreter interp,
|
||||
FactorWord word, String className,
|
||||
FactorClassLoader loader)
|
||||
{
|
||||
this.interp = interp;
|
||||
this.word = word;
|
||||
this.className = className;
|
||||
this.loader = loader;
|
||||
|
||||
literals = new HashMap();
|
||||
|
||||
datastack = new FactorArrayStack();
|
||||
callstack = new FactorCallStack();
|
||||
} //}}}
|
||||
|
||||
//{{{ getInterpreter() method
|
||||
public FactorInterpreter getInterpreter()
|
||||
{
|
||||
return interp;
|
||||
} //}}}
|
||||
|
||||
//{{{ init() method
|
||||
public void init(int base, int allotD, int allotR, String method)
|
||||
{
|
||||
effect = new StackEffect();
|
||||
|
||||
this.base = base;
|
||||
|
||||
datastack.top = 0;
|
||||
callstack.top = 0;
|
||||
|
||||
for(int i = 0; i < allotD; i++)
|
||||
{
|
||||
Result r = new Result(base + i,this,null,
|
||||
Object.class);
|
||||
datastack.push(r);
|
||||
inDtypes = new Cons(r,inDtypes);
|
||||
}
|
||||
|
||||
for(int i = 0; i < allotR; i++)
|
||||
{
|
||||
Result r = new Result(base + allotD + i,this,null,
|
||||
Object.class);
|
||||
callstack.push(r);
|
||||
inRtypes = new Cons(r,inRtypes);
|
||||
}
|
||||
|
||||
this.allotD = allotD;
|
||||
this.allotR = allotR;
|
||||
effect.inD = allotD;
|
||||
effect.inR = allotR;
|
||||
|
||||
this.method = method;
|
||||
} //}}}
|
||||
|
||||
//{{{ getAllotedEffect() method
|
||||
public StackEffect getAllotedEffect()
|
||||
{
|
||||
return new StackEffect(allotD,allotR,0,0);
|
||||
} //}}}
|
||||
|
||||
//{{{ ensure() method
|
||||
public void ensure(FactorArrayStack stack, Class type)
|
||||
{
|
||||
if(stack.top == 0)
|
||||
{
|
||||
Result r = new Result(allocate(),this,null,type);
|
||||
if(stack == datastack)
|
||||
{
|
||||
inDtypes = new Cons(r,inDtypes);
|
||||
effect.inD++;
|
||||
}
|
||||
else if(stack == callstack)
|
||||
{
|
||||
inRtypes = new Cons(r,inRtypes);
|
||||
effect.inR++;
|
||||
}
|
||||
stack.push(r);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ ensure() method
|
||||
/**
|
||||
* Ensure stack has at least 'count' elements.
|
||||
* Eg, if count is 4 and stack is A B,
|
||||
* stack will become RESULT RESULT A B.
|
||||
* Used when deducing stack effects.
|
||||
*/
|
||||
public void ensure(FactorArrayStack stack, int count)
|
||||
{
|
||||
Class[] types = new Class[count];
|
||||
for(int i = 0; i < types.length; i++)
|
||||
types[i] = Object.class;
|
||||
ensure(stack,types);
|
||||
} //}}}
|
||||
|
||||
//{{{ ensure() method
|
||||
/**
|
||||
* Ensure stack has at least 'count' elements.
|
||||
* Eg, if count is 4 and stack is A B,
|
||||
* stack will become RESULT RESULT A B.
|
||||
* Used when deducing stack effects.
|
||||
*/
|
||||
public void ensure(FactorArrayStack stack, Class[] types)
|
||||
{
|
||||
int top = stack.top;
|
||||
if(top < types.length)
|
||||
{
|
||||
Cons typespec = null;
|
||||
|
||||
if(stack == datastack)
|
||||
effect.inD += (types.length - top);
|
||||
else if(stack == callstack)
|
||||
effect.inR += (types.length - top);
|
||||
|
||||
stack.ensurePush(types.length - top);
|
||||
System.arraycopy(stack.stack,0,stack.stack,
|
||||
types.length - top,top);
|
||||
for(int i = 0; i < types.length - top; i++)
|
||||
{
|
||||
int local = allocate();
|
||||
Result r = new Result(
|
||||
local,this,null,types[i]);
|
||||
stack.stack[i] = r;
|
||||
typespec = new Cons(r,typespec);
|
||||
}
|
||||
stack.top = types.length;
|
||||
|
||||
if(stack == datastack)
|
||||
inDtypes = Cons.nappend(inDtypes,typespec);
|
||||
else if(stack == callstack)
|
||||
inRtypes = Cons.nappend(inRtypes,typespec);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ consume() method
|
||||
public void consume(FactorArrayStack stack, int count)
|
||||
{
|
||||
ensure(stack,count);
|
||||
stack.top -= count;
|
||||
} //}}}
|
||||
|
||||
//{{{ produce() method
|
||||
public void produce(FactorArrayStack stack, int count)
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
int local = allocate();
|
||||
stack.push(new Result(local,this,null,Object.class));
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ apply() method
|
||||
public void apply(StackEffect se)
|
||||
{
|
||||
consume(datastack,se.inD);
|
||||
produce(datastack,se.outD);
|
||||
consume(callstack,se.inR);
|
||||
produce(callstack,se.outR);
|
||||
} //}}}
|
||||
|
||||
//{{{ getTypeSpec() method
|
||||
private Class[] getTypeSpec(Cons list)
|
||||
{
|
||||
if(list == null)
|
||||
return new Class[0];
|
||||
|
||||
int length = list.length();
|
||||
Class[] typespec = new Class[length];
|
||||
int i = 0;
|
||||
while(list != null)
|
||||
{
|
||||
typespec[length - i - 1]
|
||||
= ((FlowObject)list.car).getType();
|
||||
i++;
|
||||
list = list.next();
|
||||
}
|
||||
|
||||
return typespec;
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffect() method
|
||||
public StackEffect getStackEffect()
|
||||
{
|
||||
effect.inDtypes = getTypeSpec(inDtypes);
|
||||
|
||||
effect.outD = datastack.top;
|
||||
|
||||
effect.outDtypes = new Class[datastack.top];
|
||||
for(int i = 0; i < datastack.top; i++)
|
||||
{
|
||||
effect.outDtypes[i] = ((FlowObject)datastack.stack[i])
|
||||
.getType();
|
||||
}
|
||||
|
||||
effect.inRtypes = getTypeSpec(inRtypes);
|
||||
|
||||
effect.outR = callstack.top;
|
||||
|
||||
effect.outRtypes = new Class[callstack.top];
|
||||
for(int i = 0; i < callstack.top; i++)
|
||||
{
|
||||
effect.outRtypes[i] = ((FlowObject)callstack.stack[i])
|
||||
.getType();
|
||||
}
|
||||
|
||||
return (StackEffect)effect.clone();
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffect() method
|
||||
public void getStackEffect(Cons definition,
|
||||
RecursiveState recursiveCheck)
|
||||
throws Exception
|
||||
{
|
||||
while(definition != null)
|
||||
{
|
||||
Object obj = definition.car;
|
||||
if(obj instanceof FactorWord)
|
||||
getStackEffectOfWord((FactorWord)obj,recursiveCheck);
|
||||
else
|
||||
pushLiteral(obj,recursiveCheck);
|
||||
|
||||
definition = definition.next();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffectOfWord() method
|
||||
private void getStackEffectOfWord(FactorWord word,
|
||||
RecursiveState recursiveCheck)
|
||||
throws Exception
|
||||
{
|
||||
RecursiveForm rec = recursiveCheck.get(word);
|
||||
|
||||
try
|
||||
{
|
||||
boolean recursiveCall;
|
||||
if(rec == null)
|
||||
{
|
||||
recursiveCall = false;
|
||||
recursiveCheck.add(word,
|
||||
getStackEffect(),
|
||||
className,loader,
|
||||
"core");
|
||||
/* recursiveCheck.last().tail
|
||||
= (word.def instanceof FactorPrimitiveDefinition); */
|
||||
}
|
||||
else
|
||||
{
|
||||
recursiveCall = true;
|
||||
rec.active = true;
|
||||
}/*
|
||||
if(rec == null)
|
||||
recursiveCheck.add(word,getStackEffect(),null,null,null);
|
||||
else
|
||||
rec.active = true; */
|
||||
|
||||
compileCallTo(word,null,recursiveCheck,false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(rec == null)
|
||||
recursiveCheck.remove(word);
|
||||
else
|
||||
{
|
||||
rec.active = false;
|
||||
rec.tail = false;
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compileCore() method
|
||||
public void compileCore(Cons definition, ClassWriter cw,
|
||||
StackEffect effect, RecursiveState recursiveCheck)
|
||||
throws Exception
|
||||
{
|
||||
RecursiveForm last = recursiveCheck.last();
|
||||
last.method = "core";
|
||||
last.className = className;
|
||||
last.loader = loader;
|
||||
|
||||
compileMethod(definition,cw,"core",effect,word,recursiveCheck,true);
|
||||
} //}}}
|
||||
|
||||
//{{{ compileFieldInit() method
|
||||
private void compileFieldInit(CodeVisitor mw, Label start)
|
||||
{
|
||||
mw.visitFieldInsn(GETSTATIC,className,"initialized","Z");
|
||||
mw.visitJumpInsn(IFNE,start);
|
||||
mw.visitInsn(ICONST_1);
|
||||
mw.visitFieldInsn(PUTSTATIC,className,"initialized","Z");
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitMethodInsn(INVOKESTATIC,className,"setFields",
|
||||
"(Lfactor/FactorInterpreter;)V");
|
||||
} //}}}
|
||||
|
||||
//{{{ compileReturn() method
|
||||
/**
|
||||
* Once the word finishes executing, any return values need to be
|
||||
* passed up.
|
||||
*/
|
||||
private void compileReturn(CodeVisitor mw, Label end,
|
||||
StackEffect effect) throws Exception
|
||||
{
|
||||
// special case where return value is passed on
|
||||
// JVM operand stack
|
||||
|
||||
// note: in each branch, must visit end label before RETURN!
|
||||
if(effect.outD == 0 && effect.outR == 0)
|
||||
{
|
||||
mw.visitLabel(end);
|
||||
mw.visitInsn(RETURN);
|
||||
}
|
||||
else if(effect.outD == 1 && effect.outR == 0)
|
||||
{
|
||||
pop(datastack,mw,Object.class);
|
||||
mw.visitLabel(end);
|
||||
mw.visitInsn(ARETURN);
|
||||
}
|
||||
else
|
||||
{
|
||||
// store datastack in a local
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitFieldInsn(GETFIELD,
|
||||
"factor/FactorInterpreter",
|
||||
"datastack",
|
||||
"Lfactor/FactorArrayStack;");
|
||||
int datastackLocal = allocate();
|
||||
mw.visitVarInsn(ASTORE,datastackLocal);
|
||||
|
||||
for(int i = 0; i < datastack.top; i++)
|
||||
{
|
||||
mw.visitVarInsn(ALOAD,datastackLocal);
|
||||
((FlowObject)datastack.stack[i])
|
||||
.pop(mw,Object.class);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||
"factor/FactorArrayStack",
|
||||
"push",
|
||||
"(Ljava/lang/Object;)V");
|
||||
}
|
||||
|
||||
datastack.top = 0;
|
||||
|
||||
// store callstack in a local
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitFieldInsn(GETFIELD,
|
||||
"factor/FactorInterpreter",
|
||||
"callstack",
|
||||
"Lfactor/FactorCallStack;");
|
||||
int callstackLocal = allocate();
|
||||
mw.visitVarInsn(ASTORE,callstackLocal);
|
||||
|
||||
for(int i = 0; i < callstack.top; i++)
|
||||
{
|
||||
mw.visitVarInsn(ALOAD,callstackLocal);
|
||||
((FlowObject)callstack.stack[i])
|
||||
.pop(mw,Object.class);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||
"factor/FactorCallStack",
|
||||
"push",
|
||||
"(Ljava/lang/Object;)V");
|
||||
}
|
||||
|
||||
callstack.top = 0;
|
||||
|
||||
mw.visitLabel(end);
|
||||
mw.visitInsn(RETURN);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compileMethod() method
|
||||
/**
|
||||
* Compiles a method.
|
||||
*/
|
||||
public void compileMethod(Cons definition, ClassWriter cw,
|
||||
String methodName, StackEffect effect, FactorWord word,
|
||||
RecursiveState recursiveCheck, boolean fieldInit)
|
||||
throws Exception
|
||||
{
|
||||
String signature = effect.getCorePrototype();
|
||||
|
||||
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
|
||||
methodName,signature,null,null);
|
||||
|
||||
Label start = recursiveCheck.get(word).label;
|
||||
|
||||
if(fieldInit)
|
||||
compileFieldInit(mw,start);
|
||||
|
||||
mw.visitLabel(start);
|
||||
|
||||
compile(definition,mw,recursiveCheck);
|
||||
|
||||
Label end = new Label();
|
||||
|
||||
compileReturn(mw,end,effect);
|
||||
|
||||
compileExceptionHandler(mw,start,end,word);
|
||||
|
||||
mw.visitMaxs(0,0);
|
||||
} //}}}
|
||||
|
||||
//{{{ compileExceptionHandler() method
|
||||
private void compileExceptionHandler(CodeVisitor mw,
|
||||
Label start, Label end, FactorWord word)
|
||||
{
|
||||
// otherwise no code can throw exception etc
|
||||
if(start.getOffset() != end.getOffset())
|
||||
{
|
||||
// Now compile exception handler.
|
||||
|
||||
Label target = new Label();
|
||||
mw.visitLabel(target);
|
||||
|
||||
mw.visitVarInsn(ASTORE,1);
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitFieldInsn(GETSTATIC,className,literal(word),
|
||||
"Ljava/lang/Object;");
|
||||
mw.visitTypeInsn(CHECKCAST,"factor/FactorWord");
|
||||
mw.visitVarInsn(ALOAD,1);
|
||||
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL,"factor/FactorInterpreter",
|
||||
"compiledException",
|
||||
"(Lfactor/FactorWord;Ljava/lang/Throwable;)V");
|
||||
|
||||
mw.visitVarInsn(ALOAD,1);
|
||||
mw.visitInsn(ATHROW);
|
||||
|
||||
mw.visitTryCatchBlock(start,end,target,"java/lang/Throwable");
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compile() method
|
||||
/**
|
||||
* Compiles a quotation.
|
||||
*/
|
||||
public void compile(Cons definition, CodeVisitor mw,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
while(definition != null)
|
||||
{
|
||||
Object obj = definition.car;
|
||||
if(obj instanceof FactorWord)
|
||||
{
|
||||
compileWord((FactorWord)obj,mw,recursiveCheck,
|
||||
definition.cdr == null);
|
||||
}
|
||||
else
|
||||
pushLiteral(obj,recursiveCheck);
|
||||
|
||||
definition = definition.next();
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compileWord() method
|
||||
private void compileWord(FactorWord w, CodeVisitor mw,
|
||||
RecursiveState recursiveCheck,
|
||||
boolean tail) throws Exception
|
||||
{
|
||||
if(tail && interp.verboseCompile)
|
||||
System.err.println("Tail: " + recursiveCheck.last());
|
||||
recursiveCheck.last().tail = tail;
|
||||
|
||||
RecursiveForm rec = recursiveCheck.get(w);
|
||||
|
||||
try
|
||||
{
|
||||
boolean recursiveCall;
|
||||
if(rec == null)
|
||||
{
|
||||
recursiveCall = false;
|
||||
recursiveCheck.add(w,
|
||||
new StackEffect(),
|
||||
className,loader,
|
||||
"core");
|
||||
recursiveCheck.last().tail
|
||||
= (w.def instanceof FactorPrimitiveDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
recursiveCall = true;
|
||||
rec.active = true;
|
||||
}
|
||||
|
||||
compileCallTo(w,mw,recursiveCheck,recursiveCall);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(rec == null)
|
||||
recursiveCheck.remove(w);
|
||||
else
|
||||
{
|
||||
rec.active = false;
|
||||
rec.tail = false;
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ compileCallTo() method
|
||||
private void compileCallTo(FactorWord w, CodeVisitor mw,
|
||||
RecursiveState recursiveCheck,
|
||||
boolean recursiveCall) throws Exception
|
||||
{
|
||||
if(w.def == null)
|
||||
throw new FactorUndefinedWordException(w);
|
||||
|
||||
FactorWordDefinition d = w.def;
|
||||
|
||||
if(!recursiveCall)
|
||||
{
|
||||
StackEffect effect = getStackEffectOrNull(d);
|
||||
if(w.inline)
|
||||
{
|
||||
d.compileImmediate(mw,this,recursiveCheck);
|
||||
return;
|
||||
}
|
||||
else if(d instanceof FactorCompoundDefinition
|
||||
&& mw != null)
|
||||
{
|
||||
w.compile(interp,recursiveCheck);
|
||||
if(d == w.def)
|
||||
{
|
||||
throw new FactorCompilerException(word + " depends on " + w + " which cannot be compiled");
|
||||
}
|
||||
d = w.def;
|
||||
}
|
||||
|
||||
w.compileRef = true;
|
||||
}
|
||||
|
||||
d.compileCallTo(mw,this,recursiveCheck);
|
||||
} //}}}
|
||||
|
||||
//{{{ push() method
|
||||
/**
|
||||
* Generates code for pushing the top of the JVM stack onto the
|
||||
* data stack. Also generates code for converting this value to
|
||||
* the given type.
|
||||
*/
|
||||
public void push(FactorArrayStack stack, CodeVisitor mw, Class type)
|
||||
throws Exception
|
||||
{
|
||||
int local = allocate();
|
||||
Result r = new Result(local,this,null,type);
|
||||
stack.push(r);
|
||||
r.push(mw,type);
|
||||
} //}}}
|
||||
|
||||
//{{{ pushLiteral() method
|
||||
public void pushLiteral(Object literal, RecursiveState recursiveCheck)
|
||||
{
|
||||
if(literal == null)
|
||||
datastack.push(new Null(this,recursiveCheck));
|
||||
else if(literal instanceof Cons)
|
||||
{
|
||||
datastack.push(new CompiledList((Cons)literal,this,
|
||||
recursiveCheck));
|
||||
}
|
||||
else if(literal instanceof String)
|
||||
{
|
||||
datastack.push(new ConstantPoolString((String)literal,
|
||||
this,recursiveCheck));
|
||||
}
|
||||
else
|
||||
{
|
||||
datastack.push(new Literal(literal,this,
|
||||
recursiveCheck));
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ pop() method
|
||||
/**
|
||||
* Generates code for popping the top of the data stack onto
|
||||
* the JVM stack. Also generates code for converting this value to
|
||||
* the given type.
|
||||
*/
|
||||
public void pop(FactorArrayStack stack, CodeVisitor mw, Class type)
|
||||
throws Exception
|
||||
{
|
||||
FlowObject obj = (FlowObject)datastack.pop();
|
||||
obj.pop(mw,type);
|
||||
} //}}}
|
||||
|
||||
//{{{ popLiteral() method
|
||||
/**
|
||||
* Pops a literal off the datastack or throws an exception.
|
||||
*/
|
||||
public Object popLiteral() throws FactorException
|
||||
{
|
||||
FlowObject obj = (FlowObject)datastack.pop();
|
||||
return obj.getLiteral();
|
||||
} //}}}
|
||||
|
||||
//{{{ allocate() method
|
||||
/**
|
||||
* Allocate a local variable.
|
||||
*/
|
||||
public int allocate()
|
||||
{
|
||||
// inefficient!
|
||||
int i = base;
|
||||
for(;;)
|
||||
{
|
||||
if(allocate(i,datastack) && allocate(i,callstack))
|
||||
return i;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ allocate() method
|
||||
/**
|
||||
* Return true if not in use, false if in use.
|
||||
*/
|
||||
private boolean allocate(int local, FactorArrayStack stack)
|
||||
{
|
||||
for(int i = 0; i < stack.top; i++)
|
||||
{
|
||||
FlowObject obj = (FlowObject)stack.stack[i];
|
||||
if(obj.usingLocal(local))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} //}}}
|
||||
|
||||
//{{{ literal() method
|
||||
public String literal(Object obj)
|
||||
{
|
||||
Integer i = (Integer)literals.get(obj);
|
||||
int literal;
|
||||
if(i == null)
|
||||
{
|
||||
literal = literalCount++;
|
||||
literals.put(obj,new Integer(literal));
|
||||
}
|
||||
else
|
||||
literal = i.intValue();
|
||||
|
||||
return "literal_" + literal;
|
||||
} //}}}
|
||||
|
||||
//{{{ auxiliary() method
|
||||
public String auxiliary(FactorWord word, Cons code, StackEffect effect,
|
||||
RecursiveState recursiveCheck) throws Exception
|
||||
{
|
||||
FactorArrayStack savedDatastack = (FactorArrayStack)
|
||||
datastack.clone();
|
||||
FactorCallStack savedCallstack = (FactorCallStack)
|
||||
callstack.clone();
|
||||
|
||||
String method = "aux_" + FactorJava.getSanitizedName(word.name)
|
||||
+ "_" + (auxCount++);
|
||||
|
||||
recursiveCheck.last().method = method;
|
||||
aux = new Cons(new AuxiliaryQuotation(
|
||||
method,savedDatastack,savedCallstack,
|
||||
code,effect,word,this,recursiveCheck),aux);
|
||||
|
||||
return method;
|
||||
} //}}}
|
||||
|
||||
//{{{ generateAuxiliary() method
|
||||
public void generateAuxiliary(ClassWriter cw) throws Exception
|
||||
{
|
||||
while(aux != null)
|
||||
{
|
||||
AuxiliaryQuotation q = (AuxiliaryQuotation)aux.car;
|
||||
// order of these two important, in case
|
||||
// compilation of q adds more quotations to aux list
|
||||
aux = aux.next();
|
||||
q.compile(this,cw);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ normalizeStacks() method
|
||||
public void normalizeStacks(CodeVisitor mw)
|
||||
throws Exception
|
||||
{
|
||||
int datastackTop = datastack.top;
|
||||
datastack.top = 0;
|
||||
int callstackTop = callstack.top;
|
||||
callstack.top = 0;
|
||||
|
||||
localsToStack(callstack,callstackTop,mw);
|
||||
localsToStack(datastack,datastackTop,mw);
|
||||
stackToLocals(datastack,datastackTop,mw);
|
||||
stackToLocals(callstack,callstackTop,mw);
|
||||
} //}}}
|
||||
|
||||
//{{{ localsToStack() method
|
||||
private void localsToStack(FactorArrayStack stack, int top,
|
||||
CodeVisitor mw)
|
||||
{
|
||||
for(int i = top - 1; i >= 0; i--)
|
||||
{
|
||||
FlowObject obj = (FlowObject)stack.stack[i];
|
||||
obj.pop(mw);
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ stackToLocals() method
|
||||
private void stackToLocals(FactorArrayStack stack, int top,
|
||||
CodeVisitor mw) throws Exception
|
||||
{
|
||||
for(int i = 0; i < top; i++)
|
||||
push(stack,mw,Object.class);
|
||||
} //}}}
|
||||
|
||||
//{{{ generateArgs() method
|
||||
/**
|
||||
* Generate instructions for copying arguments from the allocated
|
||||
* local variables to the JVM stack, doing type conversion in the
|
||||
* process.
|
||||
*/
|
||||
public void generateArgs(CodeVisitor mw, int inD, int inR, Class[] args)
|
||||
throws Exception
|
||||
{
|
||||
for(int i = 0; i < inD; i++)
|
||||
{
|
||||
FlowObject obj = (FlowObject)datastack.stack[
|
||||
datastack.top - inD + i];
|
||||
obj.pop(mw,args == null ? Object.class : args[i]);
|
||||
}
|
||||
|
||||
datastack.top -= inD;
|
||||
|
||||
for(int i = 0; i < inR; i++)
|
||||
{
|
||||
FlowObject obj = (FlowObject)callstack.stack[
|
||||
callstack.top - inR + i];
|
||||
obj.pop(mw,args == null ? Object.class : args[i]);
|
||||
}
|
||||
|
||||
callstack.top -= inR;
|
||||
} //}}}
|
||||
|
||||
//{{{ generateReturn() method
|
||||
public void generateReturn(CodeVisitor mw, int outD, int outR)
|
||||
throws Exception
|
||||
{
|
||||
if(outD == 0 && outR == 0)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if(outD == 1 && outR == 0)
|
||||
{
|
||||
push(datastack,mw,Object.class);
|
||||
}
|
||||
else
|
||||
{
|
||||
// transfer from data stack to JVM locals
|
||||
|
||||
// allocate the appropriate number of locals
|
||||
|
||||
if(outD != 0)
|
||||
{
|
||||
produce(datastack,outD);
|
||||
|
||||
// store the datastack instance somewhere
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitFieldInsn(GETFIELD,
|
||||
"factor/FactorInterpreter",
|
||||
"datastack",
|
||||
"Lfactor/FactorArrayStack;");
|
||||
int datastackLocal = allocate();
|
||||
mw.visitVarInsn(ASTORE,datastackLocal);
|
||||
|
||||
// put all elements from the real datastack
|
||||
// into locals
|
||||
for(int i = 0; i < outD; i++)
|
||||
{
|
||||
mw.visitVarInsn(ALOAD,datastackLocal);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||
"factor/FactorArrayStack",
|
||||
"pop",
|
||||
"()Ljava/lang/Object;");
|
||||
|
||||
Result destination = (Result)
|
||||
datastack.stack[
|
||||
datastack.top - i - 1];
|
||||
|
||||
destination.push(mw,Object.class);
|
||||
}
|
||||
}
|
||||
|
||||
if(outR != 0)
|
||||
{
|
||||
produce(callstack,outR);
|
||||
|
||||
mw.visitVarInsn(ALOAD,0);
|
||||
mw.visitFieldInsn(GETFIELD,
|
||||
"factor/FactorInterpreter",
|
||||
"callstack",
|
||||
"Lfactor/FactorCallStack;");
|
||||
int callstackLocal = allocate();
|
||||
mw.visitVarInsn(ASTORE,callstackLocal);
|
||||
|
||||
// put all elements from the real callstack
|
||||
// into locals
|
||||
for(int i = 0; i < outR; i++)
|
||||
{
|
||||
mw.visitVarInsn(ALOAD,callstackLocal);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL,
|
||||
"factor/FactorCallStack",
|
||||
"pop",
|
||||
"()Ljava/lang/Object;");
|
||||
|
||||
Result destination = (Result)
|
||||
callstack.stack[
|
||||
callstack.top - i - 1];
|
||||
|
||||
destination.push(mw,Object.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ generateFields() method
|
||||
public void generateFields(ClassWriter cw)
|
||||
throws Exception
|
||||
{
|
||||
for(int i = 0; i < literalCount; i++)
|
||||
{
|
||||
cw.visitField(ACC_PRIVATE | ACC_STATIC,"literal_" + i,
|
||||
"Ljava/lang/Object;",null,null);
|
||||
}
|
||||
|
||||
CodeVisitor mw = cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
|
||||
"setFields","(Lfactor/FactorInterpreter;)V",null,null);
|
||||
|
||||
Iterator entries = literals.entrySet().iterator();
|
||||
while(entries.hasNext())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry)entries.next();
|
||||
Object literal = entry.getKey();
|
||||
int index = ((Integer)entry.getValue()).intValue();
|
||||
|
||||
generateParse(mw,literal,0);
|
||||
mw.visitFieldInsn(PUTSTATIC,
|
||||
className,
|
||||
"literal_" + index,
|
||||
"Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
mw.visitInsn(RETURN);
|
||||
|
||||
mw.visitMaxs(0,0);
|
||||
} //}}}
|
||||
|
||||
//{{{ generateParse() method
|
||||
public void generateParse(CodeVisitor mw, Object obj, int interpLocal)
|
||||
{
|
||||
mw.visitLdcInsn(FactorReader.getVocabularyDeclaration(obj)
|
||||
+ FactorReader.unparseObject(obj));
|
||||
mw.visitVarInsn(ALOAD,interpLocal);
|
||||
mw.visitMethodInsn(INVOKESTATIC,
|
||||
"factor/FactorReader",
|
||||
"parseObject",
|
||||
"(Ljava/lang/String;Lfactor/FactorInterpreter;)"
|
||||
+ "Ljava/lang/Object;");
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffectOrNull() method
|
||||
public StackEffect getStackEffectOrNull(FactorWordDefinition def)
|
||||
{
|
||||
try
|
||||
{
|
||||
return def.getStackEffect(interp,
|
||||
new RecursiveState());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//System.err.println("WARNING: " + e);
|
||||
//System.err.println(def);
|
||||
return null;
|
||||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ getStackEffectOrNull() method
|
||||
public StackEffect getStackEffectOrNull(FlowObject obj,
|
||||
RecursiveState recursiveCheck,
|
||||
boolean decompose)
|
||||
{
|
||||
try
|
||||
{
|
||||
obj.getStackEffect(recursiveCheck);
|
||||
StackEffect effect = getStackEffect();
|
||||
if(decompose)
|
||||
{
|
||||
effect = StackEffect.decompose(
|
||||
recursiveCheck.last().effect,
|
||||
effect);
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//System.err.println("WARNING: " + e);
|
||||
//System.err.println(obj);
|
||||
return null;
|
||||
}
|
||||
} //}}}
|
||||
}
|
|
@ -39,15 +39,12 @@ import sidekick.*;
|
|||
public class FactorAsset extends Asset
|
||||
{
|
||||
private FactorWord word;
|
||||
private FactorWordDefinition def;
|
||||
|
||||
public FactorAsset(FactorWord word, FactorWordDefinition def,
|
||||
Position start)
|
||||
public FactorAsset(FactorWord word, Position start)
|
||||
{
|
||||
super(word.name);
|
||||
this.start = start;
|
||||
this.word = word;
|
||||
this.def = def;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public Icon getIcon()
|
||||
|
@ -62,6 +59,6 @@ public class FactorAsset extends Asset
|
|||
|
||||
public String getLongString()
|
||||
{
|
||||
return FactorWordRenderer.getWordHTMLString(word,def,false);
|
||||
return FactorWordRenderer.getWordHTMLString(word,false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,11 +43,11 @@ sidekick.parser.factor.label=Factor
|
|||
mode.factor.sidekick.parser=factor
|
||||
|
||||
factor.completion.in=<font color="#a0a0a0">IN: {0}</font>\
|
||||
factor.completion.plain=: <b>{0}</b>
|
||||
factor.completion.colon=: <b>{0}</b>
|
||||
factor.completion.defer=DEFER: <b>{0}</b>
|
||||
factor.completion.parsing=PARSING: <b>{0}</b>
|
||||
factor.completion.stack=: <b>{0}</b> {1}
|
||||
factor.completion.symbol=SYMBOL: <b>{0}</b>
|
||||
factor.completion.stack={0} ({1})
|
||||
|
||||
# Dialog boxes
|
||||
factor.status.inserted-use=Inserted {0}
|
||||
|
|
|
@ -40,7 +40,6 @@ import sidekick.*;
|
|||
|
||||
public class FactorSideKickParser extends SideKickParser
|
||||
{
|
||||
private WordPreview wordPreview;
|
||||
private Map previewMap;
|
||||
|
||||
/**
|
||||
|
@ -55,22 +54,6 @@ public class FactorSideKickParser extends SideKickParser
|
|||
{
|
||||
super("factor");
|
||||
previewMap = new HashMap();
|
||||
worddefs = new HashMap();
|
||||
} //}}}
|
||||
|
||||
//{{{ getWordDefinition() method
|
||||
/**
|
||||
* Check for a word definition from a parsed source file. If one is
|
||||
* found, return it, otherwise return interpreter's definition.
|
||||
*/
|
||||
public FactorWordDefinition getWordDefinition(FactorWord word)
|
||||
{
|
||||
FactorWordDefinition def = (FactorWordDefinition)
|
||||
worddefs.get(word);
|
||||
if(def != null)
|
||||
return def;
|
||||
else
|
||||
return word.def;
|
||||
} //}}}
|
||||
|
||||
//{{{ activate() method
|
||||
|
@ -180,7 +163,6 @@ public class FactorSideKickParser extends SideKickParser
|
|||
parsed.car;
|
||||
|
||||
FactorWord word = def.word;
|
||||
worddefs.put(word,def);
|
||||
|
||||
/* word lines are indexed from 1 */
|
||||
int startLine = Math.min(
|
||||
|
@ -197,8 +179,7 @@ public class FactorSideKickParser extends SideKickParser
|
|||
if(last != null)
|
||||
last.end = buffer.createPosition(start - 1);
|
||||
|
||||
last = new FactorAsset(word,def,
|
||||
buffer.createPosition(start));
|
||||
last = new FactorAsset(word,buffer.createPosition(start));
|
||||
d.root.add(new DefaultMutableTreeNode(last));
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,11 @@ import org.gjt.sp.jedit.*;
|
|||
public class FactorWordRenderer extends DefaultListCellRenderer
|
||||
{
|
||||
//{{{ getWordHTMLString() method
|
||||
public static String getWordHTMLString(FactorWord word,
|
||||
FactorWordDefinition def, boolean showIn)
|
||||
public static String getWordHTMLString(FactorWord word, boolean showIn)
|
||||
{
|
||||
String prop = "factor.completion.plain";
|
||||
String stackEffect = null;
|
||||
String prop = "factor.completion.colon";
|
||||
|
||||
if(def == null)
|
||||
/* if(def == null)
|
||||
{
|
||||
if(word.parsing != null)
|
||||
prop = "factor.completion.parsing";
|
||||
|
@ -63,11 +61,10 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
|||
d.car;
|
||||
if(comment.isStackComment())
|
||||
{
|
||||
prop = "factor.completion.stack";
|
||||
stackEffect = comment.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
String in;
|
||||
if(showIn)
|
||||
|
@ -80,13 +77,15 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
|||
else
|
||||
in = "";
|
||||
|
||||
return "<html>" + in + jEdit.getProperty(prop,
|
||||
new Object[] {
|
||||
MiscUtilities.charsToEntities(word.name),
|
||||
stackEffect == null
|
||||
? null :
|
||||
MiscUtilities.charsToEntities(stackEffect)
|
||||
});
|
||||
String html = "<html>" + in + jEdit.getProperty(prop,
|
||||
new Object[] { MiscUtilities.charsToEntities(word.name) });
|
||||
if(word.stackEffect != null)
|
||||
{
|
||||
html += jEdit.getProperty("factor.completion.stack",
|
||||
new String[] { html, word.stackEffect });
|
||||
}
|
||||
|
||||
return html;
|
||||
} //}}}
|
||||
|
||||
private FactorSideKickParser parser;
|
||||
|
@ -114,9 +113,7 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
|||
return this;
|
||||
|
||||
FactorWord word = (FactorWord)value;
|
||||
setText(getWordHTMLString(word,
|
||||
parser.getWordDefinition(word),
|
||||
showIn));
|
||||
setText(getWordHTMLString(word,showIn));
|
||||
|
||||
return this;
|
||||
} //}}}
|
||||
|
|
|
@ -125,7 +125,7 @@ public class WordPreview implements ActionListener, CaretListener
|
|||
{
|
||||
view.getStatus().setMessageAndClear(
|
||||
FactorWordRenderer.getWordHTMLString(
|
||||
w,fdata.parser.getWordDefinition(w),true));
|
||||
w,true));
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
|
|
|
@ -49,10 +49,13 @@ public class Ine extends FactorParsingDefinition
|
|||
throws Exception
|
||||
{
|
||||
FactorReader.ParseState state = reader.popState(start,word);
|
||||
FactorWord w = (FactorWord)state.arg;
|
||||
FactorWord w = state.defining;
|
||||
/* Only ever null with restartable scanner;
|
||||
error already logged, so give up */
|
||||
if(w == null)
|
||||
return;
|
||||
|
||||
reader.append(new FactorCompoundDefinition(w,state.first));
|
||||
w.def = new FactorCompoundDefinition(w,state.first);
|
||||
reader.append(w.def);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,6 @@ public class LineComment extends FactorParsingDefinition
|
|||
{
|
||||
String comment = reader.getScanner().readUntilEOL();
|
||||
if(doc)
|
||||
reader.append(new FactorDocComment(comment,false));
|
||||
reader.addDocComment(comment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,6 @@ public class StackComment extends FactorParsingDefinition
|
|||
throws Exception
|
||||
{
|
||||
String comment = reader.getScanner().readUntil( '(',')',false);
|
||||
reader.append(new FactorDocComment(comment,true));
|
||||
reader.setStackComment(comment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ public class Symbol extends FactorParsingDefinition
|
|||
throws Exception
|
||||
{
|
||||
FactorWord w = reader.nextWord(true);
|
||||
reader.append(new FactorSymbolDefinition(w,w));
|
||||
w.def = new FactorSymbolDefinition(w,w);
|
||||
reader.append(w.def);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue