[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 &gt;= 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 &lt;=&gt; 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  =&gt;   a literal Functor(..., data)
     *     Functor       =&gt;   same
     *     Token         =&gt;   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              =&gt;   null
     *     literal data      =&gt;   a literal Functor(..., data)
     *     literal Functor   =&gt;   same
     *     literal Token     =&gt;   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);
        }
    }
}