updates
[IRC.git] / Robust / src / IR / Tree / SemanticCheck.java
1 package IR.Tree;
2
3 import java.util.*;
4 import IR.*;
5
6 public class SemanticCheck {
7     State state;
8     TypeUtil typeutil;
9
10     public SemanticCheck(State state, TypeUtil tu) {
11         this.state=state;
12         this.typeutil=tu;
13     }
14
15     public void semanticCheck() {
16         SymbolTable classtable=state.getClassSymbolTable();
17         Iterator it=classtable.getDescriptorsIterator();
18         while(it.hasNext()) {
19             ClassDescriptor cd=(ClassDescriptor)it.next();
20             System.out.println("Checking class: "+cd);
21             for(Iterator field_it=cd.getFields();field_it.hasNext();) {
22                 FieldDescriptor fd=(FieldDescriptor)field_it.next();
23                 System.out.println("Checking field: "+fd);
24                 checkField(cd,fd);
25             }
26
27             for(Iterator method_it=cd.getMethods();method_it.hasNext();) {
28                 MethodDescriptor md=(MethodDescriptor)method_it.next();
29                 checkMethod(cd,md);
30             }
31         }
32     }
33
34     public void checkTypeDescriptor(TypeDescriptor td) {
35         if (td.isPrimitive())
36             return; /* Done */
37         if (td.isClass()) {
38             String name=td.toString();
39             ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name);
40             if (field_cd==null)
41                 throw new Error("Undefined class "+name);
42             td.setClassDescriptor(field_cd);
43             return;
44         }
45         throw new Error();
46     }
47
48     public void checkField(ClassDescriptor cd, FieldDescriptor fd) {
49         checkTypeDescriptor(fd.getType());
50     }
51
52     public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
53         /* Check return type */
54         if (!md.getReturnType().isVoid())
55             checkTypeDescriptor(md.getReturnType());
56         for(int i=0;i<md.numParameters();i++) {
57             TypeDescriptor param_type=md.getParamType(i);
58             checkTypeDescriptor(param_type);
59         }
60         BlockNode bn=state.getMethodBody(md);
61         /* Link the naming environments */
62         md.getParameterTable().setParent(cd.getFieldTable());
63         checkBlockNode(md, md.getParameterTable(),bn);
64     }
65     
66     public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
67         /* Link in the naming environment */
68         bn.getVarTable().setParent(nametable);
69         for(int i=0;i<bn.size();i++) {
70             BlockStatementNode bsn=bn.get(i);
71             checkBlockStatementNode(md, bn.getVarTable(),bsn);
72         }
73     }
74     
75     public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) {
76         switch(bsn.kind()) {
77         case Kind.BlockExpressionNode:
78             checkBlockExpressionNode(md, nametable,(BlockExpressionNode)bsn);
79             return;
80
81         case Kind.DeclarationNode:
82             checkDeclarationNode(md, nametable, (DeclarationNode)bsn);
83             return;
84             
85         case Kind.IfStatementNode:
86             checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
87             return;
88             
89         case Kind.LoopNode:
90             checkLoopNode(md, nametable, (LoopNode)bsn);
91             return;
92             
93         case Kind.ReturnNode:
94             checkReturnNode(md, nametable, (ReturnNode)bsn);
95             return;
96
97         case Kind.SubBlockNode:
98             checkSubBlockNode(md, nametable, (SubBlockNode)bsn);
99             return;
100         }
101         throw new Error();
102     }
103
104     void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
105         checkExpressionNode(md, nametable, ben.getExpression(), null);
106     }
107
108     void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable,  DeclarationNode dn) {
109         VarDescriptor vd=dn.getVarDescriptor();
110         checkTypeDescriptor(vd.getType());
111         Descriptor d=nametable.get(vd.getSymbol());
112         if ((d==null)||
113             (d instanceof FieldDescriptor)) {
114             nametable.add(vd);
115         } else
116             throw new Error(vd.getSymbol()+" defined a second time");
117         if (dn.getExpression()!=null)
118             checkExpressionNode(md, nametable, dn.getExpression(), vd.getType());
119     }
120     
121     void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
122         checkBlockNode(md, nametable, sbn.getBlockNode());
123     }
124
125     void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
126         checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType());
127     }
128
129     void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
130         checkExpressionNode(md, nametable, isn.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
131         checkBlockNode(md, nametable, isn.getTrueBlock());
132         checkBlockNode(md, nametable, isn.getFalseBlock());
133     }
134     
135     void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
136         switch(en.kind()) {
137         case Kind.AssignmentNode:
138             checkAssignmentNode(md,nametable,(AssignmentNode)en,td);
139             return;
140         case Kind.CastNode:
141             checkCastNode(md,nametable,(CastNode)en,td);
142             return;
143         case Kind.CreateObjectNode:
144             checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td);
145             return;
146         case Kind.FieldAccessNode:
147             checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
148             return;
149         case Kind.LiteralNode:
150             checkLiteralNode(md,nametable,(LiteralNode)en,td);
151             return;
152         case Kind.MethodInvokeNode:
153             checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
154             return;
155         case Kind.NameNode:
156             checkNameNode(md,nametable,(NameNode)en,td);
157             return;
158         case Kind.OpNode:
159             checkOpNode(md,nametable,(OpNode)en,td);
160             return;
161         }
162         throw new Error();
163     }
164
165     void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
166         
167     }
168
169     void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
170     }
171
172     void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
173     }
174
175     void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) {
176     }
177
178     void checkLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) {
179         
180     }
181
182     void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
183     }
184
185     void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
186     }
187
188     void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,TypeDescriptor td) {
189     }
190
191     void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
192     }
193 }