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