diff --git a/AstBuilding.py b/AstBuilding.py index b67b81eb775d763a9a8e4d7dac4e91d09dab6682..e3382ba4857ebe8f718af68b222fd8d5a9693318 100644 --- a/AstBuilding.py +++ b/AstBuilding.py @@ -62,26 +62,36 @@ def reachabilityChecking(ASTs): # (also simultaneosly creating fieldOffset because fieldOffset table is required to generate size) def codeGenPrep(ASTs): interM = [] + types = [] + for t in ASTs: classInterNode = t[1].typeDcl - if classInterNode and classInterNode.__class__.__name__ == "ClassNode": + types.append(classInterNode) + if classInterNode.__class__.__name__ == "ClassNode": classInterNode.populateSizeAndFieldOffset() else: # interfaceNode, get their methods to prep for SIT interM += classInterNode.methods - if interM: # prep SIT - for i in range(len(interM)): - interM[i].methodOffset = i * 4 - interM[i].isInterM = True - for t in ASTs: - classInterNode = t[1].typeDcl - if classInterNode and classInterNode.__class__.__name__ == "ClassNode": - classInterNode.SITsize = len(interM) + # prep SIT + for i in range(len(interM)): + interM[i].methodOffset = i * 4 + interM[i].isInterM = True + + # prep subtype testing table + for i in range(len(types)): + types[i].subTypeOffset = i * 4 # assign each type a position in the subtype testing table + + # store SIT and subtype table size + for t in ASTs: + classInterNode = t[1].typeDcl + if classInterNode.__class__.__name__ == "ClassNode": + classInterNode.SITsize = len(interM) + classInterNode.subTypeSize = len(types) def codeGen(ASTs, output="output"): - ASTs = ASTs[:10] # TOREMOVE: don't compile stdlib for now codeGenPrep(ASTs) + ASTs = ASTs[:1] # TOREMOVE: don't compile stdlib for now for t in ASTs: t[1].codeGen() # Outputting the generated code into className.s diff --git a/TypeNodes.py b/TypeNodes.py index e316f54124845db55a97f08e7122c37822487f23..aeec0904e12b107225193878a793f3d274c4ee59 100644 --- a/TypeNodes.py +++ b/TypeNodes.py @@ -17,6 +17,8 @@ class ClassInterNode(ASTNode): self.children = [] self.canonName = '' self.SITsize = 0 + self.subTypeSize = 0 + self.subTypeOffset = 0 # sets self.inherits = [] @@ -310,7 +312,6 @@ class ClassNode(ClassInterNode): if hasattr(self, "code"): return - self.code = "" # For read-only section self.data = "" # For writeable data section # print("This is the super class: {}".format(self.superClass)) @@ -324,10 +325,12 @@ class ClassNode(ClassInterNode): self.data += self.label # SIT - self.data += pLabel("SIT_spot_"+ self.name, "inter") # type 'inter' for interface methods + self.data += pLabel("SIT_spot_"+ self.name, "inter") # type 'inter' for internal usage self.data += p("dd", "42") - # TODO: subtype testing tables + # subtype testing table + self.data += pLabel("subT_spot_"+ self.name, "inter") # type 'inter' for internal usage + self.data += p("dd", "42") ####### ADDING METHODS TO CLASS MEMORY LAYOUT AND FIELDS TO FIELD OFFSET TABLE ######### # Copying over the offsets of methods from superclass and DECLARING memory segment for the methods @@ -381,6 +384,12 @@ class ClassNode(ClassInterNode): self.data += pLabel("SIT_" + str(i), "inter") self.data += p("dd", "42") + # Layout subtype testing column + self.data += pLabel("subT_" + self.name, "inter") + for i in range(self.subTypeSize): + self.data += pLabel("subT_" + str(i), "inter") + self.data += p("dd", "0") # 0 for False, 1 for True + self.data += ";END OF CLASS MEMORY LAYOUT FOR CLASS " + self.name + "\n" @@ -423,19 +432,21 @@ class ClassNode(ClassInterNode): self.code += p("mov", "[eax]", "dword " + imLabel) self.code += "; End of fill in SIT.\n" - self.code += p(instruction="ret", arg1="") - self.code += "; End of function for filling in class memory layout\n" - - + # fill in subtype testing column + self.code += "\n; Filling in subtype testing\n" + self.code += p("mov", "eax", "I_subT_spot_" + self.name) + self.code += p("mov", "[eax]", "dword I_subT_" + self.name) + for t in getSupers(self): # getSupers includes self + dlabel = "I_subT_" + str(t.subTypeOffset // 4) + self.code += p("mov", "eax", dlabel, "self is a subType of " + t.canonName) + self.code += p("mov", "[eax]", "dword 1") + self.code += "; End of fill in subtype testing.\n" + self.code += p(instruction="ret", arg1="") + self.code += "; End of function for filling in class memory layout\n" - # print(self.name) - # print(self.fieldOffset) - - # print(self.code) - ########################################################### # Generating a function that allocates and initializes all static fields @@ -552,3 +563,12 @@ def safeReplace(cur, new, className): # quick fix for final method getClass from java.lang.Object if 'final' in cur.mods and cur.name != 'getClass': raise Exception("ERROR: In class {0}, {1} '{2}' in class '{3}' replaces final {1} in class/interface {4}".format(className, methodOrField, new.name, new.typeName, cur.typeName)) + + +# helper: get list of all super class/interface of a ClassInterNode +def getSupers(classType): + result = {classType} + for s in classType.super: + result.add(s) + result.union(getSupers(s)) + return result