[e-cvs] cvs commit: e/src/jsrc/org/quasiliteral/term Converter.java ToFunctor.java ToLiteral.java ToTerm.java ToTermList.java
markm@eros.cs.jhu.edu
markm@eros.cs.jhu.edu
Wed, 21 Nov 2001 06:02:48 -0500
markm 01/11/21 06:02:48
Added: src/jsrc/org/quasiliteral/term Converter.java ToFunctor.java
ToLiteral.java ToTerm.java ToTermList.java
Removed: src/jsrc/org/quasiliteral/quasiterm ToFunctor.java
ToLiteral.java ToTerm.java
Log:
Oops, forgot these
Revision Changes Path
1.1 e/src/jsrc/org/quasiliteral/term/Converter.java
Index: Converter.java
===================================================================
package org.quasiliteral.term;
import org.erights.e.elib.serial.PassByConstruction;
import org.erights.e.elib.serial.Persistent;
import org.erights.e.elib.slot.ValueGuard;
import org.erights.e.elib.tables.Selfless;
import org.erights.e.elib.tables.Twine;
import org.erights.e.elib.base.ClassDesc;
import org.erights.e.elib.prim.E;
/**
* Coerces input to some type needed in a Term/Functor tree.
* <p>
* A Converter is a ValueGuard suitable for parameterizing a
* {@link org.quasiliteral.quasiterm.BaseHole}. Even though BaseHole is in
* the quasiterm package, the Converters are in the term package since they
* don't depend on anything in the quasiterm package, and the term package
* depends on them.
*
* @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
*/
public abstract class Converter
implements ValueGuard, Selfless, PassByConstruction, Persistent {
/**
* Returns the literal type code according to the type of 'value'.
* <p>
* 'value' is assumed to already be in resolved form.
* <pre>
* If value is return is
* null -1
* a Character TermParser.LiteralChar
* a BigInteger TermParser.LiteralInteger
* or Byte,
* or Short,
* or Integer,
* or Long
* a Double TermParser.LiteralFloat64
* or Float
* a Twine TermParser.LiteralString
* or String
* anything else -2
* </pre>
* Note that the ints representing literal types are >= 0.
*/
static /*package*/ int literalType(Object value) {
if (null == value) {
return -1;
} else if (value instanceof Character) {
return TermParser.LiteralChar;
} else if (value instanceof Number) {
if (ClassDesc.isIntegral(value.getClass())) {
return TermParser.LiteralInteger;
} else if (ClassDesc.isFloating(value.getClass())) {
return TermParser.LiteralFloat64;
} else {
throw new RuntimeException
("Unrecognized number class: " + value.getClass());
}
} else if (value instanceof String || value instanceof Twine) {
return TermParser.LiteralString;
} else {
return -2;
}
}
/**
* Tests if x <=> y.
* <p>
* Assumes they've already been converted
*/
static public boolean equiv(Object x, Object y) {
return 0.0 == E.asFloat64(E.call(x, "compareTo", y));
}
/**
* Given that litHole has already been generated by calling either
* dollarHole/1 or atHole/1 on builder, this will do the further calls
* to build from that the kind of hole that would be parameterized by
* this converter.
*/
public abstract Object qbuild(TermBuilder builder, Object litHole);
}
1.1 e/src/jsrc/org/quasiliteral/term/ToFunctor.java
Index: ToFunctor.java
===================================================================
package org.quasiliteral.term;
import org.erights.e.elib.prim.StaticMaker;
import org.erights.e.elib.prim.Thrower;
import org.erights.e.elib.tables.Twine;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.util.OneArgFunc;
import org.erights.e.elib.ref.Ref;
import org.quasiliteral.astro.AstroToken;
import antlr.Token;
/**
* Converts to a Functor
*
* @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
*/
public class ToFunctor extends Converter {
/**
*
*/
static public StaticMaker ToFunctorMaker =
StaticMaker.make(ToFunctor.class);
/**
*
*/
static public ToFunctor THE_ONE = new ToFunctor();
/**
*
*/
private ToFunctor() {}
/**
* 'ToFunctorMaker THE_ONE()'
*/
public Object[] getCanonicalState() {
Object[] result = { ToFunctorMaker, "THE_ONE" };
return result;
}
/**
* Calls builder's functorHole(litHole)
*/
public Object qbuild(TermBuilder builder, Object litHole) {
return builder.functorHole(litHole);
}
/**
*
*/
public String getName() {
return "ToFunctor";
}
/**
* Coerces the specimen to a Functor.
* <p><pre>
* literal data => a literal Functor(..., data)
* Functor => same
* Token => it's asFunctor()
* </pre>
*/
public Object coerce(Object specimen, OneArgFunc optEjector) {
//XXX The following implementation is annoyingly reduntand with
//ToLiteral's coerce/2.
specimen = Ref.resolution(specimen);
ConstList typeNames = TermParser.getTokenNames();
int ttype = literalType(specimen);
if (ttype >= 0) {
//It's literal data
String tag = (String)typeNames.get(ttype);
return new Functor(tag,
Twine.fromString(""),
specimen);
} else if (-1 == ttype) {
Thrower.toEject(optEjector, "Functor must not be null");
return null; //make compiler happy
} else if (specimen instanceof Functor) {
return specimen;
} else if (specimen instanceof Token) {
Token token = (Token)specimen;
return coerce(Functor.fromToken(token, "", typeNames),
optEjector);
} else {
Thrower.toEject(optEjector,
"Unrecognized specimen type: " +
specimen.getClass());
return null; //make compiler happy
}
}
}
1.1 e/src/jsrc/org/quasiliteral/term/ToLiteral.java
Index: ToLiteral.java
===================================================================
package org.quasiliteral.term;
import org.erights.e.elib.prim.E;
import org.erights.e.elib.prim.StaticMaker;
import org.erights.e.elib.prim.Thrower;
import org.erights.e.elib.tables.Twine;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.base.ClassDesc;
import org.erights.e.elib.util.OneArgFunc;
import org.erights.e.elib.ref.Ref;
import org.quasiliteral.astro.AstroToken;
import java.math.BigInteger;
import antlr.Token;
/**
* Converts to null or to a Functor representing untagged literal data.
*
* @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
*/
public class ToLiteral extends Converter {
/**
*
*/
static public StaticMaker ToLiteralMaker =
StaticMaker.make(ToLiteral.class);
/**
*
*/
static public ToLiteral THE_ONE = new ToLiteral();
/**
*
*/
private ToLiteral() {}
/**
* 'ToLiteralMaker THE_ONE()'
*/
public Object[] getCanonicalState() {
Object[] result = { ToLiteralMaker, "THE_ONE" };
return result;
}
/**
* Just returns litHole itself
*/
public Object qbuild(TermBuilder builder, Object litHole) {
return litHole;
}
/**
* Returns "ToLiteral".
* <p>
* Unclear what's sensible here.
*/
public String getName() {
return "ToLiteral";
}
/**
* Coerces the specimen to null or a Functor representing untagged
* literal data.
* <p><pre>
* null => null
* literal data => a literal Functor(..., data)
* literal Functor => same
* literal Token => it's asFunctor()
* </pre>
*/
public Object coerce(Object specimen, OneArgFunc optEjector) {
specimen = Ref.resolution(specimen);
ConstList typeNames = TermParser.getTokenNames();
int ttype = literalType(specimen);
if (ttype >= 0) {
//It's literal data
String tag = (String)typeNames.get(ttype);
return new Functor(tag,
Twine.fromString(""),
specimen);
} else if (-1 == ttype) {
return null;
} else if (specimen instanceof Functor) {
Functor functor = (Functor)specimen;
if (functor.isLiteral()) {
return functor;
} else {
Thrower.toEject(optEjector,
"Functor must be literal: " + functor);
return null; //make compiler happy
}
} else if (specimen instanceof Token) {
Token token = (Token)specimen;
return coerce(Functor.fromToken(token, "", typeNames),
optEjector);
} else {
Thrower.toEject(optEjector,
"Unrecognized specimen type: " +
specimen.getClass());
return null; //make compiler happy
}
}
}
1.1 e/src/jsrc/org/quasiliteral/term/ToTerm.java
Index: ToTerm.java
===================================================================
package org.quasiliteral.term;
import org.erights.e.elib.prim.StaticMaker;
import org.erights.e.elib.prim.E;
import org.erights.e.elib.prim.Thrower;
import org.erights.e.elib.util.OneArgFunc;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.tables.Twine;
import org.quasiliteral.astro.AstroToken;
import antlr.collections.AST;
/**
* Converts either to any Term (if optTag is null), or to a Term with a
* particular tag.
*
* @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
*/
public class ToTerm extends Converter {
/**
*
*/
static public StaticMaker ToTermMaker =
StaticMaker.make(ToTerm.class);
/**
*
*/
static private ToTerm TO_ANY_TERM = new ToTerm(null);
/**
*
*/
private final String myOptTag;
/**
*
*/
private ToTerm(String optTag) {
myOptTag = optTag;
}
/**
*
*/
static public ToTerm make(String optTag) {
if (null == optTag) {
return TO_ANY_TERM;
} else {
return new ToTerm(optTag);
}
}
/**
* 'ToTermMaker make(myOptTag)'
*/
public Object[] getCanonicalState() {
Object[] result = { ToTermMaker, "make", myOptTag };
return result;
}
/**
* null, or the tag being filtered on.
*/
public String getOptTag() {
return myOptTag;
}
/**
* Call's builder's termHole(optTag, functorHole(litHole))
*/
public Object qbuild(TermBuilder builder, Object litHole) {
AstroToken optToken = null;
if (null != myOptTag) {
optToken = new AstroToken(TermParser.ID,
Twine.fromString(""),
myOptTag);
}
Object functorHole = builder.functorHole(litHole);
return builder.termHole(optToken, functorHole);
}
/**
* Returns "ToTerm" or "ToTerm(tag)"
*/
public String getName() {
if (null == myOptTag) {
return "ToTerm";
} else {
return "ToTerm(" + E.toQuote(myOptTag) + ")";
}
}
/**
*
*/
public Object coerce(Object specimen, OneArgFunc optEjector) {
if (specimen instanceof Term) {
Term term = (Term)specimen;
String tag = term.getFunctor().getTag();
if (null == myOptTag) {
//any term will do
return term;
} else if (tag == myOptTag) {
//tags match
return term;
} else {
Thrower.toEject(optEjector,
"Mismatch: " + myOptTag + " vs " + tag);
return null; //make compiler happy
}
} else if (specimen instanceof AST) {
//convert AST to Term, and recur
AST ast = (AST)specimen;
return coerce(Term.fromAST(ast, "", TermParser.getTokenNames()),
optEjector);
} else if (specimen instanceof Functor) {
//make functor into functor(), and recur
Functor functor = (Functor)specimen;
return coerce(new Term(functor, ConstList.EmptyList),
optEjector);
} else {
//coerce to a functor, and recur
return coerce(ToFunctor.THE_ONE.coerce(specimen, optEjector),
optEjector);
}
}
}
1.1 e/src/jsrc/org/quasiliteral/term/ToTermList.java
Index: ToTermList.java
===================================================================
package org.quasiliteral.term;
import org.erights.e.elib.prim.StaticMaker;
import org.erights.e.elib.prim.E;
import org.erights.e.elib.prim.Thrower;
import org.erights.e.elib.util.OneArgFunc;
import org.erights.e.elib.tables.EList;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.tables.FlexList;
import org.erights.e.elib.tables.Twine;
import org.quasiliteral.astro.AstroToken;
/**
* Converts to an appropriately sized list of terms with possibly matching
* tags.
*
* @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
*/
public class ToTermList extends Converter {
/**
*
*/
static public StaticMaker ToTermListMaker =
StaticMaker.make(ToTermList.class);
/**
* '?'
*/
static public final Character ZERO_OR_ONE = new Character('?');
/**
* '+'
*/
static public final Character ONE_OR_MORE = new Character('+');
/**
* '*'
*/
static public final Character ZERO_OR_MORE = new Character('*');
static public Character box(char quant) {
if ('?' == quant) {
return ZERO_OR_ONE;
} else if ('+' == quant) {
return ONE_OR_MORE;
} else if ('*' == quant) {
return ZERO_OR_MORE;
} else {
throw new RuntimeException
("Repetition character must be '?', '+', or '*': " + quant);
}
}
/**
*
*/
private final String myOptTag;
/**
* Either '?', '+', or '*'
*/
private final Character myQuant;
/**
*
*/
public ToTermList(String optTag, Character quant) {
myOptTag = optTag;
myQuant = quant;
}
/**
* 'ToTermListMaker new(myOptTag, myQuant)'
*/
public Object[] getCanonicalState() {
Object[] result = {
ToTermListMaker, "new", myOptTag };
return result;
}
/**
* null, or the tag being filtered on.
*/
public String getOptTag() {
return myOptTag;
}
/**
*
*/
public Object qbuild(TermBuilder builder, Object litHole) {
Object optTermHole = null;
if (null != myOptTag) {
ToTerm toTerm = ToTerm.make(myOptTag);
optTermHole = toTerm.qbuild(builder, litHole);
}
AstroToken quant = new AstroToken((int)myQuant.charValue(),
Twine.fromString(""),
null);
return builder.argHole(optTermHole, quant);
}
/**
* Returns "ToTermList(myOptTag, myQuant)"
*/
public String getName() {
return "ToTermList(" +
E.toQuote(myOptTag) + "," +
E.toQuote(myQuant)+ ")";
}
/**
* Coerces to a ConstList of Term
*/
public Object coerce(Object specimen, OneArgFunc optEjector) {
ToTerm toTerm = ToTerm.make(myOptTag);
if (specimen instanceof EList) {
ConstList list = ((EList)specimen).snapshot();
int len = list.size();
char q = myQuant.charValue();
if ('?' == q && len >= 2) {
Thrower.toEject(optEjector,
"'?' doesn't allow " + len + " elements: " +
specimen);
} else if ('+' == q && len <= 0) {
Thrower.toEject(optEjector,
"'+' requires at least one element: " +
specimen);
} else {
//do nothing, '*' allows any length
}
//passed the quantity check.
FlexList result = FlexList.fromType(Term.class, len);
for (int i = 0; i < len; i++) {
Object element = list.get(i);
result.put(i, toTerm.coerce(element, optEjector));
}
return result.snapshot();
} else if (specimen.getClass().isArray()) {
//convert an array to a list, and recur
return coerce(ConstList.fromArray(specimen), optEjector);
} else if (specimen instanceof Term) {
//convert a Term to a singleton list, and recur
ConstList list = ConstList.EmptyList.with(specimen);
return coerce(list, optEjector);
} else {
//convert all else to a Term, and recur
return coerce(toTerm.coerce(specimen, optEjector),
optEjector);
}
}
}