Skip to content

Commit

Permalink
Fixed Bugs Related to Circular Heritage
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigo-pino committed Feb 26, 2021
1 parent ef6608a commit c62da3b
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 31 deletions.
16 changes: 11 additions & 5 deletions src/devdeb.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,28 @@ def run_pipeline(program):
print('Context\n', context)

auto_collector = autotype_collector.AutotypeCollector(context)
auto_collector.visit(ast)
scope = auto_collector.visit(ast)

s = "Type Collector Errors:\n"
s = format_errors(collector.errors, s)
s += "Type Builder Errors:\n"
s = format_errors(builder.errors, s)
s += "Inference Gatherer Errors:\n"
s = format_errors(auto_collector.errors, s)

s += "Scope:\n" + scope.get_all_names()
print(s)

folder_path = r'./zTests/Misc'
filenames = os.listdir(folder_path)
filenames.sort()
try:
folder_path = r'./zTests/Misc'
filenames = os.listdir(folder_path)
filenames.sort()
except FileNotFoundError:
print("Error Importing Files")
count = 4

filenames = [r'/home/rodro/Aarka/Complementos de Compilacion/cool-compiler-2022/src/zTests/Misc/06FooBarRaz.cl']
filenames = [r'/home/rodro/Aarka/Complementos de Compilacion/cool-compiler-2022/src/zTests/Misc/07MultipleClass.cl']

for filename in filenames:
if count == 0:
print("Reach Count Limit")
Expand Down
2 changes: 1 addition & 1 deletion src/semantics/autotype_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def visit(self, node:ProgramNode) -> Scope:
@visitor.when(ClassDeclarationNode)
def visit(self, node, scope):
self.current_type = self.context.get_type(node.id, unpacked=True)
scope.define_variable("self", self.current_type)
scope.define_variable("self", TypeBag({self.current_type}))
for attr in self.current_type.attributes:
scope.define_variable(attr.name, attr.type)

Expand Down
59 changes: 45 additions & 14 deletions src/semantics/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,35 @@ def define_attribute(self, name:str, typex):
else:
raise SemanticError(f'Attribute "{name}" is already defined in {self.name}.')

def get_attribute(self, name:str):
def get_attribute(self, name:str, first=None):
if not first:
first = self.name
elif first == self.name:
raise AttributeError(f'Attribute "{name}" is not defined in {self.name}.')

try:
return next(attr for attr in self.attributes if attr.name == name)
except StopIteration:
if self.parent is None:
raise AttributeError(f'Attribute "{name}" is not defined in {self.name}.')
try:
return self.parent.get_attribute(name)
return self.parent.get_attribute(name, first=first)
except SemanticError:
raise AttributeError(f'Attribute "{name}" is not defined in {self.name}.')

def get_method(self, name:str, local:bool = False):
def get_method(self, name:str, local:bool = False, first = None):
if not first:
first = self.name
elif first == self.name:
raise SemanticError(f'Method "{name}" is not defined in class {self.name}.')

try:
return next(method for method in self.methods if method.name == name)
except StopIteration:
if self.parent is None:
raise SemanticError(f'Method "{name}" is not defined in class {self.name}.')
try:
return self.parent.get_method(name)
return self.parent.get_method(name, first = first)
except SemanticError:
raise SemanticError(f'Method "{name}" is not defined in class {self.name}.')

