diff --git a/AST.py b/AST.py index 7a67a498830df152f5714a3225cb5ee8ae9e29b1..885000ea05442e6e2712bfd6b9c618da066a1d69 100644 --- a/AST.py +++ b/AST.py @@ -108,3 +108,21 @@ def getParseTreeNodes(names, tree, terminateList = []): else: result.extend(getParseTreeNodes(names, n, terminateList)) return result + +def getASTNode(names, AST): + result = [] + if not AST: + return result + if AST.__class__.__name__ in names: + result.append(AST) + return result + if not AST.children: + return [] + for n in AST.children: + if not n: + continue + if n.__class__.__name__ in names: + result.append(n) + else: + result.extend(getASTNode(names, n)) + return result diff --git a/LineNodes.py b/LineNodes.py index 52f1a024fec1f19358a2107d00b7771d5f027670..57d091e2c710631c7accf04d95078e8474a16773 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -209,7 +209,7 @@ class ReturnNode(ASTNode): self.expr.checkType() self.myType = self.expr.myType else: - self.myType = TypeStruct("void", None) + self.myType = None # this is None as returning a value of type Void is invalid even in a function with type Void # forStatement and forStatementNoShortIf # Rules: diff --git a/MemberNodes.py b/MemberNodes.py index 13ba951fffeac30d5656d1e6acce2163fa380ada..4eeabd135b91b8c308e3fa1633de59145a10254a 100644 --- a/MemberNodes.py +++ b/MemberNodes.py @@ -1,4 +1,4 @@ -from AST import ASTNode, getParseTreeNodes +from AST import ASTNode, getParseTreeNodes, getASTNode from LineNodes import BlockNode, VarDclNode from ExprPrimaryNodes import makeNodeFromExpr from UnitNodes import ParamNode @@ -107,9 +107,37 @@ class MethodNode(ASTNode): return env def checkType(self): - if self.methodType: # constructor + if self.methodType: # constructor would be None self.myType = self.methodType.myType for p in self.params: p.checkType() if self.body: self.body.checkType() + + # Checking return types against the function type + # No method body: do not check type as function isn't implemented + if not self.body: + return + + # With method body + returnNodes = getASTNode(["ReturnNode"], self.body) + + # Checking for cases where there are no return statements + if not returnNodes: + # Either a constructor or the function has type Void + if not self.methodType or self.myType.name == "void": + return + raise Exception("ERROR: no return statement at function {}".format(self.name)) + + # Checking for cases where there are return statements + for n in returnNodes: + # Checking for functions of type void + # Only valid if either the function doesn't have a return statement(checked above), or the return statement is a semicolon (return;) + if self.myType.name == "void": + if n.myType: + raise Exception("ERROR: return type of function {} doesn't match with return statement.".format(self.name)) + + # Checking for non void cases + if not self.myType.assignable(n.myType): + raise Exception("ERROR: return type of function {} doesn't match with return statement.".format(self.name)) + return \ No newline at end of file