Flatten fields in namenodes
[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         // Do descriptors first
19         while(it.hasNext()) {
20             ClassDescriptor cd=(ClassDescriptor)it.next();
21             System.out.println("Checking class: "+cd);
22             //Set superclass link up
23             if (cd.getSuper()!=null) {
24                 cd.setSuper(typeutil.getClass(cd.getSuper()));
25                 // Link together Field and Method tables
26                 cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
27                 cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
28             }
29             
30             for(Iterator field_it=cd.getFields();field_it.hasNext();) {
31                 FieldDescriptor fd=(FieldDescriptor)field_it.next();
32                 System.out.println("Checking field: "+fd);
33                 checkField(cd,fd);
34             }
35             for(Iterator method_it=cd.getMethods();method_it.hasNext();) {
36                 MethodDescriptor md=(MethodDescriptor)method_it.next();
37                 checkMethod(cd,md);
38             }
39         }
40
41         it=classtable.getDescriptorsIterator();
42         // Do descriptors first
43         while(it.hasNext()) {
44             ClassDescriptor cd=(ClassDescriptor)it.next();
45             for(Iterator method_it=cd.getMethods();method_it.hasNext();) {
46                 MethodDescriptor md=(MethodDescriptor)method_it.next();
47                 checkMethodBody(cd,md);
48             }
49         }
50     }
51
52     public void checkTypeDescriptor(TypeDescriptor td) {
53         if (td.isPrimitive())
54             return; /* Done */
55         if (td.isClass()) {
56             String name=td.toString();
57             ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name);
58             if (field_cd==null)
59                 throw new Error("Undefined class "+name);
60             td.setClassDescriptor(field_cd);
61             return;
62         }
63         throw new Error();
64     }
65
66     public void checkField(ClassDescriptor cd, FieldDescriptor fd) {
67         checkTypeDescriptor(fd.getType());
68     }
69
70     public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
71         /* Check return type */
72         if (!md.isConstructor())
73             if (!md.getReturnType().isVoid())
74                 checkTypeDescriptor(md.getReturnType());
75
76         for(int i=0;i<md.numParameters();i++) {
77             TypeDescriptor param_type=md.getParamType(i);
78             checkTypeDescriptor(param_type);
79         }
80         /* Link the naming environments */
81         if (!md.isStatic()) /* Fields aren't accessible directly in a static method, so don't link in this table */
82             md.getParameterTable().setParent(cd.getFieldTable());
83         md.setClassDesc(cd);
84         if (!md.isStatic()) {
85             VarDescriptor thisvd=new VarDescriptor(new TypeDescriptor(cd),"this");
86             md.setThis(thisvd);
87         }
88     }
89
90     public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
91         System.out.println("Processing method:"+md);
92         BlockNode bn=state.getMethodBody(md);
93         checkBlockNode(md, md.getParameterTable(),bn);
94     }
95     
96     public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
97         /* Link in the naming environment */
98         bn.getVarTable().setParent(nametable);
99         for(int i=0;i<bn.size();i++) {
100             BlockStatementNode bsn=bn.get(i);
101             checkBlockStatementNode(md, bn.getVarTable(),bsn);
102         }
103     }
104     
105     public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) {
106         switch(bsn.kind()) {
107         case Kind.BlockExpressionNode:
108             checkBlockExpressionNode(md, nametable,(BlockExpressionNode)bsn);
109             return;
110
111         case Kind.DeclarationNode:
112             checkDeclarationNode(md, nametable, (DeclarationNode)bsn);
113             return;
114             
115         case Kind.IfStatementNode:
116             checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
117             return;
118             
119         case Kind.LoopNode:
120             checkLoopNode(md, nametable, (LoopNode)bsn);
121             return;
122             
123         case Kind.ReturnNode:
124             checkReturnNode(md, nametable, (ReturnNode)bsn);
125             return;
126
127         case Kind.SubBlockNode:
128             checkSubBlockNode(md, nametable, (SubBlockNode)bsn);
129             return;
130         }
131         throw new Error();
132     }
133
134     void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
135         checkExpressionNode(md, nametable, ben.getExpression(), null);
136     }
137
138     void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable,  DeclarationNode dn) {
139         VarDescriptor vd=dn.getVarDescriptor();
140         checkTypeDescriptor(vd.getType());
141         Descriptor d=nametable.get(vd.getSymbol());
142         if ((d==null)||
143             (d instanceof FieldDescriptor)) {
144             nametable.add(vd);
145         } else
146             throw new Error(vd.getSymbol()+" defined a second time");
147         if (dn.getExpression()!=null)
148             checkExpressionNode(md, nametable, dn.getExpression(), vd.getType());
149     }
150     
151     void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
152         checkBlockNode(md, nametable, sbn.getBlockNode());
153     }
154
155     void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
156         checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType());
157     }
158
159     void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
160         checkExpressionNode(md, nametable, isn.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
161         checkBlockNode(md, nametable, isn.getTrueBlock());
162         if (isn.getFalseBlock()!=null)
163             checkBlockNode(md, nametable, isn.getFalseBlock());
164     }
165     
166     void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
167         switch(en.kind()) {
168         case Kind.AssignmentNode:
169             checkAssignmentNode(md,nametable,(AssignmentNode)en,td);
170             return;
171         case Kind.CastNode:
172             checkCastNode(md,nametable,(CastNode)en,td);
173             return;
174         case Kind.CreateObjectNode:
175             checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td);
176             return;
177         case Kind.FieldAccessNode:
178             checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
179             return;
180         case Kind.LiteralNode:
181             checkLiteralNode(md,nametable,(LiteralNode)en,td);
182             return;
183         case Kind.MethodInvokeNode:
184             checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
185             return;
186         case Kind.NameNode:
187             checkNameNode(md,nametable,(NameNode)en,td);
188             return;
189         case Kind.OpNode:
190             checkOpNode(md,nametable,(OpNode)en,td);
191             return;
192         }
193         throw new Error();
194     }
195
196     void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
197         /* Get type descriptor */
198         if (cn.getType()==null) {
199             NameDescriptor typenamed=cn.getTypeName().getName();
200             String typename=typenamed.toString();
201             TypeDescriptor ntd=new TypeDescriptor(typeutil.getClass(typename));
202             cn.setType(ntd);
203         }
204
205         /* Check the type descriptor */
206         TypeDescriptor cast_type=cn.getType();
207         checkTypeDescriptor(cast_type);
208
209         /* Type check */
210         if (td!=null) {
211             if (!typeutil.isSuperorType(td,cast_type))
212                 throw new Error("Cast node returns "+cast_type+", but need "+td);
213         }
214
215         ExpressionNode en=cn.getExpression();
216         checkExpressionNode(md, nametable, en, null);
217         TypeDescriptor etd=en.getType();
218         if (typeutil.isSuperorType(cast_type,etd)) /* Cast trivially succeeds */
219             return;
220
221         if (typeutil.isSuperorType(etd,cast_type)) /* Cast may succeed */
222             return;
223
224         /* Different branches */
225         /* TODO: change if add interfaces */
226         throw new Error("Cast will always fail\n"+cn.printNode(0));
227     }
228
229     void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) {
230         ExpressionNode left=fan.getExpression();
231         checkExpressionNode(md,nametable,left,null);
232         TypeDescriptor ltd=left.getType();
233         String fieldname=fan.getFieldName();
234         FieldDescriptor fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
235         if (fd==null)
236             throw new Error("Unknown field "+fieldname);
237         fan.setField(fd);
238         if (td!=null)
239             if (!typeutil.isSuperorType(td,fan.getType()))
240                 throw new Error("Field node returns "+fan.getType()+", but need "+td);
241     }
242
243     void checkLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) {
244         /* Resolve the type */
245         Object o=ln.getValue();
246         if (ln.getTypeString().equals("null")) {
247             ln.setType(new TypeDescriptor(TypeDescriptor.NULL));
248         } else if (o instanceof Integer) {
249             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
250         } else if (o instanceof Long) {
251             ln.setType(new TypeDescriptor(TypeDescriptor.LONG));
252         } else if (o instanceof Float) {
253             ln.setType(new TypeDescriptor(TypeDescriptor.FLOAT));
254         } else if (o instanceof Double) {
255             ln.setType(new TypeDescriptor(TypeDescriptor.DOUBLE));
256         } else if (o instanceof Character) {
257             ln.setType(new TypeDescriptor(TypeDescriptor.CHAR));
258         } else if (o instanceof String) {
259             ln.setType(new TypeDescriptor(typeutil.getClass(TypeUtil.StringClass)));
260         } 
261
262         if (td!=null)
263             if (!typeutil.isSuperorType(td,ln.getType()))
264                 throw new Error("Field node returns "+ln.getType()+", but need "+td);
265     }
266
267     void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
268         NameDescriptor nd=nn.getName();
269         if (nd.getBase()!=null) {
270             /* Big hack */
271             /* Rewrite NameNode */
272             ExpressionNode en=translateNameDescriptorintoExpression(nd);
273             nn.setExpression(en);
274             checkExpressionNode(md,nametable,en,td);
275         } else {
276             String varname=nd.toString();
277             Descriptor d=(Descriptor)nametable.get(varname);
278             if (d==null) {
279                 throw new Error("Name "+varname+" undefined");
280             }
281             if (d instanceof VarDescriptor) {
282                 nn.setVar((VarDescriptor)d);
283             } else if (d instanceof FieldDescriptor) {
284                 nn.setField((FieldDescriptor)d);
285                 nn.setVar((VarDescriptor)nametable.get("this")); /* Need a pointer to this */
286             }
287             if (td!=null)
288                 if (!typeutil.isSuperorType(td,nn.getType()))
289                     throw new Error("Field node returns "+nn.getType()+", but need "+td);
290         }
291     }
292
293     void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
294         checkExpressionNode(md, nametable, an.getSrc() ,td);
295         //TODO: Need check on validity of operation here
296         if (!((an.getDest() instanceof FieldAccessNode)||
297               (an.getDest() instanceof NameNode)))
298             throw new Error("Bad lside in "+an.printNode(0));
299         checkExpressionNode(md, nametable, an.getDest(), null);
300         if (!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) {
301             throw new Error("Type of rside ("+an.getSrc().getType()+") not compatible with type of lside ("+an.getDest().getType()+")"+an.printNode(0));
302         }
303     }
304
305     void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
306         if (ln.getType()==LoopNode.WHILELOOP||ln.getType()==LoopNode.DOWHILELOOP) {
307             checkExpressionNode(md, nametable, ln.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
308             checkBlockNode(md, nametable, ln.getBody());
309         } else {
310             //For loop case
311             /* Link in the initializer naming environment */
312             BlockNode bn=ln.getInitializer();
313             bn.getVarTable().setParent(nametable);
314             for(int i=0;i<bn.size();i++) {
315                 BlockStatementNode bsn=bn.get(i);
316                 checkBlockStatementNode(md, bn.getVarTable(),bsn);
317             }
318             //check the condition
319             checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
320             checkBlockNode(md, bn.getVarTable(), ln.getBody());
321             checkBlockNode(md, bn.getVarTable(), ln.getUpdate());
322         }
323     }
324
325
326     void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
327         TypeDescriptor[] tdarray=new TypeDescriptor[con.numArgs()];
328         for(int i=0;i<con.numArgs();i++) {
329             ExpressionNode en=con.getArg(i);
330             checkExpressionNode(md,nametable,en,null);
331             tdarray[i]=en.getType();
332         }
333
334         TypeDescriptor typetolookin=con.getType();
335         checkTypeDescriptor(typetolookin);
336         if (!typetolookin.isClass()) 
337             throw new Error();
338
339         ClassDescriptor classtolookin=typetolookin.getClassDesc();
340         System.out.println("Looking for "+typetolookin.getSymbol());
341         System.out.println(classtolookin.getMethodTable());
342
343         Set methoddescriptorset=classtolookin.getMethodTable().getSet(typetolookin.getSymbol());
344         MethodDescriptor bestmd=null;
345         NextMethod:
346         for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
347             MethodDescriptor currmd=(MethodDescriptor)methodit.next();
348             /* Need correct number of parameters */
349             System.out.println("Examining: "+currmd);
350             if (con.numArgs()!=currmd.numParameters())
351                 continue;
352             for(int i=0;i<con.numArgs();i++) {
353                 if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
354                     continue NextMethod;
355             }
356             /* Method okay so far */
357             if (bestmd==null)
358                 bestmd=currmd;
359             else {
360                 if (isMoreSpecific(currmd,bestmd)) {
361                     bestmd=currmd;
362                 } else if (!isMoreSpecific(bestmd, currmd))
363                     throw new Error("No method is most specific");
364                 
365                 /* Is this more specific than bestmd */
366             }
367         }
368         if (bestmd==null)
369             throw new Error("No method found for "+con.printNode(0));
370         con.setConstructor(bestmd);
371
372         
373     }
374
375
376     /** Check to see if md1 is more specific than md2...  Informally
377         if md2 could always be called given the arguments passed into
378         md1 */
379
380     boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
381         /* Checks if md1 is more specific than md2 */
382         if (md1.numParameters()!=md2.numParameters())
383             throw new Error();
384         for(int i=0;i<md1.numParameters();i++) {
385             if (!typeutil.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
386                 return false;
387         }
388         if (!typeutil.isSuperorType(md2.getReturnType(), md1.getReturnType()))
389                 return false;
390         return true;
391     }
392
393     ExpressionNode translateNameDescriptorintoExpression(NameDescriptor nd) {
394         String id=nd.getIdentifier();
395         NameDescriptor base=nd.getBase();
396         if (base==null) 
397             return new NameNode(nd);
398         else 
399             return new FieldAccessNode(translateNameDescriptorintoExpression(base),id);
400     }
401
402
403     void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
404         /*Typecheck subexpressions
405           and get types for expressions*/
406
407         TypeDescriptor[] tdarray=new TypeDescriptor[min.numArgs()];
408         for(int i=0;i<min.numArgs();i++) {
409             ExpressionNode en=min.getArg(i);
410             checkExpressionNode(md,nametable,en,null);
411             tdarray[i]=en.getType();
412         }
413         TypeDescriptor typetolookin=null;
414         if (min.getExpression()!=null) {
415             checkExpressionNode(md,nametable,min.getExpression(),null);
416             typetolookin=min.getExpression().getType();
417         } else if (min.getBaseName()!=null) {
418             String rootname=min.getBaseName().getRoot();
419             if (nametable.get(rootname)!=null) {
420                 //we have an expression
421                 min.setExpression(translateNameDescriptorintoExpression(min.getBaseName()));
422                 checkExpressionNode(md, nametable, min.getExpression(), null);
423                 typetolookin=min.getExpression().getType();
424             } else {
425                 //we have a type
426                 ClassDescriptor cd=typeutil.getClass(min.getBaseName().getSymbol());
427                 if (cd==null)
428                     throw new Error(min.getBaseName()+" undefined");
429                 typetolookin=new TypeDescriptor(cd);
430             }
431         } else {
432             typetolookin=new TypeDescriptor(md.getClassDesc());
433         }
434         if (!typetolookin.isClass()) 
435             throw new Error();
436         ClassDescriptor classtolookin=typetolookin.getClassDesc();
437         System.out.println("Method name="+min.getMethodName());
438         Set methoddescriptorset=classtolookin.getMethodTable().getSet(min.getMethodName());
439         MethodDescriptor bestmd=null;
440         NextMethod:
441         for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
442             MethodDescriptor currmd=(MethodDescriptor)methodit.next();
443             /* Need correct number of parameters */
444             if (min.numArgs()!=currmd.numParameters())
445                 continue;
446             for(int i=0;i<min.numArgs();i++) {
447                 if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
448                     continue NextMethod;
449             }
450             /* Method okay so far */
451             if (bestmd==null)
452                 bestmd=currmd;
453             else {
454                 if (isMoreSpecific(currmd,bestmd)) {
455                     bestmd=currmd;
456                 } else if (!isMoreSpecific(bestmd, currmd))
457                     throw new Error("No method is most specific");
458                 
459                 /* Is this more specific than bestmd */
460             }
461         }
462         if (bestmd==null)
463             throw new Error("No method found for :"+min.printNode(0));
464         min.setMethod(bestmd);
465     }
466
467
468     void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
469         checkExpressionNode(md, nametable, on.getLeft(), null);
470         if (on.getRight()!=null)
471             checkExpressionNode(md, nametable, on.getRight(), null);
472         TypeDescriptor ltd=on.getLeft().getType();
473         TypeDescriptor rtd=on.getRight()!=null?on.getRight().getType():null;
474         TypeDescriptor lefttype=null;
475         TypeDescriptor righttype=null;
476         Operation op=on.getOp();
477
478         switch(op.getOp()) {
479         case Operation.LOGIC_OR:
480         case Operation.LOGIC_AND:
481             if (!(ltd.isBoolean()&&rtd.isBoolean()))
482                 throw new Error();
483             //no promotion
484             on.setLeftType(ltd);
485             on.setRightType(rtd);
486             on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
487             break;
488
489         case Operation.BIT_OR:
490         case Operation.BIT_XOR:
491         case Operation.BIT_AND:
492             // 5.6.2 Binary Numeric Promotion
493             //TODO unboxing of reference objects
494             if (ltd.isDouble()||rtd.isDouble())
495                 throw new Error();
496             else if (ltd.isFloat()||rtd.isFloat())
497                 throw new Error();
498             else if (ltd.isLong()||rtd.isLong())
499                 lefttype=new TypeDescriptor(TypeDescriptor.LONG);
500             else 
501                 lefttype=new TypeDescriptor(TypeDescriptor.INT);
502             righttype=lefttype;
503
504             on.setLeftType(lefttype);
505             on.setRightType(righttype);
506             on.setType(lefttype);
507             break;
508
509         case Operation.EQUAL:
510         case Operation.NOTEQUAL:
511             // 5.6.2 Binary Numeric Promotion
512             //TODO unboxing of reference objects
513             if (ltd.isBoolean()||rtd.isBoolean()) {
514                 if (!(ltd.isBoolean()&&rtd.isBoolean()))
515                     throw new Error();
516                 righttype=lefttype=new TypeDescriptor(TypeDescriptor.BOOLEAN);
517             } else if (ltd.isPtr()||rtd.isPtr()) {
518                 if (!(ltd.isPtr()&&rtd.isPtr()))
519                     throw new Error();
520                 righttype=rtd;
521                 lefttype=ltd;
522             } else if (ltd.isDouble()||rtd.isDouble())
523                 righttype=lefttype=new TypeDescriptor(TypeDescriptor.DOUBLE);
524             else if (ltd.isFloat()||rtd.isFloat())
525                 righttype=lefttype=new TypeDescriptor(TypeDescriptor.FLOAT);
526             else if (ltd.isLong()||rtd.isLong())
527                 righttype=lefttype=new TypeDescriptor(TypeDescriptor.LONG);
528             else 
529                 righttype=lefttype=new TypeDescriptor(TypeDescriptor.INT);
530
531             on.setLeftType(lefttype);
532             on.setRightType(righttype);
533             on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
534             break;
535
536
537
538         case Operation.LT:
539         case Operation.GT:
540         case Operation.LTE:
541         case Operation.GTE:
542             // 5.6.2 Binary Numeric Promotion
543             //TODO unboxing of reference objects
544             if (!ltd.isNumber()||!rtd.isNumber())
545                 throw new Error();
546
547             if (ltd.isDouble()||rtd.isDouble())
548                 lefttype=new TypeDescriptor(TypeDescriptor.DOUBLE);
549             else if (ltd.isFloat()||rtd.isFloat())
550                 lefttype=new TypeDescriptor(TypeDescriptor.FLOAT);
551             else if (ltd.isLong()||rtd.isLong())
552                 lefttype=new TypeDescriptor(TypeDescriptor.LONG);
553             else 
554                 lefttype=new TypeDescriptor(TypeDescriptor.INT);
555             righttype=lefttype;
556             on.setLeftType(lefttype);
557             on.setRightType(righttype);
558             on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
559             break;
560
561         case Operation.ADD:
562             //TODO: Need special case for strings eventually
563             
564             
565         case Operation.SUB:
566         case Operation.MULT:
567         case Operation.DIV:
568         case Operation.MOD:
569             // 5.6.2 Binary Numeric Promotion
570             //TODO unboxing of reference objects
571             if (!ltd.isNumber()||!rtd.isNumber())
572                 throw new Error("Error in "+on.printNode(0));
573
574             if (ltd.isDouble()||rtd.isDouble())
575                 lefttype=new TypeDescriptor(TypeDescriptor.DOUBLE);
576             else if (ltd.isFloat()||rtd.isFloat())
577                 lefttype=new TypeDescriptor(TypeDescriptor.FLOAT);
578             else if (ltd.isLong()||rtd.isLong())
579                 lefttype=new TypeDescriptor(TypeDescriptor.LONG);
580             else 
581                 lefttype=new TypeDescriptor(TypeDescriptor.INT);
582             righttype=lefttype;
583             on.setLeftType(lefttype);
584             on.setRightType(righttype);
585             on.setType(lefttype);
586             break;
587
588         case Operation.LEFTSHIFT:
589         case Operation.RIGHTSHIFT:
590             if (!rtd.isIntegerType())
591                 throw new Error();
592             //5.6.1 Unary Numeric Promotion
593             if (rtd.isByte()||rtd.isShort()||rtd.isInt())
594                 righttype=new TypeDescriptor(TypeDescriptor.INT);
595             else
596                 righttype=rtd;
597
598             on.setRightType(righttype);
599             if (!ltd.isIntegerType())
600                 throw new Error();
601         case Operation.UNARYPLUS:
602         case Operation.UNARYMINUS:
603         case Operation.POSTINC:
604         case Operation.POSTDEC:
605         case Operation.PREINC:
606         case Operation.PREDEC:
607             if (!ltd.isNumber())
608                 throw new Error();
609             //5.6.1 Unary Numeric Promotion
610             if (ltd.isByte()||ltd.isShort()||ltd.isInt())
611                 lefttype=new TypeDescriptor(TypeDescriptor.INT);
612             else
613                 lefttype=ltd;
614             on.setLeftType(lefttype);
615             on.setType(lefttype);
616             break;
617         default:
618             throw new Error();
619         }
620
621      
622
623         if (td!=null)
624             if (!typeutil.isSuperorType(td, on.getType())) {
625                 System.out.println(td);
626                 System.out.println(on.getType());
627                 throw new Error("Type of rside not compatible with type of lside"+on.printNode(0));     
628             }
629     }
630 }