Package org.cx4a.rsense.typing.vertex

Source Code of org.cx4a.rsense.typing.vertex.Vertex

package org.cx4a.rsense.typing.vertex;

import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;

import org.jruby.ast.Node;
import org.jruby.ast.FixnumNode;
import org.jruby.ast.StrNode;
import org.jruby.ast.SymbolNode;
import org.jruby.ast.types.INameNode;

import org.cx4a.rsense.ruby.IRubyObject;
import org.cx4a.rsense.typing.TypeSet;
import org.cx4a.rsense.typing.Propagation;
import org.cx4a.rsense.typing.runtime.PolymorphicObject;
import org.cx4a.rsense.util.Logger;

public class Vertex {
    public static final int MEGAMORPHIC_THRESHOLD = 5;
    public static final Vertex EMPTY = new Vertex(null, TypeSet.EMPTY) {
            @Override
            public void addEdge(Vertex dest) {}
            @Override
            public void removeEdge(Vertex dest) {}
        };

    static {
        EMPTY.edges = Collections.<Vertex>emptyList();
    }

    protected Node node;
    protected int capacity = MEGAMORPHIC_THRESHOLD + 1;
    protected TypeSet typeSet;
    protected IRubyObject singleType;
    protected boolean megamorphic;
    protected List<Vertex> edges;
    protected boolean changed = true;
    protected long changedTime;

    public Vertex() {}

    public Vertex(int capacity) {
        this.capacity = capacity;
    }

    public Vertex(Node node) {
        this.node = node;
    }

    public Vertex(Node node, int capacity) {
        this.node = node;
        this.capacity = capacity;
    }

    public Vertex(Node node, TypeSet typeSet) {
        this.node = node;
        this.typeSet = typeSet;
    }

    public Node getNode() {
        return node;
    }

    public TypeSet getTypeSet() {
        return typeSet != null ? typeSet : TypeSet.EMPTY;
    }

    public List<Vertex> getEdges() {
        return edges != null ? edges : Collections.<Vertex>emptyList();
    }

    public boolean isEmpty() {
        return typeSet == null || typeSet.isEmpty();
    }

    public boolean addType(IRubyObject type) {
        if (type == null)
            throw new NullPointerException("type is null");

        if (megamorphic)
            return false;

        if (typeSet().size() >= MEGAMORPHIC_THRESHOLD) {
            Logger.info("megamorphic detected");
            megamorphic = true;

            // FIXME generalize
            singleType = type.getRuntime().newInstance(type.getRuntime().getObject());
            typeSet = new TypeSet(1);
            typeSet.add(singleType);

            return false;
        } else {
            if (singleType == null)
                singleType = type;
            if (typeSet().add(type))
                return changed = true;
            else
                return false;
        }
    }

    public boolean addTypes(Collection<IRubyObject> types) {
        boolean added = false;
        for (IRubyObject type : types) {
            if (addType(type))
                added = true;
        }
        return added;
    }

    public boolean update(Vertex other) {
        return addTypes(other.getTypeSet());
    }

    public boolean isChanged() {
        if (changed)
            return true;

        // Check to see if polymorphic objects are changed
        if (typeSet != null && !megamorphic) {
            for (IRubyObject obj : typeSet) {
                if (obj instanceof PolymorphicObject) {
                    PolymorphicObject pobj = (PolymorphicObject) obj;
                    if (changedTime <= pobj.getModifiedTime())
                        return changed = true;
                }
            }
        }

        return false;
    }

    public void markUnchanged() {
        if (changed)
            changedTime = System.currentTimeMillis();
        changed = false;
    }

    public IRubyObject singleType() {
        if (typeSet == null || typeSet.size() != 1)
            return null;
        else if (singleType != null)
            return singleType;
        else
            return singleType = typeSet.iterator().next();
    }

    public void addEdge(Vertex dest) {
        if (edges == null)
            edges = new ArrayList<Vertex>(2);
        edges.add(dest);
    }

    public void removeEdge(Vertex dest) {
        if (edges != null)
            edges.remove(dest);
    }

    public boolean accept(Propagation propagation, Vertex src) {
        return propagation.getGraph().propagateVertex(propagation, this, src);
    }

    public boolean isFree() {
        return node == null;
    }

    @Override
    public String toString() {
        return getTypeSet().toString();
    }

    private TypeSet typeSet() {
        if (typeSet == null)
            typeSet = new TypeSet(capacity);
        return typeSet;
    }

    public static String getName(Vertex vertex) {
        Node node = vertex.getNode();
        if (node instanceof INameNode) {
            return ((INameNode) node).getName();
        } else {
            return null;
        }
    }

    public static Integer getFixnum(Vertex vertex) {
        Node node = vertex.getNode();
        if (node instanceof FixnumNode) {
            return Integer.valueOf((int) ((FixnumNode) node).getValue());
        } else {
            return null;
        }
    }

    public static String getString(Vertex vertex) {
        Node node = vertex.getNode();
        if (node instanceof StrNode) {
            return ((StrNode) node).getValue().toString();
        } else {
            return null;
        }
    }

    public static String getSymbol(Vertex vertex) {
        Node node = vertex.getNode();
        if (node instanceof SymbolNode) {
            return ((SymbolNode) node).getName();
        } else {
            return null;
        }
    }

    public static String getStringOrSymbol(Vertex vertex) {
        String value = getString(vertex);
        return value != null ? value : getSymbol(vertex);
    }
}
TOP

Related Classes of org.cx4a.rsense.typing.vertex.Vertex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.