From 2f31b4d19d03d782a43d3695efe3e1c74562e378 Mon Sep 17 00:00:00 2001
From: Xun Yang <x299yang@uwaterloo.ca>
Date: Sun, 12 Apr 2020 16:20:05 -0400
Subject: [PATCH] subtype testing table

---
 AstBuilding.py | 30 ++++++++++++++++++++----------
 TypeNodes.py   | 44 ++++++++++++++++++++++++++++++++------------
 2 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/AstBuilding.py b/AstBuilding.py
index b67b81e..e3382ba 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 e316f54..aeec090 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
-- 
GitLab