SHOW:
|
|
- or go back to the newest paste.
| 1 | ##################### NAME IN OOP: QUESTION 2 ########################### | |
| 2 | class GetEnv(Visitor): | |
| 3 | def visitProgram(self,ctx:Program,o:object): | |
| 4 | o = [] | |
| 5 | for decl in ctx.decl: | |
| 6 | o = self.visit(decl,o) | |
| 7 | return o | |
| 8 | def visitClassDecl(self,ctx:ClassDecl,o:object): | |
| 9 | if ctx.name in o: | |
| 10 | raise RedeclaredField(ctx.name) | |
| 11 | env = [] | |
| 12 | foundParent = False | |
| 13 | if len(ctx.parent) != 0: | |
| 14 | for decl in o: | |
| 15 | if len(decl) == 3: | |
| 16 | if ctx.parent == decl[0]: | |
| 17 | env += decl[2] | |
| 18 | foundParent = True | |
| 19 | if foundParent == False: raise UndeclaredClass(ctx.parent) | |
| 20 | for decl in ctx.mem: | |
| 21 | env = self.visit(decl,env) | |
| 22 | o += [(ctx.name,ctx.parent,env)] | |
| 23 | return o | |
| 24 | def visitVarDecl(self,ctx:VarDecl,o:object): | |
| 25 | if ctx.name in o: | |
| 26 | raise RedeclaredField(ctx.name) | |
| 27 | o += [(ctx.name,ctx.typ)] | |
| 28 | return o | |
| 29 | def visitFuncDecl(self,ctx:FuncDecl,o:object): | |
| 30 | env = [] | |
| 31 | if ctx.name in o: | |
| 32 | raise RedeclaredMethod(ctx.name) | |
| 33 | o += [(ctx.name,None)] | |
| 34 | for decl in ctx.param: | |
| 35 | env = self.visit(decl,env) | |
| 36 | for decl in ctx.body[0]: | |
| 37 | env = self.visit(decl,env) | |
| 38 | return o | |
| 39 | class StaticCheck(Visitor): | |
| 40 | def visitProgram(self,ctx:Program,o:object): | |
| 41 | env = GetEnv().visit(ctx,o) | |
| 42 | for decl in ctx.decl: | |
| 43 | self.visit(decl,env) | |
| 44 | def visitClassDecl(self,ctx:ClassDecl,o:object): | |
| 45 | for decl in ctx.mem: | |
| 46 | if type(decl) is FuncDecl: | |
| 47 | self.visit(decl,o) | |
| 48 | def visitVarDecl(self,ctx:VarDecl,o:object): | |
| 49 | if ctx.name in o: | |
| 50 | raise RedeclaredField(ctx.name) | |
| 51 | o += [(ctx.name,ctx.typ)] | |
| 52 | def visitFuncDecl(self,ctx:FuncDecl,o:object): | |
| 53 | env = ctx.param + ctx.body[0] | |
| 54 | NotDeclInFunction = o | |
| 55 | for expr in ctx.body[1]: | |
| 56 | self.visit(expr,(env,NotDeclInFunction)) | |
| 57 | def visitIntType(self,ctx:IntType,o:object):pass | |
| 58 | ||
| 59 | def visitFloatType(self,ctx:FloatType,o:object):pass | |
| 60 | ||
| 61 | def visitClassType(self,ctx:ClassType,o:object):pass | |
| 62 | ||
| 63 | def visitIntLit(self,ctx:IntLit,o:object):pass | |
| 64 | ||
| 65 | def visitId(self,ctx:Id,o:object): | |
| 66 | idTyp = None | |
| 67 | for element in o[0]: # o[0] is local scope of function | |
| 68 | if ctx.name == element.name: # there is no class decl inside function LOL | |
| 69 | idTyp = element.typ | |
| 70 | if not idTyp : # Two type of stuff inside function: FuncDecl and VarDecl | |
| 71 | raise UndeclaredIdentifier(ctx.name) | |
| 72 | return idTyp | |
| 73 | def visitFieldAccess(self,ctx:FieldAccess,o:object): | |
| 74 | typ = self.visit(ctx.exp,o) | |
| 75 | if type(typ) is ClassType: | |
| 76 | classData = None | |
| 77 | for x in o[1]: # global scope | |
| 78 | if typ.name == x[0]: | |
| 79 | classData = x | |
| 80 | break | |
| 81 | if classData == None: raise UndeclaredClass(typ.name) | |
| 82 | for classElement in classData[2]: | |
| 83 | if ctx.field == classElement[0]: | |
| 84 | return | |
| 85 | raise UndeclaredField(ctx.field) | |
| 86 |