summaryrefslogblamecommitdiff
path: root/sources/meta/scalac/checkers/MetaCheckTreeNodes.java
blob: 9fb2f2018d3a7186da654a9598944e6ee1969581 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                                          
                             


                                                

                                
                                
                                 
                                     











                                                                              







                                                                 

                             
                                  































































                                                                               







                                                                               













































                                                                               
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package meta.scalac.checkers;

import meta.java.Type;
import meta.scalac.ast.AbstractTreeCaseExpander;
import meta.scalac.ast.TreeKind;
import meta.scalac.ast.TreeType;
import meta.scalac.ast.TreeNode;
import meta.scalac.ast.TreeField;
import meta.scalac.ast.TreeFieldLink;

public class MetaCheckTreeNodes extends AbstractTreeCaseExpander {

    //########################################################################
    // Public Methods

    public void printTreeCaseBody(TreeNode node) {
        if (node.fields != null) {
            for (int i = 0; i < node.fields.length; i++) {
                TreeField field = node.fields[i];
                printCheckField(node, field.type, field.name, "i");
            }
            if (node.hasLinkedFields()) {
                writer.println("Symbol symbol = tree.symbol();");
                writer.print("if (symbol != null)").lbrace();
                for (int i = 0; i < node.fields.length; i++)
                    if (node.fields[i].link != null)
                        printCheckFieldLink(node.fields[i]);
                writer.rbrace();
            }
        }
        printCheckNode(node);
        writer.println("return;");
    }

    private void printCheckNode(TreeNode node) {
        if (node.start.constant != null) {
            writer.println("assert global.currentPhase.id >=  " +
                "global.PHASE."+node.start.constant + ".id :").indent();
            writer.println("\"cannot create instance of " + node.name +
                " before phase " + node.start.name + ", \" +");
            writer.println(
                "\"current phase is \" + " + "global.currentPhase;").undent();
        }
        if (node.stop.constant != null) {
            writer.println("assert global.currentPhase.id <=  " +
                "global.PHASE."+node.stop.constant + ".id :").indent();
            writer.println("\"cannot create instance of " + node.name +
                " after phase " + node.stop.name + ", \" +");
            writer.println(
                "\"current phase is \" + " + "global.currentPhase;").undent();
        }
    }

    private void printCheckField(TreeNode node,Type type,String name,String i){
        if (type.isPrimitive()) return;
        writer.println("assert " + name + " != null :").indent();
        printNullValue(node, name);
        writer.println(";").undent();
        switch (type) {
        case Reference(_, _):
            break;

        case Array(Type item):
            writer.print(
                "for (int "+i+" = 0; "+i+" < "+name+".length; "+i+"++)");
            writer.lbrace();
            printCheckField(node, item, name+"["+i+"]", i+"i");
            writer.rbrace();
            break;

        case TreeType.Name(TreeKind kind):
            if (kind != TreeKind.Any && kind != TreeKind.Test) {
                writer.println("assert " + (kind == TreeKind.Type ? "" : "!")+
                    name +".isTypeName() :").indent();
                printWrongKind(node, name, kind);
                writer.println(";").undent();
            }
            break;

        case TreeType.Tree(TreeKind kind):
            if (kind != TreeKind.Any) {
                writer.println("assert " +
                    name + ".is" + kind + "() :").indent();
                printWrongKind(node, name, kind);
                writer.println(";").undent();
            }
            break;

        case TreeType.Node(_):
            break;

        default:
            throw new Error(type.getClass().getName());
        }
    }

    private void printCheckFieldLink(TreeField field) {
        String getter = field.link.getLink();
        writer.println("assert symbol." +getter+ " == " +field+ " :").indent();
        writer.println("\"symbol and tree " + field.link + " differ: \"+" +
            "symbol." + getter + "+\" != \"+" +field+ ";");
        writer.undent();
    }

    private void printNullValue(TreeNode node, String field) {
        String expanded = getExpandedField(field);
        writer.print("\"field " +expanded+ " of class " +node+ " is null\"");
    }

    private void printWrongKind(TreeNode node, String field, TreeKind kind) {
        String expanded = getExpandedField(field);
        writer.println("\"field " + expanded + " of class " + node +
            " is not of kind " + kind + ", \" +");
        writer.print("\"found: \" + Debug.show("+field+")");
        // !!! " + \" of kind \" + kind("+field+")";
    }

    private String getExpandedField(String field) {
        int begin = field.indexOf('[');
        if (begin < 0) return field;
        StringBuffer buffer = new StringBuffer(field.substring(0, begin));
        for (int end; (end = field.indexOf(']', begin)) >= 0; begin = end + 1){
            String index = field.substring(begin + 1, end);
            buffer.append("[\"+").append(index).append("+\"]");
        }
        return buffer.toString();
    }

    //########################################################################
}


/* !!!

    protected static String kind(Tree tree) {
        switch (tree) {
        case Select(_, Name name): return kind(name);
        case Ident(Name name): return kind(name);
        }
        return "unknown";
    }

    protected static String kind(Name name) {
        if (name.isTypeName()) return "Type";
        if (name.isTermName()) return "Term";
        if (name.isConstrName()) return "Constr";
        return "unknown";
    }

*/