Skip to content

Commit 9a6ebca

Browse files
committed
Replace checked exceptions with Optional and validation
- Remove WrongObjKindException and WrongStructKindException - MJUtils: haveSameSignatures/returnTypesAssignmentCompatible return boolean; getCompactClassMethodSignature returns Optional<String>; sizeOfClassInstance returns OptionalInt - Add ClassMethodSignature.from() and GlobalMethodSignature.from() factories - VMT: add() returns boolean; getSameSignatureMethod returns Optional<Obj> - InheritanceTree: getNode returns Optional; addNodeForClass validates and returns - CodeGenerator and SemanticAnalyzer: use Optional instead of try-catch
1 parent 434d3bd commit 9a6ebca

12 files changed

Lines changed: 213 additions & 308 deletions

src/main/java/dev/askov/mjcompiler/CodeGenerator.java

Lines changed: 60 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
package dev.askov.mjcompiler;
2121

2222
import dev.askov.mjcompiler.ast.*;
23-
import dev.askov.mjcompiler.exceptions.WrongObjKindException;
24-
import dev.askov.mjcompiler.exceptions.WrongStructKindException;
2523
import dev.askov.mjcompiler.inheritancetree.InheritanceTree;
24+
import dev.askov.mjcompiler.inheritancetree.InheritanceTreeNode;
2625
import dev.askov.mjcompiler.mjsymboltable.MJTab;
2726
import dev.askov.mjcompiler.util.MJUtils;
2827
import java.util.ArrayList;
2928
import java.util.HashMap;
3029
import java.util.List;
3130
import java.util.Map;
31+
import java.util.Optional;
3232
import java.util.Stack;
3333
import rs.etf.pp1.mj.runtime.Code;
3434
import rs.etf.pp1.symboltable.Tab;
@@ -65,7 +65,7 @@ public int getCode() {
6565
private final List<Integer> currentSkipNextCondTermJumps = new ArrayList<>();
6666
private int currentConditionalJump = 0;
6767
private final Stack<Obj> thisParameterObjs = new Stack<>();
68-
private final Map<Obj, List<Integer>> notYetDeclaredMethod = new HashMap<>();
68+
private final Map<Obj, List<Integer>> addressesToPatch = new HashMap<>();
6969

7070
public int getMainPc() {
7171
return mainPc;
@@ -637,12 +637,8 @@ public void generateMethodInvocationCode(Obj overriddenMethod) {
637637
for (var clss : leafClasses) {
638638
for (var member : clss.getType().getMembers()) {
639639
if (member.getKind() == Obj.Meth) {
640-
try {
641-
if (MJUtils.haveSameSignatures(member, overriddenMethod)) {
642-
filteredLeafClasses.add(clss);
643-
}
644-
} catch (WrongObjKindException e) {
645-
e.printStackTrace();
640+
if (MJUtils.haveSameSignatures(member, overriddenMethod)) {
641+
filteredLeafClasses.add(clss);
646642
}
647643
}
648644
}
@@ -657,26 +653,25 @@ public void generateMethodInvocationCode(Obj overriddenMethod) {
657653
Code.put2(0);
658654
Code.put(Code.pop);
659655
Code.put(Code.call);
660-
try {
661-
var method =
662-
InheritanceTree.getNode(clss).getVMT().getSameSignatureMethod(overriddenMethod);
663-
var addr = method.getAdr();
664-
if (addr != 0) {
665-
Code.put2(addr - Code.pc + 1);
666-
} else {
667-
if (notYetDeclaredMethod.containsKey(method)) {
668-
var list = notYetDeclaredMethod.get(method);
669-
list.add(Code.pc);
670-
} else {
671-
List<Integer> list = new ArrayList<>();
672-
list.add(Code.pc);
673-
notYetDeclaredMethod.put(method, list);
674-
}
675-
Code.put2(0);
676-
}
677-
} catch (WrongObjKindException | WrongStructKindException e) {
678-
e.printStackTrace();
679-
}
656+
InheritanceTree.getNode(clss)
657+
.flatMap(node -> node.getVMT().getSameSignatureMethod(overriddenMethod))
658+
.ifPresent(
659+
method -> {
660+
var addr = method.getAdr();
661+
if (addr != 0) {
662+
Code.put2(addr - Code.pc + 1);
663+
} else {
664+
if (addressesToPatch.containsKey(method)) {
665+
var addressesToPatch = this.addressesToPatch.get(method);
666+
addressesToPatch.add(Code.pc);
667+
} else {
668+
List<Integer> addressesToPatch = new ArrayList<>();
669+
addressesToPatch.add(Code.pc);
670+
this.addressesToPatch.put(method, addressesToPatch);
671+
}
672+
Code.put2(0);
673+
}
674+
});
680675
Code.put(Code.jmp);
681676
jmpAddresses.add(Code.pc);
682677
Code.put2(0);
@@ -687,16 +682,13 @@ public void generateMethodInvocationCode(Obj overriddenMethod) {
687682
Code.put2(0);
688683

689684
Code.put(Code.invokevirtual);
690-
String methodSignature;
691-
try {
692-
methodSignature = MJUtils.getCompactClassMethodSignature(overriddenMethod);
693-
} catch (WrongObjKindException e) {
694-
methodSignature = null;
695-
e.printStackTrace();
696-
}
697-
for (var i = 0; i < (methodSignature != null ? methodSignature.length() : 0); i++) {
698-
Code.put4(methodSignature.charAt(i));
699-
}
685+
MJUtils.getCompactClassMethodSignature(overriddenMethod)
686+
.ifPresent(
687+
methodSignature -> {
688+
for (var i = 0; i < methodSignature.length(); i++) {
689+
Code.put4(methodSignature.charAt(i));
690+
}
691+
});
700692
Code.put4(-1);
701693
for (int address : jmpAddresses) {
702694
Code.fixup(address);
@@ -751,10 +743,10 @@ public void visit(ClassDecl classDecl) {
751743
public void visit(MethodName methodName) {
752744
var methodNameObj = methodName.obj;
753745
methodNameObj.setAdr(Code.pc);
754-
if (notYetDeclaredMethod.containsKey(methodNameObj)) {
755-
var list = notYetDeclaredMethod.get(methodNameObj);
756-
for (int addr : list) {
757-
Code.fixup(addr);
746+
if (addressesToPatch.containsKey(methodNameObj)) {
747+
var addressesToPatch = this.addressesToPatch.get(methodNameObj);
748+
for (int addressToPatch : addressesToPatch) {
749+
Code.fixup(addressToPatch);
758750
}
759751
}
760752
if (methodNameObj.getName().equals(MJTab.MAIN)) {
@@ -790,9 +782,10 @@ public void visit(ActParsEnd actParsEnd) {
790782
} else if (!(methodDesignator.obj == MJTab.ordMethod
791783
|| methodDesignator.obj == MJTab.chrMethod)) {
792784
if (!thisParameterObj.equals(Tab.noObj)) {
793-
try {
794-
var thisParameterTypeNode =
795-
InheritanceTree.getNode((MJTab.findObjForClass(thisParameterObj.getType())));
785+
Optional<InheritanceTreeNode> nodeOpt =
786+
InheritanceTree.getNode(MJTab.findObjForClass(thisParameterObj.getType()));
787+
if (nodeOpt.isPresent()) {
788+
var thisParameterTypeNode = nodeOpt.get();
796789
if (thisParameterTypeNode.getVMT().containsSameSignatureMethod(methodDesignator.obj)
797790
&& thisParameterTypeNode.hasChildren()) {
798791
methodDesignator.traverseBottomUp(new ThisParameterLoader());
@@ -801,8 +794,9 @@ public void visit(ActParsEnd actParsEnd) {
801794
Code.put(Code.call);
802795
Code.put2(offset);
803796
}
804-
} catch (WrongObjKindException | WrongStructKindException e) {
805-
e.printStackTrace();
797+
} else {
798+
Code.put(Code.call);
799+
Code.put2(offset);
806800
}
807801
} else {
808802
Code.put(Code.call);
@@ -1195,29 +1189,25 @@ public void visit(BoolFactor boolFactor) {
11951189
@Override
11961190
public void visit(NewScalarFactor newScalarFactor) {
11971191
Code.put(Code.new_);
1198-
try {
1199-
Code.put2(MJUtils.sizeOfClassInstance(newScalarFactor.getType().obj.getType()));
1200-
} catch (WrongStructKindException e1) {
1201-
e1.printStackTrace();
1202-
}
1192+
MJUtils.sizeOfClassInstance(newScalarFactor.getType().obj.getType()).ifPresent(Code::put2);
12031193
if (newScalarFactor.getType().obj.getType().getKind() == Struct.Class) {
1204-
try {
1205-
if (!InheritanceTree.getNode(newScalarFactor.obj).getVMT().isEmpty()) {
1206-
var constObj =
1207-
new Obj(Obj.Con, "", Tab.intType, newScalarFactor.getType().obj.getAdr(), 1);
1208-
Code.put(Code.dup);
1209-
Code.load(constObj);
1210-
Code.put(Code.putfield);
1211-
Code.put2(0);
1212-
constObj.setAdr(newScalarFactor.getType().obj.getLevel());
1213-
Code.put(Code.dup);
1214-
Code.load(constObj);
1215-
Code.put(Code.putfield);
1216-
Code.put2(1);
1217-
}
1218-
} catch (WrongObjKindException | WrongStructKindException e) {
1219-
e.printStackTrace();
1220-
}
1194+
InheritanceTree.getNode(newScalarFactor.obj)
1195+
.ifPresent(
1196+
node -> {
1197+
if (!node.getVMT().isEmpty()) {
1198+
var constObj =
1199+
new Obj(Obj.Con, "", Tab.intType, newScalarFactor.getType().obj.getAdr(), 1);
1200+
Code.put(Code.dup);
1201+
Code.load(constObj);
1202+
Code.put(Code.putfield);
1203+
Code.put2(0);
1204+
constObj.setAdr(newScalarFactor.getType().obj.getLevel());
1205+
Code.put(Code.dup);
1206+
Code.load(constObj);
1207+
Code.put(Code.putfield);
1208+
Code.put2(1);
1209+
}
1210+
});
12211211
}
12221212
}
12231213

src/main/java/dev/askov/mjcompiler/SemanticAnalyzer.java

Lines changed: 48 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@
9999
import dev.askov.mjcompiler.ast.VoidFormPars;
100100
import dev.askov.mjcompiler.ast.VoidReturnType;
101101
import dev.askov.mjcompiler.ast.VoidSuperclass;
102-
import dev.askov.mjcompiler.exceptions.WrongObjKindException;
103-
import dev.askov.mjcompiler.exceptions.WrongStructKindException;
104102
import dev.askov.mjcompiler.inheritancetree.InheritanceTree;
105103
import dev.askov.mjcompiler.loggers.SemanticErrorMJLogger;
106104
import dev.askov.mjcompiler.loggers.SemanticErrorMJLogger.SemanticErrorKind;
@@ -111,6 +109,7 @@
111109
import dev.askov.mjcompiler.methodsignature.MethodSignatureGenerator;
112110
import dev.askov.mjcompiler.mjsymboltable.MJTab;
113111
import dev.askov.mjcompiler.util.MJUtils;
112+
import java.util.Optional;
114113
import java.util.Stack;
115114
import rs.etf.pp1.symboltable.Tab;
116115
import rs.etf.pp1.symboltable.concepts.Obj;
@@ -244,13 +243,8 @@ private Obj findNearestDeclaration(MethodSignature classMethodSignature, Obj cls
244243
while (currentClass != null) {
245244
var method = currentClass.getMembersTable().searchKey(classMethodSignature.getMethodName());
246245
if (method != null && method != Tab.noObj && method.getKind() == Obj.Meth) {
247-
try {
248-
if (new ClassMethodSignature(method, MJTab.noType)
249-
.isInvokableBy(classMethodSignature)) {
250-
return method;
251-
}
252-
} catch (WrongObjKindException e) {
253-
e.printStackTrace();
246+
if (new ClassMethodSignature(method, MJTab.noType).isInvokableBy(classMethodSignature)) {
247+
return method;
254248
}
255249
}
256250
currentClass = currentClass.getElemType();
@@ -265,17 +259,13 @@ private void validateOverriding(MethodDecl methodDecl) {
265259
while (clss != null) {
266260
var overriddenMethod =
267261
clss.getMembersTable().searchKey(methodDecl.getMethodName().obj.getName());
268-
try {
269-
if (MJUtils.haveSameSignatures(overridingMethod, overriddenMethod)
270-
&& !MJUtils.returnTypesAssignmentCompatible(overridingMethod, overriddenMethod)) {
271-
detectSemanticError(
272-
null,
273-
methodDecl,
274-
SemanticErrorKind.INCOMPATIBLE_RET_TYPE,
275-
new ClassMethodSignature(overriddenMethod, clss));
276-
}
277-
} catch (WrongObjKindException e) {
278-
e.printStackTrace();
262+
if (MJUtils.haveSameSignatures(overridingMethod, overriddenMethod)
263+
&& !MJUtils.returnTypesAssignmentCompatible(overridingMethod, overriddenMethod)) {
264+
detectSemanticError(
265+
null,
266+
methodDecl,
267+
SemanticErrorKind.INCOMPATIBLE_RET_TYPE,
268+
new ClassMethodSignature(overriddenMethod, clss));
279269
}
280270
clss = clss.getElemType();
281271
}
@@ -529,11 +519,7 @@ public void visit(NonVoidSuperclass nonVoidSuperclass) {
529519
if (superclassType != MJTab.noType) {
530520
if (superclassType.getKind() == Struct.Class && superclassType != currentClassObj.getType()) {
531521
var superclassObj = nonVoidSuperclass.getType().obj;
532-
try {
533-
InheritanceTree.addNodeForClass(currentClassObj, superclassObj);
534-
} catch (WrongObjKindException | WrongStructKindException e) {
535-
e.printStackTrace();
536-
}
522+
InheritanceTree.addNodeForClass(currentClassObj, superclassObj);
537523
currentClassObj.setAdr(superclassObj.getAdr());
538524
currentClassObj.getType().setElementType(superclassType);
539525
} else {
@@ -549,11 +535,7 @@ public void visit(VoidSuperclass voidSuperclass) {
549535
MJTab.insert(Obj.Fld, VMT_POINTER, MJTab.intType);
550536
MJTab.insert(Obj.Fld, CLASS_ID, MJTab.intType);
551537
currentClassObj.setAdr(1);
552-
try {
553-
InheritanceTree.addNodeForClass(currentClassObj);
554-
} catch (WrongObjKindException | WrongStructKindException e) {
555-
e.printStackTrace();
556-
}
538+
InheritanceTree.addNodeForClass(currentClassObj);
557539
}
558540

559541
@Override
@@ -808,38 +790,36 @@ public void visit(MethodCallDesignatorStatement methodCallDesignatorStatement) {
808790
}
809791
}
810792
} else {
811-
MethodSignature methodSignature = null;
812-
try {
813-
if (isGlobalMethod(methodObj)) {
814-
methodSignature = new GlobalMethodSignature(methodObj);
815-
} else {
816-
methodSignature = new ClassMethodSignature(methodObj, thisParameterObjs.peek().getType());
817-
}
818-
} catch (WrongObjKindException ignored) {
819-
}
820-
if (methodSignature != null) {
821-
if (!methodSignature.isInvokableBy(invokedMethodSignatureGenerator.getMethodSignature())) {
822-
var overriddenMethodObj =
823-
findNearestDeclaration(
824-
invokedMethodSignatureGenerator.getMethodSignature(), thisParameterObjs.pop());
825-
if (overriddenMethodObj.equals(Tab.noObj)) {
826-
if (invokedMethodSignatureGenerator.getMethodSignature().allTypesAreKnown()) {
827-
detectSemanticError(
828-
null,
829-
methodCallDesignatorStatement,
830-
SemanticErrorKind.INAPPLICABLE_METHOD,
831-
methodSignature.toString(),
832-
invokedMethodSignatureGenerator.getMethodSignature().getParameterList());
833-
} else {
834-
detectSemanticError();
793+
Optional<MethodSignature> methodSignatureOpt =
794+
isGlobalMethod(methodObj)
795+
? GlobalMethodSignature.from(methodObj).map(m -> (MethodSignature) m)
796+
: ClassMethodSignature.from(methodObj, thisParameterObjs.peek().getType())
797+
.map(m -> (MethodSignature) m);
798+
methodSignatureOpt.ifPresentOrElse(
799+
methodSignature -> {
800+
if (!methodSignature.isInvokableBy(
801+
invokedMethodSignatureGenerator.getMethodSignature())) {
802+
var overriddenMethodObj =
803+
findNearestDeclaration(
804+
invokedMethodSignatureGenerator.getMethodSignature(),
805+
thisParameterObjs.pop());
806+
if (overriddenMethodObj.equals(Tab.noObj)) {
807+
if (invokedMethodSignatureGenerator.getMethodSignature().allTypesAreKnown()) {
808+
detectSemanticError(
809+
null,
810+
methodCallDesignatorStatement,
811+
SemanticErrorKind.INAPPLICABLE_METHOD,
812+
methodSignature.toString(),
813+
invokedMethodSignatureGenerator.getMethodSignature().getParameterList());
814+
} else {
815+
detectSemanticError();
816+
}
817+
} else {
818+
methodCallDesignatorStatement.getDesignator().obj = overriddenMethodObj;
819+
}
835820
}
836-
} else {
837-
methodCallDesignatorStatement.getDesignator().obj = overriddenMethodObj;
838-
}
839-
}
840-
} else {
841-
detectSemanticError();
842-
}
821+
},
822+
this::detectSemanticError);
843823
}
844824
}
845825

@@ -1216,16 +1196,13 @@ public void visit(MethodCallFactor methodCallFactor) {
12161196
}
12171197
}
12181198
} else {
1219-
MethodSignature methodSignature = null;
1220-
try {
1221-
if (isGlobalMethod(methodObj)) {
1222-
methodSignature = new GlobalMethodSignature(methodObj);
1223-
} else {
1224-
methodSignature = new ClassMethodSignature(methodObj, thisParameterObjs.peek().getType());
1225-
}
1226-
} catch (WrongObjKindException ignored) {
1227-
}
1228-
if (methodSignature != null) {
1199+
Optional<MethodSignature> methodSignatureOpt =
1200+
isGlobalMethod(methodObj)
1201+
? GlobalMethodSignature.from(methodObj).map(m -> (MethodSignature) m)
1202+
: ClassMethodSignature.from(methodObj, thisParameterObjs.peek().getType())
1203+
.map(m -> (MethodSignature) m);
1204+
if (methodSignatureOpt.isPresent()) {
1205+
var methodSignature = methodSignatureOpt.get();
12291206
if (!methodSignature.isInvokableBy(invokedMethodSignatureGenerator.getMethodSignature())) {
12301207
var overriddenMethodObj =
12311208
findNearestDeclaration(

0 commit comments

Comments
 (0)