-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOverridingOverloadingVisitor.java
More file actions
171 lines (149 loc) · 6.65 KB
/
Copy pathOverridingOverloadingVisitor.java
File metadata and controls
171 lines (149 loc) · 6.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import syntaxtree.*;
import visitor.GJDepthFirst;
/*This visitor checks overriding and overloading rules*/
public class OverridingOverloadingVisitor extends GJDepthFirst<String, Argu> {
LinkedHashMap<String,ClassInfo> symbolTable;
/*getting the symbol table from v1 */
public OverridingOverloadingVisitor(LinkedHashMap<String, ClassInfo> symbolTable){
this.symbolTable = symbolTable;
}
/*HELPER FUNCTIONS */
/*Helper that checks whether var1 is subtype of var2 or of the same type*/
boolean checkType(String var1, String var2){
//same type
if(var1.equals(var2)){
return true;
}
ClassInfo cInfo=symbolTable.get(var1);
//no such class
if (cInfo==null){
return false;
}
//doesnt have a parent so type doesnt exist for sure
if(cInfo.parent==null){
return false;
}
//go up through the parents to check
return checkType(cInfo.parent, var2);
}
/*Checks function overloading within the same class */
/*Rules:
1. same name differnt param count= valid overloading
2. same name, same arg count, at least one position with no subtype relationship= valid overloading
3. same name, same arg count, all positions have subtype relationship= ERROR
*/
void checkOverloading(String classname){
for(String methodName: symbolTable.get(classname).methods.keySet()){
List<MethodInfo> methodList=symbolTable.get(classname).methods.get(methodName);
//if we have more than 1 method with same name in class
if(methodList.size()>1){
for(int i=0;i<methodList.size();i++){
for(int j=i+1;j<methodList.size();j++){
MethodInfo mInfo1=methodList.get(i);
MethodInfo mInfo2=methodList.get(j);
if(mInfo1.formalParams.size()==mInfo2.formalParams.size()){
List<String> params1= new ArrayList<>(mInfo1.formalParams.values());
List<String> params2= new ArrayList<>(mInfo2.formalParams.values());
boolean flag=false;
for(int k=0;k<mInfo1.formalParams.size();k++){
String type1= params1.get(k);
String type2= params2.get(k);
if(!checkType(type1, type2) && !checkType(type2,type1)){
flag=true;
}
}
if(flag==false){
throw new RuntimeException("Method overloading error in "+classname+"\n for methods with identifier: "+methodName);
}
}
}
}
}
}
}
/* Checks method overriding and overloading form parent classes*/
/*Rules:
1. Same name, different arg count= ok -overload
2. Same name, same arg count, exactly same types BUT return type must match parent = ok - overriding
3. Same name, same arg count, at least one position with no subtype relationship= ok - overload
4. Same name, same arg count, all positions have subtype relationship but not exactly same type->ERROR overriding
*/
void checkExtendBoth(String classname, String parentname){
for(String methodNameChild: symbolTable.get(classname).methods.keySet()){
if(symbolTable.get(parentname).methods.containsKey(methodNameChild)){
List<MethodInfo> childMethods = symbolTable.get(classname).methods.get(methodNameChild);
List<MethodInfo> parentMethods = symbolTable.get(parentname).methods.get(methodNameChild);
for(MethodInfo child: childMethods){
for(MethodInfo parent: parentMethods){
if(child.formalParams.size()==parent.formalParams.size()){
List<String> params1= new ArrayList<>(child.formalParams.values());
List<String> params2= new ArrayList<>(parent.formalParams.values());
boolean sameType=true;
boolean noSubtype=false;
for(int k=0;k<params1.size();k++){
String type1=params1.get(k);
String type2=params2.get(k);
if(!type1.equals(type2)){
sameType=false;
}
if(!checkType(type1, type2) && !checkType(type2, type1)){
noSubtype=true;
}
}
if(!sameType && !noSubtype){
throw new RuntimeException("Method overloading/overriding error in class "+classname+" for method: "+methodNameChild+ " ambiguous signature with method in parent class " + parentname);
}
if(sameType && !child.methodType.equals(parent.methodType)){
throw new RuntimeException("Method overriding error in class "+classname+" for method: "+ methodNameChild+" - return type "+child.methodType+" does not match parent return type "+parent.methodType);
}
}
}
}
}
}
//go up the parent chani
String grandparent = symbolTable.get(parentname).parent;
if(grandparent != null){
checkExtendBoth(classname, grandparent);
}
}
/*CLASS DECLARATION */
/**
* Grammar production:
* f0 -> "class"
* f1 -> Identifier()
* f2 -> "{"
* f3 -> ( VarDeclaration() )*
* f4 -> ( MethodDeclaration() )*
* f5 -> "}"
*/
@Override
public String visit(ClassDeclaration cd, Argu argu){
String classname=cd.f1.f0.toString();
checkOverloading(classname);
return null;
}
/*CLASS EXTENDS DECLARATION */
/**
* Grammar production:
* f0 -> "class"
* f1 -> Identifier()
* f2 -> "extends"
* f3 -> Identifier()
* f4 -> "{"
* f5 -> ( VarDeclaration() )*
* f6 -> ( MethodDeclaration() )*
* f7 -> "}"
*/
@Override
public String visit(ClassExtendsDeclaration ced, Argu argu){
String classname=ced.f1.f0.toString();
String parentname=ced.f3.f0.toString();
checkOverloading(classname);
checkExtendBoth(classname,parentname);
return null;
}
}