communicates stack effect from socket
parent
84d1667fdf
commit
cf75abc247
|
@ -135,7 +135,11 @@ public class ExternalFactor extends DefaultVocabularyLookup
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
result = (Cons)result.car;
|
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)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,6 @@ import java.util.*;
|
||||||
public class FactorCompoundDefinition extends FactorWordDefinition
|
public class FactorCompoundDefinition extends FactorWordDefinition
|
||||||
{
|
{
|
||||||
public Cons definition;
|
public Cons definition;
|
||||||
private Cons endOfDocs;
|
|
||||||
|
|
||||||
//{{{ FactorCompoundDefinition constructor
|
//{{{ FactorCompoundDefinition constructor
|
||||||
/**
|
/**
|
||||||
|
@ -48,15 +47,6 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
||||||
{
|
{
|
||||||
super(word);
|
super(word);
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
if(definition == null)
|
|
||||||
endOfDocs = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
endOfDocs = definition;
|
|
||||||
while(endOfDocs != null
|
|
||||||
&& endOfDocs.car instanceof FactorDocComment)
|
|
||||||
endOfDocs = endOfDocs.next();
|
|
||||||
}
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ toList() method
|
//{{{ 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.line = line;
|
||||||
w.col = col;
|
w.col = col;
|
||||||
w.file = scanner.getFileName();
|
w.file = scanner.getFileName();
|
||||||
|
w.stackEffect = null;
|
||||||
|
w.documentation = null;
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
@ -313,8 +315,7 @@ public class FactorReader
|
||||||
return true;
|
return true;
|
||||||
else if(next instanceof String)
|
else if(next instanceof String)
|
||||||
{
|
{
|
||||||
FactorWord word = intern((String)next,
|
FactorWord word = intern((String)next,false);
|
||||||
!getCurrentState().warnUndefined);
|
|
||||||
if(word == null)
|
if(word == null)
|
||||||
{
|
{
|
||||||
/* We're ignoring errors */
|
/* We're ignoring errors */
|
||||||
|
@ -341,24 +342,22 @@ public class FactorReader
|
||||||
* An exclusive state can only happen at the top level.
|
* An exclusive state can only happen at the top level.
|
||||||
* For example, : ... ; definitions cannot be nested so they
|
* For example, : ... ; definitions cannot be nested so they
|
||||||
* are exclusive.
|
* 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
|
throws FactorParseException
|
||||||
{
|
{
|
||||||
if(getCurrentState().start != toplevel)
|
if(getCurrentState().start != toplevel)
|
||||||
scanner.error(start + " cannot be nested");
|
scanner.error(start + " cannot be nested");
|
||||||
pushState(start,args);
|
pushState(start,defining);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ pushState() method
|
//{{{ pushState() method
|
||||||
/**
|
/**
|
||||||
* Push a parser state, for example reading of a list.
|
* 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
|
//{{{ popState() method
|
||||||
|
@ -391,6 +390,18 @@ public class FactorReader
|
||||||
getCurrentState().append(obj);
|
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
|
//{{{ bar() method
|
||||||
/**
|
/**
|
||||||
* Sets the current parser state's cdr to the given object.
|
* Sets the current parser state's cdr to the given object.
|
||||||
|
@ -410,39 +421,24 @@ public class FactorReader
|
||||||
public class ParseState
|
public class ParseState
|
||||||
{
|
{
|
||||||
public FactorWord start;
|
public FactorWord start;
|
||||||
public Object arg;
|
public FactorWord defining;
|
||||||
public Cons first;
|
public Cons first;
|
||||||
public Cons last;
|
public Cons last;
|
||||||
public boolean warnUndefined;
|
private boolean bar;
|
||||||
private boolean comma;
|
|
||||||
private boolean docComment;
|
private boolean docComment;
|
||||||
|
|
||||||
ParseState(FactorWord start, Object arg)
|
ParseState(FactorWord start, FactorWord defining)
|
||||||
{
|
{
|
||||||
docComment = start.docComment;
|
docComment = start.docComment;
|
||||||
warnUndefined = true;
|
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.arg = arg;
|
this.defining = defining;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(Object obj) throws FactorParseException
|
void append(Object obj) throws FactorParseException
|
||||||
{
|
{
|
||||||
boolean docComment = (this.docComment || alwaysDocComments);
|
docComment = false;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(comma)
|
if(bar)
|
||||||
{
|
{
|
||||||
if(last.cdr != null)
|
if(last.cdr != null)
|
||||||
scanner.error("Only one token allowed after |");
|
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
|
void bar() throws FactorParseException
|
||||||
{
|
{
|
||||||
if(last.cdr != null)
|
if(last.cdr != null)
|
||||||
|
@ -468,7 +485,7 @@ public class FactorReader
|
||||||
scanner.error("Only one token allowed after |");
|
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
|
public class FactorWord implements FactorExternalizable
|
||||||
{
|
{
|
||||||
private static int gensymCount = 0;
|
|
||||||
|
|
||||||
public String vocabulary;
|
public String vocabulary;
|
||||||
public String name;
|
public String name;
|
||||||
|
public String stackEffect;
|
||||||
/**
|
public String documentation;
|
||||||
* Interpreted/compiled word definition.
|
|
||||||
*/
|
|
||||||
public FactorWordDefinition def;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsing word definition.
|
* Parsing word definition.
|
||||||
*/
|
*/
|
||||||
public FactorParsingDefinition parsing;
|
public FactorParsingDefinition parsing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub for interpreter definitin.
|
||||||
|
*/
|
||||||
|
public FactorWordDefinition def;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the parser keep doc comments?
|
* Should the parser keep doc comments?
|
||||||
*/
|
*/
|
||||||
|
@ -64,37 +64,12 @@ public class FactorWord implements FactorExternalizable
|
||||||
public int col;
|
public int col;
|
||||||
|
|
||||||
//{{{ FactorWord constructor
|
//{{{ 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)
|
public FactorWord(String vocabulary, String name)
|
||||||
{
|
{
|
||||||
this.vocabulary = vocabulary;
|
this.vocabulary = vocabulary;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ define() method
|
|
||||||
public void define(FactorWordDefinition def)
|
|
||||||
{
|
|
||||||
this.def = def;
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ toString() method
|
//{{{ toString() method
|
||||||
public String toString()
|
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
|
public class FactorAsset extends Asset
|
||||||
{
|
{
|
||||||
private FactorWord word;
|
private FactorWord word;
|
||||||
private FactorWordDefinition def;
|
|
||||||
|
|
||||||
public FactorAsset(FactorWord word, FactorWordDefinition def,
|
public FactorAsset(FactorWord word, Position start)
|
||||||
Position start)
|
|
||||||
{
|
{
|
||||||
super(word.name);
|
super(word.name);
|
||||||
this.start = start;
|
|
||||||
this.word = word;
|
this.word = word;
|
||||||
this.def = def;
|
this.start = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Icon getIcon()
|
public Icon getIcon()
|
||||||
|
@ -62,6 +59,6 @@ public class FactorAsset extends Asset
|
||||||
|
|
||||||
public String getLongString()
|
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
|
mode.factor.sidekick.parser=factor
|
||||||
|
|
||||||
factor.completion.in=<font color="#a0a0a0">IN: {0}</font>\
|
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.defer=DEFER: <b>{0}</b>
|
||||||
factor.completion.parsing=PARSING: <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.symbol=SYMBOL: <b>{0}</b>
|
||||||
|
factor.completion.stack={0} ({1})
|
||||||
|
|
||||||
# Dialog boxes
|
# Dialog boxes
|
||||||
factor.status.inserted-use=Inserted {0}
|
factor.status.inserted-use=Inserted {0}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import sidekick.*;
|
||||||
|
|
||||||
public class FactorSideKickParser extends SideKickParser
|
public class FactorSideKickParser extends SideKickParser
|
||||||
{
|
{
|
||||||
private WordPreview wordPreview;
|
|
||||||
private Map previewMap;
|
private Map previewMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,22 +54,6 @@ public class FactorSideKickParser extends SideKickParser
|
||||||
{
|
{
|
||||||
super("factor");
|
super("factor");
|
||||||
previewMap = new HashMap();
|
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
|
//{{{ activate() method
|
||||||
|
@ -180,7 +163,6 @@ public class FactorSideKickParser extends SideKickParser
|
||||||
parsed.car;
|
parsed.car;
|
||||||
|
|
||||||
FactorWord word = def.word;
|
FactorWord word = def.word;
|
||||||
worddefs.put(word,def);
|
|
||||||
|
|
||||||
/* word lines are indexed from 1 */
|
/* word lines are indexed from 1 */
|
||||||
int startLine = Math.min(
|
int startLine = Math.min(
|
||||||
|
@ -197,8 +179,7 @@ public class FactorSideKickParser extends SideKickParser
|
||||||
if(last != null)
|
if(last != null)
|
||||||
last.end = buffer.createPosition(start - 1);
|
last.end = buffer.createPosition(start - 1);
|
||||||
|
|
||||||
last = new FactorAsset(word,def,
|
last = new FactorAsset(word,buffer.createPosition(start));
|
||||||
buffer.createPosition(start));
|
|
||||||
d.root.add(new DefaultMutableTreeNode(last));
|
d.root.add(new DefaultMutableTreeNode(last));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,13 +37,11 @@ import org.gjt.sp.jedit.*;
|
||||||
public class FactorWordRenderer extends DefaultListCellRenderer
|
public class FactorWordRenderer extends DefaultListCellRenderer
|
||||||
{
|
{
|
||||||
//{{{ getWordHTMLString() method
|
//{{{ getWordHTMLString() method
|
||||||
public static String getWordHTMLString(FactorWord word,
|
public static String getWordHTMLString(FactorWord word, boolean showIn)
|
||||||
FactorWordDefinition def, boolean showIn)
|
|
||||||
{
|
{
|
||||||
String prop = "factor.completion.plain";
|
String prop = "factor.completion.colon";
|
||||||
String stackEffect = null;
|
|
||||||
|
|
||||||
if(def == null)
|
/* if(def == null)
|
||||||
{
|
{
|
||||||
if(word.parsing != null)
|
if(word.parsing != null)
|
||||||
prop = "factor.completion.parsing";
|
prop = "factor.completion.parsing";
|
||||||
|
@ -63,11 +61,10 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
||||||
d.car;
|
d.car;
|
||||||
if(comment.isStackComment())
|
if(comment.isStackComment())
|
||||||
{
|
{
|
||||||
prop = "factor.completion.stack";
|
|
||||||
stackEffect = comment.toString();
|
stackEffect = comment.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
String in;
|
String in;
|
||||||
if(showIn)
|
if(showIn)
|
||||||
|
@ -80,13 +77,15 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
||||||
else
|
else
|
||||||
in = "";
|
in = "";
|
||||||
|
|
||||||
return "<html>" + in + jEdit.getProperty(prop,
|
String html = "<html>" + in + jEdit.getProperty(prop,
|
||||||
new Object[] {
|
new Object[] { MiscUtilities.charsToEntities(word.name) });
|
||||||
MiscUtilities.charsToEntities(word.name),
|
if(word.stackEffect != null)
|
||||||
stackEffect == null
|
{
|
||||||
? null :
|
html += jEdit.getProperty("factor.completion.stack",
|
||||||
MiscUtilities.charsToEntities(stackEffect)
|
new String[] { html, word.stackEffect });
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
private FactorSideKickParser parser;
|
private FactorSideKickParser parser;
|
||||||
|
@ -114,9 +113,7 @@ public class FactorWordRenderer extends DefaultListCellRenderer
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
FactorWord word = (FactorWord)value;
|
FactorWord word = (FactorWord)value;
|
||||||
setText(getWordHTMLString(word,
|
setText(getWordHTMLString(word,showIn));
|
||||||
parser.getWordDefinition(word),
|
|
||||||
showIn));
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
|
@ -125,7 +125,7 @@ public class WordPreview implements ActionListener, CaretListener
|
||||||
{
|
{
|
||||||
view.getStatus().setMessageAndClear(
|
view.getStatus().setMessageAndClear(
|
||||||
FactorWordRenderer.getWordHTMLString(
|
FactorWordRenderer.getWordHTMLString(
|
||||||
w,fdata.parser.getWordDefinition(w),true));
|
w,true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(IOException e)
|
catch(IOException e)
|
||||||
|
|
|
@ -49,10 +49,13 @@ public class Ine extends FactorParsingDefinition
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
FactorReader.ParseState state = reader.popState(start,word);
|
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)
|
if(w == null)
|
||||||
return;
|
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();
|
String comment = reader.getScanner().readUntilEOL();
|
||||||
if(doc)
|
if(doc)
|
||||||
reader.append(new FactorDocComment(comment,false));
|
reader.addDocComment(comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,6 @@ public class StackComment extends FactorParsingDefinition
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
String comment = reader.getScanner().readUntil( '(',')',false);
|
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
|
throws Exception
|
||||||
{
|
{
|
||||||
FactorWord w = reader.nextWord(true);
|
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