Package org.yinwang.pysonar.ast

Source Code of org.yinwang.pysonar.ast.Attribute

package org.yinwang.pysonar.ast;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.yinwang.pysonar.Analyzer;
import org.yinwang.pysonar.Binding;
import org.yinwang.pysonar.State;
import org.yinwang.pysonar.types.FunType;
import org.yinwang.pysonar.types.InstanceType;
import org.yinwang.pysonar.types.Type;
import org.yinwang.pysonar.types.UnionType;

import java.util.Set;

import static org.yinwang.pysonar.Binding.Kind.ATTRIBUTE;


public class Attribute extends Node {

    @Nullable
    public Node target;
    @NotNull
    public Name attr;


    public Attribute(@Nullable Node target, @NotNull Name attr, String file, int start, int end) {
        super(file, start, end);
        this.target = target;
        this.attr = attr;
        addChildren(target, attr);
    }


    public void setAttr(State s, @NotNull Type v) {
        Type targetType = transformExpr(target, s);
        if (targetType instanceof UnionType) {
            Set<Type> types = ((UnionType) targetType).types;
            for (Type tp : types) {
                setAttrType(tp, v);
            }
        } else {
            setAttrType(targetType, v);
        }
    }


    private void addRef(@NotNull Type targetType, @NotNull Set<Binding> bs) {
        for (Binding b : bs) {
            Analyzer.self.putRef(attr, b);
            if (parent != null && parent instanceof Call &&
                    b.type instanceof FunType && targetType instanceof InstanceType)
            {  // method call
                ((FunType) b.type).setSelfType(targetType);
            }
        }
    }


    private void setAttrType(@NotNull Type targetType, @NotNull Type v) {
        if (targetType.isUnknownType()) {
            Analyzer.self.putProblem(this, "Can't set attribute for UnknownType");
            return;
        }
        Set<Binding> bs = targetType.table.lookupAttr(attr.id);
        if (bs != null) {
            addRef(targetType, bs);
        }

        targetType.table.insert(attr.id, attr, v, ATTRIBUTE);
    }


    @NotNull
    @Override
    public Type transform(State s) {
        // the form of ::A in ruby
        if (target == null) {
            return transformExpr(attr, s);
        }

        Type targetType = transformExpr(target, s);
        if (targetType instanceof UnionType) {
            Set<Type> types = ((UnionType) targetType).types;
            Type retType = Type.UNKNOWN;
            for (Type tt : types) {
                retType = UnionType.union(retType, getAttrType(tt));
            }
            return retType;
        } else {
            return getAttrType(targetType);
        }
    }


    private Type getAttrType(@NotNull Type targetType) {
        Set<Binding> bs = targetType.table.lookupAttr(attr.id);
        if (bs == null) {
            Analyzer.self.putProblem(attr, "attribute not found in type: " + targetType);
            Type t = Type.UNKNOWN;
            t.table.setPath(targetType.table.extendPath(attr.id));
            return t;
        } else {
            addRef(targetType, bs);
            return State.makeUnion(bs);
        }
    }


    @NotNull
    @Override
    public String toString() {
        return "<Attribute:" + start + ":" + target + "." + attr.id + ">";
    }

}
TOP

Related Classes of org.yinwang.pysonar.ast.Attribute

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.