Expand All @@ -108,15 +118,15 @@ def define_method(self, name:str, param_names:list, param_types:list, return_typ
parent_method = None
if parent_method:
error_list = []
if conforms(return_type, parent_method.return_type):
if not conforms(return_type, parent_method.return_type):
error_list.append(f" -> Same return type: Redefined method has \'{return_type.name}\' as return type instead of \'{parent_method.return_type.name}\'.")
if len(param_types) != len(parent_method.param_types):
error_list.append(f" -> Same amount of params: Redefined method has {len(param_types)} params instead of {len(parent_method.param_types)}.")
else:
count = 0
err = []
for param_type, parent_param_type in zip(param_types, parent_method.param_types):
if param_type != parent_param_type:
if not conforms(param_type, parent_param_type):
err.append(f" -Param number {count} has {param_type.name} as type instead of {parent_param_type.name}")
count += 1
if err:
Expand All @@ -130,29 +140,42 @@ def define_method(self, name:str, param_names:list, param_types:list, return_typ
self.methods.append(method)
return method

def all_attributes(self, clean=True):
plain = OrderedDict() if self.parent is None else self.parent.all_attributes(False)
def all_attributes(self, clean=True, first=None):
if not first:
first = self.name
elif first == self.name:
return OrderedDict.values() if clean else OrderedDict()

plain = OrderedDict() if self.parent is None else self.parent.all_attributes(clean = False, first=first)
for attr in self.attributes:
plain[attr.name] = (attr, self)
return plain.values() if clean else plain

def all_methods(self, clean=True):
plain = OrderedDict() if self.parent is None else self.parent.all_methods(False)
def all_methods(self, clean=True, first=None):
if not first:
first = self.name
elif first == self.name:
return OrderedDict.values() if clean else OrderedDict()

plain = OrderedDict() if self.parent is None else self.parent.all_methods(clean = False, first=first)
for method in self.methods:
plain[method.name] = (method, self)
return plain.values() if clean else plain

def conforms_to(self, other):
return other.bypass() or self == other or self.parent is not None and self.parent.conforms_to(other)
def conforms_to(self, other, first=None):
if not first:
first = self.name
elif self.name == first:
return False
return other.bypass() or self == other or self.parent and self.parent.conforms_to(other, first)

def bypass(self):
return False

def least_common_ancestor(self, other):
this = self
if isinstance(this, ErrorType) or isinstance(other, ErrorType):
return ErrorType()
#raise SemanticError("Error Type detected while perfoming Join. Aborting.")
return ErrorType()

while this.index < other.index:
other = other.parent
Expand Down Expand Up @@ -397,6 +420,14 @@ def reset(self):
self.current_child = -1
for child in self.children:
child.reset()

def get_all_names(self, s:str = "", level:int = 0):
if self.locals:
s += "\n ".join([x.name + ":" + str([typex.name for typex in x.type.type_set]) for x in self.locals])
s += "\n\n"
for child in self.children:
s = child.get_all_names(s, level + 1)
return s


def conforms(bag1:TypeBag, bag2:TypeBag):
Expand Down
9 changes: 6 additions & 3 deletions src/semantics/type_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ def visit(self, node):
def visit(self, node):
try:
self.context.create_type(node.id)
self.type_graph[node.id] = []
self.node_dict[node.id] = node
try:
self.type_graph[node.id]
except KeyError:
self.type_graph[node.id] = []
if node.parent:
if node.parent in {'String', 'Int, Bool'}:
raise SemanticError(f"Type \'{node.id}\' cannot inherit from \'{node.parent}\' beacuse is forbidden.")
Expand All @@ -56,7 +59,7 @@ def get_type_hierarchy(self):
visited.add(node)
path = [node]
circular_heritage_errors.append(self.check_circular_heritage(node, self.type_graph, path, visited))
new_order = new_order + [self.context.get_type(node) for node in path]
new_order = new_order + [self.node_dict[node] for node in path]

if circular_heritage_errors:
print(circular_heritage_errors)
Expand All @@ -82,7 +85,7 @@ def dfs_type_graph(self, root, graph, visited:set, new_order, index):
def check_circular_heritage(self, root, graph, path, visited):
for node in graph[root]:
if node in path:
return ' -> '.join(child for child in visited + [visited[0]])
return ' -> '.join(child for child in path + [path[0]])

visited.add(node)
path.append(node)
Expand Down
28 changes: 20 additions & 8 deletions src/zTests/Misc/07MultipleClass.cl
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
class Main
{
h:AUTO_TYPE <- new H;
a:AUTO_TYPE <- new A;
main(): Int
{
{
3;
}
};
};

class H
{
a:int;
a:Int;
};

class Z inherits H
{
x:int;
x:Int;
};

class A inherits F
{
b:int;
b:Int;
};

class B inherits A
{
c:int;
c:Int;
};

class C inherits B
{
e:int;
e:Int;
};

class D inherits C
{
f:int;
f:Int;
};

class F inherits D
{
g:int;
};
g:Int;
};

0 comments on commit c62da3b

Please sign in to comment.