From fbb8fed571a1d1b8e1f5c5573c02397ccbe30ccd Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 17 Feb 2020 09:00:20 -0500 Subject: [PATCH 001/435] Add .idea to ignore PyCharm files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4acafde1..4a009637 100644 --- a/.gitignore +++ b/.gitignore @@ -408,3 +408,4 @@ dmypy.json # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) +.idea From 78a26f739d1820f87502872869ee6ddaf153f96e Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 13:52:55 -0500 Subject: [PATCH 002/435] Add basic information about team members --- doc/Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/Readme.md b/doc/Readme.md index 402477c8..46b4fbf6 100644 --- a/doc/Readme.md +++ b/doc/Readme.md @@ -4,9 +4,9 @@ **Nombre** | **Grupo** | **Github** --|--|-- -Nombre1 Apellido1 Apellido2 | C4xx | [@github_user](https://github.com/) -Nombre2 Apellido1 Apellido2 | C4xx | [@github_user](https://github.com/) -Nombre3 Apellido1 Apellido2 | C4xx | [@github_user](https://github.com/) +Isabella Maria Sierra Ponce | C412 | [@TuquiSierra](https://github.com/TuquiSierra) +Adrian Tubal Paez Ruiz | C412 | [@stdevAdrianPaez](https://github.com/stdevAdrianPaez) +Eric Martin Garcia | C411 | [@ericmg97](https://github.com/ericmg97) ## Readme From 6209285ec0215cae5777f3cc770f88dcabeb33da Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 13:53:28 -0500 Subject: [PATCH 003/435] Basic implementation of lexer --- src/lexer.py | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/lexer.py diff --git a/src/lexer.py b/src/lexer.py new file mode 100644 index 00000000..8887902d --- /dev/null +++ b/src/lexer.py @@ -0,0 +1,90 @@ +import ply.lex as lex + +# List of token names. This is always required +tokens = [ + 'ASSIGN', + 'ARROW', + 'GREATHER', + 'GREATHEREQ', + 'LOWEREQ', + 'INT', + 'STRING', + 'TYPE', + 'ID' +] + +reserved = { + 'if': 'IF', + 'fi': 'FI', + 'else': 'ELSE', + 'true': 'TRUE', + 'false': 'FALSE', + 'class': 'CLASS', + 'inherits': 'INHERITS', + 'then': 'THEN', + 'while': 'WHILE', + 'loop': 'LOOP', + 'pool': 'POOL', + 'let': 'LET', + 'in': 'IN', + 'case': 'CASE', + 'isvoid': 'ISVOID', + 'esac': 'ESAC', + 'new': 'NEW', + 'of': 'OF', + 'not': 'LNOT' +} + +literals = [';', '{', '}', '(', ')', ':', '@', '.', '>', '<', '=', '+', '-', '*', '/', '~'] + +tokens += list(reserved.values()) + +# Regular expression rules for simple tokens +t_ASSIGN = r'<-' +t_ARROW = r'=>' +t_GREATHEREQ = r'>=' +t_LOWEREQ = r'<=' +t_STRING = r'".*"' +t_TYPE = r'[A-Z]+([a-z]|[A-Z]|[0-9]|_)*' + +t_ignore = ' \t' + + +def t_INT(t): + r'[1-9]+[0-9]*' + t.value = int(t.value) + return t + + +def t_ID(t): + r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' + t.type = reserved.get(t.value, 'ID') + t.type = reserved.get(t.value, 'ID') + return t + + +def t_error(t): + print(f'({lex.lexpos}:{find_column(t)}) LexicographicError: illegal token {t.value[0]}') + t.lexer.skip(1) + + +def t_newline(t): + r'\n+' + t.lexer.lineno += len(t.value) + + +def find_column(token): + line_start = lexer.lexdata.rfind('\n', 0, token.lexpos) + 1 + return (token.lexpos - line_start) + 1 + + +def test(data): + lexer.input(data) + while True: + tok = lexer.token() + if not tok: + break + print(tok) + + +lexer = lex.lex() From fa05a97938efa69b3c3b20ceba644511fe833bbe Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 13:54:01 -0500 Subject: [PATCH 004/435] Initial declaration of parser --- src/parser.py | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 src/parser.py diff --git a/src/parser.py b/src/parser.py new file mode 100644 index 00000000..2bd199d7 --- /dev/null +++ b/src/parser.py @@ -0,0 +1,196 @@ +import ply.yacc as yacc +from src.lexer import tokens + + +def p_program(p): + 'program : class_list' + pass + + +def p_empty(p): + 'empty :' + pass + + +def p_class_list(p): + '''class_list : def_class ; class_list + | def_class ;''' + pass + + +def p_def_class(p): + '''dedf_class : CLASS TYPE { feature_list } + | CLASS TYPE INHERITS TYPE { feature_list }''' + pass + + +def p_feature_list(p): + '''feature_list : def_attr ; feature_list + | def_function ; feature_list + | empty''' + + +def p_def_attr(p): + '''def_attr : assign_elem''' + pass + + +def p_def_func(p): + '''def_func : ID ( param_list ) : TYPE { expr_list }''' + pass + + +def p_param_list(p): + '''param_list : param , param_list + | param + | empty''' + pass + + +def p_param(p): + '''param : ID : TYPE''' + pass + + +def p_expr_list(p): + '''expr_list : expr expr_list + | expr''' + pass + + +def p_assign(p): + '''assign : ID <- expr''' + pass + + +def p_func_call(p): + '''func_call : expr @ TYPE . ID ( arg_list ) + | expr . ID ( arg_list ) + | ID ( arg_list )''' + + +def p_arg_list(p): + '''arg_list : expr , arg_list + | expr + | empty''' + pass + + +def p_if_expr(p): + '''if_expr : IF expr THEN expr ELSE expr FI''' + pass + + +def p_loop_expr(p): + '''loop_expr : WHILE expr LOOP expr POOL''' + pass + + +def p_block(p): + '''block : { block_list }''' + pass + + +def p_block_list(p): + '''block_list : expr ; block_list + | expr ;''' + pass + + +def p_let_expr(p): + '''let_expr : LET assign_list IN expr''' + pass + + +def p_assign_list(p): + '''assign_list : assign_elem , assign_list + | assign_elem''' + pass + + +def p_assign_elem(p): + '''assign_elem : ID : TYPE assign_oper''' + pass + + +def p_assign_oper(p): + '''assign_oper : <- expr + | empty''' + pass + + +def p_case_expr(p): + '''case_expr : CASE expr OF case_list ESAC''' + pass + + +def p_case_list(p): + '''case_list : case_elem ; case_list + | case_elem ;''' + pass + + +def p_case_elem(p): + '''case_elem : ID : TYPE => expr''' + pass + + +def p_init_expr(p): + '''init_expr : NEW TYPE''' + pass + + +def p_expr(p): + '''expr : NOT expr + | cmp + | e''' + pass + + +def p_cmp(p): + '''cmp : e > e + | e < e + | e = e + | e >= e + | e <= e''' + pass + + +def p_e(p): + '''e : e + t + | e - t + | t''' + pass + + +def p_t(p): + '''t : t * f + | t / f + | f''' + pass + + +def p_f(p): + '''f : ~ f + | ( expr ) + | atom + | ISVOID f''' + pass + + +def p_atom(p): + '''atom : ID + | INT + | TRUE + | FALSE + | STRING + | assign + | func_call + | if_expr + | loop_expr + | block + | let_expr + | case_expr + | init_expr + | is_void_expr''' + pass From e67569232271c94630fc30d3680b41894c94d2ec Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 14:29:25 -0500 Subject: [PATCH 005/435] Add initial configurations and test workflow for lexer --- src/__init__.py | 0 src/coolc.sh | 5 +++-- src/main.py | 25 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/__init__.py create mode 100644 src/main.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/coolc.sh b/src/coolc.sh index 3088de4f..ae6cb356 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -4,8 +4,9 @@ INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips # Si su compilador no lo hace ya, aquí puede imprimir la información de contacto -echo "LINEA_CON_NOMBRE_Y_VERSION_DEL_COMPILADOR" # TODO: Recuerde cambiar estas -echo "Copyright (c) 2019: Nombre1, Nombre2, Nombre3" # TODO: líneas a los valores correctos +echo "COOL COMPILER 0.0v" +echo "Copyright (c) 2019: Isabella Maria Sierra Ponce, Adrian Tubal Paez Ruiz, Eric Martin Garcia" # Llamar al compilador echo "Compiling $INPUT_FILE into $OUTPUT_FILE" +python3 main.py $INPUT_FILE \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 00000000..e88a02c2 --- /dev/null +++ b/src/main.py @@ -0,0 +1,25 @@ +import lexer as lex +import sys + + +def exit_with_error(error): + print(f'CompilerError: {error}') + exit(1) + + +def main(): + if len(sys.argv) != 2: + exit_with_error("invalid number of arguments") + + input_data = "" + try: + with open(sys.argv[1]) as f: + input_data = f.read() + except FileNotFoundError: + exit_with_error(f'file {sys.argv[1]} not found') + + lex.test(input_data) + + +if __name__ == "__main__": + main() From 356e927c86b926cab0dfbcf17251fea5b5f814c5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 19:09:33 -0500 Subject: [PATCH 006/435] - Remove duplicated line - Fix error message on lexer --- src/lexer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 8887902d..eea0710b 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -59,12 +59,11 @@ def t_INT(t): def t_ID(t): r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' t.type = reserved.get(t.value, 'ID') - t.type = reserved.get(t.value, 'ID') return t def t_error(t): - print(f'({lex.lexpos}:{find_column(t)}) LexicographicError: illegal token {t.value[0]}') + print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: illegal token {t.value[0]}') t.lexer.skip(1) From ff00bdc0244dc92f73232cc8fde7c697a59278ca Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 18 Feb 2020 19:54:43 -0500 Subject: [PATCH 007/435] Lexer fixes: - Add ',' to literals - Int can be start with 0 - Change error message - Change token print on test method --- src/lexer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index eea0710b..a992d3a7 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -35,7 +35,7 @@ 'not': 'LNOT' } -literals = [';', '{', '}', '(', ')', ':', '@', '.', '>', '<', '=', '+', '-', '*', '/', '~'] +literals = [';', '{', '}', '(', ')', ':', '@', '.', '>', '<', '=', '+', '-', '*', '/', '~', ','] tokens += list(reserved.values()) @@ -51,7 +51,7 @@ def t_INT(t): - r'[1-9]+[0-9]*' + r'[0-9]+[0-9]*' t.value = int(t.value) return t @@ -63,7 +63,7 @@ def t_ID(t): def t_error(t): - print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: illegal token {t.value[0]}') + print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: ERROR \"{t.value[0]}\"') t.lexer.skip(1) @@ -83,7 +83,7 @@ def test(data): tok = lexer.token() if not tok: break - print(tok) + print(f'#{tok.lineno} {tok.type} {tok.value}') lexer = lex.lex() From e672a84957c81ff82553ea8194aeb36e6b137e1f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 18 Feb 2020 20:44:06 -0500 Subject: [PATCH 008/435] Ast firsts steps --- src/ast.py | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lexer.py | 2 +- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/ast.py diff --git a/src/ast.py b/src/ast.py new file mode 100644 index 00000000..ca0c1470 --- /dev/null +++ b/src/ast.py @@ -0,0 +1,101 @@ +class ProgramNode: + def __init__(self, def_class_nodes): + self.def_class_nodes=def_class_nodes + +class DefClassNode: + def __init__(self, type, feature_nodes, parent_type): #poner null# + self.type=type + self.parent_type=parent_type + self.feature_nodes=feature_nodes + +class FeatureNode: + pass + +class DefAttrNode(FeatureNode): + def __init__(self,id, type, expr): + self.id=id + self.type=type + self.expr=expr + +class DefFuncNode(FeatureNode): + def __init__(self, id, params, return_type, expressions): + self.id=id + self.params=params + self.return_type=return_type + self.expressions=expressions + +class AssignNode: + def __init__(self, id, expr, type): #poner null# + self.id=id + self.expr=expr + self.type=type + + +class FuncCallNode: + def __init__(self, object, type, id, expressions): + self.object=object + self.type=type + self.id=id + self.expressions=expressions + +class IfNode: + def __init__(self, if_expr, then_expr, else_expr): + self.if_expr=if_expr + self.then_expr=then_expr + self.else_expr=else_expr + + +class LoopNode: + def __init__(self, cond, body): + self.cond=cond + self.body=body + + +class BlockNode: + def __init__(self, expressions): + self.expressions=expressions + +class LetNode: + def __init__(self, assign_nodes, expr): + self.assign_nodes =assign_nodes + self.expr=expr + +class CaseNode: + def __init__(self, expr, ids): + self.expr=expr + self.ids=ids + +class InitNode: + def __init__(self, type): + self.type=type + +class ExpressionNode: + pass + +class ArithNode(ExpressionNode): + def __init__(self, lvalue, rvalue): + self.lvalue=lvalue + self.rvalue=rvalue + + +class PlusNode(ArithNode): + pass + +class MinusNode(ArithNode): + pass + +class StarNode(ArithNode): + pass + +class DivNOde(ArithNode): + pass + +class UnaryNode(ExpressionNode): + def __init__(self, val): + self.val=val + +class NegationNode(UnaryNode): + pass + +class AtomNode(UnaryNode): + pass \ No newline at end of file diff --git a/src/lexer.py b/src/lexer.py index 8887902d..572cf19c 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -42,7 +42,7 @@ # Regular expression rules for simple tokens t_ASSIGN = r'<-' t_ARROW = r'=>' -t_GREATHEREQ = r'>=' +t_GREATEREQ = r'>=' t_LOWEREQ = r'<=' t_STRING = r'".*"' t_TYPE = r'[A-Z]+([a-z]|[A-Z]|[0-9]|_)*' From 5e2fbaafe7efecbf187e6dd8f613a2ff7c13ad63 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 19 Feb 2020 10:41:04 -0500 Subject: [PATCH 009/435] stupid NOde --- src/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast.py b/src/ast.py index ca0c1470..5189f006 100644 --- a/src/ast.py +++ b/src/ast.py @@ -87,7 +87,7 @@ class MinusNode(ArithNode): class StarNode(ArithNode): pass -class DivNOde(ArithNode): +class DivNode(ArithNode): pass class UnaryNode(ExpressionNode): From 75f11c2e36d40988ee11ae423c99467fc2f9a3af Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 19 Feb 2020 11:23:19 -0500 Subject: [PATCH 010/435] atributando la gramatica --- src/ast.py | 17 +++++++--- src/parser.py | 88 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 29 deletions(-) diff --git a/src/ast.py b/src/ast.py index 5189f006..285b1ca1 100644 --- a/src/ast.py +++ b/src/ast.py @@ -32,11 +32,11 @@ def __init__(self, id, expr, type): #poner null# class FuncCallNode: - def __init__(self, object, type, id, expressions): + def __init__(self, object, type, id, args): self.object=object self.type=type self.id=id - self.expressions=expressions + self.args=args class IfNode: def __init__(self, if_expr, then_expr, else_expr): @@ -59,11 +59,18 @@ class LetNode: def __init__(self, assign_nodes, expr): self.assign_nodes =assign_nodes self.expr=expr - + class CaseNode: - def __init__(self, expr, ids): + def __init__(self, expr, case_list): + self.expr=expr + self.case_list=case_list + +class CaseElemNode: + def __init__(self, expr, id, type): self.expr=expr - self.ids=ids + self.id=id + self.type=type + class InitNode: def __init__(self, type): diff --git a/src/parser.py b/src/parser.py index 2bd199d7..71957931 100644 --- a/src/parser.py +++ b/src/parser.py @@ -1,10 +1,11 @@ import ply.yacc as yacc from src.lexer import tokens +import src.ast as ast def p_program(p): 'program : class_list' - pass + p[0]= ast.ProgramNode(p[1]) def p_empty(p): @@ -15,136 +16,170 @@ def p_empty(p): def p_class_list(p): '''class_list : def_class ; class_list | def_class ;''' - pass + try: + p[0]=[p[1]]+p[3] + except: + p[0]=[p[1]] def p_def_class(p): '''dedf_class : CLASS TYPE { feature_list } | CLASS TYPE INHERITS TYPE { feature_list }''' - pass - + try: + p[0]=ast.DefClassNode(p[2], p[6], p[4]) + except: + p[0]=ast.DefClassNode(p[2], p[4]) + def p_feature_list(p): '''feature_list : def_attr ; feature_list | def_function ; feature_list | empty''' + try: + p[0]=[p[1]]+p[3] + except: + p[0]=[] def p_def_attr(p): '''def_attr : assign_elem''' - pass + p[0]=ast.DefAttrNode(p[1]) def p_def_func(p): '''def_func : ID ( param_list ) : TYPE { expr_list }''' - pass + p[0]=ast.DefFuncNode(p[1], p[3], p[6], p[8]) def p_param_list(p): '''param_list : param , param_list | param | empty''' - pass + #:( aqui no se como manejar la diferencia entre las ultimas dos producciones# def p_param(p): '''param : ID : TYPE''' - pass + p[0]=(p[1], p[3]) def p_expr_list(p): '''expr_list : expr expr_list | expr''' - pass + try: + p[0]=[p[1]]+p[2] + except: + p[0]=[p[1]] def p_assign(p): '''assign : ID <- expr''' - pass + p[0]=ast.AssignNode(p[1], p[3]) def p_func_call(p): '''func_call : expr @ TYPE . ID ( arg_list ) | expr . ID ( arg_list ) - | ID ( arg_list )''' + | ID ( arg_list )''' + try: + p[0]=ast.FuncCallNode(p[1], p[3], p[5], p[7]) + except: + try: + p[0]=ast.FuncCallNode(p[1], null, p[3], p[5]) + except: + p[0]=ast.FuncCallNode(null, null, p[1], p[3]) + def p_arg_list(p): '''arg_list : expr , arg_list | expr | empty''' + #aqui me pasa lo mismo que con el de arriba# pass def p_if_expr(p): '''if_expr : IF expr THEN expr ELSE expr FI''' - pass + p[0]=ast.IfNode(p[2], p[4], p[6]) def p_loop_expr(p): '''loop_expr : WHILE expr LOOP expr POOL''' - pass + p[0]=ast.LoopNode(p[2], p[4]) def p_block(p): '''block : { block_list }''' - pass + p[0]=p[2] def p_block_list(p): '''block_list : expr ; block_list | expr ;''' - pass + try: + p[0]=[p[1]]+p[3] + except: + p[0]=[p[1]] def p_let_expr(p): '''let_expr : LET assign_list IN expr''' - pass + p[0]=ast.LetNode(p[2], p[4]) def p_assign_list(p): '''assign_list : assign_elem , assign_list | assign_elem''' - pass + try: + p[0]=[p[1]]+p[3] + except: + p[0]=[p[1]] def p_assign_elem(p): '''assign_elem : ID : TYPE assign_oper''' - pass + p[0]=(p[1], p[4], p[3]) def p_assign_oper(p): '''assign_oper : <- expr | empty''' - pass + try: + p[0]=p[2] + except: + p[0]=null def p_case_expr(p): '''case_expr : CASE expr OF case_list ESAC''' - pass + p[0]=ast.CaseNode(p[2], p[4]) def p_case_list(p): '''case_list : case_elem ; case_list | case_elem ;''' - pass + try: + p[0]=[p[1]]+p[3] + except: + p[0]=[p[1]] def p_case_elem(p): '''case_elem : ID : TYPE => expr''' - pass + p[0]=ast.CaseElemNode(p[5], p[1], p[3]) def p_init_expr(p): '''init_expr : NEW TYPE''' - pass + p[0]=ast.InitNode(p[2]) def p_expr(p): '''expr : NOT expr | cmp | e''' - pass + #no se separar# def p_cmp(p): @@ -153,6 +188,7 @@ def p_cmp(p): | e = e | e >= e | e <= e''' + #no se separar# pass @@ -160,6 +196,7 @@ def p_e(p): '''e : e + t | e - t | t''' + #no se separar# pass @@ -167,6 +204,7 @@ def p_t(p): '''t : t * f | t / f | f''' + #no se separar# pass @@ -175,6 +213,7 @@ def p_f(p): | ( expr ) | atom | ISVOID f''' + #no se separar# pass @@ -193,4 +232,5 @@ def p_atom(p): | case_expr | init_expr | is_void_expr''' + #no se separar en la vida# pass From 2761eb19daa3ba09c70426769928154965b7b382 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 13:34:40 -0500 Subject: [PATCH 011/435] Refactor code on parser.py --- src/parser.py | 83 +++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/parser.py b/src/parser.py index 71957931..92f4401d 100644 --- a/src/parser.py +++ b/src/parser.py @@ -5,7 +5,7 @@ def p_program(p): 'program : class_list' - p[0]= ast.ProgramNode(p[1]) + p[0] = ast.ProgramNode(p[1]) def p_empty(p): @@ -17,38 +17,38 @@ def p_class_list(p): '''class_list : def_class ; class_list | def_class ;''' try: - p[0]=[p[1]]+p[3] + p[0] = [p[1]] + p[3] except: - p[0]=[p[1]] + p[0] = [p[1]] def p_def_class(p): '''dedf_class : CLASS TYPE { feature_list } | CLASS TYPE INHERITS TYPE { feature_list }''' try: - p[0]=ast.DefClassNode(p[2], p[6], p[4]) + p[0] = ast.DefClassNode(p[2], p[6], p[4]) except: - p[0]=ast.DefClassNode(p[2], p[4]) - + p[0] = ast.DefClassNode(p[2], p[4]) + def p_feature_list(p): '''feature_list : def_attr ; feature_list | def_function ; feature_list | empty''' try: - p[0]=[p[1]]+p[3] + p[0] = [p[1]] + p[3] except: - p[0]=[] + p[0] = [] def p_def_attr(p): '''def_attr : assign_elem''' - p[0]=ast.DefAttrNode(p[1]) + p[0] = ast.DefAttrNode(p[1]) def p_def_func(p): '''def_func : ID ( param_list ) : TYPE { expr_list }''' - p[0]=ast.DefFuncNode(p[1], p[3], p[6], p[8]) + p[0] = ast.DefFuncNode(p[1], p[3], p[6], p[8]) def p_param_list(p): @@ -60,126 +60,125 @@ def p_param_list(p): def p_param(p): '''param : ID : TYPE''' - p[0]=(p[1], p[3]) + p[0] = (p[1], p[3]) def p_expr_list(p): '''expr_list : expr expr_list | expr''' try: - p[0]=[p[1]]+p[2] + p[0] = [p[1]] + p[2] except: - p[0]=[p[1]] + p[0] = [p[1]] def p_assign(p): '''assign : ID <- expr''' - p[0]=ast.AssignNode(p[1], p[3]) + p[0] = ast.AssignNode(p[1], p[3]) def p_func_call(p): '''func_call : expr @ TYPE . ID ( arg_list ) | expr . ID ( arg_list ) - | ID ( arg_list )''' + | ID ( arg_list )''' try: - p[0]=ast.FuncCallNode(p[1], p[3], p[5], p[7]) + p[0] = ast.FuncCallNode(p[1], p[3], p[5], p[7]) except: try: - p[0]=ast.FuncCallNode(p[1], null, p[3], p[5]) + p[0] = ast.FuncCallNode(p[1], null, p[3], p[5]) except: - p[0]=ast.FuncCallNode(null, null, p[1], p[3]) - + p[0] = ast.FuncCallNode(null, null, p[1], p[3]) def p_arg_list(p): '''arg_list : expr , arg_list | expr | empty''' - #aqui me pasa lo mismo que con el de arriba# + # aqui me pasa lo mismo que con el de arriba# pass def p_if_expr(p): '''if_expr : IF expr THEN expr ELSE expr FI''' - p[0]=ast.IfNode(p[2], p[4], p[6]) + p[0] = ast.IfNode(p[2], p[4], p[6]) def p_loop_expr(p): '''loop_expr : WHILE expr LOOP expr POOL''' - p[0]=ast.LoopNode(p[2], p[4]) + p[0] = ast.LoopNode(p[2], p[4]) def p_block(p): '''block : { block_list }''' - p[0]=p[2] + p[0] = p[2] def p_block_list(p): '''block_list : expr ; block_list | expr ;''' try: - p[0]=[p[1]]+p[3] + p[0] = [p[1]] + p[3] except: - p[0]=[p[1]] + p[0] = [p[1]] def p_let_expr(p): '''let_expr : LET assign_list IN expr''' - p[0]=ast.LetNode(p[2], p[4]) + p[0] = ast.LetNode(p[2], p[4]) def p_assign_list(p): '''assign_list : assign_elem , assign_list | assign_elem''' try: - p[0]=[p[1]]+p[3] + p[0] = [p[1]] + p[3] except: - p[0]=[p[1]] + p[0] = [p[1]] def p_assign_elem(p): '''assign_elem : ID : TYPE assign_oper''' - p[0]=(p[1], p[4], p[3]) + p[0] = (p[1], p[4], p[3]) def p_assign_oper(p): '''assign_oper : <- expr | empty''' try: - p[0]=p[2] + p[0] = p[2] except: - p[0]=null + p[0] = null def p_case_expr(p): '''case_expr : CASE expr OF case_list ESAC''' - p[0]=ast.CaseNode(p[2], p[4]) + p[0] = ast.CaseNode(p[2], p[4]) def p_case_list(p): '''case_list : case_elem ; case_list | case_elem ;''' try: - p[0]=[p[1]]+p[3] + p[0] = [p[1]] + p[3] except: - p[0]=[p[1]] + p[0] = [p[1]] def p_case_elem(p): '''case_elem : ID : TYPE => expr''' - p[0]=ast.CaseElemNode(p[5], p[1], p[3]) + p[0] = ast.CaseElemNode(p[5], p[1], p[3]) def p_init_expr(p): '''init_expr : NEW TYPE''' - p[0]=ast.InitNode(p[2]) + p[0] = ast.InitNode(p[2]) def p_expr(p): '''expr : NOT expr | cmp | e''' - #no se separar# + # no se separar# def p_cmp(p): @@ -188,7 +187,7 @@ def p_cmp(p): | e = e | e >= e | e <= e''' - #no se separar# + # no se separar# pass @@ -196,7 +195,7 @@ def p_e(p): '''e : e + t | e - t | t''' - #no se separar# + # no se separar# pass @@ -204,7 +203,7 @@ def p_t(p): '''t : t * f | t / f | f''' - #no se separar# + # no se separar# pass @@ -213,7 +212,7 @@ def p_f(p): | ( expr ) | atom | ISVOID f''' - #no se separar# + # no se separar# pass @@ -232,5 +231,5 @@ def p_atom(p): | case_expr | init_expr | is_void_expr''' - #no se separar en la vida# + # no se separar en la vida# pass From 91a40493363d79693c372f5064d2d95e929b0b16 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 13:35:06 -0500 Subject: [PATCH 012/435] - Remove GREATER from tokens --- src/lexer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 72ea3d5f..ac22d7d0 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -4,8 +4,7 @@ tokens = [ 'ASSIGN', 'ARROW', - 'GREATHER', - 'GREATHEREQ', + 'GREATEREQ', 'LOWEREQ', 'INT', 'STRING', From d529305009bbccb30773b59b9a9bce45a63b3eec Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 19 Feb 2020 14:20:38 -0500 Subject: [PATCH 013/435] handling differences without exception catching --- src/ast.py | 25 ++++++++++++++++---- src/parser.py | 65 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/ast.py b/src/ast.py index 285b1ca1..f26a2e12 100644 --- a/src/ast.py +++ b/src/ast.py @@ -79,22 +79,37 @@ def __init__(self, type): class ExpressionNode: pass -class ArithNode(ExpressionNode): +class BinaryNode(ExpressionNode): def __init__(self, lvalue, rvalue): self.lvalue=lvalue self.rvalue=rvalue -class PlusNode(ArithNode): +class PlusNode(BinaryNode): pass -class MinusNode(ArithNode): +class MinusNode(BinaryNode): pass -class StarNode(ArithNode): +class StarNode(BinaryNode): pass -class DivNode(ArithNode): +class DivNode(BinaryNode): + pass + +class GreaterThanNode(BinaryNode): + pass + +class LessThanNode(BinaryNode): + pass + +class GreaterEqNode(BinaryNode): + pass + +class LessEqNode(BinaryNode): + pass + +class EqNode(BinaryNode): pass class UnaryNode(ExpressionNode): diff --git a/src/parser.py b/src/parser.py index 92f4401d..1d0a149f 100644 --- a/src/parser.py +++ b/src/parser.py @@ -1,5 +1,5 @@ import ply.yacc as yacc -from src.lexer import tokens +import src.lexer import src.ast as ast @@ -16,18 +16,18 @@ def p_empty(p): def p_class_list(p): '''class_list : def_class ; class_list | def_class ;''' - try: + if len(p)==4: p[0] = [p[1]] + p[3] - except: + else: p[0] = [p[1]] def p_def_class(p): '''dedf_class : CLASS TYPE { feature_list } | CLASS TYPE INHERITS TYPE { feature_list }''' - try: + if len(p)==7: p[0] = ast.DefClassNode(p[2], p[6], p[4]) - except: + else: p[0] = ast.DefClassNode(p[2], p[4]) @@ -35,9 +35,9 @@ def p_feature_list(p): '''feature_list : def_attr ; feature_list | def_function ; feature_list | empty''' - try: + if len(p)==4: p[0] = [p[1]] + p[3] - except: + else: p[0] = [] @@ -66,9 +66,9 @@ def p_param(p): def p_expr_list(p): '''expr_list : expr expr_list | expr''' - try: + if len(p)==3: p[0] = [p[1]] + p[2] - except: + else: p[0] = [p[1]] @@ -81,13 +81,12 @@ def p_func_call(p): '''func_call : expr @ TYPE . ID ( arg_list ) | expr . ID ( arg_list ) | ID ( arg_list )''' - try: + if len(p)==9: p[0] = ast.FuncCallNode(p[1], p[3], p[5], p[7]) - except: - try: - p[0] = ast.FuncCallNode(p[1], null, p[3], p[5]) - except: - p[0] = ast.FuncCallNode(null, null, p[1], p[3]) + elif len(p)==7: + p[0] = ast.FuncCallNode(p[1], null, p[3], p[5]) + else: + p[0] = ast.FuncCallNode(null, null, p[1], p[3]) def p_arg_list(p): @@ -116,9 +115,9 @@ def p_block(p): def p_block_list(p): '''block_list : expr ; block_list | expr ;''' - try: + if len(p)==4: p[0] = [p[1]] + p[3] - except: + else: p[0] = [p[1]] @@ -130,9 +129,9 @@ def p_let_expr(p): def p_assign_list(p): '''assign_list : assign_elem , assign_list | assign_elem''' - try: + if len(p)==4: p[0] = [p[1]] + p[3] - except: + else: p[0] = [p[1]] @@ -144,9 +143,9 @@ def p_assign_elem(p): def p_assign_oper(p): '''assign_oper : <- expr | empty''' - try: + if len(p)==3: p[0] = p[2] - except: + else: p[0] = null @@ -158,9 +157,9 @@ def p_case_expr(p): def p_case_list(p): '''case_list : case_elem ; case_list | case_elem ;''' - try: + if len(p)==4: p[0] = [p[1]] + p[3] - except: + else: p[0] = [p[1]] @@ -187,15 +186,29 @@ def p_cmp(p): | e = e | e >= e | e <= e''' - # no se separar# - pass + if p[2]=='>': + p[0]=ast.GreaterThanNode(p[1], p[3]) + elif p[2]=='<': + p[0]=ast.LessThanNode(p[1], p[3]) + elif p[2]== t_GREATEREQ: + p[0]=ast.GreaterEqNode(p[1], p[3]) + elif p[2]==t_LOWEREQ: + p[0]=ast.LessEqNode(p[1], p[3]) + elif p[2]=='=': + p[0]=ast.EqNode(p[1], p[3]) def p_e(p): '''e : e + t | e - t | t''' - # no se separar# + if len(p)==2: + p[0]=p[1] + else: + if p[2]=='+': + p[0]=ast.PlusNode(p[1], p[3]) + elif p[2]=='-': + p[0]=ast.MinusNOde(p[1], p[3]) pass From a64a945d7303decfd9fdc36c52488fb0206ce35a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 19 Feb 2020 14:33:23 -0500 Subject: [PATCH 014/435] Almost solving previous freakout --- src/ast.py | 6 ++++++ src/parser.py | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/ast.py b/src/ast.py index f26a2e12..48cd33f5 100644 --- a/src/ast.py +++ b/src/ast.py @@ -119,5 +119,11 @@ def __init__(self, val): class NegationNode(UnaryNode): pass +class LogicNegationNode(UnaryNode): + pass + class AtomNode(UnaryNode): + pass + +class IsVoidNode(UnaryNode): pass \ No newline at end of file diff --git a/src/parser.py b/src/parser.py index 1d0a149f..c3e538fb 100644 --- a/src/parser.py +++ b/src/parser.py @@ -55,7 +55,10 @@ def p_param_list(p): '''param_list : param , param_list | param | empty''' - #:( aqui no se como manejar la diferencia entre las ultimas dos producciones# + if len(p)==4: + p[0]=[p[1]]+p[3] + else: + #problemita aun, las empty se cuentan como que tienen len=2?? def p_param(p): @@ -93,8 +96,10 @@ def p_arg_list(p): '''arg_list : expr , arg_list | expr | empty''' - # aqui me pasa lo mismo que con el de arriba# - pass + if len(p)==4: + p[0]=[p[1]]+p[3] + else: + #problemita aun, las empty se cuentan como que tienen len=2?? def p_if_expr(p): @@ -177,7 +182,10 @@ def p_expr(p): '''expr : NOT expr | cmp | e''' - # no se separar# + if len(p)==3: + p[0]=ast.LogicNegationNode(p[2]) + else: + p[0]=p[1] def p_cmp(p): @@ -209,14 +217,19 @@ def p_e(p): p[0]=ast.PlusNode(p[1], p[3]) elif p[2]=='-': p[0]=ast.MinusNOde(p[1], p[3]) - pass def p_t(p): '''t : t * f | t / f | f''' - # no se separar# + if len(p)==2: + p[0]=p[1] + else: + if p[2]=='*': + p[0]=ast.StarNode(p[1], p[3]) + elif p[2]=='/': + p[0]=ast.DivNode(p[1], p[3]) pass @@ -225,7 +238,15 @@ def p_f(p): | ( expr ) | atom | ISVOID f''' - # no se separar# + if len(p)==4: + p[0]=p[2] + if len(p)==3: + if p[1]=='~': + p[0]=ast.NegationNode(p[2]) + if p[1]=='ISVOID': + p[0]=ast.IsVoidNode(p[2]) + else: + p[0]=p[1] pass @@ -242,7 +263,5 @@ def p_atom(p): | block | let_expr | case_expr - | init_expr - | is_void_expr''' - # no se separar en la vida# - pass + | init_expr''' + p[0]=ast.AtomNode(p[1]) From 5c459f711398c123d6d29f28d86c7e39c15d9adc Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 19 Feb 2020 15:15:48 -0500 Subject: [PATCH 015/435] adding CommentLine to lexer --- src/lexer.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/lexer.py b/src/lexer.py index ac22d7d0..196cd762 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -48,12 +48,29 @@ t_ignore = ' \t' +states = (('commentLine','exclusive'),) def t_INT(t): r'[0-9]+[0-9]*' t.value = int(t.value) return t +def t_LINECOMMENT(t): + r'--' + if t.lexpos == 0 or t.lexer.lexdata[t.lexpos - 1] == '\n': + t.lexer.begin('commentLine') + else: + t_error(t) + +def t_commentLine_ALL(t): + r'.' + return None + +def t_commentLine_newline(t): + r'\n' + t.lexer.begin('INITIAL') + t.lexer.lineno =+ 1 + return None def t_ID(t): r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' From 793bf0ce3af381c81212d9814500539147a6e179 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 19 Feb 2020 15:15:48 -0500 Subject: [PATCH 016/435] adding CommentLine to lexer --- src/lexer.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/lexer.py b/src/lexer.py index ac22d7d0..196cd762 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -48,12 +48,29 @@ t_ignore = ' \t' +states = (('commentLine','exclusive'),) def t_INT(t): r'[0-9]+[0-9]*' t.value = int(t.value) return t +def t_LINECOMMENT(t): + r'--' + if t.lexpos == 0 or t.lexer.lexdata[t.lexpos - 1] == '\n': + t.lexer.begin('commentLine') + else: + t_error(t) + +def t_commentLine_ALL(t): + r'.' + return None + +def t_commentLine_newline(t): + r'\n' + t.lexer.begin('INITIAL') + t.lexer.lineno =+ 1 + return None def t_ID(t): r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' From 1f8656cd7e575d769ff284b8b96fd802280dbfde Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 15:43:49 -0500 Subject: [PATCH 017/435] Lexer: Add error and ignore to commentLine state --- src/lexer.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 196cd762..3b5a154f 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -48,13 +48,15 @@ t_ignore = ' \t' -states = (('commentLine','exclusive'),) +states = (('commentLine', 'exclusive'),) + def t_INT(t): r'[0-9]+[0-9]*' t.value = int(t.value) return t + def t_LINECOMMENT(t): r'--' if t.lexpos == 0 or t.lexer.lexdata[t.lexpos - 1] == '\n': @@ -62,15 +64,25 @@ def t_LINECOMMENT(t): else: t_error(t) + +t_commentLine_ignore = ' \t' + + +def t_commentLine_error(t): + t_error(t) + + def t_commentLine_ALL(t): r'.' return None + def t_commentLine_newline(t): r'\n' t.lexer.begin('INITIAL') - t.lexer.lineno =+ 1 - return None + t.lexer.lineno = + 1 + return None + def t_ID(t): r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' From 8b49778b7ad91520ec8f98a7e0d9b752ee13583b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 16:29:56 -0500 Subject: [PATCH 018/435] Adding Text Comments --- src/lexer.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 3b5a154f..6085ccb0 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -48,7 +48,10 @@ t_ignore = ' \t' -states = (('commentLine', 'exclusive'),) +states = ( + ('commentLine', 'exclusive'), + ('commentText', 'exclusive'), +) def t_INT(t): @@ -78,12 +81,52 @@ def t_commentLine_ALL(t): def t_commentLine_newline(t): - r'\n' + r'\n+' t.lexer.begin('INITIAL') - t.lexer.lineno = + 1 + t.lexer.lineno += len(t.value) return None +def t_TEXTCOMMENT(t): + r'\(\*' + t.lexer.comment_start = t.lexer.lexpos + t.lexer.level = 1 + t.lexer.begin('commentText') + + +t_commentText_ignore = ' \t' + + +def t_commentText_error(t): + t_error(t) + + +def t_commentText_OPENTEXT(t): + r'\(\*' + t.lexer.level += 1 + + +def t_commentText_CLOSETEXT(t): + r'\*\)' + t.lexer.level -= 1 + if t.lexer.level == 0: + t.lexer.begin('INITIAL') + + +def t_commentText_ALL(t): + r'.' + return None + + +def t_commentText_newline(t): + r'\n+' + t.lexer.lineno += len(t.value) + + +def t_commentText_eof(t): + print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: EOF in comment') + + def t_ID(t): r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' t.type = reserved.get(t.value, 'ID') @@ -91,7 +134,7 @@ def t_ID(t): def t_error(t): - print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: ERROR \"{t.value[0]}\"') + print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: ERROR \"{t.value[0]}\"') t.lexer.skip(1) From fde405ba10338305537379b40e795c543c597410 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 17:27:47 -0500 Subject: [PATCH 019/435] Adding string to Lexer --- src/lexer.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 6085ccb0..776b40ba 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -43,7 +43,6 @@ t_ARROW = r'=>' t_GREATEREQ = r'>=' t_LOWEREQ = r'<=' -t_STRING = r'".*"' t_TYPE = r'[A-Z]+([a-z]|[A-Z]|[0-9]|_)*' t_ignore = ' \t' @@ -51,6 +50,7 @@ states = ( ('commentLine', 'exclusive'), ('commentText', 'exclusive'), + ('string', 'exclusive'), ) @@ -124,7 +124,76 @@ def t_commentText_newline(t): def t_commentText_eof(t): - print(f'({t.lexer.lineno}:{find_column(t)}) LexicographicError: EOF in comment') + print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: EOF in comment') + + +def t_STRING(t): + r'"' + t.lexer.stringValue = "" + t.lexer.escape = False + t.lexer.begin('string') + + +t_string_ignore = '' + + +def t_string_ESCAPE(t): + r'\\' + if t.lexer.escape: + t.lexer.stringValue += "\\" + else: + t.lexer.escape = True + + +def t_string_CLOSESTRING(t): + r'"' + if t.lexer.escape: + t.lexer.stringValue += "\"" + else: + t.value = t.lexer.stringValue + t.lexer.stringValue = None + t.type = 'STRING' + t.lexer.begin('INITIAL') + return t + + +def t_string_eof(t): + print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: EOF in string constant') + + +def t_string_newline(t): + r'\n+' + if t.lexer.escape: + t.lexer.escape = False + else: + print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: Unterminated string constant') + t.lexer.begin('INITIAL') + t.lexer.lineno += len(t.value) + + +def t_string_ALL(t): + r'.' + if t.lexer.escape: + x = { + "b": "\b", + "t": "\t", + "n": "\n", + "f": "\f" + } + if t.value in x.keys(): + t.lexer.stringValue += x[t.value] + elif t.value == "0": + print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: String contains null character') + t.lexer.begin('INITIAL') + else: + t.lexer.stringValue += t.value + t.lexer.escape = False + else: + t.lexer.stringValue += t.value + + +def t_string_error(t): + t_error(t) def t_ID(t): From de715662f574645b8542a70d35c235c12644cb09 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 19 Feb 2020 19:06:52 -0500 Subject: [PATCH 020/435] Add lexer error message builder --- src/lexer.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 776b40ba..e80f08bc 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -1,5 +1,10 @@ import ply.lex as lex + +def printLexicograficError(error, token): + print(f'({token.lexer.lineno}, {find_column(token)}) - LexicographicError: {error}') + + # List of token names. This is always required tokens = [ 'ASSIGN', @@ -158,7 +163,7 @@ def t_string_CLOSESTRING(t): def t_string_eof(t): - print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: EOF in string constant') + printLexicograficError("EOF in string constant", t) def t_string_newline(t): @@ -203,7 +208,7 @@ def t_ID(t): def t_error(t): - print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: ERROR \"{t.value[0]}\"') + printLexicograficError(f'ERROR \"{t.value[0]}\"', t) t.lexer.skip(1) From 193fafba0745457c69ba2dea5aaec707bd7b883f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 20 Feb 2020 14:02:44 -0500 Subject: [PATCH 021/435] error and test --- src/main.py | 3 ++- src/parser.py | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index e88a02c2..f4e34128 100644 --- a/src/main.py +++ b/src/main.py @@ -1,4 +1,5 @@ import lexer as lex +import parser import sys @@ -18,7 +19,7 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - lex.test(input_data) + parser.test(input_data) if __name__ == "__main__": diff --git a/src/parser.py b/src/parser.py index c3e538fb..7ce4f5cd 100644 --- a/src/parser.py +++ b/src/parser.py @@ -3,6 +3,18 @@ import src.ast as ast +precedence=( + ('left','.'), + ('left','@'), + ('left','~'), + ('left','isvoid'), + ('left', '*', '/'), + ('left', '+', '-'), + ('left',t_GREATREQ,t_LOWEREQ,'<', '>', '='), + ('left', 'not'), + ('right', t_ASSIGN), +) + def p_program(p): 'program : class_list' p[0] = ast.ProgramNode(p[1]) @@ -10,7 +22,7 @@ def p_program(p): def p_empty(p): 'empty :' - pass + p[0]=null def p_class_list(p): @@ -58,7 +70,7 @@ def p_param_list(p): if len(p)==4: p[0]=[p[1]]+p[3] else: - #problemita aun, las empty se cuentan como que tienen len=2?? + p[0]=[p[1]] def p_param(p): @@ -96,12 +108,11 @@ def p_arg_list(p): '''arg_list : expr , arg_list | expr | empty''' - if len(p)==4: + if len(p)==4: p[0]=[p[1]]+p[3] else: - #problemita aun, las empty se cuentan como que tienen len=2?? - - + p[0]=[p[1]] + def p_if_expr(p): '''if_expr : IF expr THEN expr ELSE expr FI''' p[0] = ast.IfNode(p[2], p[4], p[6]) @@ -265,3 +276,17 @@ def p_atom(p): | case_expr | init_expr''' p[0]=ast.AtomNode(p[1]) + +def p_error(p): + if p: + line=p.lineno(0) + pos=p.lexpos(0) + print(f'({line}, {pos}) - SyntacticError: ERROR at or near \"{p.value[0]}\"') + else: + print('EOF') + + +def test(input_data): + parser.parse(input_data) + +parser=yacc.yacc() From 6a5d32b29793b97641326e76e3aa5f818f6fd56e Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 20 Feb 2020 14:26:15 -0500 Subject: [PATCH 022/435] fixing stupid little things --- src/parser.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/parser.py b/src/parser.py index 7ce4f5cd..6b501ae9 100644 --- a/src/parser.py +++ b/src/parser.py @@ -1,18 +1,18 @@ import ply.yacc as yacc -import src.lexer -import src.ast as ast +from lexer import * +import ast precedence=( ('left','.'), ('left','@'), ('left','~'), - ('left','isvoid'), + ('left','ISVOID'), ('left', '*', '/'), ('left', '+', '-'), - ('left',t_GREATREQ,t_LOWEREQ,'<', '>', '='), + ('left','GREATREQ', 'LOWEREQ','<', '>', '='), ('left', 'not'), - ('right', t_ASSIGN), + ('right', 'ASSIGN'), ) def p_program(p): @@ -209,9 +209,9 @@ def p_cmp(p): p[0]=ast.GreaterThanNode(p[1], p[3]) elif p[2]=='<': p[0]=ast.LessThanNode(p[1], p[3]) - elif p[2]== t_GREATEREQ: + elif p[2]== 'GREATEREQ': p[0]=ast.GreaterEqNode(p[1], p[3]) - elif p[2]==t_LOWEREQ: + elif p[2]=='LOWEREQ': p[0]=ast.LessEqNode(p[1], p[3]) elif p[2]=='=': p[0]=ast.EqNode(p[1], p[3]) From 72288e02e05f25a4f1a8b97d36da7bd824b930a2 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 20 Feb 2020 14:48:47 -0500 Subject: [PATCH 023/435] this.null=none --- src/ast.py | 2 +- src/parser.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ast.py b/src/ast.py index 48cd33f5..8d0975ce 100644 --- a/src/ast.py +++ b/src/ast.py @@ -32,7 +32,7 @@ def __init__(self, id, expr, type): #poner null# class FuncCallNode: - def __init__(self, object, type, id, args): + def __init__(self, id, args,object=None, type=None): self.object=object self.type=type self.id=id diff --git a/src/parser.py b/src/parser.py index 6b501ae9..da10b027 100644 --- a/src/parser.py +++ b/src/parser.py @@ -22,7 +22,7 @@ def p_program(p): def p_empty(p): 'empty :' - p[0]=null + p[0]=None def p_class_list(p): @@ -99,9 +99,9 @@ def p_func_call(p): if len(p)==9: p[0] = ast.FuncCallNode(p[1], p[3], p[5], p[7]) elif len(p)==7: - p[0] = ast.FuncCallNode(p[1], null, p[3], p[5]) + p[0] = ast.FuncCallNode(p[3], p[5], p[1]) else: - p[0] = ast.FuncCallNode(null, null, p[1], p[3]) + p[0] = ast.FuncCallNode(p[1], p[3]) def p_arg_list(p): @@ -162,7 +162,7 @@ def p_assign_oper(p): if len(p)==3: p[0] = p[2] else: - p[0] = null + p[0] = None def p_case_expr(p): From fa0eb24b894baa46747a4f95b210b0028573180f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 21 Feb 2020 11:54:21 -0500 Subject: [PATCH 024/435] - Clean Lexer - Add error.py file - Add utils.py file --- src/errors.py | 6 ++ src/lexer.py | 231 ++++++++++++++++++++++++-------------------------- src/main.py | 3 + src/utils.py | 3 + 4 files changed, 121 insertions(+), 122 deletions(-) create mode 100644 src/errors.py create mode 100644 src/utils.py diff --git a/src/errors.py b/src/errors.py new file mode 100644 index 00000000..df19703e --- /dev/null +++ b/src/errors.py @@ -0,0 +1,6 @@ +LEXER_ERRORS = [] +PARSER_ERRORS = [] + + +def add_lexer_error(line, column, message): + LEXER_ERRORS.append(f'({line}, {column}) - LexicographicError: {message}') diff --git a/src/lexer.py b/src/lexer.py index e80f08bc..af5a7304 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -1,31 +1,20 @@ import ply.lex as lex +from utils import * +from errors import add_lexer_error - -def printLexicograficError(error, token): - print(f'({token.lexer.lineno}, {find_column(token)}) - LexicographicError: {error}') - - -# List of token names. This is always required -tokens = [ - 'ASSIGN', - 'ARROW', - 'GREATEREQ', - 'LOWEREQ', - 'INT', - 'STRING', - 'TYPE', - 'ID' -] +states = ( + ('commentLine', 'exclusive'), + ('commentText', 'exclusive'), + ('string', 'exclusive'), +) reserved = { 'if': 'IF', - 'fi': 'FI', + 'then': 'THEN', 'else': 'ELSE', - 'true': 'TRUE', - 'false': 'FALSE', + 'fi': 'FI', 'class': 'CLASS', 'inherits': 'INHERITS', - 'then': 'THEN', 'while': 'WHILE', 'loop': 'LOOP', 'pool': 'POOL', @@ -39,71 +28,120 @@ def printLexicograficError(error, token): 'not': 'LNOT' } -literals = [';', '{', '}', '(', ')', ':', '@', '.', '>', '<', '=', '+', '-', '*', '/', '~', ','] - -tokens += list(reserved.values()) +tokens = [ + 'ASSIGN', + 'ARROW', + 'GREATEREQ', + 'LOWEREQ', + 'INT', + 'STRING', + 'TYPE', + 'ID', + 'SEMICOLON', + 'OBRACKET', + 'CBRACKET', + 'OPAREN', + 'CPAREN', + 'COLON', + 'AT', + 'DOT', + 'LOWER', + 'GREATER', + 'EQUAL', + 'PLUS', + 'MINUS', + 'STAR', + 'DIV', + 'NOT', + 'COMMA', + 'BOOL' +] -# Regular expression rules for simple tokens -t_ASSIGN = r'<-' -t_ARROW = r'=>' +t_SEMICOLON = r';' +t_OBRACKET = r'{' +t_CBRACKET = r'}' +t_OPAREN = r'\(' +t_CPAREN = r'\)' +t_COLON = r':' +t_AT = r'@' +t_DOT = r'\.' +t_LOWER = r'<' +t_GREATER = r'>' +t_EQUAL = r'=' t_GREATEREQ = r'>=' t_LOWEREQ = r'<=' +t_ASSIGN = r'<-' +t_ARROW = r'=>' +t_PLUS = r'\+' +t_MINUS = r'-' +t_STAR = r'\*' +t_DIV = r'/' +t_NOT = r'~' +t_COMMA = r',' t_TYPE = r'[A-Z]+([a-z]|[A-Z]|[0-9]|_)*' -t_ignore = ' \t' - -states = ( - ('commentLine', 'exclusive'), - ('commentText', 'exclusive'), - ('string', 'exclusive'), -) - def t_INT(t): - r'[0-9]+[0-9]*' + r'\d+' t.value = int(t.value) return t +def t_ID(t): + r'[a-z][a-zA-Z_0-9]*' + t.type = reserved.get(t.value, 'ID') + return t + + +def t_BOOL(t): + r'f[Aa][Ll][Ss][Ee]|t[Rr][Uu][Ee]' + t.value = (t.value.lower == 'true') + return t + + def t_LINECOMMENT(t): r'--' if t.lexpos == 0 or t.lexer.lexdata[t.lexpos - 1] == '\n': t.lexer.begin('commentLine') else: - t_error(t) + add_lexer_error(t.lexer.lineno, find_column(t.lexer.lexdata, t.lexer.lexpos), f'ERROR {t.value}') -t_commentLine_ignore = ' \t' +def t_TEXTCOMMENT(t): + r'\(\*' + t.lexer.comment_start = t.lexer.lexpos + t.lexer.level = 1 + t.lexer.begin('commentText') -def t_commentLine_error(t): - t_error(t) +def t_STRING(t): + r'"' + t.lexer.string_start = t.lexer.lexpos + t.lexer.begin('string') -def t_commentLine_ALL(t): - r'.' - return None +tokens += list(reserved.values()) + +t_ignore = ' \t' + +t_commentLine_ignore = ' \t' + + +def t_commentLine_error(t): + t.lexer.skip(1) def t_commentLine_newline(t): r'\n+' t.lexer.begin('INITIAL') t.lexer.lineno += len(t.value) - return None - - -def t_TEXTCOMMENT(t): - r'\(\*' - t.lexer.comment_start = t.lexer.lexpos - t.lexer.level = 1 - t.lexer.begin('commentText') t_commentText_ignore = ' \t' def t_commentText_error(t): - t_error(t) + t.lexer.skip(1) def t_commentText_OPENTEXT(t): @@ -118,97 +156,51 @@ def t_commentText_CLOSETEXT(t): t.lexer.begin('INITIAL') -def t_commentText_ALL(t): - r'.' - return None - - def t_commentText_newline(t): r'\n+' t.lexer.lineno += len(t.value) def t_commentText_eof(t): - print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: EOF in comment') - - -def t_STRING(t): - r'"' - t.lexer.stringValue = "" - t.lexer.escape = False - t.lexer.begin('string') + add_lexer_error(t.lexer.lineno, find_column(t.lexer.lexdata, t.lexer.lexpos), "EOF in comment") t_string_ignore = '' -def t_string_ESCAPE(t): - r'\\' - if t.lexer.escape: - t.lexer.stringValue += "\\" - else: - t.lexer.escape = True - - def t_string_CLOSESTRING(t): r'"' - if t.lexer.escape: - t.lexer.stringValue += "\"" - else: - t.value = t.lexer.stringValue - t.lexer.stringValue = None - t.type = 'STRING' - t.lexer.begin('INITIAL') - return t - - -def t_string_eof(t): - printLexicograficError("EOF in string constant", t) + t.value = t.lexer.lexdata[t.lexer.string_start:t.lexer.lexpos - 1] + t.type = 'STRING' + t.lexer.begin('INITIAL') + return t def t_string_newline(t): - r'\n+' - if t.lexer.escape: - t.lexer.escape = False - else: - print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: Unterminated string constant') - t.lexer.begin('INITIAL') - t.lexer.lineno += len(t.value) + r'\\\n' + t.lexer.lineno += 1 -def t_string_ALL(t): - r'.' - if t.lexer.escape: - x = { - "b": "\b", - "t": "\t", - "n": "\n", - "f": "\f" - } - if t.value in x.keys(): - t.lexer.stringValue += x[t.value] - elif t.value == "0": - print(f'({t.lexer.lineno}, {find_column(t)}) - LexicographicError: String contains null character') - t.lexer.begin('INITIAL') - else: - t.lexer.stringValue += t.value - t.lexer.escape = False - else: - t.lexer.stringValue += t.value +def t_string_body(t): + r'([^\n\"\\]|\\.)+' + if t.value.rfind('\0') != -1: + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "String contains null character") def t_string_error(t): - t_error(t) + if t.value[0] == '\n': + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "Unterminated string constant") + t.lexer.lineno += 1 + t.lexer.skip(1) + t.lexer.begin('INITIAL') -def t_ID(t): - r'[a-z]+([a-z]|[A-Z]|[0-9]|_)*' - t.type = reserved.get(t.value, 'ID') - return t +def t_string_eof(t): + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "EOF in string constant") def t_error(t): - printLexicograficError(f'ERROR \"{t.value[0]}\"', t) + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), f'ERROR \"{t.value[0]}\"') t.lexer.skip(1) @@ -217,18 +209,13 @@ def t_newline(t): t.lexer.lineno += len(t.value) -def find_column(token): - line_start = lexer.lexdata.rfind('\n', 0, token.lexpos) + 1 - return (token.lexpos - line_start) + 1 - - def test(data): lexer.input(data) while True: tok = lexer.token() if not tok: break - print(f'#{tok.lineno} {tok.type} {tok.value}') + # print(f'#{tok.lineno} {tok.type} {tok.value}') lexer = lex.lex() diff --git a/src/main.py b/src/main.py index e88a02c2..83248280 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,6 @@ import lexer as lex import sys +import errors as err def exit_with_error(error): @@ -19,6 +20,8 @@ def main(): exit_with_error(f'file {sys.argv[1]} not found') lex.test(input_data) + for e in err.LEXER_ERRORS: + print(e) if __name__ == "__main__": diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 00000000..743031b0 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,3 @@ +def find_column(text, pos): + line_start = text.rfind('\n', 0, pos) + 1 + return (pos - line_start) + 1 From 5230bbe50ce90cb15a1cabae46c02a2b34dd6b27 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 21 Feb 2020 17:27:34 -0500 Subject: [PATCH 025/435] parent_type=none by default --- src/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast.py b/src/ast.py index 8d0975ce..8bea90ff 100644 --- a/src/ast.py +++ b/src/ast.py @@ -3,7 +3,7 @@ def __init__(self, def_class_nodes): self.def_class_nodes=def_class_nodes class DefClassNode: - def __init__(self, type, feature_nodes, parent_type): #poner null# + def __init__(self, type, feature_nodes, parent_type=None): #poner null# self.type=type self.parent_type=parent_type self.feature_nodes=feature_nodes From 6454909a7e58e064cff5b08e405399f092c83d56 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 21 Feb 2020 17:28:54 -0500 Subject: [PATCH 026/435] Fix some bugs on parser --- src/main.py | 5 +- src/parser.py | 212 +++++++++++++++++++++++++------------------------- 2 files changed, 108 insertions(+), 109 deletions(-) diff --git a/src/main.py b/src/main.py index 7fdd2e4a..866d7d30 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,5 @@ import lexer as lex -import parser +from parser import parser import sys import errors as err @@ -20,9 +20,10 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - parser.test(input_data) + parser.parse(input_data, lex.lexer) for e in err.LEXER_ERRORS: print(e) + if __name__ == "__main__": main() diff --git a/src/parser.py b/src/parser.py index da10b027..412f6a44 100644 --- a/src/parser.py +++ b/src/parser.py @@ -2,19 +2,19 @@ from lexer import * import ast - -precedence=( - ('left','.'), - ('left','@'), - ('left','~'), - ('left','ISVOID'), - ('left', '*', '/'), - ('left', '+', '-'), - ('left','GREATREQ', 'LOWEREQ','<', '>', '='), - ('left', 'not'), +precedence = ( + ('left', 'DOT'), + ('left', 'AT'), + ('left', 'NOT'), + ('left', 'ISVOID'), + ('left', 'STAR', 'DIV'), + ('left', 'PLUS', 'MINUS'), + ('left', 'GREATEREQ', 'LOWEREQ', 'LOWER', 'GREATER', 'EQUAL'), + ('left', 'LNOT'), ('right', 'ASSIGN'), ) + def p_program(p): 'program : class_list' p[0] = ast.ProgramNode(p[1]) @@ -22,32 +22,32 @@ def p_program(p): def p_empty(p): 'empty :' - p[0]=None + pass def p_class_list(p): - '''class_list : def_class ; class_list - | def_class ;''' - if len(p)==4: + '''class_list : def_class SEMICOLON class_list + | def_class SEMICOLON''' + if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] def p_def_class(p): - '''dedf_class : CLASS TYPE { feature_list } - | CLASS TYPE INHERITS TYPE { feature_list }''' - if len(p)==7: + '''def_class : CLASS TYPE OBRACKET feature_list CBRACKET + | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET''' + if len(p) == 7: p[0] = ast.DefClassNode(p[2], p[6], p[4]) else: p[0] = ast.DefClassNode(p[2], p[4]) def p_feature_list(p): - '''feature_list : def_attr ; feature_list - | def_function ; feature_list + '''feature_list : def_attr SEMICOLON feature_list + | def_func SEMICOLON feature_list | empty''' - if len(p)==4: + if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [] @@ -59,60 +59,61 @@ def p_def_attr(p): def p_def_func(p): - '''def_func : ID ( param_list ) : TYPE { expr_list }''' + '''def_func : ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKET''' p[0] = ast.DefFuncNode(p[1], p[3], p[6], p[8]) def p_param_list(p): - '''param_list : param , param_list + '''param_list : param COMMA param_list | param | empty''' - if len(p)==4: - p[0]=[p[1]]+p[3] + if len(p) == 4: + p[0] = [p[1]] + p[3] else: - p[0]=[p[1]] + p[0] = [p[1]] def p_param(p): - '''param : ID : TYPE''' + '''param : ID COLON TYPE''' p[0] = (p[1], p[3]) def p_expr_list(p): '''expr_list : expr expr_list | expr''' - if len(p)==3: + if len(p) == 3: p[0] = [p[1]] + p[2] else: p[0] = [p[1]] def p_assign(p): - '''assign : ID <- expr''' + '''assign : ID ASSIGN expr''' p[0] = ast.AssignNode(p[1], p[3]) def p_func_call(p): - '''func_call : expr @ TYPE . ID ( arg_list ) - | expr . ID ( arg_list ) - | ID ( arg_list )''' - if len(p)==9: + '''func_call : expr AT TYPE DOT ID OPAREN arg_list CPAREN + | expr DOT ID OPAREN arg_list CPAREN + | ID OPAREN arg_list CPAREN''' + if len(p) == 9: p[0] = ast.FuncCallNode(p[1], p[3], p[5], p[7]) - elif len(p)==7: + elif len(p) == 7: p[0] = ast.FuncCallNode(p[3], p[5], p[1]) else: p[0] = ast.FuncCallNode(p[1], p[3]) def p_arg_list(p): - '''arg_list : expr , arg_list + '''arg_list : expr COMMA arg_list | expr | empty''' - if len(p)==4: - p[0]=[p[1]]+p[3] + if len(p) == 4: + p[0] = [p[1]] + p[3] else: - p[0]=[p[1]] - + p[0] = [p[1]] + + def p_if_expr(p): '''if_expr : IF expr THEN expr ELSE expr FI''' p[0] = ast.IfNode(p[2], p[4], p[6]) @@ -124,14 +125,14 @@ def p_loop_expr(p): def p_block(p): - '''block : { block_list }''' + '''block : OBRACKET block_list CBRACKET''' p[0] = p[2] def p_block_list(p): - '''block_list : expr ; block_list - | expr ;''' - if len(p)==4: + '''block_list : expr SEMICOLON block_list + | expr SEMICOLON''' + if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] @@ -143,23 +144,23 @@ def p_let_expr(p): def p_assign_list(p): - '''assign_list : assign_elem , assign_list + '''assign_list : assign_elem COMMA assign_list | assign_elem''' - if len(p)==4: + if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] def p_assign_elem(p): - '''assign_elem : ID : TYPE assign_oper''' + '''assign_elem : ID COLON TYPE assign_oper''' p[0] = (p[1], p[4], p[3]) def p_assign_oper(p): - '''assign_oper : <- expr + '''assign_oper : ASSIGN expr | empty''' - if len(p)==3: + if len(p) == 3: p[0] = p[2] else: p[0] = None @@ -171,16 +172,16 @@ def p_case_expr(p): def p_case_list(p): - '''case_list : case_elem ; case_list - | case_elem ;''' - if len(p)==4: + '''case_list : case_elem SEMICOLON case_list + | case_elem SEMICOLON''' + if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] def p_case_elem(p): - '''case_elem : ID : TYPE => expr''' + '''case_elem : ID COLON TYPE ARROW expr''' p[0] = ast.CaseElemNode(p[5], p[1], p[3]) @@ -193,79 +194,78 @@ def p_expr(p): '''expr : NOT expr | cmp | e''' - if len(p)==3: - p[0]=ast.LogicNegationNode(p[2]) + if len(p) == 3: + p[0] = ast.LogicNegationNode(p[2]) else: - p[0]=p[1] + p[0] = p[1] def p_cmp(p): - '''cmp : e > e - | e < e - | e = e - | e >= e - | e <= e''' - if p[2]=='>': - p[0]=ast.GreaterThanNode(p[1], p[3]) - elif p[2]=='<': - p[0]=ast.LessThanNode(p[1], p[3]) - elif p[2]== 'GREATEREQ': - p[0]=ast.GreaterEqNode(p[1], p[3]) - elif p[2]=='LOWEREQ': - p[0]=ast.LessEqNode(p[1], p[3]) - elif p[2]=='=': - p[0]=ast.EqNode(p[1], p[3]) + '''cmp : e LOWER e + | e GREATER e + | e EQUAL e + | e GREATEREQ e + | e LOWEREQ e''' + if p[2] == '>': + p[0] = ast.GreaterThanNode(p[1], p[3]) + elif p[2] == '<': + p[0] = ast.LessThanNode(p[1], p[3]) + elif p[2] == 'GREATEREQ': + p[0] = ast.GreaterEqNode(p[1], p[3]) + elif p[2] == 'LOWEREQ': + p[0] = ast.LessEqNode(p[1], p[3]) + elif p[2] == '=': + p[0] = ast.EqNode(p[1], p[3]) def p_e(p): - '''e : e + t - | e - t + '''e : e PLUS t + | e MINUS t | t''' - if len(p)==2: - p[0]=p[1] + if len(p) == 2: + p[0] = p[1] else: - if p[2]=='+': - p[0]=ast.PlusNode(p[1], p[3]) - elif p[2]=='-': - p[0]=ast.MinusNOde(p[1], p[3]) + if p[2] == '+': + p[0] = ast.PlusNode(p[1], p[3]) + elif p[2] == '-': + p[0] = ast.MinusNOde(p[1], p[3]) def p_t(p): - '''t : t * f - | t / f + '''t : t STAR f + | t DIV f | f''' - if len(p)==2: - p[0]=p[1] + if len(p) == 2: + p[0] = p[1] else: - if p[2]=='*': - p[0]=ast.StarNode(p[1], p[3]) - elif p[2]=='/': - p[0]=ast.DivNode(p[1], p[3]) + if p[2] == '*': + p[0] = ast.StarNode(p[1], p[3]) + elif p[2] == '/': + p[0] = ast.DivNode(p[1], p[3]) pass def p_f(p): - '''f : ~ f - | ( expr ) + '''f : NOT f + | OPAREN expr CPAREN | atom | ISVOID f''' - if len(p)==4: - p[0]=p[2] - if len(p)==3: - if p[1]=='~': - p[0]=ast.NegationNode(p[2]) - if p[1]=='ISVOID': - p[0]=ast.IsVoidNode(p[2]) + if len(p) == 4: + p[0] = p[2] + if len(p) == 3: + if p[1] == '~': + p[0] = ast.NegationNode(p[2]) + if p[1] == 'ISVOID': + p[0] = ast.IsVoidNode(p[2]) else: - p[0]=p[1] + p[0] = p[1] pass def p_atom(p): '''atom : ID | INT - | TRUE - | FALSE + | BOOL | STRING | assign | func_call @@ -275,18 +275,16 @@ def p_atom(p): | let_expr | case_expr | init_expr''' - p[0]=ast.AtomNode(p[1]) - + p[0] = ast.AtomNode(p[1]) + + def p_error(p): if p: - line=p.lineno(0) - pos=p.lexpos(0) + line = p.lineno(0) + pos = p.lexpos(0) print(f'({line}, {pos}) - SyntacticError: ERROR at or near \"{p.value[0]}\"') else: print('EOF') - - -def test(input_data): - parser.parse(input_data) - -parser=yacc.yacc() + + +parser = yacc.yacc() From 170c67a501318bfd0d0d864c3e784cb8a641ae90 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 22 Feb 2020 13:05:20 -0500 Subject: [PATCH 027/435] bug --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..03b88ac8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "C:\\Users\\Isabella Sierra\\Anaconda3\\python.exe" +} \ No newline at end of file From 5d66421ca6c14720026e62266052358d69a247c4 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 22 Feb 2020 13:05:33 -0500 Subject: [PATCH 028/435] bug --- src/main.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 866d7d30..4e12153e 100644 --- a/src/main.py +++ b/src/main.py @@ -1,9 +1,8 @@ import lexer as lex -from parser import parser +import parser as p import sys import errors as err - def exit_with_error(error): print(f'CompilerError: {error}') exit(1) @@ -20,7 +19,7 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - parser.parse(input_data, lex.lexer) + p.parser.parse(input_data, lex.lexer) for e in err.LEXER_ERRORS: print(e) From 797c8403fe5a89fe1d9ccbfa90c2c4a46bb359c0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 22 Feb 2020 18:15:53 -0500 Subject: [PATCH 029/435] Add .vscode folder to .gitignore --- .gitignore | 1 + .vscode/settings.json | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 4a009637..2a3375b1 100644 --- a/.gitignore +++ b/.gitignore @@ -409,3 +409,4 @@ dmypy.json # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) .idea +.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 03b88ac8..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.pythonPath": "C:\\Users\\Isabella Sierra\\Anaconda3\\python.exe" -} \ No newline at end of file From fdc3d186c350b66c18cba2b9bdfa3c5c6ba5d6e8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 22 Feb 2020 18:20:24 -0500 Subject: [PATCH 030/435] bug on parser.py --- src/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser.py b/src/parser.py index 412f6a44..644c1654 100644 --- a/src/parser.py +++ b/src/parser.py @@ -280,8 +280,8 @@ def p_atom(p): def p_error(p): if p: - line = p.lineno(0) - pos = p.lexpos(0) + line = p.lineno + pos = p.lexpos print(f'({line}, {pos}) - SyntacticError: ERROR at or near \"{p.value[0]}\"') else: print('EOF') From 110c25b7b2c0756da52a80a815e82016eab0d864 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 22 Feb 2020 20:23:08 -0500 Subject: [PATCH 031/435] Add parsetab.py to clean command on makefile --- src/makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/makefile b/src/makefile index 021189d6..122a6147 100644 --- a/src/makefile +++ b/src/makefile @@ -5,6 +5,7 @@ main: clean: rm -rf build/* + rm parsetab.py test: pytest ../tests -v --tb=short -m=${TAG} From 6d2a8f8d643fcb59e7814779e825c60a5970be85 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 22 Feb 2020 20:31:00 -0500 Subject: [PATCH 032/435] - Reformat code on parser.py, ast.py - Add parser_error function to errors.py - Support inline comment at not start line on lexer - Reformat imports on parser.py --- src/ast.py | 145 ++++++++++++++++++++++++++++++-------------------- src/errors.py | 4 ++ src/lexer.py | 6 +-- src/main.py | 5 +- src/parser.py | 79 +++++++++++++-------------- 5 files changed, 134 insertions(+), 105 deletions(-) diff --git a/src/ast.py b/src/ast.py index 8bea90ff..43d1ea23 100644 --- a/src/ast.py +++ b/src/ast.py @@ -1,129 +1,156 @@ class ProgramNode: - def __init__(self, def_class_nodes): - self.def_class_nodes=def_class_nodes - + def __init__(self, classes: list): + self.classes = classes + + class DefClassNode: - def __init__(self, type, feature_nodes, parent_type=None): #poner null# - self.type=type - self.parent_type=parent_type - self.feature_nodes=feature_nodes + def __init__(self, type, features, parent_type=None): + self.type = type + self.feature_nodes = features + self.parent_type = parent_type + class FeatureNode: pass + class DefAttrNode(FeatureNode): - def __init__(self,id, type, expr): - self.id=id - self.type=type - self.expr=expr - + def __init__(self, id, type, expr=None): + self.id = id + self.type = type + self.expr = expr + + def __index__(self): + return None + + class DefFuncNode(FeatureNode): def __init__(self, id, params, return_type, expressions): - self.id=id - self.params=params - self.return_type=return_type - self.expressions=expressions - + self.id = id + self.params = params + self.return_type = return_type + self.expressions = expressions + + class AssignNode: - def __init__(self, id, expr, type): #poner null# - self.id=id - self.expr=expr - self.type=type - - + def __init__(self, id, expr, type=None): + self.id = id + self.expr = expr + self.type = type + + class FuncCallNode: - def __init__(self, id, args,object=None, type=None): - self.object=object - self.type=type - self.id=id - self.args=args + def __init__(self, id, args, object=None, type=None): + self.object = object + self.type = type + self.id = id + self.args = args + class IfNode: def __init__(self, if_expr, then_expr, else_expr): - self.if_expr=if_expr - self.then_expr=then_expr - self.else_expr=else_expr - - + self.if_expr = if_expr + self.then_expr = then_expr + self.else_expr = else_expr + + class LoopNode: def __init__(self, cond, body): - self.cond=cond - self.body=body - - + self.cond = cond + self.body = body + + class BlockNode: def __init__(self, expressions): - self.expressions=expressions - + self.expressions = expressions + + class LetNode: def __init__(self, assign_nodes, expr): - self.assign_nodes =assign_nodes - self.expr=expr - + self.assign_nodes = assign_nodes + self.expr = expr + + class CaseNode: def __init__(self, expr, case_list): - self.expr=expr - self.case_list=case_list - + self.expr = expr + self.case_list = case_list + + class CaseElemNode: def __init__(self, expr, id, type): - self.expr=expr - self.id=id - self.type=type - - + self.expr = expr + self.id = id + self.type = type + + class InitNode: def __init__(self, type): - self.type=type - + self.type = type + + class ExpressionNode: pass + class BinaryNode(ExpressionNode): def __init__(self, lvalue, rvalue): - self.lvalue=lvalue - self.rvalue=rvalue - - + self.lvalue = lvalue + self.rvalue = rvalue + + class PlusNode(BinaryNode): pass + class MinusNode(BinaryNode): pass + class StarNode(BinaryNode): pass + class DivNode(BinaryNode): pass + class GreaterThanNode(BinaryNode): pass + class LessThanNode(BinaryNode): pass + class GreaterEqNode(BinaryNode): pass + class LessEqNode(BinaryNode): pass + class EqNode(BinaryNode): pass + class UnaryNode(ExpressionNode): def __init__(self, val): - self.val=val - + self.val = val + + class NegationNode(UnaryNode): pass + class LogicNegationNode(UnaryNode): pass + class AtomNode(UnaryNode): pass + class IsVoidNode(UnaryNode): - pass \ No newline at end of file + pass diff --git a/src/errors.py b/src/errors.py index df19703e..f1b77487 100644 --- a/src/errors.py +++ b/src/errors.py @@ -4,3 +4,7 @@ def add_lexer_error(line, column, message): LEXER_ERRORS.append(f'({line}, {column}) - LexicographicError: {message}') + + +def add_parser_error(line, column, message): + PARSER_ERRORS.append(f'({line}, {column}) - SyntacticError: {message}') diff --git a/src/lexer.py b/src/lexer.py index af5a7304..443f8ceb 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -101,10 +101,8 @@ def t_BOOL(t): def t_LINECOMMENT(t): r'--' - if t.lexpos == 0 or t.lexer.lexdata[t.lexpos - 1] == '\n': - t.lexer.begin('commentLine') - else: - add_lexer_error(t.lexer.lineno, find_column(t.lexer.lexdata, t.lexer.lexpos), f'ERROR {t.value}') + t.lexer.begin('commentLine') + def t_TEXTCOMMENT(t): diff --git a/src/main.py b/src/main.py index 4e12153e..48663a72 100644 --- a/src/main.py +++ b/src/main.py @@ -3,6 +3,7 @@ import sys import errors as err + def exit_with_error(error): print(f'CompilerError: {error}') exit(1) @@ -19,9 +20,11 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - p.parser.parse(input_data, lex.lexer) + ast = p.parser.parse(input_data, lex.lexer) for e in err.LEXER_ERRORS: print(e) + for e in err.PARSER_ERRORS: + print(e) if __name__ == "__main__": diff --git a/src/parser.py b/src/parser.py index 644c1654..76577486 100644 --- a/src/parser.py +++ b/src/parser.py @@ -1,6 +1,7 @@ import ply.yacc as yacc from lexer import * -import ast +from errors import add_parser_error +from ast import * precedence = ( ('left', 'DOT'), @@ -17,7 +18,7 @@ def p_program(p): 'program : class_list' - p[0] = ast.ProgramNode(p[1]) + p[0] = ProgramNode(p[1]) def p_empty(p): @@ -26,21 +27,22 @@ def p_empty(p): def p_class_list(p): - '''class_list : def_class SEMICOLON class_list - | def_class SEMICOLON''' - if len(p) == 4: + '''class_list : def_class class_list + | def_class''' + + if len(p) == 3: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] def p_def_class(p): - '''def_class : CLASS TYPE OBRACKET feature_list CBRACKET - | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET''' - if len(p) == 7: - p[0] = ast.DefClassNode(p[2], p[6], p[4]) + '''def_class : CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON + | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLON''' + if len(p) == 8: + p[0] = DefClassNode(p[2], p[6], p[4]) else: - p[0] = ast.DefClassNode(p[2], p[4]) + p[0] = DefClassNode(p[2], p[4]) def p_feature_list(p): @@ -55,12 +57,12 @@ def p_feature_list(p): def p_def_attr(p): '''def_attr : assign_elem''' - p[0] = ast.DefAttrNode(p[1]) + p[0] = DefAttrNode(*p[1]) def p_def_func(p): '''def_func : ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKET''' - p[0] = ast.DefFuncNode(p[1], p[3], p[6], p[8]) + p[0] = DefFuncNode(p[1], p[3], p[6], p[8]) def p_param_list(p): @@ -89,7 +91,7 @@ def p_expr_list(p): def p_assign(p): '''assign : ID ASSIGN expr''' - p[0] = ast.AssignNode(p[1], p[3]) + p[0] = AssignNode(p[1], p[3]) def p_func_call(p): @@ -97,11 +99,11 @@ def p_func_call(p): | expr DOT ID OPAREN arg_list CPAREN | ID OPAREN arg_list CPAREN''' if len(p) == 9: - p[0] = ast.FuncCallNode(p[1], p[3], p[5], p[7]) + p[0] = FuncCallNode(p[1], p[3], p[5], p[7]) elif len(p) == 7: - p[0] = ast.FuncCallNode(p[3], p[5], p[1]) + p[0] = FuncCallNode(p[3], p[5], p[1]) else: - p[0] = ast.FuncCallNode(p[1], p[3]) + p[0] = FuncCallNode(p[1], p[3]) def p_arg_list(p): @@ -116,12 +118,12 @@ def p_arg_list(p): def p_if_expr(p): '''if_expr : IF expr THEN expr ELSE expr FI''' - p[0] = ast.IfNode(p[2], p[4], p[6]) + p[0] = IfNode(p[2], p[4], p[6]) def p_loop_expr(p): '''loop_expr : WHILE expr LOOP expr POOL''' - p[0] = ast.LoopNode(p[2], p[4]) + p[0] = LoopNode(p[2], p[4]) def p_block(p): @@ -140,7 +142,7 @@ def p_block_list(p): def p_let_expr(p): '''let_expr : LET assign_list IN expr''' - p[0] = ast.LetNode(p[2], p[4]) + p[0] = LetNode(p[2], p[4]) def p_assign_list(p): @@ -168,7 +170,7 @@ def p_assign_oper(p): def p_case_expr(p): '''case_expr : CASE expr OF case_list ESAC''' - p[0] = ast.CaseNode(p[2], p[4]) + p[0] = CaseNode(p[2], p[4]) def p_case_list(p): @@ -182,12 +184,12 @@ def p_case_list(p): def p_case_elem(p): '''case_elem : ID COLON TYPE ARROW expr''' - p[0] = ast.CaseElemNode(p[5], p[1], p[3]) + p[0] = CaseElemNode(p[5], p[1], p[3]) def p_init_expr(p): '''init_expr : NEW TYPE''' - p[0] = ast.InitNode(p[2]) + p[0] = InitNode(p[2]) def p_expr(p): @@ -195,7 +197,7 @@ def p_expr(p): | cmp | e''' if len(p) == 3: - p[0] = ast.LogicNegationNode(p[2]) + p[0] = LogicNegationNode(p[2]) else: p[0] = p[1] @@ -207,15 +209,15 @@ def p_cmp(p): | e GREATEREQ e | e LOWEREQ e''' if p[2] == '>': - p[0] = ast.GreaterThanNode(p[1], p[3]) + p[0] = GreaterThanNode(p[1], p[3]) elif p[2] == '<': - p[0] = ast.LessThanNode(p[1], p[3]) + p[0] = LessThanNode(p[1], p[3]) elif p[2] == 'GREATEREQ': - p[0] = ast.GreaterEqNode(p[1], p[3]) + p[0] = GreaterEqNode(p[1], p[3]) elif p[2] == 'LOWEREQ': - p[0] = ast.LessEqNode(p[1], p[3]) + p[0] = LessEqNode(p[1], p[3]) elif p[2] == '=': - p[0] = ast.EqNode(p[1], p[3]) + p[0] = EqNode(p[1], p[3]) def p_e(p): @@ -226,9 +228,9 @@ def p_e(p): p[0] = p[1] else: if p[2] == '+': - p[0] = ast.PlusNode(p[1], p[3]) + p[0] = PlusNode(p[1], p[3]) elif p[2] == '-': - p[0] = ast.MinusNOde(p[1], p[3]) + p[0] = MinusNode(p[1], p[3]) def p_t(p): @@ -239,9 +241,9 @@ def p_t(p): p[0] = p[1] else: if p[2] == '*': - p[0] = ast.StarNode(p[1], p[3]) + p[0] = StarNode(p[1], p[3]) elif p[2] == '/': - p[0] = ast.DivNode(p[1], p[3]) + p[0] = DivNode(p[1], p[3]) pass @@ -254,9 +256,9 @@ def p_f(p): p[0] = p[2] if len(p) == 3: if p[1] == '~': - p[0] = ast.NegationNode(p[2]) + p[0] = NegationNode(p[2]) if p[1] == 'ISVOID': - p[0] = ast.IsVoidNode(p[2]) + p[0] = IsVoidNode(p[2]) else: p[0] = p[1] pass @@ -275,16 +277,11 @@ def p_atom(p): | let_expr | case_expr | init_expr''' - p[0] = ast.AtomNode(p[1]) + p[0] = AtomNode(p[1]) def p_error(p): - if p: - line = p.lineno - pos = p.lexpos - print(f'({line}, {pos}) - SyntacticError: ERROR at or near \"{p.value[0]}\"') - else: - print('EOF') + add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \"{p.value[0]}\"') parser = yacc.yacc() From e735237a18f0c1f61ad6d098911ee3c710ca9c35 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 16:47:39 -0500 Subject: [PATCH 033/435] - Fix null character column calculator on error format - Exit with status 1 if LEXER_ERRORS - Handle EOF on parser --- src/lexer.py | 4 ++-- src/main.py | 6 ++++-- src/parser.py | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 443f8ceb..06fff47d 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -104,7 +104,6 @@ def t_LINECOMMENT(t): t.lexer.begin('commentLine') - def t_TEXTCOMMENT(t): r'\(\*' t.lexer.comment_start = t.lexer.lexpos @@ -182,7 +181,8 @@ def t_string_newline(t): def t_string_body(t): r'([^\n\"\\]|\\.)+' if t.value.rfind('\0') != -1: - add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "String contains null character") + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos) + t.value.rfind('\0'), + "String contains null character") def t_string_error(t): diff --git a/src/main.py b/src/main.py index 48663a72..f60a7876 100644 --- a/src/main.py +++ b/src/main.py @@ -21,8 +21,10 @@ def main(): exit_with_error(f'file {sys.argv[1]} not found') ast = p.parser.parse(input_data, lex.lexer) - for e in err.LEXER_ERRORS: - print(e) + if err.LEXER_ERRORS: + for e in err.LEXER_ERRORS: + print(e) + exit(1) for e in err.PARSER_ERRORS: print(e) diff --git a/src/parser.py b/src/parser.py index 76577486..eee391fa 100644 --- a/src/parser.py +++ b/src/parser.py @@ -281,7 +281,10 @@ def p_atom(p): def p_error(p): - add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \"{p.value[0]}\"') + if p: + add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \"{p.value}\"') + else: + add_parser_error(0, 0, "ERROR at or near EOF") parser = yacc.yacc() From f3c3250641bad12c2cd73ba4f149dc175be8d402 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 16:56:18 -0500 Subject: [PATCH 034/435] Delete the echo line in the cool.sh file because the tests need errors to start on line 2 output --- src/coolc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coolc.sh b/src/coolc.sh index ae6cb356..eb2814b1 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -4,9 +4,9 @@ INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips # Si su compilador no lo hace ya, aquí puede imprimir la información de contacto -echo "COOL COMPILER 0.0v" +# echo "COOL COMPILER 0.0v" echo "Copyright (c) 2019: Isabella Maria Sierra Ponce, Adrian Tubal Paez Ruiz, Eric Martin Garcia" # Llamar al compilador echo "Compiling $INPUT_FILE into $OUTPUT_FILE" -python3 main.py $INPUT_FILE \ No newline at end of file +python3 main.py $INPUT_FILE From 92f98c8c84c0153b4517f5d152a3604fafdde42c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 17:00:52 -0500 Subject: [PATCH 035/435] Remove parsetab.py from clean on makefile --- src/makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/makefile b/src/makefile index 122a6147..021189d6 100644 --- a/src/makefile +++ b/src/makefile @@ -5,7 +5,6 @@ main: clean: rm -rf build/* - rm parsetab.py test: pytest ../tests -v --tb=short -m=${TAG} From 5b051c29735e003806d20bfebba22b7110883ec5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 17:05:42 -0500 Subject: [PATCH 036/435] pushing parsetab.py --- src/parsetab.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/parsetab.py diff --git a/src/parsetab.py b/src/parsetab.py new file mode 100644 index 00000000..20931c86 --- /dev/null +++ b/src/parsetab.py @@ -0,0 +1,100 @@ + +# parsetab.py +# This file is automatically generated. Do not edit. +# pylint: disable=W,C,R +_tabversion = '3.10' + +_lr_method = 'LALR' + +_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftGREATEREQLOWEREQLOWERGREATEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI GREATER GREATEREQ ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class class_list\n | def_classdef_class : CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLONfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : assign_elemdef_func : ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKETparam_list : param COMMA param_list\n | param\n | emptyparam : ID COLON TYPEexpr_list : expr expr_list\n | exprassign : ID ASSIGN exprfunc_call : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENarg_list : expr COMMA arg_list\n | expr\n | emptyif_expr : IF expr THEN expr ELSE expr FIloop_expr : WHILE expr LOOP expr POOLblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLONlet_expr : LET assign_list IN exprassign_list : assign_elem COMMA assign_list\n | assign_elemassign_elem : ID COLON TYPE assign_operassign_oper : ASSIGN expr\n | emptycase_expr : CASE expr OF case_list ESACcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprinit_expr : NEW TYPEexpr : NOT expr\n | cmp\n | ecmp : e LOWER e\n | e GREATER e\n | e EQUAL e\n | e GREATEREQ e\n | e LOWEREQ ee : e PLUS t\n | e MINUS t\n | tt : t STAR f\n | t DIV f\n | ff : NOT f\n | OPAREN expr CPAREN\n | atom\n | ISVOID fatom : ID\n | INT\n | BOOL\n | STRING\n | assign\n | func_call\n | if_expr\n | loop_expr\n | block\n | let_expr\n | case_expr\n | init_expr' + +_lr_action_items = {'CLASS':([0,3,22,68,],[4,4,-5,-6,]),'$end':([1,2,3,5,22,68,],[0,-1,-4,-3,-5,-6,]),'TYPE':([4,8,20,31,39,67,70,145,],[6,15,29,38,69,97,99,150,]),'OBRACKET':([6,15,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,69,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[7,21,64,64,-42,-43,-51,-54,64,-57,64,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,64,64,64,64,98,-41,-54,64,64,64,64,64,64,64,64,64,-58,64,64,64,-40,64,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,64,64,-27,64,64,64,64,-21,64,-30,64,-26,-36,64,-20,-25,64,-19,]),'INHERITS':([6,],[8,]),'ID':([7,17,18,19,21,33,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,71,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,120,121,123,124,125,126,127,131,141,142,143,144,146,147,152,153,154,],[14,14,14,25,14,25,50,50,-42,-43,-51,-54,50,-57,50,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,50,50,50,95,50,100,-41,-54,50,50,50,50,50,50,50,50,50,-58,50,50,50,-40,50,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,50,50,-27,50,50,95,135,50,138,50,-21,50,-30,50,-26,-36,135,50,-20,-25,50,-19,]),'CBRACKET':([7,9,12,17,18,21,23,24,30,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,91,97,101,102,103,104,105,106,107,108,109,110,111,117,118,122,123,126,130,131,137,142,143,147,152,154,],[-2,16,-9,-2,-2,-2,-7,-8,37,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,117,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-29,136,-17,-21,-28,-30,-16,-26,-36,-20,-25,-19,]),'SEMICOLON':([10,11,13,16,29,34,36,37,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,92,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,134,136,142,143,147,152,154,155,],[17,18,-10,22,-2,-33,-35,68,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,118,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,144,-11,-26,-36,-20,-25,-19,-39,]),'OPAREN':([14,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,100,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,138,141,142,143,146,147,152,153,154,],[19,47,47,-42,-43,-51,-54,47,-57,47,88,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,47,47,47,47,-41,-54,47,47,47,47,47,47,47,47,47,-58,47,47,47,-40,47,125,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,47,47,-27,47,47,47,47,-21,47,-30,146,47,-26,-36,47,-20,-25,47,-19,]),'COLON':([14,25,32,95,135,],[20,31,39,20,145,]),'CPAREN':([19,26,27,28,33,38,40,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,88,97,101,102,103,104,105,106,107,108,109,110,111,112,113,114,117,125,126,127,131,139,140,142,143,146,147,151,152,154,],[-2,32,-13,-14,-2,-15,-12,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,110,-58,-2,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,126,-23,-24,-27,-2,-21,-2,-30,147,-22,-26,-36,-2,-20,154,-25,-19,]),'COMMA':([27,29,34,36,38,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,94,97,101,102,103,104,105,106,107,108,109,110,111,113,117,126,131,142,143,147,152,154,],[33,-2,-33,-35,-15,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,120,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,127,-27,-21,-30,-26,-36,-20,-25,-19,]),'ASSIGN':([29,50,],[35,87,]),'IN':([29,34,36,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,93,94,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,132,142,143,147,152,154,],[-2,-33,-35,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,119,-32,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-31,-26,-36,-20,-25,-19,]),'NOT':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[42,42,-42,-43,-51,-54,42,-57,85,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,42,42,42,42,-41,-54,85,85,85,85,85,85,85,85,85,-58,85,42,42,-40,42,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,42,42,-27,42,42,42,42,-21,42,-30,42,-26,-36,42,-20,-25,42,-19,]),'ISVOID':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[49,49,-42,-43,-51,-54,49,-57,49,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,49,49,49,49,-41,-54,49,49,49,49,49,49,49,49,49,-58,49,49,49,-40,49,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,49,49,-27,49,49,49,49,-21,49,-30,49,-26,-36,49,-20,-25,49,-19,]),'INT':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[51,51,-42,-43,-51,-54,51,-57,51,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,51,51,51,51,-41,-54,51,51,51,51,51,51,51,51,51,-58,51,51,51,-40,51,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,51,51,-27,51,51,51,51,-21,51,-30,51,-26,-36,51,-20,-25,51,-19,]),'BOOL':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[52,52,-42,-43,-51,-54,52,-57,52,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,52,52,52,52,-41,-54,52,52,52,52,52,52,52,52,52,-58,52,52,52,-40,52,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,52,52,-27,52,52,52,52,-21,52,-30,52,-26,-36,52,-20,-25,52,-19,]),'STRING':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[53,53,-42,-43,-51,-54,53,-57,53,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,53,53,53,53,-41,-54,53,53,53,53,53,53,53,53,53,-58,53,53,53,-40,53,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,53,53,-27,53,53,53,53,-21,53,-30,53,-26,-36,53,-20,-25,53,-19,]),'IF':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[62,62,-42,-43,-51,-54,62,-57,62,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,62,62,62,62,-41,-54,62,62,62,62,62,62,62,62,62,-58,62,62,62,-40,62,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,62,62,-27,62,62,62,62,-21,62,-30,62,-26,-36,62,-20,-25,62,-19,]),'WHILE':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[63,63,-42,-43,-51,-54,63,-57,63,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,63,63,63,63,-41,-54,63,63,63,63,63,63,63,63,63,-58,63,63,63,-40,63,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,63,63,-27,63,63,63,63,-21,63,-30,63,-26,-36,63,-20,-25,63,-19,]),'LET':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[65,65,-42,-43,-51,-54,65,-57,65,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,65,65,65,65,-41,-54,65,65,65,65,65,65,65,65,65,-58,65,65,65,-40,65,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,65,65,-27,65,65,65,65,-21,65,-30,65,-26,-36,65,-20,-25,65,-19,]),'CASE':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[66,66,-42,-43,-51,-54,66,-57,66,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,66,66,66,66,-41,-54,66,66,66,66,66,66,66,66,66,-58,66,66,66,-40,66,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,66,66,-27,66,66,66,66,-21,66,-30,66,-26,-36,66,-20,-25,66,-19,]),'NEW':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[67,67,-42,-43,-51,-54,67,-57,67,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,67,67,67,67,-41,-54,67,67,67,67,67,67,67,67,67,-58,67,67,67,-40,67,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,67,67,-27,67,67,67,67,-21,67,-30,67,-26,-36,67,-20,-25,67,-19,]),'AT':([41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,86,89,90,92,96,97,101,102,103,104,105,106,107,108,109,110,111,113,117,123,126,128,129,131,142,143,147,148,152,154,155,],[70,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,70,-54,70,70,70,70,70,-40,-43,-43,-43,-43,-43,-49,-50,-52,-53,-56,-18,70,-27,70,-21,70,70,70,-26,-36,-20,70,-25,-19,70,]),'DOT':([41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,86,89,90,92,96,97,99,101,102,103,104,105,106,107,108,109,110,111,113,117,123,126,128,129,131,142,143,147,148,152,154,155,],[71,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,71,-54,71,71,71,71,71,-40,124,-43,-43,-43,-43,-43,-49,-50,-52,-53,-56,-18,71,-27,71,-21,71,71,71,-26,-36,-20,71,-25,-19,71,]),'THEN':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,89,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,115,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOOP':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,90,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,116,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'OF':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,96,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,121,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'STAR':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,81,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'DIV':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,82,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOWER':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,74,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'GREATER':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,75,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'EQUAL':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,76,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'GREATEREQ':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,77,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOWEREQ':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,78,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'PLUS':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,79,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'MINUS':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,80,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'ELSE':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,128,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,141,-30,-26,-36,-20,-25,-19,]),'POOL':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,129,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,142,-30,-26,-36,-20,-25,-19,]),'FI':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,148,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,152,-25,-19,]),'ESAC':([133,144,149,],[143,-38,-37,]),'ARROW':([150,],[153,]),} + +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items + +_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,3,],[2,5,]),'def_class':([0,3,],[3,3,]),'feature_list':([7,17,18,21,],[9,23,24,30,]),'def_attr':([7,17,18,21,],[10,10,10,10,]),'def_func':([7,17,18,21,],[11,11,11,11,]),'empty':([7,17,18,19,21,29,33,88,125,127,146,],[12,12,12,28,12,36,28,114,114,114,114,]),'assign_elem':([7,17,18,21,65,120,],[13,13,13,13,94,94,]),'param_list':([19,33,],[26,40,]),'param':([19,33,],[27,27,]),'assign_oper':([29,],[34,]),'expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[41,72,83,86,89,90,92,96,86,86,86,86,86,86,86,86,86,72,111,113,123,128,129,92,131,123,113,113,148,113,155,]),'cmp':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,]),'e':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[44,44,44,44,44,44,44,44,101,102,103,104,105,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'t':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[45,45,45,45,45,45,45,45,45,45,45,45,45,106,107,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'f':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[46,73,46,84,46,46,46,46,46,46,46,46,46,46,46,108,109,73,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'atom':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'assign':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,]),'func_call':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,]),'if_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,]),'loop_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,]),'block':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,]),'let_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,]),'case_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,]),'init_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,]),'block_list':([64,118,],[91,130,]),'assign_list':([65,120,],[93,132,]),'arg_list':([88,125,127,146,],[112,139,140,151,]),'expr_list':([98,123,],[122,137,]),'case_list':([121,144,],[133,149,]),'case_elem':([121,144,],[134,134,]),} + +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +_lr_productions = [ + ("S' -> program","S'",1,None,None,None), + ('program -> class_list','program',1,'p_program','parser.py',20), + ('empty -> ','empty',0,'p_empty','parser.py',25), + ('class_list -> def_class class_list','class_list',2,'p_class_list','parser.py',30), + ('class_list -> def_class','class_list',1,'p_class_list','parser.py',31), + ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON','def_class',6,'p_def_class','parser.py',40), + ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLON','def_class',8,'p_def_class','parser.py',41), + ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), + ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), + ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), + ('def_attr -> assign_elem','def_attr',1,'p_def_attr','parser.py',59), + ('def_func -> ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKET','def_func',9,'p_def_func','parser.py',64), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',69), + ('param_list -> param','param_list',1,'p_param_list','parser.py',70), + ('param_list -> empty','param_list',1,'p_param_list','parser.py',71), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',79), + ('expr_list -> expr expr_list','expr_list',2,'p_expr_list','parser.py',84), + ('expr_list -> expr','expr_list',1,'p_expr_list','parser.py',85), + ('assign -> ID ASSIGN expr','assign',3,'p_assign','parser.py',93), + ('func_call -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','func_call',8,'p_func_call','parser.py',98), + ('func_call -> expr DOT ID OPAREN arg_list CPAREN','func_call',6,'p_func_call','parser.py',99), + ('func_call -> ID OPAREN arg_list CPAREN','func_call',4,'p_func_call','parser.py',100), + ('arg_list -> expr COMMA arg_list','arg_list',3,'p_arg_list','parser.py',110), + ('arg_list -> expr','arg_list',1,'p_arg_list','parser.py',111), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',112), + ('if_expr -> IF expr THEN expr ELSE expr FI','if_expr',7,'p_if_expr','parser.py',120), + ('loop_expr -> WHILE expr LOOP expr POOL','loop_expr',5,'p_loop_expr','parser.py',125), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',130), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',135), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',136), + ('let_expr -> LET assign_list IN expr','let_expr',4,'p_let_expr','parser.py',144), + ('assign_list -> assign_elem COMMA assign_list','assign_list',3,'p_assign_list','parser.py',149), + ('assign_list -> assign_elem','assign_list',1,'p_assign_list','parser.py',150), + ('assign_elem -> ID COLON TYPE assign_oper','assign_elem',4,'p_assign_elem','parser.py',158), + ('assign_oper -> ASSIGN expr','assign_oper',2,'p_assign_oper','parser.py',163), + ('assign_oper -> empty','assign_oper',1,'p_assign_oper','parser.py',164), + ('case_expr -> CASE expr OF case_list ESAC','case_expr',5,'p_case_expr','parser.py',172), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',177), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',178), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',186), + ('init_expr -> NEW TYPE','init_expr',2,'p_init_expr','parser.py',191), + ('expr -> NOT expr','expr',2,'p_expr','parser.py',196), + ('expr -> cmp','expr',1,'p_expr','parser.py',197), + ('expr -> e','expr',1,'p_expr','parser.py',198), + ('cmp -> e LOWER e','cmp',3,'p_cmp','parser.py',206), + ('cmp -> e GREATER e','cmp',3,'p_cmp','parser.py',207), + ('cmp -> e EQUAL e','cmp',3,'p_cmp','parser.py',208), + ('cmp -> e GREATEREQ e','cmp',3,'p_cmp','parser.py',209), + ('cmp -> e LOWEREQ e','cmp',3,'p_cmp','parser.py',210), + ('e -> e PLUS t','e',3,'p_e','parser.py',224), + ('e -> e MINUS t','e',3,'p_e','parser.py',225), + ('e -> t','e',1,'p_e','parser.py',226), + ('t -> t STAR f','t',3,'p_t','parser.py',237), + ('t -> t DIV f','t',3,'p_t','parser.py',238), + ('t -> f','t',1,'p_t','parser.py',239), + ('f -> NOT f','f',2,'p_f','parser.py',251), + ('f -> OPAREN expr CPAREN','f',3,'p_f','parser.py',252), + ('f -> atom','f',1,'p_f','parser.py',253), + ('f -> ISVOID f','f',2,'p_f','parser.py',254), + ('atom -> ID','atom',1,'p_atom','parser.py',268), + ('atom -> INT','atom',1,'p_atom','parser.py',269), + ('atom -> BOOL','atom',1,'p_atom','parser.py',270), + ('atom -> STRING','atom',1,'p_atom','parser.py',271), + ('atom -> assign','atom',1,'p_atom','parser.py',272), + ('atom -> func_call','atom',1,'p_atom','parser.py',273), + ('atom -> if_expr','atom',1,'p_atom','parser.py',274), + ('atom -> loop_expr','atom',1,'p_atom','parser.py',275), + ('atom -> block','atom',1,'p_atom','parser.py',276), + ('atom -> let_expr','atom',1,'p_atom','parser.py',277), + ('atom -> case_expr','atom',1,'p_atom','parser.py',278), + ('atom -> init_expr','atom',1,'p_atom','parser.py',279), +] From b2a9d16dd540eb61620fec8c3125bf407ddf64d0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 17:31:44 -0500 Subject: [PATCH 037/435] Update EOF error on string --- src/lexer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer.py b/src/lexer.py index 06fff47d..dc9bfa3e 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -194,7 +194,7 @@ def t_string_error(t): def t_string_eof(t): - add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "EOF in string constant") + add_lexer_error(t.lineno, find_column(t.lexer.lexdata, t.lexpos), "Unterminated string constant") def t_error(t): From 8a7d81ffa4c09a9ec6917ccb5220a56047490e8c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 19:04:42 -0500 Subject: [PATCH 038/435] add ply to requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9eb0cad1..cba16ee2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pytest pytest-ordering +ply From 66a66f42b3218c845419ff2bbdaa096165bd21ce Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 19:07:57 -0500 Subject: [PATCH 039/435] Add exit with code 1 if PARSER_ERRORS --- src/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index f60a7876..b483fa2a 100644 --- a/src/main.py +++ b/src/main.py @@ -25,8 +25,10 @@ def main(): for e in err.LEXER_ERRORS: print(e) exit(1) - for e in err.PARSER_ERRORS: - print(e) + if err.PARSER_ERRORS: + for e in err.PARSER_ERRORS: + print(e) + exit(1) if __name__ == "__main__": From e04b3ee4d66b544dc41c76a6216be6248c91c38b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 24 Feb 2020 22:38:53 -0500 Subject: [PATCH 040/435] fixing reserved words regexes --- src/lexer.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index dc9bfa3e..3f74a4cd 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -9,23 +9,23 @@ ) reserved = { - 'if': 'IF', - 'then': 'THEN', - 'else': 'ELSE', - 'fi': 'FI', - 'class': 'CLASS', - 'inherits': 'INHERITS', - 'while': 'WHILE', - 'loop': 'LOOP', - 'pool': 'POOL', - 'let': 'LET', - 'in': 'IN', - 'case': 'CASE', - 'isvoid': 'ISVOID', - 'esac': 'ESAC', - 'new': 'NEW', - 'of': 'OF', - 'not': 'LNOT' + r'(?i)if': 'IF', + r'(?i)then': 'THEN', + r'(?i)else': 'ELSE', + r'(?i)fi': 'FI', + r'(?i)class': 'CLASS', + r'(?i)inherits': 'INHERITS', + r'(?i)while': 'WHILE', + r'(?i)loop': 'LOOP', + r'(?i)pool': 'POOL', + r'(?i)let': 'LET', + r'(?i)in': 'IN', + r'(?i)case': 'CASE', + r'(?i)isvoid': 'ISVOID', + r'(?i)esac': 'ESAC', + r'(?i)new': 'NEW', + r'(?i)of': 'OF', + r'(?i)not': 'LNOT' } tokens = [ From 347fd8d971eb27c7a4fcdcb7c0927826b496bd41 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 24 Feb 2020 22:52:42 -0500 Subject: [PATCH 041/435] changing logic not --- src/parser.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/parser.py b/src/parser.py index eee391fa..bab64845 100644 --- a/src/parser.py +++ b/src/parser.py @@ -193,13 +193,9 @@ def p_init_expr(p): def p_expr(p): - '''expr : NOT expr - | cmp + '''expr : cmp | e''' - if len(p) == 3: - p[0] = LogicNegationNode(p[2]) - else: - p[0] = p[1] + p[0] = p[1] def p_cmp(p): @@ -251,7 +247,8 @@ def p_f(p): '''f : NOT f | OPAREN expr CPAREN | atom - | ISVOID f''' + | ISVOID f + | ~ f''' if len(p) == 4: p[0] = p[2] if len(p) == 3: @@ -259,6 +256,8 @@ def p_f(p): p[0] = NegationNode(p[2]) if p[1] == 'ISVOID': p[0] = IsVoidNode(p[2]) + if p[1] == 'NOT': + p[0] = LogicNegationNode(p[2]) else: p[0] = p[1] pass From 1b91d4dd11154e2e8f8ccbcbffabbc756c32572f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 24 Feb 2020 22:54:59 -0500 Subject: [PATCH 042/435] reverting change in regexes --- src/lexer.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index 3f74a4cd..dc9bfa3e 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -9,23 +9,23 @@ ) reserved = { - r'(?i)if': 'IF', - r'(?i)then': 'THEN', - r'(?i)else': 'ELSE', - r'(?i)fi': 'FI', - r'(?i)class': 'CLASS', - r'(?i)inherits': 'INHERITS', - r'(?i)while': 'WHILE', - r'(?i)loop': 'LOOP', - r'(?i)pool': 'POOL', - r'(?i)let': 'LET', - r'(?i)in': 'IN', - r'(?i)case': 'CASE', - r'(?i)isvoid': 'ISVOID', - r'(?i)esac': 'ESAC', - r'(?i)new': 'NEW', - r'(?i)of': 'OF', - r'(?i)not': 'LNOT' + 'if': 'IF', + 'then': 'THEN', + 'else': 'ELSE', + 'fi': 'FI', + 'class': 'CLASS', + 'inherits': 'INHERITS', + 'while': 'WHILE', + 'loop': 'LOOP', + 'pool': 'POOL', + 'let': 'LET', + 'in': 'IN', + 'case': 'CASE', + 'isvoid': 'ISVOID', + 'esac': 'ESAC', + 'new': 'NEW', + 'of': 'OF', + 'not': 'LNOT' } tokens = [ From 9396fab0af3fec220da4b34c0a477745aa41c704 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 24 Feb 2020 23:16:59 -0500 Subject: [PATCH 043/435] - Fix lexer regex - Remove index out of range bug on parser --- src/lexer.py | 7 +++++-- src/parser.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lexer.py b/src/lexer.py index dc9bfa3e..f4fd9dfb 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -78,7 +78,6 @@ t_DIV = r'/' t_NOT = r'~' t_COMMA = r',' -t_TYPE = r'[A-Z]+([a-z]|[A-Z]|[0-9]|_)*' def t_INT(t): @@ -86,10 +85,14 @@ def t_INT(t): t.value = int(t.value) return t +def t_TYPE(t): + r'[A-Z][a-zA-Z_0-9]*' + t.type = reserved.get(t.value.lower(),'TYPE') + return t def t_ID(t): r'[a-z][a-zA-Z_0-9]*' - t.type = reserved.get(t.value, 'ID') + t.type = reserved.get(t.value.lower(), 'ID') return t diff --git a/src/parser.py b/src/parser.py index eee391fa..1ddf7c3d 100644 --- a/src/parser.py +++ b/src/parser.py @@ -30,9 +30,9 @@ def p_class_list(p): '''class_list : def_class class_list | def_class''' - if len(p) == 3: + try: p[0] = [p[1]] + p[3] - else: + except: p[0] = [p[1]] From 12d2a5266297d5a3288a746cbb8951eb3bd8181c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 28 Feb 2020 08:07:42 -0500 Subject: [PATCH 044/435] - AST: Add VarNode and Constants Nodes - Remove GREATEREQ and GREATER tokens - Finishing the parser --- src/ast.py | 44 +++++--- src/lexer.py | 8 +- src/parser.py | 294 ++++++++++++++++++++++-------------------------- src/parsetab.py | 121 +++++++++----------- 4 files changed, 221 insertions(+), 246 deletions(-) diff --git a/src/ast.py b/src/ast.py index 43d1ea23..164ddbd0 100644 --- a/src/ast.py +++ b/src/ast.py @@ -33,10 +33,9 @@ def __init__(self, id, params, return_type, expressions): class AssignNode: - def __init__(self, id, expr, type=None): + def __init__(self, id, expr): self.id = id self.expr = expr - self.type = type class FuncCallNode: @@ -54,7 +53,7 @@ def __init__(self, if_expr, then_expr, else_expr): self.else_expr = else_expr -class LoopNode: +class WhileNode: def __init__(self, cond, body): self.cond = cond self.body = body @@ -66,8 +65,8 @@ def __init__(self, expressions): class LetNode: - def __init__(self, assign_nodes, expr): - self.assign_nodes = assign_nodes + def __init__(self, let_attrs, expr): + self.let_attrs = let_attrs self.expr = expr @@ -115,18 +114,10 @@ class DivNode(BinaryNode): pass -class GreaterThanNode(BinaryNode): - pass - - class LessThanNode(BinaryNode): pass -class GreaterEqNode(BinaryNode): - pass - - class LessEqNode(BinaryNode): pass @@ -154,3 +145,30 @@ class AtomNode(UnaryNode): class IsVoidNode(UnaryNode): pass + + +class VarNode: + def __init__(self, id): + self.id = id + + +class NewNode: + def __init__(self, t): + self.type = t + + +class ConstantNode: + def __init__(self, value): + self.value = value + + +class IntNode(ConstantNode): + pass + + +class BoolNode(ConstantNode): + pass + + +class StringNode(ConstantNode): + pass diff --git a/src/lexer.py b/src/lexer.py index f4fd9dfb..ee645117 100644 --- a/src/lexer.py +++ b/src/lexer.py @@ -31,7 +31,6 @@ tokens = [ 'ASSIGN', 'ARROW', - 'GREATEREQ', 'LOWEREQ', 'INT', 'STRING', @@ -46,7 +45,6 @@ 'AT', 'DOT', 'LOWER', - 'GREATER', 'EQUAL', 'PLUS', 'MINUS', @@ -66,9 +64,7 @@ t_AT = r'@' t_DOT = r'\.' t_LOWER = r'<' -t_GREATER = r'>' t_EQUAL = r'=' -t_GREATEREQ = r'>=' t_LOWEREQ = r'<=' t_ASSIGN = r'<-' t_ARROW = r'=>' @@ -85,11 +81,13 @@ def t_INT(t): t.value = int(t.value) return t + def t_TYPE(t): r'[A-Z][a-zA-Z_0-9]*' - t.type = reserved.get(t.value.lower(),'TYPE') + t.type = reserved.get(t.value.lower(), 'TYPE') return t + def t_ID(t): r'[a-z][a-zA-Z_0-9]*' t.type = reserved.get(t.value.lower(), 'ID') diff --git a/src/parser.py b/src/parser.py index 1ddf7c3d..0b481e61 100644 --- a/src/parser.py +++ b/src/parser.py @@ -10,7 +10,7 @@ ('left', 'ISVOID'), ('left', 'STAR', 'DIV'), ('left', 'PLUS', 'MINUS'), - ('left', 'GREATEREQ', 'LOWEREQ', 'LOWER', 'GREATER', 'EQUAL'), + ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'LNOT'), ('right', 'ASSIGN'), ) @@ -27,8 +27,8 @@ def p_empty(p): def p_class_list(p): - '''class_list : def_class class_list - | def_class''' + '''class_list : def_class SEMICOLON class_list + | def_class SEMICOLON''' try: p[0] = [p[1]] + p[3] @@ -37,8 +37,8 @@ def p_class_list(p): def p_def_class(p): - '''def_class : CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON - | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLON''' + '''def_class : CLASS TYPE OBRACKET feature_list CBRACKET + | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET''' if len(p) == 8: p[0] = DefClassNode(p[2], p[6], p[4]) else: @@ -55,23 +55,36 @@ def p_feature_list(p): p[0] = [] -def p_def_attr(p): - '''def_attr : assign_elem''' - p[0] = DefAttrNode(*p[1]) +def p_def_attr_declaration(p): + '''def_attr : ID COLON TYPE ASSIGN expr + | ID COLON TYPE''' + try: + p[0] = DefAttrNode(p[1], p[3], p[5]) + except: + p[0] = DefAttrNode(p[1], p[3]) def p_def_func(p): - '''def_func : ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKET''' + '''def_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET''' p[0] = DefFuncNode(p[1], p[3], p[6], p[8]) +def p_params_ne(p): + '''params : param_list''' + p[0] = p[1] + + +def p_params_e(p): + '''params : empty''' + p[0] = [] + + def p_param_list(p): '''param_list : param COMMA param_list - | param - | empty''' - if len(p) == 4: + | param empty''' + try: p[0] = [p[1]] + p[3] - else: + except: p[0] = [p[1]] @@ -80,24 +93,31 @@ def p_param(p): p[0] = (p[1], p[3]) -def p_expr_list(p): - '''expr_list : expr expr_list - | expr''' - if len(p) == 3: - p[0] = [p[1]] + p[2] - else: - p[0] = [p[1]] +def p_expr_flow(p): + '''expr : LET let_attrs IN expr + | CASE expr OF case_list ESAC + | IF expr THEN expr ELSE expr FI + | WHILE expr LOOP expr POOL''' + + if p[1].lower() == 'let': + p[0] = LetNode(p[2], p[4]) + elif p[1].lower() == 'case': + p[0] = CaseNode(p[2], p[4]) + elif p[1].lower() == 'if': + p[0] = IfNode(p[2], p[4], p[6]) + elif p[1].lower() == 'while': + p[0] = WhileNode(p[2], p[4]) -def p_assign(p): - '''assign : ID ASSIGN expr''' +def p_expr_assign(p): + '''expr : ID ASSIGN expr''' p[0] = AssignNode(p[1], p[3]) -def p_func_call(p): - '''func_call : expr AT TYPE DOT ID OPAREN arg_list CPAREN - | expr DOT ID OPAREN arg_list CPAREN - | ID OPAREN arg_list CPAREN''' +def p_expr_func_all(p): + '''expr : expr AT TYPE DOT ID OPAREN arg_list CPAREN + | expr DOT ID OPAREN arg_list CPAREN + | ID OPAREN arg_list CPAREN''' if len(p) == 9: p[0] = FuncCallNode(p[1], p[3], p[5], p[7]) elif len(p) == 7: @@ -106,178 +126,132 @@ def p_func_call(p): p[0] = FuncCallNode(p[1], p[3]) -def p_arg_list(p): - '''arg_list : expr COMMA arg_list - | expr - | empty''' - if len(p) == 4: - p[0] = [p[1]] + p[3] - else: - p[0] = [p[1]] +def p_expr_operators_binary(p): + '''expr : expr PLUS expr + | expr MINUS expr + | expr STAR expr + | expr DIV expr + | expr LOWER expr + | expr LOWEREQ expr + | expr EQUAL expr''' + if p[2] == '+': + p[0] = PlusNode(p[1], p[3]) + elif p[2] == '-': + p[0] = MinusNode(p[1], p[3]) + elif p[2] == '*': + p[0] = PlusNode(p[1], p[3]) + elif p[2] == '/': + p[0] = DivNode(p[1], p[3]) + elif p[2] == '<': + p[0] = LessThanNode(p[1], p[3]) + elif p[2] == '<=': + p[0] = LessEqNode(p[1], p[3]) + elif p[2] == '=': + p[0] = EqNode(p[1], p[3]) -def p_if_expr(p): - '''if_expr : IF expr THEN expr ELSE expr FI''' - p[0] = IfNode(p[2], p[4], p[6]) +def p_expr_operators_unary(p): + '''expr : NOT expr + | ISVOID expr + | LNOT expr''' + if p[1] == '~': + p[0] = NegationNode(p[2]) + elif p[1].lower() == 'isvoid': + p[0] = IsVoidNode(p[2]) + elif p[1].lower() == 'not': + p[0] = LogicNegationNode(p[2]) -def p_loop_expr(p): - '''loop_expr : WHILE expr LOOP expr POOL''' - p[0] = LoopNode(p[2], p[4]) +def p_expr_group(p): + '''expr : OPAREN expr CPAREN''' + p[0] = p[2] -def p_block(p): - '''block : OBRACKET block_list CBRACKET''' - p[0] = p[2] +def p_expr_atom(p): + '''expr : atom''' + p[0] = p[1] -def p_block_list(p): - '''block_list : expr SEMICOLON block_list - | expr SEMICOLON''' - if len(p) == 4: +def p_let_attrs(p): + '''let_attrs : def_attr COMMA let_attrs + | def_attr''' + try: p[0] = [p[1]] + p[3] - else: + except: p[0] = [p[1]] -def p_let_expr(p): - '''let_expr : LET assign_list IN expr''' - p[0] = LetNode(p[2], p[4]) - - -def p_assign_list(p): - '''assign_list : assign_elem COMMA assign_list - | assign_elem''' - if len(p) == 4: +def p_case_list(p): + '''case_list : case_elem SEMICOLON case_list + | case_elem SEMICOLON''' + try: p[0] = [p[1]] + p[3] - else: + except: p[0] = [p[1]] -def p_assign_elem(p): - '''assign_elem : ID COLON TYPE assign_oper''' - p[0] = (p[1], p[4], p[3]) - - -def p_assign_oper(p): - '''assign_oper : ASSIGN expr - | empty''' - if len(p) == 3: - p[0] = p[2] - else: - p[0] = None +def p_case_elem(p): + '''case_elem : ID COLON TYPE ARROW expr''' + p[0] = CaseElemNode(p[5], p[1], p[3]) -def p_case_expr(p): - '''case_expr : CASE expr OF case_list ESAC''' - p[0] = CaseNode(p[2], p[4]) +def p_arg_list(p): + '''arg_list : arg_list_ne + | empty''' + p[0] = [p[1]] -def p_case_list(p): - '''case_list : case_elem SEMICOLON case_list - | case_elem SEMICOLON''' +def p_arg_list_ne(p): + '''arg_list_ne : expr COMMA arg_list_ne + | expr ''' if len(p) == 4: p[0] = [p[1]] + p[3] else: p[0] = [p[1]] -def p_case_elem(p): - '''case_elem : ID COLON TYPE ARROW expr''' - p[0] = CaseElemNode(p[5], p[1], p[3]) +def p_atom_int(p): + '''atom : INT''' + p[0] = IntNode(int(p[1])) -def p_init_expr(p): - '''init_expr : NEW TYPE''' - p[0] = InitNode(p[2]) +def p_atom_id(p): + '''atom : ID''' + p[0] = VarNode(p[1]) -def p_expr(p): - '''expr : NOT expr - | cmp - | e''' - if len(p) == 3: - p[0] = LogicNegationNode(p[2]) - else: - p[0] = p[1] +def p_atom_new(p): + '''atom : NEW TYPE''' + p[0] = NewNode(p[2]) -def p_cmp(p): - '''cmp : e LOWER e - | e GREATER e - | e EQUAL e - | e GREATEREQ e - | e LOWEREQ e''' - if p[2] == '>': - p[0] = GreaterThanNode(p[1], p[3]) - elif p[2] == '<': - p[0] = LessThanNode(p[1], p[3]) - elif p[2] == 'GREATEREQ': - p[0] = GreaterEqNode(p[1], p[3]) - elif p[2] == 'LOWEREQ': - p[0] = LessEqNode(p[1], p[3]) - elif p[2] == '=': - p[0] = EqNode(p[1], p[3]) +def p_atom_block(p): + '''atom : block''' + p[0] = p[1] -def p_e(p): - '''e : e PLUS t - | e MINUS t - | t''' - if len(p) == 2: - p[0] = p[1] - else: - if p[2] == '+': - p[0] = PlusNode(p[1], p[3]) - elif p[2] == '-': - p[0] = MinusNode(p[1], p[3]) - - -def p_t(p): - '''t : t STAR f - | t DIV f - | f''' - if len(p) == 2: - p[0] = p[1] - else: - if p[2] == '*': - p[0] = StarNode(p[1], p[3]) - elif p[2] == '/': - p[0] = DivNode(p[1], p[3]) - pass +def p_atom_bool(p): + '''atom : BOOL''' + p[0] = BoolNode(p[1].lower()) -def p_f(p): - '''f : NOT f - | OPAREN expr CPAREN - | atom - | ISVOID f''' - if len(p) == 4: - p[0] = p[2] - if len(p) == 3: - if p[1] == '~': - p[0] = NegationNode(p[2]) - if p[1] == 'ISVOID': - p[0] = IsVoidNode(p[2]) - else: - p[0] = p[1] - pass +def p_atom_atring(p): + '''atom : STRING''' + p[0] = StringNode(p[1]) -def p_atom(p): - '''atom : ID - | INT - | BOOL - | STRING - | assign - | func_call - | if_expr - | loop_expr - | block - | let_expr - | case_expr - | init_expr''' - p[0] = AtomNode(p[1]) +def p_block(p): + '''block : OBRACKET block_list CBRACKET''' + p[0] = p[2] + + +def p_block_list(p): + '''block_list : expr SEMICOLON block_list + | expr SEMICOLON''' + if len(p) == 4: + p[0] = [p[1]] + p[3] + else: + p[0] = [p[1]] def p_error(p): diff --git a/src/parsetab.py b/src/parsetab.py index 20931c86..31fa1724 100644 --- a/src/parsetab.py +++ b/src/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftGREATEREQLOWEREQLOWERGREATEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI GREATER GREATEREQ ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class class_list\n | def_classdef_class : CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLONfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : assign_elemdef_func : ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKETparam_list : param COMMA param_list\n | param\n | emptyparam : ID COLON TYPEexpr_list : expr expr_list\n | exprassign : ID ASSIGN exprfunc_call : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENarg_list : expr COMMA arg_list\n | expr\n | emptyif_expr : IF expr THEN expr ELSE expr FIloop_expr : WHILE expr LOOP expr POOLblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLONlet_expr : LET assign_list IN exprassign_list : assign_elem COMMA assign_list\n | assign_elemassign_elem : ID COLON TYPE assign_operassign_oper : ASSIGN expr\n | emptycase_expr : CASE expr OF case_list ESACcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprinit_expr : NEW TYPEexpr : NOT expr\n | cmp\n | ecmp : e LOWER e\n | e GREATER e\n | e EQUAL e\n | e GREATEREQ e\n | e LOWEREQ ee : e PLUS t\n | e MINUS t\n | tt : t STAR f\n | t DIV f\n | ff : NOT f\n | OPAREN expr CPAREN\n | atom\n | ISVOID fatom : ID\n | INT\n | BOOL\n | STRING\n | assign\n | func_call\n | if_expr\n | loop_expr\n | block\n | let_expr\n | case_expr\n | init_expr' +_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,3,22,68,],[4,4,-5,-6,]),'$end':([1,2,3,5,22,68,],[0,-1,-4,-3,-5,-6,]),'TYPE':([4,8,20,31,39,67,70,145,],[6,15,29,38,69,97,99,150,]),'OBRACKET':([6,15,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,69,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[7,21,64,64,-42,-43,-51,-54,64,-57,64,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,64,64,64,64,98,-41,-54,64,64,64,64,64,64,64,64,64,-58,64,64,64,-40,64,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,64,64,-27,64,64,64,64,-21,64,-30,64,-26,-36,64,-20,-25,64,-19,]),'INHERITS':([6,],[8,]),'ID':([7,17,18,19,21,33,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,71,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,120,121,123,124,125,126,127,131,141,142,143,144,146,147,152,153,154,],[14,14,14,25,14,25,50,50,-42,-43,-51,-54,50,-57,50,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,50,50,50,95,50,100,-41,-54,50,50,50,50,50,50,50,50,50,-58,50,50,50,-40,50,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,50,50,-27,50,50,95,135,50,138,50,-21,50,-30,50,-26,-36,135,50,-20,-25,50,-19,]),'CBRACKET':([7,9,12,17,18,21,23,24,30,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,91,97,101,102,103,104,105,106,107,108,109,110,111,117,118,122,123,126,130,131,137,142,143,147,152,154,],[-2,16,-9,-2,-2,-2,-7,-8,37,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,117,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-29,136,-17,-21,-28,-30,-16,-26,-36,-20,-25,-19,]),'SEMICOLON':([10,11,13,16,29,34,36,37,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,92,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,134,136,142,143,147,152,154,155,],[17,18,-10,22,-2,-33,-35,68,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,118,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,144,-11,-26,-36,-20,-25,-19,-39,]),'OPAREN':([14,35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,100,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,138,141,142,143,146,147,152,153,154,],[19,47,47,-42,-43,-51,-54,47,-57,47,88,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,47,47,47,47,-41,-54,47,47,47,47,47,47,47,47,47,-58,47,47,47,-40,47,125,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,47,47,-27,47,47,47,47,-21,47,-30,146,47,-26,-36,47,-20,-25,47,-19,]),'COLON':([14,25,32,95,135,],[20,31,39,20,145,]),'CPAREN':([19,26,27,28,33,38,40,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,88,97,101,102,103,104,105,106,107,108,109,110,111,112,113,114,117,125,126,127,131,139,140,142,143,146,147,151,152,154,],[-2,32,-13,-14,-2,-15,-12,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,110,-58,-2,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,126,-23,-24,-27,-2,-21,-2,-30,147,-22,-26,-36,-2,-20,154,-25,-19,]),'COMMA':([27,29,34,36,38,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,94,97,101,102,103,104,105,106,107,108,109,110,111,113,117,126,131,142,143,147,152,154,],[33,-2,-33,-35,-15,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,120,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,127,-27,-21,-30,-26,-36,-20,-25,-19,]),'ASSIGN':([29,50,],[35,87,]),'IN':([29,34,36,41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,93,94,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,132,142,143,147,152,154,],[-2,-33,-35,-34,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,119,-32,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-31,-26,-36,-20,-25,-19,]),'NOT':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[42,42,-42,-43,-51,-54,42,-57,85,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,42,42,42,42,-41,-54,85,85,85,85,85,85,85,85,85,-58,85,42,42,-40,42,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,42,42,-27,42,42,42,42,-21,42,-30,42,-26,-36,42,-20,-25,42,-19,]),'ISVOID':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[49,49,-42,-43,-51,-54,49,-57,49,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,49,49,49,49,-41,-54,49,49,49,49,49,49,49,49,49,-58,49,49,49,-40,49,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,49,49,-27,49,49,49,49,-21,49,-30,49,-26,-36,49,-20,-25,49,-19,]),'INT':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[51,51,-42,-43,-51,-54,51,-57,51,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,51,51,51,51,-41,-54,51,51,51,51,51,51,51,51,51,-58,51,51,51,-40,51,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,51,51,-27,51,51,51,51,-21,51,-30,51,-26,-36,51,-20,-25,51,-19,]),'BOOL':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[52,52,-42,-43,-51,-54,52,-57,52,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,52,52,52,52,-41,-54,52,52,52,52,52,52,52,52,52,-58,52,52,52,-40,52,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,52,52,-27,52,52,52,52,-21,52,-30,52,-26,-36,52,-20,-25,52,-19,]),'STRING':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[53,53,-42,-43,-51,-54,53,-57,53,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,53,53,53,53,-41,-54,53,53,53,53,53,53,53,53,53,-58,53,53,53,-40,53,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,53,53,-27,53,53,53,53,-21,53,-30,53,-26,-36,53,-20,-25,53,-19,]),'IF':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[62,62,-42,-43,-51,-54,62,-57,62,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,62,62,62,62,-41,-54,62,62,62,62,62,62,62,62,62,-58,62,62,62,-40,62,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,62,62,-27,62,62,62,62,-21,62,-30,62,-26,-36,62,-20,-25,62,-19,]),'WHILE':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[63,63,-42,-43,-51,-54,63,-57,63,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,63,63,63,63,-41,-54,63,63,63,63,63,63,63,63,63,-58,63,63,63,-40,63,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,63,63,-27,63,63,63,63,-21,63,-30,63,-26,-36,63,-20,-25,63,-19,]),'LET':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[65,65,-42,-43,-51,-54,65,-57,65,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,65,65,65,65,-41,-54,65,65,65,65,65,65,65,65,65,-58,65,65,65,-40,65,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,65,65,-27,65,65,65,65,-21,65,-30,65,-26,-36,65,-20,-25,65,-19,]),'CASE':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[66,66,-42,-43,-51,-54,66,-57,66,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,66,66,66,66,-41,-54,66,66,66,66,66,66,66,66,66,-58,66,66,66,-40,66,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,66,66,-27,66,66,66,66,-21,66,-30,66,-26,-36,66,-20,-25,66,-19,]),'NEW':([35,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,72,73,74,75,76,77,78,79,80,81,82,84,85,87,88,97,98,101,102,103,104,105,106,107,108,109,110,111,115,116,117,118,119,123,125,126,127,131,141,142,143,146,147,152,153,154,],[67,67,-42,-43,-51,-54,67,-57,67,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,67,67,67,67,-41,-54,67,67,67,67,67,67,67,67,67,-58,67,67,67,-40,67,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,67,67,-27,67,67,67,67,-21,67,-30,67,-26,-36,67,-20,-25,67,-19,]),'AT':([41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,86,89,90,92,96,97,101,102,103,104,105,106,107,108,109,110,111,113,117,123,126,128,129,131,142,143,147,148,152,154,155,],[70,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,70,-54,70,70,70,70,70,-40,-43,-43,-43,-43,-43,-49,-50,-52,-53,-56,-18,70,-27,70,-21,70,70,70,-26,-36,-20,70,-25,-19,70,]),'DOT':([41,43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,83,84,86,89,90,92,96,97,99,101,102,103,104,105,106,107,108,109,110,111,113,117,123,126,128,129,131,142,143,147,148,152,154,155,],[71,-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,71,-54,71,71,71,71,71,-40,124,-43,-43,-43,-43,-43,-49,-50,-52,-53,-56,-18,71,-27,71,-21,71,71,71,-26,-36,-20,71,-25,-19,71,]),'THEN':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,89,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,115,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOOP':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,90,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,116,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'OF':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,96,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,121,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'STAR':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,81,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'DIV':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,-43,82,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOWER':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,74,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'GREATER':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,75,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'EQUAL':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,76,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'GREATEREQ':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,77,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'LOWEREQ':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,78,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'PLUS':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,79,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'MINUS':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,152,154,],[-42,80,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-54,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,-25,-19,]),'ELSE':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,128,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,141,-30,-26,-36,-20,-25,-19,]),'POOL':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,129,131,142,143,147,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,142,-30,-26,-36,-20,-25,-19,]),'FI':([43,44,45,46,48,50,51,52,53,54,55,56,57,58,59,60,61,72,73,84,97,101,102,103,104,105,106,107,108,109,110,111,117,126,131,142,143,147,148,152,154,],[-42,-43,-51,-54,-57,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-41,-54,-58,-40,-44,-45,-46,-47,-48,-49,-50,-52,-53,-56,-18,-27,-21,-30,-26,-36,-20,152,-25,-19,]),'ESAC':([133,144,149,],[143,-38,-37,]),'ARROW':([150,],[153,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,-22,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,-22,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,-22,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,-22,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,-22,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,-22,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,-22,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,-22,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,-22,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): @@ -17,7 +17,7 @@ _lr_action[_x][_k] = _y del _lr_action_items -_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,3,],[2,5,]),'def_class':([0,3,],[3,3,]),'feature_list':([7,17,18,21,],[9,23,24,30,]),'def_attr':([7,17,18,21,],[10,10,10,10,]),'def_func':([7,17,18,21,],[11,11,11,11,]),'empty':([7,17,18,19,21,29,33,88,125,127,146,],[12,12,12,28,12,36,28,114,114,114,114,]),'assign_elem':([7,17,18,21,65,120,],[13,13,13,13,94,94,]),'param_list':([19,33,],[26,40,]),'param':([19,33,],[27,27,]),'assign_oper':([29,],[34,]),'expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[41,72,83,86,89,90,92,96,86,86,86,86,86,86,86,86,86,72,111,113,123,128,129,92,131,123,113,113,148,113,155,]),'cmp':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,]),'e':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[44,44,44,44,44,44,44,44,101,102,103,104,105,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'t':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[45,45,45,45,45,45,45,45,45,45,45,45,45,106,107,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'f':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[46,73,46,84,46,46,46,46,46,46,46,46,46,46,46,108,109,73,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'atom':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'assign':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,]),'func_call':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,]),'if_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,]),'loop_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,]),'block':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,]),'let_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,]),'case_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,]),'init_expr':([35,42,47,49,62,63,64,66,74,75,76,77,78,79,80,81,82,85,87,88,98,115,116,118,119,123,125,127,141,146,153,],[61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,]),'block_list':([64,118,],[91,130,]),'assign_list':([65,120,],[93,132,]),'arg_list':([88,125,127,146,],[112,139,140,151,]),'expr_list':([98,123,],[122,137,]),'case_list':([121,144,],[133,149,]),'case_elem':([121,144,],[134,134,]),} +_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,5,],[2,7,]),'def_class':([0,5,],[3,3,]),'feature_list':([8,17,18,21,],[10,22,23,30,]),'def_attr':([8,17,18,21,39,97,],[11,11,11,11,69,69,]),'def_func':([8,17,18,21,],[12,12,12,12,]),'empty':([8,17,18,20,21,29,58,108,127,],[13,13,13,28,13,35,85,85,85,]),'params':([20,],[26,]),'param_list':([20,34,],[27,56,]),'param':([20,34,],[29,29,]),'expr':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[38,71,72,73,74,75,76,77,80,82,86,89,90,91,92,93,94,95,109,114,115,80,117,86,86,131,86,136,]),'atom':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,]),'block':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,]),'let_attrs':([39,97,],[68,110,]),'block_list':([53,103,],[79,116,]),'arg_list':([58,108,127,],[83,120,132,]),'arg_list_ne':([58,106,108,127,],[84,118,84,84,]),'case_list':([98,122,],[111,129,]),'case_elem':([98,122,],[112,112,]),} _lr_goto = {} for _k, _v in _lr_goto_items.items(): @@ -29,72 +29,57 @@ ("S' -> program","S'",1,None,None,None), ('program -> class_list','program',1,'p_program','parser.py',20), ('empty -> ','empty',0,'p_empty','parser.py',25), - ('class_list -> def_class class_list','class_list',2,'p_class_list','parser.py',30), - ('class_list -> def_class','class_list',1,'p_class_list','parser.py',31), - ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET SEMICOLON','def_class',6,'p_def_class','parser.py',40), - ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET SEMICOLON','def_class',8,'p_def_class','parser.py',41), + ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',30), + ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), + ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), + ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), - ('def_attr -> assign_elem','def_attr',1,'p_def_attr','parser.py',59), - ('def_func -> ID OPAREN param_list CPAREN COLON TYPE OBRACKET expr_list CBRACKET','def_func',9,'p_def_func','parser.py',64), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',69), - ('param_list -> param','param_list',1,'p_param_list','parser.py',70), - ('param_list -> empty','param_list',1,'p_param_list','parser.py',71), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',79), - ('expr_list -> expr expr_list','expr_list',2,'p_expr_list','parser.py',84), - ('expr_list -> expr','expr_list',1,'p_expr_list','parser.py',85), - ('assign -> ID ASSIGN expr','assign',3,'p_assign','parser.py',93), - ('func_call -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','func_call',8,'p_func_call','parser.py',98), - ('func_call -> expr DOT ID OPAREN arg_list CPAREN','func_call',6,'p_func_call','parser.py',99), - ('func_call -> ID OPAREN arg_list CPAREN','func_call',4,'p_func_call','parser.py',100), - ('arg_list -> expr COMMA arg_list','arg_list',3,'p_arg_list','parser.py',110), - ('arg_list -> expr','arg_list',1,'p_arg_list','parser.py',111), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',112), - ('if_expr -> IF expr THEN expr ELSE expr FI','if_expr',7,'p_if_expr','parser.py',120), - ('loop_expr -> WHILE expr LOOP expr POOL','loop_expr',5,'p_loop_expr','parser.py',125), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',130), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',135), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',136), - ('let_expr -> LET assign_list IN expr','let_expr',4,'p_let_expr','parser.py',144), - ('assign_list -> assign_elem COMMA assign_list','assign_list',3,'p_assign_list','parser.py',149), - ('assign_list -> assign_elem','assign_list',1,'p_assign_list','parser.py',150), - ('assign_elem -> ID COLON TYPE assign_oper','assign_elem',4,'p_assign_elem','parser.py',158), - ('assign_oper -> ASSIGN expr','assign_oper',2,'p_assign_oper','parser.py',163), - ('assign_oper -> empty','assign_oper',1,'p_assign_oper','parser.py',164), - ('case_expr -> CASE expr OF case_list ESAC','case_expr',5,'p_case_expr','parser.py',172), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',177), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',178), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',186), - ('init_expr -> NEW TYPE','init_expr',2,'p_init_expr','parser.py',191), - ('expr -> NOT expr','expr',2,'p_expr','parser.py',196), - ('expr -> cmp','expr',1,'p_expr','parser.py',197), - ('expr -> e','expr',1,'p_expr','parser.py',198), - ('cmp -> e LOWER e','cmp',3,'p_cmp','parser.py',206), - ('cmp -> e GREATER e','cmp',3,'p_cmp','parser.py',207), - ('cmp -> e EQUAL e','cmp',3,'p_cmp','parser.py',208), - ('cmp -> e GREATEREQ e','cmp',3,'p_cmp','parser.py',209), - ('cmp -> e LOWEREQ e','cmp',3,'p_cmp','parser.py',210), - ('e -> e PLUS t','e',3,'p_e','parser.py',224), - ('e -> e MINUS t','e',3,'p_e','parser.py',225), - ('e -> t','e',1,'p_e','parser.py',226), - ('t -> t STAR f','t',3,'p_t','parser.py',237), - ('t -> t DIV f','t',3,'p_t','parser.py',238), - ('t -> f','t',1,'p_t','parser.py',239), - ('f -> NOT f','f',2,'p_f','parser.py',251), - ('f -> OPAREN expr CPAREN','f',3,'p_f','parser.py',252), - ('f -> atom','f',1,'p_f','parser.py',253), - ('f -> ISVOID f','f',2,'p_f','parser.py',254), - ('atom -> ID','atom',1,'p_atom','parser.py',268), - ('atom -> INT','atom',1,'p_atom','parser.py',269), - ('atom -> BOOL','atom',1,'p_atom','parser.py',270), - ('atom -> STRING','atom',1,'p_atom','parser.py',271), - ('atom -> assign','atom',1,'p_atom','parser.py',272), - ('atom -> func_call','atom',1,'p_atom','parser.py',273), - ('atom -> if_expr','atom',1,'p_atom','parser.py',274), - ('atom -> loop_expr','atom',1,'p_atom','parser.py',275), - ('atom -> block','atom',1,'p_atom','parser.py',276), - ('atom -> let_expr','atom',1,'p_atom','parser.py',277), - ('atom -> case_expr','atom',1,'p_atom','parser.py',278), - ('atom -> init_expr','atom',1,'p_atom','parser.py',279), + ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',59), + ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',60), + ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',68), + ('params -> param_list','params',1,'p_params_ne','parser.py',73), + ('params -> empty','params',1,'p_params_e','parser.py',78), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',83), + ('param_list -> param empty','param_list',2,'p_param_list','parser.py',84), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',92), + ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',97), + ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',98), + ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',99), + ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',100), + ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',113), + ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',118), + ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',119), + ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',120), + ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',130), + ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',131), + ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',132), + ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',133), + ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',134), + ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',135), + ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',136), + ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',154), + ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',155), + ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',156), + ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',166), + ('expr -> atom','expr',1,'p_expr_atom','parser.py',171), + ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',176), + ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',177), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',185), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',186), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',194), + ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',199), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',200), + ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',205), + ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',206), + ('atom -> INT','atom',1,'p_atom_int','parser.py',214), + ('atom -> ID','atom',1,'p_atom_id','parser.py',219), + ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',224), + ('atom -> block','atom',1,'p_atom_block','parser.py',229), + ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',234), + ('atom -> STRING','atom',1,'p_atom_atring','parser.py',239), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',244), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',249), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',250), ] From 81838036fc6744e4eeb8feea8615751494d24f35 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:09:13 -0400 Subject: [PATCH 045/435] Add visitor pattern to AST --- src/ast.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/ast.py b/src/ast.py index 164ddbd0..88abe08c 100644 --- a/src/ast.py +++ b/src/ast.py @@ -1,22 +1,28 @@ -class ProgramNode: +class AstNode: + def accept(self, visitor): + visitor.visit(self) + + +class ProgramNode(AstNode): def __init__(self, classes: list): self.classes = classes -class DefClassNode: +class DefClassNode(AstNode): def __init__(self, type, features, parent_type=None): self.type = type self.feature_nodes = features self.parent_type = parent_type -class FeatureNode: - pass +class FeatureNode(AstNode): + def __init__(self, id): + self.id = id class DefAttrNode(FeatureNode): def __init__(self, id, type, expr=None): - self.id = id + super().__init__(id) self.type = type self.expr = expr @@ -26,19 +32,19 @@ def __index__(self): class DefFuncNode(FeatureNode): def __init__(self, id, params, return_type, expressions): - self.id = id + super().__init__(id) self.params = params self.return_type = return_type self.expressions = expressions -class AssignNode: +class AssignNode(AstNode): def __init__(self, id, expr): self.id = id self.expr = expr -class FuncCallNode: +class FuncCallNode(AstNode): def __init__(self, id, args, object=None, type=None): self.object = object self.type = type @@ -46,49 +52,49 @@ def __init__(self, id, args, object=None, type=None): self.args = args -class IfNode: +class IfNode(AstNode): def __init__(self, if_expr, then_expr, else_expr): self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr -class WhileNode: +class WhileNode(AstNode): def __init__(self, cond, body): self.cond = cond self.body = body -class BlockNode: +class BlockNode(AstNode): def __init__(self, expressions): self.expressions = expressions -class LetNode: +class LetNode(AstNode): def __init__(self, let_attrs, expr): self.let_attrs = let_attrs self.expr = expr -class CaseNode: +class CaseNode(AstNode): def __init__(self, expr, case_list): self.expr = expr self.case_list = case_list -class CaseElemNode: +class CaseElemNode(AstNode): def __init__(self, expr, id, type): self.expr = expr self.id = id self.type = type -class InitNode: +class InitNode(AstNode): def __init__(self, type): self.type = type -class ExpressionNode: +class ExpressionNode(AstNode): pass @@ -147,17 +153,17 @@ class IsVoidNode(UnaryNode): pass -class VarNode: +class VarNode(AstNode): def __init__(self, id): self.id = id -class NewNode: +class NewNode(AstNode): def __init__(self, t): self.type = t -class ConstantNode: +class ConstantNode(AstNode): def __init__(self, value): self.value = value From 65bb4b5f63cadc6193bbd4d2c33a65dfc2f8c5b7 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:09:44 -0400 Subject: [PATCH 046/435] Add semantic error manager --- src/errors.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/errors.py b/src/errors.py index f1b77487..079babe4 100644 --- a/src/errors.py +++ b/src/errors.py @@ -1,5 +1,6 @@ LEXER_ERRORS = [] PARSER_ERRORS = [] +SEMANTIC_ERRORS = [] def add_lexer_error(line, column, message): @@ -8,3 +9,7 @@ def add_lexer_error(line, column, message): def add_parser_error(line, column, message): PARSER_ERRORS.append(f'({line}, {column}) - SyntacticError: {message}') + + +def add_semantic_error(line, column, message): + SEMANTIC_ERRORS.append(f'({line}, {column}) - SemanticError: {message}') From f1113cd7ac3d03281e78de870a99cd8be3eba544 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:32:59 -0400 Subject: [PATCH 047/435] Move errors to package --- src/errors/__init__.py | 1 + src/{ => errors}/errors.py | 0 2 files changed, 1 insertion(+) create mode 100644 src/errors/__init__.py rename src/{ => errors}/errors.py (100%) diff --git a/src/errors/__init__.py b/src/errors/__init__.py new file mode 100644 index 00000000..0179aa8a --- /dev/null +++ b/src/errors/__init__.py @@ -0,0 +1 @@ +from .errors import * diff --git a/src/errors.py b/src/errors/errors.py similarity index 100% rename from src/errors.py rename to src/errors/errors.py From b13dfbc3cd1ac38434ab3ac90b797e56b6c4820b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:42:00 -0400 Subject: [PATCH 048/435] Move lexer and parser to package --- src/{ => lexer_parser}/ast.py | 0 src/{ => lexer_parser}/lexer.py | 0 src/{ => lexer_parser}/parser.py | 4 ++-- src/main.py | 5 ++--- 4 files changed, 4 insertions(+), 5 deletions(-) rename src/{ => lexer_parser}/ast.py (100%) rename src/{ => lexer_parser}/lexer.py (100%) rename src/{ => lexer_parser}/parser.py (99%) diff --git a/src/ast.py b/src/lexer_parser/ast.py similarity index 100% rename from src/ast.py rename to src/lexer_parser/ast.py diff --git a/src/lexer.py b/src/lexer_parser/lexer.py similarity index 100% rename from src/lexer.py rename to src/lexer_parser/lexer.py diff --git a/src/parser.py b/src/lexer_parser/parser.py similarity index 99% rename from src/parser.py rename to src/lexer_parser/parser.py index 0b481e61..1b433aa7 100644 --- a/src/parser.py +++ b/src/lexer_parser/parser.py @@ -1,7 +1,7 @@ import ply.yacc as yacc -from lexer import * +from .lexer import * from errors import add_parser_error -from ast import * +from .ast import * precedence = ( ('left', 'DOT'), diff --git a/src/main.py b/src/main.py index b483fa2a..0411c10d 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,6 @@ -import lexer as lex -import parser as p import sys import errors as err +from lexer_parser import lexer, parser def exit_with_error(error): @@ -20,7 +19,7 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - ast = p.parser.parse(input_data, lex.lexer) + ast = parser.parse(input_data, lexer) if err.LEXER_ERRORS: for e in err.LEXER_ERRORS: print(e) From 720381c0229154f0e245cf88b492ef5a976b07a8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:45:44 -0400 Subject: [PATCH 049/435] Add missing files --- src/lexer_parser/__init__.py | 2 + src/lexer_parser/parsetab.py | 85 ++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/lexer_parser/__init__.py create mode 100644 src/lexer_parser/parsetab.py diff --git a/src/lexer_parser/__init__.py b/src/lexer_parser/__init__.py new file mode 100644 index 00000000..49e147dc --- /dev/null +++ b/src/lexer_parser/__init__.py @@ -0,0 +1,2 @@ +from .lexer import lexer +from .parser import parser diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py new file mode 100644 index 00000000..31fa1724 --- /dev/null +++ b/src/lexer_parser/parsetab.py @@ -0,0 +1,85 @@ + +# parsetab.py +# This file is automatically generated. Do not edit. +# pylint: disable=W,C,R +_tabversion = '3.10' + +_lr_method = 'LALR' + +_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' + +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,-22,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,-22,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,-22,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,-22,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,-22,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,-22,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,-22,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,-22,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,-22,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} + +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items + +_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,5,],[2,7,]),'def_class':([0,5,],[3,3,]),'feature_list':([8,17,18,21,],[10,22,23,30,]),'def_attr':([8,17,18,21,39,97,],[11,11,11,11,69,69,]),'def_func':([8,17,18,21,],[12,12,12,12,]),'empty':([8,17,18,20,21,29,58,108,127,],[13,13,13,28,13,35,85,85,85,]),'params':([20,],[26,]),'param_list':([20,34,],[27,56,]),'param':([20,34,],[29,29,]),'expr':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[38,71,72,73,74,75,76,77,80,82,86,89,90,91,92,93,94,95,109,114,115,80,117,86,86,131,86,136,]),'atom':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,]),'block':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,]),'let_attrs':([39,97,],[68,110,]),'block_list':([53,103,],[79,116,]),'arg_list':([58,108,127,],[83,120,132,]),'arg_list_ne':([58,106,108,127,],[84,118,84,84,]),'case_list':([98,122,],[111,129,]),'case_elem':([98,122,],[112,112,]),} + +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +_lr_productions = [ + ("S' -> program","S'",1,None,None,None), + ('program -> class_list','program',1,'p_program','parser.py',20), + ('empty -> ','empty',0,'p_empty','parser.py',25), + ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',30), + ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), + ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), + ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), + ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), + ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), + ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), + ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',59), + ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',60), + ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',68), + ('params -> param_list','params',1,'p_params_ne','parser.py',73), + ('params -> empty','params',1,'p_params_e','parser.py',78), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',83), + ('param_list -> param empty','param_list',2,'p_param_list','parser.py',84), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',92), + ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',97), + ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',98), + ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',99), + ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',100), + ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',113), + ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',118), + ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',119), + ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',120), + ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',130), + ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',131), + ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',132), + ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',133), + ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',134), + ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',135), + ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',136), + ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',154), + ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',155), + ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',156), + ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',166), + ('expr -> atom','expr',1,'p_expr_atom','parser.py',171), + ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',176), + ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',177), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',185), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',186), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',194), + ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',199), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',200), + ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',205), + ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',206), + ('atom -> INT','atom',1,'p_atom_int','parser.py',214), + ('atom -> ID','atom',1,'p_atom_id','parser.py',219), + ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',224), + ('atom -> block','atom',1,'p_atom_block','parser.py',229), + ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',234), + ('atom -> STRING','atom',1,'p_atom_atring','parser.py',239), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',244), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',249), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',250), +] From fd1b0071360fde80304747f453d356e3648feea8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 10:51:12 -0400 Subject: [PATCH 050/435] Delete unnecessary file --- src/parsetab.py | 85 ------------------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 src/parsetab.py diff --git a/src/parsetab.py b/src/parsetab.py deleted file mode 100644 index 31fa1724..00000000 --- a/src/parsetab.py +++ /dev/null @@ -1,85 +0,0 @@ - -# parsetab.py -# This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' - -_lr_method = 'LALR' - -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' - -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,-22,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,-22,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,-22,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,-22,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,-22,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,-22,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,-22,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,-22,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,-22,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} - -_lr_action = {} -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = {} - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,5,],[2,7,]),'def_class':([0,5,],[3,3,]),'feature_list':([8,17,18,21,],[10,22,23,30,]),'def_attr':([8,17,18,21,39,97,],[11,11,11,11,69,69,]),'def_func':([8,17,18,21,],[12,12,12,12,]),'empty':([8,17,18,20,21,29,58,108,127,],[13,13,13,28,13,35,85,85,85,]),'params':([20,],[26,]),'param_list':([20,34,],[27,56,]),'param':([20,34,],[29,29,]),'expr':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[38,71,72,73,74,75,76,77,80,82,86,89,90,91,92,93,94,95,109,114,115,80,117,86,86,131,86,136,]),'atom':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,]),'block':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,]),'let_attrs':([39,97,],[68,110,]),'block_list':([53,103,],[79,116,]),'arg_list':([58,108,127,],[83,120,132,]),'arg_list_ne':([58,106,108,127,],[84,118,84,84,]),'case_list':([98,122,],[111,129,]),'case_elem':([98,122,],[112,112,]),} - -_lr_goto = {} -for _k, _v in _lr_goto_items.items(): - for _x, _y in zip(_v[0], _v[1]): - if not _x in _lr_goto: _lr_goto[_x] = {} - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> program","S'",1,None,None,None), - ('program -> class_list','program',1,'p_program','parser.py',20), - ('empty -> ','empty',0,'p_empty','parser.py',25), - ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',30), - ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), - ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), - ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), - ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), - ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), - ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), - ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',59), - ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',60), - ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',68), - ('params -> param_list','params',1,'p_params_ne','parser.py',73), - ('params -> empty','params',1,'p_params_e','parser.py',78), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',83), - ('param_list -> param empty','param_list',2,'p_param_list','parser.py',84), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',92), - ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',97), - ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',98), - ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',99), - ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',100), - ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',113), - ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',118), - ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',119), - ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',120), - ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',130), - ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',131), - ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',132), - ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',133), - ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',134), - ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',135), - ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',136), - ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',154), - ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',155), - ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',156), - ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',166), - ('expr -> atom','expr',1,'p_expr_atom','parser.py',171), - ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',176), - ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',177), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',185), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',186), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',194), - ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',199), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',200), - ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',205), - ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',206), - ('atom -> INT','atom',1,'p_atom_int','parser.py',214), - ('atom -> ID','atom',1,'p_atom_id','parser.py',219), - ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',224), - ('atom -> block','atom',1,'p_atom_block','parser.py',229), - ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',234), - ('atom -> STRING','atom',1,'p_atom_atring','parser.py',239), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',244), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',249), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',250), -] From 4be4ffeab129efbfcd69bad3088ed74c7da91ed3 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 23 Apr 2020 13:03:48 -0400 Subject: [PATCH 051/435] Initial Visitor --- src/lexer_parser/ast.py | 2 +- src/main.py | 7 +++ src/semantic/__init__.py | 1 + src/semantic/semantic.py | 111 +++++++++++++++++++++++++++++++++++++++ src/semantic/types.py | 15 ++++++ 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/semantic/__init__.py create mode 100644 src/semantic/semantic.py create mode 100644 src/semantic/types.py diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 88abe08c..1f0e7b04 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,6 +1,6 @@ class AstNode: def accept(self, visitor): - visitor.visit(self) + return visitor.visit(self) class ProgramNode(AstNode): diff --git a/src/main.py b/src/main.py index 0411c10d..f6df61d7 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,7 @@ import sys import errors as err from lexer_parser import lexer, parser +from semantic import semantic_check def exit_with_error(error): @@ -29,6 +30,12 @@ def main(): print(e) exit(1) + semantic_check(ast) + if err.SEMANTIC_ERRORS: + for e in err.SEMANTIC_ERRORS: + print(e) + exit(1) + if __name__ == "__main__": main() diff --git a/src/semantic/__init__.py b/src/semantic/__init__.py new file mode 100644 index 00000000..5c5a05f0 --- /dev/null +++ b/src/semantic/__init__.py @@ -0,0 +1 @@ +from .semantic import semantic_check diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py new file mode 100644 index 00000000..0d637efc --- /dev/null +++ b/src/semantic/semantic.py @@ -0,0 +1,111 @@ +from errors import add_semantic_error +from lexer_parser.ast import * +from .types import * + + +class Visitor: + def __init__(self, method_env, object_env, current_class): + self.MethodEnv = method_env + self.ObjectEnv = object_env + self.CurrentClass = current_class + + def visit(self, node): + pass + + +def __check_type_declaration__(node: ProgramNode): + for c in node.classes: + if c.type in Types: + add_semantic_error(0, 0, f'duplicated declaration of type {c.type}') + return False + else: + Types.append(c.type) + return True + + +def __check_type_hierarchy__(node: ProgramNode): + for c in node.classes: + if c.parent_type: + if c.parent_type in Types: + TypesHierarchy[c.type] = c.parent_type + else: + add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') + return False + else: + TypesHierarchy[c.type] = ObjectType + return True + + +class ProgramVisitor(Visitor): + def __init__(self): + super().__init__({}, {}, None) + + def visit(self, node: ProgramNode): + if not (__check_type_declaration__(node) and __check_type_hierarchy__(node)): + return + # Initialize MethodEnv + for c in node.classes: + className = c.type + for f in c.feature_nodes: + if type(f) is DefFuncNode: + functionName = f.id + functionArgsType = [a[1] for a in f.params] + self.MethodEnv[className, functionName] = functionArgsType + + # Visit each class inside + for c in node.classes: + c.accept(DefClassVisitor(self.MethodEnv)) + + +class DefClassVisitor(Visitor): + def __init__(self, method_env): + super().__init__(method_env, {}, None) + + def visit(self, node: DefClassNode): + # Set current class name + self.CurrentClass = node.type + # Initialize ObjectEnv + for feature in node.feature_nodes: + if type(feature) is DefAttrNode: + self.ObjectEnv[feature.id] = feature.type + # Check all features + for feature in node.feature_nodes: + if type(feature) is DefAttrNode: + feature.accept(DefAttrVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) + if type(feature) is DefFuncNode: + feature.accept(DefFuncVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) + + +class DefAttrVisitor(Visitor): + def __init__(self, method_env, object_env, current_class): + super().__init__(method_env, object_env, current_class) + + def visit(self, node: DefAttrNode): + if node.expr: + expr_type = node.expr.accept(DefExpressionVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) + if expr_type != self.ObjectEnv[node.id]: + add_semantic_error(0, 0, f'Invalid type {expr_type}') + + +class DefFuncVisitor(Visitor): + def __init__(self, method_env, object_env, current_class): + super().__init__(method_env, object_env, current_class) + + def visit(self, node: DefFuncNode): + pass + + +class DefExpressionVisitor(Visitor): + def __init__(self, method_env, object_env, current_class): + super().__init__(method_env, object_env, current_class) + + def visit(self, node): + if type(node) is IntNode: + return IntType + if type(node) is StringNode: + return StringType + + +def semantic_check(node): + if type(node) is ProgramNode: + node.accept(ProgramVisitor()) diff --git a/src/semantic/types.py b/src/semantic/types.py new file mode 100644 index 00000000..03ad4828 --- /dev/null +++ b/src/semantic/types.py @@ -0,0 +1,15 @@ +ObjectType = 'Object' +IOType = 'IO' +IntType = 'Int' +StringType = 'String' +BoolType = 'Bool' + +Types = [ObjectType, IOType, IntType, StringType, BoolType] + +TypesHierarchy = { + ObjectType: None, + IOType: ObjectType, + IntType: ObjectType, + StringType: ObjectType, + BoolType: ObjectType +} From a8c0c66ec5e4a627c15dc8c1f4c1f9b44cf28ca6 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 25 Apr 2020 11:30:51 -0400 Subject: [PATCH 052/435] Add new semantic checks --- src/semantic/semantic.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 0d637efc..538b5b0c 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -36,6 +36,18 @@ def __check_type_hierarchy__(node: ProgramNode): return True +def __check_inherits__(typeA, typeB): + ''' + Return True if typeA <= typeB + ''' + current = typeA + while current != typeB: + if current is None: + return False + current = TypesHierarchy[current] + return True + + class ProgramVisitor(Visitor): def __init__(self): super().__init__({}, {}, None) @@ -83,7 +95,7 @@ def __init__(self, method_env, object_env, current_class): def visit(self, node: DefAttrNode): if node.expr: expr_type = node.expr.accept(DefExpressionVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) - if expr_type != self.ObjectEnv[node.id]: + if not __check_inherits__(expr_type, self.ObjectEnv[node.id]): add_semantic_error(0, 0, f'Invalid type {expr_type}') @@ -104,6 +116,12 @@ def visit(self, node): return IntType if type(node) is StringNode: return StringType + if type(node) is VarNode: + try: + return self.ObjectEnv[node.id] + except KeyError: + add_semantic_error(0, 0, f'invalid variable {node.id}') + return def semantic_check(node): From f2e7dc16549d671bef289fbdd2631298ee4007e5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 25 Apr 2020 22:07:53 -0400 Subject: [PATCH 053/435] Add types structure --- src/semantic/semantic.py | 141 +++++++++++++++++++++++++++------------ src/semantic/types.py | 53 +++++++++++---- 2 files changed, 136 insertions(+), 58 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 538b5b0c..1f27daab 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -4,9 +4,7 @@ class Visitor: - def __init__(self, method_env, object_env, current_class): - self.MethodEnv = method_env - self.ObjectEnv = object_env + def __init__(self, current_class): self.CurrentClass = current_class def visit(self, node): @@ -15,113 +13,168 @@ def visit(self, node): def __check_type_declaration__(node: ProgramNode): for c in node.classes: - if c.type in Types: + try: + _ = TypesByName[c.type] add_semantic_error(0, 0, f'duplicated declaration of type {c.type}') return False - else: - Types.append(c.type) + except KeyError: + TypesByName[c.type] = CoolType(c.type, None) return True def __check_type_hierarchy__(node: ProgramNode): for c in node.classes: + cType = TypesByName[c.type] if c.parent_type: - if c.parent_type in Types: - TypesHierarchy[c.type] = c.parent_type - else: + try: + cType.parent = TypesByName[c.parent_type] + except KeyError: add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') return False else: - TypesHierarchy[c.type] = ObjectType + cType.parent = ObjectType return True -def __check_inherits__(typeA, typeB): - ''' - Return True if typeA <= typeB - ''' - current = typeA - while current != typeB: +def __check_inherits__(type_a: CoolType, type_b: CoolType): + """ + Return True if type_a <= typeB + """ + current = type_a + while current != type_b: if current is None: return False - current = TypesHierarchy[current] + current = current.parent return True class ProgramVisitor(Visitor): def __init__(self): - super().__init__({}, {}, None) + super().__init__(None) def visit(self, node: ProgramNode): if not (__check_type_declaration__(node) and __check_type_hierarchy__(node)): return + # Check Main class exists + try: + TypesByName['Main'] + except KeyError: + add_semantic_error(0, 0, f'Main class undeclared') + return # Initialize MethodEnv for c in node.classes: - className = c.type + classType = TypesByName[c.type] for f in c.feature_nodes: if type(f) is DefFuncNode: - functionName = f.id - functionArgsType = [a[1] for a in f.params] - self.MethodEnv[className, functionName] = functionArgsType + # Add all functions to types + functionArgsTypeNames = [a[1] for a in f.params] + functionArgsType = [] + for type_name in functionArgsTypeNames: + # Check all argument types + try: + functionArgsType.append(TypesByName[type_name]) + except KeyError: + add_semantic_error(0, 0, f'unknown type {type_name}') + return + # Check returned type + try: + returnType = TypesByName[f.return_type] + except KeyError: + add_semantic_error(0, 0, f'unknown type {f.return_type}') + return + try: + _ = classType.methods[f.id] + # Duplicated method declaration in same class, not overload allowed + add_semantic_error(0, 0, f'method {f.id} already declared in class {classType.name}') + except KeyError: + classType.methods[f.id] = CoolTypeMethod(f.id, functionArgsType, returnType) + elif type(f) is DefAttrNode: + # Add all attributes to types + try: + _ = classType.attributes[f.id] + add_semantic_error(0, 0, f'attribute {f.id} already declared') + except KeyError: + try: + attrType = TypesByName[f.type] + except KeyError: + add_semantic_error(0, 0, f'unknown type {f.type}') + return + classType.attributes[f.id] = CoolTypeAttribute(f.id, attrType) # Visit each class inside for c in node.classes: - c.accept(DefClassVisitor(self.MethodEnv)) + c.accept(DefClassVisitor()) class DefClassVisitor(Visitor): - def __init__(self, method_env): - super().__init__(method_env, {}, None) + def __init__(self): + super().__init__(None) def visit(self, node: DefClassNode): - # Set current class name - self.CurrentClass = node.type - # Initialize ObjectEnv - for feature in node.feature_nodes: - if type(feature) is DefAttrNode: - self.ObjectEnv[feature.id] = feature.type + self.CurrentClass = TypesByName[node.type] # Check all features for feature in node.feature_nodes: if type(feature) is DefAttrNode: - feature.accept(DefAttrVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) + feature.accept(DefAttrVisitor(self.CurrentClass)) if type(feature) is DefFuncNode: - feature.accept(DefFuncVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) + feature.accept(DefFuncVisitor(self.CurrentClass)) class DefAttrVisitor(Visitor): - def __init__(self, method_env, object_env, current_class): - super().__init__(method_env, object_env, current_class) + def __init__(self, current_class): + super().__init__(current_class) def visit(self, node: DefAttrNode): if node.expr: - expr_type = node.expr.accept(DefExpressionVisitor(self.MethodEnv, self.ObjectEnv, self.CurrentClass)) - if not __check_inherits__(expr_type, self.ObjectEnv[node.id]): + expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass)) + attr_type = self.CurrentClass.attributes[node.id].attrType + if not __check_inherits__(expr_type, attr_type): add_semantic_error(0, 0, f'Invalid type {expr_type}') + else: + return attr_type class DefFuncVisitor(Visitor): - def __init__(self, method_env, object_env, current_class): - super().__init__(method_env, object_env, current_class) + def __init__(self, current_class): + super().__init__(current_class) def visit(self, node: DefFuncNode): - pass + body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) + return_type = TypesByName[node.return_type] + if __check_inherits__(body_type, return_type): + return return_type + elif body_type is not None: + add_semantic_error(0, 0, f'invalid returned type {body_type}') class DefExpressionVisitor(Visitor): - def __init__(self, method_env, object_env, current_class): - super().__init__(method_env, object_env, current_class) + def __init__(self, current_class): + super().__init__(current_class) def visit(self, node): if type(node) is IntNode: return IntType if type(node) is StringNode: return StringType + if type(node) is BoolNode: + return BoolType if type(node) is VarNode: try: - return self.ObjectEnv[node.id] + return self.CurrentClass.attributes[node.id].attrType except KeyError: add_semantic_error(0, 0, f'invalid variable {node.id}') - return + return None + if type(node) is AssignNode: + try: + varType = self.CurrentClass.attributes[node.id].attrType + except KeyError: + add_semantic_error(0, 0, f'invalid variable {node.id}') + return None + expressionType = node.accept(DefExpressionVisitor(self.CurrentClass)) + if __check_inherits__(expressionType, varType): + return varType + else: + return None def semantic_check(node): diff --git a/src/semantic/types.py b/src/semantic/types.py index 03ad4828..52c643a1 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -1,15 +1,40 @@ -ObjectType = 'Object' -IOType = 'IO' -IntType = 'Int' -StringType = 'String' -BoolType = 'Bool' - -Types = [ObjectType, IOType, IntType, StringType, BoolType] - -TypesHierarchy = { - ObjectType: None, - IOType: ObjectType, - IntType: ObjectType, - StringType: ObjectType, - BoolType: ObjectType +class CoolType: + def __init__(self, name, parent_type): + self.name = name + self.parent = parent_type + self.attributes = {} + self.methods = {} + + def __repr__(self): + return f'{self.name}' + + def __str__(self): + return f'{self.name}' + + +class CoolTypeAttribute: + def __init__(self, id, attr_type): + self.id = id + self.attrType = attr_type + + +class CoolTypeMethod: + def __init__(self, id, args, returned_type): + self.returnedType = returned_type + self.id = id + self.args = args + + +ObjectType = CoolType('Object', None) +IOType = CoolType('IO', ObjectType) +IntType = CoolType('Int', ObjectType) +StringType = CoolType('String', ObjectType) +BoolType = CoolType('Bool', ObjectType) + +TypesByName = { + 'Object': ObjectType, + 'IO': IOType, + 'Int': IntType, + 'String': StringType, + 'Bool': BoolType } From 74d2eca5263de7c2a1f13b8b2ea6243756b7d552 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 26 Apr 2020 10:09:33 -0400 Subject: [PATCH 054/435] Move some functions to types.py --- src/semantic/semantic.py | 46 +++++----------------------------------- src/semantic/types.py | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 1f27daab..a6f7dd9f 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -11,49 +11,12 @@ def visit(self, node): pass -def __check_type_declaration__(node: ProgramNode): - for c in node.classes: - try: - _ = TypesByName[c.type] - add_semantic_error(0, 0, f'duplicated declaration of type {c.type}') - return False - except KeyError: - TypesByName[c.type] = CoolType(c.type, None) - return True - - -def __check_type_hierarchy__(node: ProgramNode): - for c in node.classes: - cType = TypesByName[c.type] - if c.parent_type: - try: - cType.parent = TypesByName[c.parent_type] - except KeyError: - add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') - return False - else: - cType.parent = ObjectType - return True - - -def __check_inherits__(type_a: CoolType, type_b: CoolType): - """ - Return True if type_a <= typeB - """ - current = type_a - while current != type_b: - if current is None: - return False - current = current.parent - return True - - class ProgramVisitor(Visitor): def __init__(self): super().__init__(None) def visit(self, node: ProgramNode): - if not (__check_type_declaration__(node) and __check_type_hierarchy__(node)): + if not (check_type_declaration(node) and check_type_hierarchy(node)): return # Check Main class exists try: @@ -128,7 +91,7 @@ def visit(self, node: DefAttrNode): if node.expr: expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass)) attr_type = self.CurrentClass.attributes[node.id].attrType - if not __check_inherits__(expr_type, attr_type): + if not check_inherits(expr_type, attr_type): add_semantic_error(0, 0, f'Invalid type {expr_type}') else: return attr_type @@ -141,7 +104,7 @@ def __init__(self, current_class): def visit(self, node: DefFuncNode): body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) return_type = TypesByName[node.return_type] - if __check_inherits__(body_type, return_type): + if check_inherits(body_type, return_type): return return_type elif body_type is not None: add_semantic_error(0, 0, f'invalid returned type {body_type}') @@ -171,10 +134,11 @@ def visit(self, node): add_semantic_error(0, 0, f'invalid variable {node.id}') return None expressionType = node.accept(DefExpressionVisitor(self.CurrentClass)) - if __check_inherits__(expressionType, varType): + if check_inherits(expressionType, varType): return varType else: return None + print(f'Not rule for {type(node)} in DefExpressionVisitor') def semantic_check(node): diff --git a/src/semantic/types.py b/src/semantic/types.py index 52c643a1..d2045367 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -1,3 +1,7 @@ +from lexer_parser.ast import * +from errors import add_semantic_error + + class CoolType: def __init__(self, name, parent_type): self.name = name @@ -24,6 +28,9 @@ def __init__(self, id, args, returned_type): self.id = id self.args = args + def __repr__(self): + return f'{self.id}{self.args}:{self.returnedType}' + ObjectType = CoolType('Object', None) IOType = CoolType('IO', ObjectType) @@ -38,3 +45,40 @@ def __init__(self, id, args, returned_type): 'String': StringType, 'Bool': BoolType } + + +def check_inherits(type_a: CoolType, type_b: CoolType): + """ + Return True if type_a <= typeB + """ + current = type_a + while current != type_b: + if current is None: + return False + current = current.parent + return True + + +def check_type_declaration(node: ProgramNode): + for c in node.classes: + try: + _ = TypesByName[c.type] + add_semantic_error(0, 0, f'duplicated declaration of type {c.type}') + return False + except KeyError: + TypesByName[c.type] = CoolType(c.type, None) + return True + + +def check_type_hierarchy(node: ProgramNode): + for c in node.classes: + cType = TypesByName[c.type] + if c.parent_type: + try: + cType.parent = TypesByName[c.parent_type] + except KeyError: + add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') + return False + else: + cType.parent = ObjectType + return True From 9a7819fe1eb8e2d15d7b78d2906ec957c4c180a0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 27 Apr 2020 11:16:20 -0400 Subject: [PATCH 055/435] Make better types administration: - Move method build to types structure - Add initial SELF_TYPE tools - Add hierarchy restrictions - Add initial methods for default classes - Reorganize types.py file --- src/semantic/semantic.py | 41 +++------------- src/semantic/types.py | 102 +++++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 49 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index a6f7dd9f..93d19b70 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -29,41 +29,14 @@ def visit(self, node: ProgramNode): classType = TypesByName[c.type] for f in c.feature_nodes: if type(f) is DefFuncNode: - # Add all functions to types - functionArgsTypeNames = [a[1] for a in f.params] - functionArgsType = [] - for type_name in functionArgsTypeNames: - # Check all argument types - try: - functionArgsType.append(TypesByName[type_name]) - except KeyError: - add_semantic_error(0, 0, f'unknown type {type_name}') - return - # Check returned type - try: - returnType = TypesByName[f.return_type] - except KeyError: - add_semantic_error(0, 0, f'unknown type {f.return_type}') - return - try: - _ = classType.methods[f.id] - # Duplicated method declaration in same class, not overload allowed - add_semantic_error(0, 0, f'method {f.id} already declared in class {classType.name}') - except KeyError: - classType.methods[f.id] = CoolTypeMethod(f.id, functionArgsType, returnType) + result, msg = classType.add_method(f.id, f.params, f.return_type) + if not result: + add_semantic_error(0, 0, msg) elif type(f) is DefAttrNode: # Add all attributes to types - try: - _ = classType.attributes[f.id] - add_semantic_error(0, 0, f'attribute {f.id} already declared') - except KeyError: - try: - attrType = TypesByName[f.type] - except KeyError: - add_semantic_error(0, 0, f'unknown type {f.type}') - return - classType.attributes[f.id] = CoolTypeAttribute(f.id, attrType) - + result, msg = classType.add_attr(f.id, f.type) + if not result: + add_semantic_error(0, 0, msg) # Visit each class inside for c in node.classes: c.accept(DefClassVisitor()) @@ -103,7 +76,7 @@ def __init__(self, current_class): def visit(self, node: DefFuncNode): body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) - return_type = TypesByName[node.return_type] + return_type = type_by_name(node.return_type, self.CurrentClass.name) if check_inherits(body_type, return_type): return return_type elif body_type is not None: diff --git a/src/semantic/types.py b/src/semantic/types.py index d2045367..9a7500f6 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -3,11 +3,57 @@ class CoolType: - def __init__(self, name, parent_type): + def __init__(self, name, parent_type, inherit=True): self.name = name self.parent = parent_type self.attributes = {} self.methods = {} + self.inherit = inherit + + def __can_be_define_hierarchy__(self, id): + try: + method = self.methods[id] + if method.redefine: + return True, None + return False, f'method {id} in class {self.name} can\'t be redefine' + except KeyError: + if self.parent: + return self.parent.__can_be_define_hierarchy__(id) + return True, None + + def __can_be_define__(self, id): + if id in self.methods.keys(): + return False, f'method {id} already declared in class {self.name}' + return self.__can_be_define_hierarchy__(id) + + def add_method(self, id, arg_types, returned_type): + ok, msg = self.__can_be_define__(id) + if ok: + arg_types_name = [a[1] for a in arg_types] + arg_types = [] + for arg in arg_types_name: + arg_type = type_by_name(arg, self.name) + if arg_type is None: + return False, f'unknown type {arg}' + arg_types.append(arg_type) + returned_type = type_by_name(returned_type, self.name) + if returned_type is None: + return False, f'unknown type {returned_type}' + self.methods[id] = CoolTypeMethod(id, arg_types, returned_type) + return True, None + else: + return False, msg + + def add_attr(self, id, attr_type): + try: + _ = self.attributes[id] + return False, f'attribute {id} already declared in class {self.name}' + except KeyError: + attr_type = type_by_name(attr_type, self.name) + if attr_type is None: + return False, f'unknown type {attr_type}' + self.attributes[id] = CoolTypeAttribute(id, attr_type) + return True, None def __repr__(self): return f'{self.name}' @@ -32,19 +78,13 @@ def __repr__(self): return f'{self.id}{self.args}:{self.returnedType}' -ObjectType = CoolType('Object', None) -IOType = CoolType('IO', ObjectType) -IntType = CoolType('Int', ObjectType) -StringType = CoolType('String', ObjectType) -BoolType = CoolType('Bool', ObjectType) - -TypesByName = { - 'Object': ObjectType, - 'IO': IOType, - 'Int': IntType, - 'String': StringType, - 'Bool': BoolType -} +def type_by_name(type_name, current_class): + if type_name == 'SELF_TYPE': + return current_class + try: + return TypesByName[type_name] + except KeyError: + return None def check_inherits(type_a: CoolType, type_b: CoolType): @@ -75,10 +115,42 @@ def check_type_hierarchy(node: ProgramNode): cType = TypesByName[c.type] if c.parent_type: try: - cType.parent = TypesByName[c.parent_type] + parentType = TypesByName[c.parent_type] + if parentType.inherit: + cType.parent = parentType + else: + add_semantic_error(0, 0, f'can\'t be inherit from class {parentType.name}') + return False except KeyError: add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') return False else: cType.parent = ObjectType return True + + +SelfType = CoolType('SELF_TYPE', None) +ObjectType = CoolType('Object', None) +IOType = CoolType('IO', ObjectType) +IntType = CoolType('Int', ObjectType, False) +StringType = CoolType('String', ObjectType, False) +BoolType = CoolType('Bool', ObjectType, False) + +TypesByName = { + 'Object': ObjectType, + 'IO': IOType, + 'Int': IntType, + 'String': StringType, + 'Bool': BoolType +} + +ObjectType.add_method('abort', [], 'Object') +ObjectType.add_method('type_name', [], 'String') +ObjectType.add_method('copy', [], 'SELF_TYPE') +IOType.add_method('out_string', ['String'], 'SELF_TYPE') +IOType.add_method('out_int', ['Int'], 'SELF_TYPE') +IOType.add_method('in_string', [], 'String') +IOType.add_method('in_int', [], 'Int') +StringType.add_method('length', [], 'Int') +StringType.add_method('concat', ['String'], 'String') +StringType.add_method('substr', ['Int', 'Int'], 'String') From 5db7f85edd20a420e6a561b5e5e032a2d6216d9b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 27 Apr 2020 16:45:32 -0400 Subject: [PATCH 056/435] Fix little bug in parser --- src/lexer_parser/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 1b433aa7..a8ec4f8f 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -198,7 +198,7 @@ def p_case_elem(p): def p_arg_list(p): '''arg_list : arg_list_ne | empty''' - p[0] = [p[1]] + p[0] = p[1] def p_arg_list_ne(p): From a26379f1414163dbf244f49e1e8ba12ebb9f41ee Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 27 Apr 2020 16:46:39 -0400 Subject: [PATCH 057/435] Initial check for function calls --- src/semantic/semantic.py | 11 +++++++++++ src/semantic/types.py | 20 +++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 93d19b70..71dcc785 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -111,6 +111,17 @@ def visit(self, node): return varType else: return None + if type(node) is FuncCallNode: + args_types = [] + for a in node.args: + a_type = a.accept(DefExpressionVisitor(self.CurrentClass)) + if a_type: + args_types.append(a_type) + if node.object: + print('Not rule for FuncCall from var') + else: + method, msg = self.CurrentClass.get_method(node.id, args_types) + return method.returnedType print(f'Not rule for {type(node)} in DefExpressionVisitor') diff --git a/src/semantic/types.py b/src/semantic/types.py index 9a7500f6..7f37a52b 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -26,10 +26,9 @@ def __can_be_define__(self, id): return False, f'method {id} already declared in class {self.name}' return self.__can_be_define_hierarchy__(id) - def add_method(self, id, arg_types, returned_type): + def add_method(self, id, arg_types_name, returned_type): ok, msg = self.__can_be_define__(id) if ok: - arg_types_name = [a[1] for a in arg_types] arg_types = [] for arg in arg_types_name: arg_type = type_by_name(arg, self.name) @@ -44,6 +43,21 @@ def add_method(self, id, arg_types, returned_type): else: return False, msg + def get_method(self, id, args_types): + try: + method = self.methods[id] + if len(args_types) != len(method.args): + return None, f'arguments count mismatch' + for i, a in enumerate(args_types): + if a != method.args[i]: + return None, f'type of argument {i} mismatch' + return method, None + except KeyError: + if self.parent: + return self.parent.get_method(id, args_types) + else: + return None, f'unknown method {id}' + def add_attr(self, id, attr_type): try: _ = self.attributes[id] @@ -80,7 +94,7 @@ def __repr__(self): def type_by_name(type_name, current_class): if type_name == 'SELF_TYPE': - return current_class + return TypesByName[current_class] try: return TypesByName[type_name] except KeyError: From 9c0f7f8d2843caf7dd29fcee618ad9ddfe9675f6 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 12:15:55 -0400 Subject: [PATCH 058/435] Add empty list in function call without arguments Replacing the value None with an empty list because None produces an error afterwards, in semantic verification --- src/lexer_parser/parser.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index a8ec4f8f..ca0891f7 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -123,6 +123,8 @@ def p_expr_func_all(p): elif len(p) == 7: p[0] = FuncCallNode(p[3], p[5], p[1]) else: + if p[3] is None: + p[3] = [] p[0] = FuncCallNode(p[1], p[3]) From 9a30103612680e70991f2f89ebf1b3bb6406eb19 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 12:18:59 -0400 Subject: [PATCH 059/435] Fix bug Previously, a tuple was passed as an argument, whereas only the second argument is needed --- src/semantic/semantic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 71dcc785..184cf44f 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -29,7 +29,8 @@ def visit(self, node: ProgramNode): classType = TypesByName[c.type] for f in c.feature_nodes: if type(f) is DefFuncNode: - result, msg = classType.add_method(f.id, f.params, f.return_type) + param_types = [param[1] for param in f.params] + result, msg = classType.add_method(f.id, param_types, f.return_type) if not result: add_semantic_error(0, 0, msg) elif type(f) is DefAttrNode: From cf94b1c07d4bff37990ca880888eb140416f9792 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 12:22:03 -0400 Subject: [PATCH 060/435] Fix bug Body of a DefFunctionNode can be a list of expressions, this case not was considered --- src/semantic/semantic.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 184cf44f..97bdc387 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -76,8 +76,14 @@ def __init__(self, current_class): super().__init__(current_class) def visit(self, node: DefFuncNode): - body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) - return_type = type_by_name(node.return_type, self.CurrentClass.name) + if type(node.expressions) is list: + for exp in node.expressions: + body_type = exp.accept(DefExpressionVisitor(self.CurrentClass)) + if body_type is None: + break + else: + body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) + return_type = type_by_name(node.return_type) if check_inherits(body_type, return_type): return return_type elif body_type is not None: From bf5de9b1352b51ac687e2dd1038e6ddca8093e3b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 12:26:47 -0400 Subject: [PATCH 061/435] Fix SELF_TYPE bug SELF_TYPE needs to be resolved in the type check returned, not when the method declaration is checked. In short, SELF_TYPE must survive the type hierarchy --- src/semantic/semantic.py | 2 ++ src/semantic/types.py | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 97bdc387..54a1ac1f 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -128,6 +128,8 @@ def visit(self, node): print('Not rule for FuncCall from var') else: method, msg = self.CurrentClass.get_method(node.id, args_types) + if method.returnedType == SelfType: + return self.CurrentClass return method.returnedType print(f'Not rule for {type(node)} in DefExpressionVisitor') diff --git a/src/semantic/types.py b/src/semantic/types.py index 7f37a52b..203d3730 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -31,11 +31,11 @@ def add_method(self, id, arg_types_name, returned_type): if ok: arg_types = [] for arg in arg_types_name: - arg_type = type_by_name(arg, self.name) + arg_type = type_by_name(arg) if arg_type is None: return False, f'unknown type {arg}' arg_types.append(arg_type) - returned_type = type_by_name(returned_type, self.name) + returned_type = type_by_name(returned_type) if returned_type is None: return False, f'unknown type {returned_type}' self.methods[id] = CoolTypeMethod(id, arg_types, returned_type) @@ -63,7 +63,7 @@ def add_attr(self, id, attr_type): _ = self.attributes[id] return False, f'attribute {id} already declared in class {self.name}' except KeyError: - attr_type = type_by_name(attr_type, self.name) + attr_type = type_by_name(attr_type) if attr_type is None: return False, f'unknown type {attr_type}' self.attributes[id] = CoolTypeAttribute(id, attr_type) @@ -92,9 +92,7 @@ def __repr__(self): return f'{self.id}{self.args}:{self.returnedType}' -def type_by_name(type_name, current_class): - if type_name == 'SELF_TYPE': - return TypesByName[current_class] +def type_by_name(type_name): try: return TypesByName[type_name] except KeyError: @@ -143,7 +141,7 @@ def check_type_hierarchy(node: ProgramNode): return True -SelfType = CoolType('SELF_TYPE', None) +SelfType = CoolType('SELF_TYPE', None, False) ObjectType = CoolType('Object', None) IOType = CoolType('IO', ObjectType) IntType = CoolType('Int', ObjectType, False) @@ -151,6 +149,7 @@ def check_type_hierarchy(node: ProgramNode): BoolType = CoolType('Bool', ObjectType, False) TypesByName = { + 'SELF_TYPE': SelfType, 'Object': ObjectType, 'IO': IOType, 'Int': IntType, From 464b0c18d31859cc04d8bcc10375c792b2e63551 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 12:46:14 -0400 Subject: [PATCH 062/435] Add type check for EqNode EqNode return a Bool type --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 54a1ac1f..406f2e1a 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -99,7 +99,7 @@ def visit(self, node): return IntType if type(node) is StringNode: return StringType - if type(node) is BoolNode: + if type(node) in [BoolNode, EqNode]: return BoolType if type(node) is VarNode: try: From a49dc0f94fff0672e889c0757679021367fd3dd9 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 14:56:15 -0400 Subject: [PATCH 063/435] Fix bug in parser Change wrong PlusNode for StaNode in * symbol --- src/lexer_parser/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index ca0891f7..fbbf4779 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -141,7 +141,7 @@ def p_expr_operators_binary(p): elif p[2] == '-': p[0] = MinusNode(p[1], p[3]) elif p[2] == '*': - p[0] = PlusNode(p[1], p[3]) + p[0] = StarNode(p[1], p[3]) elif p[2] == '/': p[0] = DivNode(p[1], p[3]) elif p[2] == '<': From 048f692f0a3da84211f00ae07e882e09d28223e0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 17:46:25 -0400 Subject: [PATCH 064/435] Type checking for binary arithmetic operators Check the type of PlusNode, MinusNode, StarNode and DivNode. All this nodes get and return an Int type. --- src/semantic/semantic.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 406f2e1a..afb190db 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -107,6 +107,16 @@ def visit(self, node): except KeyError: add_semantic_error(0, 0, f'invalid variable {node.id}') return None + if type(node) in [StarNode, PlusNode, DivNode, MinusNode]: + lvalue_type = node.lvalue.accept(DefExpressionVisitor(self.CurrentClass)) + if lvalue_type != IntType and lvalue_type is not None: + add_semantic_error(0, 0, f'invalid left value type') + return None + rvalue_type = node.rvalue.accept(DefExpressionVisitor(self.CurrentClass)) + if rvalue_type != IntType and rvalue_type is not None: + add_semantic_error(0, 0, f'invalid right value type') + return None + return IntType if type(node) is AssignNode: try: varType = self.CurrentClass.attributes[node.id].attrType From ac549ac045459836d6f0adf4b05f234deacc3472 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 18:55:42 -0400 Subject: [PATCH 065/435] Add __type_hierarchy__ Return a sorted list with all hierarchy of types from type_x to Object --- src/semantic/types.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/semantic/types.py b/src/semantic/types.py index 203d3730..270536f2 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -141,6 +141,14 @@ def check_type_hierarchy(node: ProgramNode): return True +def __type_hierarchy__(type_x): + h = [] + while type_x is not None: + h.append(type_x) + type_x = type_x.parent + return h + + SelfType = CoolType('SELF_TYPE', None, False) ObjectType = CoolType('Object', None) IOType = CoolType('IO', ObjectType) From c07ada6d64ac0cf254c493e69f8894b913e61962 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 18:58:58 -0400 Subject: [PATCH 066/435] Add pronounced_join function join_pronoun (A, B) = C if C is the first type such that A < C and B < C --- src/semantic/types.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/semantic/types.py b/src/semantic/types.py index 270536f2..5d3cbc87 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -149,6 +149,15 @@ def __type_hierarchy__(type_x): return h +def pronounced_join(type_a, type_b): + h = __type_hierarchy__(type_b) + while type_a is not None: + if type_a in h: + break + type_a = type_a.parent + return type_a + + SelfType = CoolType('SELF_TYPE', None, False) ObjectType = CoolType('Object', None) IOType = CoolType('IO', ObjectType) From a772e71217794b9ca9c0fe50ef4dd96532f4fdbf Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 19:10:59 -0400 Subject: [PATCH 067/435] Add check type for IfNode "if" condition need be Bool and returned type of IfNode is the pronounced join of "then" type and "else" type --- src/semantic/semantic.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index afb190db..876c3d89 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -128,6 +128,16 @@ def visit(self, node): return varType else: return None + if type(node) is IfNode: + if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass)) + if if_expr_type != BoolType: + add_semantic_error(0, 0, f'\"if\" expression must be a Bool type') + return + then_expr_type = node.then_expr.accept(DefExpressionVisitor(self.CurrentClass)) + else_expr_type = node.else_expr.accept(DefExpressionVisitor(self.CurrentClass)) + if then_expr_type is None or else_expr_type is None: + return + return pronounced_join(then_expr_type, else_expr_type) if type(node) is FuncCallNode: args_types = [] for a in node.args: From d361dee9e730c40330f3fccb07a0422dfdcf023f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 28 Apr 2020 19:42:01 -0400 Subject: [PATCH 068/435] Add local scope For now only function arguments have been added to the local scope. Every time the local scope is modified, a copy is passed to the child expressions. --- src/semantic/semantic.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 876c3d89..8b5acbab 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -4,8 +4,9 @@ class Visitor: - def __init__(self, current_class): + def __init__(self, current_class, local_scope=None): self.CurrentClass = current_class + self.LocalScope = local_scope if local_scope else {} def visit(self, node): pass @@ -76,13 +77,16 @@ def __init__(self, current_class): super().__init__(current_class) def visit(self, node: DefFuncNode): + local_scope = self.LocalScope.copy() + for arg in node.params: + local_scope[arg[0]] = type_by_name(arg[1]) if type(node.expressions) is list: for exp in node.expressions: - body_type = exp.accept(DefExpressionVisitor(self.CurrentClass)) + body_type = exp.accept(DefExpressionVisitor(self.CurrentClass, local_scope)) if body_type is None: break else: - body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass)) + body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass, local_scope)) return_type = type_by_name(node.return_type) if check_inherits(body_type, return_type): return return_type @@ -91,8 +95,8 @@ def visit(self, node: DefFuncNode): class DefExpressionVisitor(Visitor): - def __init__(self, current_class): - super().__init__(current_class) + def __init__(self, current_class, local_scope=None): + super().__init__(current_class, local_scope) def visit(self, node): if type(node) is IntNode: @@ -102,17 +106,19 @@ def visit(self, node): if type(node) in [BoolNode, EqNode]: return BoolType if type(node) is VarNode: + if node.id in self.LocalScope.keys(): + return self.LocalScope[node.id] try: return self.CurrentClass.attributes[node.id].attrType except KeyError: add_semantic_error(0, 0, f'invalid variable {node.id}') return None if type(node) in [StarNode, PlusNode, DivNode, MinusNode]: - lvalue_type = node.lvalue.accept(DefExpressionVisitor(self.CurrentClass)) + lvalue_type = node.lvalue.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if lvalue_type != IntType and lvalue_type is not None: add_semantic_error(0, 0, f'invalid left value type') return None - rvalue_type = node.rvalue.accept(DefExpressionVisitor(self.CurrentClass)) + rvalue_type = node.rvalue.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(0, 0, f'invalid right value type') return None @@ -129,19 +135,19 @@ def visit(self, node): else: return None if type(node) is IfNode: - if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass)) + if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if if_expr_type != BoolType: add_semantic_error(0, 0, f'\"if\" expression must be a Bool type') return - then_expr_type = node.then_expr.accept(DefExpressionVisitor(self.CurrentClass)) - else_expr_type = node.else_expr.accept(DefExpressionVisitor(self.CurrentClass)) + then_expr_type = node.then_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) + else_expr_type = node.else_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if then_expr_type is None or else_expr_type is None: return return pronounced_join(then_expr_type, else_expr_type) if type(node) is FuncCallNode: args_types = [] for a in node.args: - a_type = a.accept(DefExpressionVisitor(self.CurrentClass)) + a_type = a.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if a_type: args_types.append(a_type) if node.object: From ea753169502f44d9ac3ca60e19ab85ef73ed97a4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 12:23:42 -0400 Subject: [PATCH 069/435] Add LetNode and DefAttrNode type verification LetNode has a list of attributes, each one is added to the local scope and has the following properties: * There can only be one attribute with the same ID. * The ID of an attribute can be equal to the ID of another variable in the global scope, because the local scope has a higher priority. The DefAttrNode checker checks if its attribute type exists and if the expression type inherits from that --- src/semantic/semantic.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 8b5acbab..f9762ea1 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -134,6 +134,26 @@ def visit(self, node): return varType else: return None + if type(node) is DefAttrNode: + attr_type = type_by_name(node.type) + if attr_type is None: + add_semantic_error(0, 0, f'unknown type {node.type}') + return None + if node.expr: + expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) + if check_inherits(expr_type, attr_type): + return attr_type + else: + add_semantic_error(0, 0, f'type {expr_type.name} cannot be stored in an {attr_type.name}') + return None + return attr_type + if type(node) is LetNode: + for attr in node.let_attrs: + attr_type = attr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) + if attr_type is None: + return None + self.LocalScope[attr.id] = attr_type + return None if type(node) is IfNode: if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if if_expr_type != BoolType: From 2a6802e1bb1b1bfc6e447c11b7e939c5f36ae95e Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 16:10:17 -0400 Subject: [PATCH 070/435] Fix bug In the "let" structure the attributes can only be used within it, then LocalSocope must be a copy of the current LocalScope --- src/semantic/semantic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index f9762ea1..90267544 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -148,6 +148,7 @@ def visit(self, node): return None return attr_type if type(node) is LetNode: + self.LocalScope = self.LocalScope.copy() for attr in node.let_attrs: attr_type = attr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if attr_type is None: From 01daf11f2958a37a980b2281bbf105d8022cce6d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 16:14:50 -0400 Subject: [PATCH 071/435] Checking the type for the "let" structure body --- src/semantic/semantic.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 90267544..375eca16 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -154,7 +154,9 @@ def visit(self, node): if attr_type is None: return None self.LocalScope[attr.id] = attr_type - return None + expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) + if expr_type is not None: + return expr_type if type(node) is IfNode: if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) if if_expr_type != BoolType: From 2377551c952d5c5d7591359a19be69b5a86c44c5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 16:45:47 -0400 Subject: [PATCH 072/435] Check if attribute already exists It is illegal to redefine attribute names --- src/semantic/types.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index 5d3cbc87..bb826c5c 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -59,9 +59,12 @@ def get_method(self, id, args_types): return None, f'unknown method {id}' def add_attr(self, id, attr_type): + attribute, owner_type = get_attribute(self, id) + if attribute is not None: + return False, f'attribute \"{id}\" already declared in class \"{owner_type.name}\"' try: _ = self.attributes[id] - return False, f'attribute {id} already declared in class {self.name}' + return False, f'attribute \"{id}\" already declared in class \"{self.name}\"' except KeyError: attr_type = type_by_name(attr_type) if attr_type is None: @@ -76,6 +79,15 @@ def __str__(self): return f'{self.name}' +def get_attribute(type_c: CoolType, id: str): + while type_c is not None: + try: + return type_c.attributes[id], type_c + except KeyError: + type_c = type_c.parent + return None, None + + class CoolTypeAttribute: def __init__(self, id, attr_type): self.id = id From 839628f4348b80a4e2c34ec5a754a7f91555dc3f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 22:23:41 -0400 Subject: [PATCH 073/435] Fix bug Add an empty list to function calls with no arguments --- src/lexer_parser/parser.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index fbbf4779..6f8ce1fa 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -119,8 +119,12 @@ def p_expr_func_all(p): | expr DOT ID OPAREN arg_list CPAREN | ID OPAREN arg_list CPAREN''' if len(p) == 9: - p[0] = FuncCallNode(p[1], p[3], p[5], p[7]) + if p[7] is None: + p[7] = [] + p[0] = FuncCallNode(p[5], p[7], p[1], p[3]) elif len(p) == 7: + if p[5] is None: + p[5] = [] p[0] = FuncCallNode(p[3], p[5], p[1]) else: if p[3] is None: From 43be21d7411b1de54b2b6a21f414b69d12b9321d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 29 Apr 2020 22:26:02 -0400 Subject: [PATCH 074/435] Change get method pipeline Add get_method_without_hierarchy for search in current type without hierarchy searches --- src/semantic/types.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index bb826c5c..027d4cec 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -10,21 +10,10 @@ def __init__(self, name, parent_type, inherit=True): self.methods = {} self.inherit = inherit - def __can_be_define_hierarchy__(self, id): - try: - method = self.methods[id] - if method.redefine: - return True, None - return False, f'method {id} in class {self.name} can\'t be redefine' - except KeyError: - if self.parent: - return self.parent.__can_be_define_hierarchy__(id) - return True, None - def __can_be_define__(self, id): if id in self.methods.keys(): return False, f'method {id} already declared in class {self.name}' - return self.__can_be_define_hierarchy__(id) + return True, None def add_method(self, id, arg_types_name, returned_type): ok, msg = self.__can_be_define__(id) @@ -44,6 +33,15 @@ def add_method(self, id, arg_types_name, returned_type): return False, msg def get_method(self, id, args_types): + try: + return self.get_method_without_hierarchy(id, args_types) + except Exception: + if self.parent: + return self.parent.get_method(id, args_types) + else: + return None, f'unknown method {id}' + + def get_method_without_hierarchy(self, id, args_types): try: method = self.methods[id] if len(args_types) != len(method.args): @@ -53,10 +51,7 @@ def get_method(self, id, args_types): return None, f'type of argument {i} mismatch' return method, None except KeyError: - if self.parent: - return self.parent.get_method(id, args_types) - else: - return None, f'unknown method {id}' + raise Exception(f'type {self.name} don\'t have a method {id}') def add_attr(self, id, attr_type): attribute, owner_type = get_attribute(self, id) From 71370a16ba1f05d1dcf026772608b90fc180109d Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 30 Apr 2020 02:28:56 -0400 Subject: [PATCH 075/435] Add lineno info to ast nodes --- src/lexer_parser/ast.py | 3 +++ src/lexer_parser/parser.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 1f0e7b04..b0a0cafa 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,4 +1,7 @@ class AstNode: + def __init__(self): + self.lineno = 0 + def accept(self, visitor): return visitor.visit(self) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 6f8ce1fa..f5a13297 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -19,6 +19,7 @@ def p_program(p): 'program : class_list' p[0] = ProgramNode(p[1]) + p[0].lineno = p.lineno(0) def p_empty(p): @@ -44,6 +45,8 @@ def p_def_class(p): else: p[0] = DefClassNode(p[2], p[4]) + p[0].lineno = p.lineno(0) + def p_feature_list(p): '''feature_list : def_attr SEMICOLON feature_list @@ -63,10 +66,13 @@ def p_def_attr_declaration(p): except: p[0] = DefAttrNode(p[1], p[3]) + p[0].lineno = p.lineno(0) + def p_def_func(p): '''def_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET''' p[0] = DefFuncNode(p[1], p[3], p[6], p[8]) + p[0].lineno = p.lineno(0) def p_params_ne(p): @@ -108,10 +114,13 @@ def p_expr_flow(p): elif p[1].lower() == 'while': p[0] = WhileNode(p[2], p[4]) + p[0].lineno = p.lineno(0) + def p_expr_assign(p): '''expr : ID ASSIGN expr''' p[0] = AssignNode(p[1], p[3]) + p[0].lineno = p.lineno(0) def p_expr_func_all(p): @@ -130,6 +139,8 @@ def p_expr_func_all(p): if p[3] is None: p[3] = [] p[0] = FuncCallNode(p[1], p[3]) + + p[0].lineno = p.lineno(0) def p_expr_operators_binary(p): @@ -155,6 +166,8 @@ def p_expr_operators_binary(p): elif p[2] == '=': p[0] = EqNode(p[1], p[3]) + p[0].lineno = p.lineno(0) + def p_expr_operators_unary(p): '''expr : NOT expr @@ -167,6 +180,8 @@ def p_expr_operators_unary(p): elif p[1].lower() == 'not': p[0] = LogicNegationNode(p[2]) + p[0].lineno = p.lineno(0) + def p_expr_group(p): '''expr : OPAREN expr CPAREN''' @@ -199,6 +214,7 @@ def p_case_list(p): def p_case_elem(p): '''case_elem : ID COLON TYPE ARROW expr''' p[0] = CaseElemNode(p[5], p[1], p[3]) + p[0].lineno = p.lineno(0) def p_arg_list(p): @@ -219,16 +235,19 @@ def p_arg_list_ne(p): def p_atom_int(p): '''atom : INT''' p[0] = IntNode(int(p[1])) + p[0].lineno = p.lineno(0) def p_atom_id(p): '''atom : ID''' p[0] = VarNode(p[1]) + p[0].lineno = p.lineno(0) def p_atom_new(p): '''atom : NEW TYPE''' p[0] = NewNode(p[2]) + p[0].lineno = p.lineno(0) def p_atom_block(p): @@ -239,11 +258,13 @@ def p_atom_block(p): def p_atom_bool(p): '''atom : BOOL''' p[0] = BoolNode(p[1].lower()) + p[0].lineno = p.lineno(0) def p_atom_atring(p): '''atom : STRING''' p[0] = StringNode(p[1]) + p[0].lineno = p.lineno(0) def p_block(p): From b6fb03a5705e9a1f3821dd47891ddd0fab2b896c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 07:31:59 -0400 Subject: [PATCH 076/435] Reorder semantic check --- src/semantic/semantic.py | 248 ++++++++++++++++++++++++--------------- 1 file changed, 155 insertions(+), 93 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 375eca16..ca4d2551 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -64,7 +64,7 @@ def __init__(self, current_class): def visit(self, node: DefAttrNode): if node.expr: - expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass)) + expr_type = expression_visitor(node.expr, self.CurrentClass, {}) attr_type = self.CurrentClass.attributes[node.id].attrType if not check_inherits(expr_type, attr_type): add_semantic_error(0, 0, f'Invalid type {expr_type}') @@ -80,13 +80,7 @@ def visit(self, node: DefFuncNode): local_scope = self.LocalScope.copy() for arg in node.params: local_scope[arg[0]] = type_by_name(arg[1]) - if type(node.expressions) is list: - for exp in node.expressions: - body_type = exp.accept(DefExpressionVisitor(self.CurrentClass, local_scope)) - if body_type is None: - break - else: - body_type = node.expressions.accept(DefExpressionVisitor(self.CurrentClass, local_scope)) + body_type = expression_visitor(node.expressions, self.CurrentClass, local_scope) return_type = type_by_name(node.return_type) if check_inherits(body_type, return_type): return return_type @@ -94,93 +88,161 @@ def visit(self, node: DefFuncNode): add_semantic_error(0, 0, f'invalid returned type {body_type}') -class DefExpressionVisitor(Visitor): - def __init__(self, current_class, local_scope=None): - super().__init__(current_class, local_scope) +def int_visitor(expr, current_class, local_scope): + return IntType - def visit(self, node): - if type(node) is IntNode: - return IntType - if type(node) is StringNode: - return StringType - if type(node) in [BoolNode, EqNode]: - return BoolType - if type(node) is VarNode: - if node.id in self.LocalScope.keys(): - return self.LocalScope[node.id] - try: - return self.CurrentClass.attributes[node.id].attrType - except KeyError: - add_semantic_error(0, 0, f'invalid variable {node.id}') - return None - if type(node) in [StarNode, PlusNode, DivNode, MinusNode]: - lvalue_type = node.lvalue.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if lvalue_type != IntType and lvalue_type is not None: - add_semantic_error(0, 0, f'invalid left value type') - return None - rvalue_type = node.rvalue.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if rvalue_type != IntType and rvalue_type is not None: - add_semantic_error(0, 0, f'invalid right value type') - return None - return IntType - if type(node) is AssignNode: - try: - varType = self.CurrentClass.attributes[node.id].attrType - except KeyError: - add_semantic_error(0, 0, f'invalid variable {node.id}') - return None - expressionType = node.accept(DefExpressionVisitor(self.CurrentClass)) - if check_inherits(expressionType, varType): - return varType - else: - return None - if type(node) is DefAttrNode: - attr_type = type_by_name(node.type) - if attr_type is None: - add_semantic_error(0, 0, f'unknown type {node.type}') - return None - if node.expr: - expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if check_inherits(expr_type, attr_type): - return attr_type - else: - add_semantic_error(0, 0, f'type {expr_type.name} cannot be stored in an {attr_type.name}') - return None - return attr_type - if type(node) is LetNode: - self.LocalScope = self.LocalScope.copy() - for attr in node.let_attrs: - attr_type = attr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if attr_type is None: - return None - self.LocalScope[attr.id] = attr_type - expr_type = node.expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if expr_type is not None: - return expr_type - if type(node) is IfNode: - if_expr_type = node.if_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if if_expr_type != BoolType: - add_semantic_error(0, 0, f'\"if\" expression must be a Bool type') - return - then_expr_type = node.then_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - else_expr_type = node.else_expr.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if then_expr_type is None or else_expr_type is None: - return - return pronounced_join(then_expr_type, else_expr_type) - if type(node) is FuncCallNode: - args_types = [] - for a in node.args: - a_type = a.accept(DefExpressionVisitor(self.CurrentClass, self.LocalScope)) - if a_type: - args_types.append(a_type) - if node.object: - print('Not rule for FuncCall from var') + +def string_visitor(expr, current_class, local_scope): + return StringType + + +def bool_visitor(expr, current_class, local_scope): + return BoolType + + +def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): + if var.id in local_scope.keys(): + return local_scope[var.id] + attribute, _ = get_attribute(current_class, var.id) + if attribute is not None: + return attribute.attrType + else: + raise Exception(f'unknown variable {var.id}') + + +def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) + if lvalue_type != IntType: + raise Exception(f'invalid left value type {lvalue_type}, must be a {IntType}') + rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) + if rvalue_type != IntType: + raise Exception(f'invalid left value type {rvalue_type}, must be a {IntType}') + return IntType + + +def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(equal.lvalue, current_class, local_scope) + rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) + static_types = [IntType, BoolType, StringType] + if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: + raise Exception(f'impossible compare {lvalue_type} and {rvalue_type} types') + return BoolType + + +def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) + if lvalue_type != IntType: + raise Exception(f'lvalue type must be a {IntType}') + rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) + if rvalue_type != IntType: + raise Exception(f'rvalue type must be a {IntType}') + return BoolType + + +def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: dict): + try: + id_type = local_scope[assign.id] + except KeyError: + attr, _ = get_attribute(current_class, assign.id) + if attr is None: + raise Exception(f'unknown variable {assign.id}') + else: + id_type = attr.attrType + expr_type = expression_visitor(assign.expr, current_class, local_scope) + if check_inherits(expr_type, id_type): + return expr_type + raise Exception(f'Type {expr_type} cannot be stored in type {id_type}') + + +def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): + id_type = type_by_name(def_attr.type) + if id_type is None: + raise Exception(f'unknown type {def_attr.type}') + if def_attr.expr: + expr_type = expression_visitor(def_attr.expr, current_class, local_scope) + if not check_inherits(expr_type, id_type): + raise Exception(f'Type {expr_type} cannot be stored in type {id_type}') + return id_type + + +def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): + local_scope = local_scope.copy() + for attribute in let.let_attrs: + attribute_type = expression_visitor(attribute, current_class, local_scope) + local_scope[attribute.id] = attribute_type + return expression_visitor(let.expr, current_class, local_scope) + + +def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: dict): + final_type = None + for expr in expressions: + final_type = expression_visitor(expr, current_class, local_scope) + return final_type + + +def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): + predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) + if predicate_type != BoolType: + raise Exception(f'\"if\" condition must be a {BoolType}') + then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) + else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) + return pronounced_join(then_type, else_type) + + +def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_scope: dict): + args_types = [] + method = None + msg = None + for arg in func_call.args: + arg_type = expression_visitor(arg, current_class, local_scope) + args_types.append(arg_type) + if func_call.object: + if func_call.type: + specific_type = type_by_name(func_call.type) + if specific_type is None: + raise Exception(f'unknown type {func_call.type}') + if check_inherits(current_class, specific_type): + method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) else: - method, msg = self.CurrentClass.get_method(node.id, args_types) - if method.returnedType == SelfType: - return self.CurrentClass - return method.returnedType - print(f'Not rule for {type(node)} in DefExpressionVisitor') + raise Exception(f'type {current_class} not inherits from {specific_type}') + else: + object_type = expression_visitor(func_call.object, current_class, local_scope) + method, msg = object_type.get_method(func_call.id, args_types) + else: + method, msg = current_class.get_method(func_call.id, args_types) + if method is None: + raise Exception(msg) + if method.returnedType == SelfType: + return current_class + return method.returnedType + + +__visitors__ = { + list: list_expr_visitor, + IntNode: int_visitor, + StringNode: string_visitor, + BoolNode: bool_visitor, + VarNode: var_visitor, + PlusNode: arithmetic_operator_visitor, + MinusNode: arithmetic_operator_visitor, + StarNode: arithmetic_operator_visitor, + DivNode: arithmetic_operator_visitor, + EqNode: equal_visitor, + LessThanNode: comparison_visitor, + LessEqNode: comparison_visitor, + AssignNode: assignment_visitor, + DefAttrNode: def_attribute_visitor, + LetNode: let_visitor, + IfNode: if_visitor, + FuncCallNode: func_call_visitor +} + + +def expression_visitor(expression, current_class: CoolType, local_scope: dict) -> CoolType: + try: + return __visitors__[type(expression)](expression, current_class, local_scope) + except KeyError: + print(f'Not visitor for {expression}') def semantic_check(node): From a6046a1aa84cfb126993f0e37cc1034fb7c9f183 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 30 Apr 2020 02:28:56 -0400 Subject: [PATCH 077/435] Add lineno info to ast nodes --- src/lexer_parser/ast.py | 3 +++ src/lexer_parser/parser.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 1f0e7b04..b0a0cafa 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,4 +1,7 @@ class AstNode: + def __init__(self): + self.lineno = 0 + def accept(self, visitor): return visitor.visit(self) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 6f8ce1fa..f5a13297 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -19,6 +19,7 @@ def p_program(p): 'program : class_list' p[0] = ProgramNode(p[1]) + p[0].lineno = p.lineno(0) def p_empty(p): @@ -44,6 +45,8 @@ def p_def_class(p): else: p[0] = DefClassNode(p[2], p[4]) + p[0].lineno = p.lineno(0) + def p_feature_list(p): '''feature_list : def_attr SEMICOLON feature_list @@ -63,10 +66,13 @@ def p_def_attr_declaration(p): except: p[0] = DefAttrNode(p[1], p[3]) + p[0].lineno = p.lineno(0) + def p_def_func(p): '''def_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET''' p[0] = DefFuncNode(p[1], p[3], p[6], p[8]) + p[0].lineno = p.lineno(0) def p_params_ne(p): @@ -108,10 +114,13 @@ def p_expr_flow(p): elif p[1].lower() == 'while': p[0] = WhileNode(p[2], p[4]) + p[0].lineno = p.lineno(0) + def p_expr_assign(p): '''expr : ID ASSIGN expr''' p[0] = AssignNode(p[1], p[3]) + p[0].lineno = p.lineno(0) def p_expr_func_all(p): @@ -130,6 +139,8 @@ def p_expr_func_all(p): if p[3] is None: p[3] = [] p[0] = FuncCallNode(p[1], p[3]) + + p[0].lineno = p.lineno(0) def p_expr_operators_binary(p): @@ -155,6 +166,8 @@ def p_expr_operators_binary(p): elif p[2] == '=': p[0] = EqNode(p[1], p[3]) + p[0].lineno = p.lineno(0) + def p_expr_operators_unary(p): '''expr : NOT expr @@ -167,6 +180,8 @@ def p_expr_operators_unary(p): elif p[1].lower() == 'not': p[0] = LogicNegationNode(p[2]) + p[0].lineno = p.lineno(0) + def p_expr_group(p): '''expr : OPAREN expr CPAREN''' @@ -199,6 +214,7 @@ def p_case_list(p): def p_case_elem(p): '''case_elem : ID COLON TYPE ARROW expr''' p[0] = CaseElemNode(p[5], p[1], p[3]) + p[0].lineno = p.lineno(0) def p_arg_list(p): @@ -219,16 +235,19 @@ def p_arg_list_ne(p): def p_atom_int(p): '''atom : INT''' p[0] = IntNode(int(p[1])) + p[0].lineno = p.lineno(0) def p_atom_id(p): '''atom : ID''' p[0] = VarNode(p[1]) + p[0].lineno = p.lineno(0) def p_atom_new(p): '''atom : NEW TYPE''' p[0] = NewNode(p[2]) + p[0].lineno = p.lineno(0) def p_atom_block(p): @@ -239,11 +258,13 @@ def p_atom_block(p): def p_atom_bool(p): '''atom : BOOL''' p[0] = BoolNode(p[1].lower()) + p[0].lineno = p.lineno(0) def p_atom_atring(p): '''atom : STRING''' p[0] = StringNode(p[1]) + p[0].lineno = p.lineno(0) def p_block(p): From 1cda65f6c42134d726ef15200b0aabd2f779f876 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 30 Apr 2020 09:57:38 -0400 Subject: [PATCH 078/435] Add location info into semantic errors --- src/lexer_parser/ast.py | 5 +++++ src/main.py | 2 +- src/semantic/semantic.py | 8 ++++---- src/semantic/types.py | 6 +++--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index b0a0cafa..719eb452 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,6 +1,11 @@ class AstNode: def __init__(self): self.lineno = 0 + self.colno = 0 + + def add_location(self, line, column): + self.lineno = line + self.colno = column def accept(self, visitor): return visitor.visit(self) diff --git a/src/main.py b/src/main.py index f6df61d7..676f3ef4 100644 --- a/src/main.py +++ b/src/main.py @@ -20,7 +20,7 @@ def main(): except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') - ast = parser.parse(input_data, lexer) + ast = parser.parse(input_data, lexer, tracking=True) if err.LEXER_ERRORS: for e in err.LEXER_ERRORS: print(e) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index ca4d2551..1cd243c4 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -33,12 +33,12 @@ def visit(self, node: ProgramNode): param_types = [param[1] for param in f.params] result, msg = classType.add_method(f.id, param_types, f.return_type) if not result: - add_semantic_error(0, 0, msg) + add_semantic_error(f.lineno, f.colno, msg) elif type(f) is DefAttrNode: # Add all attributes to types result, msg = classType.add_attr(f.id, f.type) if not result: - add_semantic_error(0, 0, msg) + add_semantic_error(f.lineno, f.colno, msg) # Visit each class inside for c in node.classes: c.accept(DefClassVisitor()) @@ -67,7 +67,7 @@ def visit(self, node: DefAttrNode): expr_type = expression_visitor(node.expr, self.CurrentClass, {}) attr_type = self.CurrentClass.attributes[node.id].attrType if not check_inherits(expr_type, attr_type): - add_semantic_error(0, 0, f'Invalid type {expr_type}') + add_semantic_error(node.lineno, node.colno, f'Invalid type {expr_type}') else: return attr_type @@ -85,7 +85,7 @@ def visit(self, node: DefFuncNode): if check_inherits(body_type, return_type): return return_type elif body_type is not None: - add_semantic_error(0, 0, f'invalid returned type {body_type}') + add_semantic_error(node.lineno, node.colno, f'invalid returned type {body_type}') def int_visitor(expr, current_class, local_scope): diff --git a/src/semantic/types.py b/src/semantic/types.py index 027d4cec..e7e18025 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -122,7 +122,7 @@ def check_type_declaration(node: ProgramNode): for c in node.classes: try: _ = TypesByName[c.type] - add_semantic_error(0, 0, f'duplicated declaration of type {c.type}') + add_semantic_error(c.lineno, c.colno, f'duplicated declaration of type {c.type}') return False except KeyError: TypesByName[c.type] = CoolType(c.type, None) @@ -138,10 +138,10 @@ def check_type_hierarchy(node: ProgramNode): if parentType.inherit: cType.parent = parentType else: - add_semantic_error(0, 0, f'can\'t be inherit from class {parentType.name}') + add_semantic_error(c.lineno, c.colno, f'can\'t be inherit from class {parentType.name}') return False except KeyError: - add_semantic_error(0, 0, f'unknown parent type {c.parent_type}') + add_semantic_error(c.lineno, c.colno, f'unknown parent type {c.parent_type}') return False else: cType.parent = ObjectType From b6537f352f86da13af421b15521f188838a59e5a Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 30 Apr 2020 12:11:45 -0400 Subject: [PATCH 079/435] Fix default location on semantic errors --- src/lexer_parser/parser.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index f5a13297..90061314 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -19,8 +19,6 @@ def p_program(p): 'program : class_list' p[0] = ProgramNode(p[1]) - p[0].lineno = p.lineno(0) - def p_empty(p): 'empty :' @@ -45,7 +43,7 @@ def p_def_class(p): else: p[0] = DefClassNode(p[2], p[4]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2))) def p_feature_list(p): @@ -66,13 +64,14 @@ def p_def_attr_declaration(p): except: p[0] = DefAttrNode(p[1], p[3]) - p[0].lineno = p.lineno(0) - + p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) + def p_def_func(p): '''def_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET''' p[0] = DefFuncNode(p[1], p[3], p[6], p[8]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(6), find_column(p.lexer.lexdata, p.lexpos(6))) + def p_params_ne(p): @@ -114,13 +113,14 @@ def p_expr_flow(p): elif p[1].lower() == 'while': p[0] = WhileNode(p[2], p[4]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2))) def p_expr_assign(p): '''expr : ID ASSIGN expr''' p[0] = AssignNode(p[1], p[3]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) + def p_expr_func_all(p): @@ -131,14 +131,17 @@ def p_expr_func_all(p): if p[7] is None: p[7] = [] p[0] = FuncCallNode(p[5], p[7], p[1], p[3]) + p[0].add_location(p.lineno(5), find_column(p.lexer.lexdata, p.lexpos(5))) elif len(p) == 7: if p[5] is None: p[5] = [] p[0] = FuncCallNode(p[3], p[5], p[1]) + p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) else: if p[3] is None: p[3] = [] p[0] = FuncCallNode(p[1], p[3]) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) p[0].lineno = p.lineno(0) @@ -166,8 +169,7 @@ def p_expr_operators_binary(p): elif p[2] == '=': p[0] = EqNode(p[1], p[3]) - p[0].lineno = p.lineno(0) - + p[0].add_location(p.lineno(0), find_column(p.lexer.lexdata, p.lexpos(0))) def p_expr_operators_unary(p): '''expr : NOT expr @@ -180,7 +182,7 @@ def p_expr_operators_unary(p): elif p[1].lower() == 'not': p[0] = LogicNegationNode(p[2]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2))) def p_expr_group(p): @@ -214,7 +216,7 @@ def p_case_list(p): def p_case_elem(p): '''case_elem : ID COLON TYPE ARROW expr''' p[0] = CaseElemNode(p[5], p[1], p[3]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) def p_arg_list(p): @@ -235,19 +237,19 @@ def p_arg_list_ne(p): def p_atom_int(p): '''atom : INT''' p[0] = IntNode(int(p[1])) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) def p_atom_id(p): '''atom : ID''' p[0] = VarNode(p[1]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) def p_atom_new(p): '''atom : NEW TYPE''' p[0] = NewNode(p[2]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(2), find_column(p.lexer.lexdata, p.lexpos(2))) def p_atom_block(p): @@ -258,13 +260,13 @@ def p_atom_block(p): def p_atom_bool(p): '''atom : BOOL''' p[0] = BoolNode(p[1].lower()) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) def p_atom_atring(p): '''atom : STRING''' p[0] = StringNode(p[1]) - p[0].lineno = p.lineno(0) + p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) def p_block(p): From 89e5d66dbb39863beab3157656aa1efa2a4e32f4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 15:38:51 -0400 Subject: [PATCH 080/435] Change DefFuncVisitor class with a function --- src/semantic/semantic.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index ca4d2551..3cb819fe 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -55,7 +55,7 @@ def visit(self, node: DefClassNode): if type(feature) is DefAttrNode: feature.accept(DefAttrVisitor(self.CurrentClass)) if type(feature) is DefFuncNode: - feature.accept(DefFuncVisitor(self.CurrentClass)) + def_func_visitor(feature, self.CurrentClass, {}) class DefAttrVisitor(Visitor): @@ -72,20 +72,16 @@ def visit(self, node: DefAttrNode): return attr_type -class DefFuncVisitor(Visitor): - def __init__(self, current_class): - super().__init__(current_class) - - def visit(self, node: DefFuncNode): - local_scope = self.LocalScope.copy() - for arg in node.params: - local_scope[arg[0]] = type_by_name(arg[1]) - body_type = expression_visitor(node.expressions, self.CurrentClass, local_scope) - return_type = type_by_name(node.return_type) - if check_inherits(body_type, return_type): - return return_type - elif body_type is not None: - add_semantic_error(0, 0, f'invalid returned type {body_type}') +def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope: dict): + local_scope = local_scope.copy() + for arg in function.params: + local_scope[arg[0]] = type_by_name(arg[1]) + body_type = expression_visitor(function.expressions, current_class, local_scope) + return_type = type_by_name(function.return_type) + if check_inherits(body_type, return_type): + return return_type + elif body_type is not None: + add_semantic_error(0, 0, f'invalid returned type {body_type}') def int_visitor(expr, current_class, local_scope): @@ -202,7 +198,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if specific_type is None: raise Exception(f'unknown type {func_call.type}') if check_inherits(current_class, specific_type): - method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) + method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) else: raise Exception(f'type {current_class} not inherits from {specific_type}') else: From 61c919e4c85180858228516614c2f09fbd8663ae Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 15:42:54 -0400 Subject: [PATCH 081/435] Change DefAttrVisitor class with a function --- src/semantic/semantic.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 3cb819fe..6d2e24ee 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -53,23 +53,19 @@ def visit(self, node: DefClassNode): # Check all features for feature in node.feature_nodes: if type(feature) is DefAttrNode: - feature.accept(DefAttrVisitor(self.CurrentClass)) + def_attr_class_visitor(feature, self.CurrentClass, {}) if type(feature) is DefFuncNode: def_func_visitor(feature, self.CurrentClass, {}) -class DefAttrVisitor(Visitor): - def __init__(self, current_class): - super().__init__(current_class) - - def visit(self, node: DefAttrNode): - if node.expr: - expr_type = expression_visitor(node.expr, self.CurrentClass, {}) - attr_type = self.CurrentClass.attributes[node.id].attrType - if not check_inherits(expr_type, attr_type): - add_semantic_error(0, 0, f'Invalid type {expr_type}') - else: - return attr_type +def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): + if attr.expr: + expr_type = expression_visitor(attr.expr, current_class, {}) + attr_type = current_class.attributes[attr.id].attrType + if not check_inherits(expr_type, attr_type): + add_semantic_error(0, 0, f'Invalid type {expr_type}') + else: + return attr_type def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope: dict): From c761844599462de333f2884d43405a575cecb642 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 15:46:39 -0400 Subject: [PATCH 082/435] Change DefClassVisitor class with a function --- src/semantic/semantic.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 6d2e24ee..ef6fe973 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -41,21 +41,17 @@ def visit(self, node: ProgramNode): add_semantic_error(0, 0, msg) # Visit each class inside for c in node.classes: - c.accept(DefClassVisitor()) + class_visitor(c, self.CurrentClass, {}) -class DefClassVisitor(Visitor): - def __init__(self): - super().__init__(None) - - def visit(self, node: DefClassNode): - self.CurrentClass = TypesByName[node.type] - # Check all features - for feature in node.feature_nodes: - if type(feature) is DefAttrNode: - def_attr_class_visitor(feature, self.CurrentClass, {}) - if type(feature) is DefFuncNode: - def_func_visitor(feature, self.CurrentClass, {}) +def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: dict): + current_class = TypesByName[_class.type] + # Check all features + for feature in _class.feature_nodes: + if type(feature) is DefAttrNode: + def_attr_class_visitor(feature, current_class, {}) + if type(feature) is DefFuncNode: + def_func_visitor(feature, current_class, {}) def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): From 7425f9ad969bffbdf60bb4ec7cdaecff1c4d55a2 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 16:01:12 -0400 Subject: [PATCH 083/435] Reformat code imports --- src/lexer_parser/lexer.py | 3 ++- src/lexer_parser/parser.py | 3 ++- src/main.py | 1 + src/semantic/semantic.py | 2 -- src/semantic/types.py | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index ee645117..166ddf26 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -1,6 +1,7 @@ import ply.lex as lex -from utils import * + from errors import add_lexer_error +from utils import * states = ( ('commentLine', 'exclusive'), diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 6f8ce1fa..1c865a83 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -1,7 +1,8 @@ import ply.yacc as yacc -from .lexer import * + from errors import add_parser_error from .ast import * +from .lexer import * precedence = ( ('left', 'DOT'), diff --git a/src/main.py b/src/main.py index f6df61d7..37dade58 100644 --- a/src/main.py +++ b/src/main.py @@ -1,4 +1,5 @@ import sys + import errors as err from lexer_parser import lexer, parser from semantic import semantic_check diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index ef6fe973..705e5ce0 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -1,5 +1,3 @@ -from errors import add_semantic_error -from lexer_parser.ast import * from .types import * diff --git a/src/semantic/types.py b/src/semantic/types.py index 027d4cec..e3dda0aa 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -1,5 +1,5 @@ -from lexer_parser.ast import * from errors import add_semantic_error +from lexer_parser.ast import * class CoolType: From 8797215025d3c811482fb371887913de50240dbe Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 17:47:19 -0400 Subject: [PATCH 084/435] Adding case expression visitor --- src/semantic/semantic.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 705e5ce0..3e2833b4 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -202,6 +202,22 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return current_class return method.returnedType +def case_expr_visitor(case:CaseNode, current_class:CoolType, scope:dict): + expr_0=expression_visitor(case.expr, current_class, local_scope) + current_type=expression_visitor(case.case_list[0].expr, current_class, local_scope) + + for branch in case.case_list[1:]: + temp={} + temp=local_scope.copy() + temp[branch.id]=expr_0 + current_type=pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) + + return current_type + + +def is_void_expr_visitor(isvoid:IsVoidNode, current_class:CoolType, scope:dict): + pass + __visitors__ = { list: list_expr_visitor, @@ -220,7 +236,9 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc DefAttrNode: def_attribute_visitor, LetNode: let_visitor, IfNode: if_visitor, - FuncCallNode: func_call_visitor + FuncCallNode: func_call_visitor, + CaseNode: case_expr_visitor, + IsVoidNode: is_void_expr_visitor } From 695adb8a5c1fa05e298f2b49715f5cbf1ecf4a58 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:05:48 -0400 Subject: [PATCH 085/435] adding copy of scope in first iteration --- src/semantic/semantic.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 3e2833b4..9c16047b 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -202,9 +202,14 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return current_class return method.returnedType -def case_expr_visitor(case:CaseNode, current_class:CoolType, scope:dict): +def case_expr_visitor(case:CaseNode, current_class:CoolType, local_scope:dict): expr_0=expression_visitor(case.expr, current_class, local_scope) - current_type=expression_visitor(case.case_list[0].expr, current_class, local_scope) + + branch_0=case.case_list[0] + temp={} + temp=local_scope.copy() + temp[branch_0.id]=expr_0 + current_type=expression_visitor(branch_0.expr, current_class, temp) for branch in case.case_list[1:]: temp={} From e75c0687ebe0a131d621ee24fdb9fbb2105c3c08 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:12:12 -0400 Subject: [PATCH 086/435] adding is void expression visitor --- src/semantic/semantic.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 9c16047b..4884076b 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -220,8 +220,9 @@ def case_expr_visitor(case:CaseNode, current_class:CoolType, local_scope:dict): return current_type -def is_void_expr_visitor(isvoid:IsVoidNode, current_class:CoolType, scope:dict): - pass +def is_void_expr_visitor(isvoid:IsVoidNode, current_class:CoolType, local_scope:dict): + expression_visitor(isvoid.val, current_class, local_scope) + return BoolType __visitors__ = { From db948a508e4bc38a6d5e8dd18b504dc47c7f884c Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:24:16 -0400 Subject: [PATCH 087/435] removing unnecessary initialization --- src/semantic/semantic.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 4884076b..8479ef23 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -206,13 +206,11 @@ def case_expr_visitor(case:CaseNode, current_class:CoolType, local_scope:dict): expr_0=expression_visitor(case.expr, current_class, local_scope) branch_0=case.case_list[0] - temp={} temp=local_scope.copy() temp[branch_0.id]=expr_0 current_type=expression_visitor(branch_0.expr, current_class, temp) for branch in case.case_list[1:]: - temp={} temp=local_scope.copy() temp[branch.id]=expr_0 current_type=pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) From 21da0328d75eab2d322687704d003efc282218fa Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:44:26 -0400 Subject: [PATCH 088/435] adding new and loop expression visitors --- src/semantic/semantic.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 8479ef23..e5b12c6f 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -222,6 +222,19 @@ def is_void_expr_visitor(isvoid:IsVoidNode, current_class:CoolType, local_scope: expression_visitor(isvoid.val, current_class, local_scope) return BoolType +def loop_expr_visitor(loop:WhileNode, current_class:CoolType, local_scope:dict): + predicate_type=expression_visitor(loop.cond, current_class, local_scope) + if predicate_type != BoolType: + raise Exception(f'\"loop\" condition must be a {BoolType}') + expression_visitor(loop.body, current_class, local_scope) + return ObjectType + +def new_visitor(new:NewNode, current_class:CoolType, local_scope:dict): + t=type_by_name(new.type) + if not t: + raise Exception(f'Type {new.type} does not exist. Cannot create instance.') + return t + __visitors__ = { list: list_expr_visitor, From 181bda8e64a5be668c4dee211a8844512607aa79 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:47:13 -0400 Subject: [PATCH 089/435] adding new and loop visitors to visitors dict --- src/semantic/semantic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index e5b12c6f..ebc6494a 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -229,7 +229,7 @@ def loop_expr_visitor(loop:WhileNode, current_class:CoolType, local_scope:dict): expression_visitor(loop.body, current_class, local_scope) return ObjectType -def new_visitor(new:NewNode, current_class:CoolType, local_scope:dict): +def new_expr_visitor(new:NewNode, current_class:CoolType, local_scope:dict): t=type_by_name(new.type) if not t: raise Exception(f'Type {new.type} does not exist. Cannot create instance.') @@ -255,7 +255,9 @@ def new_visitor(new:NewNode, current_class:CoolType, local_scope:dict): IfNode: if_visitor, FuncCallNode: func_call_visitor, CaseNode: case_expr_visitor, - IsVoidNode: is_void_expr_visitor + IsVoidNode: is_void_expr_visitor, + WhileNode: loop_expr_visitor, + NewNode:new_expr_visitor } From f1100780d2995e23d51f12f81cfa901e16bcd405 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 30 Apr 2020 18:52:49 -0400 Subject: [PATCH 090/435] Adding self type consideration to new visitor --- src/semantic/semantic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index ebc6494a..7e7233e0 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -233,6 +233,8 @@ def new_expr_visitor(new:NewNode, current_class:CoolType, local_scope:dict): t=type_by_name(new.type) if not t: raise Exception(f'Type {new.type} does not exist. Cannot create instance.') + if t==SelfType: + return current_class return t From de4cd96b88fa2723bccb2c4c28b3e6c63bd69bdb Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 30 Apr 2020 19:23:52 -0400 Subject: [PATCH 091/435] Reformat code --- src/semantic/semantic.py | 43 +++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 7e7233e0..eb7be810 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -202,38 +202,41 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return current_class return method.returnedType -def case_expr_visitor(case:CaseNode, current_class:CoolType, local_scope:dict): - expr_0=expression_visitor(case.expr, current_class, local_scope) - - branch_0=case.case_list[0] - temp=local_scope.copy() - temp[branch_0.id]=expr_0 - current_type=expression_visitor(branch_0.expr, current_class, temp) - + +def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): + expr_0 = expression_visitor(case.expr, current_class, local_scope) + + branch_0 = case.case_list[0] + temp = local_scope.copy() + temp[branch_0.id] = expr_0 + current_type = expression_visitor(branch_0.expr, current_class, temp) + for branch in case.case_list[1:]: - temp=local_scope.copy() - temp[branch.id]=expr_0 - current_type=pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) - + temp = local_scope.copy() + temp[branch.id] = expr_0 + current_type = pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) + return current_type - -def is_void_expr_visitor(isvoid:IsVoidNode, current_class:CoolType, local_scope:dict): + +def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): expression_visitor(isvoid.val, current_class, local_scope) return BoolType -def loop_expr_visitor(loop:WhileNode, current_class:CoolType, local_scope:dict): - predicate_type=expression_visitor(loop.cond, current_class, local_scope) + +def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): + predicate_type = expression_visitor(loop.cond, current_class, local_scope) if predicate_type != BoolType: raise Exception(f'\"loop\" condition must be a {BoolType}') expression_visitor(loop.body, current_class, local_scope) return ObjectType -def new_expr_visitor(new:NewNode, current_class:CoolType, local_scope:dict): - t=type_by_name(new.type) + +def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): + t = type_by_name(new.type) if not t: raise Exception(f'Type {new.type} does not exist. Cannot create instance.') - if t==SelfType: + if t == SelfType: return current_class return t @@ -259,7 +262,7 @@ def new_expr_visitor(new:NewNode, current_class:CoolType, local_scope:dict): CaseNode: case_expr_visitor, IsVoidNode: is_void_expr_visitor, WhileNode: loop_expr_visitor, - NewNode:new_expr_visitor + NewNode: new_expr_visitor } From b96ff04c1024158875a356874feb5376e156a3f2 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 12:20:27 -0400 Subject: [PATCH 092/435] Add IndexError --- src/lexer_parser/parser.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 1c865a83..f407370b 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -33,7 +33,7 @@ def p_class_list(p): try: p[0] = [p[1]] + p[3] - except: + except IndexError: p[0] = [p[1]] @@ -61,7 +61,7 @@ def p_def_attr_declaration(p): | ID COLON TYPE''' try: p[0] = DefAttrNode(p[1], p[3], p[5]) - except: + except IndexError: p[0] = DefAttrNode(p[1], p[3]) @@ -85,11 +85,12 @@ def p_param_list(p): | param empty''' try: p[0] = [p[1]] + p[3] - except: + except IndexError: p[0] = [p[1]] def p_param(p): + # noinspection PySingleQuotedDocstring '''param : ID COLON TYPE''' p[0] = (p[1], p[3]) @@ -184,7 +185,7 @@ def p_let_attrs(p): | def_attr''' try: p[0] = [p[1]] + p[3] - except: + except IndexError: p[0] = [p[1]] @@ -193,7 +194,7 @@ def p_case_list(p): | case_elem SEMICOLON''' try: p[0] = [p[1]] + p[3] - except: + except IndexError: p[0] = [p[1]] From 86b7f6a8997e63a9b71d72500d192364f762b737 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 12:20:41 -0400 Subject: [PATCH 093/435] Remove unnecessary comment --- src/lexer_parser/lexer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index 166ddf26..2fe9cea9 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -215,7 +215,6 @@ def test(data): tok = lexer.token() if not tok: break - # print(f'#{tok.lineno} {tok.type} {tok.value}') lexer = lex.lex() From 9343bafc6f1392aa648e73b0cd33a2513385122f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 12:21:02 -0400 Subject: [PATCH 094/435] Change ProgramVisitor class for program_visitor function --- src/semantic/semantic.py | 58 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index eb7be810..4c89ecbe 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -10,36 +10,32 @@ def visit(self, node): pass -class ProgramVisitor(Visitor): - def __init__(self): - super().__init__(None) - - def visit(self, node: ProgramNode): - if not (check_type_declaration(node) and check_type_hierarchy(node)): - return - # Check Main class exists - try: - TypesByName['Main'] - except KeyError: - add_semantic_error(0, 0, f'Main class undeclared') - return - # Initialize MethodEnv - for c in node.classes: - classType = TypesByName[c.type] - for f in c.feature_nodes: - if type(f) is DefFuncNode: - param_types = [param[1] for param in f.params] - result, msg = classType.add_method(f.id, param_types, f.return_type) - if not result: - add_semantic_error(0, 0, msg) - elif type(f) is DefAttrNode: - # Add all attributes to types - result, msg = classType.add_attr(f.id, f.type) - if not result: - add_semantic_error(0, 0, msg) - # Visit each class inside - for c in node.classes: - class_visitor(c, self.CurrentClass, {}) +def program_visitor(program: ProgramNode): + if not (check_type_declaration(program) and check_type_hierarchy(program)): + return + # Check Main class exists + try: + TypesByName['Main'] + except KeyError: + add_semantic_error(0, 0, f'Main class undeclared') + return + # Initialize MethodEnv + for c in program.classes: + classType = TypesByName[c.type] + for f in c.feature_nodes: + if type(f) is DefFuncNode: + param_types = [param[1] for param in f.params] + result, msg = classType.add_method(f.id, param_types, f.return_type) + if not result: + add_semantic_error(0, 0, msg) + elif type(f) is DefAttrNode: + # Add all attributes to types + result, msg = classType.add_attr(f.id, f.type) + if not result: + add_semantic_error(0, 0, msg) + # Visit each class inside + for c in program.classes: + class_visitor(c, None, {}) def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: dict): @@ -275,4 +271,4 @@ def expression_visitor(expression, current_class: CoolType, local_scope: dict) - def semantic_check(node): if type(node) is ProgramNode: - node.accept(ProgramVisitor()) + program_visitor(node) From a05a3be3d769101d615ccf771517a79b837f4bfe Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 12:53:20 -0400 Subject: [PATCH 095/435] Capture error exceptions in semantic checks --- src/semantic/semantic.py | 48 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 795b4ef9..b754ebd5 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -42,10 +42,13 @@ def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: di current_class = TypesByName[_class.type] # Check all features for feature in _class.feature_nodes: - if type(feature) is DefAttrNode: - def_attr_class_visitor(feature, current_class, {}) - if type(feature) is DefFuncNode: - def_func_visitor(feature, current_class, {}) + try: + if type(feature) is DefAttrNode: + def_attr_class_visitor(feature, current_class, {}) + if type(feature) is DefFuncNode: + def_func_visitor(feature, current_class, {}) + except Exception as exception: + add_semantic_error(exception.args[0], exception.args[1], exception.args[2]) def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): @@ -67,7 +70,7 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope if check_inherits(body_type, return_type): return return_type elif body_type is not None: - add_semantic_error(node.lineno, node.colno, f'invalid returned type {body_type}') + raise Exception(function.lineno, function.colno, f'invalid returned type {function.return_type}') def int_visitor(expr, current_class, local_scope): @@ -89,16 +92,18 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if attribute is not None: return attribute.attrType else: - raise Exception(f'unknown variable {var.id}') + raise Exception(var.lineno, var.colno, f'unknown variable {var.id}') def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) if lvalue_type != IntType: - raise Exception(f'invalid left value type {lvalue_type}, must be a {IntType}') + raise Exception(operator.lvalue.lineno, operator.lvalue.colno, + f'invalid left value type {lvalue_type}, must be a {IntType}') rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) if rvalue_type != IntType: - raise Exception(f'invalid left value type {rvalue_type}, must be a {IntType}') + raise Exception(operator.rvalue.lineno, operator.rvalue.colno, + f'invalid left value type {rvalue_type}, must be a {IntType}') return IntType @@ -107,17 +112,17 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) static_types = [IntType, BoolType, StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: - raise Exception(f'impossible compare {lvalue_type} and {rvalue_type} types') + raise Exception(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') return BoolType def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) if lvalue_type != IntType: - raise Exception(f'lvalue type must be a {IntType}') + raise Exception(cmp.lvalue.lineno, cmp.lvalue.colno, 'lvalue type must be a {IntType}') rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) if rvalue_type != IntType: - raise Exception(f'rvalue type must be a {IntType}') + raise Exception(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') return BoolType @@ -127,23 +132,23 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: except KeyError: attr, _ = get_attribute(current_class, assign.id) if attr is None: - raise Exception(f'unknown variable {assign.id}') + raise Exception(assign.id.lineno, assign.id.colno, f'unknown variable {assign.id}') else: id_type = attr.attrType expr_type = expression_visitor(assign.expr, current_class, local_scope) if check_inherits(expr_type, id_type): return expr_type - raise Exception(f'Type {expr_type} cannot be stored in type {id_type}') + raise Exception(assign.expr.lineno, assign.expr.colno, f'Type {expr_type} cannot be stored in type {id_type}') def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): id_type = type_by_name(def_attr.type) if id_type is None: - raise Exception(f'unknown type {def_attr.type}') + raise Exception(def_attr.lineno, def_attr.colno, f'unknown type {def_attr.type}') if def_attr.expr: expr_type = expression_visitor(def_attr.expr, current_class, local_scope) if not check_inherits(expr_type, id_type): - raise Exception(f'Type {expr_type} cannot be stored in type {id_type}') + raise Exception(def_attr.lineno, def_attr.colno, f'Type {expr_type} cannot be stored in type {id_type}') return id_type @@ -165,7 +170,7 @@ def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: d def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) if predicate_type != BoolType: - raise Exception(f'\"if\" condition must be a {BoolType}') + raise Exception(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\"if\" condition must be a {BoolType}') then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) return pronounced_join(then_type, else_type) @@ -182,18 +187,19 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if func_call.type: specific_type = type_by_name(func_call.type) if specific_type is None: - raise Exception(f'unknown type {func_call.type}') + raise Exception(func_call.lineno, func_call.colno, f'unknown type {func_call.type}') if check_inherits(current_class, specific_type): method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) else: - raise Exception(f'type {current_class} not inherits from {specific_type}') + raise Exception(func_call.lineno, func_call.colno, + f'type {current_class} not inherits from {specific_type}') else: object_type = expression_visitor(func_call.object, current_class, local_scope) method, msg = object_type.get_method(func_call.id, args_types) else: method, msg = current_class.get_method(func_call.id, args_types) if method is None: - raise Exception(msg) + raise Exception(func_call.lineno, func_call.colno, msg) if method.returnedType == SelfType: return current_class return method.returnedType @@ -223,7 +229,7 @@ def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scop def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(loop.cond, current_class, local_scope) if predicate_type != BoolType: - raise Exception(f'\"loop\" condition must be a {BoolType}') + raise Exception(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') expression_visitor(loop.body, current_class, local_scope) return ObjectType @@ -231,7 +237,7 @@ def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dic def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): t = type_by_name(new.type) if not t: - raise Exception(f'Type {new.type} does not exist. Cannot create instance.') + raise Exception(new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') if t == SelfType: return current_class return t From c30ff512c8ae3af78bd6154144f48131c2bc70b5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 13:33:02 -0400 Subject: [PATCH 096/435] Fix bug --- src/semantic/types.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index dcdb18be..52684458 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -24,10 +24,10 @@ def add_method(self, id, arg_types_name, returned_type): if arg_type is None: return False, f'unknown type {arg}' arg_types.append(arg_type) - returned_type = type_by_name(returned_type) - if returned_type is None: + _returned_type = type_by_name(returned_type) + if _returned_type is None: return False, f'unknown type {returned_type}' - self.methods[id] = CoolTypeMethod(id, arg_types, returned_type) + self.methods[id] = CoolTypeMethod(id, arg_types, _returned_type) return True, None else: return False, msg @@ -61,10 +61,10 @@ def add_attr(self, id, attr_type): _ = self.attributes[id] return False, f'attribute \"{id}\" already declared in class \"{self.name}\"' except KeyError: - attr_type = type_by_name(attr_type) - if attr_type is None: + _attr_type = type_by_name(attr_type) + if _attr_type is None: return False, f'unknown type {attr_type}' - self.attributes[id] = CoolTypeAttribute(id, attr_type) + self.attributes[id] = CoolTypeAttribute(id, _attr_type) return True, None def __repr__(self): From ddc008a03fd84c0b76477c6e563a2888c2400309 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 13:33:34 -0400 Subject: [PATCH 097/435] Fix bug --- src/semantic/semantic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index b754ebd5..609e27ac 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -54,9 +54,11 @@ def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: di def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): if attr.expr: expr_type = expression_visitor(attr.expr, current_class, {}) - attr_type = current_class.attributes[attr.id].attrType + attr_type = type_by_name(attr.type) + if attr_type is None: + raise Exception(attr.lineno, attr.colno, f'unknown type {attr.type}') if not check_inherits(expr_type, attr_type): - add_semantic_error(0, 0, f'Invalid type {expr_type}') + raise Exception(attr.lineno, attr.colno, f'cannot save type {expr_type} inside type {attr_type}') else: return attr_type From 6f8bf3505879619fdd5324587e3378402a34f391 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 13:46:30 -0400 Subject: [PATCH 098/435] Fix bug --- src/semantic/semantic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 609e27ac..7aac812b 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -55,9 +55,7 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco if attr.expr: expr_type = expression_visitor(attr.expr, current_class, {}) attr_type = type_by_name(attr.type) - if attr_type is None: - raise Exception(attr.lineno, attr.colno, f'unknown type {attr.type}') - if not check_inherits(expr_type, attr_type): + if attr_type is not None and not check_inherits(expr_type, attr_type): raise Exception(attr.lineno, attr.colno, f'cannot save type {expr_type} inside type {attr_type}') else: return attr_type From 5e709fe380c5d75b1f0ebc93e7eb0fc8a143a257 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 13:48:07 -0400 Subject: [PATCH 099/435] Remove class Visitor --- src/lexer_parser/ast.py | 5 +---- src/semantic/semantic.py | 9 --------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 719eb452..143874f2 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,5 +1,5 @@ class AstNode: - def __init__(self): + def __init__(self): self.lineno = 0 self.colno = 0 @@ -7,9 +7,6 @@ def add_location(self, line, column): self.lineno = line self.colno = column - def accept(self, visitor): - return visitor.visit(self) - class ProgramNode(AstNode): def __init__(self, classes: list): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 7aac812b..8477670d 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -1,15 +1,6 @@ from .types import * -class Visitor: - def __init__(self, current_class, local_scope=None): - self.CurrentClass = current_class - self.LocalScope = local_scope if local_scope else {} - - def visit(self, node): - pass - - def program_visitor(program: ProgramNode): if not (check_type_declaration(program) and check_type_hierarchy(program)): return From 04fe51c2a7310a2004d49b95ee1567f306553382 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 15:04:03 -0400 Subject: [PATCH 100/435] Change Exceptions for add_semantic_error --- src/semantic/semantic.py | 85 +++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 8477670d..3748f75e 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -33,13 +33,10 @@ def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: di current_class = TypesByName[_class.type] # Check all features for feature in _class.feature_nodes: - try: - if type(feature) is DefAttrNode: - def_attr_class_visitor(feature, current_class, {}) - if type(feature) is DefFuncNode: - def_func_visitor(feature, current_class, {}) - except Exception as exception: - add_semantic_error(exception.args[0], exception.args[1], exception.args[2]) + if type(feature) is DefAttrNode: + def_attr_class_visitor(feature, current_class, {}) + if type(feature) is DefFuncNode: + def_func_visitor(feature, current_class, {}) def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): @@ -47,7 +44,7 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco expr_type = expression_visitor(attr.expr, current_class, {}) attr_type = type_by_name(attr.type) if attr_type is not None and not check_inherits(expr_type, attr_type): - raise Exception(attr.lineno, attr.colno, f'cannot save type {expr_type} inside type {attr_type}') + add_semantic_error(attr.lineno, attr.colno, f'cannot save type {expr_type} inside type {attr_type}') else: return attr_type @@ -61,7 +58,7 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope if check_inherits(body_type, return_type): return return_type elif body_type is not None: - raise Exception(function.lineno, function.colno, f'invalid returned type {function.return_type}') + add_semantic_error(function.lineno, function.colno, f'invalid returned type {function.return_type}') def int_visitor(expr, current_class, local_scope): @@ -83,18 +80,18 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if attribute is not None: return attribute.attrType else: - raise Exception(var.lineno, var.colno, f'unknown variable {var.id}') + add_semantic_error(var.lineno, var.colno, f'unknown variable {var.id}') def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) - if lvalue_type != IntType: - raise Exception(operator.lvalue.lineno, operator.lvalue.colno, - f'invalid left value type {lvalue_type}, must be a {IntType}') + if lvalue_type != IntType and lvalue_type is not None: + add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, + f'invalid left value type {lvalue_type}, must be a {IntType}') rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) - if rvalue_type != IntType: - raise Exception(operator.rvalue.lineno, operator.rvalue.colno, - f'invalid left value type {rvalue_type}, must be a {IntType}') + if rvalue_type != IntType and rvalue_type is not None: + add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, + f'invalid left value type {rvalue_type}, must be a {IntType}') return IntType @@ -103,17 +100,17 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) static_types = [IntType, BoolType, StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: - raise Exception(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') + add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') return BoolType def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) - if lvalue_type != IntType: - raise Exception(cmp.lvalue.lineno, cmp.lvalue.colno, 'lvalue type must be a {IntType}') + if lvalue_type != IntType and lvalue_type is not None: + add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, f'lvalue type must be a {IntType}') rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) - if rvalue_type != IntType: - raise Exception(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') + if rvalue_type != IntType and rvalue_type is not None: + add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') return BoolType @@ -123,23 +120,25 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: except KeyError: attr, _ = get_attribute(current_class, assign.id) if attr is None: - raise Exception(assign.id.lineno, assign.id.colno, f'unknown variable {assign.id}') + add_semantic_error(assign.id.lineno, assign.id.colno, f'unknown variable {assign.id}') + id_type = None else: id_type = attr.attrType expr_type = expression_visitor(assign.expr, current_class, local_scope) - if check_inherits(expr_type, id_type): - return expr_type - raise Exception(assign.expr.lineno, assign.expr.colno, f'Type {expr_type} cannot be stored in type {id_type}') + if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: + add_semantic_error(assign.expr.lineno, assign.expr.colno, + f'Type {expr_type} cannot be stored in type {id_type}') + return expr_type def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): id_type = type_by_name(def_attr.type) if id_type is None: - raise Exception(def_attr.lineno, def_attr.colno, f'unknown type {def_attr.type}') + add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type {def_attr.type}') if def_attr.expr: expr_type = expression_visitor(def_attr.expr, current_class, local_scope) - if not check_inherits(expr_type, id_type): - raise Exception(def_attr.lineno, def_attr.colno, f'Type {expr_type} cannot be stored in type {id_type}') + if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: + add_semantic_error(def_attr.lineno, def_attr.colno, f'Type {expr_type} cannot be stored in type {id_type}') return id_type @@ -147,7 +146,7 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): local_scope = local_scope.copy() for attribute in let.let_attrs: attribute_type = expression_visitor(attribute, current_class, local_scope) - local_scope[attribute.id] = attribute_type + local_scope[attribute.id] = ObjectType return expression_visitor(let.expr, current_class, local_scope) @@ -161,7 +160,7 @@ def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: d def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) if predicate_type != BoolType: - raise Exception(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\"if\" condition must be a {BoolType}') + add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\"if\" condition must be a {BoolType}') then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) return pronounced_join(then_type, else_type) @@ -178,22 +177,26 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if func_call.type: specific_type = type_by_name(func_call.type) if specific_type is None: - raise Exception(func_call.lineno, func_call.colno, f'unknown type {func_call.type}') - if check_inherits(current_class, specific_type): + add_semantic_error(func_call.lineno, func_call.colno, f'unknown type {func_call.type}') + elif check_inherits(current_class, specific_type): method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) else: - raise Exception(func_call.lineno, func_call.colno, - f'type {current_class} not inherits from {specific_type}') + add_semantic_error(func_call.lineno, func_call.colno, + f'type {current_class} not inherits from {specific_type}') else: object_type = expression_visitor(func_call.object, current_class, local_scope) - method, msg = object_type.get_method(func_call.id, args_types) + if object_type is None: + return None + else: + method, msg = object_type.get_method(func_call.id, args_types) else: method, msg = current_class.get_method(func_call.id, args_types) if method is None: - raise Exception(func_call.lineno, func_call.colno, msg) - if method.returnedType == SelfType: + add_semantic_error(func_call.lineno, func_call.colno, msg) + elif method.returnedType == SelfType: return current_class - return method.returnedType + else: + return method.returnedType def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): @@ -219,8 +222,8 @@ def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scop def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(loop.cond, current_class, local_scope) - if predicate_type != BoolType: - raise Exception(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') + if predicate_type != BoolType and predicate_type is not None: + add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') expression_visitor(loop.body, current_class, local_scope) return ObjectType @@ -228,7 +231,7 @@ def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dic def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): t = type_by_name(new.type) if not t: - raise Exception(new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') + add_semantic_error(new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') if t == SelfType: return current_class return t From 10a56291609487f26b63429e14614068295f5325 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 17:27:39 -0400 Subject: [PATCH 101/435] Fix bool type in lexer/parser --- src/lexer_parser/lexer.py | 12 ++++++------ src/lexer_parser/parser.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index 2fe9cea9..43dbc0b2 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -89,18 +89,18 @@ def t_TYPE(t): return t -def t_ID(t): - r'[a-z][a-zA-Z_0-9]*' - t.type = reserved.get(t.value.lower(), 'ID') - return t - - def t_BOOL(t): r'f[Aa][Ll][Ss][Ee]|t[Rr][Uu][Ee]' t.value = (t.value.lower == 'true') return t +def t_ID(t): + r'[a-z][a-zA-Z_0-9]*' + t.type = reserved.get(t.value.lower(), 'ID') + return t + + def t_LINECOMMENT(t): r'--' t.lexer.begin('commentLine') diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 03d15f26..ba168b0c 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -261,7 +261,7 @@ def p_atom_block(p): def p_atom_bool(p): '''atom : BOOL''' - p[0] = BoolNode(p[1].lower()) + p[0] = BoolNode(p[1]) p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) From c2d81b2de796342aa1f11ce1af718feeace791fa Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 17:32:21 -0400 Subject: [PATCH 102/435] Add self variable Add self variable to each class local_scope --- src/semantic/semantic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 3748f75e..e62657bc 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -31,12 +31,14 @@ def program_visitor(program: ProgramNode): def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: dict): current_class = TypesByName[_class.type] + local_scope = local_scope.copy() + local_scope['self'] = current_class # Check all features for feature in _class.feature_nodes: if type(feature) is DefAttrNode: - def_attr_class_visitor(feature, current_class, {}) + def_attr_class_visitor(feature, current_class, local_scope) if type(feature) is DefFuncNode: - def_func_visitor(feature, current_class, {}) + def_func_visitor(feature, current_class, local_scope) def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): From a680bd554772599b27b0f8484bcb865b841b5346 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 18:01:15 -0400 Subject: [PATCH 103/435] Make better error messages --- src/semantic/semantic.py | 19 ++++++++++--------- src/semantic/types.py | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index e62657bc..7d06deed 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -46,7 +46,7 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco expr_type = expression_visitor(attr.expr, current_class, {}) attr_type = type_by_name(attr.type) if attr_type is not None and not check_inherits(expr_type, attr_type): - add_semantic_error(attr.lineno, attr.colno, f'cannot save type {expr_type} inside type {attr_type}') + add_semantic_error(attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') else: return attr_type @@ -60,7 +60,7 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope if check_inherits(body_type, return_type): return return_type elif body_type is not None: - add_semantic_error(function.lineno, function.colno, f'invalid returned type {function.return_type}') + add_semantic_error(function.lineno, function.colno, f'invalid returned type \'{function.return_type}\'') def int_visitor(expr, current_class, local_scope): @@ -82,7 +82,7 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if attribute is not None: return attribute.attrType else: - add_semantic_error(var.lineno, var.colno, f'unknown variable {var.id}') + add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): @@ -122,25 +122,26 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: except KeyError: attr, _ = get_attribute(current_class, assign.id) if attr is None: - add_semantic_error(assign.id.lineno, assign.id.colno, f'unknown variable {assign.id}') + add_semantic_error(assign.id.lineno, assign.id.colno, f'unknown variable \'{assign.id}\'') id_type = None else: id_type = attr.attrType expr_type = expression_visitor(assign.expr, current_class, local_scope) if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(assign.expr.lineno, assign.expr.colno, - f'Type {expr_type} cannot be stored in type {id_type}') + f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') return expr_type def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): id_type = type_by_name(def_attr.type) if id_type is None: - add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type {def_attr.type}') + add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') if def_attr.expr: expr_type = expression_visitor(def_attr.expr, current_class, local_scope) if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: - add_semantic_error(def_attr.lineno, def_attr.colno, f'Type {expr_type} cannot be stored in type {id_type}') + add_semantic_error(def_attr.lineno, def_attr.colno, + f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') return id_type @@ -162,7 +163,7 @@ def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: d def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) if predicate_type != BoolType: - add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\"if\" condition must be a {BoolType}') + add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) return pronounced_join(then_type, else_type) @@ -179,7 +180,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if func_call.type: specific_type = type_by_name(func_call.type) if specific_type is None: - add_semantic_error(func_call.lineno, func_call.colno, f'unknown type {func_call.type}') + add_semantic_error(func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') elif check_inherits(current_class, specific_type): method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) else: diff --git a/src/semantic/types.py b/src/semantic/types.py index 52684458..8b896059 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -22,11 +22,11 @@ def add_method(self, id, arg_types_name, returned_type): for arg in arg_types_name: arg_type = type_by_name(arg) if arg_type is None: - return False, f'unknown type {arg}' + return False, f'unknown type \'{arg}\'' arg_types.append(arg_type) _returned_type = type_by_name(returned_type) if _returned_type is None: - return False, f'unknown type {returned_type}' + return False, f'unknown type \'{returned_type}\'' self.methods[id] = CoolTypeMethod(id, arg_types, _returned_type) return True, None else: @@ -39,16 +39,18 @@ def get_method(self, id, args_types): if self.parent: return self.parent.get_method(id, args_types) else: - return None, f'unknown method {id}' + return None, f'unknown method \'{id}\'' def get_method_without_hierarchy(self, id, args_types): try: method = self.methods[id] if len(args_types) != len(method.args): - return None, f'arguments count mismatch' + return None, f'method \'{self.name}.{id}\' formal parameter count ({len(method.args)}) ' \ + f'does not match actual parameter count ({len(args_types)})' for i, a in enumerate(args_types): if a != method.args[i]: - return None, f'type of argument {i} mismatch' + return None, f'method \'{self.name}.{id}\' parameter #{i} type mismatch. Actual: \'{a}\' should ' \ + f'be a subtype of \'{method.args[i]}\' ' return method, None except KeyError: raise Exception(f'type {self.name} don\'t have a method {id}') @@ -56,14 +58,14 @@ def get_method_without_hierarchy(self, id, args_types): def add_attr(self, id, attr_type): attribute, owner_type = get_attribute(self, id) if attribute is not None: - return False, f'attribute \"{id}\" already declared in class \"{owner_type.name}\"' + return False, f'attribute \'{id}\' already declared in class \'{owner_type.name}\'' try: _ = self.attributes[id] - return False, f'attribute \"{id}\" already declared in class \"{self.name}\"' + return False, f'attribute \'{id}\' already declared in class \'{self.name}\'' except KeyError: _attr_type = type_by_name(attr_type) if _attr_type is None: - return False, f'unknown type {attr_type}' + return False, f'unknown type \'{attr_type}\'' self.attributes[id] = CoolTypeAttribute(id, _attr_type) return True, None From 3fae63b645cd140bee35a433c0a5c4603ac828aa Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 18:01:31 -0400 Subject: [PATCH 104/435] Reformat code --- src/lexer_parser/parser.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index ba168b0c..96bba64e 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -21,6 +21,7 @@ def p_program(p): 'program : class_list' p[0] = ProgramNode(p[1]) + def p_empty(p): 'empty :' pass @@ -66,7 +67,7 @@ def p_def_attr_declaration(p): p[0] = DefAttrNode(p[1], p[3]) p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) - + def p_def_func(p): '''def_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET''' @@ -74,7 +75,6 @@ def p_def_func(p): p[0].add_location(p.lineno(6), find_column(p.lexer.lexdata, p.lexpos(6))) - def p_params_ne(p): '''params : param_list''' p[0] = p[1] @@ -124,7 +124,6 @@ def p_expr_assign(p): p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) - def p_expr_func_all(p): '''expr : expr AT TYPE DOT ID OPAREN arg_list CPAREN | expr DOT ID OPAREN arg_list CPAREN @@ -144,7 +143,7 @@ def p_expr_func_all(p): p[3] = [] p[0] = FuncCallNode(p[1], p[3]) p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) - + p[0].lineno = p.lineno(0) @@ -173,6 +172,7 @@ def p_expr_operators_binary(p): p[0].add_location(p.lineno(0), find_column(p.lexer.lexdata, p.lexpos(0))) + def p_expr_operators_unary(p): '''expr : NOT expr | ISVOID expr @@ -287,7 +287,7 @@ def p_block_list(p): def p_error(p): if p: - add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \"{p.value}\"') + add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \'{p.value}\'') else: add_parser_error(0, 0, "ERROR at or near EOF") From e4a326e5a7c5b693cd6fa8c1a938c7a0b4e58a98 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 1 May 2020 18:26:21 -0400 Subject: [PATCH 105/435] Change class order visit in semantic check --- src/semantic/semantic.py | 11 ++++++++++- src/semantic/types.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 7d06deed..11ae9a6e 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -11,7 +11,15 @@ def program_visitor(program: ProgramNode): add_semantic_error(0, 0, f'Main class undeclared') return # Initialize MethodEnv - for c in program.classes: + types_already_check = [ObjectType, IntType, StringNode, BoolType, IOType] + classes = program.classes.copy() + while len(classes) != 0: + c: DefClassNode = classes.pop() + if c.parent_type is not None: + parent_type = TypesByName[c.parent_type] + if parent_type not in types_already_check: + classes = [c] + classes + continue classType = TypesByName[c.type] for f in c.feature_nodes: if type(f) is DefFuncNode: @@ -24,6 +32,7 @@ def program_visitor(program: ProgramNode): result, msg = classType.add_attr(f.id, f.type) if not result: add_semantic_error(f.lineno, f.colno, msg) + types_already_check.append(classType) # Visit each class inside for c in program.classes: class_visitor(c, None, {}) diff --git a/src/semantic/types.py b/src/semantic/types.py index 8b896059..73b57275 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -124,7 +124,7 @@ def check_type_declaration(node: ProgramNode): for c in node.classes: try: _ = TypesByName[c.type] - add_semantic_error(c.lineno, c.colno, f'duplicated declaration of type {c.type}') + add_semantic_error(c.lineno, c.colno, f'duplicated declaration of type \'{c.type}\'') return False except KeyError: TypesByName[c.type] = CoolType(c.type, None) From c5e949573c8692f24acf3858558254ce3697eaf9 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 1 May 2020 18:28:13 -0400 Subject: [PATCH 106/435] adding cil ast --- src/code_generation/cil_ast.py | 148 +++++++++++++++++++++++++ src/code_generation/code_generation.py | 1 + 2 files changed, 149 insertions(+) create mode 100644 src/code_generation/cil_ast.py create mode 100644 src/code_generation/code_generation.py diff --git a/src/code_generation/cil_ast.py b/src/code_generation/cil_ast.py new file mode 100644 index 00000000..eecf93f1 --- /dev/null +++ b/src/code_generation/cil_ast.py @@ -0,0 +1,148 @@ +class Node: + pass + +class ProgramNode(Node): + def __init__(self, types, data, code): + self.types = types + self.data = data + self.code = code + +class TypesNode(Node): + def __init__(self, type): + self.attributes=[] + self.methods=[] + self.type=type + +class DataNode(Node): + def __init__(self, id, val): + self.id=id + self.val=val + +class FuncNode(Node): + def __init__(self, name, params, locals, body): + self.name=name + self.params=params + self.locals=locals + self.body=body + +class InstructionNode(Node): + pass + +class LocalNode(Node): + def __init__(self, id): + self.id=id + +class ParamNode(Node): + def __init__(self, id): + self.id=id + +class AssignNode(InstructionNode): + def __init__(self, id, val): + self.id=id + self.val=val + +class ArithNode(InstructionNode): + def __init__(self, left, right, result): + self.left=left + self.right=right + self.result=result + +class GetAttrNode(InstructionNode): + def __init__(self, obj, attr, result): + self.attr=attr + self.obj=obj + self.result=result + +class SetAttrNode(InstructionNode): + def __init__(self, obj, attr, val): + self.val=val + self.obj=obj + self.attr=attr + +class SetIndexNode(InstructionNode): + def __init__(self, array, index, val): + self.val=val + self.array=array + self.index=index + +class GetIndexNode(InstructionNode): + def __init__(self, array, index, result): + self.result=result + self.array=array + self.index=index + +class AllocateNode(InstructionNode): + def __init__(self, type, addr): + self.type=type + self.addr=addr + +class TypeOfNode(InstructionNode): + def __init__(self, result, var): + self.result=result + self.var=var + +class ArrayNode(InstructionNode): + def __init__(self, len, result): + self.len=len + self.result=result + +class CallNode(InstructionNode): + def __init__(self, method): + self.method=method + +class VCAllNode(InstructionNode): + def __init__(self, type, method): + self.method=method + +class ArgNode(InstructionNode): + def __init__(self, val): + self.val=val + +class ConditionalGotoNode(InstructionNode): + def __init__(self, predicate, label): + self.predicate=predicate + self.label=label + +class GotoNode(InstructionNode): + def __init__(self, label): + self.label=label + +class LabelNode(InstructionNode): + def __init__(self, label_name): + self.label_name=label_name + +class ReturnNode(InstructionNode): + def __init__(self, ret_value): + self.ret_value=ret_value + +class StrOpNode(InstructionNode): + def __init__(self, str, result): + self.result=result + self.str=str + +class LoadNode(StrOpNode): + pass + +class LengthNode(StrOpNode): + pass + +class ConcatNode(StrOpNode): + pass + +class SubStringNode(StrOpNode): + pass + +class StrNode(StrOpNode): + pass + +class ReadNode(InstructionNode): + pass + +class PrintNode(InstructionNode): + def __init__(self, str): + self.str=str + + + + + \ No newline at end of file diff --git a/src/code_generation/code_generation.py b/src/code_generation/code_generation.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/code_generation/code_generation.py @@ -0,0 +1 @@ + From 9e57719a5648d9f89e2c73e15dcee5920f34a445 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 1 May 2020 18:36:16 -0400 Subject: [PATCH 107/435] Adding arithmetic nodes --- src/code_generation/cil_ast.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/code_generation/cil_ast.py b/src/code_generation/cil_ast.py index eecf93f1..95352e61 100644 --- a/src/code_generation/cil_ast.py +++ b/src/code_generation/cil_ast.py @@ -46,6 +46,18 @@ def __init__(self, left, right, result): self.left=left self.right=right self.result=result + +class PlusNode(ArithNode): + pass + +class MinusNode(ArithNode): + pass + +class StarNode(ArithNode): + pass + +class DivNode(ArithNode): + pass class GetAttrNode(InstructionNode): def __init__(self, obj, attr, result): From f7ae9518b73b95939cac35bc0737b0e93e3ec9d4 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 1 May 2020 19:59:05 -0400 Subject: [PATCH 108/435] adding code generation visitors to each cil ast node --- src/code_generation/cil_ast.py | 46 ++++++--- src/code_generation/code_generation.py | 138 +++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 17 deletions(-) diff --git a/src/code_generation/cil_ast.py b/src/code_generation/cil_ast.py index 95352e61..ec1e5c9a 100644 --- a/src/code_generation/cil_ast.py +++ b/src/code_generation/cil_ast.py @@ -7,7 +7,7 @@ def __init__(self, types, data, code): self.data = data self.code = code -class TypesNode(Node): +class TypeNode(Node): def __init__(self, type): self.attributes=[] self.methods=[] @@ -99,12 +99,15 @@ def __init__(self, len, result): self.result=result class CallNode(InstructionNode): - def __init__(self, method): + def __init__(self, method, result): self.method=method + self.result=result class VCAllNode(InstructionNode): - def __init__(self, type, method): + def __init__(self, type, method, result): self.method=method + self.type=type + self.result=result class ArgNode(InstructionNode): def __init__(self, val): @@ -127,25 +130,34 @@ class ReturnNode(InstructionNode): def __init__(self, ret_value): self.ret_value=ret_value -class StrOpNode(InstructionNode): - def __init__(self, str, result): - self.result=result - self.str=str -class LoadNode(StrOpNode): - pass +class LoadNode(InstructionNode): + def __init__(self, addr, result): + self.result=result + self.addr=addr -class LengthNode(StrOpNode): - pass +class LengthNode(InstructionNode): + def __init__(self, str, result): + self.result=result + self.str=str -class ConcatNode(StrOpNode): - pass +class ConcatNode(InstructionNode): + def __init__(self, str_a, str_b, result): + self.result=result + self.str_a=str_a + self.str_b=str_b -class SubStringNode(StrOpNode): - pass +class SubStringNode(InstructionNode): + def __init__(self, str_a, str_b, result): + self.result=result + self.str_a=str_a + self.str_b=str_b -class StrNode(StrOpNode): - pass +class StrNode(InstructionNode): + def __init__(self, val, str): + self.str=str + self.val=val + class ReadNode(InstructionNode): pass diff --git a/src/code_generation/code_generation.py b/src/code_generation/code_generation.py index 8b137891..c7e93b4c 100644 --- a/src/code_generation/code_generation.py +++ b/src/code_generation/code_generation.py @@ -1 +1,139 @@ +from cil_ast import * + +def program_cg_visitor(program:ProgramNode): + type_code='' + data_code='' + func_code='' + for t in program.types: + type_code+=f'{type_cg_visitor(t)}\n' + for d in program.data: + data_code+=f'{data_cg_visitor(d)}\n' + for f in program.code: + func_code+=f'{func_cg_visitor(f)}\n' + + return f'.TYPES \n {type_code} .DATA \n {data_code} .CODE \n {func_code}' + + +def type_cg_visitor(type: TypeNode): + attr_code='' + method_code='' + for attr in type.attributes: + attr_code+=f'attribute {attr}; \n' + + for met in type.methods: + method_code+=f'method {met}:{type.name}_{met};\n' + + return f'type {type.name} {{ \n {attr_code} {method_code} }}' + + +def data_cg_visitor(data: DataNode): + return f'{data.id} = {data.value} ;' + +def func_cg_visitor(func: FuncNode): + params_code='' + locals_code='' + body_code='' + for param in func.params: + params_code+=f'{param_cg_visitor(param)}\n' + + for local in func.locals: + locals_code+=f'{local_cg_visitor(local)}\n' + + for instruction in func.body: + body_code+=f'{instruction_cg_visitor(instruction)}\n' + + return f'function {func.name} {{ \n {params_code} {locals_code} {body_code} }}' + + +def param_cg_visitor(param:ParamNode): + return f'PARAM {param} ;' + +def local_cg_visitor(local:LocalNode): + return f'LOCAL {local} ;' + + +def instruction_cg_visitor(instrucion:InstructionNode): + #aqui se llama al metodo que toque segun el tipo dinamico de instruction + pass + + +def assign_cg_visitor(assign:AssignNode): + return f'{assign.id} = {assign.val} ;' + +def plus_cg_visitor(plus:PlusNode): + return f'{plus.result} = {plus.left} + {plus.right} ;' + +def minus_cg_visitor(minus:MinusNode): + return f'{minus.result} = {minus.left} - {minus.right} ;' + +def star_cg_visitor(star:StarNode): + return f'{star.result} = {star.left} * {star.right} ;' + +def div_cg_visitor(div:DivNode): + return f'{div.result} = {div.left} / {div.right} ;' + +def get_attr_cg_visitor(getattr:GetAttrNode): + return f'{getattr.result} = GETATTR {getattr.obj} {getattr.attr} ;' + +def set_attr_cg_visitor(setattr:SetAttrNode): + return f'SETATTR {setattr.obj} {setattr.attr} {setattr.val} ;' + +def get_index_cg_visitor(getindex:GetIndexNode): + return f'{getindex.result} = GETINDEX {getindex.array} {getindex.index} ;' + +def set_index_cg_visitor(setindex:SetIndexNode): + return f'SETINDEX {setindex.array} {setindex.index} {setindex.val} ;' + +def allocate_cg_visitor(allocate:AllocateNode): + return f'{allocate.addr} = ALLOCATE {allocate.type} ;' + +def typeof_cg_visitor(typeof: TypeOfNode): + return f'{typeof.result} = TYPEOF {typeof.var} ;' + +def array_cg_visitor(array: ArrayNode): + return f'{array.result} = ARRAY {array.len} ;' + +def call_cg_visitor(call:CallNode): + return f'{call.result} = CALL {call.method} ;' + +def vcall_cg_visitor(vcall:VCAllNode): + return f'{vcall.result} = VCALL {vcall.type} {vcall.method} ;' + +def arg_cg_visitor(arg:ArgNode): + return f'ARG {arg.val} ;' + +def cond_goto_cg_visitor(gcoto:ConditionalGotoNode): + return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' + +def goto_cg_visitor(goto:GotoNode): + return f'GOTO {goto.label} ;' + +def label_cg_visitor(label:LabelNode): + return f'LABEL {label.label_name} ;' + +def return_cg_visitor(ret:ReturnNode): + return f'RETURN {ret.ret_value} ;' if ret.ret_value else f'RETURN ;' + +def load_cg_visitor(load:LoadNode): + return f'{load.result} = LOAD {load.addr} ;' + +def length_cg_visitor(length:LengthNode): + return f'{length.result} = LENGTH {length.str} ;' + +def concat_cg_visitor(concat:ConcatNode): + return f'{concat.result} = CONCAT {concat.str_a} {concat.str_b} ;' + +def substring_cg_visitor(substring:SubStringNode): + return f'{substring.result} = SUBSTRING {substring.str_a} {substring.str_b} ;' + +def str_cg_visitor(str: StrNode): + return f'{str.str} = STR {str.val} ;' + +def read_cg_visitor(read:ReadNode): + return 'READ ;' + +def print_cg_visitor(print:PrintNode): + return f'PRINT {print.str} ;' + + From f943b2d9643b9757289722072208ceacfa7374d9 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 1 May 2020 20:08:43 -0400 Subject: [PATCH 109/435] Completing instruction code generation visitor --- src/code_generation/code_generation.py | 38 ++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/code_generation/code_generation.py b/src/code_generation/code_generation.py index c7e93b4c..3ee7e379 100644 --- a/src/code_generation/code_generation.py +++ b/src/code_generation/code_generation.py @@ -52,9 +52,11 @@ def local_cg_visitor(local:LocalNode): return f'LOCAL {local} ;' -def instruction_cg_visitor(instrucion:InstructionNode): - #aqui se llama al metodo que toque segun el tipo dinamico de instruction - pass +def instruction_cg_visitor(instruction:InstructionNode): + try: + return __visitors__[type(instruction)](instruction) + except KeyError: + print(f'Not visitor for {instruction}') def assign_cg_visitor(assign:AssignNode): @@ -134,6 +136,36 @@ def read_cg_visitor(read:ReadNode): def print_cg_visitor(print:PrintNode): return f'PRINT {print.str} ;' + + +__visitors__ = { + AssignNode:assign_cg_visitor, + PlusNode:plus_cg_visitor, + MinusNode:minus_cg_visitor, + StarNode:star_cg_visitor, + DivNode:div_cg_visitor, + GetAttrNode:get_attr_cg_visitor, + SetAttrNode:set_attr_cg_visitor, + GetIndexNode:get_index_cg_visitor, + SetIndexNode:set_index_cg_visitor, + AllocateNode:allocate_cg_visitor, + TypeOfNode:typeof_cg_visitor, + ArrayNode:array_cg_visitor, + CallNode:call_cg_visitor, + VCAllNode:vcall_cg_visitor, + ArgNode:arg_cg_visitor, + ConditionalGotoNode:cond_goto_cg_visitor, + GotoNode:goto_cg_visitor, + LabelNode: label_cg_visitor, + ReturnNode:return_cg_visitor, + LoadNode:load_cg_visitor, + LengthNode:length_cg_visitor, + ConcatNode:concat_cg_visitor, + SubStringNode:substring_cg_visitor, + StrNode:str_cg_visitor, + ReadNode:read_cg_visitor, + PrintNode:print_cg_visitor +} From 7a6d71aedff6bfb8bc572c3e4c6c45909b03422a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 00:11:17 -0400 Subject: [PATCH 110/435] adding assign, arith, if, loop, equal ast-to-cil visitors --- src/code_generation/ast_to_cil.py | 129 +++++++++++++++++++++++++ src/code_generation/code_generation.py | 9 +- 2 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/code_generation/ast_to_cil.py diff --git a/src/code_generation/ast_to_cil.py b/src/code_generation/ast_to_cil.py new file mode 100644 index 00000000..7202bd32 --- /dev/null +++ b/src/code_generation/ast_to_cil.py @@ -0,0 +1,129 @@ +import lexer_parser.ast as lp_ast +from types import TypesByName +import cil_ast as cil + +def program_to_cil_visitor(program): + types=[] + data=[] + code=[] + + return cil.ProgramNode(types, data, code) + +def func_to_cil_visitor(type_name, func): + name=f'{type_name}_{func.id}' + params=[id for (id, t) in func.params] + locals=[] + body=[] + locals_count=0 + for exp in func.expressions: + instruction=expression_to_cil_visitor(exp, locals_count) + locals.append(instruction.locals) + body.append(instruction.body) + locals_count+=len(instruction.locals) + + return cil.FuncNode(name, params, locals, body) + + +def expression_to_cil_visitor(expression, locals_count): + pass + +def assign_to_cil_visitor(assign, locals_count): + expr=expression_to_cil_visitor(assign.expr, locals_count) + locals_count+=len(expr.locals) + value=[f'local_{locals_count}'] + locals=expr.locals+[cil.LocalNode(value)] + body=expr.body+[cil.AssignNode(assign.id, expr.value)] + return CIL_block(locals, body, value) + +def arith_to_cil_visitor(arith, locals_count): + + l=expression_to_cil_visitor(arith.lvalue, locals_count) + r=expression_to_cil_visitor(arith.rvalue, locals_count) + locals_count+=len(l.locals)+len(r.locals) + + cil_result=f'local_{locals_count}' + + locals=l.locals+r.locals+[cil.LocalNode(cil_result)] + body=l.body+r.body + + if type(arith)==lp_ast.PlusNode: + body.append(cil.PlusNode(l.value, r.value, cil_result)) + elif type(arith)==lp_ast.MinusNode: + body.append(cil.MinusNode(l.value, r.value, cil_result)) + elif type(arith)==lp_ast.StarNode: + body.append(cil.StarNode(l.value, r.value, cil_result)) + elif type(arith)==lp_ast.DivNode: + body.append(cil.DivNode(l.value, r.value, cil_result)) + + return CIL_block(locals, body, cil_result) + +def if_to_cil_visitor(_if, locals_count): + predicate=expression_to_cil_visitor(_if.if_expr, locals_count) + locals_count+=len(predicate.locals) + + then=expression_to_cil_visitor(_if.then_expr, locals_count) + locals_count+=len(then.locals) + + else_expression=expression_to_cil_visitor(_if.else_expr, locals_count) + locals_count+=len(else_expression.locals) + + label_1=f'local_{locals_count}' + label_2=f'local_{locals_count+1}' + value=f'local_{locals_count+2}' + + locals=predicate.locals+then.locals+else_expression.locals+[cil.LocalNode(value)] + body=[cil.ConditionalGotoNode(predicate.value, label_1)]+else_expression.body+[cil.AssignNode(value, else_expression.value),cil.GotoNode(label_2),cil.LabelNode(label_1)]+then.body+[cil.AssignNode(value, then.value),cil.LabelNode(label_2)] + + return CIL_block(locals, body, value) + +def loop_to_cil_visitor(loop, locals_count): + predicate=expression_to_cil_visitor(loop.cond, locals_count) + locals_count+=len(predicate.locals) + + loop_block=expression_to_cil_visitor(loop.body, locals_count) + locals_count+=len(loop_block.locals) + + value=f'local_{locals_count}' + + locals=predicate.locals+loop_block.locals+[cil.LocalNode(value)] + + loop_label=f'local_{locals_count+1}' + end_label=f'local_{locals_count+2}' + + body=[cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)]+loop_block.body+[cil.AssignNode(value, loop_block.value) ,cil.LabelNode(end_label)] + + return CIL_block(locals, body, value) + +def equal_to_cil_visitor(less_than, locals_count): + l=expression_to_cil_visitor(arith.lvalue, locals_count) + r=expression_to_cil_visitor(arith.rvalue, locals_count) + locals_count+=len(l.locals)+len(r.locals) + + cil_result=f'local_{locals_count}' + end_label=f'local_{locals_count+1}' + value=f'local_{locals_count+2}' + + locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] + body=l.body+r.body+[cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] + + return CIL_block(locals, body) + + +class CIL_block: + def __init__(self, locals, body): + self.locals=locals + self.body=body + self.value=value + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/code_generation/code_generation.py b/src/code_generation/code_generation.py index 3ee7e379..964e9c60 100644 --- a/src/code_generation/code_generation.py +++ b/src/code_generation/code_generation.py @@ -12,8 +12,7 @@ def program_cg_visitor(program:ProgramNode): func_code+=f'{func_cg_visitor(f)}\n' return f'.TYPES \n {type_code} .DATA \n {data_code} .CODE \n {func_code}' - - + def type_cg_visitor(type: TypeNode): attr_code='' method_code='' @@ -25,7 +24,6 @@ def type_cg_visitor(type: TypeNode): return f'type {type.name} {{ \n {attr_code} {method_code} }}' - def data_cg_visitor(data: DataNode): return f'{data.id} = {data.value} ;' @@ -44,21 +42,18 @@ def func_cg_visitor(func: FuncNode): return f'function {func.name} {{ \n {params_code} {locals_code} {body_code} }}' - def param_cg_visitor(param:ParamNode): return f'PARAM {param} ;' def local_cg_visitor(local:LocalNode): return f'LOCAL {local} ;' - def instruction_cg_visitor(instruction:InstructionNode): - try: + try: return __visitors__[type(instruction)](instruction) except KeyError: print(f'Not visitor for {instruction}') - def assign_cg_visitor(assign:AssignNode): return f'{assign.id} = {assign.val} ;' From 629c57dca20e0cf955f0bda34e8256a50fc6cf82 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 2 May 2020 11:33:32 -0400 Subject: [PATCH 111/435] Support SELF_TYPE for the type returned in function declarations --- src/semantic/semantic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 11ae9a6e..1ba34cf0 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -66,6 +66,8 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope local_scope[arg[0]] = type_by_name(arg[1]) body_type = expression_visitor(function.expressions, current_class, local_scope) return_type = type_by_name(function.return_type) + if return_type == SelfType: + return_type = current_class if check_inherits(body_type, return_type): return return_type elif body_type is not None: From ca609bedff249148928c546cf722d5ef00f7f6fd Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 13:58:24 -0400 Subject: [PATCH 112/435] Organization issues --- src/code_generation/__init__.py | 1 + src/code_generation/{cil_ast.py => ast.py} | 0 src/code_generation/{ast_to_cil.py => cil.py} | 14 ++++++++------ .../{code_generation.py => code.py} | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/code_generation/__init__.py rename src/code_generation/{cil_ast.py => ast.py} (100%) rename src/code_generation/{ast_to_cil.py => cil.py} (94%) rename src/code_generation/{code_generation.py => code.py} (99%) diff --git a/src/code_generation/__init__.py b/src/code_generation/__init__.py new file mode 100644 index 00000000..59169856 --- /dev/null +++ b/src/code_generation/__init__.py @@ -0,0 +1 @@ +#aun no tengo la funcion que hay que importar de aqui, por eso no lo habia puesto \ No newline at end of file diff --git a/src/code_generation/cil_ast.py b/src/code_generation/ast.py similarity index 100% rename from src/code_generation/cil_ast.py rename to src/code_generation/ast.py diff --git a/src/code_generation/ast_to_cil.py b/src/code_generation/cil.py similarity index 94% rename from src/code_generation/ast_to_cil.py rename to src/code_generation/cil.py index 7202bd32..5543fb49 100644 --- a/src/code_generation/ast_to_cil.py +++ b/src/code_generation/cil.py @@ -1,17 +1,19 @@ import lexer_parser.ast as lp_ast + + from types import TypesByName -import cil_ast as cil +import code_generation.ast as cil def program_to_cil_visitor(program): types=[] data=[] code=[] - + #build program node with each section return cil.ProgramNode(types, data, code) def func_to_cil_visitor(type_name, func): name=f'{type_name}_{func.id}' - params=[id for (id, t) in func.params] + params=[cil.ParamNode(id) for (id, t) in func.params] locals=[] body=[] locals_count=0 @@ -22,9 +24,9 @@ def func_to_cil_visitor(type_name, func): locals_count+=len(instruction.locals) return cil.FuncNode(name, params, locals, body) - - + def expression_to_cil_visitor(expression, locals_count): + #choose appropriate visitor pass def assign_to_cil_visitor(assign, locals_count): @@ -106,7 +108,7 @@ def equal_to_cil_visitor(less_than, locals_count): locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] body=l.body+r.body+[cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body) + return CIL_block(locals, body, value) class CIL_block: diff --git a/src/code_generation/code_generation.py b/src/code_generation/code.py similarity index 99% rename from src/code_generation/code_generation.py rename to src/code_generation/code.py index 964e9c60..a528ffb7 100644 --- a/src/code_generation/code_generation.py +++ b/src/code_generation/code.py @@ -1,4 +1,4 @@ -from cil_ast import * +from code_generation.ast import * def program_cg_visitor(program:ProgramNode): type_code='' From 4ba2d44e4dd225f682ffd75a4e2384d6d49e7568 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 2 May 2020 14:07:34 -0400 Subject: [PATCH 113/435] Add TypesByName to __init__.py of semantic library --- src/semantic/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semantic/__init__.py b/src/semantic/__init__.py index 5c5a05f0..226d5515 100644 --- a/src/semantic/__init__.py +++ b/src/semantic/__init__.py @@ -1 +1,2 @@ from .semantic import semantic_check +from .types import TypesByName From 2900f92147119237e4f14573854bf6b013196c79 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 14:42:27 -0400 Subject: [PATCH 114/435] adding cil generators for constants and for new --- src/code_generation/cil.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 5543fb49..a30ae526 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -110,12 +110,40 @@ def equal_to_cil_visitor(less_than, locals_count): return CIL_block(locals, body, value) + +def integer_to_cil_visitor(integer, locals_count): + return CIL_block([], [], integer.value) + +def bool_to_cil_visitor(bool, locals_count): + return CIL_block([], [], 1) if bool=='true' else CIL_block([], [], 0) + +def id_to_cil_visitor(id, locals_count): + return CIL_block([], [], id.id) + +def new_to_cil_visitor(new_node, locals_count): + value=f'local_{locals_count}' + body=[cil.AllocateNode(new_node.type, value)] + locals=[cil.LocalNode(value)] + return CIL_block(locals, body, value) + +def string_to_cil_visitor(str, locals_count): + str_addr=f'local_{locals_count}' + str_id=f'local_{locals_count+1}' + + locals=[cil.LocalNode(str_id)] + data=[cil.DataNode(str_addr, str.value)] + body=[cil.LoadNode(str_addr, str_id)] + + return CIL_block(locals, body, str_id, data) class CIL_block: - def __init__(self, locals, body): + def __init__(self, locals, body, value, data=[]): self.locals=locals self.body=body self.value=value + self.data=data + + From c95c71a42c704989b2d58bfc8c393bc116073235 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:09:18 -0400 Subject: [PATCH 115/435] Adding data to visitors --- src/code_generation/cil.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a30ae526..b8bf0580 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -35,7 +35,7 @@ def assign_to_cil_visitor(assign, locals_count): value=[f'local_{locals_count}'] locals=expr.locals+[cil.LocalNode(value)] body=expr.body+[cil.AssignNode(assign.id, expr.value)] - return CIL_block(locals, body, value) + return CIL_block(locals, body, value, expr.data) def arith_to_cil_visitor(arith, locals_count): @@ -47,6 +47,7 @@ def arith_to_cil_visitor(arith, locals_count): locals=l.locals+r.locals+[cil.LocalNode(cil_result)] body=l.body+r.body + data=l.data+r.data if type(arith)==lp_ast.PlusNode: body.append(cil.PlusNode(l.value, r.value, cil_result)) @@ -57,7 +58,7 @@ def arith_to_cil_visitor(arith, locals_count): elif type(arith)==lp_ast.DivNode: body.append(cil.DivNode(l.value, r.value, cil_result)) - return CIL_block(locals, body, cil_result) + return CIL_block(locals, body, cil_result, data) def if_to_cil_visitor(_if, locals_count): predicate=expression_to_cil_visitor(_if.if_expr, locals_count) @@ -75,8 +76,9 @@ def if_to_cil_visitor(_if, locals_count): locals=predicate.locals+then.locals+else_expression.locals+[cil.LocalNode(value)] body=[cil.ConditionalGotoNode(predicate.value, label_1)]+else_expression.body+[cil.AssignNode(value, else_expression.value),cil.GotoNode(label_2),cil.LabelNode(label_1)]+then.body+[cil.AssignNode(value, then.value),cil.LabelNode(label_2)] + data=predicate.data+then.data+else_expression.data - return CIL_block(locals, body, value) + return CIL_block(locals, body, value, data) def loop_to_cil_visitor(loop, locals_count): predicate=expression_to_cil_visitor(loop.cond, locals_count) @@ -93,8 +95,9 @@ def loop_to_cil_visitor(loop, locals_count): end_label=f'local_{locals_count+2}' body=[cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)]+loop_block.body+[cil.AssignNode(value, loop_block.value) ,cil.LabelNode(end_label)] + data=predicate.data+loop_block.data - return CIL_block(locals, body, value) + return CIL_block(locals, body, value, data) def equal_to_cil_visitor(less_than, locals_count): l=expression_to_cil_visitor(arith.lvalue, locals_count) @@ -107,10 +110,10 @@ def equal_to_cil_visitor(less_than, locals_count): locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] body=l.body+r.body+[cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] + data=l.data+r.data - return CIL_block(locals, body, value) - - + return CIL_block(locals, body, value, data) + def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) @@ -136,6 +139,26 @@ def string_to_cil_visitor(str, locals_count): return CIL_block(locals, body, str_id, data) +def let_to_cil_visitor(let, locals_count): + body=[] + locals=[] + data=[] + for attr in let.let_attr: + attr_cil=expression_to_cil_visitor(attr, locals_count) + locals_count+=len(attr_cil.locals) + body.append(cil.AssignNode(attr.id, attr_cil.value)) + body+=attr_cil.body + locals+=attr_cil.locals + data+=attr_cil.data + + expr_cil=expression_to_cil_visitor(let.expr, locals_count) + locals+=expr_cil.locals + body+=expr_cil.locals + data+=expr_cil.data + + return CIL_block(locals, body, expr_cil.value, data) + + class CIL_block: def __init__(self, locals, body, value, data=[]): self.locals=locals From d8750ad39f29786e2f75f2d03f37b9ade4d3ba67 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:24:01 -0400 Subject: [PATCH 116/435] Adding logic not cil visitor --- src/code_generation/cil.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index b8bf0580..a222fc5a 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -158,6 +158,18 @@ def let_to_cil_visitor(let, locals_count): return CIL_block(locals, body, expr_cil.value, data) +def logic_not_to_cil_visitor(not_node, locals_count): + expr_cil=expression_to_cil_visitor(not_node.val, locals_count) + locals_count+=len(expr_cil.locals) + + value=f'local_{locals_count}' + end_label=f'local_{locals_count + 1}' + + + locals=expr_cil.locals+[cil.LocalNode(value)] + body=expr_cil.body+[cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] + + return CIL_block(locals, body, value, expr_cil.data) class CIL_block: def __init__(self, locals, body, value, data=[]): From e94b9d0737e4f6a343c647e07af1d4a140d23692 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 2 May 2020 15:32:45 -0400 Subject: [PATCH 117/435] Reformat code and remove unnecessary imports --- src/code_generation/ast.py | 209 ++++++++++++++++++--------------- src/code_generation/cil.py | 229 +++++++++++++++++++------------------ 2 files changed, 233 insertions(+), 205 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index ec1e5c9a..36154d82 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -1,172 +1,199 @@ class Node: pass + class ProgramNode(Node): def __init__(self, types, data, code): self.types = types self.data = data self.code = code - + + class TypeNode(Node): def __init__(self, type): - self.attributes=[] - self.methods=[] - self.type=type - + self.attributes = [] + self.methods = [] + self.type = type + + class DataNode(Node): def __init__(self, id, val): - self.id=id - self.val=val - + self.id = id + self.val = val + + class FuncNode(Node): def __init__(self, name, params, locals, body): - self.name=name - self.params=params - self.locals=locals - self.body=body - + self.name = name + self.params = params + self.locals = locals + self.body = body + + class InstructionNode(Node): pass - + + class LocalNode(Node): def __init__(self, id): - self.id=id - + self.id = id + + class ParamNode(Node): def __init__(self, id): - self.id=id - + self.id = id + + class AssignNode(InstructionNode): def __init__(self, id, val): - self.id=id - self.val=val - + self.id = id + self.val = val + + class ArithNode(InstructionNode): def __init__(self, left, right, result): - self.left=left - self.right=right - self.result=result - + self.left = left + self.right = right + self.result = result + + class PlusNode(ArithNode): pass + class MinusNode(ArithNode): pass + class StarNode(ArithNode): pass + class DivNode(ArithNode): pass + class GetAttrNode(InstructionNode): def __init__(self, obj, attr, result): - self.attr=attr - self.obj=obj - self.result=result - + self.attr = attr + self.obj = obj + self.result = result + + class SetAttrNode(InstructionNode): - def __init__(self, obj, attr, val): - self.val=val - self.obj=obj - self.attr=attr - + def __init__(self, obj, attr, val): + self.val = val + self.obj = obj + self.attr = attr + + class SetIndexNode(InstructionNode): def __init__(self, array, index, val): - self.val=val - self.array=array - self.index=index - + self.val = val + self.array = array + self.index = index + + class GetIndexNode(InstructionNode): def __init__(self, array, index, result): - self.result=result - self.array=array - self.index=index - + self.result = result + self.array = array + self.index = index + + class AllocateNode(InstructionNode): def __init__(self, type, addr): - self.type=type - self.addr=addr - + self.type = type + self.addr = addr + + class TypeOfNode(InstructionNode): def __init__(self, result, var): - self.result=result - self.var=var - + self.result = result + self.var = var + + class ArrayNode(InstructionNode): def __init__(self, len, result): - self.len=len - self.result=result - + self.len = len + self.result = result + + class CallNode(InstructionNode): def __init__(self, method, result): - self.method=method - self.result=result - + self.method = method + self.result = result + + class VCAllNode(InstructionNode): def __init__(self, type, method, result): - self.method=method - self.type=type - self.result=result - + self.method = method + self.type = type + self.result = result + + class ArgNode(InstructionNode): def __init__(self, val): - self.val=val - + self.val = val + + class ConditionalGotoNode(InstructionNode): def __init__(self, predicate, label): - self.predicate=predicate - self.label=label - + self.predicate = predicate + self.label = label + + class GotoNode(InstructionNode): def __init__(self, label): - self.label=label - + self.label = label + + class LabelNode(InstructionNode): def __init__(self, label_name): - self.label_name=label_name - + self.label_name = label_name + + class ReturnNode(InstructionNode): def __init__(self, ret_value): - self.ret_value=ret_value + self.ret_value = ret_value + - class LoadNode(InstructionNode): def __init__(self, addr, result): - self.result=result - self.addr=addr - + self.result = result + self.addr = addr + + class LengthNode(InstructionNode): def __init__(self, str, result): - self.result=result - self.str=str + self.result = result + self.str = str + class ConcatNode(InstructionNode): def __init__(self, str_a, str_b, result): - self.result=result - self.str_a=str_a - self.str_b=str_b + self.result = result + self.str_a = str_a + self.str_b = str_b + class SubStringNode(InstructionNode): def __init__(self, str_a, str_b, result): - self.result=result - self.str_a=str_a - self.str_b=str_b - + self.result = result + self.str_a = str_a + self.str_b = str_b + + class StrNode(InstructionNode): def __init__(self, val, str): - self.str=str - self.val=val - - + self.str = str + self.val = val + + class ReadNode(InstructionNode): pass + class PrintNode(InstructionNode): def __init__(self, str): - self.str=str - - - - - \ No newline at end of file + self.str = str diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a30ae526..721f9791 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,159 +1,160 @@ import lexer_parser.ast as lp_ast - -from types import TypesByName import code_generation.ast as cil + def program_to_cil_visitor(program): - types=[] - data=[] - code=[] - #build program node with each section + types = [] + data = [] + code = [] + # build program node with each section return cil.ProgramNode(types, data, code) - -def func_to_cil_visitor(type_name, func): - name=f'{type_name}_{func.id}' - params=[cil.ParamNode(id) for (id, t) in func.params] - locals=[] - body=[] - locals_count=0 + + +def func_to_cil_visitor(type_name, func): + name = f'{type_name}_{func.id}' + params = [cil.ParamNode(id) for (id, t) in func.params] + locals = [] + body = [] + locals_count = 0 for exp in func.expressions: - instruction=expression_to_cil_visitor(exp, locals_count) + instruction = expression_to_cil_visitor(exp, locals_count) locals.append(instruction.locals) body.append(instruction.body) - locals_count+=len(instruction.locals) - + locals_count += len(instruction.locals) + return cil.FuncNode(name, params, locals, body) - + + def expression_to_cil_visitor(expression, locals_count): - #choose appropriate visitor + # choose appropriate visitor pass + def assign_to_cil_visitor(assign, locals_count): - expr=expression_to_cil_visitor(assign.expr, locals_count) - locals_count+=len(expr.locals) - value=[f'local_{locals_count}'] - locals=expr.locals+[cil.LocalNode(value)] - body=expr.body+[cil.AssignNode(assign.id, expr.value)] + expr = expression_to_cil_visitor(assign.expr, locals_count) + locals_count += len(expr.locals) + value = [f'local_{locals_count}'] + locals = expr.locals + [cil.LocalNode(value)] + body = expr.body + [cil.AssignNode(assign.id, expr.value)] return CIL_block(locals, body, value) + def arith_to_cil_visitor(arith, locals_count): - - l=expression_to_cil_visitor(arith.lvalue, locals_count) - r=expression_to_cil_visitor(arith.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) - - cil_result=f'local_{locals_count}' - - locals=l.locals+r.locals+[cil.LocalNode(cil_result)] - body=l.body+r.body - - if type(arith)==lp_ast.PlusNode: + l = expression_to_cil_visitor(arith.lvalue, locals_count) + r = expression_to_cil_visitor(arith.rvalue, locals_count) + locals_count += len(l.locals) + len(r.locals) + + cil_result = f'local_{locals_count}' + + locals = l.locals + r.locals + [cil.LocalNode(cil_result)] + body = l.body + r.body + + if type(arith) == lp_ast.PlusNode: body.append(cil.PlusNode(l.value, r.value, cil_result)) - elif type(arith)==lp_ast.MinusNode: + elif type(arith) == lp_ast.MinusNode: body.append(cil.MinusNode(l.value, r.value, cil_result)) - elif type(arith)==lp_ast.StarNode: + elif type(arith) == lp_ast.StarNode: body.append(cil.StarNode(l.value, r.value, cil_result)) - elif type(arith)==lp_ast.DivNode: + elif type(arith) == lp_ast.DivNode: body.append(cil.DivNode(l.value, r.value, cil_result)) - + return CIL_block(locals, body, cil_result) - + + def if_to_cil_visitor(_if, locals_count): - predicate=expression_to_cil_visitor(_if.if_expr, locals_count) - locals_count+=len(predicate.locals) - - then=expression_to_cil_visitor(_if.then_expr, locals_count) - locals_count+=len(then.locals) - - else_expression=expression_to_cil_visitor(_if.else_expr, locals_count) - locals_count+=len(else_expression.locals) - - label_1=f'local_{locals_count}' - label_2=f'local_{locals_count+1}' - value=f'local_{locals_count+2}' - - locals=predicate.locals+then.locals+else_expression.locals+[cil.LocalNode(value)] - body=[cil.ConditionalGotoNode(predicate.value, label_1)]+else_expression.body+[cil.AssignNode(value, else_expression.value),cil.GotoNode(label_2),cil.LabelNode(label_1)]+then.body+[cil.AssignNode(value, then.value),cil.LabelNode(label_2)] - + predicate = expression_to_cil_visitor(_if.if_expr, locals_count) + locals_count += len(predicate.locals) + + then = expression_to_cil_visitor(_if.then_expr, locals_count) + locals_count += len(then.locals) + + else_expression = expression_to_cil_visitor(_if.else_expr, locals_count) + locals_count += len(else_expression.locals) + + label_1 = f'local_{locals_count}' + label_2 = f'local_{locals_count + 1}' + value = f'local_{locals_count + 2}' + + locals = predicate.locals + then.locals + else_expression.locals + [cil.LocalNode(value)] + body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ + cil.AssignNode(value, then.value), cil.LabelNode(label_2)] + return CIL_block(locals, body, value) - + + def loop_to_cil_visitor(loop, locals_count): - predicate=expression_to_cil_visitor(loop.cond, locals_count) - locals_count+=len(predicate.locals) - - loop_block=expression_to_cil_visitor(loop.body, locals_count) - locals_count+=len(loop_block.locals) - - value=f'local_{locals_count}' - - locals=predicate.locals+loop_block.locals+[cil.LocalNode(value)] - - loop_label=f'local_{locals_count+1}' - end_label=f'local_{locals_count+2}' - - body=[cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)]+loop_block.body+[cil.AssignNode(value, loop_block.value) ,cil.LabelNode(end_label)] - + predicate = expression_to_cil_visitor(loop.cond, locals_count) + locals_count += len(predicate.locals) + + loop_block = expression_to_cil_visitor(loop.body, locals_count) + locals_count += len(loop_block.locals) + + value = f'local_{locals_count}' + + locals = predicate.locals + loop_block.locals + [cil.LocalNode(value)] + + loop_label = f'local_{locals_count + 1}' + end_label = f'local_{locals_count + 2}' + + body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), + cil.LabelNode(loop_label)] + loop_block.body + [cil.AssignNode(value, loop_block.value), + cil.LabelNode(end_label)] + return CIL_block(locals, body, value) + def equal_to_cil_visitor(less_than, locals_count): - l=expression_to_cil_visitor(arith.lvalue, locals_count) - r=expression_to_cil_visitor(arith.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) - - cil_result=f'local_{locals_count}' - end_label=f'local_{locals_count+1}' - value=f'local_{locals_count+2}' - - locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] - body=l.body+r.body+[cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - + l = expression_to_cil_visitor(arith.lvalue, locals_count) + r = expression_to_cil_visitor(arith.rvalue, locals_count) + locals_count += len(l.locals) + len(r.locals) + + cil_result = f'local_{locals_count}' + end_label = f'local_{locals_count + 1}' + value = f'local_{locals_count + 2}' + + locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] + body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), + cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.LabelNode(end_label)] + return CIL_block(locals, body, value) - - + + def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) + def bool_to_cil_visitor(bool, locals_count): - return CIL_block([], [], 1) if bool=='true' else CIL_block([], [], 0) + return CIL_block([], [], 1) if bool == 'true' else CIL_block([], [], 0) + def id_to_cil_visitor(id, locals_count): return CIL_block([], [], id.id) + def new_to_cil_visitor(new_node, locals_count): - value=f'local_{locals_count}' - body=[cil.AllocateNode(new_node.type, value)] - locals=[cil.LocalNode(value)] + value = f'local_{locals_count}' + body = [cil.AllocateNode(new_node.type, value)] + locals = [cil.LocalNode(value)] return CIL_block(locals, body, value) + def string_to_cil_visitor(str, locals_count): - str_addr=f'local_{locals_count}' - str_id=f'local_{locals_count+1}' - - locals=[cil.LocalNode(str_id)] - data=[cil.DataNode(str_addr, str.value)] - body=[cil.LoadNode(str_addr, str_id)] - + str_addr = f'local_{locals_count}' + str_id = f'local_{locals_count + 1}' + + locals = [cil.LocalNode(str_id)] + data = [cil.DataNode(str_addr, str.value)] + body = [cil.LoadNode(str_addr, str_id)] + return CIL_block(locals, body, str_id, data) + class CIL_block: def __init__(self, locals, body, value, data=[]): - self.locals=locals - self.body=body - self.value=value - self.data=data - - - - - - - - - - - - - - - \ No newline at end of file + self.locals = locals + self.body = body + self.value = value + self.data = data From d644e8671b5671161e26163c3df096a3f5a2fb19 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:37:07 -0400 Subject: [PATCH 118/435] adding block cil visitor --- src/code_generation/cil.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a222fc5a..f474593b 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -171,6 +171,22 @@ def logic_not_to_cil_visitor(not_node, locals_count): return CIL_block(locals, body, value, expr_cil.data) +def block_to_cil_visitor(block, locals_count): + locals=[] + body=[] + data=[] + value=None + + for expr in block.expressions: + expr_cil=expression_to_cil_visitor(expr, locals_count) + locals_count+=len(expr_cil.locals) + locals+=expr_cil.locals + body+=expr_cil.body + data+=expr_cil.data + value=expr_cil.value + + return CIL_block(locals, body, value, data) + class CIL_block: def __init__(self, locals, body, value, data=[]): self.locals=locals From adc4c8109d30416f365e95c4fce928df3fd631ba Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 2 May 2020 15:37:30 -0400 Subject: [PATCH 119/435] Reformat code --- src/code_generation/code.py | 190 +++++++++++++++++++++--------------- 1 file changed, 110 insertions(+), 80 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index a528ffb7..9308b95e 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -1,166 +1,196 @@ from code_generation.ast import * -def program_cg_visitor(program:ProgramNode): - type_code='' - data_code='' - func_code='' - for t in program.types: - type_code+=f'{type_cg_visitor(t)}\n' + +def program_cg_visitor(program: ProgramNode): + type_code = '' + data_code = '' + func_code = '' + for t in program.types: + type_code += f'{type_cg_visitor(t)}\n' for d in program.data: - data_code+=f'{data_cg_visitor(d)}\n' + data_code += f'{data_cg_visitor(d)}\n' for f in program.code: - func_code+=f'{func_cg_visitor(f)}\n' - + func_code += f'{func_cg_visitor(f)}\n' + return f'.TYPES \n {type_code} .DATA \n {data_code} .CODE \n {func_code}' - + + def type_cg_visitor(type: TypeNode): - attr_code='' - method_code='' + attr_code = '' + method_code = '' for attr in type.attributes: - attr_code+=f'attribute {attr}; \n' - + attr_code += f'attribute {attr}; \n' + for met in type.methods: - method_code+=f'method {met}:{type.name}_{met};\n' - + method_code += f'method {met}:{type.name}_{met};\n' + return f'type {type.name} {{ \n {attr_code} {method_code} }}' + def data_cg_visitor(data: DataNode): return f'{data.id} = {data.value} ;' + def func_cg_visitor(func: FuncNode): - params_code='' - locals_code='' - body_code='' + params_code = '' + locals_code = '' + body_code = '' for param in func.params: - params_code+=f'{param_cg_visitor(param)}\n' - + params_code += f'{param_cg_visitor(param)}\n' + for local in func.locals: - locals_code+=f'{local_cg_visitor(local)}\n' - + locals_code += f'{local_cg_visitor(local)}\n' + for instruction in func.body: - body_code+=f'{instruction_cg_visitor(instruction)}\n' - + body_code += f'{instruction_cg_visitor(instruction)}\n' + return f'function {func.name} {{ \n {params_code} {locals_code} {body_code} }}' - -def param_cg_visitor(param:ParamNode): + + +def param_cg_visitor(param: ParamNode): return f'PARAM {param} ;' -def local_cg_visitor(local:LocalNode): + +def local_cg_visitor(local: LocalNode): return f'LOCAL {local} ;' -def instruction_cg_visitor(instruction:InstructionNode): + +def instruction_cg_visitor(instruction: InstructionNode): try: return __visitors__[type(instruction)](instruction) except KeyError: print(f'Not visitor for {instruction}') -def assign_cg_visitor(assign:AssignNode): + +def assign_cg_visitor(assign: AssignNode): return f'{assign.id} = {assign.val} ;' -def plus_cg_visitor(plus:PlusNode): + +def plus_cg_visitor(plus: PlusNode): return f'{plus.result} = {plus.left} + {plus.right} ;' -def minus_cg_visitor(minus:MinusNode): + +def minus_cg_visitor(minus: MinusNode): return f'{minus.result} = {minus.left} - {minus.right} ;' -def star_cg_visitor(star:StarNode): + +def star_cg_visitor(star: StarNode): return f'{star.result} = {star.left} * {star.right} ;' -def div_cg_visitor(div:DivNode): + +def div_cg_visitor(div: DivNode): return f'{div.result} = {div.left} / {div.right} ;' -def get_attr_cg_visitor(getattr:GetAttrNode): + +def get_attr_cg_visitor(getattr: GetAttrNode): return f'{getattr.result} = GETATTR {getattr.obj} {getattr.attr} ;' -def set_attr_cg_visitor(setattr:SetAttrNode): + +def set_attr_cg_visitor(setattr: SetAttrNode): return f'SETATTR {setattr.obj} {setattr.attr} {setattr.val} ;' -def get_index_cg_visitor(getindex:GetIndexNode): + +def get_index_cg_visitor(getindex: GetIndexNode): return f'{getindex.result} = GETINDEX {getindex.array} {getindex.index} ;' -def set_index_cg_visitor(setindex:SetIndexNode): + +def set_index_cg_visitor(setindex: SetIndexNode): return f'SETINDEX {setindex.array} {setindex.index} {setindex.val} ;' -def allocate_cg_visitor(allocate:AllocateNode): + +def allocate_cg_visitor(allocate: AllocateNode): return f'{allocate.addr} = ALLOCATE {allocate.type} ;' + def typeof_cg_visitor(typeof: TypeOfNode): return f'{typeof.result} = TYPEOF {typeof.var} ;' + def array_cg_visitor(array: ArrayNode): return f'{array.result} = ARRAY {array.len} ;' -def call_cg_visitor(call:CallNode): + +def call_cg_visitor(call: CallNode): return f'{call.result} = CALL {call.method} ;' -def vcall_cg_visitor(vcall:VCAllNode): + +def vcall_cg_visitor(vcall: VCAllNode): return f'{vcall.result} = VCALL {vcall.type} {vcall.method} ;' -def arg_cg_visitor(arg:ArgNode): + +def arg_cg_visitor(arg: ArgNode): return f'ARG {arg.val} ;' -def cond_goto_cg_visitor(gcoto:ConditionalGotoNode): + +def cond_goto_cg_visitor(gcoto: ConditionalGotoNode): return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' -def goto_cg_visitor(goto:GotoNode): + +def goto_cg_visitor(goto: GotoNode): return f'GOTO {goto.label} ;' -def label_cg_visitor(label:LabelNode): + +def label_cg_visitor(label: LabelNode): return f'LABEL {label.label_name} ;' -def return_cg_visitor(ret:ReturnNode): + +def return_cg_visitor(ret: ReturnNode): return f'RETURN {ret.ret_value} ;' if ret.ret_value else f'RETURN ;' -def load_cg_visitor(load:LoadNode): + +def load_cg_visitor(load: LoadNode): return f'{load.result} = LOAD {load.addr} ;' -def length_cg_visitor(length:LengthNode): + +def length_cg_visitor(length: LengthNode): return f'{length.result} = LENGTH {length.str} ;' -def concat_cg_visitor(concat:ConcatNode): + +def concat_cg_visitor(concat: ConcatNode): return f'{concat.result} = CONCAT {concat.str_a} {concat.str_b} ;' -def substring_cg_visitor(substring:SubStringNode): + +def substring_cg_visitor(substring: SubStringNode): return f'{substring.result} = SUBSTRING {substring.str_a} {substring.str_b} ;' + def str_cg_visitor(str: StrNode): return f'{str.str} = STR {str.val} ;' -def read_cg_visitor(read:ReadNode): + +def read_cg_visitor(read: ReadNode): return 'READ ;' -def print_cg_visitor(print:PrintNode): + +def print_cg_visitor(print: PrintNode): return f'PRINT {print.str} ;' __visitors__ = { - AssignNode:assign_cg_visitor, - PlusNode:plus_cg_visitor, - MinusNode:minus_cg_visitor, - StarNode:star_cg_visitor, - DivNode:div_cg_visitor, - GetAttrNode:get_attr_cg_visitor, - SetAttrNode:set_attr_cg_visitor, - GetIndexNode:get_index_cg_visitor, - SetIndexNode:set_index_cg_visitor, - AllocateNode:allocate_cg_visitor, - TypeOfNode:typeof_cg_visitor, - ArrayNode:array_cg_visitor, - CallNode:call_cg_visitor, - VCAllNode:vcall_cg_visitor, - ArgNode:arg_cg_visitor, - ConditionalGotoNode:cond_goto_cg_visitor, - GotoNode:goto_cg_visitor, + AssignNode: assign_cg_visitor, + PlusNode: plus_cg_visitor, + MinusNode: minus_cg_visitor, + StarNode: star_cg_visitor, + DivNode: div_cg_visitor, + GetAttrNode: get_attr_cg_visitor, + SetAttrNode: set_attr_cg_visitor, + GetIndexNode: get_index_cg_visitor, + SetIndexNode: set_index_cg_visitor, + AllocateNode: allocate_cg_visitor, + TypeOfNode: typeof_cg_visitor, + ArrayNode: array_cg_visitor, + CallNode: call_cg_visitor, + VCAllNode: vcall_cg_visitor, + ArgNode: arg_cg_visitor, + ConditionalGotoNode: cond_goto_cg_visitor, + GotoNode: goto_cg_visitor, LabelNode: label_cg_visitor, - ReturnNode:return_cg_visitor, - LoadNode:load_cg_visitor, - LengthNode:length_cg_visitor, - ConcatNode:concat_cg_visitor, - SubStringNode:substring_cg_visitor, - StrNode:str_cg_visitor, - ReadNode:read_cg_visitor, - PrintNode:print_cg_visitor + ReturnNode: return_cg_visitor, + LoadNode: load_cg_visitor, + LengthNode: length_cg_visitor, + ConcatNode: concat_cg_visitor, + SubStringNode: substring_cg_visitor, + StrNode: str_cg_visitor, + ReadNode: read_cg_visitor, + PrintNode: print_cg_visitor } - - - From 0acbfc185c61addc712b641df7135896c5b317b3 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:41:01 -0400 Subject: [PATCH 120/435] adding visitors dictionary --- src/code_generation/cil.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index f474593b..719748cf 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -193,7 +193,26 @@ def __init__(self, locals, body, value, data=[]): self.body=body self.value=value self.data=data - + + +__visitor__={ + lp_ast.AssignNode:assign_to_cil_visitor, + lp_ast.BlockNode:block_to_cil_visitor, + lp_ast.BoolNode:bool_to_cil_visitor, + lp_ast.IfNode:if_to_cil_visitor, + lp_ast.WhileNode:loop_to_cil_visitor, + lp_ast.EqNode:equal_to_cil_visitor, + lp_ast.LogicNegationNode:logic_not_to_cil_visitor, + lp_ast.LetNode:let_to_cil_visitor, + lp_ast.NewNode:new_to_cil_visitor, + lp_ast.IntNode:integer_to_cil_visitor, + lp_ast.StringNode:string_to_cil_visitor, + lp_ast.PlusNode:arith_to_cil_visitor, + lp_ast.MinusNode:arith_to_cil_visitor, + lp_ast.StarNode:arith_to_cil_visitor, + lp_ast.DivNode:arith_to_cil_visitor, + lp_ast.VarNode:id_to_cil_visitor +} From 6cc0c7de328b099d64f6e0b56965c04fe106cd80 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:42:16 -0400 Subject: [PATCH 121/435] adding expression generic visitor --- src/code_generation/cil.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 719748cf..d25b65a4 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -26,8 +26,10 @@ def func_to_cil_visitor(type_name, func): return cil.FuncNode(name, params, locals, body) def expression_to_cil_visitor(expression, locals_count): - #choose appropriate visitor - pass + try: + return __visitor__[type(expression)](expression, locals_count) + except: + raise Exception(f'There is no visitor for {type(expression)}') def assign_to_cil_visitor(assign, locals_count): expr=expression_to_cil_visitor(assign.expr, locals_count) From 30d402e5433b81fe820243a6869011f21b3a2f7c Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 15:44:20 -0400 Subject: [PATCH 122/435] fixing ctrl-c --- src/code_generation/cil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index d25b65a4..b46a4a43 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -101,9 +101,9 @@ def loop_to_cil_visitor(loop, locals_count): return CIL_block(locals, body, value, data) -def equal_to_cil_visitor(less_than, locals_count): - l=expression_to_cil_visitor(arith.lvalue, locals_count) - r=expression_to_cil_visitor(arith.rvalue, locals_count) +def equal_to_cil_visitor(equal, locals_count): + l=expression_to_cil_visitor(equal.lvalue, locals_count) + r=expression_to_cil_visitor(equal.rvalue, locals_count) locals_count+=len(l.locals)+len(r.locals) cil_result=f'local_{locals_count}' From de47465e1b209e52b8a38772d68c78777c9156b7 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 16:10:10 -0400 Subject: [PATCH 123/435] adding util function --- src/semantic/types.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/semantic/types.py b/src/semantic/types.py index 8b896059..f2faa709 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -31,6 +31,18 @@ def add_method(self, id, arg_types_name, returned_type): return True, None else: return False, msg + + def get_all_attributes(self): + t=self + result=[] + while t: + temp=[] + for attr in t.attributes: + temp.append(attr) + result.append(temp) + t=t.parent + return [elem for sublist in result[::-1] for elem in sublist] + def get_method(self, id, args_types): try: From 1266ed977a9d70210799c67e5b3a880596ec16f2 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 2 May 2020 16:27:31 -0400 Subject: [PATCH 124/435] Add expression to CoolTypeAttribute --- src/semantic/semantic.py | 2 +- src/semantic/types.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 1ba34cf0..a6508b25 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -29,7 +29,7 @@ def program_visitor(program: ProgramNode): add_semantic_error(f.lineno, f.colno, msg) elif type(f) is DefAttrNode: # Add all attributes to types - result, msg = classType.add_attr(f.id, f.type) + result, msg = classType.add_attr(f.id, f.type, f.expr) if not result: add_semantic_error(f.lineno, f.colno, msg) types_already_check.append(classType) diff --git a/src/semantic/types.py b/src/semantic/types.py index 73b57275..56e87ea9 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -55,7 +55,7 @@ def get_method_without_hierarchy(self, id, args_types): except KeyError: raise Exception(f'type {self.name} don\'t have a method {id}') - def add_attr(self, id, attr_type): + def add_attr(self, id, attr_type, expression): attribute, owner_type = get_attribute(self, id) if attribute is not None: return False, f'attribute \'{id}\' already declared in class \'{owner_type.name}\'' @@ -66,7 +66,7 @@ def add_attr(self, id, attr_type): _attr_type = type_by_name(attr_type) if _attr_type is None: return False, f'unknown type \'{attr_type}\'' - self.attributes[id] = CoolTypeAttribute(id, _attr_type) + self.attributes[id] = CoolTypeAttribute(id, _attr_type, expression) return True, None def __repr__(self): @@ -86,9 +86,10 @@ def get_attribute(type_c: CoolType, id: str): class CoolTypeAttribute: - def __init__(self, id, attr_type): + def __init__(self, id, attr_type, expression=None): self.id = id self.attrType = attr_type + self.expression = expression class CoolTypeMethod: From fcc948ea4fe8dbe0abb2f204846928fccb66437e Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 22:33:52 -0400 Subject: [PATCH 125/435] adding default initialization to allocate --- src/code_generation/cil.py | 47 ++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index b46a4a43..15a65fba 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,15 +1,38 @@ import lexer_parser.ast as lp_ast -from types import TypesByName +from semantic.types import * import code_generation.ast as cil +__types_attributes__={} + def program_to_cil_visitor(program): types=[] data=[] code=[] - #build program node with each section + entry_body=[] + entry_locals=[] + entry_data=[] + + for t in TypesByName: + value=TypesByName[t] + attr=value.get_all_atributes() + _type=cil.TypeNode(t) + __types_attributes__[t]=[] + + #los atributos que llevan inicializacion por defecto se los guarda aqui + for a in attr: + if a.expression: + __types_attributes__[t].append(a) + + + + entry_function=cil.FuncNode(f'entry', [], [], body) + + + return cil.ProgramNode(types, data, code) + def func_to_cil_visitor(type_name, func): name=f'{type_name}_{func.id}' @@ -127,9 +150,22 @@ def id_to_cil_visitor(id, locals_count): def new_to_cil_visitor(new_node, locals_count): value=f'local_{locals_count}' - body=[cil.AllocateNode(new_node.type, value)] locals=[cil.LocalNode(value)] - return CIL_block(locals, body, value) + locals_count+=1 + body=[cil.AllocateNode(new_node.type, value)] + data=[] + init_attr=__types_attributes__[new_node.type] + for attr in init_attr: + + attr_cil=expression_to_cil_visitor(attr.expression, locals_count) + locals_count+=len(attr_cil.locals) + locals.append(attr_cil.locals) + body.append(attr_cil.body) + data.append(attr_cil.data) + + body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) + + return CIL_block(locals, body, value, data) def string_to_cil_visitor(str, locals_count): str_addr=f'local_{locals_count}' @@ -214,7 +250,8 @@ def __init__(self, locals, body, value, data=[]): lp_ast.StarNode:arith_to_cil_visitor, lp_ast.DivNode:arith_to_cil_visitor, lp_ast.VarNode:id_to_cil_visitor -} +} + From d8b83af2de34bd7cc83bc36c3add990478b32a85 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 22:36:19 -0400 Subject: [PATCH 126/435] removing unnecessary dictionary --- src/code_generation/cil.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 15a65fba..16687861 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -4,8 +4,6 @@ from semantic.types import * import code_generation.ast as cil -__types_attributes__={} - def program_to_cil_visitor(program): types=[] data=[] @@ -15,19 +13,9 @@ def program_to_cil_visitor(program): entry_data=[] for t in TypesByName: - value=TypesByName[t] - attr=value.get_all_atributes() _type=cil.TypeNode(t) - __types_attributes__[t]=[] #los atributos que llevan inicializacion por defecto se los guarda aqui - for a in attr: - if a.expression: - __types_attributes__[t].append(a) - - - - entry_function=cil.FuncNode(f'entry', [], [], body) @@ -154,16 +142,16 @@ def new_to_cil_visitor(new_node, locals_count): locals_count+=1 body=[cil.AllocateNode(new_node.type, value)] data=[] - init_attr=__types_attributes__[new_node.type] + init_attr=TypesByName[new_node.type].get_all_attributes() for attr in init_attr: - - attr_cil=expression_to_cil_visitor(attr.expression, locals_count) - locals_count+=len(attr_cil.locals) - locals.append(attr_cil.locals) - body.append(attr_cil.body) - data.append(attr_cil.data) - - body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) + if attr.expression: + attr_cil=expression_to_cil_visitor(attr.expression, locals_count) + locals_count+=len(attr_cil.locals) + locals.append(attr_cil.locals) + body.append(attr_cil.body) + data.append(attr_cil.data) + + body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) return CIL_block(locals, body, value, data) From 429b0685846745e52dfd0ee1bbd1f81ca5c7f522 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 22:38:29 -0400 Subject: [PATCH 127/435] Adding attributes to types in .type section --- src/code_generation/cil.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 16687861..1183cc60 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -14,9 +14,8 @@ def program_to_cil_visitor(program): for t in TypesByName: _type=cil.TypeNode(t) - - #los atributos que llevan inicializacion por defecto se los guarda aqui - + for attr in TypesByName[t].get_all_attributes(): + _type.attributes.append(attr.id) return cil.ProgramNode(types, data, code) @@ -149,8 +148,7 @@ def new_to_cil_visitor(new_node, locals_count): locals_count+=len(attr_cil.locals) locals.append(attr_cil.locals) body.append(attr_cil.body) - data.append(attr_cil.data) - + data.append(attr_cil.data) body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) return CIL_block(locals, body, value, data) From 720cc52dbabaa0c6039f9945869004e05e8aea60 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 2 May 2020 22:42:13 -0400 Subject: [PATCH 128/435] removing unnecessary initializations --- src/code_generation/cil.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 1183cc60..3691d177 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -8,9 +8,7 @@ def program_to_cil_visitor(program): types=[] data=[] code=[] - entry_body=[] - entry_locals=[] - entry_data=[] + for t in TypesByName: _type=cil.TypeNode(t) From e2a17190478153e17b9f4caa97a3a67d7c434e9d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 3 May 2020 11:50:56 -0400 Subject: [PATCH 129/435] Reformat code --- src/code_generation/cil.py | 316 ++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 161 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a9ee1102..bedda346 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,22 +1,19 @@ import lexer_parser.ast as lp_ast - from semantic.types import * import code_generation.ast as cil def program_to_cil_visitor(program): - types=[] - data=[] - code=[] + types = [] + data = [] + code = [] - for t in TypesByName: - _type=cil.TypeNode(t) + _type = cil.TypeNode(t) for attr in TypesByName[t].get_all_attributes(): _type.attributes.append(attr.id) - - + return cil.ProgramNode(types, data, code) @@ -43,27 +40,26 @@ def expression_to_cil_visitor(expression, locals_count): def assign_to_cil_visitor(assign, locals_count): - expr=expression_to_cil_visitor(assign.expr, locals_count) - locals_count+=len(expr.locals) - value=[f'local_{locals_count}'] - locals=expr.locals+[cil.LocalNode(value)] - body=expr.body+[cil.AssignNode(assign.id, expr.value)] + expr = expression_to_cil_visitor(assign.expr, locals_count) + locals_count += len(expr.locals) + value = [f'local_{locals_count}'] + locals = expr.locals + [cil.LocalNode(value)] + body = expr.body + [cil.AssignNode(assign.id, expr.value)] return CIL_block(locals, body, value, expr.data) def arith_to_cil_visitor(arith, locals_count): - - l=expression_to_cil_visitor(arith.lvalue, locals_count) - r=expression_to_cil_visitor(arith.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) - - cil_result=f'local_{locals_count}' - - locals=l.locals+r.locals+[cil.LocalNode(cil_result)] - body=l.body+r.body - data=l.data+r.data - - if type(arith)==lp_ast.PlusNode: + l = expression_to_cil_visitor(arith.lvalue, locals_count) + r = expression_to_cil_visitor(arith.rvalue, locals_count) + locals_count += len(l.locals) + len(r.locals) + + cil_result = f'local_{locals_count}' + + locals = l.locals + r.locals + [cil.LocalNode(cil_result)] + body = l.body + r.body + data = l.data + r.data + + if type(arith) == lp_ast.PlusNode: body.append(cil.PlusNode(l.value, r.value, cil_result)) elif type(arith) == lp_ast.MinusNode: body.append(cil.MinusNode(l.value, r.value, cil_result)) @@ -71,63 +67,73 @@ def arith_to_cil_visitor(arith, locals_count): body.append(cil.StarNode(l.value, r.value, cil_result)) elif type(arith) == lp_ast.DivNode: body.append(cil.DivNode(l.value, r.value, cil_result)) - + return CIL_block(locals, body, cil_result, data) - + + def if_to_cil_visitor(_if, locals_count): - predicate=expression_to_cil_visitor(_if.if_expr, locals_count) - locals_count+=len(predicate.locals) - - then=expression_to_cil_visitor(_if.then_expr, locals_count) - locals_count+=len(then.locals) - - else_expression=expression_to_cil_visitor(_if.else_expr, locals_count) - locals_count+=len(else_expression.locals) - - label_1=f'local_{locals_count}' - label_2=f'local_{locals_count+1}' - value=f'local_{locals_count+2}' - - locals=predicate.locals+then.locals+else_expression.locals+[cil.LocalNode(value)] - body=[cil.ConditionalGotoNode(predicate.value, label_1)]+else_expression.body+[cil.AssignNode(value, else_expression.value),cil.GotoNode(label_2),cil.LabelNode(label_1)]+then.body+[cil.AssignNode(value, then.value),cil.LabelNode(label_2)] - data=predicate.data+then.data+else_expression.data - + predicate = expression_to_cil_visitor(_if.if_expr, locals_count) + locals_count += len(predicate.locals) + + then = expression_to_cil_visitor(_if.then_expr, locals_count) + locals_count += len(then.locals) + + else_expression = expression_to_cil_visitor(_if.else_expr, locals_count) + locals_count += len(else_expression.locals) + + label_1 = f'local_{locals_count}' + label_2 = f'local_{locals_count + 1}' + value = f'local_{locals_count + 2}' + + locals = predicate.locals + then.locals + else_expression.locals + [cil.LocalNode(value)] + body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ + cil.AssignNode(value, then.value), cil.LabelNode(label_2)] + data = predicate.data + then.data + else_expression.data + return CIL_block(locals, body, value, data) - + + def loop_to_cil_visitor(loop, locals_count): - predicate=expression_to_cil_visitor(loop.cond, locals_count) - locals_count+=len(predicate.locals) - - loop_block=expression_to_cil_visitor(loop.body, locals_count) - locals_count+=len(loop_block.locals) - - value=f'local_{locals_count}' - - locals=predicate.locals+loop_block.locals+[cil.LocalNode(value)] - - loop_label=f'local_{locals_count+1}' - end_label=f'local_{locals_count+2}' - - body=[cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)]+loop_block.body+[cil.AssignNode(value, loop_block.value) ,cil.LabelNode(end_label)] - data=predicate.data+loop_block.data - + predicate = expression_to_cil_visitor(loop.cond, locals_count) + locals_count += len(predicate.locals) + + loop_block = expression_to_cil_visitor(loop.body, locals_count) + locals_count += len(loop_block.locals) + + value = f'local_{locals_count}' + + locals = predicate.locals + loop_block.locals + [cil.LocalNode(value)] + + loop_label = f'local_{locals_count + 1}' + end_label = f'local_{locals_count + 2}' + + body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), + cil.LabelNode(loop_label)] + loop_block.body + [cil.AssignNode(value, loop_block.value), + cil.LabelNode(end_label)] + data = predicate.data + loop_block.data + return CIL_block(locals, body, value, data) + def equal_to_cil_visitor(equal, locals_count): - l=expression_to_cil_visitor(equal.lvalue, locals_count) - r=expression_to_cil_visitor(equal.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) - - cil_result=f'local_{locals_count}' - end_label=f'local_{locals_count+1}' - value=f'local_{locals_count+2}' - - locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] - body=l.body+r.body+[cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data=l.data+r.data - + l = expression_to_cil_visitor(equal.lvalue, locals_count) + r = expression_to_cil_visitor(equal.rvalue, locals_count) + locals_count += len(l.locals) + len(r.locals) + + cil_result = f'local_{locals_count}' + end_label = f'local_{locals_count + 1}' + value = f'local_{locals_count + 2}' + + locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] + body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), + cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.LabelNode(end_label)] + data = l.data + r.data + return CIL_block(locals, body, value, data) - + + def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) @@ -141,21 +147,21 @@ def id_to_cil_visitor(id, locals_count): def new_to_cil_visitor(new_node, locals_count): - value=f'local_{locals_count}' - locals=[cil.LocalNode(value)] - locals_count+=1 - body=[cil.AllocateNode(new_node.type, value)] - data=[] - init_attr=TypesByName[new_node.type].get_all_attributes() + value = f'local_{locals_count}' + locals = [cil.LocalNode(value)] + locals_count += 1 + body = [cil.AllocateNode(new_node.type, value)] + data = [] + init_attr = TypesByName[new_node.type].get_all_attributes() for attr in init_attr: if attr.expression: - attr_cil=expression_to_cil_visitor(attr.expression, locals_count) - locals_count+=len(attr_cil.locals) + attr_cil = expression_to_cil_visitor(attr.expression, locals_count) + locals_count += len(attr_cil.locals) locals.append(attr_cil.locals) body.append(attr_cil.body) - data.append(attr_cil.data) + data.append(attr_cil.data) body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) - + return CIL_block(locals, body, value, data) @@ -171,91 +177,79 @@ def string_to_cil_visitor(str, locals_count): def let_to_cil_visitor(let, locals_count): - body=[] - locals=[] - data=[] + body = [] + locals = [] + data = [] for attr in let.let_attr: - attr_cil=expression_to_cil_visitor(attr, locals_count) - locals_count+=len(attr_cil.locals) + attr_cil = expression_to_cil_visitor(attr, locals_count) + locals_count += len(attr_cil.locals) body.append(cil.AssignNode(attr.id, attr_cil.value)) - body+=attr_cil.body - locals+=attr_cil.locals - data+=attr_cil.data - - expr_cil=expression_to_cil_visitor(let.expr, locals_count) - locals+=expr_cil.locals - body+=expr_cil.locals - data+=expr_cil.data - + body += attr_cil.body + locals += attr_cil.locals + data += attr_cil.data + + expr_cil = expression_to_cil_visitor(let.expr, locals_count) + locals += expr_cil.locals + body += expr_cil.locals + data += expr_cil.data + return CIL_block(locals, body, expr_cil.value, data) - + + def logic_not_to_cil_visitor(not_node, locals_count): - expr_cil=expression_to_cil_visitor(not_node.val, locals_count) - locals_count+=len(expr_cil.locals) - - value=f'local_{locals_count}' - end_label=f'local_{locals_count + 1}' - - - locals=expr_cil.locals+[cil.LocalNode(value)] - body=expr_cil.body+[cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - + expr_cil = expression_to_cil_visitor(not_node.val, locals_count) + locals_count += len(expr_cil.locals) + + value = f'local_{locals_count}' + end_label = f'local_{locals_count + 1}' + + locals = expr_cil.locals + [cil.LocalNode(value)] + body = expr_cil.body + [cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), + cil.AssignNode(value, 1), cil.LabelNode(end_label)] + return CIL_block(locals, body, value, expr_cil.data) + def block_to_cil_visitor(block, locals_count): - locals=[] - body=[] - data=[] - value=None - + locals = [] + body = [] + data = [] + value = None + for expr in block.expressions: - expr_cil=expression_to_cil_visitor(expr, locals_count) - locals_count+=len(expr_cil.locals) - locals+=expr_cil.locals - body+=expr_cil.body - data+=expr_cil.data - value=expr_cil.value - + expr_cil = expression_to_cil_visitor(expr, locals_count) + locals_count += len(expr_cil.locals) + locals += expr_cil.locals + body += expr_cil.body + data += expr_cil.data + value = expr_cil.value + return CIL_block(locals, body, value, data) - + + class CIL_block: def __init__(self, locals, body, value, data=[]): - self.locals=locals - self.body=body - self.value=value - self.data=data - - -__visitor__={ - lp_ast.AssignNode:assign_to_cil_visitor, - lp_ast.BlockNode:block_to_cil_visitor, - lp_ast.BoolNode:bool_to_cil_visitor, - lp_ast.IfNode:if_to_cil_visitor, - lp_ast.WhileNode:loop_to_cil_visitor, - lp_ast.EqNode:equal_to_cil_visitor, - lp_ast.LogicNegationNode:logic_not_to_cil_visitor, - lp_ast.LetNode:let_to_cil_visitor, - lp_ast.NewNode:new_to_cil_visitor, - lp_ast.IntNode:integer_to_cil_visitor, - lp_ast.StringNode:string_to_cil_visitor, - lp_ast.PlusNode:arith_to_cil_visitor, - lp_ast.MinusNode:arith_to_cil_visitor, - lp_ast.StarNode:arith_to_cil_visitor, - lp_ast.DivNode:arith_to_cil_visitor, - lp_ast.VarNode:id_to_cil_visitor -} - - - - - - - - - - - - - - - + self.locals = locals + self.body = body + self.value = value + self.data = data + + +__visitor__ = { + lp_ast.AssignNode: assign_to_cil_visitor, + lp_ast.BlockNode: block_to_cil_visitor, + lp_ast.BoolNode: bool_to_cil_visitor, + lp_ast.IfNode: if_to_cil_visitor, + lp_ast.WhileNode: loop_to_cil_visitor, + lp_ast.EqNode: equal_to_cil_visitor, + lp_ast.LogicNegationNode: logic_not_to_cil_visitor, + lp_ast.LetNode: let_to_cil_visitor, + lp_ast.NewNode: new_to_cil_visitor, + lp_ast.IntNode: integer_to_cil_visitor, + lp_ast.StringNode: string_to_cil_visitor, + lp_ast.PlusNode: arith_to_cil_visitor, + lp_ast.MinusNode: arith_to_cil_visitor, + lp_ast.StarNode: arith_to_cil_visitor, + lp_ast.DivNode: arith_to_cil_visitor, + lp_ast.VarNode: id_to_cil_visitor +} From f24f5e6376673f3f20e7f06edac85cd504ab9d41 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 12:59:25 -0400 Subject: [PATCH 130/435] adding main functions for generating code --- src/code_generation/__init__.py | 2 +- src/code_generation/cil.py | 7 ++++++- src/code_generation/code.py | 6 ++++++ src/code_generation/code_gen.py | 7 +++++++ 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/code_generation/code_gen.py diff --git a/src/code_generation/__init__.py b/src/code_generation/__init__.py index 59169856..f0ac8303 100644 --- a/src/code_generation/__init__.py +++ b/src/code_generation/__init__.py @@ -1 +1 @@ -#aun no tengo la funcion que hay que importar de aqui, por eso no lo habia puesto \ No newline at end of file +from .code_gen import generate_code \ No newline at end of file diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 3691d177..fd3c5edf 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -4,12 +4,17 @@ from semantic.types import * import code_generation.ast as cil +def ast_to_cil(ast): + if type(ast)==lp_ast.ProgramNode: + return program_to_cil_visitor(program) + raise Exception(f'AST root must be program') + def program_to_cil_visitor(program): types=[] data=[] code=[] - + #esta funcion esta incompleta for t in TypesByName: _type=cil.TypeNode(t) for attr in TypesByName[t].get_all_attributes(): diff --git a/src/code_generation/code.py b/src/code_generation/code.py index a528ffb7..b07c1c3e 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -1,5 +1,11 @@ from code_generation.ast import * + +def cil_to_code(ast): + if type(ast)==ProgramNode: + return program_cg_visitor(ast) + raise Exception(f'AST root must be program') + def program_cg_visitor(program:ProgramNode): type_code='' data_code='' diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py new file mode 100644 index 00000000..8c4d0a1d --- /dev/null +++ b/src/code_generation/code_gen.py @@ -0,0 +1,7 @@ +from .cil import ast_to_cil +from .code import cil_to_code + +def generate_code(ast): + cil_ast=ast_to_cil(ast) + return cil_to_code(cil_ast) + \ No newline at end of file From 6688df7c1cd8a71f6a4df4ceba6ef06f2a109bf7 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 13:25:49 -0400 Subject: [PATCH 131/435] add functions to get methods --- src/code_generation/cil.py | 6 +++++- src/semantic/types.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index fd3c5edf..1b2e9b7e 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -17,8 +17,12 @@ def program_to_cil_visitor(program): #esta funcion esta incompleta for t in TypesByName: _type=cil.TypeNode(t) - for attr in TypesByName[t].get_all_attributes(): + value=TypesByName[t] + for attr in value.get_all_attributes(): _type.attributes.append(attr.id) + + for met in value.get_all_methods(): + return cil.ProgramNode(types, data, code) diff --git a/src/semantic/types.py b/src/semantic/types.py index 2e873137..8f5895b7 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -43,6 +43,23 @@ def get_all_attributes(self): t=t.parent return [elem for sublist in result[::-1] for elem in sublist] + + def get_all_self_methods(self): + return self.methods + + def get_all_inherited_methods(self): + t=self.parent + result=[] + while t: + temp=[] + for met in t.methods: + met.owner=t.name + temp.append(met) + result.append(temp) + t=t.parent + return [elem for sublist in result[::-1] for elem in sublist] + + def get_method(self, id, args_types): try: From 439b024f6e8f5418bcd5074546108b6b7201eb10 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 3 May 2020 13:38:43 -0400 Subject: [PATCH 132/435] Add Less and Less Equal CIL visitors --- src/code_generation/cil.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index bedda346..9c5c54e9 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,5 +1,4 @@ import lexer_parser.ast as lp_ast - from semantic.types import * import code_generation.ast as cil @@ -133,6 +132,38 @@ def equal_to_cil_visitor(equal, locals_count): return CIL_block(locals, body, value, data) +def lessthan_to_cil_visitor(lessthan, locals_count): + l=expression_to_cil_visitor(lessthan.lvalue, locals_count) + r=expression_to_cil_visitor(lessthan.rvalue, locals_count) + locals_count+=len(l.locals)+len(r.locals) + + cil_less=f'local_{locals_count}' + cil_equal=f'local_{locals_count+1}' + eq_label=f'local_{locals_count+2}' + end_label=f'local_{locals_count+3}' + value=f'local_{locals_count+4}' + + locals=l.locals+r.locals+[cil.LocalNode(cil_less), cil.LocalNode(cil_equal), cil.LocalNode(value)] + body=l.body+r.body+[cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), cil.GotoNode(end_label), cil.LabelNode(eq_label), cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] + data=l.data+r.data + + return CIL_block(locals, body, value, data) + +def lesseqthan_to_cil_visitor(lessthan, locals_count): + l=expression_to_cil_visitor(lessthan.lvalue, locals_count) + r=expression_to_cil_visitor(lessthan.rvalue, locals_count) + locals_count+=len(l.locals)+len(r.locals) + + cil_result=f'local_{locals_count}' + end_label=f'local_{locals_count+1}' + value=f'local_{locals_count+2}' + + locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] + body=l.body+r.body+[cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] + data=l.data+r.data + + return CIL_block(locals, body, value, data) + def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) From 8398d99b9b5b48c8079f8f23ebb0f3fd72f28fcf Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 13:54:58 -0400 Subject: [PATCH 133/435] completing program to cil visitor --- src/code_generation/cil.py | 26 +++++++++++++++++++++----- src/code_generation/code.py | 4 ++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 1b2e9b7e..6e3fb48b 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -14,16 +14,30 @@ def program_to_cil_visitor(program): data=[] code=[] - #esta funcion esta incompleta + #completing .TYPE section for t in TypesByName: _type=cil.TypeNode(t) value=TypesByName[t] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) - for met in value.get_all_methods(): + for met in value.get_all_self_methods(): + _type.methods.append((met.id, t)) + + for met in value.get_all_inherited_methods(): + _type.methods.append((met.id, met.owner)) + + types.append(_type) + #completing .CODE and .DATA sections + for c in program.classes: + for f in c.features: + if type(f)==DefFuncNode: + fun=func_to_cil_visitor(c.name, f) + code.append(fun[0]) + data.append(fun[1]) + return cil.ProgramNode(types, data, code) @@ -33,14 +47,16 @@ def func_to_cil_visitor(type_name, func): params=[cil.ParamNode(id) for (id, t) in func.params] locals=[] body=[] + data=[] locals_count=0 for exp in func.expressions: instruction=expression_to_cil_visitor(exp, locals_count) - locals.append(instruction.locals) - body.append(instruction.body) + locals+=instruction.locals + body+=instruction.body + data+=instruction.data locals_count+=len(instruction.locals) - return cil.FuncNode(name, params, locals, body) + return cil.FuncNode(name, params, locals, body), data def expression_to_cil_visitor(expression, locals_count): try: diff --git a/src/code_generation/code.py b/src/code_generation/code.py index b07c1c3e..1ea8a69f 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -25,8 +25,8 @@ def type_cg_visitor(type: TypeNode): for attr in type.attributes: attr_code+=f'attribute {attr}; \n' - for met in type.methods: - method_code+=f'method {met}:{type.name}_{met};\n' + for name, owner in type.methods: + method_code+=f'method {name}:{owner}_{name};\n' return f'type {type.name} {{ \n {attr_code} {method_code} }}' From f1ad374f3a9e50eacccb1b300f09541a3561c885 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 3 May 2020 13:59:17 -0400 Subject: [PATCH 134/435] Reformat Code and Fix Equal CIL Visitors names --- src/code_generation/cil.py | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 9c5c54e9..8e5bc24b 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -135,32 +135,38 @@ def equal_to_cil_visitor(equal, locals_count): def lessthan_to_cil_visitor(lessthan, locals_count): l=expression_to_cil_visitor(lessthan.lvalue, locals_count) r=expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) + locals_count += len(l.locals) + len(r.locals) - cil_less=f'local_{locals_count}' - cil_equal=f'local_{locals_count+1}' - eq_label=f'local_{locals_count+2}' - end_label=f'local_{locals_count+3}' - value=f'local_{locals_count+4}' + cil_result = f'local_{locals_count}' + end_label = f'local_{locals_count + 1}' + value = f'local_{locals_count + 2}' - locals=l.locals+r.locals+[cil.LocalNode(cil_less), cil.LocalNode(cil_equal), cil.LocalNode(value)] - body=l.body+r.body+[cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), cil.GotoNode(end_label), cil.LabelNode(eq_label), cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data=l.data+r.data + locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] + body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), + cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.LabelNode(end_label)] + data = l.data + r.data return CIL_block(locals, body, value, data) def lesseqthan_to_cil_visitor(lessthan, locals_count): l=expression_to_cil_visitor(lessthan.lvalue, locals_count) r=expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count+=len(l.locals)+len(r.locals) + locals_count += len(l.locals) + len(r.locals) - cil_result=f'local_{locals_count}' - end_label=f'local_{locals_count+1}' - value=f'local_{locals_count+2}' + cil_less = f'local_{locals_count}' + cil_equal = f'local_{locals_count + 1}' + eq_label = f'local_{locals_count + 2}' + end_label = f'local_{locals_count + 3}' + value = f'local_{locals_count + 4}' - locals=l.locals+r.locals+[cil.LocalNode(cil_result), cil.LocalNode(value)] - body=l.body+r.body+[cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0),cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data=l.data+r.data + locals = l.locals + r.locals + [cil.LocalNode(cil_less), cil.LocalNode(cil_equal), cil.LocalNode(value)] + body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), + cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), + cil.GotoNode(end_label), cil.LabelNode(eq_label), + cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), + cil.AssignNode(value, 1), cil.LabelNode(end_label)] + data = l.data + r.data return CIL_block(locals, body, value, data) From dd6e9d39d44d4f873f58b013a0fd13de32bb9efc Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 14:13:30 -0400 Subject: [PATCH 135/435] Adding main function to code section --- src/code_generation/cil.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 6e3fb48b..1e0e29e4 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -29,19 +29,23 @@ def program_to_cil_visitor(program): _type.methods.append((met.id, met.owner)) types.append(_type) - + + #completing .CODE and .DATA sections for c in program.classes: for f in c.features: if type(f)==DefFuncNode: - fun=func_to_cil_visitor(c.name, f) - code.append(fun[0]) - data.append(fun[1]) + if f.id=='main' and c.name=='Main': + code.insert(0, func_to_cil_visitor(c.name, f)) + else: + fun=func_to_cil_visitor(c.name, f) + code.append(fun[0]) + data.append(fun[1]) + return cil.ProgramNode(types, data, code) - - + def func_to_cil_visitor(type_name, func): name=f'{type_name}_{func.id}' params=[cil.ParamNode(id) for (id, t) in func.params] @@ -49,6 +53,22 @@ def func_to_cil_visitor(type_name, func): body=[] data=[] locals_count=0 + + if type_name=='Main' and func.id=='main': + instance='__main__' + locals.append(cil.LocalNode(instance)) + body.append(cil.AllocateNode('Main', instance)) + + init_attr=TypesByName['Main'].get_all_attributes() + for attr in init_attr: + if attr.expression: + attr_cil=expression_to_cil_visitor(attr.expression, locals_count) + locals_count+=len(attr_cil.locals) + locals.append(attr_cil.locals) + body.append(attr_cil.body) + data.append(attr_cil.data) + body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) + for exp in func.expressions: instruction=expression_to_cil_visitor(exp, locals_count) locals+=instruction.locals @@ -165,6 +185,7 @@ def new_to_cil_visitor(new_node, locals_count): body=[cil.AllocateNode(new_node.type, value)] data=[] init_attr=TypesByName[new_node.type].get_all_attributes() + for attr in init_attr: if attr.expression: attr_cil=expression_to_cil_visitor(attr.expression, locals_count) From 9c64517a93e5c7af9b518f1a22f8d65e070b658a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 14:15:21 -0400 Subject: [PATCH 136/435] Fixing error --- src/code_generation/cil.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 1e0e29e4..d2bf88ba 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -36,7 +36,9 @@ def program_to_cil_visitor(program): for f in c.features: if type(f)==DefFuncNode: if f.id=='main' and c.name=='Main': - code.insert(0, func_to_cil_visitor(c.name, f)) + fun=func_to_cil_visitor(c.name, f) + code.insert(0, fun[0]) + data.append(fun[1]) else: fun=func_to_cil_visitor(c.name, f) code.append(fun[0]) From 13cffe07558901f8d4199bcfe9316acce103b979 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 14:44:15 -0400 Subject: [PATCH 137/435] treat methods from types as a dictionary --- src/code_generation/ast.py | 2 +- src/code_generation/cil.py | 13 ++++++------- src/code_generation/code.py | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index ec1e5c9a..84dc5f48 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -10,7 +10,7 @@ def __init__(self, types, data, code): class TypeNode(Node): def __init__(self, type): self.attributes=[] - self.methods=[] + self.methods={} self.type=type class DataNode(Node): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index d2bf88ba..c0bd5f7d 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -19,15 +19,14 @@ def program_to_cil_visitor(program): _type=cil.TypeNode(t) value=TypesByName[t] for attr in value.get_all_attributes(): - _type.attributes.append(attr.id) - - for met in value.get_all_self_methods(): - _type.methods.append((met.id, t)) - + _type.attributes.append(attr.id) for met in value.get_all_inherited_methods(): - _type.methods.append((met.id, met.owner)) + _type.methods[met.id]=met.owner + for met in value.get_all_self_methods(): + _type.methods[met.id]=t + types.append(_type) @@ -256,7 +255,7 @@ def block_to_cil_visitor(block, locals_count): value=expr_cil.value return CIL_block(locals, body, value, data) - + class CIL_block: def __init__(self, locals, body, value, data=[]): self.locals=locals diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 1ea8a69f..c2fae089 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -25,8 +25,8 @@ def type_cg_visitor(type: TypeNode): for attr in type.attributes: attr_code+=f'attribute {attr}; \n' - for name, owner in type.methods: - method_code+=f'method {name}:{owner}_{name};\n' + for name in type.methods: + method_code+=f'method {name}:{type.methods[name]}_{name};\n' return f'type {type.name} {{ \n {attr_code} {method_code} }}' From a9c5041c6e500b33c341aa696e52098ca71b4ad1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 14:51:57 -0400 Subject: [PATCH 138/435] Adding type function call visitor --- src/code_generation/cil.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index c0bd5f7d..57ef90d8 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -255,6 +255,42 @@ def block_to_cil_visitor(block, locals_count): value=expr_cil.value return CIL_block(locals, body, value, data) + +def type_func_call_to_cil_visitor(call, locals_count): + locals=[] + body=[] + data=[] + obj_cil=expression_to_cil_visitor(call.object, locals_count) + locals_count+=len(obj_cil.locals) + locals+=obj_cil.locals + body+=obj_cil.body + data+=obj_cil.data + + arg_values=[] + + for arg in call.args: + arg_cil=expression_to_cil_visitor(arg, locals_count) + locals_count+=len(arg_cil.locals) + locals+=arg_cil.locals + body+=arg_cil.body + data+=arg_cil.data + arg_values.append(arg_cil.value) + + body.append(cil.ArgNode(obj_cil.value)) + + for arg in arg_values: + body.append(cil.ArgNode(arg)) + + result=f'local_{locals_count}' + locals.append(cil.LocalNode(result)) + body.append(cil.VCAllNode(type, call.id, result)) + + return CIL_block(locals, body, result, data) + + + + + class CIL_block: def __init__(self, locals, body, value, data=[]): From 9ef48d603c23683f0a4673f2e7434345d2d7c52e Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 16:12:08 -0400 Subject: [PATCH 139/435] adding self param to functions --- src/code_generation/cil.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 57ef90d8..e1c1f291 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -49,7 +49,8 @@ def program_to_cil_visitor(program): def func_to_cil_visitor(type_name, func): name=f'{type_name}_{func.id}' - params=[cil.ParamNode(id) for (id, t) in func.params] + params=[cil.ParamNode('self')] + params+=[cil.ParamNode(id) for (id, t) in func.params] locals=[] body=[] data=[] @@ -287,7 +288,8 @@ def type_func_call_to_cil_visitor(call, locals_count): return CIL_block(locals, body, result, data) - +def func_call_to_cil_visitor(call, locals_count): + pass From 6e48846710d632f64d8e4ddd5cfee20c244fe70c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 3 May 2020 21:34:36 -0400 Subject: [PATCH 140/435] Add returned_type property and call to super class --- src/lexer_parser/ast.py | 31 +++++++++++++++++++++++- src/semantic/semantic.py | 52 ++++++++++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 143874f2..2b6aacc3 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -10,11 +10,13 @@ def add_location(self, line, column): class ProgramNode(AstNode): def __init__(self, classes: list): + super().__init__() self.classes = classes class DefClassNode(AstNode): def __init__(self, type, features, parent_type=None): + super().__init__() self.type = type self.feature_nodes = features self.parent_type = parent_type @@ -22,6 +24,7 @@ def __init__(self, type, features, parent_type=None): class FeatureNode(AstNode): def __init__(self, id): + super().__init__() self.id = id @@ -45,50 +48,64 @@ def __init__(self, id, params, return_type, expressions): class AssignNode(AstNode): def __init__(self, id, expr): + super().__init__() self.id = id self.expr = expr + self.returned_type = None class FuncCallNode(AstNode): def __init__(self, id, args, object=None, type=None): + super().__init__() self.object = object self.type = type self.id = id self.args = args + self.returned_type = None class IfNode(AstNode): def __init__(self, if_expr, then_expr, else_expr): + super().__init__() self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr + self.returned_type = None class WhileNode(AstNode): def __init__(self, cond, body): + super().__init__() self.cond = cond self.body = body + self.returned_type = None class BlockNode(AstNode): def __init__(self, expressions): + super().__init__() self.expressions = expressions class LetNode(AstNode): def __init__(self, let_attrs, expr): + super().__init__() self.let_attrs = let_attrs self.expr = expr + self.returned_type = None class CaseNode(AstNode): def __init__(self, expr, case_list): + super().__init__() self.expr = expr self.case_list = case_list + self.returned_type = None class CaseElemNode(AstNode): def __init__(self, expr, id, type): + super().__init__() self.expr = expr self.id = id self.type = type @@ -96,15 +113,19 @@ def __init__(self, expr, id, type): class InitNode(AstNode): def __init__(self, type): + super().__init__() self.type = type class ExpressionNode(AstNode): - pass + def __init__(self): + super().__init__() + self.returned_type = None class BinaryNode(ExpressionNode): def __init__(self, lvalue, rvalue): + super().__init__() self.lvalue = lvalue self.rvalue = rvalue @@ -139,7 +160,9 @@ class EqNode(BinaryNode): class UnaryNode(ExpressionNode): def __init__(self, val): + super().__init__() self.val = val + self.returned_type = None class NegationNode(UnaryNode): @@ -160,17 +183,23 @@ class IsVoidNode(UnaryNode): class VarNode(AstNode): def __init__(self, id): + super().__init__() self.id = id + self.returned_type = None class NewNode(AstNode): def __init__(self, t): + super().__init__() self.type = t + self.returned_type = None class ConstantNode(AstNode): def __init__(self, value): + super().__init__() self.value = value + self.returned_type = None class IntNode(ConstantNode): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index a6508b25..9d52e72d 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -74,26 +74,30 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope add_semantic_error(function.lineno, function.colno, f'invalid returned type \'{function.return_type}\'') -def int_visitor(expr, current_class, local_scope): +def int_visitor(expr: IntNode, current_class, local_scope): + expr.returned_type = IntType return IntType -def string_visitor(expr, current_class, local_scope): +def string_visitor(expr: StringNode, current_class, local_scope): + expr.returned_type = StringType return StringType -def bool_visitor(expr, current_class, local_scope): +def bool_visitor(expr: BoolNode, current_class, local_scope): + expr.returned_type = BoolType return BoolType def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if var.id in local_scope.keys(): - return local_scope[var.id] + var.returned_type = local_scope[var.id] attribute, _ = get_attribute(current_class, var.id) if attribute is not None: - return attribute.attrType + var.returned_type = attribute.attrType else: add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') + return var.returned_type def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): @@ -105,6 +109,7 @@ def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, l if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, f'invalid left value type {rvalue_type}, must be a {IntType}') + operator.returned_type = IntType return IntType @@ -114,6 +119,7 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): static_types = [IntType, BoolType, StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') + equal.returned_type = BoolType return BoolType @@ -124,6 +130,7 @@ def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: di rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') + cmp.returned_type = BoolType return BoolType @@ -141,6 +148,7 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(assign.expr.lineno, assign.expr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + assign.returned_type = expr_type return expr_type @@ -159,15 +167,27 @@ def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): local_scope = local_scope.copy() for attribute in let.let_attrs: + id_type = type_by_name(attribute.type) + if id_type is None: + add_semantic_error(attribute.lineno, attribute.colno, f'unknown type \'{attribute.type}\'') + return None attribute_type = expression_visitor(attribute, current_class, local_scope) + if attribute_type is None: + return None + if not check_inherits(attribute_type, id_type): + add_semantic_error(attribute.lineno, attribute.colno, + f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') + return None local_scope[attribute.id] = ObjectType - return expression_visitor(let.expr, current_class, local_scope) + let.returned_type = expression_visitor(let.expr, current_class, local_scope) + return let.returned_type def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: dict): final_type = None for expr in expressions: final_type = expression_visitor(expr, current_class, local_scope) + expressions.returned_type = final_type return final_type @@ -177,7 +197,8 @@ def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) - return pronounced_join(then_type, else_type) + if_struct.returned_type = pronounced_join(then_type, else_type) + return if_struct.returned_type def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_scope: dict): @@ -208,9 +229,10 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if method is None: add_semantic_error(func_call.lineno, func_call.colno, msg) elif method.returnedType == SelfType: - return current_class + func_call.returned_type = current_class else: - return method.returnedType + func_call.returned_type = method.returnedType + return func_call.returned_type def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): @@ -225,12 +247,13 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict temp = local_scope.copy() temp[branch.id] = expr_0 current_type = pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) - - return current_type + case.returned_type = current_type + return case.returned_type def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): expression_visitor(isvoid.val, current_class, local_scope) + isvoid.returned_type = BoolType return BoolType @@ -239,6 +262,7 @@ def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dic if predicate_type != BoolType and predicate_type is not None: add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') expression_visitor(loop.body, current_class, local_scope) + loop.returned_type = ObjectType return ObjectType @@ -247,8 +271,10 @@ def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): if not t: add_semantic_error(new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') if t == SelfType: - return current_class - return t + new.returned_type = current_class + else: + new.returned_type = t + return new.returned_type __visitors__ = { From a01f6c3e9b64664a8e4e3699abea4a75cc4fbb39 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 22:19:45 -0400 Subject: [PATCH 141/435] adding self function call to cil visitor --- src/code_generation/cil.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index e1c1f291..17d07888 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -284,15 +284,36 @@ def type_func_call_to_cil_visitor(call, locals_count): result=f'local_{locals_count}' locals.append(cil.LocalNode(result)) - body.append(cil.VCAllNode(type, call.id, result)) + body.append(cil.VCAllNode(call.type, call.id, result)) return CIL_block(locals, body, result, data) def func_call_to_cil_visitor(call, locals_count): - pass + pass + +def self_func_call_to_cil_visitor(call, locals_count): + locals=[] + body=[] + data=[] + for arg in call.args: + arg_cil=expression_to_cil_visitor(arg, locals_count) + locals_count+=len(arg_cil.locals) + locals+=arg_cil.locals + body+=arg_cil.body + data+=arg_cil.data + arg_values.append(arg_cil.value) + + body.append(cil.ArgNode('self')) + + for arg in arg_values: + body.append(cil.ArgNode(arg)) + result=f'local_{locals_count}' + locals.append(cil.LocalNode(result)) + body.append(cil.VCAllNode(type, call.id, result)) + return CIL_block(locals, body, result, data) class CIL_block: def __init__(self, locals, body, value, data=[]): @@ -318,7 +339,7 @@ def __init__(self, locals, body, value, data=[]): lp_ast.MinusNode:arith_to_cil_visitor, lp_ast.StarNode:arith_to_cil_visitor, lp_ast.DivNode:arith_to_cil_visitor, - lp_ast.VarNode:id_to_cil_visitor + lp_ast.VarNode:id_to_cil_visitor } From d3e73d09de75c59b21943a7fd1f0ab19ee4ee2f9 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 22:21:57 -0400 Subject: [PATCH 142/435] adding generic func call to cil function --- src/code_generation/cil.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 17d07888..b2cdfd78 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -288,7 +288,7 @@ def type_func_call_to_cil_visitor(call, locals_count): return CIL_block(locals, body, result, data) -def func_call_to_cil_visitor(call, locals_count): +def standard_func_call_to_cil_visitor(call, locals_count): pass def self_func_call_to_cil_visitor(call, locals_count): @@ -322,6 +322,13 @@ def __init__(self, locals, body, value, data=[]): self.value=value self.data=data +def func_call_to_cil_visitor(call, locals_count): + if not object: + return self_func_call_to_cil_visitor(call, locals_count) + if not type: + return standard_func_call_to_cil_visitor(call, locals_count) + return type_func_call_to_cil_visitor(call, locals_count) + __visitor__={ lp_ast.AssignNode:assign_to_cil_visitor, @@ -339,7 +346,8 @@ def __init__(self, locals, body, value, data=[]): lp_ast.MinusNode:arith_to_cil_visitor, lp_ast.StarNode:arith_to_cil_visitor, lp_ast.DivNode:arith_to_cil_visitor, - lp_ast.VarNode:id_to_cil_visitor + lp_ast.VarNode:id_to_cil_visitor, + lp_ast.FuncCallNode: func_call_to_cil_visitor } From 672162629f81a51a9086b36691cfca84bc7a1bf1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 22:29:28 -0400 Subject: [PATCH 143/435] Eliminating unnecessary spaces in import --- src/code_generation/cil.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index b2cdfd78..68d548cf 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,6 +1,4 @@ import lexer_parser.ast as lp_ast - - from semantic.types import * import code_generation.ast as cil From c0c762f05e02b9973df86f4ef822f0dcb2947844 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 22:30:47 -0400 Subject: [PATCH 144/435] fix error --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 68d548cf..948eb782 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -173,7 +173,7 @@ def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) def bool_to_cil_visitor(bool, locals_count): - return CIL_block([], [], 1) if bool=='true' else CIL_block([], [], 0) + return CIL_block([], [], 1) if bool.value=='true' else CIL_block([], [], 0) def id_to_cil_visitor(id, locals_count): return CIL_block([], [], id.id) From 39e81300eedc80dc85704877c367f7a9368296ca Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 3 May 2020 22:33:22 -0400 Subject: [PATCH 145/435] remove self func call to cil function because of mistake --- src/code_generation/cil.py | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 948eb782..8a85603e 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -290,28 +290,7 @@ def standard_func_call_to_cil_visitor(call, locals_count): pass def self_func_call_to_cil_visitor(call, locals_count): - locals=[] - body=[] - data=[] - - for arg in call.args: - arg_cil=expression_to_cil_visitor(arg, locals_count) - locals_count+=len(arg_cil.locals) - locals+=arg_cil.locals - body+=arg_cil.body - data+=arg_cil.data - arg_values.append(arg_cil.value) - - body.append(cil.ArgNode('self')) - - for arg in arg_values: - body.append(cil.ArgNode(arg)) - - result=f'local_{locals_count}' - locals.append(cil.LocalNode(result)) - body.append(cil.VCAllNode(type, call.id, result)) - - return CIL_block(locals, body, result, data) + pass class CIL_block: def __init__(self, locals, body, value, data=[]): From 8f4c7e566facf8bb43e3ef60f0259dcada3de88f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 4 May 2020 13:49:38 -0400 Subject: [PATCH 146/435] fixing mistake --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index cb454724..ef2867a2 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -67,7 +67,7 @@ def func_to_cil_visitor(type_name, func): locals.append(attr_cil.locals) body.append(attr_cil.body) data.append(attr_cil.data) - body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) + body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) for exp in func.expressions: instruction=expression_to_cil_visitor(exp, locals_count) From 0e4f71cbea614c996e89cd9683569897bab3344a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 14:20:53 -0400 Subject: [PATCH 147/435] Change list for BlockNode --- src/lexer_parser/ast.py | 1 + src/lexer_parser/parser.py | 4 ++-- src/semantic/semantic.py | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 2b6aacc3..48334425 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -85,6 +85,7 @@ class BlockNode(AstNode): def __init__(self, expressions): super().__init__() self.expressions = expressions + self.returned_type = None class LetNode(AstNode): diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 96bba64e..bb9f7570 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -280,9 +280,9 @@ def p_block_list(p): '''block_list : expr SEMICOLON block_list | expr SEMICOLON''' if len(p) == 4: - p[0] = [p[1]] + p[3] + p[0] = BlockNode([p[1]] + p[3].expressions) else: - p[0] = [p[1]] + p[0] = BlockNode([p[1]]) def p_error(p): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 9d52e72d..d5bc0035 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -183,11 +183,11 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): return let.returned_type -def list_expr_visitor(expressions: list, current_class: CoolType, local_scope: dict): +def list_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): final_type = None - for expr in expressions: + for expr in block.expressions: final_type = expression_visitor(expr, current_class, local_scope) - expressions.returned_type = final_type + block.returned_type = final_type return final_type @@ -278,7 +278,7 @@ def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): __visitors__ = { - list: list_expr_visitor, + BlockNode: list_expr_visitor, IntNode: int_visitor, StringNode: string_visitor, BoolNode: bool_visitor, From 2f928358ecfb8cd911db9e23d56e80e51e2eb436 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 14:29:49 -0400 Subject: [PATCH 148/435] Clean lexer_parser AST --- src/lexer_parser/ast.py | 49 ++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 48334425..2c47c92f 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -46,62 +46,61 @@ def __init__(self, id, params, return_type, expressions): self.expressions = expressions -class AssignNode(AstNode): +class ExpressionNode(AstNode): + def __init__(self): + super().__init__() + self.returned_type = None + + +class AssignNode(ExpressionNode): def __init__(self, id, expr): super().__init__() self.id = id self.expr = expr - self.returned_type = None -class FuncCallNode(AstNode): +class FuncCallNode(ExpressionNode): def __init__(self, id, args, object=None, type=None): super().__init__() self.object = object self.type = type self.id = id self.args = args - self.returned_type = None -class IfNode(AstNode): +class IfNode(ExpressionNode): def __init__(self, if_expr, then_expr, else_expr): super().__init__() self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr - self.returned_type = None -class WhileNode(AstNode): +class WhileNode(ExpressionNode): def __init__(self, cond, body): super().__init__() self.cond = cond self.body = body - self.returned_type = None -class BlockNode(AstNode): +class BlockNode(ExpressionNode): def __init__(self, expressions): super().__init__() self.expressions = expressions - self.returned_type = None -class LetNode(AstNode): +class LetNode(ExpressionNode): def __init__(self, let_attrs, expr): super().__init__() self.let_attrs = let_attrs self.expr = expr - self.returned_type = None -class CaseNode(AstNode): +class CaseNode(ExpressionNode): def __init__(self, expr, case_list): super().__init__() self.expr = expr self.case_list = case_list - self.returned_type = None class CaseElemNode(AstNode): @@ -112,18 +111,6 @@ def __init__(self, expr, id, type): self.type = type -class InitNode(AstNode): - def __init__(self, type): - super().__init__() - self.type = type - - -class ExpressionNode(AstNode): - def __init__(self): - super().__init__() - self.returned_type = None - - class BinaryNode(ExpressionNode): def __init__(self, lvalue, rvalue): super().__init__() @@ -163,7 +150,6 @@ class UnaryNode(ExpressionNode): def __init__(self, val): super().__init__() self.val = val - self.returned_type = None class NegationNode(UnaryNode): @@ -182,25 +168,22 @@ class IsVoidNode(UnaryNode): pass -class VarNode(AstNode): +class VarNode(ExpressionNode): def __init__(self, id): super().__init__() self.id = id - self.returned_type = None -class NewNode(AstNode): +class NewNode(ExpressionNode): def __init__(self, t): super().__init__() self.type = t - self.returned_type = None -class ConstantNode(AstNode): +class ConstantNode(ExpressionNode): def __init__(self, value): super().__init__() self.value = value - self.returned_type = None class IntNode(ConstantNode): From cbb98bae3c2c032f42bd3d9903260a7bb9cbd1c0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 14:33:02 -0400 Subject: [PATCH 149/435] Rename list_expr_visitor to block_expr_visitor --- src/semantic/semantic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index d5bc0035..4ae294bf 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -183,7 +183,7 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): return let.returned_type -def list_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): +def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): final_type = None for expr in block.expressions: final_type = expression_visitor(expr, current_class, local_scope) @@ -278,7 +278,7 @@ def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): __visitors__ = { - BlockNode: list_expr_visitor, + BlockNode: block_expr_visitor, IntNode: int_visitor, StringNode: string_visitor, BoolNode: bool_visitor, From b7c3de021cae56805f56f3fa40832d5507a6f600 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 14:45:57 -0400 Subject: [PATCH 150/435] Reorganize AST --- src/semantic/semantic.py | 232 +++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 116 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 4ae294bf..4cecb7fe 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -60,6 +60,18 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco return attr_type +def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): + id_type = type_by_name(def_attr.type) + if id_type is None: + add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') + if def_attr.expr: + expr_type = expression_visitor(def_attr.expr, current_class, local_scope) + if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: + add_semantic_error(def_attr.lineno, def_attr.colno, + f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + return id_type + + def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope: dict): local_scope = local_scope.copy() for arg in function.params: @@ -74,66 +86,6 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope add_semantic_error(function.lineno, function.colno, f'invalid returned type \'{function.return_type}\'') -def int_visitor(expr: IntNode, current_class, local_scope): - expr.returned_type = IntType - return IntType - - -def string_visitor(expr: StringNode, current_class, local_scope): - expr.returned_type = StringType - return StringType - - -def bool_visitor(expr: BoolNode, current_class, local_scope): - expr.returned_type = BoolType - return BoolType - - -def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): - if var.id in local_scope.keys(): - var.returned_type = local_scope[var.id] - attribute, _ = get_attribute(current_class, var.id) - if attribute is not None: - var.returned_type = attribute.attrType - else: - add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') - return var.returned_type - - -def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): - lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) - if lvalue_type != IntType and lvalue_type is not None: - add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, - f'invalid left value type {lvalue_type}, must be a {IntType}') - rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) - if rvalue_type != IntType and rvalue_type is not None: - add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, - f'invalid left value type {rvalue_type}, must be a {IntType}') - operator.returned_type = IntType - return IntType - - -def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): - lvalue_type = expression_visitor(equal.lvalue, current_class, local_scope) - rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) - static_types = [IntType, BoolType, StringType] - if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: - add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') - equal.returned_type = BoolType - return BoolType - - -def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): - lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) - if lvalue_type != IntType and lvalue_type is not None: - add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, f'lvalue type must be a {IntType}') - rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) - if rvalue_type != IntType and rvalue_type is not None: - add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') - cmp.returned_type = BoolType - return BoolType - - def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: dict): try: id_type = local_scope[assign.id] @@ -152,55 +104,6 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: return expr_type -def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): - id_type = type_by_name(def_attr.type) - if id_type is None: - add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') - if def_attr.expr: - expr_type = expression_visitor(def_attr.expr, current_class, local_scope) - if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: - add_semantic_error(def_attr.lineno, def_attr.colno, - f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') - return id_type - - -def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): - local_scope = local_scope.copy() - for attribute in let.let_attrs: - id_type = type_by_name(attribute.type) - if id_type is None: - add_semantic_error(attribute.lineno, attribute.colno, f'unknown type \'{attribute.type}\'') - return None - attribute_type = expression_visitor(attribute, current_class, local_scope) - if attribute_type is None: - return None - if not check_inherits(attribute_type, id_type): - add_semantic_error(attribute.lineno, attribute.colno, - f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') - return None - local_scope[attribute.id] = ObjectType - let.returned_type = expression_visitor(let.expr, current_class, local_scope) - return let.returned_type - - -def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): - final_type = None - for expr in block.expressions: - final_type = expression_visitor(expr, current_class, local_scope) - block.returned_type = final_type - return final_type - - -def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): - predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) - if predicate_type != BoolType: - add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') - then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) - else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) - if_struct.returned_type = pronounced_join(then_type, else_type) - return if_struct.returned_type - - def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_scope: dict): args_types = [] method = None @@ -235,6 +138,52 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return func_call.returned_type +def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): + predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) + if predicate_type != BoolType: + add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') + then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) + else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) + if_struct.returned_type = pronounced_join(then_type, else_type) + return if_struct.returned_type + + +def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): + predicate_type = expression_visitor(loop.cond, current_class, local_scope) + if predicate_type != BoolType and predicate_type is not None: + add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') + expression_visitor(loop.body, current_class, local_scope) + loop.returned_type = ObjectType + return ObjectType + + +def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): + final_type = None + for expr in block.expressions: + final_type = expression_visitor(expr, current_class, local_scope) + block.returned_type = final_type + return final_type + + +def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): + local_scope = local_scope.copy() + for attribute in let.let_attrs: + id_type = type_by_name(attribute.type) + if id_type is None: + add_semantic_error(attribute.lineno, attribute.colno, f'unknown type \'{attribute.type}\'') + return None + attribute_type = expression_visitor(attribute, current_class, local_scope) + if attribute_type is None: + return None + if not check_inherits(attribute_type, id_type): + add_semantic_error(attribute.lineno, attribute.colno, + f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') + return None + local_scope[attribute.id] = ObjectType + let.returned_type = expression_visitor(let.expr, current_class, local_scope) + return let.returned_type + + def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): expr_0 = expression_visitor(case.expr, current_class, local_scope) @@ -251,19 +200,55 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict return case.returned_type +def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) + if lvalue_type != IntType and lvalue_type is not None: + add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, + f'invalid left value type {lvalue_type}, must be a {IntType}') + rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) + if rvalue_type != IntType and rvalue_type is not None: + add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, + f'invalid left value type {rvalue_type}, must be a {IntType}') + operator.returned_type = IntType + return IntType + + +def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) + if lvalue_type != IntType and lvalue_type is not None: + add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, f'lvalue type must be a {IntType}') + rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) + if rvalue_type != IntType and rvalue_type is not None: + add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') + cmp.returned_type = BoolType + return BoolType + + +def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): + lvalue_type = expression_visitor(equal.lvalue, current_class, local_scope) + rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) + static_types = [IntType, BoolType, StringType] + if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: + add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') + equal.returned_type = BoolType + return BoolType + + def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): expression_visitor(isvoid.val, current_class, local_scope) isvoid.returned_type = BoolType return BoolType -def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): - predicate_type = expression_visitor(loop.cond, current_class, local_scope) - if predicate_type != BoolType and predicate_type is not None: - add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') - expression_visitor(loop.body, current_class, local_scope) - loop.returned_type = ObjectType - return ObjectType +def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): + if var.id in local_scope.keys(): + var.returned_type = local_scope[var.id] + attribute, _ = get_attribute(current_class, var.id) + if attribute is not None: + var.returned_type = attribute.attrType + else: + add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') + return var.returned_type def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): @@ -277,6 +262,21 @@ def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): return new.returned_type +def int_visitor(expr: IntNode, current_class, local_scope): + expr.returned_type = IntType + return IntType + + +def bool_visitor(expr: BoolNode, current_class, local_scope): + expr.returned_type = BoolType + return BoolType + + +def string_visitor(expr: StringNode, current_class, local_scope): + expr.returned_type = StringType + return StringType + + __visitors__ = { BlockNode: block_expr_visitor, IntNode: int_visitor, From d3b7c259a04a27d62b1309471bc636717454941c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 14:59:16 -0400 Subject: [PATCH 151/435] Add negation_visitor --- src/semantic/semantic.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 4cecb7fe..d405283c 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -234,6 +234,14 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): return BoolType +def negation_visitor(negation: NegationNode, current_class: CoolType, local_scope: dict): + value_type = expression_visitor(negation.val, current_class, local_scope) + if value_type != IntNode and value_type is not None: + add_semantic_error(negation.lineno, negation.colno, + f'type {value_type} invalid. The \'~\' operator can only be used with type {IntType}') + return IntType + + def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): expression_visitor(isvoid.val, current_class, local_scope) isvoid.returned_type = BoolType @@ -288,6 +296,7 @@ def string_visitor(expr: StringNode, current_class, local_scope): StarNode: arithmetic_operator_visitor, DivNode: arithmetic_operator_visitor, EqNode: equal_visitor, + NegationNode: negation_visitor, LessThanNode: comparison_visitor, LessEqNode: comparison_visitor, AssignNode: assignment_visitor, From 5b894e323b0fe497ab1f45b6956966fe42303af8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 15:01:39 -0400 Subject: [PATCH 152/435] Add logic_negation_visitor --- src/semantic/semantic.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index d405283c..c258e048 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -242,6 +242,14 @@ def negation_visitor(negation: NegationNode, current_class: CoolType, local_scop return IntType +def logic_negation_visitor(negation: LogicNegationNode, current_class: CoolType, local_scope: dict): + value_type = expression_visitor(negation.val, current_class, local_scope) + if value_type != BoolType and value_type is not None: + add_semantic_error(negation.lineno, negation.colno, + f'type {value_type} invalid. The \'not\' operator can only be used with type {BoolType}') + return BoolType + + def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): expression_visitor(isvoid.val, current_class, local_scope) isvoid.returned_type = BoolType @@ -297,6 +305,7 @@ def string_visitor(expr: StringNode, current_class, local_scope): DivNode: arithmetic_operator_visitor, EqNode: equal_visitor, NegationNode: negation_visitor, + LogicNegationNode: logic_negation_visitor, LessThanNode: comparison_visitor, LessEqNode: comparison_visitor, AssignNode: assignment_visitor, From c941c4ca42f1b9499c18b7d34f462837fd34f1b4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 15:05:08 -0400 Subject: [PATCH 153/435] Reformat code --- src/code_generation/cil.py | 252 ++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 128 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ef2867a2..e6501f34 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -2,80 +2,80 @@ from semantic.types import * import code_generation.ast as cil + def ast_to_cil(ast): - if type(ast)==lp_ast.ProgramNode: - return program_to_cil_visitor(program) + if type(ast) == lp_ast.ProgramNode: + return program_to_cil_visitor(lp_ast.Proprogram) raise Exception(f'AST root must be program') + def program_to_cil_visitor(program): types = [] data = [] code = [] - #completing .TYPE section + # completing .TYPE section for t in TypesByName: - _type=cil.TypeNode(t) - value=TypesByName[t] + _type = cil.TypeNode(t) + value = TypesByName[t] for attr in value.get_all_attributes(): - _type.attributes.append(attr.id) - + _type.attributes.append(attr.id) + for met in value.get_all_inherited_methods(): - _type.methods[met.id]=met.owner - + _type.methods[met.id] = met.owner + for met in value.get_all_self_methods(): - _type.methods[met.id]=t - - types.append(_type) + _type.methods[met.id] = t + types.append(_type) - #completing .CODE and .DATA sections + # completing .CODE and .DATA sections for c in program.classes: for f in c.features: - if type(f)==DefFuncNode: - if f.id=='main' and c.name=='Main': - fun=func_to_cil_visitor(c.name, f) + if type(f) == DefFuncNode: + if f.id == 'main' and c.name == 'Main': + fun = func_to_cil_visitor(c.name, f) code.insert(0, fun[0]) data.append(fun[1]) else: - fun=func_to_cil_visitor(c.name, f) + fun = func_to_cil_visitor(c.name, f) code.append(fun[0]) data.append(fun[1]) - - - + return cil.ProgramNode(types, data, code) - -def func_to_cil_visitor(type_name, func): - name=f'{type_name}_{func.id}' - params=[cil.ParamNode('self')] - params+=[cil.ParamNode(id) for (id, t) in func.params] - locals=[] - body=[] - data=[] - locals_count=0 - - if type_name=='Main' and func.id=='main': - instance='__main__' + + +def func_to_cil_visitor(type_name, func): + name = f'{type_name}_{func.id}' + params = [cil.ParamNode('self')] + params += [cil.ParamNode(id) for (id, t) in func.params] + locals = [] + body = [] + data = [] + locals_count = 0 + + if type_name == 'Main' and func.id == 'main': + instance = '__main__' locals.append(cil.LocalNode(instance)) body.append(cil.AllocateNode('Main', instance)) - - init_attr=TypesByName['Main'].get_all_attributes() + + init_attr = TypesByName['Main'].get_all_attributes() for attr in init_attr: if attr.expression: - attr_cil=expression_to_cil_visitor(attr.expression, locals_count) - locals_count+=len(attr_cil.locals) + attr_cil = expression_to_cil_visitor(attr.expression, locals_count) + locals_count += len(attr_cil.locals) locals.append(attr_cil.locals) body.append(attr_cil.body) - data.append(attr_cil.data) + data.append(attr_cil.data) body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) - + for exp in func.expressions: - instruction=expression_to_cil_visitor(exp, locals_count) - locals+=instruction.locals - body+=instruction.body - data+=instruction.data - locals_count+=len(instruction.locals) - + instruction = expression_to_cil_visitor(exp, locals_count) + locals += instruction.locals + body += instruction.body + data += instruction.data + locals_count += len(instruction.locals) + return cil.FuncNode(name, params, locals, body), data @@ -180,42 +180,44 @@ def equal_to_cil_visitor(equal, locals_count): return CIL_block(locals, body, value, data) + def lessthan_to_cil_visitor(lessthan, locals_count): - l=expression_to_cil_visitor(lessthan.lvalue, locals_count) - r=expression_to_cil_visitor(lessthan.rvalue, locals_count) + l = expression_to_cil_visitor(lessthan.lvalue, locals_count) + r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(l.locals) + len(r.locals) - + cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' value = f'local_{locals_count + 2}' - + locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), - cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] data = l.data + r.data - + return CIL_block(locals, body, value, data) + def lesseqthan_to_cil_visitor(lessthan, locals_count): - l=expression_to_cil_visitor(lessthan.lvalue, locals_count) - r=expression_to_cil_visitor(lessthan.rvalue, locals_count) + l = expression_to_cil_visitor(lessthan.lvalue, locals_count) + r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(l.locals) + len(r.locals) - + cil_less = f'local_{locals_count}' cil_equal = f'local_{locals_count + 1}' eq_label = f'local_{locals_count + 2}' end_label = f'local_{locals_count + 3}' value = f'local_{locals_count + 4}' - + locals = l.locals + r.locals + [cil.LocalNode(cil_less), cil.LocalNode(cil_equal), cil.LocalNode(value)] - body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), - cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), - cil.GotoNode(end_label), cil.LabelNode(eq_label), - cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), + body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), + cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), + cil.GotoNode(end_label), cil.LabelNode(eq_label), + cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] data = l.data + r.data - + return CIL_block(locals, body, value, data) @@ -224,20 +226,21 @@ def integer_to_cil_visitor(integer, locals_count): def bool_to_cil_visitor(bool, locals_count): - return CIL_block([], [], 1) if bool.value=='true' else CIL_block([], [], 0) + return CIL_block([], [], 1) if bool.value == 'true' else CIL_block([], [], 0) + def id_to_cil_visitor(id, locals_count): return CIL_block([], [], id.id) def new_to_cil_visitor(new_node, locals_count): - value=f'local_{locals_count}' - locals=[cil.LocalNode(value)] - locals_count+=1 - body=[cil.AllocateNode(new_node.type, value)] - data=[] - init_attr=TypesByName[new_node.type].get_all_attributes() - + value = f'local_{locals_count}' + locals = [cil.LocalNode(value)] + locals_count += 1 + body = [cil.AllocateNode(new_node.type, value)] + data = [] + init_attr = TypesByName[new_node.type].get_all_attributes() + for attr in init_attr: if attr.expression: attr_cil = expression_to_cil_visitor(attr.expression, locals_count) @@ -311,50 +314,55 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) + def type_func_call_to_cil_visitor(call, locals_count): - locals=[] - body=[] - data=[] - obj_cil=expression_to_cil_visitor(call.object, locals_count) - locals_count+=len(obj_cil.locals) - locals+=obj_cil.locals - body+=obj_cil.body - data+=obj_cil.data - - arg_values=[] - + locals = [] + body = [] + data = [] + obj_cil = expression_to_cil_visitor(call.object, locals_count) + locals_count += len(obj_cil.locals) + locals += obj_cil.locals + body += obj_cil.body + data += obj_cil.data + + arg_values = [] + for arg in call.args: - arg_cil=expression_to_cil_visitor(arg, locals_count) - locals_count+=len(arg_cil.locals) - locals+=arg_cil.locals - body+=arg_cil.body - data+=arg_cil.data + arg_cil = expression_to_cil_visitor(arg, locals_count) + locals_count += len(arg_cil.locals) + locals += arg_cil.locals + body += arg_cil.body + data += arg_cil.data arg_values.append(arg_cil.value) - + body.append(cil.ArgNode(obj_cil.value)) - + for arg in arg_values: body.append(cil.ArgNode(arg)) - - result=f'local_{locals_count}' + + result = f'local_{locals_count}' locals.append(cil.LocalNode(result)) body.append(cil.VCAllNode(call.type, call.id, result)) - + return CIL_block(locals, body, result, data) - + + def standard_func_call_to_cil_visitor(call, locals_count): - pass + pass + def self_func_call_to_cil_visitor(call, locals_count): pass - + + class CIL_block: def __init__(self, locals, body, value, data=[]): - self.locals=locals - self.body=body - self.value=value - self.data=data - + self.locals = locals + self.body = body + self.value = value + self.data = data + + def func_call_to_cil_visitor(call, locals_count): if not object: return self_func_call_to_cil_visitor(call, locals_count) @@ -362,38 +370,27 @@ def func_call_to_cil_visitor(call, locals_count): return standard_func_call_to_cil_visitor(call, locals_count) return type_func_call_to_cil_visitor(call, locals_count) - -__visitor__={ - lp_ast.AssignNode:assign_to_cil_visitor, - lp_ast.BlockNode:block_to_cil_visitor, - lp_ast.BoolNode:bool_to_cil_visitor, - lp_ast.IfNode:if_to_cil_visitor, - lp_ast.WhileNode:loop_to_cil_visitor, - lp_ast.EqNode:equal_to_cil_visitor, - lp_ast.LogicNegationNode:logic_not_to_cil_visitor, - lp_ast.LetNode:let_to_cil_visitor, - lp_ast.NewNode:new_to_cil_visitor, - lp_ast.IntNode:integer_to_cil_visitor, - lp_ast.StringNode:string_to_cil_visitor, - lp_ast.PlusNode:arith_to_cil_visitor, - lp_ast.MinusNode:arith_to_cil_visitor, - lp_ast.StarNode:arith_to_cil_visitor, - lp_ast.DivNode:arith_to_cil_visitor, - lp_ast.VarNode:id_to_cil_visitor, + +__visitor__ = { + lp_ast.AssignNode: assign_to_cil_visitor, + lp_ast.BlockNode: block_to_cil_visitor, + lp_ast.BoolNode: bool_to_cil_visitor, + lp_ast.IfNode: if_to_cil_visitor, + lp_ast.WhileNode: loop_to_cil_visitor, + lp_ast.EqNode: equal_to_cil_visitor, + lp_ast.LogicNegationNode: logic_not_to_cil_visitor, + lp_ast.LetNode: let_to_cil_visitor, + lp_ast.NewNode: new_to_cil_visitor, + lp_ast.IntNode: integer_to_cil_visitor, + lp_ast.StringNode: string_to_cil_visitor, + lp_ast.PlusNode: arith_to_cil_visitor, + lp_ast.MinusNode: arith_to_cil_visitor, + lp_ast.StarNode: arith_to_cil_visitor, + lp_ast.DivNode: arith_to_cil_visitor, + lp_ast.VarNode: id_to_cil_visitor, lp_ast.FuncCallNode: func_call_to_cil_visitor -} - - - - - - - - - - - - +} + class CIL_block: def __init__(self, locals, body, value, data=[]): @@ -401,4 +398,3 @@ def __init__(self, locals, body, value, data=[]): self.body = body self.value = value self.data = data - From 42e88dda92ccd4bc40332a6fa9d690322af5b229 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 15:05:44 -0400 Subject: [PATCH 154/435] Fix bug --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index e6501f34..5479e32c 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -5,7 +5,7 @@ def ast_to_cil(ast): if type(ast) == lp_ast.ProgramNode: - return program_to_cil_visitor(lp_ast.Proprogram) + return program_to_cil_visitor(ast) raise Exception(f'AST root must be program') From f40722d29cc1dfd266a891f83952d59bc1a2c6cd Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 4 May 2020 15:51:39 -0400 Subject: [PATCH 155/435] merge type and standard func call visitors into one --- src/code_generation/cil.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 5479e32c..917051b9 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -314,8 +314,7 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) - -def type_func_call_to_cil_visitor(call, locals_count): +def standard_func_call_to_cil_visitor(call, locals_count): locals = [] body = [] data = [] @@ -342,15 +341,13 @@ def type_func_call_to_cil_visitor(call, locals_count): result = f'local_{locals_count}' locals.append(cil.LocalNode(result)) - body.append(cil.VCAllNode(call.type, call.id, result)) + if not call.type: + body.append(cil.VCAllNode(call.object.returned_type, call.id, result)) + else: + body.append(cil.VCAllNode(call.type, call.id, result)) return CIL_block(locals, body, result, data) - -def standard_func_call_to_cil_visitor(call, locals_count): - pass - - def self_func_call_to_cil_visitor(call, locals_count): pass @@ -366,9 +363,7 @@ def __init__(self, locals, body, value, data=[]): def func_call_to_cil_visitor(call, locals_count): if not object: return self_func_call_to_cil_visitor(call, locals_count) - if not type: - return standard_func_call_to_cil_visitor(call, locals_count) - return type_func_call_to_cil_visitor(call, locals_count) + return standard_func_call_to_cil_visitor(call, locals_count) __visitor__ = { From b047594dfe3d80d771461c6f33b18acf2ca4e100 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 4 May 2020 16:01:02 -0400 Subject: [PATCH 156/435] fixing stupid error --- src/code_generation/code.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 04dc0e72..e9f4933a 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -1,6 +1,5 @@ from code_generation.ast import * - def cil_to_code(ast): if type(ast)==ProgramNode: return program_cg_visitor(ast) @@ -127,7 +126,7 @@ def arg_cg_visitor(arg: ArgNode): return f'ARG {arg.val} ;' -def cond_goto_cg_visitor(gcoto: ConditionalGotoNode): +def cond_goto_cg_visitor(cgoto: ConditionalGotoNode): return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' From 9986a9534ade261a96c40ba75dd6975837b509b0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 4 May 2020 16:55:46 -0400 Subject: [PATCH 157/435] Add self type to FuncCallNode --- src/lexer_parser/ast.py | 1 + src/semantic/semantic.py | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 2c47c92f..869bb850 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -66,6 +66,7 @@ def __init__(self, id, args, object=None, type=None): self.type = type self.id = id self.args = args + self.self_type = None class IfNode(ExpressionNode): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index c258e048..404ce258 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -108,6 +108,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc args_types = [] method = None msg = None + func_call.self_type = current_class for arg in func_call.args: arg_type = expression_visitor(arg, current_class, local_scope) args_types.append(arg_type) From 7d423d8ae17c4fcb74cda1b0488341a9a4a8c3a2 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 4 May 2020 17:21:24 -0400 Subject: [PATCH 158/435] adding self function visitor --- src/code_generation/cil.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 917051b9..f0d1fe57 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -349,7 +349,33 @@ def standard_func_call_to_cil_visitor(call, locals_count): return CIL_block(locals, body, result, data) def self_func_call_to_cil_visitor(call, locals_count): - pass + locals=[] + body=[] + data=[] + + arg_values = [] + + for arg in call.args: + arg_cil = expression_to_cil_visitor(arg, locals_count) + locals_count += len(arg_cil.locals) + locals += arg_cil.locals + body += arg_cil.body + data += arg_cil.data + arg_values.append(arg_cil.value) + + body.append(cil.ArgNode('self')) + + for arg in arg_values: + body.append(cil.ArgNode(arg)) + + result = f'local_{locals_count}' + locals.append(cil.LocalNode(result)) + + body.append(cil.VCAllNode(call.self_type, call.id, result)) + + return CIL_block(locals, body, data, result) + + class CIL_block: From 3e9cf7ec3e54b001a1cb5c608503309e7493bbb5 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 4 May 2020 21:40:57 -0400 Subject: [PATCH 159/435] merging func to cil function, adding dynamic type consideration --- src/code_generation/cil.py | 66 ++++++++++++-------------------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index f0d1fe57..b7f5e878 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -314,15 +314,22 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) -def standard_func_call_to_cil_visitor(call, locals_count): +def case_to_cil_visitor(case, locals_count): + pass + +def func_call_to_cil_visitor(call, locals_count): locals = [] body = [] data = [] - obj_cil = expression_to_cil_visitor(call.object, locals_count) - locals_count += len(obj_cil.locals) - locals += obj_cil.locals - body += obj_cil.body - data += obj_cil.data + if call.object: + obj_cil = expression_to_cil_visitor(call.object, locals_count) + locals_count += len(obj_cil.locals) + locals += obj_cil.locals + body += obj_cil.body + data += obj_cil.data + obj=obj_cil.value + else: + obj='self' arg_values = [] @@ -333,48 +340,24 @@ def standard_func_call_to_cil_visitor(call, locals_count): body += arg_cil.body data += arg_cil.data arg_values.append(arg_cil.value) + + t=f'local_{locals_count}' + locals.append(cil.LocalNode(t)) + body.append(cil.TypeOfNode(t, obj)) - body.append(cil.ArgNode(obj_cil.value)) + body.append(cil.ArgNode(obj)) for arg in arg_values: body.append(cil.ArgNode(arg)) - result = f'local_{locals_count}' + result = f'local_{locals_count+1}' locals.append(cil.LocalNode(result)) if not call.type: - body.append(cil.VCAllNode(call.object.returned_type, call.id, result)) + body.append(cil.VCAllNode(t, call.id, result)) else: body.append(cil.VCAllNode(call.type, call.id, result)) - return CIL_block(locals, body, result, data) - -def self_func_call_to_cil_visitor(call, locals_count): - locals=[] - body=[] - data=[] - - arg_values = [] - - for arg in call.args: - arg_cil = expression_to_cil_visitor(arg, locals_count) - locals_count += len(arg_cil.locals) - locals += arg_cil.locals - body += arg_cil.body - data += arg_cil.data - arg_values.append(arg_cil.value) - - body.append(cil.ArgNode('self')) - - for arg in arg_values: - body.append(cil.ArgNode(arg)) - - result = f'local_{locals_count}' - locals.append(cil.LocalNode(result)) - - body.append(cil.VCAllNode(call.self_type, call.id, result)) - - return CIL_block(locals, body, data, result) - + return CIL_block(locals, body, result, data) @@ -385,13 +368,6 @@ def __init__(self, locals, body, value, data=[]): self.value = value self.data = data - -def func_call_to_cil_visitor(call, locals_count): - if not object: - return self_func_call_to_cil_visitor(call, locals_count) - return standard_func_call_to_cil_visitor(call, locals_count) - - __visitor__ = { lp_ast.AssignNode: assign_to_cil_visitor, lp_ast.BlockNode: block_to_cil_visitor, From 4c72b015d58b33521b810f00466367c779c7f1da Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 11:50:29 -0400 Subject: [PATCH 160/435] adding case to cil visitor --- src/code_generation/cil.py | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index b7f5e878..33ceaa8a 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -84,6 +84,50 @@ def expression_to_cil_visitor(expression, locals_count): return __visitor__[type(expression)](expression, locals_count) except: raise Exception(f'There is no visitor for {type(expression)}') + +def case_to_cil_visitor(case, locals_count): + locals=[] + body=[] + data=[] + expr_cil=expression_to_cil_visitor(case.expr, locals_count) + locals_count+=len(expr_cil.locals) + locals+=expr_cil.locals + body+=expr_cil.body + data+=expr_cil.data + t=f'local_{locals_count}' + locals_count+=1 + locals.append(cil.LocalNode(t)) + body.append(cil.TypeOfNode(t, expr_cil.value)) + types=[] + labels=[] + for c in case.case_list: + types.append(c.type) + + for l in range(len(case.case_list)): + labels.append(f'local_{locals_count}') + locals_count+=1 + + value=None + + for i, branch in enumerate(case.case_list): + predicate=f'local_{locals_count}' + locals_count+=1 + locals+=[cil.LocalNode(predicate), cil.LocalNode(branch.id)] + body.append(cil.MinusNode(t, branch.type, predicate)) + body.append(cil.ConditionalGotoNode(predicate, labels[i])) + body.append(cil.AssignNode(branch.id, expr_cil.value)) + branch_cil=expression_to_cil_visitor(branch.expr, locals_count) + locals+=branch_cil.locals + body+=branch_cil.body + data+=branch_cil.data + locals_count+=len(branch_cil.locals) + value=branch_cil.value + body.append(cil.LabelNode(labels[i])) + + return CIL_block(locals, body, value, data) + + + def assign_to_cil_visitor(assign, locals_count): From 96f7de0ec1dde90b3528ac9729b9a7f56ab94aa0 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 11:52:12 -0400 Subject: [PATCH 161/435] removing previous case to cil visitor --- src/code_generation/cil.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 33ceaa8a..ea67df83 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -358,9 +358,6 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) -def case_to_cil_visitor(case, locals_count): - pass - def func_call_to_cil_visitor(call, locals_count): locals = [] body = [] From 578658ad9183722f8f159de9bf6a1d7388915102 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 11:52:37 -0400 Subject: [PATCH 162/435] removing duplicate class --- src/code_generation/cil.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ea67df83..f2f7e158 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -401,14 +401,6 @@ def func_call_to_cil_visitor(call, locals_count): return CIL_block(locals, body, result, data) - -class CIL_block: - def __init__(self, locals, body, value, data=[]): - self.locals = locals - self.body = body - self.value = value - self.data = data - __visitor__ = { lp_ast.AssignNode: assign_to_cil_visitor, lp_ast.BlockNode: block_to_cil_visitor, From ab04701eb29e44f0cbf24a2263b16d21b9f7fee9 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 11:53:46 -0400 Subject: [PATCH 163/435] Fixing attributes mistake --- src/code_generation/code.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index e9f4933a..78cfbb98 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -28,11 +28,11 @@ def type_cg_visitor(type: TypeNode): for name in type.methods: method_code+=f'method {name}:{type.methods[name]}_{name};\n' - return f'type {type.name} {{ \n {attr_code} {method_code} }}' + return f'type {type.type} {{ \n {attr_code} {method_code} }}' def data_cg_visitor(data: DataNode): - return f'{data.id} = {data.value} ;' + return f'{data.id} = {data.val} ;' def func_cg_visitor(func: FuncNode): From b1376cbdd4baf758bef2ff31c3f78edef82f1b48 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 12:03:50 -0400 Subject: [PATCH 164/435] adding main call to code generation --- src/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.py b/src/main.py index 2f97fe85..5b1a0eff 100644 --- a/src/main.py +++ b/src/main.py @@ -3,6 +3,7 @@ import errors as err from lexer_parser import lexer, parser from semantic import semantic_check +from src.code_generation import generate_code def exit_with_error(error): @@ -36,6 +37,8 @@ def main(): for e in err.SEMANTIC_ERRORS: print(e) exit(1) + + cil_code=generate_code(ast) if __name__ == "__main__": From 896385ed40849a026802b9ee8504c9f44cf7349b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:05:09 -0400 Subject: [PATCH 165/435] Fix import error --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index 5b1a0eff..db2c342c 100644 --- a/src/main.py +++ b/src/main.py @@ -3,7 +3,7 @@ import errors as err from lexer_parser import lexer, parser from semantic import semantic_check -from src.code_generation import generate_code +from code_generation import generate_code def exit_with_error(error): From cb49d1f225a811b27334931f07f3f513a36ab189 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:13:05 -0400 Subject: [PATCH 166/435] Fix key --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index f2f7e158..fc498e1a 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -25,7 +25,7 @@ def program_to_cil_visitor(program): _type.methods[met.id] = met.owner for met in value.get_all_self_methods(): - _type.methods[met.id] = t + _type.methods[met] = t types.append(_type) From 3819e0121ada5d47e23da5c2be14d6f514a94ef4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:14:49 -0400 Subject: [PATCH 167/435] Reformat code --- src/code_generation/ast.py | 9 ++-- src/code_generation/cil.py | 75 ++++++++++++++++----------------- src/code_generation/code.py | 24 ++++++----- src/code_generation/code_gen.py | 6 +-- src/semantic/types.py | 27 ++++++------ 5 files changed, 70 insertions(+), 71 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 57ec7cfc..e42d863a 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -11,10 +11,11 @@ def __init__(self, types, data, code): class TypeNode(Node): def __init__(self, type): - self.attributes=[] - self.methods={} - self.type=type - + self.attributes = [] + self.methods = {} + self.type = type + + class DataNode(Node): def __init__(self, id, val): self.id = id diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index fc498e1a..29d27d78 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -84,50 +84,48 @@ def expression_to_cil_visitor(expression, locals_count): return __visitor__[type(expression)](expression, locals_count) except: raise Exception(f'There is no visitor for {type(expression)}') - + + def case_to_cil_visitor(case, locals_count): - locals=[] - body=[] - data=[] - expr_cil=expression_to_cil_visitor(case.expr, locals_count) - locals_count+=len(expr_cil.locals) - locals+=expr_cil.locals - body+=expr_cil.body - data+=expr_cil.data - t=f'local_{locals_count}' - locals_count+=1 + locals = [] + body = [] + data = [] + expr_cil = expression_to_cil_visitor(case.expr, locals_count) + locals_count += len(expr_cil.locals) + locals += expr_cil.locals + body += expr_cil.body + data += expr_cil.data + t = f'local_{locals_count}' + locals_count += 1 locals.append(cil.LocalNode(t)) body.append(cil.TypeOfNode(t, expr_cil.value)) - types=[] - labels=[] + types = [] + labels = [] for c in case.case_list: types.append(c.type) - + for l in range(len(case.case_list)): labels.append(f'local_{locals_count}') - locals_count+=1 - - value=None - + locals_count += 1 + + value = None + for i, branch in enumerate(case.case_list): - predicate=f'local_{locals_count}' - locals_count+=1 - locals+=[cil.LocalNode(predicate), cil.LocalNode(branch.id)] + predicate = f'local_{locals_count}' + locals_count += 1 + locals += [cil.LocalNode(predicate), cil.LocalNode(branch.id)] body.append(cil.MinusNode(t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) body.append(cil.AssignNode(branch.id, expr_cil.value)) - branch_cil=expression_to_cil_visitor(branch.expr, locals_count) - locals+=branch_cil.locals - body+=branch_cil.body - data+=branch_cil.data - locals_count+=len(branch_cil.locals) - value=branch_cil.value + branch_cil = expression_to_cil_visitor(branch.expr, locals_count) + locals += branch_cil.locals + body += branch_cil.body + data += branch_cil.data + locals_count += len(branch_cil.locals) + value = branch_cil.value body.append(cil.LabelNode(labels[i])) - + return CIL_block(locals, body, value, data) - - - def assign_to_cil_visitor(assign, locals_count): @@ -358,6 +356,7 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) + def func_call_to_cil_visitor(call, locals_count): locals = [] body = [] @@ -368,9 +367,9 @@ def func_call_to_cil_visitor(call, locals_count): locals += obj_cil.locals body += obj_cil.body data += obj_cil.data - obj=obj_cil.value + obj = obj_cil.value else: - obj='self' + obj = 'self' arg_values = [] @@ -381,8 +380,8 @@ def func_call_to_cil_visitor(call, locals_count): body += arg_cil.body data += arg_cil.data arg_values.append(arg_cil.value) - - t=f'local_{locals_count}' + + t = f'local_{locals_count}' locals.append(cil.LocalNode(t)) body.append(cil.TypeOfNode(t, obj)) @@ -391,15 +390,15 @@ def func_call_to_cil_visitor(call, locals_count): for arg in arg_values: body.append(cil.ArgNode(arg)) - result = f'local_{locals_count+1}' + result = f'local_{locals_count + 1}' locals.append(cil.LocalNode(result)) if not call.type: body.append(cil.VCAllNode(t, call.id, result)) else: body.append(cil.VCAllNode(call.type, call.id, result)) - return CIL_block(locals, body, result, data) - + return CIL_block(locals, body, result, data) + __visitor__ = { lp_ast.AssignNode: assign_to_cil_visitor, diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 78cfbb98..7a366a40 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -1,16 +1,18 @@ from code_generation.ast import * + def cil_to_code(ast): - if type(ast)==ProgramNode: + if type(ast) == ProgramNode: return program_cg_visitor(ast) raise Exception(f'AST root must be program') -def program_cg_visitor(program:ProgramNode): - type_code='' - data_code='' - func_code='' - for t in program.types: - type_code+=f'{type_cg_visitor(t)}\n' + +def program_cg_visitor(program: ProgramNode): + type_code = '' + data_code = '' + func_code = '' + for t in program.types: + type_code += f'{type_cg_visitor(t)}\n' for d in program.data: data_code += f'{data_cg_visitor(d)}\n' for f in program.code: @@ -23,11 +25,11 @@ def type_cg_visitor(type: TypeNode): attr_code = '' method_code = '' for attr in type.attributes: - attr_code+=f'attribute {attr}; \n' - + attr_code += f'attribute {attr}; \n' + for name in type.methods: - method_code+=f'method {name}:{type.methods[name]}_{name};\n' - + method_code += f'method {name}:{type.methods[name]}_{name};\n' + return f'type {type.type} {{ \n {attr_code} {method_code} }}' diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py index 8c4d0a1d..13b0f4ee 100644 --- a/src/code_generation/code_gen.py +++ b/src/code_generation/code_gen.py @@ -1,7 +1,7 @@ -from .cil import ast_to_cil +from .cil import ast_to_cil from .code import cil_to_code + def generate_code(ast): - cil_ast=ast_to_cil(ast) + cil_ast = ast_to_cil(ast) return cil_to_code(cil_ast) - \ No newline at end of file diff --git a/src/semantic/types.py b/src/semantic/types.py index 8f5895b7..9e38f39c 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -31,35 +31,32 @@ def add_method(self, id, arg_types_name, returned_type): return True, None else: return False, msg - + def get_all_attributes(self): - t=self - result=[] + t = self + result = [] while t: - temp=[] + temp = [] for attr in t.attributes: temp.append(attr) result.append(temp) - t=t.parent + t = t.parent return [elem for sublist in result[::-1] for elem in sublist] - - + def get_all_self_methods(self): return self.methods - + def get_all_inherited_methods(self): - t=self.parent - result=[] + t = self.parent + result = [] while t: - temp=[] + temp = [] for met in t.methods: - met.owner=t.name + met.owner = t.name temp.append(met) result.append(temp) - t=t.parent + t = t.parent return [elem for sublist in result[::-1] for elem in sublist] - - def get_method(self, id, args_types): try: From b96cda1d3b4b1a5bea671ccf6381944b607a8dab Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:17:54 -0400 Subject: [PATCH 168/435] Fix dictionary iteration --- src/semantic/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index 9e38f39c..10082a57 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -51,7 +51,7 @@ def get_all_inherited_methods(self): result = [] while t: temp = [] - for met in t.methods: + for met in t.methods.values(): met.owner = t.name temp.append(met) result.append(temp) From f1f1d08a709c9bc89e1c8f36390e8c96fcbc1837 Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 12:20:39 -0400 Subject: [PATCH 169/435] Add Output File --- src/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index db2c342c..b4f1989e 100644 --- a/src/main.py +++ b/src/main.py @@ -16,8 +16,9 @@ def main(): exit_with_error("invalid number of arguments") input_data = "" + input_file = sys.argv[1] try: - with open(sys.argv[1]) as f: + with open(input_file) as f: input_data = f.read() except FileNotFoundError: exit_with_error(f'file {sys.argv[1]} not found') @@ -39,7 +40,10 @@ def main(): exit(1) cil_code=generate_code(ast) + output_file = input_file[0:-2] + 'cli' + with open(output_file,"x") as output: + output.write(cil_code) if __name__ == "__main__": main() From db8ce2c73ee2be910d43a6a5fa9f9bd2366008a8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:20:39 -0400 Subject: [PATCH 170/435] Fix call features to feature_nodes --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 29d27d78..97c86ce7 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -31,7 +31,7 @@ def program_to_cil_visitor(program): # completing .CODE and .DATA sections for c in program.classes: - for f in c.features: + for f in c.feature_nodes: if type(f) == DefFuncNode: if f.id == 'main' and c.name == 'Main': fun = func_to_cil_visitor(c.name, f) From 53cd4cb999537c9ec79c507dddbce492e74784cf Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:22:45 -0400 Subject: [PATCH 171/435] Fix access to class name --- src/code_generation/cil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 97c86ce7..b22ec9ad 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -33,8 +33,8 @@ def program_to_cil_visitor(program): for c in program.classes: for f in c.feature_nodes: if type(f) == DefFuncNode: - if f.id == 'main' and c.name == 'Main': - fun = func_to_cil_visitor(c.name, f) + if f.id == 'main' and c.type == 'Main': + fun = func_to_cil_visitor(c.type, f) code.insert(0, fun[0]) data.append(fun[1]) else: From e38e5fe031b8078a2f11ad6d25010c157b41df2a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 12:36:06 -0400 Subject: [PATCH 172/435] Fix iteration for function expressions --- src/code_generation/cil.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index b22ec9ad..5737ffaa 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -69,8 +69,15 @@ def func_to_cil_visitor(type_name, func): data.append(attr_cil.data) body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) - for exp in func.expressions: - instruction = expression_to_cil_visitor(exp, locals_count) + if type(func.expressions) is BlockNode: + for exp in func.expressions.expressions: + instruction = expression_to_cil_visitor(exp, locals_count) + locals += instruction.locals + body += instruction.body + data += instruction.data + locals_count += len(instruction.locals) + else: + instruction = expression_to_cil_visitor(func.expressions, locals_count) locals += instruction.locals body += instruction.body data += instruction.data From 1c31b7b3b52fc44b7e2bb948b3e057900a0c8532 Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 12:43:47 -0400 Subject: [PATCH 173/435] Fix some bugs in cil visitors --- src/code_generation/cil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 5737ffaa..a43470d6 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -19,7 +19,7 @@ def program_to_cil_visitor(program): _type = cil.TypeNode(t) value = TypesByName[t] for attr in value.get_all_attributes(): - _type.attributes.append(attr.id) + _type.attributes.append(attr) for met in value.get_all_inherited_methods(): _type.methods[met.id] = met.owner @@ -38,7 +38,7 @@ def program_to_cil_visitor(program): code.insert(0, fun[0]) data.append(fun[1]) else: - fun = func_to_cil_visitor(c.name, f) + fun = func_to_cil_visitor(c.type, f) code.append(fun[0]) data.append(fun[1]) From 7a1d02c435ea0d785238a00ae51bfc4a9e4ba990 Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 12:56:33 -0400 Subject: [PATCH 174/435] Fix data access from cil code --- src/code_generation/code.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 7a366a40..fc18b259 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -34,8 +34,10 @@ def type_cg_visitor(type: TypeNode): def data_cg_visitor(data: DataNode): - return f'{data.id} = {data.val} ;' - + try: + return f'{data[0].id} = {data[0].val} ;' + except: + return '' def func_cg_visitor(func: FuncNode): params_code = '' From f6448cb565ff8e13f3288a145576cbd546a89bb6 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 13:06:11 -0400 Subject: [PATCH 175/435] adding id fix to param and local code printing --- src/code_generation/code.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 7a366a40..67e1a84a 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -54,11 +54,11 @@ def func_cg_visitor(func: FuncNode): def param_cg_visitor(param: ParamNode): - return f'PARAM {param} ;' + return f'PARAM {param.id} ;' def local_cg_visitor(local: LocalNode): - return f'LOCAL {local} ;' + return f'LOCAL {local.id} ;' def instruction_cg_visitor(instruction: InstructionNode): From 82285ac24ba03932b78b69b5afb69230bda3e144 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 13:33:15 -0400 Subject: [PATCH 176/435] adding global data_count --- src/code_generation/cil.py | 127 +++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 47 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a43470d6..69c57e06 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -13,6 +13,8 @@ def program_to_cil_visitor(program): types = [] data = [] code = [] + data_count=0 + # completing .TYPE section for t in TypesByName: @@ -34,18 +36,20 @@ def program_to_cil_visitor(program): for f in c.feature_nodes: if type(f) == DefFuncNode: if f.id == 'main' and c.type == 'Main': - fun = func_to_cil_visitor(c.type, f) + fun = func_to_cil_visitor(c.type, f, data_count) code.insert(0, fun[0]) data.append(fun[1]) + data_count+=len(fun[1]) else: fun = func_to_cil_visitor(c.type, f) code.append(fun[0]) data.append(fun[1]) + data_count+=len(fun[1]) return cil.ProgramNode(types, data, code) -def func_to_cil_visitor(type_name, func): +def func_to_cil_visitor(type_name, func, data_count): name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] @@ -62,8 +66,9 @@ def func_to_cil_visitor(type_name, func): init_attr = TypesByName['Main'].get_all_attributes() for attr in init_attr: if attr.expression: - attr_cil = expression_to_cil_visitor(attr.expression, locals_count) + attr_cil = expression_to_cil_visitor(attr.expression, locals_count, data_count) locals_count += len(attr_cil.locals) + data_count+=len(attr_cil.data) locals.append(attr_cil.locals) body.append(attr_cil.body) data.append(attr_cil.data) @@ -71,34 +76,37 @@ def func_to_cil_visitor(type_name, func): if type(func.expressions) is BlockNode: for exp in func.expressions.expressions: - instruction = expression_to_cil_visitor(exp, locals_count) + instruction = expression_to_cil_visitor(exp, locals_count, data_count) locals += instruction.locals body += instruction.body data += instruction.data locals_count += len(instruction.locals) + data_count+=len(instruction.data) else: instruction = expression_to_cil_visitor(func.expressions, locals_count) locals += instruction.locals body += instruction.body data += instruction.data + data_count+=len(instruction.data) locals_count += len(instruction.locals) return cil.FuncNode(name, params, locals, body), data -def expression_to_cil_visitor(expression, locals_count): +def expression_to_cil_visitor(expression, locals_count, data_count): try: - return __visitor__[type(expression)](expression, locals_count) + return __visitor__[type(expression)](expression, locals_count, data_count) except: raise Exception(f'There is no visitor for {type(expression)}') -def case_to_cil_visitor(case, locals_count): +def case_to_cil_visitor(case, locals_count, data_count): locals = [] body = [] data = [] - expr_cil = expression_to_cil_visitor(case.expr, locals_count) + expr_cil = expression_to_cil_visitor(case.expr, locals_count, data_count) locals_count += len(expr_cil.locals) + data_count+=len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body data += expr_cil.data @@ -124,30 +132,35 @@ def case_to_cil_visitor(case, locals_count): body.append(cil.MinusNode(t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) body.append(cil.AssignNode(branch.id, expr_cil.value)) - branch_cil = expression_to_cil_visitor(branch.expr, locals_count) + branch_cil = expression_to_cil_visitor(branch.expr, locals_count, data_count) locals += branch_cil.locals body += branch_cil.body data += branch_cil.data locals_count += len(branch_cil.locals) + data_count+=len(branch_cil.data) value = branch_cil.value body.append(cil.LabelNode(labels[i])) return CIL_block(locals, body, value, data) -def assign_to_cil_visitor(assign, locals_count): +def assign_to_cil_visitor(assign, locals_count, data_count): expr = expression_to_cil_visitor(assign.expr, locals_count) locals_count += len(expr.locals) + data_count+=len(expr.data) value = [f'local_{locals_count}'] locals = expr.locals + [cil.LocalNode(value)] body = expr.body + [cil.AssignNode(assign.id, expr.value)] return CIL_block(locals, body, value, expr.data) -def arith_to_cil_visitor(arith, locals_count): - l = expression_to_cil_visitor(arith.lvalue, locals_count) - r = expression_to_cil_visitor(arith.rvalue, locals_count) - locals_count += len(l.locals) + len(r.locals) +def arith_to_cil_visitor(arith, locals_count, data_count): + l = expression_to_cil_visitor(arith.lvalue, locals_count, data_count) + locals_count+=len(l.locals) + data_count+=len(l.data) + r = expression_to_cil_visitor(arith.rvalue, locals_count, data_count) + locals_count += len(r.locals) + data_count+=len(r.data) cil_result = f'local_{locals_count}' @@ -167,15 +180,18 @@ def arith_to_cil_visitor(arith, locals_count): return CIL_block(locals, body, cil_result, data) -def if_to_cil_visitor(_if, locals_count): - predicate = expression_to_cil_visitor(_if.if_expr, locals_count) +def if_to_cil_visitor(_if, locals_count, data_count): + predicate = expression_to_cil_visitor(_if.if_expr, locals_count, data_count) locals_count += len(predicate.locals) + data_count+=len(predicate.data) - then = expression_to_cil_visitor(_if.then_expr, locals_count) + then = expression_to_cil_visitor(_if.then_expr, locals_count, data_count) locals_count += len(then.locals) + data_count+=len(then.data) - else_expression = expression_to_cil_visitor(_if.else_expr, locals_count) + else_expression = expression_to_cil_visitor(_if.else_expr, locals_count, data_count) locals_count += len(else_expression.locals) + data_count+=len(else_expression.data) label_1 = f'local_{locals_count}' label_2 = f'local_{locals_count + 1}' @@ -190,12 +206,14 @@ def if_to_cil_visitor(_if, locals_count): return CIL_block(locals, body, value, data) -def loop_to_cil_visitor(loop, locals_count): - predicate = expression_to_cil_visitor(loop.cond, locals_count) +def loop_to_cil_visitor(loop, locals_count, data_count): + predicate = expression_to_cil_visitor(loop.cond, locals_count, data_count) locals_count += len(predicate.locals) + data_count+=len(predicate.data) - loop_block = expression_to_cil_visitor(loop.body, locals_count) + loop_block = expression_to_cil_visitor(loop.body, locals_count, data_count) locals_count += len(loop_block.locals) + data_count+=len(loop_block.data) value = f'local_{locals_count}' @@ -212,10 +230,13 @@ def loop_to_cil_visitor(loop, locals_count): return CIL_block(locals, body, value, data) -def equal_to_cil_visitor(equal, locals_count): - l = expression_to_cil_visitor(equal.lvalue, locals_count) - r = expression_to_cil_visitor(equal.rvalue, locals_count) - locals_count += len(l.locals) + len(r.locals) +def equal_to_cil_visitor(equal, locals_count, data_count): + l = expression_to_cil_visitor(equal.lvalue, locals_count, data_count) + locals_count+=len(l.locals) + data_count+=len(l.data) + r = expression_to_cil_visitor(equal.rvalue, locals_count, data_count) + locals_count += len(r.locals) + data_count+=len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -230,10 +251,13 @@ def equal_to_cil_visitor(equal, locals_count): return CIL_block(locals, body, value, data) -def lessthan_to_cil_visitor(lessthan, locals_count): +def lessthan_to_cil_visitor(lessthan, locals_count, data_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) + locals_count+=len(l.locals) + data_count+=len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count += len(l.locals) + len(r.locals) + locals_count += len(r.locals) + data_count+=len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -248,10 +272,13 @@ def lessthan_to_cil_visitor(lessthan, locals_count): return CIL_block(locals, body, value, data) -def lesseqthan_to_cil_visitor(lessthan, locals_count): +def lesseqthan_to_cil_visitor(lessthan, locals_count, data_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) + locals_count+=len(l.locals) + data_count+=len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count += len(l.locals) + len(r.locals) + locals_count += len(r.locals) + data_count+=len(r.data) cil_less = f'local_{locals_count}' cil_equal = f'local_{locals_count + 1}' @@ -270,19 +297,19 @@ def lesseqthan_to_cil_visitor(lessthan, locals_count): return CIL_block(locals, body, value, data) -def integer_to_cil_visitor(integer, locals_count): +def integer_to_cil_visitor(integer, locals_count, data_count): return CIL_block([], [], integer.value) -def bool_to_cil_visitor(bool, locals_count): +def bool_to_cil_visitor(bool, locals_count, data_count): return CIL_block([], [], 1) if bool.value == 'true' else CIL_block([], [], 0) -def id_to_cil_visitor(id, locals_count): +def id_to_cil_visitor(id, locals_count, data_count): return CIL_block([], [], id.id) -def new_to_cil_visitor(new_node, locals_count): +def new_to_cil_visitor(new_node, locals_count, data_count): value = f'local_{locals_count}' locals = [cil.LocalNode(value)] locals_count += 1 @@ -292,8 +319,9 @@ def new_to_cil_visitor(new_node, locals_count): for attr in init_attr: if attr.expression: - attr_cil = expression_to_cil_visitor(attr.expression, locals_count) + attr_cil = expression_to_cil_visitor(attr.expression, locals_count, data_count) locals_count += len(attr_cil.locals) + data_count+=len(attr_cil.data) locals.append(attr_cil.locals) body.append(attr_cil.body) data.append(attr_cil.data) @@ -302,9 +330,9 @@ def new_to_cil_visitor(new_node, locals_count): return CIL_block(locals, body, value, data) -def string_to_cil_visitor(str, locals_count): - str_addr = f'local_{locals_count}' - str_id = f'local_{locals_count + 1}' +def string_to_cil_visitor(str, locals_count, data_count): + str_addr = f'data_{data_count}' + str_id = f'local_{locals_count}' locals = [cil.LocalNode(str_id)] data = [cil.DataNode(str_addr, str.value)] @@ -313,19 +341,20 @@ def string_to_cil_visitor(str, locals_count): return CIL_block(locals, body, str_id, data) -def let_to_cil_visitor(let, locals_count): +def let_to_cil_visitor(let, locals_count, data_count): body = [] locals = [] data = [] for attr in let.let_attr: - attr_cil = expression_to_cil_visitor(attr, locals_count) + attr_cil = expression_to_cil_visitor(attr, locals_count, data_count) locals_count += len(attr_cil.locals) + data_count+=len(attr_cil.data) body.append(cil.AssignNode(attr.id, attr_cil.value)) body += attr_cil.body locals += attr_cil.locals data += attr_cil.data - expr_cil = expression_to_cil_visitor(let.expr, locals_count) + expr_cil = expression_to_cil_visitor(let.expr, locals_count, data_count) locals += expr_cil.locals body += expr_cil.locals data += expr_cil.data @@ -333,9 +362,10 @@ def let_to_cil_visitor(let, locals_count): return CIL_block(locals, body, expr_cil.value, data) -def logic_not_to_cil_visitor(not_node, locals_count): - expr_cil = expression_to_cil_visitor(not_node.val, locals_count) +def logic_not_to_cil_visitor(not_node, locals_count, data_count): + expr_cil = expression_to_cil_visitor(not_node.val, locals_count, data_count) locals_count += len(expr_cil.locals) + data_count+=len(expr_cil.data) value = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -347,15 +377,16 @@ def logic_not_to_cil_visitor(not_node, locals_count): return CIL_block(locals, body, value, expr_cil.data) -def block_to_cil_visitor(block, locals_count): +def block_to_cil_visitor(block, locals_count, data_count): locals = [] body = [] data = [] value = None for expr in block.expressions: - expr_cil = expression_to_cil_visitor(expr, locals_count) + expr_cil = expression_to_cil_visitor(expr, locals_count, data_count) locals_count += len(expr_cil.locals) + data_count+=len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body data += expr_cil.data @@ -364,13 +395,14 @@ def block_to_cil_visitor(block, locals_count): return CIL_block(locals, body, value, data) -def func_call_to_cil_visitor(call, locals_count): +def func_call_to_cil_visitor(call, locals_count, data_count): locals = [] body = [] data = [] if call.object: - obj_cil = expression_to_cil_visitor(call.object, locals_count) + obj_cil = expression_to_cil_visitor(call.object, locals_count,data_count) locals_count += len(obj_cil.locals) + data_count+=len(obj_cil.data) locals += obj_cil.locals body += obj_cil.body data += obj_cil.data @@ -381,8 +413,9 @@ def func_call_to_cil_visitor(call, locals_count): arg_values = [] for arg in call.args: - arg_cil = expression_to_cil_visitor(arg, locals_count) + arg_cil = expression_to_cil_visitor(arg, locals_count, data_count) locals_count += len(arg_cil.locals) + data_count+= len(arg_cil.data) locals += arg_cil.locals body += arg_cil.body data += arg_cil.data From 253f07b30771c7cd830320c897680515aaccd913 Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 13:43:40 -0400 Subject: [PATCH 177/435] Add data_count arg to cil visitors --- src/code_generation/cil.py | 4 ++-- src/main.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 69c57e06..71550898 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -41,7 +41,7 @@ def program_to_cil_visitor(program): data.append(fun[1]) data_count+=len(fun[1]) else: - fun = func_to_cil_visitor(c.type, f) + fun = func_to_cil_visitor(c.type, f, data_count) code.append(fun[0]) data.append(fun[1]) data_count+=len(fun[1]) @@ -83,7 +83,7 @@ def func_to_cil_visitor(type_name, func, data_count): locals_count += len(instruction.locals) data_count+=len(instruction.data) else: - instruction = expression_to_cil_visitor(func.expressions, locals_count) + instruction = expression_to_cil_visitor(func.expressions, locals_count, data_count) locals += instruction.locals body += instruction.body data += instruction.data diff --git a/src/main.py b/src/main.py index b4f1989e..ffc78e37 100644 --- a/src/main.py +++ b/src/main.py @@ -42,7 +42,7 @@ def main(): cil_code=generate_code(ast) output_file = input_file[0:-2] + 'cli' - with open(output_file,"x") as output: + with open(output_file,"w") as output: output.write(cil_code) if __name__ == "__main__": From 804e15f458b68af5b47e2ce25e0e0f1db013dd4c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 13:49:21 -0400 Subject: [PATCH 178/435] Change CIL file extension --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index ffc78e37..db4e1911 100644 --- a/src/main.py +++ b/src/main.py @@ -40,7 +40,7 @@ def main(): exit(1) cil_code=generate_code(ast) - output_file = input_file[0:-2] + 'cli' + output_file = input_file[0:-2] + 'cil' with open(output_file,"w") as output: output.write(cil_code) From 2c17703bcfd47a641e93240ecac3fa23615d890a Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 13:51:15 -0400 Subject: [PATCH 179/435] Add data_count to assign visitor --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 71550898..78f6eb8f 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -145,7 +145,7 @@ def case_to_cil_visitor(case, locals_count, data_count): def assign_to_cil_visitor(assign, locals_count, data_count): - expr = expression_to_cil_visitor(assign.expr, locals_count) + expr = expression_to_cil_visitor(assign.expr, locals_count, data_count) locals_count += len(expr.locals) data_count+=len(expr.data) value = [f'local_{locals_count}'] From 81b3216e1c1baae26f14665d2fd7c9954748b992 Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Tue, 5 May 2020 14:03:25 -0400 Subject: [PATCH 180/435] String in quotes on cil data section --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 78f6eb8f..24cbf4ec 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -335,7 +335,7 @@ def string_to_cil_visitor(str, locals_count, data_count): str_id = f'local_{locals_count}' locals = [cil.LocalNode(str_id)] - data = [cil.DataNode(str_addr, str.value)] + data = [cil.DataNode(str_addr, f"\"{str.value}\"")] body = [cil.LoadNode(str_addr, str_id)] return CIL_block(locals, body, str_id, data) From 8d4edd760db2752da3b12f25903dda69098fb706 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 14:15:45 -0400 Subject: [PATCH 181/435] remove unnecessary if --- src/code_generation/cil.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 69c57e06..225039c3 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -74,15 +74,6 @@ def func_to_cil_visitor(type_name, func, data_count): data.append(attr_cil.data) body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) - if type(func.expressions) is BlockNode: - for exp in func.expressions.expressions: - instruction = expression_to_cil_visitor(exp, locals_count, data_count) - locals += instruction.locals - body += instruction.body - data += instruction.data - locals_count += len(instruction.locals) - data_count+=len(instruction.data) - else: instruction = expression_to_cil_visitor(func.expressions, locals_count) locals += instruction.locals body += instruction.body @@ -223,8 +214,7 @@ def loop_to_cil_visitor(loop, locals_count, data_count): end_label = f'local_{locals_count + 2}' body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), - cil.LabelNode(loop_label)] + loop_block.body + [cil.AssignNode(value, loop_block.value), - cil.LabelNode(end_label)] + cil.LabelNode(loop_label)] + loop_block.body + [cil.LabelNode(end_label), cil.AssignNode(value, 0)] data = predicate.data + loop_block.data return CIL_block(locals, body, value, data) @@ -329,6 +319,8 @@ def new_to_cil_visitor(new_node, locals_count, data_count): return CIL_block(locals, body, value, data) +def is_void_to_cil_visitor(isvoid, locals_count, data_count): + pass def string_to_cil_visitor(str, locals_count, data_count): str_addr = f'data_{data_count}' From d98b0db1eecf3d4a8bf113d8939afc4a644c1ece Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 5 May 2020 14:27:21 -0400 Subject: [PATCH 182/435] Fix some bugs --- src/semantic/semantic.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 404ce258..bb009704 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -180,7 +180,7 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): add_semantic_error(attribute.lineno, attribute.colno, f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') return None - local_scope[attribute.id] = ObjectType + local_scope[attribute.id] = id_type let.returned_type = expression_visitor(let.expr, current_class, local_scope) return let.returned_type @@ -260,11 +260,12 @@ def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scop def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if var.id in local_scope.keys(): var.returned_type = local_scope[var.id] - attribute, _ = get_attribute(current_class, var.id) - if attribute is not None: - var.returned_type = attribute.attrType else: - add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') + attribute, _ = get_attribute(current_class, var.id) + if attribute is not None: + var.returned_type = attribute.attrType + else: + add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') return var.returned_type From c63d1d31bf2c237886482f60dfed2ea9e6977223 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 5 May 2020 15:52:52 -0400 Subject: [PATCH 183/435] fixing argument missing --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 3e48a901..dd382382 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -74,7 +74,7 @@ def func_to_cil_visitor(type_name, func, data_count): data.append(attr_cil.data) body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) - instruction = expression_to_cil_visitor(func.expressions, locals_count) + instruction = expression_to_cil_visitor(func.expressions, locals_count, data_count) locals += instruction.locals body += instruction.body data += instruction.data From cdf292c88566c72134bdcc3bed36e79d4b2e460f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 11:50:21 -0400 Subject: [PATCH 184/435] Reformat code --- src/code_generation/cil.py | 116 +++++++++++++++++++++--------------- src/code_generation/code.py | 1 + src/main.py | 7 ++- 3 files changed, 72 insertions(+), 52 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index dd382382..ca530910 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -13,8 +13,7 @@ def program_to_cil_visitor(program): types = [] data = [] code = [] - data_count=0 - + data_count = 0 # completing .TYPE section for t in TypesByName: @@ -39,12 +38,12 @@ def program_to_cil_visitor(program): fun = func_to_cil_visitor(c.type, f, data_count) code.insert(0, fun[0]) data.append(fun[1]) - data_count+=len(fun[1]) + data_count += len(fun[1]) else: fun = func_to_cil_visitor(c.type, f, data_count) code.append(fun[0]) data.append(fun[1]) - data_count+=len(fun[1]) + data_count += len(fun[1]) return cil.ProgramNode(types, data, code) @@ -66,19 +65,21 @@ def func_to_cil_visitor(type_name, func, data_count): init_attr = TypesByName['Main'].get_all_attributes() for attr in init_attr: if attr.expression: - attr_cil = expression_to_cil_visitor(attr.expression, locals_count, data_count) + attr_cil = expression_to_cil_visitor( + attr.expression, locals_count, data_count) locals_count += len(attr_cil.locals) - data_count+=len(attr_cil.data) + data_count += len(attr_cil.data) locals.append(attr_cil.locals) body.append(attr_cil.body) data.append(attr_cil.data) body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) - instruction = expression_to_cil_visitor(func.expressions, locals_count, data_count) + instruction = expression_to_cil_visitor( + func.expressions, locals_count, data_count) locals += instruction.locals body += instruction.body data += instruction.data - data_count+=len(instruction.data) + data_count += len(instruction.data) locals_count += len(instruction.locals) return cil.FuncNode(name, params, locals, body), data @@ -97,7 +98,7 @@ def case_to_cil_visitor(case, locals_count, data_count): data = [] expr_cil = expression_to_cil_visitor(case.expr, locals_count, data_count) locals_count += len(expr_cil.locals) - data_count+=len(expr_cil.data) + data_count += len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body data += expr_cil.data @@ -123,12 +124,13 @@ def case_to_cil_visitor(case, locals_count, data_count): body.append(cil.MinusNode(t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) body.append(cil.AssignNode(branch.id, expr_cil.value)) - branch_cil = expression_to_cil_visitor(branch.expr, locals_count, data_count) + branch_cil = expression_to_cil_visitor( + branch.expr, locals_count, data_count) locals += branch_cil.locals body += branch_cil.body data += branch_cil.data locals_count += len(branch_cil.locals) - data_count+=len(branch_cil.data) + data_count += len(branch_cil.data) value = branch_cil.value body.append(cil.LabelNode(labels[i])) @@ -138,7 +140,7 @@ def case_to_cil_visitor(case, locals_count, data_count): def assign_to_cil_visitor(assign, locals_count, data_count): expr = expression_to_cil_visitor(assign.expr, locals_count, data_count) locals_count += len(expr.locals) - data_count+=len(expr.data) + data_count += len(expr.data) value = [f'local_{locals_count}'] locals = expr.locals + [cil.LocalNode(value)] body = expr.body + [cil.AssignNode(assign.id, expr.value)] @@ -147,11 +149,11 @@ def assign_to_cil_visitor(assign, locals_count, data_count): def arith_to_cil_visitor(arith, locals_count, data_count): l = expression_to_cil_visitor(arith.lvalue, locals_count, data_count) - locals_count+=len(l.locals) - data_count+=len(l.data) + locals_count += len(l.locals) + data_count += len(l.data) r = expression_to_cil_visitor(arith.rvalue, locals_count, data_count) locals_count += len(r.locals) - data_count+=len(r.data) + data_count += len(r.data) cil_result = f'local_{locals_count}' @@ -172,26 +174,29 @@ def arith_to_cil_visitor(arith, locals_count, data_count): def if_to_cil_visitor(_if, locals_count, data_count): - predicate = expression_to_cil_visitor(_if.if_expr, locals_count, data_count) + predicate = expression_to_cil_visitor( + _if.if_expr, locals_count, data_count) locals_count += len(predicate.locals) - data_count+=len(predicate.data) + data_count += len(predicate.data) then = expression_to_cil_visitor(_if.then_expr, locals_count, data_count) locals_count += len(then.locals) - data_count+=len(then.data) + data_count += len(then.data) - else_expression = expression_to_cil_visitor(_if.else_expr, locals_count, data_count) + else_expression = expression_to_cil_visitor( + _if.else_expr, locals_count, data_count) locals_count += len(else_expression.locals) - data_count+=len(else_expression.data) + data_count += len(else_expression.data) label_1 = f'local_{locals_count}' label_2 = f'local_{locals_count + 1}' value = f'local_{locals_count + 2}' - locals = predicate.locals + then.locals + else_expression.locals + [cil.LocalNode(value)] + locals = predicate.locals + then.locals + \ + else_expression.locals + [cil.LocalNode(value)] body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ - cil.AssignNode(value, then.value), cil.LabelNode(label_2)] + cil.AssignNode(value, then.value), cil.LabelNode(label_2)] data = predicate.data + then.data + else_expression.data return CIL_block(locals, body, value, data) @@ -200,11 +205,11 @@ def if_to_cil_visitor(_if, locals_count, data_count): def loop_to_cil_visitor(loop, locals_count, data_count): predicate = expression_to_cil_visitor(loop.cond, locals_count, data_count) locals_count += len(predicate.locals) - data_count+=len(predicate.data) + data_count += len(predicate.data) loop_block = expression_to_cil_visitor(loop.body, locals_count, data_count) locals_count += len(loop_block.locals) - data_count+=len(loop_block.data) + data_count += len(loop_block.data) value = f'local_{locals_count}' @@ -222,19 +227,21 @@ def loop_to_cil_visitor(loop, locals_count, data_count): def equal_to_cil_visitor(equal, locals_count, data_count): l = expression_to_cil_visitor(equal.lvalue, locals_count, data_count) - locals_count+=len(l.locals) - data_count+=len(l.data) + locals_count += len(l.locals) + data_count += len(l.data) r = expression_to_cil_visitor(equal.rvalue, locals_count, data_count) locals_count += len(r.locals) - data_count+=len(r.data) + data_count += len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' value = f'local_{locals_count + 2}' - locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] + locals = l.locals + r.locals + \ + [cil.LocalNode(cil_result), cil.LocalNode(value)] body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), - cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.ConditionalGotoNode( + cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] data = l.data + r.data @@ -243,19 +250,21 @@ def equal_to_cil_visitor(equal, locals_count, data_count): def lessthan_to_cil_visitor(lessthan, locals_count, data_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) - locals_count+=len(l.locals) - data_count+=len(l.data) + locals_count += len(l.locals) + data_count += len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(r.locals) - data_count+=len(r.data) + data_count += len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' value = f'local_{locals_count + 2}' - locals = l.locals + r.locals + [cil.LocalNode(cil_result), cil.LocalNode(value)] + locals = l.locals + r.locals + \ + [cil.LocalNode(cil_result), cil.LocalNode(value)] body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), - cil.ConditionalGotoNode(cil_result, end_label), cil.AssignNode(value, 1), + cil.ConditionalGotoNode( + cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] data = l.data + r.data @@ -264,11 +273,11 @@ def lessthan_to_cil_visitor(lessthan, locals_count, data_count): def lesseqthan_to_cil_visitor(lessthan, locals_count, data_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) - locals_count+=len(l.locals) - data_count+=len(l.data) + locals_count += len(l.locals) + data_count += len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(r.locals) - data_count+=len(r.data) + data_count += len(r.data) cil_less = f'local_{locals_count}' cil_equal = f'local_{locals_count + 1}' @@ -276,11 +285,15 @@ def lesseqthan_to_cil_visitor(lessthan, locals_count, data_count): end_label = f'local_{locals_count + 3}' value = f'local_{locals_count + 4}' - locals = l.locals + r.locals + [cil.LocalNode(cil_less), cil.LocalNode(cil_equal), cil.LocalNode(value)] + locals = l.locals + r.locals + \ + [cil.LocalNode(cil_less), cil.LocalNode( + cil_equal), cil.LocalNode(value)] body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), - cil.ConditionalGotoNode(cil_less, eq_label), cil.AssignNode(value, 1), + cil.ConditionalGotoNode( + cil_less, eq_label), cil.AssignNode(value, 1), cil.GotoNode(end_label), cil.LabelNode(eq_label), - cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode(cil_equal, end_label), + cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode( + cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] data = l.data + r.data @@ -309,9 +322,10 @@ def new_to_cil_visitor(new_node, locals_count, data_count): for attr in init_attr: if attr.expression: - attr_cil = expression_to_cil_visitor(attr.expression, locals_count, data_count) + attr_cil = expression_to_cil_visitor( + attr.expression, locals_count, data_count) locals_count += len(attr_cil.locals) - data_count+=len(attr_cil.data) + data_count += len(attr_cil.data) locals.append(attr_cil.locals) body.append(attr_cil.body) data.append(attr_cil.data) @@ -319,9 +333,11 @@ def new_to_cil_visitor(new_node, locals_count, data_count): return CIL_block(locals, body, value, data) + def is_void_to_cil_visitor(isvoid, locals_count, data_count): pass + def string_to_cil_visitor(str, locals_count, data_count): str_addr = f'data_{data_count}' str_id = f'local_{locals_count}' @@ -340,7 +356,7 @@ def let_to_cil_visitor(let, locals_count, data_count): for attr in let.let_attr: attr_cil = expression_to_cil_visitor(attr, locals_count, data_count) locals_count += len(attr_cil.locals) - data_count+=len(attr_cil.data) + data_count += len(attr_cil.data) body.append(cil.AssignNode(attr.id, attr_cil.value)) body += attr_cil.body locals += attr_cil.locals @@ -355,9 +371,10 @@ def let_to_cil_visitor(let, locals_count, data_count): def logic_not_to_cil_visitor(not_node, locals_count, data_count): - expr_cil = expression_to_cil_visitor(not_node.val, locals_count, data_count) + expr_cil = expression_to_cil_visitor( + not_node.val, locals_count, data_count) locals_count += len(expr_cil.locals) - data_count+=len(expr_cil.data) + data_count += len(expr_cil.data) value = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -378,7 +395,7 @@ def block_to_cil_visitor(block, locals_count, data_count): for expr in block.expressions: expr_cil = expression_to_cil_visitor(expr, locals_count, data_count) locals_count += len(expr_cil.locals) - data_count+=len(expr_cil.data) + data_count += len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body data += expr_cil.data @@ -392,9 +409,10 @@ def func_call_to_cil_visitor(call, locals_count, data_count): body = [] data = [] if call.object: - obj_cil = expression_to_cil_visitor(call.object, locals_count,data_count) + obj_cil = expression_to_cil_visitor( + call.object, locals_count, data_count) locals_count += len(obj_cil.locals) - data_count+=len(obj_cil.data) + data_count += len(obj_cil.data) locals += obj_cil.locals body += obj_cil.body data += obj_cil.data @@ -407,7 +425,7 @@ def func_call_to_cil_visitor(call, locals_count, data_count): for arg in call.args: arg_cil = expression_to_cil_visitor(arg, locals_count, data_count) locals_count += len(arg_cil.locals) - data_count+= len(arg_cil.data) + data_count += len(arg_cil.data) locals += arg_cil.locals body += arg_cil.body data += arg_cil.data diff --git a/src/code_generation/code.py b/src/code_generation/code.py index ed369f66..5e7c4cde 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -39,6 +39,7 @@ def data_cg_visitor(data: DataNode): except: return '' + def func_cg_visitor(func: FuncNode): params_code = '' locals_code = '' diff --git a/src/main.py b/src/main.py index db4e1911..38939c94 100644 --- a/src/main.py +++ b/src/main.py @@ -38,12 +38,13 @@ def main(): for e in err.SEMANTIC_ERRORS: print(e) exit(1) - - cil_code=generate_code(ast) + + cil_code = generate_code(ast) output_file = input_file[0:-2] + 'cil' - with open(output_file,"w") as output: + with open(output_file, "w") as output: output.write(cil_code) + if __name__ == "__main__": main() From 28d85773cf574e1e176b399866563c824f5ba5e1 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 12:04:30 -0400 Subject: [PATCH 185/435] Reformat CIL output code --- src/code_generation/code.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 5e7c4cde..1864b8f4 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -18,19 +18,19 @@ def program_cg_visitor(program: ProgramNode): for f in program.code: func_code += f'{func_cg_visitor(f)}\n' - return f'.TYPES \n {type_code} .DATA \n {data_code} .CODE \n {func_code}' + return f'.TYPES \n\n{type_code}\n.DATA\n\n{data_code}\n.CODE\n\n{func_code}\n' def type_cg_visitor(type: TypeNode): attr_code = '' method_code = '' for attr in type.attributes: - attr_code += f'attribute {attr}; \n' + attr_code += f'attribute {attr};\n' for name in type.methods: - method_code += f'method {name}:{type.methods[name]}_{name};\n' + method_code += f'\tmethod {name}:{type.methods[name]}_{name};\n' - return f'type {type.type} {{ \n {attr_code} {method_code} }}' + return f'type {type.type} {{\n{attr_code}{method_code}}}\n' def data_cg_visitor(data: DataNode): @@ -45,15 +45,15 @@ def func_cg_visitor(func: FuncNode): locals_code = '' body_code = '' for param in func.params: - params_code += f'{param_cg_visitor(param)}\n' + params_code += f'\t{param_cg_visitor(param)}\n' for local in func.locals: - locals_code += f'{local_cg_visitor(local)}\n' + locals_code += f'\t{local_cg_visitor(local)}\n' for instruction in func.body: - body_code += f'{instruction_cg_visitor(instruction)}\n' + body_code += f'\t{instruction_cg_visitor(instruction)}\n' - return f'function {func.name} {{ \n {params_code} {locals_code} {body_code} }}' + return f'function {func.name} {{\n{params_code}{locals_code}{body_code}}}' def param_cg_visitor(param: ParamNode): From 41c344fadc12ffb5196c78149bb2b2f1c6c64f8c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 13:24:59 -0400 Subject: [PATCH 186/435] Change Main function call --- src/code_generation/cil.py | 50 ++++++++++++++++++------------------- src/code_generation/code.py | 2 +- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ca530910..f93923ce 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -31,19 +31,33 @@ def program_to_cil_visitor(program): types.append(_type) # completing .CODE and .DATA sections + + """ + Building main function + + function main { + LOCAL __main__ ; + LOCAL main_result ; + __main__ = ALLOCATE Main ; + ARG __main__ ; + main_result = VCALL Main main ; + } + """ + main_instance = '__main__' + main_result = 'main_result' + main_function = cil.FuncNode('main', [], [cil.LocalNode(main_instance), cil.LocalNode(main_result)], + [cil.AllocateNode('Main', main_instance), + cil.ArgNode(main_instance), + cil.VCAllNode('Main', 'main', main_result)]) + code.append(main_function) + for c in program.classes: for f in c.feature_nodes: if type(f) == DefFuncNode: - if f.id == 'main' and c.type == 'Main': - fun = func_to_cil_visitor(c.type, f, data_count) - code.insert(0, fun[0]) - data.append(fun[1]) - data_count += len(fun[1]) - else: - fun = func_to_cil_visitor(c.type, f, data_count) - code.append(fun[0]) - data.append(fun[1]) - data_count += len(fun[1]) + fun = func_to_cil_visitor(c.type, f, data_count) + code.append(fun[0]) + data.append(fun[1]) + data_count += len(fun[1]) return cil.ProgramNode(types, data, code) @@ -57,22 +71,6 @@ def func_to_cil_visitor(type_name, func, data_count): data = [] locals_count = 0 - if type_name == 'Main' and func.id == 'main': - instance = '__main__' - locals.append(cil.LocalNode(instance)) - body.append(cil.AllocateNode('Main', instance)) - - init_attr = TypesByName['Main'].get_all_attributes() - for attr in init_attr: - if attr.expression: - attr_cil = expression_to_cil_visitor( - attr.expression, locals_count, data_count) - locals_count += len(attr_cil.locals) - data_count += len(attr_cil.data) - locals.append(attr_cil.locals) - body.append(attr_cil.body) - data.append(attr_cil.data) - body.append(cil.SetAttrNode(instance, attr.id, attr_cil.value)) instruction = expression_to_cil_visitor( func.expressions, locals_count, data_count) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 1864b8f4..6dca7bda 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -53,7 +53,7 @@ def func_cg_visitor(func: FuncNode): for instruction in func.body: body_code += f'\t{instruction_cg_visitor(instruction)}\n' - return f'function {func.name} {{\n{params_code}{locals_code}{body_code}}}' + return f'function {func.name} {{\n{params_code}{locals_code}{body_code}}}\n' def param_cg_visitor(param: ParamNode): From 8d0c193172b975193b12d702efd279eb414c94d3 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 15:22:04 -0400 Subject: [PATCH 187/435] Make better .DATA code generation --- src/code_generation/cil.py | 190 +++++++++++++++--------------------- src/code_generation/code.py | 5 +- 2 files changed, 78 insertions(+), 117 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index f93923ce..3f03c855 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -3,6 +3,18 @@ import code_generation.ast as cil +__DATA__ = {} + + +def add_str_data(data: str): + try: + return __DATA__[data] + except KeyError: + data_count = len(__DATA__) + 1 + __DATA__[data] = f'data_{data_count}' + return __DATA__[data] + + def ast_to_cil(ast): if type(ast) == lp_ast.ProgramNode: return program_to_cil_visitor(ast) @@ -11,9 +23,7 @@ def ast_to_cil(ast): def program_to_cil_visitor(program): types = [] - data = [] code = [] - data_count = 0 # completing .TYPE section for t in TypesByName: @@ -30,8 +40,6 @@ def program_to_cil_visitor(program): types.append(_type) - # completing .CODE and .DATA sections - """ Building main function @@ -51,55 +59,51 @@ def program_to_cil_visitor(program): cil.VCAllNode('Main', 'main', main_result)]) code.append(main_function) + # completing .CODE and .DATA sections + for c in program.classes: for f in c.feature_nodes: if type(f) == DefFuncNode: - fun = func_to_cil_visitor(c.type, f, data_count) - code.append(fun[0]) - data.append(fun[1]) - data_count += len(fun[1]) + fun = func_to_cil_visitor(c.type, f) + code.append(fun) + + data = [cil.DataNode(__DATA__[data_value], data_value) + for data_value in __DATA__.keys()] return cil.ProgramNode(types, data, code) -def func_to_cil_visitor(type_name, func, data_count): +def func_to_cil_visitor(type_name, func): name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] locals = [] body = [] - data = [] locals_count = 0 - instruction = expression_to_cil_visitor( - func.expressions, locals_count, data_count) + func.expressions, locals_count) locals += instruction.locals body += instruction.body - data += instruction.data - data_count += len(instruction.data) locals_count += len(instruction.locals) - return cil.FuncNode(name, params, locals, body), data + return cil.FuncNode(name, params, locals, body) -def expression_to_cil_visitor(expression, locals_count, data_count): +def expression_to_cil_visitor(expression, locals_count): try: - return __visitor__[type(expression)](expression, locals_count, data_count) + return __visitor__[type(expression)](expression, locals_count) except: raise Exception(f'There is no visitor for {type(expression)}') -def case_to_cil_visitor(case, locals_count, data_count): +def case_to_cil_visitor(case, locals_count): locals = [] body = [] - data = [] - expr_cil = expression_to_cil_visitor(case.expr, locals_count, data_count) + expr_cil = expression_to_cil_visitor(case.expr, locals_count) locals_count += len(expr_cil.locals) - data_count += len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body - data += expr_cil.data t = f'local_{locals_count}' locals_count += 1 locals.append(cil.LocalNode(t)) @@ -123,41 +127,35 @@ def case_to_cil_visitor(case, locals_count, data_count): body.append(cil.ConditionalGotoNode(predicate, labels[i])) body.append(cil.AssignNode(branch.id, expr_cil.value)) branch_cil = expression_to_cil_visitor( - branch.expr, locals_count, data_count) + branch.expr, locals_count) locals += branch_cil.locals body += branch_cil.body - data += branch_cil.data locals_count += len(branch_cil.locals) - data_count += len(branch_cil.data) value = branch_cil.value body.append(cil.LabelNode(labels[i])) - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def assign_to_cil_visitor(assign, locals_count, data_count): - expr = expression_to_cil_visitor(assign.expr, locals_count, data_count) +def assign_to_cil_visitor(assign, locals_count): + expr = expression_to_cil_visitor(assign.expr, locals_count) locals_count += len(expr.locals) - data_count += len(expr.data) value = [f'local_{locals_count}'] locals = expr.locals + [cil.LocalNode(value)] body = expr.body + [cil.AssignNode(assign.id, expr.value)] - return CIL_block(locals, body, value, expr.data) + return CIL_block(locals, body, value) -def arith_to_cil_visitor(arith, locals_count, data_count): - l = expression_to_cil_visitor(arith.lvalue, locals_count, data_count) +def arith_to_cil_visitor(arith, locals_count): + l = expression_to_cil_visitor(arith.lvalue, locals_count) locals_count += len(l.locals) - data_count += len(l.data) - r = expression_to_cil_visitor(arith.rvalue, locals_count, data_count) + r = expression_to_cil_visitor(arith.rvalue, locals_count) locals_count += len(r.locals) - data_count += len(r.data) cil_result = f'local_{locals_count}' locals = l.locals + r.locals + [cil.LocalNode(cil_result)] body = l.body + r.body - data = l.data + r.data if type(arith) == lp_ast.PlusNode: body.append(cil.PlusNode(l.value, r.value, cil_result)) @@ -168,23 +166,20 @@ def arith_to_cil_visitor(arith, locals_count, data_count): elif type(arith) == lp_ast.DivNode: body.append(cil.DivNode(l.value, r.value, cil_result)) - return CIL_block(locals, body, cil_result, data) + return CIL_block(locals, body, cil_result) -def if_to_cil_visitor(_if, locals_count, data_count): +def if_to_cil_visitor(_if, locals_count): predicate = expression_to_cil_visitor( - _if.if_expr, locals_count, data_count) + _if.if_expr, locals_count) locals_count += len(predicate.locals) - data_count += len(predicate.data) - then = expression_to_cil_visitor(_if.then_expr, locals_count, data_count) + then = expression_to_cil_visitor(_if.then_expr, locals_count) locals_count += len(then.locals) - data_count += len(then.data) else_expression = expression_to_cil_visitor( - _if.else_expr, locals_count, data_count) + _if.else_expr, locals_count) locals_count += len(else_expression.locals) - data_count += len(else_expression.data) label_1 = f'local_{locals_count}' label_2 = f'local_{locals_count + 1}' @@ -195,19 +190,16 @@ def if_to_cil_visitor(_if, locals_count, data_count): body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ cil.AssignNode(value, then.value), cil.LabelNode(label_2)] - data = predicate.data + then.data + else_expression.data - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def loop_to_cil_visitor(loop, locals_count, data_count): - predicate = expression_to_cil_visitor(loop.cond, locals_count, data_count) +def loop_to_cil_visitor(loop, locals_count): + predicate = expression_to_cil_visitor(loop.cond, locals_count) locals_count += len(predicate.locals) - data_count += len(predicate.data) - loop_block = expression_to_cil_visitor(loop.body, locals_count, data_count) + loop_block = expression_to_cil_visitor(loop.body, locals_count) locals_count += len(loop_block.locals) - data_count += len(loop_block.data) value = f'local_{locals_count}' @@ -218,18 +210,15 @@ def loop_to_cil_visitor(loop, locals_count, data_count): body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)] + loop_block.body + [cil.LabelNode(end_label), cil.AssignNode(value, 0)] - data = predicate.data + loop_block.data - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def equal_to_cil_visitor(equal, locals_count, data_count): - l = expression_to_cil_visitor(equal.lvalue, locals_count, data_count) +def equal_to_cil_visitor(equal, locals_count): + l = expression_to_cil_visitor(equal.lvalue, locals_count) locals_count += len(l.locals) - data_count += len(l.data) - r = expression_to_cil_visitor(equal.rvalue, locals_count, data_count) + r = expression_to_cil_visitor(equal.rvalue, locals_count) locals_count += len(r.locals) - data_count += len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -241,18 +230,15 @@ def equal_to_cil_visitor(equal, locals_count, data_count): cil.ConditionalGotoNode( cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data = l.data + r.data - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def lessthan_to_cil_visitor(lessthan, locals_count, data_count): +def lessthan_to_cil_visitor(lessthan, locals_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) locals_count += len(l.locals) - data_count += len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(r.locals) - data_count += len(r.data) cil_result = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -264,18 +250,15 @@ def lessthan_to_cil_visitor(lessthan, locals_count, data_count): cil.ConditionalGotoNode( cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data = l.data + r.data - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def lesseqthan_to_cil_visitor(lessthan, locals_count, data_count): +def lesseqthan_to_cil_visitor(lessthan, locals_count): l = expression_to_cil_visitor(lessthan.lvalue, locals_count) locals_count += len(l.locals) - data_count += len(l.data) r = expression_to_cil_visitor(lessthan.rvalue, locals_count) locals_count += len(r.locals) - data_count += len(r.data) cil_less = f'local_{locals_count}' cil_equal = f'local_{locals_count + 1}' @@ -293,86 +276,76 @@ def lesseqthan_to_cil_visitor(lessthan, locals_count, data_count): cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode( cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - data = l.data + r.data - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def integer_to_cil_visitor(integer, locals_count, data_count): +def integer_to_cil_visitor(integer, locals_count): return CIL_block([], [], integer.value) -def bool_to_cil_visitor(bool, locals_count, data_count): +def bool_to_cil_visitor(bool, locals_count): return CIL_block([], [], 1) if bool.value == 'true' else CIL_block([], [], 0) -def id_to_cil_visitor(id, locals_count, data_count): +def id_to_cil_visitor(id, locals_count): return CIL_block([], [], id.id) -def new_to_cil_visitor(new_node, locals_count, data_count): +def new_to_cil_visitor(new_node, locals_count): value = f'local_{locals_count}' locals = [cil.LocalNode(value)] locals_count += 1 body = [cil.AllocateNode(new_node.type, value)] - data = [] init_attr = TypesByName[new_node.type].get_all_attributes() for attr in init_attr: if attr.expression: attr_cil = expression_to_cil_visitor( - attr.expression, locals_count, data_count) + attr.expression, locals_count) locals_count += len(attr_cil.locals) - data_count += len(attr_cil.data) locals.append(attr_cil.locals) body.append(attr_cil.body) - data.append(attr_cil.data) body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def is_void_to_cil_visitor(isvoid, locals_count, data_count): +def is_void_to_cil_visitor(isvoid, locals_count): pass -def string_to_cil_visitor(str, locals_count, data_count): - str_addr = f'data_{data_count}' +def string_to_cil_visitor(str, locals_count): + str_addr = add_str_data(str.value) str_id = f'local_{locals_count}' locals = [cil.LocalNode(str_id)] - data = [cil.DataNode(str_addr, f"\"{str.value}\"")] body = [cil.LoadNode(str_addr, str_id)] - return CIL_block(locals, body, str_id, data) + return CIL_block(locals, body, str_id) -def let_to_cil_visitor(let, locals_count, data_count): +def let_to_cil_visitor(let, locals_count): body = [] locals = [] - data = [] for attr in let.let_attr: - attr_cil = expression_to_cil_visitor(attr, locals_count, data_count) + attr_cil = expression_to_cil_visitor(attr, locals_count) locals_count += len(attr_cil.locals) - data_count += len(attr_cil.data) body.append(cil.AssignNode(attr.id, attr_cil.value)) body += attr_cil.body locals += attr_cil.locals - data += attr_cil.data - expr_cil = expression_to_cil_visitor(let.expr, locals_count, data_count) + expr_cil = expression_to_cil_visitor(let.expr, locals_count) locals += expr_cil.locals body += expr_cil.locals - data += expr_cil.data - return CIL_block(locals, body, expr_cil.value, data) + return CIL_block(locals, body, expr_cil.value) -def logic_not_to_cil_visitor(not_node, locals_count, data_count): +def logic_not_to_cil_visitor(not_node, locals_count): expr_cil = expression_to_cil_visitor( - not_node.val, locals_count, data_count) + not_node.val, locals_count) locals_count += len(expr_cil.locals) - data_count += len(expr_cil.data) value = f'local_{locals_count}' end_label = f'local_{locals_count + 1}' @@ -381,39 +354,33 @@ def logic_not_to_cil_visitor(not_node, locals_count, data_count): body = expr_cil.body + [cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body, value, expr_cil.data) + return CIL_block(locals, body, value) -def block_to_cil_visitor(block, locals_count, data_count): +def block_to_cil_visitor(block, locals_count): locals = [] body = [] - data = [] value = None for expr in block.expressions: - expr_cil = expression_to_cil_visitor(expr, locals_count, data_count) + expr_cil = expression_to_cil_visitor(expr, locals_count) locals_count += len(expr_cil.locals) - data_count += len(expr_cil.data) locals += expr_cil.locals body += expr_cil.body - data += expr_cil.data value = expr_cil.value - return CIL_block(locals, body, value, data) + return CIL_block(locals, body, value) -def func_call_to_cil_visitor(call, locals_count, data_count): +def func_call_to_cil_visitor(call, locals_count): locals = [] body = [] - data = [] if call.object: obj_cil = expression_to_cil_visitor( - call.object, locals_count, data_count) + call.object, locals_count) locals_count += len(obj_cil.locals) - data_count += len(obj_cil.data) locals += obj_cil.locals body += obj_cil.body - data += obj_cil.data obj = obj_cil.value else: obj = 'self' @@ -421,12 +388,10 @@ def func_call_to_cil_visitor(call, locals_count, data_count): arg_values = [] for arg in call.args: - arg_cil = expression_to_cil_visitor(arg, locals_count, data_count) + arg_cil = expression_to_cil_visitor(arg, locals_count) locals_count += len(arg_cil.locals) - data_count += len(arg_cil.data) locals += arg_cil.locals body += arg_cil.body - data += arg_cil.data arg_values.append(arg_cil.value) t = f'local_{locals_count}' @@ -445,7 +410,7 @@ def func_call_to_cil_visitor(call, locals_count, data_count): else: body.append(cil.VCAllNode(call.type, call.id, result)) - return CIL_block(locals, body, result, data) + return CIL_block(locals, body, result) __visitor__ = { @@ -470,8 +435,7 @@ def func_call_to_cil_visitor(call, locals_count, data_count): class CIL_block: - def __init__(self, locals, body, value, data=[]): + def __init__(self, locals, body, value): self.locals = locals self.body = body self.value = value - self.data = data diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 6dca7bda..96b9a2e9 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -34,10 +34,7 @@ def type_cg_visitor(type: TypeNode): def data_cg_visitor(data: DataNode): - try: - return f'{data[0].id} = {data[0].val} ;' - except: - return '' + return f'{data.id} = \"{data.val}\" ;' def func_cg_visitor(func: FuncNode): From 642dbfab94a7db484e97efe9e14fe8a09aefab4f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 15:57:21 -0400 Subject: [PATCH 188/435] Make better LOCALS code generation --- src/code_generation/cil.py | 254 +++++++++++++++---------------------- 1 file changed, 102 insertions(+), 152 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 3f03c855..530d6b85 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -15,6 +15,16 @@ def add_str_data(data: str): return __DATA__[data] +__LOCALS__ = [] + + +def add_local(): + locals_count = len(__LOCALS__) + 1 + local = f'local_{locals_count}' + __LOCALS__.append(local) + return local + + def ast_to_cil(ast): if type(ast) == lp_ast.ProgramNode: return program_to_cil_visitor(ast) @@ -74,39 +84,33 @@ def program_to_cil_visitor(program): def func_to_cil_visitor(type_name, func): + global __LOCALS__ name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] - locals = [] + __LOCALS__ = [] body = [] - locals_count = 0 instruction = expression_to_cil_visitor( - func.expressions, locals_count) - locals += instruction.locals + func.expressions) body += instruction.body - locals_count += len(instruction.locals) - return cil.FuncNode(name, params, locals, body) + _locals = [cil.LocalNode(l) for l in __LOCALS__] + return cil.FuncNode(name, params, _locals, body) -def expression_to_cil_visitor(expression, locals_count): +def expression_to_cil_visitor(expression): try: - return __visitor__[type(expression)](expression, locals_count) + return __visitor__[type(expression)](expression) except: raise Exception(f'There is no visitor for {type(expression)}') -def case_to_cil_visitor(case, locals_count): - locals = [] +def case_to_cil_visitor(case): body = [] - expr_cil = expression_to_cil_visitor(case.expr, locals_count) - locals_count += len(expr_cil.locals) - locals += expr_cil.locals + expr_cil = expression_to_cil_visitor(case.expr) body += expr_cil.body - t = f'local_{locals_count}' - locals_count += 1 - locals.append(cil.LocalNode(t)) + t = add_local() body.append(cil.TypeOfNode(t, expr_cil.value)) types = [] labels = [] @@ -114,47 +118,37 @@ def case_to_cil_visitor(case, locals_count): types.append(c.type) for l in range(len(case.case_list)): - labels.append(f'local_{locals_count}') - locals_count += 1 + labels.append(add_local()) value = None for i, branch in enumerate(case.case_list): - predicate = f'local_{locals_count}' - locals_count += 1 - locals += [cil.LocalNode(predicate), cil.LocalNode(branch.id)] + predicate = add_local() body.append(cil.MinusNode(t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) body.append(cil.AssignNode(branch.id, expr_cil.value)) branch_cil = expression_to_cil_visitor( - branch.expr, locals_count) - locals += branch_cil.locals + branch.expr) body += branch_cil.body - locals_count += len(branch_cil.locals) value = branch_cil.value body.append(cil.LabelNode(labels[i])) - return CIL_block(locals, body, value) + return CIL_block(body, value) -def assign_to_cil_visitor(assign, locals_count): - expr = expression_to_cil_visitor(assign.expr, locals_count) - locals_count += len(expr.locals) - value = [f'local_{locals_count}'] - locals = expr.locals + [cil.LocalNode(value)] +def assign_to_cil_visitor(assign): + expr = expression_to_cil_visitor(assign.expr) + value = [add_local()] body = expr.body + [cil.AssignNode(assign.id, expr.value)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def arith_to_cil_visitor(arith, locals_count): - l = expression_to_cil_visitor(arith.lvalue, locals_count) - locals_count += len(l.locals) - r = expression_to_cil_visitor(arith.rvalue, locals_count) - locals_count += len(r.locals) +def arith_to_cil_visitor(arith): + l = expression_to_cil_visitor(arith.lvalue) + r = expression_to_cil_visitor(arith.rvalue) - cil_result = f'local_{locals_count}' + cil_result = add_local() - locals = l.locals + r.locals + [cil.LocalNode(cil_result)] body = l.body + r.body if type(arith) == lp_ast.PlusNode: @@ -166,109 +160,87 @@ def arith_to_cil_visitor(arith, locals_count): elif type(arith) == lp_ast.DivNode: body.append(cil.DivNode(l.value, r.value, cil_result)) - return CIL_block(locals, body, cil_result) + return CIL_block(body, cil_result) -def if_to_cil_visitor(_if, locals_count): +def if_to_cil_visitor(_if): predicate = expression_to_cil_visitor( - _if.if_expr, locals_count) - locals_count += len(predicate.locals) + _if.if_expr) - then = expression_to_cil_visitor(_if.then_expr, locals_count) - locals_count += len(then.locals) + then = expression_to_cil_visitor(_if.then_expr) else_expression = expression_to_cil_visitor( - _if.else_expr, locals_count) - locals_count += len(else_expression.locals) + _if.else_expr) - label_1 = f'local_{locals_count}' - label_2 = f'local_{locals_count + 1}' - value = f'local_{locals_count + 2}' + label_1 = add_local() + label_2 = add_local() + value = add_local() - locals = predicate.locals + then.locals + \ - else_expression.locals + [cil.LocalNode(value)] body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ cil.AssignNode(value, then.value), cil.LabelNode(label_2)] - return CIL_block(locals, body, value) - + return CIL_block(body, value) -def loop_to_cil_visitor(loop, locals_count): - predicate = expression_to_cil_visitor(loop.cond, locals_count) - locals_count += len(predicate.locals) - loop_block = expression_to_cil_visitor(loop.body, locals_count) - locals_count += len(loop_block.locals) +def loop_to_cil_visitor(loop): + predicate = expression_to_cil_visitor(loop.cond) - value = f'local_{locals_count}' + loop_block = expression_to_cil_visitor(loop.body) - locals = predicate.locals + loop_block.locals + [cil.LocalNode(value)] + value = add_local() - loop_label = f'local_{locals_count + 1}' - end_label = f'local_{locals_count + 2}' + loop_label = add_local() + end_label = add_local() body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)] + loop_block.body + [cil.LabelNode(end_label), cil.AssignNode(value, 0)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def equal_to_cil_visitor(equal, locals_count): - l = expression_to_cil_visitor(equal.lvalue, locals_count) - locals_count += len(l.locals) - r = expression_to_cil_visitor(equal.rvalue, locals_count) - locals_count += len(r.locals) +def equal_to_cil_visitor(equal): + l = expression_to_cil_visitor(equal.lvalue) + r = expression_to_cil_visitor(equal.rvalue) - cil_result = f'local_{locals_count}' - end_label = f'local_{locals_count + 1}' - value = f'local_{locals_count + 2}' + cil_result = add_local() + end_label = add_local() + value = add_local() - locals = l.locals + r.locals + \ - [cil.LocalNode(cil_result), cil.LocalNode(value)] body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), cil.ConditionalGotoNode( cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def lessthan_to_cil_visitor(lessthan, locals_count): - l = expression_to_cil_visitor(lessthan.lvalue, locals_count) - locals_count += len(l.locals) - r = expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count += len(r.locals) +def lessthan_to_cil_visitor(lessthan): + l = expression_to_cil_visitor(lessthan.lvalue) + r = expression_to_cil_visitor(lessthan.rvalue) - cil_result = f'local_{locals_count}' - end_label = f'local_{locals_count + 1}' - value = f'local_{locals_count + 2}' + cil_result = add_local() + end_label = add_local() + value = add_local() - locals = l.locals + r.locals + \ - [cil.LocalNode(cil_result), cil.LocalNode(value)] body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), cil.ConditionalGotoNode( cil_result, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def lesseqthan_to_cil_visitor(lessthan, locals_count): - l = expression_to_cil_visitor(lessthan.lvalue, locals_count) - locals_count += len(l.locals) - r = expression_to_cil_visitor(lessthan.rvalue, locals_count) - locals_count += len(r.locals) +def lesseqthan_to_cil_visitor(lessthan): + l = expression_to_cil_visitor(lessthan.lvalue) + r = expression_to_cil_visitor(lessthan.rvalue) - cil_less = f'local_{locals_count}' - cil_equal = f'local_{locals_count + 1}' - eq_label = f'local_{locals_count + 2}' - end_label = f'local_{locals_count + 3}' - value = f'local_{locals_count + 4}' + cil_less = add_local() + cil_equal = add_local() + eq_label = add_local() + end_label = add_local() + value = add_local() - locals = l.locals + r.locals + \ - [cil.LocalNode(cil_less), cil.LocalNode( - cil_equal), cil.LocalNode(value)] body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), cil.ConditionalGotoNode( cil_less, eq_label), cil.AssignNode(value, 1), @@ -277,109 +249,92 @@ def lesseqthan_to_cil_visitor(lessthan, locals_count): cil_equal, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def integer_to_cil_visitor(integer, locals_count): +def integer_to_cil_visitor(integer): return CIL_block([], [], integer.value) -def bool_to_cil_visitor(bool, locals_count): +def bool_to_cil_visitor(bool): return CIL_block([], [], 1) if bool.value == 'true' else CIL_block([], [], 0) -def id_to_cil_visitor(id, locals_count): +def id_to_cil_visitor(id): return CIL_block([], [], id.id) -def new_to_cil_visitor(new_node, locals_count): - value = f'local_{locals_count}' - locals = [cil.LocalNode(value)] - locals_count += 1 +def new_to_cil_visitor(new_node): + value = add_local() body = [cil.AllocateNode(new_node.type, value)] init_attr = TypesByName[new_node.type].get_all_attributes() for attr in init_attr: if attr.expression: attr_cil = expression_to_cil_visitor( - attr.expression, locals_count) - locals_count += len(attr_cil.locals) - locals.append(attr_cil.locals) + attr.expression) body.append(attr_cil.body) body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) - return CIL_block(locals, body, value) + return CIL_block(body, value) -def is_void_to_cil_visitor(isvoid, locals_count): +def is_void_to_cil_visitor(isvoid): pass -def string_to_cil_visitor(str, locals_count): +def string_to_cil_visitor(str): str_addr = add_str_data(str.value) - str_id = f'local_{locals_count}' + str_id = add_local() - locals = [cil.LocalNode(str_id)] body = [cil.LoadNode(str_addr, str_id)] - return CIL_block(locals, body, str_id) + return CIL_block(body, str_id) -def let_to_cil_visitor(let, locals_count): +def let_to_cil_visitor(let): body = [] - locals = [] for attr in let.let_attr: - attr_cil = expression_to_cil_visitor(attr, locals_count) - locals_count += len(attr_cil.locals) + attr_cil = expression_to_cil_visitor(attr) body.append(cil.AssignNode(attr.id, attr_cil.value)) body += attr_cil.body - locals += attr_cil.locals - expr_cil = expression_to_cil_visitor(let.expr, locals_count) - locals += expr_cil.locals - body += expr_cil.locals + expr_cil = expression_to_cil_visitor(let.expr) + body += expr_cil.body - return CIL_block(locals, body, expr_cil.value) + return CIL_block(body, expr_cil.value) -def logic_not_to_cil_visitor(not_node, locals_count): +def logic_not_to_cil_visitor(not_node): expr_cil = expression_to_cil_visitor( - not_node.val, locals_count) - locals_count += len(expr_cil.locals) + not_node.val) - value = f'local_{locals_count}' - end_label = f'local_{locals_count + 1}' + value = add_local() + end_label = add_local() - locals = expr_cil.locals + [cil.LocalNode(value)] body = expr_cil.body + [cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] - return CIL_block(locals, body, value) + return CIL_block(body, value) -def block_to_cil_visitor(block, locals_count): - locals = [] +def block_to_cil_visitor(block): body = [] value = None for expr in block.expressions: - expr_cil = expression_to_cil_visitor(expr, locals_count) - locals_count += len(expr_cil.locals) - locals += expr_cil.locals + expr_cil = expression_to_cil_visitor(expr) body += expr_cil.body value = expr_cil.value - return CIL_block(locals, body, value) + return CIL_block(body, value) -def func_call_to_cil_visitor(call, locals_count): - locals = [] +def func_call_to_cil_visitor(call): body = [] if call.object: obj_cil = expression_to_cil_visitor( - call.object, locals_count) - locals_count += len(obj_cil.locals) - locals += obj_cil.locals + call.object) body += obj_cil.body obj = obj_cil.value else: @@ -388,14 +343,11 @@ def func_call_to_cil_visitor(call, locals_count): arg_values = [] for arg in call.args: - arg_cil = expression_to_cil_visitor(arg, locals_count) - locals_count += len(arg_cil.locals) - locals += arg_cil.locals + arg_cil = expression_to_cil_visitor(arg) body += arg_cil.body arg_values.append(arg_cil.value) - t = f'local_{locals_count}' - locals.append(cil.LocalNode(t)) + t = add_local() body.append(cil.TypeOfNode(t, obj)) body.append(cil.ArgNode(obj)) @@ -403,14 +355,13 @@ def func_call_to_cil_visitor(call, locals_count): for arg in arg_values: body.append(cil.ArgNode(arg)) - result = f'local_{locals_count + 1}' - locals.append(cil.LocalNode(result)) + result = add_local() if not call.type: body.append(cil.VCAllNode(t, call.id, result)) else: body.append(cil.VCAllNode(call.type, call.id, result)) - return CIL_block(locals, body, result) + return CIL_block(body, result) __visitor__ = { @@ -435,7 +386,6 @@ def func_call_to_cil_visitor(call, locals_count): class CIL_block: - def __init__(self, locals, body, value): - self.locals = locals + def __init__(self, body, value): self.body = body self.value = value From f8b37e1e33d824ac51afb81dd19f911cb8183b82 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 16:04:22 -0400 Subject: [PATCH 189/435] Sort imports --- src/code_generation/cil.py | 3 +-- src/main.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 530d6b85..8c412a38 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,7 +1,6 @@ +import code_generation.ast as cil import lexer_parser.ast as lp_ast from semantic.types import * -import code_generation.ast as cil - __DATA__ = {} diff --git a/src/main.py b/src/main.py index 38939c94..55f79103 100644 --- a/src/main.py +++ b/src/main.py @@ -1,9 +1,9 @@ import sys import errors as err +from code_generation import generate_code from lexer_parser import lexer, parser from semantic import semantic_check -from code_generation import generate_code def exit_with_error(error): From 47becbf8c2db0e24a0bd43876e4612983b57e87e Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 16:22:39 -0400 Subject: [PATCH 190/435] Change __LOCALS__ for locals_count --- src/code_generation/cil.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 8c412a38..120d09b8 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -14,14 +14,13 @@ def add_str_data(data: str): return __DATA__[data] -__LOCALS__ = [] +locals_count = 0 def add_local(): - locals_count = len(__LOCALS__) + 1 - local = f'local_{locals_count}' - __LOCALS__.append(local) - return local + global locals_count + locals_count += 1 + return f'local_{locals_count}' def ast_to_cil(ast): @@ -83,18 +82,18 @@ def program_to_cil_visitor(program): def func_to_cil_visitor(type_name, func): - global __LOCALS__ + global locals_count name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] - __LOCALS__ = [] + locals_count = 0 body = [] instruction = expression_to_cil_visitor( func.expressions) body += instruction.body - _locals = [cil.LocalNode(l) for l in __LOCALS__] + _locals = [cil.LocalNode(f'local_{i}') for i in range(locals_count)] return cil.FuncNode(name, params, _locals, body) From 71295e7d52c75463f43c1ae17bfba2f442790c92 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 6 May 2020 16:34:08 -0400 Subject: [PATCH 191/435] Fix bug --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 120d09b8..92eeabc9 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -93,7 +93,7 @@ def func_to_cil_visitor(type_name, func): func.expressions) body += instruction.body - _locals = [cil.LocalNode(f'local_{i}') for i in range(locals_count)] + _locals = [cil.LocalNode(f'local_{i + 1}') for i in range(locals_count)] return cil.FuncNode(name, params, _locals, body) From f7a4e72f75f56feda26168ad97dd39497b45096d Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Thu, 7 May 2020 13:48:36 -0400 Subject: [PATCH 192/435] Add 'isvoid' and 'bitwise not' to cil visitors Others: *Fix bug on CIL_block of basics types cil visitors *Remove SELF_TYPE from cil code --- src/code_generation/ast.py | 4 ++++ src/code_generation/cil.py | 37 +++++++++++++++++++++++++++++++------ src/code_generation/code.py | 2 ++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index e42d863a..cc479d39 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -72,6 +72,10 @@ class StarNode(ArithNode): class DivNode(ArithNode): pass +class NotNode(Node): + def __init__(self, value, result): + self.value = value + self.result = result class GetAttrNode(InstructionNode): def __init__(self, obj, attr, result): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 92eeabc9..d4373f50 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -115,7 +115,7 @@ def case_to_cil_visitor(case): for c in case.case_list: types.append(c.type) - for l in range(len(case.case_list)): + for _ in range(len(case.case_list)): labels.append(add_local()) value = None @@ -251,15 +251,15 @@ def lesseqthan_to_cil_visitor(lessthan): def integer_to_cil_visitor(integer): - return CIL_block([], [], integer.value) + return CIL_block([], integer.value) def bool_to_cil_visitor(bool): - return CIL_block([], [], 1) if bool.value == 'true' else CIL_block([], [], 0) + return CIL_block([], 1) if bool.value == 'true' else CIL_block([], 0) def id_to_cil_visitor(id): - return CIL_block([], [], id.id) + return CIL_block([], id.id) def new_to_cil_visitor(new_node): @@ -278,7 +278,19 @@ def new_to_cil_visitor(new_node): def is_void_to_cil_visitor(isvoid): - pass + expr_cil = expression_to_cil_visitor( + isvoid.val) + + body = expr_cil.body + + value = add_local() + + if expr_cil.value is None: + body.append(cil.AssignNode(value, 1)) + else: + body.append(cil.AssignNode(value, 0)) + + return CIL_block(body, value) def string_to_cil_visitor(str): @@ -316,6 +328,17 @@ def logic_not_to_cil_visitor(not_node): return CIL_block(body, value) +def not_to_cil_visitor(not_node): + expr_cil = expression_to_cil_visitor( + not_node.val) + + value = add_local() + + body = expr_cil.body + [cil.NotNode(expr_cil.value, value)] + + return CIL_block(body, value) + + def block_to_cil_visitor(block): body = [] value = None @@ -379,7 +402,9 @@ def func_call_to_cil_visitor(call): lp_ast.StarNode: arith_to_cil_visitor, lp_ast.DivNode: arith_to_cil_visitor, lp_ast.VarNode: id_to_cil_visitor, - lp_ast.FuncCallNode: func_call_to_cil_visitor + lp_ast.FuncCallNode: func_call_to_cil_visitor, + lp_ast.IsVoidNode: is_void_to_cil_visitor, + lp_ast.NegationNode: not_to_cil_visitor } diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 96b9a2e9..f10a6c18 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -12,6 +12,8 @@ def program_cg_visitor(program: ProgramNode): data_code = '' func_code = '' for t in program.types: + if t == 'SELF_TYPE': + continue type_code += f'{type_cg_visitor(t)}\n' for d in program.data: data_code += f'{data_cg_visitor(d)}\n' From eb2cf8db7e2952c143213fba8b69973e81c584df Mon Sep 17 00:00:00 2001 From: ericmg97 Date: Thu, 7 May 2020 13:58:10 -0400 Subject: [PATCH 193/435] Change isvoid behavior --- src/code_generation/cil.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index d4373f50..3b49f591 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -283,14 +283,7 @@ def is_void_to_cil_visitor(isvoid): body = expr_cil.body - value = add_local() - - if expr_cil.value is None: - body.append(cil.AssignNode(value, 1)) - else: - body.append(cil.AssignNode(value, 0)) - - return CIL_block(body, value) + return CIL_block(body, 1) if expr_cil.value is None else CIL_block(body, 0) def string_to_cil_visitor(str): From f28e46c95eb219507264f82e5345b38c987b79ac Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 8 May 2020 14:41:10 -0400 Subject: [PATCH 194/435] Add .cil extension to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a3375b1..d231c54d 100644 --- a/.gitignore +++ b/.gitignore @@ -410,3 +410,4 @@ dmypy.json .idea .vscode +*.cil From b1d70b7e2510a55de4d9baa6c6b03f33455e906c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 8 May 2020 14:57:04 -0400 Subject: [PATCH 195/435] Add tab to attribute code generation --- src/code_generation/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index f10a6c18..19d5cede 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -27,7 +27,7 @@ def type_cg_visitor(type: TypeNode): attr_code = '' method_code = '' for attr in type.attributes: - attr_code += f'attribute {attr};\n' + attr_code += f'\tattribute {attr};\n' for name in type.methods: method_code += f'\tmethod {name}:{type.methods[name]}_{name};\n' From 624dbc7e5b862a01cb502eb4d4072341deaa17bb Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 8 May 2020 19:13:19 -0400 Subject: [PATCH 196/435] Fix bug --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 3b49f591..19543884 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -297,7 +297,7 @@ def string_to_cil_visitor(str): def let_to_cil_visitor(let): body = [] - for attr in let.let_attr: + for attr in let.let_attrs: attr_cil = expression_to_cil_visitor(attr) body.append(cil.AssignNode(attr.id, attr_cil.value)) body += attr_cil.body From 29ac41783883ae5708e298891023686eccbedd26 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 9 May 2020 10:03:35 -0400 Subject: [PATCH 197/435] Fix parser bug Change the precedence of ASSIGN. ASSIGN must be at the top --- src/lexer_parser/parser.py | 2 +- src/lexer_parser/parsetab.py | 114 +++++++++++++++++------------------ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index bb9f7570..cde3ed37 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -5,6 +5,7 @@ from .lexer import * precedence = ( + ('right', 'ASSIGN'), ('left', 'DOT'), ('left', 'AT'), ('left', 'NOT'), @@ -13,7 +14,6 @@ ('left', 'PLUS', 'MINUS'), ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'LNOT'), - ('right', 'ASSIGN'), ) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 31fa1724..78ba068a 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'rightASSIGNleftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,-22,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,-22,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,-22,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,-22,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,-22,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,-22,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,-22,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,-22,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,-22,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): @@ -27,59 +27,59 @@ del _lr_goto_items _lr_productions = [ ("S' -> program","S'",1,None,None,None), - ('program -> class_list','program',1,'p_program','parser.py',20), - ('empty -> ','empty',0,'p_empty','parser.py',25), - ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',30), - ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), - ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), - ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), - ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), - ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), - ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), - ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',59), - ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',60), - ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',68), - ('params -> param_list','params',1,'p_params_ne','parser.py',73), - ('params -> empty','params',1,'p_params_e','parser.py',78), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',83), - ('param_list -> param empty','param_list',2,'p_param_list','parser.py',84), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',92), - ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',97), - ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',98), - ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',99), - ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',100), - ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',113), - ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',118), - ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',119), - ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',120), - ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',130), - ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',131), - ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',132), - ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',133), - ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',134), - ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',135), - ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',136), - ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',154), - ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',155), - ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',156), - ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',166), - ('expr -> atom','expr',1,'p_expr_atom','parser.py',171), - ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',176), - ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',177), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',185), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',186), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',194), - ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',199), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',200), - ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',205), - ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',206), - ('atom -> INT','atom',1,'p_atom_int','parser.py',214), - ('atom -> ID','atom',1,'p_atom_id','parser.py',219), - ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',224), - ('atom -> block','atom',1,'p_atom_block','parser.py',229), - ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',234), - ('atom -> STRING','atom',1,'p_atom_atring','parser.py',239), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',244), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',249), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',250), + ('program -> class_list','program',1,'p_program','parser.py',21), + ('empty -> ','empty',0,'p_empty','parser.py',26), + ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',31), + ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',32), + ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',41), + ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',42), + ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',52), + ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',53), + ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',54), + ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',62), + ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',63), + ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',73), + ('params -> param_list','params',1,'p_params_ne','parser.py',79), + ('params -> empty','params',1,'p_params_e','parser.py',84), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',89), + ('param_list -> param empty','param_list',2,'p_param_list','parser.py',90), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',98), + ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',104), + ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',105), + ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',106), + ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',107), + ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',122), + ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',128), + ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',129), + ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',130), + ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',151), + ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',152), + ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',153), + ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',154), + ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',155), + ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',156), + ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',157), + ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',177), + ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',178), + ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',179), + ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',191), + ('expr -> atom','expr',1,'p_expr_atom','parser.py',196), + ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',201), + ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',202), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',210), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',211), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',219), + ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',225), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',226), + ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',231), + ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',232), + ('atom -> INT','atom',1,'p_atom_int','parser.py',240), + ('atom -> ID','atom',1,'p_atom_id','parser.py',246), + ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',252), + ('atom -> block','atom',1,'p_atom_block','parser.py',258), + ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',263), + ('atom -> STRING','atom',1,'p_atom_atring','parser.py',269), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',275), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',280), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',281), ] From 5af0826bd20e587d811a128d843972baa3da60e2 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 9 May 2020 11:02:24 -0400 Subject: [PATCH 198/435] Optimize DATA_LOCALS in function body --- src/code_generation/cil.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 19543884..6b1260d2 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -29,6 +29,18 @@ def ast_to_cil(ast): raise Exception(f'AST root must be program') +__DATA_LOCALS__ = {} + + +def add_data_local(string_addr): + try: + return __DATA_LOCALS__[string_addr], False + except KeyError: + local_data = add_local() + __DATA_LOCALS__[string_addr] = local_data + return local_data, True + + def program_to_cil_visitor(program): types = [] code = [] @@ -82,11 +94,12 @@ def program_to_cil_visitor(program): def func_to_cil_visitor(type_name, func): - global locals_count + global locals_count, __DATA_LOCALS__ name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] locals_count = 0 + __DATA_LOCALS__ = {} body = [] instruction = expression_to_cil_visitor( @@ -280,7 +293,7 @@ def new_to_cil_visitor(new_node): def is_void_to_cil_visitor(isvoid): expr_cil = expression_to_cil_visitor( isvoid.val) - + body = expr_cil.body return CIL_block(body, 1) if expr_cil.value is None else CIL_block(body, 0) @@ -288,9 +301,12 @@ def is_void_to_cil_visitor(isvoid): def string_to_cil_visitor(str): str_addr = add_str_data(str.value) - str_id = add_local() + str_id, need_load = add_data_local(str_addr) - body = [cil.LoadNode(str_addr, str_id)] + if need_load: + body = [cil.LoadNode(str_addr, str_id)] + else: + body = [] return CIL_block(body, str_id) From ce4e4ff85b674f68f92aab038c79ff22cfc645ce Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 9 May 2020 12:06:21 -0400 Subject: [PATCH 199/435] Optimize TYPEOF in function body --- src/code_generation/cil.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 6b1260d2..a83200b4 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -41,6 +41,18 @@ def add_data_local(string_addr): return local_data, True +__TYPEOF__ = {} + + +def get_typeof(obj): + try: + return __TYPEOF__[obj], False + except KeyError: + type_local = add_local() + __TYPEOF__[obj] = type_local + return type_local, True + + def program_to_cil_visitor(program): types = [] code = [] @@ -94,12 +106,13 @@ def program_to_cil_visitor(program): def func_to_cil_visitor(type_name, func): - global locals_count, __DATA_LOCALS__ + global locals_count, __DATA_LOCALS__, __TYPEOF__ name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] locals_count = 0 __DATA_LOCALS__ = {} + __TYPEOF__ = {} body = [] instruction = expression_to_cil_visitor( @@ -377,8 +390,9 @@ def func_call_to_cil_visitor(call): body += arg_cil.body arg_values.append(arg_cil.value) - t = add_local() - body.append(cil.TypeOfNode(t, obj)) + t, need_typeof = get_typeof(obj) + if need_typeof: + body.append(cil.TypeOfNode(t, obj)) body.append(cil.ArgNode(obj)) From 8dcffd1efa0f6a85b044e8220f9ab88a48f68ada Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:07:47 -0400 Subject: [PATCH 200/435] out_int and out_string to cil --- src/code_generation/cil.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index a83200b4..5372afe8 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -104,6 +104,17 @@ def program_to_cil_visitor(program): return cil.ProgramNode(types, data, code) +def built_in_to_cil(): + pass + +def out_string_to_cil(): + return cil.FuncNode('out_string_IO', ['self','str'], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + +def out_int_to_cil(): + return cil.FuncNode('out_int_IO', ['self','int'], ['str'], cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')) + + + def func_to_cil_visitor(type_name, func): global locals_count, __DATA_LOCALS__, __TYPEOF__ From b694abd56c0369e1cacf21ee7989a855c4f1a950 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:15:34 -0400 Subject: [PATCH 201/435] adding in_string_to_cil and fixing read in ast --- src/code_generation/ast.py | 4 +++- src/code_generation/cil.py | 5 +++-- src/code_generation/code.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index cc479d39..63401326 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -195,7 +195,9 @@ def __init__(self, val, str): class ReadNode(InstructionNode): - pass + def __init__(self, val): + self.val=val + class PrintNode(InstructionNode): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 5372afe8..7bed5590 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -111,9 +111,10 @@ def out_string_to_cil(): return cil.FuncNode('out_string_IO', ['self','str'], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) def out_int_to_cil(): - return cil.FuncNode('out_int_IO', ['self','int'], ['str'], cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')) - + return cil.FuncNode('out_int_IO', ['self','int'], ['str'], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) +def in_string_to_cil(): + return cil.FuncNode('in_string_IO', ['self'], ['str'], [cil.ReadNode('str'), cil.ReturnNode('str')]) def func_to_cil_visitor(type_name, func): diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 19d5cede..3ab12aa2 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -167,7 +167,7 @@ def str_cg_visitor(str: StrNode): def read_cg_visitor(read: ReadNode): - return 'READ ;' + return f'{read.val} = READ ;' def print_cg_visitor(print: PrintNode): From 51a50becb81666caced3080072bd0687e34de934 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:19:44 -0400 Subject: [PATCH 202/435] fixing ups --- src/code_generation/cil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 7bed5590..ef904e23 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -108,13 +108,13 @@ def built_in_to_cil(): pass def out_string_to_cil(): - return cil.FuncNode('out_string_IO', ['self','str'], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + return cil.FuncNode('out_string_IO', [cil.ParamNode('self'),cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) def out_int_to_cil(): - return cil.FuncNode('out_int_IO', ['self','int'], ['str'], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) + return cil.FuncNode('out_int_IO', [cil.ParamNode('self'),cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) def in_string_to_cil(): - return cil.FuncNode('in_string_IO', ['self'], ['str'], [cil.ReadNode('str'), cil.ReturnNode('str')]) + return cil.FuncNode('in_string_IO', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) def func_to_cil_visitor(type_name, func): From 0d315949d007e0912f664564e665cc16d8529029 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:46:39 -0400 Subject: [PATCH 203/435] adding string built in functions --- src/code_generation/ast.py | 7 ++++--- src/code_generation/cil.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 63401326..3e72f9ca 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -182,10 +182,11 @@ def __init__(self, str_a, str_b, result): class SubStringNode(InstructionNode): - def __init__(self, str_a, str_b, result): + def __init__(self,str, i, len, result): self.result = result - self.str_a = str_a - self.str_b = str_b + self.i = i + self.len = len + self.str=str class StrNode(InstructionNode): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ef904e23..7ca137be 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -116,6 +116,23 @@ def out_int_to_cil(): def in_string_to_cil(): return cil.FuncNode('in_string_IO', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) +def in_int_to_cil(): + pass + +def type_name_to_cil(): + pass + +def copy_to_cil(): + pass + +def length_to_cil(): + return cil.FuncNode('length_String', [cil.ParamNode('self')], [cil.LocalNode('result')], [cil.LengthNode('self', 'result'), cil.ReturnNode('result')]) + +def concat_to_cil(): + return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [cil.LocalNode('result')], [cil.ConcatNode('x', 'self', 'result'), cil.ReturnNode('result')]) + +def substring_to_cil(): + return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'),cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l','result'), cil.ReturnNode('result')]) def func_to_cil_visitor(type_name, func): global locals_count, __DATA_LOCALS__, __TYPEOF__ From 701e873aee1a98e5511b09089e6a73fd0ff86df1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:47:36 -0400 Subject: [PATCH 204/435] fixing misplaced argument --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 7ca137be..7f28bfda 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -129,7 +129,7 @@ def length_to_cil(): return cil.FuncNode('length_String', [cil.ParamNode('self')], [cil.LocalNode('result')], [cil.LengthNode('self', 'result'), cil.ReturnNode('result')]) def concat_to_cil(): - return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [cil.LocalNode('result')], [cil.ConcatNode('x', 'self', 'result'), cil.ReturnNode('result')]) + return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [cil.LocalNode('result')], [cil.ConcatNode('self', 'x', 'result'), cil.ReturnNode('result')]) def substring_to_cil(): return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'),cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l','result'), cil.ReturnNode('result')]) From e11c6f380aa6b39f304aa7b75d19c2f66b8066e5 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:49:23 -0400 Subject: [PATCH 205/435] adding return statement to func declaration --- src/code_generation/cil.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 7f28bfda..05dd8204 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -147,6 +147,8 @@ def func_to_cil_visitor(type_name, func): instruction = expression_to_cil_visitor( func.expressions) body += instruction.body + + body.append([cil.ReturnNode(instruction.value)]) _locals = [cil.LocalNode(f'local_{i + 1}') for i in range(locals_count)] return cil.FuncNode(name, params, _locals, body) From 41836623f0de38cbd371fd693309176f4633ae52 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:52:09 -0400 Subject: [PATCH 206/435] fixing is_void --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 05dd8204..16c825d6 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -340,7 +340,7 @@ def is_void_to_cil_visitor(isvoid): body = expr_cil.body - return CIL_block(body, 1) if expr_cil.value is None else CIL_block(body, 0) + return CIL_block(body, 1) if expr_cil.value==0 else CIL_block(body, 0) def string_to_cil_visitor(str): From 2acb8a4d02cd55d5a72a23766414050903beee21 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 17:52:37 -0400 Subject: [PATCH 207/435] refixing is_void --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 16c825d6..2d4b3f48 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -340,7 +340,7 @@ def is_void_to_cil_visitor(isvoid): body = expr_cil.body - return CIL_block(body, 1) if expr_cil.value==0 else CIL_block(body, 0) + return CIL_block(body, 1) if not expr_cil.value else CIL_block(body, 0) def string_to_cil_visitor(str): From 10911addf97981328680f8828c3934a1c84ddda5 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 19 May 2020 18:13:18 -0400 Subject: [PATCH 208/435] Fixing self_type initialization --- src/code_generation/cil.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 2d4b3f48..ee80e1d7 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -321,8 +321,16 @@ def id_to_cil_visitor(id): def new_to_cil_visitor(new_node): value = add_local() - body = [cil.AllocateNode(new_node.type, value)] - init_attr = TypesByName[new_node.type].get_all_attributes() + t=new_node.type + body=[] + + if t=='SELF_TYPE': + t, need_typeof=get_typeof(t,'self') + if need_typeof: + body.append(cil.TypeOfNode(t,'self')) + + body.append(cil.AllocateNode(t, value)) + init_attr = TypesByName[t].get_all_attributes() for attr in init_attr: if attr.expression: From e203430d9b8425436db00943315bb9a74558cbb4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 10:11:05 -0400 Subject: [PATCH 209/435] Fix bug: Bad type comparison with SELF_TYPE --- src/code_generation/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 3ab12aa2..812471b6 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -12,7 +12,7 @@ def program_cg_visitor(program: ProgramNode): data_code = '' func_code = '' for t in program.types: - if t == 'SELF_TYPE': + if t.type == 'SELF_TYPE': continue type_code += f'{type_cg_visitor(t)}\n' for d in program.data: From c51dd3b97a44b85fcad329311d22948d617e555b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 20 May 2020 15:37:03 -0400 Subject: [PATCH 210/435] fix some bugs --- src/code_generation/cil.py | 23 +++++++++++++---------- src/code_generation/code.py | 1 + src/lexer_parser/parsetab.py | 5 ++--- src/semantic/types.py | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ee80e1d7..ca2058af 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -98,6 +98,8 @@ def program_to_cil_visitor(program): if type(f) == DefFuncNode: fun = func_to_cil_visitor(c.type, f) code.append(fun) + + code += built_in_to_cil() data = [cil.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] @@ -105,16 +107,16 @@ def program_to_cil_visitor(program): return cil.ProgramNode(types, data, code) def built_in_to_cil(): - pass + return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil()] def out_string_to_cil(): - return cil.FuncNode('out_string_IO', [cil.ParamNode('self'),cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + return cil.FuncNode('IO_out_string', [cil.ParamNode('self'),cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) def out_int_to_cil(): - return cil.FuncNode('out_int_IO', [cil.ParamNode('self'),cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) + return cil.FuncNode('IO_out_int', [cil.ParamNode('self'),cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) def in_string_to_cil(): - return cil.FuncNode('in_string_IO', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) + return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) def in_int_to_cil(): pass @@ -148,17 +150,17 @@ def func_to_cil_visitor(type_name, func): func.expressions) body += instruction.body - body.append([cil.ReturnNode(instruction.value)]) + body.append(cil.ReturnNode(instruction.value)) _locals = [cil.LocalNode(f'local_{i + 1}') for i in range(locals_count)] return cil.FuncNode(name, params, _locals, body) def expression_to_cil_visitor(expression): - try: - return __visitor__[type(expression)](expression) - except: - raise Exception(f'There is no visitor for {type(expression)}') + #try: + return __visitor__[type(expression)](expression) + #except: + #raise Exception(f'There is no visitor for {type(expression)}') def case_to_cil_visitor(case): @@ -331,12 +333,13 @@ def new_to_cil_visitor(new_node): body.append(cil.AllocateNode(t, value)) init_attr = TypesByName[t].get_all_attributes() + for attr in init_attr: if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) - body.append(attr_cil.body) + body+=attr_cil.body body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) return CIL_block(body, value) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 812471b6..1e84fb4b 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -67,6 +67,7 @@ def instruction_cg_visitor(instruction: InstructionNode): try: return __visitors__[type(instruction)](instruction) except KeyError: + print(type(instruction)) print(f'Not visitor for {instruction}') diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 78ba068a..58004abe 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'rightASSIGNleftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'AF2A4CDADBB08353B4A5F014A33FBCF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} diff --git a/src/semantic/types.py b/src/semantic/types.py index 10082a57..db79d2bc 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -37,7 +37,7 @@ def get_all_attributes(self): result = [] while t: temp = [] - for attr in t.attributes: + for attr in t.attributes.values(): temp.append(attr) result.append(temp) t = t.parent From 249936b4e7ba9439b337bb6b186f4239b842de81 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 15:42:09 -0400 Subject: [PATCH 211/435] Fixed return SELF type error If a function is called by .function (), then the static type of SELFTYPE inside function is the static type of --- src/semantic/semantic.py | 80 +++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index bb009704..0f54c884 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -24,7 +24,8 @@ def program_visitor(program: ProgramNode): for f in c.feature_nodes: if type(f) is DefFuncNode: param_types = [param[1] for param in f.params] - result, msg = classType.add_method(f.id, param_types, f.return_type) + result, msg = classType.add_method( + f.id, param_types, f.return_type) if not result: add_semantic_error(f.lineno, f.colno, msg) elif type(f) is DefAttrNode: @@ -55,7 +56,8 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco expr_type = expression_visitor(attr.expr, current_class, {}) attr_type = type_by_name(attr.type) if attr_type is not None and not check_inherits(expr_type, attr_type): - add_semantic_error(attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') + add_semantic_error( + attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') else: return attr_type @@ -63,9 +65,11 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): id_type = type_by_name(def_attr.type) if id_type is None: - add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') + add_semantic_error(def_attr.lineno, def_attr.colno, + f'unknown type \'{def_attr.type}\'') if def_attr.expr: - expr_type = expression_visitor(def_attr.expr, current_class, local_scope) + expr_type = expression_visitor( + def_attr.expr, current_class, local_scope) if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(def_attr.lineno, def_attr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') @@ -76,14 +80,16 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope local_scope = local_scope.copy() for arg in function.params: local_scope[arg[0]] = type_by_name(arg[1]) - body_type = expression_visitor(function.expressions, current_class, local_scope) + body_type = expression_visitor( + function.expressions, current_class, local_scope) return_type = type_by_name(function.return_type) if return_type == SelfType: return_type = current_class if check_inherits(body_type, return_type): return return_type elif body_type is not None: - add_semantic_error(function.lineno, function.colno, f'invalid returned type \'{function.return_type}\'') + add_semantic_error(function.lineno, function.colno, + f'invalid returned type \'{function.return_type}\'') def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: dict): @@ -92,7 +98,8 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: except KeyError: attr, _ = get_attribute(current_class, assign.id) if attr is None: - add_semantic_error(assign.id.lineno, assign.id.colno, f'unknown variable \'{assign.id}\'') + add_semantic_error(assign.id.lineno, assign.id.colno, + f'unknown variable \'{assign.id}\'') id_type = None else: id_type = attr.attrType @@ -116,18 +123,23 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if func_call.type: specific_type = type_by_name(func_call.type) if specific_type is None: - add_semantic_error(func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') + add_semantic_error( + func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') elif check_inherits(current_class, specific_type): - method, msg = specific_type.get_method_without_hierarchy(func_call.id, args_types) + method, msg = specific_type.get_method_without_hierarchy( + func_call.id, args_types) else: add_semantic_error(func_call.lineno, func_call.colno, f'type {current_class} not inherits from {specific_type}') else: - object_type = expression_visitor(func_call.object, current_class, local_scope) + object_type = expression_visitor( + func_call.object, current_class, local_scope) if object_type is None: return None else: method, msg = object_type.get_method(func_call.id, args_types) + if method.returnedType == SelfType: + method.returnedType = object_type else: method, msg = current_class.get_method(func_call.id, args_types) if method is None: @@ -140,11 +152,15 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): - predicate_type = expression_visitor(if_struct.if_expr, current_class, local_scope) + predicate_type = expression_visitor( + if_struct.if_expr, current_class, local_scope) if predicate_type != BoolType: - add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') - then_type = expression_visitor(if_struct.then_expr, current_class, local_scope) - else_type = expression_visitor(if_struct.else_expr, current_class, local_scope) + add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, + f'\'if\' condition must be a {BoolType}') + then_type = expression_visitor( + if_struct.then_expr, current_class, local_scope) + else_type = expression_visitor( + if_struct.else_expr, current_class, local_scope) if_struct.returned_type = pronounced_join(then_type, else_type) return if_struct.returned_type @@ -152,7 +168,8 @@ def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor(loop.cond, current_class, local_scope) if predicate_type != BoolType and predicate_type is not None: - add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') + add_semantic_error(loop.cond.lineno, loop.cond.colno, + f'\"loop\" condition must be a {BoolType}') expression_visitor(loop.body, current_class, local_scope) loop.returned_type = ObjectType return ObjectType @@ -171,9 +188,11 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): for attribute in let.let_attrs: id_type = type_by_name(attribute.type) if id_type is None: - add_semantic_error(attribute.lineno, attribute.colno, f'unknown type \'{attribute.type}\'') + add_semantic_error(attribute.lineno, attribute.colno, + f'unknown type \'{attribute.type}\'') return None - attribute_type = expression_visitor(attribute, current_class, local_scope) + attribute_type = expression_visitor( + attribute, current_class, local_scope) if attribute_type is None: return None if not check_inherits(attribute_type, id_type): @@ -181,7 +200,8 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') return None local_scope[attribute.id] = id_type - let.returned_type = expression_visitor(let.expr, current_class, local_scope) + let.returned_type = expression_visitor( + let.expr, current_class, local_scope) return let.returned_type @@ -196,17 +216,20 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict for branch in case.case_list[1:]: temp = local_scope.copy() temp[branch.id] = expr_0 - current_type = pronounced_join(current_type, expression_visitor(branch.expr, current_class, temp)) + current_type = pronounced_join( + current_type, expression_visitor(branch.expr, current_class, temp)) case.returned_type = current_type return case.returned_type def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): - lvalue_type = expression_visitor(operator.lvalue, current_class, local_scope) + lvalue_type = expression_visitor( + operator.lvalue, current_class, local_scope) if lvalue_type != IntType and lvalue_type is not None: add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, f'invalid left value type {lvalue_type}, must be a {IntType}') - rvalue_type = expression_visitor(operator.rvalue, current_class, local_scope) + rvalue_type = expression_visitor( + operator.rvalue, current_class, local_scope) if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, f'invalid left value type {rvalue_type}, must be a {IntType}') @@ -217,10 +240,12 @@ def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, l def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) if lvalue_type != IntType and lvalue_type is not None: - add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, f'lvalue type must be a {IntType}') + add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, + f'lvalue type must be a {IntType}') rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) if rvalue_type != IntType and rvalue_type is not None: - add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') + add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, + f'rvalue type must be a {IntType}') cmp.returned_type = BoolType return BoolType @@ -230,7 +255,8 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) static_types = [IntType, BoolType, StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: - add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') + add_semantic_error(equal.lineno, equal.colno, + f'impossible compare {lvalue_type} and {rvalue_type} types') equal.returned_type = BoolType return BoolType @@ -265,14 +291,16 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): if attribute is not None: var.returned_type = attribute.attrType else: - add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') + add_semantic_error(var.lineno, var.colno, + f'unknown variable \'{var.id}\'') return var.returned_type def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): t = type_by_name(new.type) if not t: - add_semantic_error(new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') + add_semantic_error( + new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') if t == SelfType: new.returned_type = current_class else: From 82b0582f8edd6e786e092aa1a8982a3ac37fed02 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 20 May 2020 15:45:30 -0400 Subject: [PATCH 212/435] fixing bugs --- src/code_generation/cil.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index ca2058af..201533c3 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -365,13 +365,13 @@ def string_to_cil_visitor(str): return CIL_block(body, str_id) - def let_to_cil_visitor(let): body = [] for attr in let.let_attrs: - attr_cil = expression_to_cil_visitor(attr) - body.append(cil.AssignNode(attr.id, attr_cil.value)) - body += attr_cil.body + if attr.expr: + attr_cil = expression_to_cil_visitor(attr.expr) + body += attr_cil.body + body.append(cil.AssignNode(attr.id, attr_cil.value)) expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body From aa64d07db688000ef53815e1b580060e6c91da03 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 20 May 2020 15:50:40 -0400 Subject: [PATCH 213/435] fixing bug --- src/semantic/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index 8f5895b7..93e82930 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -37,7 +37,7 @@ def get_all_attributes(self): result=[] while t: temp=[] - for attr in t.attributes: + for attr in t.attributes.values(): temp.append(attr) result.append(temp) t=t.parent From 9edeac83687760cfe086529cba81c83374dd2e93 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 15:52:43 -0400 Subject: [PATCH 214/435] Fix bug --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 0f54c884..c9893ac5 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -138,7 +138,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return None else: method, msg = object_type.get_method(func_call.id, args_types) - if method.returnedType == SelfType: + if method is not None and method.returnedType == SelfType: method.returnedType = object_type else: method, msg = current_class.get_method(func_call.id, args_types) From 8cd4b0385929153ebcd56de8b1d9ee14f7b3f070 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 15:53:40 -0400 Subject: [PATCH 215/435] Fix error Change IntNode to Int Type in type comparison --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index c9893ac5..250ba1a6 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -263,7 +263,7 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): def negation_visitor(negation: NegationNode, current_class: CoolType, local_scope: dict): value_type = expression_visitor(negation.val, current_class, local_scope) - if value_type != IntNode and value_type is not None: + if value_type != IntType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, f'type {value_type} invalid. The \'~\' operator can only be used with type {IntType}') return IntType From d7cef8467c423ff848b175e4c101103c2130f7b4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 16:11:08 -0400 Subject: [PATCH 216/435] Fix lexer/parser bug - Remove ASSIGN from precedence - Regenerate parsetab --- src/lexer_parser/parser.py | 1 - src/lexer_parser/parsetab.py | 102 +++++++++++++++++------------------ 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index bb9f7570..26ae451b 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -13,7 +13,6 @@ ('left', 'PLUS', 'MINUS'), ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'LNOT'), - ('right', 'ASSIGN'), ) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 31fa1724..39f80cde 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTrightASSIGNARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,-22,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,-22,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,-22,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,-22,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,-22,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,-22,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,-22,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,-22,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,-22,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): @@ -33,53 +33,53 @@ ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), - ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',49), - ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',50), - ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',51), - ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',59), - ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',60), - ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',68), - ('params -> param_list','params',1,'p_params_ne','parser.py',73), - ('params -> empty','params',1,'p_params_e','parser.py',78), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',83), - ('param_list -> param empty','param_list',2,'p_param_list','parser.py',84), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',92), - ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',97), - ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',98), - ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',99), - ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',100), - ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',113), - ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',118), - ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',119), - ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',120), - ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',130), - ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',131), - ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',132), - ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',133), - ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',134), - ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',135), - ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',136), - ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',154), - ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',155), - ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',156), - ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',166), - ('expr -> atom','expr',1,'p_expr_atom','parser.py',171), - ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',176), - ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',177), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',185), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',186), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',194), - ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',199), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',200), - ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',205), - ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',206), - ('atom -> INT','atom',1,'p_atom_int','parser.py',214), - ('atom -> ID','atom',1,'p_atom_id','parser.py',219), - ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',224), - ('atom -> block','atom',1,'p_atom_block','parser.py',229), - ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',234), - ('atom -> STRING','atom',1,'p_atom_atring','parser.py',239), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',244), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',249), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',250), + ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',51), + ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',52), + ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',53), + ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',61), + ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',62), + ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',72), + ('params -> param_list','params',1,'p_params_ne','parser.py',78), + ('params -> empty','params',1,'p_params_e','parser.py',83), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',88), + ('param_list -> param empty','param_list',2,'p_param_list','parser.py',89), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',97), + ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',103), + ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',104), + ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',105), + ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',106), + ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',121), + ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',127), + ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',128), + ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',129), + ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',150), + ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',151), + ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',152), + ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',153), + ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',154), + ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',155), + ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',156), + ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',176), + ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',177), + ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',178), + ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',190), + ('expr -> atom','expr',1,'p_expr_atom','parser.py',195), + ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',200), + ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',201), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',209), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',210), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',218), + ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',224), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',225), + ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',230), + ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',231), + ('atom -> INT','atom',1,'p_atom_int','parser.py',239), + ('atom -> ID','atom',1,'p_atom_id','parser.py',245), + ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',251), + ('atom -> block','atom',1,'p_atom_block','parser.py',257), + ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',262), + ('atom -> STRING','atom',1,'p_atom_atring','parser.py',268), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',274), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',279), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',280), ] From d3bc52696ec7f1b5fd25952a4698ce7d70610a6d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 16:36:16 -0400 Subject: [PATCH 217/435] Fix bug in CASE The static type of the declared ID in each case branch must be the declared type, not the type of the case expression --- src/semantic/semantic.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 250ba1a6..a60da6db 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -209,13 +209,22 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict expr_0 = expression_visitor(case.expr, current_class, local_scope) branch_0 = case.case_list[0] + branch_0_type = type_by_name(branch_0.type) temp = local_scope.copy() - temp[branch_0.id] = expr_0 + if branch_0_type is None: + add_semantic_error(branch_0.line, branch_0.column, + f"unknow type \"{branch_0.type}\"") + else: + temp[branch_0.id] = branch_0_type current_type = expression_visitor(branch_0.expr, current_class, temp) for branch in case.case_list[1:]: temp = local_scope.copy() - temp[branch.id] = expr_0 + branch_type = type_by_name(branch.type) + if branch_type is None: + add_semantic_error(branch_0.line, branch_0.column, + f"unknow type \"{branch.type}\"") + temp[branch.id] = branch_type current_type = pronounced_join( current_type, expression_visitor(branch.expr, current_class, temp)) case.returned_type = current_type From b7c6387c159d8f5d942a347e2784596adb770212 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 16:57:13 -0400 Subject: [PATCH 218/435] Fix semantic bug Change static function call --- src/semantic/semantic.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index a60da6db..e5bd87b2 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -120,29 +120,30 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc arg_type = expression_visitor(arg, current_class, local_scope) args_types.append(arg_type) if func_call.object: + object_type = expression_visitor( + func_call.object, current_class, local_scope) + if object_type is None: + return None if func_call.type: specific_type = type_by_name(func_call.type) if specific_type is None: add_semantic_error( func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') - elif check_inherits(current_class, specific_type): + elif check_inherits(object_type, specific_type): method, msg = specific_type.get_method_without_hierarchy( func_call.id, args_types) + if method is not None and method.returnedType == SelfType: + method.returnedType = specific_type else: add_semantic_error(func_call.lineno, func_call.colno, - f'type {current_class} not inherits from {specific_type}') + f'type {object_type} not inherits from {specific_type}') else: - object_type = expression_visitor( - func_call.object, current_class, local_scope) - if object_type is None: - return None - else: - method, msg = object_type.get_method(func_call.id, args_types) - if method is not None and method.returnedType == SelfType: - method.returnedType = object_type + method, msg = object_type.get_method(func_call.id, args_types) + if method is not None and method.returnedType == SelfType: + method.returnedType = object_type else: method, msg = current_class.get_method(func_call.id, args_types) - if method is None: + if method is None and msg is not None: add_semantic_error(func_call.lineno, func_call.colno, msg) elif method.returnedType == SelfType: func_call.returned_type = current_class From db6b4684431f03a95c1f3428610cde736ba48825 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 18:47:38 -0400 Subject: [PATCH 219/435] Fix bug in types check --- src/semantic/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index 8f5895b7..5f49dd1d 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -77,7 +77,7 @@ def get_method_without_hierarchy(self, id, args_types): return None, f'method \'{self.name}.{id}\' formal parameter count ({len(method.args)}) ' \ f'does not match actual parameter count ({len(args_types)})' for i, a in enumerate(args_types): - if a != method.args[i]: + if not check_inherits(a,method.args[i]): return None, f'method \'{self.name}.{id}\' parameter #{i} type mismatch. Actual: \'{a}\' should ' \ f'be a subtype of \'{method.args[i]}\' ' return method, None From 906a8e4cc2bd0ccd7c25f9aebcd9799259b630b5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 18:48:32 -0400 Subject: [PATCH 220/435] Reformat code types.py --- src/semantic/types.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/semantic/types.py b/src/semantic/types.py index 5f49dd1d..19d4c7b3 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -31,35 +31,32 @@ def add_method(self, id, arg_types_name, returned_type): return True, None else: return False, msg - + def get_all_attributes(self): - t=self - result=[] + t = self + result = [] while t: - temp=[] + temp = [] for attr in t.attributes: temp.append(attr) result.append(temp) - t=t.parent + t = t.parent return [elem for sublist in result[::-1] for elem in sublist] - - + def get_all_self_methods(self): return self.methods - + def get_all_inherited_methods(self): - t=self.parent - result=[] + t = self.parent + result = [] while t: - temp=[] + temp = [] for met in t.methods: - met.owner=t.name + met.owner = t.name temp.append(met) result.append(temp) - t=t.parent + t = t.parent return [elem for sublist in result[::-1] for elem in sublist] - - def get_method(self, id, args_types): try: @@ -77,7 +74,7 @@ def get_method_without_hierarchy(self, id, args_types): return None, f'method \'{self.name}.{id}\' formal parameter count ({len(method.args)}) ' \ f'does not match actual parameter count ({len(args_types)})' for i, a in enumerate(args_types): - if not check_inherits(a,method.args[i]): + if not check_inherits(a, method.args[i]): return None, f'method \'{self.name}.{id}\' parameter #{i} type mismatch. Actual: \'{a}\' should ' \ f'be a subtype of \'{method.args[i]}\' ' return method, None @@ -154,7 +151,8 @@ def check_type_declaration(node: ProgramNode): for c in node.classes: try: _ = TypesByName[c.type] - add_semantic_error(c.lineno, c.colno, f'duplicated declaration of type \'{c.type}\'') + add_semantic_error(c.lineno, c.colno, + f'duplicated declaration of type \'{c.type}\'') return False except KeyError: TypesByName[c.type] = CoolType(c.type, None) @@ -170,10 +168,12 @@ def check_type_hierarchy(node: ProgramNode): if parentType.inherit: cType.parent = parentType else: - add_semantic_error(c.lineno, c.colno, f'can\'t be inherit from class {parentType.name}') + add_semantic_error( + c.lineno, c.colno, f'can\'t be inherit from class {parentType.name}') return False except KeyError: - add_semantic_error(c.lineno, c.colno, f'unknown parent type {c.parent_type}') + add_semantic_error(c.lineno, c.colno, + f'unknown parent type {c.parent_type}') return False else: cType.parent = ObjectType From e8637c902e66ee4753504cc03286cd076173281a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 19:47:30 -0400 Subject: [PATCH 221/435] Fix parser bug Change equal precedence --- src/lexer_parser/parser.py | 2 +- src/lexer_parser/parsetab.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 26ae451b..44aa540a 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -9,9 +9,9 @@ ('left', 'AT'), ('left', 'NOT'), ('left', 'ISVOID'), + ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'STAR', 'DIV'), ('left', 'PLUS', 'MINUS'), - ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'LNOT'), ) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 39f80cde..c5fcf30b 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftSTARDIVleftPLUSMINUSleftLOWEREQLOWEREQUALleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftLOWEREQLOWEREQUALleftSTARDIVleftPLUSMINUSleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,-30,-31,-32,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,-30,-31,-32,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,65,65,65,65,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,66,66,66,66,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,67,67,67,67,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): From aa9f3932d4e638593815144a7d81b8183bbff17a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 19:51:21 -0400 Subject: [PATCH 222/435] Remove redundant error if predicate is wrong --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index e5bd87b2..de666852 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -155,7 +155,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): predicate_type = expression_visitor( if_struct.if_expr, current_class, local_scope) - if predicate_type != BoolType: + if predicate_type != BoolType and predicate_type is not None: add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') then_type = expression_visitor( From da009408722ef56ed64d49c2fe7e3e523ebfa00d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 20:36:32 -0400 Subject: [PATCH 223/435] Fix precedence --- src/lexer_parser/parser.py | 4 ++-- src/lexer_parser/parsetab.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 44aa540a..93553612 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -5,14 +5,14 @@ from .lexer import * precedence = ( - ('left', 'DOT'), ('left', 'AT'), ('left', 'NOT'), ('left', 'ISVOID'), ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), - ('left', 'STAR', 'DIV'), ('left', 'PLUS', 'MINUS'), + ('left', 'STAR', 'DIV'), ('left', 'LNOT'), + ('left', 'DOT'), ) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index c5fcf30b..7a967593 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftDOTleftATleftNOTleftISVOIDleftLOWEREQLOWEREQUALleftSTARDIVleftPLUSMINUSleftLNOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'leftATleftNOTleftISVOIDleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftLNOTleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,-33,-34,-35,-49,60,60,60,107,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,61,61,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,62,62,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,-26,-27,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,-26,-27,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): From 7227ca4737b665b13049819d178da1c0604c207a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 20:46:15 -0400 Subject: [PATCH 224/435] Fix bug local_scope missing --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index de666852..c01ba549 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -53,7 +53,7 @@ def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: di def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): if attr.expr: - expr_type = expression_visitor(attr.expr, current_class, {}) + expr_type = expression_visitor(attr.expr, current_class, local_scope) attr_type = type_by_name(attr.type) if attr_type is not None and not check_inherits(expr_type, attr_type): add_semantic_error( From c5c2e22d2f56806f16f83013890460238af9ecd5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 20 May 2020 20:54:10 -0400 Subject: [PATCH 225/435] Fix LNOT precedence --- src/lexer_parser/parser.py | 2 +- src/lexer_parser/parsetab.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 93553612..9e3b25f1 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -8,10 +8,10 @@ ('left', 'AT'), ('left', 'NOT'), ('left', 'ISVOID'), + ('left', 'LNOT'), ('left', 'LOWEREQ', 'LOWER', 'EQUAL'), ('left', 'PLUS', 'MINUS'), ('left', 'STAR', 'DIV'), - ('left', 'LNOT'), ('left', 'DOT'), ) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 7a967593..e821d12b 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -6,9 +6,9 @@ _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftLNOTleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,-35,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,-35,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,-35,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,-35,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,-35,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,-35,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,-35,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} +_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): From 50226c266e12c0f62c899404a4b9ea422f207c67 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 21 May 2020 11:17:56 -0400 Subject: [PATCH 226/435] Add documentation to each function in semantic.py - remove unnecessary id type check in let_visitor, attribute_visitor already check it --- src/semantic/semantic.py | 345 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 330 insertions(+), 15 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index c01ba549..d8b11eef 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -2,15 +2,26 @@ def program_visitor(program: ProgramNode): + ''' + Check semantic for a program. + 1) Check type declaration (check duplicated types...) + 2) Check type hierarchy + 3) Check class Main + 4) Check all methos and attributes for all declared types, and add them to respective type + 5) Check recursive each delared class + ''' + # 1) and 2) if not (check_type_declaration(program) and check_type_hierarchy(program)): return - # Check Main class exists + + # 3) try: TypesByName['Main'] except KeyError: add_semantic_error(0, 0, f'Main class undeclared') return - # Initialize MethodEnv + + # 4) types_already_check = [ObjectType, IntType, StringNode, BoolType, IOType] classes = program.classes.copy() while len(classes) != 0: @@ -29,21 +40,30 @@ def program_visitor(program: ProgramNode): if not result: add_semantic_error(f.lineno, f.colno, msg) elif type(f) is DefAttrNode: - # Add all attributes to types result, msg = classType.add_attr(f.id, f.type, f.expr) if not result: add_semantic_error(f.lineno, f.colno, msg) types_already_check.append(classType) - # Visit each class inside + + # 5) for c in program.classes: class_visitor(c, None, {}) def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: dict): + ''' + Check class + + class MY_TYPE inherits INHERITS_TYPE{ + FEATURE_LIST + } + + 1) Check each feature in FEATURE_LIST + ''' current_class = TypesByName[_class.type] local_scope = local_scope.copy() local_scope['self'] = current_class - # Check all features + # 1) for feature in _class.feature_nodes: if type(feature) is DefAttrNode: def_attr_class_visitor(feature, current_class, local_scope) @@ -52,9 +72,20 @@ def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: di def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): + ''' + Check class attribute + + ID:TYPE <- EXPR + + If EXPR is not None: + 1) Check EXPR + 2) Check type(EXPR) <= TYPE + ''' if attr.expr: + # 1) expr_type = expression_visitor(attr.expr, current_class, local_scope) attr_type = type_by_name(attr.type) + # 2) if attr_type is not None and not check_inherits(expr_type, attr_type): add_semantic_error( attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') @@ -63,28 +94,60 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): + ''' + Check attribute (except class attribute) + + ID:TYPE <- EXPR + + 1) Check if TYPE exists + 2) Check if EXPR is not None + 2.1) Check EXPR + 2.2) Check type(EXPR) <= TYPE + 3) Type of the attribute is TYPE + ''' + # 1) id_type = type_by_name(def_attr.type) if id_type is None: add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') + # 2) if def_attr.expr: + # 2.1) expr_type = expression_visitor( def_attr.expr, current_class, local_scope) + # 2.2) if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(def_attr.lineno, def_attr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + # 3) return id_type def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope: dict): + ''' + Check function declaration + + ID (PARAMS): RETURN_TYPE{ + EXPR + } + + 1) Add PARAMS to local_scope. Type of PARAMS already check in program_visitor(4) + 2) Check EXPR + 3) Update RETURN_TYPE with current class type if that is SELFTYPE + 4) Check type(EXPR) <= RETURN_TYPE + ''' local_scope = local_scope.copy() + # 1) for arg in function.params: local_scope[arg[0]] = type_by_name(arg[1]) + # 2) body_type = expression_visitor( function.expressions, current_class, local_scope) return_type = type_by_name(function.return_type) + # 3) if return_type == SelfType: return_type = current_class + # 4) if check_inherits(body_type, return_type): return return_type elif body_type is not None: @@ -93,9 +156,24 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: dict): + ''' + Check assigment + + ID <- EXPR + + 1) Check type(ID) + 1.1) First find in local_scope + 1.2) Second find in current class attributes + 2) Check EXPR + 3) Check type(EXPR) <= type(ID) + 4) Type of assigment is type(EXPR) + ''' + # 1) try: + # 1.1) id_type = local_scope[assign.id] except KeyError: + # 1.2) attr, _ = get_attribute(current_class, assign.id) if attr is None: add_semantic_error(assign.id.lineno, assign.id.colno, @@ -103,35 +181,66 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: id_type = None else: id_type = attr.attrType + # 2) expr_type = expression_visitor(assign.expr, current_class, local_scope) + # 3) if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(assign.expr.lineno, assign.expr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + # 4) assign.returned_type = expr_type return expr_type def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_scope: dict): + ''' + Check function call + + Exist three forms of function call: + + 1- EXPR@TYPE.ID(ARGS) + 2- EXPR.ID(ARGS) + 3- ID(ARGS) + + 1) Compute args type, not check yet, because check need wait to find the specific function + 2) EXPR is not None (cases 1 and 2) + 2.1) Check type(EXPR) + 2.2) TYPE is not None + 2.2.1) Check TYPE + 2.2.2) Check type(EXPR) <= TYPE + 2.2.3) If returned type of the funtion is SELFTYPE then returned type is TYPE + 3) If EXPR is None + 3.2) If returned type of the function is SELFTYPE then returned type is current class type + 4) Type of function call is the returned type of function + + ''' args_types = [] method = None msg = None func_call.self_type = current_class + # 1) for arg in func_call.args: arg_type = expression_visitor(arg, current_class, local_scope) args_types.append(arg_type) + # 2) if func_call.object: + # 2.1) object_type = expression_visitor( func_call.object, current_class, local_scope) if object_type is None: return None + # 2.2) if func_call.type: + # 2.2.1) specific_type = type_by_name(func_call.type) if specific_type is None: add_semantic_error( func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') + # 2.2.2) elif check_inherits(object_type, specific_type): method, msg = specific_type.get_method_without_hierarchy( func_call.id, args_types) + # 2.2.3) if method is not None and method.returnedType == SelfType: method.returnedType = specific_type else: @@ -141,194 +250,389 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc method, msg = object_type.get_method(func_call.id, args_types) if method is not None and method.returnedType == SelfType: method.returnedType = object_type + # 3) else: method, msg = current_class.get_method(func_call.id, args_types) if method is None and msg is not None: add_semantic_error(func_call.lineno, func_call.colno, msg) + # 3.1) elif method.returnedType == SelfType: func_call.returned_type = current_class else: + # 4) func_call.returned_type = method.returnedType return func_call.returned_type def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): + ''' + Check \"if\" stament + + if IF_EXPR then THEN_EXPR else ELSE_EXPR fi + + 1) Check IF_EXPR. type(IF_EXPR) must be a Bool + 2) Check THEN_EXPR + 3) Check ELSE_EXPR + 4) Type of \"if\" stament is the pronounced join of THEN_EXPR and ELSE_EXPR + ''' + # 1) predicate_type = expression_visitor( if_struct.if_expr, current_class, local_scope) if predicate_type != BoolType and predicate_type is not None: add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, f'\'if\' condition must be a {BoolType}') + # 2) then_type = expression_visitor( if_struct.then_expr, current_class, local_scope) + # 3) else_type = expression_visitor( if_struct.else_expr, current_class, local_scope) + # 4) if_struct.returned_type = pronounced_join(then_type, else_type) return if_struct.returned_type def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): + ''' + Check loop + + while CONDITION_EXPR loop EXPR pool + + 1) Check CONDITION_EXPR. type(CONDITION_EXPR) must be a Bool + 2) Check EXPR + 3) Type of loop is Oject + ''' + # 1) predicate_type = expression_visitor(loop.cond, current_class, local_scope) if predicate_type != BoolType and predicate_type is not None: add_semantic_error(loop.cond.lineno, loop.cond.colno, f'\"loop\" condition must be a {BoolType}') + # 2) expression_visitor(loop.body, current_class, local_scope) + # 3) loop.returned_type = ObjectType return ObjectType def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): + ''' + Check block + + { EXPR_LIST } + + 1) Check each epression in EXPR_LIST + 2) Type of block is type of the last expression in EXPR_LIST + ''' final_type = None + # 1) for expr in block.expressions: final_type = expression_visitor(expr, current_class, local_scope) + # 2) block.returned_type = final_type return final_type def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): + ''' + Check let + + let LET_ATTRS in EXPR + + 1) Check all attributes in LET_ATTRS + 2) Check EXPR + 3) Type of let is type(EXPR) + + + ''' local_scope = local_scope.copy() + # 1) for attribute in let.let_attrs: - id_type = type_by_name(attribute.type) - if id_type is None: - add_semantic_error(attribute.lineno, attribute.colno, - f'unknown type \'{attribute.type}\'') - return None attribute_type = expression_visitor( attribute, current_class, local_scope) if attribute_type is None: return None - if not check_inherits(attribute_type, id_type): - add_semantic_error(attribute.lineno, attribute.colno, - f'Type \'{attribute_type}\' cannot be stored in type \'{id_type}\'') - return None - local_scope[attribute.id] = id_type + local_scope[attribute.id] = attribute_type + # 2) and 3) let.returned_type = expression_visitor( let.expr, current_class, local_scope) return let.returned_type def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): + ''' + Check case + + case EXPR_0 of + ID_1:TYPE_1 => EXPR_1; + ... + ... + ID_n:TYPE_n => EXPR_n; + esac + + 1) Check EXPR_0 + 2) Check first branch + 2.1) Check TYPE_1 + 2.2) Update local scope with ID_1 + 2.3) Check EXPR_1 and set current type as type(EXPR_1) + 3) Check rest of branches (k=2,...,n) + 3.1) Check TYPE_k + 3.2) Update local scope with ID_k + 3.3) Check EXPR_k and set current type as pronounced join of current type and type(EXPR_k) + 4) Type of case is the pronounced join of all branch expressions types, then is the current type at final of step 3) + ''' + + # 1) expr_0 = expression_visitor(case.expr, current_class, local_scope) + # 2) branch_0 = case.case_list[0] + # 2.1) branch_0_type = type_by_name(branch_0.type) temp = local_scope.copy() if branch_0_type is None: add_semantic_error(branch_0.line, branch_0.column, f"unknow type \"{branch_0.type}\"") else: + # 2.2) temp[branch_0.id] = branch_0_type + # 2.3) current_type = expression_visitor(branch_0.expr, current_class, temp) + # 3) for branch in case.case_list[1:]: temp = local_scope.copy() + # 3.1) branch_type = type_by_name(branch.type) if branch_type is None: add_semantic_error(branch_0.line, branch_0.column, f"unknow type \"{branch.type}\"") + # 3.2) temp[branch.id] = branch_type + # 3.3) current_type = pronounced_join( current_type, expression_visitor(branch.expr, current_class, temp)) + # 4) case.returned_type = current_type return case.returned_type def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): + ''' + Check arithmetic operator (binary) + + LEXPR operator REXPR + + 1) Check LEXPR, must be Int + 2) Check REXPR, must be a Int + 3) Type of the arithmetic operator (binary) is Int + ''' + # 1) lvalue_type = expression_visitor( operator.lvalue, current_class, local_scope) if lvalue_type != IntType and lvalue_type is not None: add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, f'invalid left value type {lvalue_type}, must be a {IntType}') + # 2) rvalue_type = expression_visitor( operator.rvalue, current_class, local_scope) if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, f'invalid left value type {rvalue_type}, must be a {IntType}') + # 3) operator.returned_type = IntType return IntType def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): + ''' + Check comparison + + LEXPR operator REXPR + + 1) Check LEXPR, must be Int + 2) Check REXPR, must be Int + 3) Type of the comparison is Bool + ''' + # 1) lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) if lvalue_type != IntType and lvalue_type is not None: add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, f'lvalue type must be a {IntType}') + # 2) rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) if rvalue_type != IntType and rvalue_type is not None: add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, f'rvalue type must be a {IntType}') + # 3) cmp.returned_type = BoolType return BoolType def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): + ''' + Check equal + + LEXPR = REXPR + + 1) Check LEXPR + 2) Check REXPR + 3) Check type(LEXPR) is equal to type(REXPR) and must be Int, Bool or String + 4) Type of the equal is Bool + ''' + # 1) lvalue_type = expression_visitor(equal.lvalue, current_class, local_scope) + # 2) rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) + # 3) static_types = [IntType, BoolType, StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') + # 4) equal.returned_type = BoolType return BoolType def negation_visitor(negation: NegationNode, current_class: CoolType, local_scope: dict): + ''' + Check binary negation + + ~EXPR + + 1) Check EXPR + 2) Check type(EXPR) must be Int + 3) Type of the binary negation (~) is Int + ''' + # 1) value_type = expression_visitor(negation.val, current_class, local_scope) + # 2) if value_type != IntType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, f'type {value_type} invalid. The \'~\' operator can only be used with type {IntType}') + # 3) return IntType def logic_negation_visitor(negation: LogicNegationNode, current_class: CoolType, local_scope: dict): + ''' + Check logic negation + + not EXPR + + 1) Check EXPR + 2) Check type(EXPR) must be Bool + 3) Type of the logic negation is Bool + + ''' + # 1) value_type = expression_visitor(negation.val, current_class, local_scope) + # 2) if value_type != BoolType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, f'type {value_type} invalid. The \'not\' operator can only be used with type {BoolType}') + # 3) return BoolType def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): + ''' + Check isvoid + + isvoid EXPR + + 1) Check EXPR + 2) Type of the isvoid is Bool + ''' + # 1) expression_visitor(isvoid.val, current_class, local_scope) + # 2) isvoid.returned_type = BoolType return BoolType def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): + ''' + Check var + + ID + + 1) Check if ID is in local scope + 2) Check if ID is an class attribute + 3) Type of var is the already funded type + ''' + # 1) if var.id in local_scope.keys(): var.returned_type = local_scope[var.id] else: + # 2) attribute, _ = get_attribute(current_class, var.id) if attribute is not None: var.returned_type = attribute.attrType else: add_semantic_error(var.lineno, var.colno, f'unknown variable \'{var.id}\'') + # 3) return var.returned_type def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): + ''' + Check new + + new TYPE + + 1) Check TYPE exists + 2) Is TYPE is SELFTYPE then TYPE is updated to current class type + 3) Type of new is TYPE + ''' + # 1) t = type_by_name(new.type) if not t: add_semantic_error( new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') + # 2) if t == SelfType: new.returned_type = current_class else: new.returned_type = t + # 3) return new.returned_type def int_visitor(expr: IntNode, current_class, local_scope): + ''' + Check int + + number + + 1) Type os int is Int :) + ''' + # 1) expr.returned_type = IntType return IntType def bool_visitor(expr: BoolNode, current_class, local_scope): + ''' + Check bool + + [True|Fsle] + + 1) Type of bool is Bool :) + ''' + # 1) expr.returned_type = BoolType return BoolType def string_visitor(expr: StringNode, current_class, local_scope): + ''' + Check string + + "string" + + 1) Type of string is String :) + ''' expr.returned_type = StringType return StringType @@ -361,6 +665,14 @@ def string_visitor(expr: StringNode, current_class, local_scope): def expression_visitor(expression, current_class: CoolType, local_scope: dict) -> CoolType: + ''' + This is the main function to check any expression. This function search the + right function for check the expression. + + expression: expression to check + current_class: class containing the expression + local_scope: local scope at the moment + ''' try: return __visitors__[type(expression)](expression, current_class, local_scope) except KeyError: @@ -368,5 +680,8 @@ def expression_visitor(expression, current_class: CoolType, local_scope: dict) - def semantic_check(node): + ''' + Start semantic check for the entire program. It only works if the node type is ProgramNode + ''' if type(node) is ProgramNode: program_visitor(node) From 152505127557c407d26613c0dc78e7b15cf61515 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 21 May 2020 14:28:43 -0400 Subject: [PATCH 227/435] fix last bugs --- src/code_generation/cil.py | 39 ++++++++++++++++++++++-------------- src/code_generation/code.py | 6 +++++- src/lexer_parser/parsetab.py | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 201533c3..bdb4602c 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -22,6 +22,11 @@ def add_local(): locals_count += 1 return f'local_{locals_count}' +def add_label(): + global labels_count + labels_count+=1 + return f'label_{labels_count}' + def ast_to_cil(ast): if type(ast) == lp_ast.ProgramNode: @@ -62,7 +67,7 @@ def program_to_cil_visitor(program): _type = cil.TypeNode(t) value = TypesByName[t] for attr in value.get_all_attributes(): - _type.attributes.append(attr) + _type.attributes.append(attr.id) for met in value.get_all_inherited_methods(): _type.methods[met.id] = met.owner @@ -137,11 +142,12 @@ def substring_to_cil(): return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'),cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l','result'), cil.ReturnNode('result')]) def func_to_cil_visitor(type_name, func): - global locals_count, __DATA_LOCALS__, __TYPEOF__ + global locals_count, __DATA_LOCALS__, __TYPEOF__, labels_count name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] locals_count = 0 + labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} body = [] @@ -175,7 +181,7 @@ def case_to_cil_visitor(case): types.append(c.type) for _ in range(len(case.case_list)): - labels.append(add_local()) + labels.append(add_label()) value = None @@ -229,8 +235,8 @@ def if_to_cil_visitor(_if): else_expression = expression_to_cil_visitor( _if.else_expr) - label_1 = add_local() - label_2 = add_local() + label_1 = add_label() + label_2 = add_label() value = add_local() body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ @@ -247,8 +253,8 @@ def loop_to_cil_visitor(loop): value = add_local() - loop_label = add_local() - end_label = add_local() + loop_label = add_label() + end_label = add_label() body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), cil.LabelNode(loop_label)] + loop_block.body + [cil.LabelNode(end_label), cil.AssignNode(value, 0)] @@ -260,8 +266,8 @@ def equal_to_cil_visitor(equal): l = expression_to_cil_visitor(equal.lvalue) r = expression_to_cil_visitor(equal.rvalue) - cil_result = add_local() - end_label = add_local() + cil_result = add_label() + end_label = add_label() value = add_local() body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), @@ -276,8 +282,8 @@ def lessthan_to_cil_visitor(lessthan): l = expression_to_cil_visitor(lessthan.lvalue) r = expression_to_cil_visitor(lessthan.rvalue) - cil_result = add_local() - end_label = add_local() + cil_result = add_label() + end_label = add_label() value = add_local() body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), @@ -294,8 +300,8 @@ def lesseqthan_to_cil_visitor(lessthan): cil_less = add_local() cil_equal = add_local() - eq_label = add_local() - end_label = add_local() + eq_label = add_label() + end_label = add_label() value = add_local() body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), @@ -384,7 +390,7 @@ def logic_not_to_cil_visitor(not_node): not_node.val) value = add_local() - end_label = add_local() + end_label = add_label() body = expr_cil.body + [cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), cil.AssignNode(value, 1), cil.LabelNode(end_label)] @@ -469,7 +475,10 @@ def func_call_to_cil_visitor(call): lp_ast.VarNode: id_to_cil_visitor, lp_ast.FuncCallNode: func_call_to_cil_visitor, lp_ast.IsVoidNode: is_void_to_cil_visitor, - lp_ast.NegationNode: not_to_cil_visitor + lp_ast.NegationNode: not_to_cil_visitor, + lp_ast.LessThanNode:lessthan_to_cil_visitor, + lp_ast.LessEqNode:lesseqthan_to_cil_visitor, + lp_ast.CaseNode:case_to_cil_visitor, } diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 1e84fb4b..808ee076 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -134,6 +134,9 @@ def arg_cg_visitor(arg: ArgNode): def cond_goto_cg_visitor(cgoto: ConditionalGotoNode): return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' +def not_cg_visitor(n:NotNode): + return f'{n.result} = ~ {n.value}' + def goto_cg_visitor(goto: GotoNode): return f'GOTO {goto.label} ;' @@ -201,5 +204,6 @@ def print_cg_visitor(print: PrintNode): SubStringNode: substring_cg_visitor, StrNode: str_cg_visitor, ReadNode: read_cg_visitor, - PrintNode: print_cg_visitor + PrintNode: print_cg_visitor, + NotNode: not_cg_visitor } diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 5254b608..d0d73f0c 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -5,7 +5,7 @@ _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 1c07ae2378090b6daf5dc5bcc6566b29f9374eb2 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 21 May 2020 14:59:05 -0400 Subject: [PATCH 228/435] adding lasts built in functions --- src/code_generation/ast.py | 14 +++++++++++++- src/code_generation/cil.py | 6 +++--- src/code_generation/code.py | 13 ++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 3e72f9ca..af70fd9f 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -72,7 +72,7 @@ class StarNode(ArithNode): class DivNode(ArithNode): pass -class NotNode(Node): +class NotNode(InstructionNode): def __init__(self, value, result): self.value = value self.result = result @@ -109,6 +109,18 @@ class AllocateNode(InstructionNode): def __init__(self, type, addr): self.type = type self.addr = addr + +class AbortNode(InstructionNode): + pass + +class ReadIntNode(InstructionNode): + def __init__(self, result): + self.result=result + +class CopyNode(InstructionNode): + def __init__(self, val, result): + self.result=result + self.val=val class TypeOfNode(InstructionNode): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index bdb4602c..aa4e8da1 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -124,13 +124,13 @@ def in_string_to_cil(): return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) def in_int_to_cil(): - pass + return cil.FuncNode('IO_in_int', [cil.ParamNode('self')], [cil.LocalNode('int')], [cil.ReadIntNode('int'), cil.ReturnNode('int')]) def type_name_to_cil(): - pass + return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type')], [cil.TypeOfNode('type', 'self'), cil.ReturnNode('type')]) def copy_to_cil(): - pass + return cil.FuncNode('Object_copy', [cil.ParamNode('self')], [cil.LocalNode('copy')], [cil.CopyNode('self', 'copy'), cil.ReturnNode('copy')]) def length_to_cil(): return cil.FuncNode('length_String', [cil.ParamNode('self')], [cil.LocalNode('result')], [cil.LengthNode('self', 'result'), cil.ReturnNode('result')]) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 808ee076..f8ea2b87 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -177,6 +177,14 @@ def read_cg_visitor(read: ReadNode): def print_cg_visitor(print: PrintNode): return f'PRINT {print.str} ;' +def abort_cg_visitor(abort:AbortNode): + return 'ABORT ;' + +def read_int_cg_visitor(ri:ReadIntNode): + return f'{ri.result} = READINT ;' + +def copy_cg_visitor(copy:CopyNode): + return f'{copy.result} = COPY {copy.val} ;' __visitors__ = { AssignNode: assign_cg_visitor, @@ -205,5 +213,8 @@ def print_cg_visitor(print: PrintNode): StrNode: str_cg_visitor, ReadNode: read_cg_visitor, PrintNode: print_cg_visitor, - NotNode: not_cg_visitor + NotNode: not_cg_visitor, + AbortNode:abort_cg_visitor, + ReadIntNode: read_int_cg_visitor, + CopyNode:copy_cg_visitor } From 4964ae1d9c7c0ce97dc2f31c75a49203d1c08207 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 21 May 2020 15:00:39 -0400 Subject: [PATCH 229/435] removing commented exception handling --- src/code_generation/cil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index aa4e8da1..6a0bd6b2 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -163,10 +163,10 @@ def func_to_cil_visitor(type_name, func): def expression_to_cil_visitor(expression): - #try: + try: return __visitor__[type(expression)](expression) - #except: - #raise Exception(f'There is no visitor for {type(expression)}') + except: + raise Exception(f'There is no visitor for {type(expression)}') def case_to_cil_visitor(case): From 65d2f4084626aa07cfa2a798f28e0b853685f782 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 21 May 2020 15:02:34 -0400 Subject: [PATCH 230/435] fixing error --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 6a0bd6b2..181e272d 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -164,7 +164,7 @@ def func_to_cil_visitor(type_name, func): def expression_to_cil_visitor(expression): try: - return __visitor__[type(expression)](expression) + return __visitor__[type(expression)](expression) except: raise Exception(f'There is no visitor for {type(expression)}') From 31891399df89c1078fa268b16c1419c1d94d2fdc Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 21 May 2020 19:15:39 -0400 Subject: [PATCH 231/435] adding less equal and less to cil --- src/code_generation/ast.py | 6 ++++++ src/code_generation/cil.py | 27 ++++----------------------- src/code_generation/code.py | 12 ++++++++++-- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index af70fd9f..b5e533b2 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -72,6 +72,12 @@ class StarNode(ArithNode): class DivNode(ArithNode): pass +class LessEqNode(ArithNode): + pass + +class LessNode(ArithNode): + pass + class NotNode(InstructionNode): def __init__(self, value, result): self.value = value diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 181e272d..52173042 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -239,7 +239,7 @@ def if_to_cil_visitor(_if): label_2 = add_label() value = add_local() - body = [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + body = predicate.body+ [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ cil.AssignNode(value, then.value), cil.LabelNode(label_2)] @@ -282,36 +282,17 @@ def lessthan_to_cil_visitor(lessthan): l = expression_to_cil_visitor(lessthan.lvalue) r = expression_to_cil_visitor(lessthan.rvalue) - cil_result = add_label() - end_label = add_label() value = add_local() - - body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), - cil.ConditionalGotoNode( - cil_result, end_label), cil.AssignNode(value, 1), - cil.LabelNode(end_label)] - + body = l.body + r.body + [cil.LessNode(l.value, r.value, value)] return CIL_block(body, value) def lesseqthan_to_cil_visitor(lessthan): l = expression_to_cil_visitor(lessthan.lvalue) r = expression_to_cil_visitor(lessthan.rvalue) - - cil_less = add_local() - cil_equal = add_local() - eq_label = add_label() - end_label = add_label() + value = add_local() - - body = l.body + r.body + [cil.DivNode(l.value, r.value, cil_less), cil.AssignNode(value, 0), - cil.ConditionalGotoNode( - cil_less, eq_label), cil.AssignNode(value, 1), - cil.GotoNode(end_label), cil.LabelNode(eq_label), - cil.MinusNode(l.value, r.value, cil_equal), cil.ConditionalGotoNode( - cil_equal, end_label), - cil.AssignNode(value, 1), cil.LabelNode(end_label)] - + body = l.body + r.body + [cil.LessEqNode(l.value, r.value, value)] return CIL_block(body, value) diff --git a/src/code_generation/code.py b/src/code_generation/code.py index f8ea2b87..68b4195c 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -67,13 +67,19 @@ def instruction_cg_visitor(instruction: InstructionNode): try: return __visitors__[type(instruction)](instruction) except KeyError: - print(type(instruction)) print(f'Not visitor for {instruction}') def assign_cg_visitor(assign: AssignNode): return f'{assign.id} = {assign.val} ;' +def less_eq_cg_visitor(lesseq:LessEqNode): + return f'{lesseq.result} = {lesseq.left} <= {lesseq.right} ;' + + +def less_cg_visitor(less:LessNode): + return f'{less.result} = {less.left} < {less.right} ;' + def plus_cg_visitor(plus: PlusNode): return f'{plus.result} = {plus.left} + {plus.right} ;' @@ -216,5 +222,7 @@ def copy_cg_visitor(copy:CopyNode): NotNode: not_cg_visitor, AbortNode:abort_cg_visitor, ReadIntNode: read_int_cg_visitor, - CopyNode:copy_cg_visitor + CopyNode:copy_cg_visitor, + LessEqNode:less_eq_cg_visitor, + LessNode:less_cg_visitor } From 76f3bb674ac50f06145ac5ad5f5cc378a5188ea6 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 11:48:02 -0400 Subject: [PATCH 232/435] Add class Local --- src/code_generation/cil.py | 12 +++++++++++- src/lexer_parser/parsetab.py | 5 +++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 52173042..dc673d6c 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -16,11 +16,21 @@ def add_str_data(data: str): locals_count = 0 +class Local: + def __init__(self, name): + self.name = name + + def __repr__(self): + return self.name + + def __str__(self): + return self.name + def add_local(): global locals_count locals_count += 1 - return f'local_{locals_count}' + return Local(f'local_{locals_count}') def add_label(): global labels_count diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index d0d73f0c..e821d12b 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From d08f8d0bf3d5e68fd36652ca64457835936b653f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 11:48:30 -0400 Subject: [PATCH 233/435] Reformat code in cil.py --- src/code_generation/cil.py | 57 +++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index dc673d6c..108fc3fb 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -16,6 +16,7 @@ def add_str_data(data: str): locals_count = 0 + class Local: def __init__(self, name): self.name = name @@ -32,9 +33,10 @@ def add_local(): locals_count += 1 return Local(f'local_{locals_count}') + def add_label(): global labels_count - labels_count+=1 + labels_count += 1 return f'label_{labels_count}' @@ -113,7 +115,7 @@ def program_to_cil_visitor(program): if type(f) == DefFuncNode: fun = func_to_cil_visitor(c.type, f) code.append(fun) - + code += built_in_to_cil() data = [cil.DataNode(__DATA__[data_value], data_value) @@ -121,35 +123,46 @@ def program_to_cil_visitor(program): return cil.ProgramNode(types, data, code) + def built_in_to_cil(): return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil()] - + + def out_string_to_cil(): - return cil.FuncNode('IO_out_string', [cil.ParamNode('self'),cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + return cil.FuncNode('IO_out_string', [cil.ParamNode('self'), cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + def out_int_to_cil(): - return cil.FuncNode('IO_out_int', [cil.ParamNode('self'),cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) + return cil.FuncNode('IO_out_int', [cil.ParamNode('self'), cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) + def in_string_to_cil(): return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) + def in_int_to_cil(): return cil.FuncNode('IO_in_int', [cil.ParamNode('self')], [cil.LocalNode('int')], [cil.ReadIntNode('int'), cil.ReturnNode('int')]) + def type_name_to_cil(): return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type')], [cil.TypeOfNode('type', 'self'), cil.ReturnNode('type')]) + def copy_to_cil(): return cil.FuncNode('Object_copy', [cil.ParamNode('self')], [cil.LocalNode('copy')], [cil.CopyNode('self', 'copy'), cil.ReturnNode('copy')]) + def length_to_cil(): return cil.FuncNode('length_String', [cil.ParamNode('self')], [cil.LocalNode('result')], [cil.LengthNode('self', 'result'), cil.ReturnNode('result')]) + def concat_to_cil(): return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [cil.LocalNode('result')], [cil.ConcatNode('self', 'x', 'result'), cil.ReturnNode('result')]) + def substring_to_cil(): - return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'),cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l','result'), cil.ReturnNode('result')]) + return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'), cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l', 'result'), cil.ReturnNode('result')]) + def func_to_cil_visitor(type_name, func): global locals_count, __DATA_LOCALS__, __TYPEOF__, labels_count @@ -165,7 +178,7 @@ def func_to_cil_visitor(type_name, func): instruction = expression_to_cil_visitor( func.expressions) body += instruction.body - + body.append(cil.ReturnNode(instruction.value)) _locals = [cil.LocalNode(f'local_{i + 1}') for i in range(locals_count)] @@ -249,7 +262,7 @@ def if_to_cil_visitor(_if): label_2 = add_label() value = add_local() - body = predicate.body+ [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + body = predicate.body + [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ cil.AssignNode(value, then.value), cil.LabelNode(label_2)] @@ -300,7 +313,7 @@ def lessthan_to_cil_visitor(lessthan): def lesseqthan_to_cil_visitor(lessthan): l = expression_to_cil_visitor(lessthan.lvalue) r = expression_to_cil_visitor(lessthan.rvalue) - + value = add_local() body = l.body + r.body + [cil.LessEqNode(l.value, r.value, value)] return CIL_block(body, value) @@ -320,23 +333,22 @@ def id_to_cil_visitor(id): def new_to_cil_visitor(new_node): value = add_local() - t=new_node.type - body=[] - - if t=='SELF_TYPE': - t, need_typeof=get_typeof(t,'self') + t = new_node.type + body = [] + + if t == 'SELF_TYPE': + t, need_typeof = get_typeof(t, 'self') if need_typeof: - body.append(cil.TypeOfNode(t,'self')) - + body.append(cil.TypeOfNode(t, 'self')) + body.append(cil.AllocateNode(t, value)) init_attr = TypesByName[t].get_all_attributes() - for attr in init_attr: if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) - body+=attr_cil.body + body += attr_cil.body body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) return CIL_block(body, value) @@ -362,6 +374,7 @@ def string_to_cil_visitor(str): return CIL_block(body, str_id) + def let_to_cil_visitor(let): body = [] for attr in let.let_attrs: @@ -466,10 +479,10 @@ def func_call_to_cil_visitor(call): lp_ast.VarNode: id_to_cil_visitor, lp_ast.FuncCallNode: func_call_to_cil_visitor, lp_ast.IsVoidNode: is_void_to_cil_visitor, - lp_ast.NegationNode: not_to_cil_visitor, - lp_ast.LessThanNode:lessthan_to_cil_visitor, - lp_ast.LessEqNode:lesseqthan_to_cil_visitor, - lp_ast.CaseNode:case_to_cil_visitor, + lp_ast.NegationNode: not_to_cil_visitor, + lp_ast.LessThanNode: lessthan_to_cil_visitor, + lp_ast.LessEqNode: lesseqthan_to_cil_visitor, + lp_ast.CaseNode: case_to_cil_visitor, } From c66a53d2a27dd2c46393a2208343090cae561f5c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 12:18:27 -0400 Subject: [PATCH 234/435] Change locals_count for __LOCALS __ --- src/code_generation/ast.py | 6 ++++++ src/code_generation/cil.py | 26 ++++++++------------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index b5e533b2..95dff7a0 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -37,6 +37,12 @@ class InstructionNode(Node): class LocalNode(Node): def __init__(self, id): self.id = id + + def __str__(self): + return self.id + + def __repr__(self): + return self.id class ParamNode(Node): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 108fc3fb..6c148ac5 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -14,24 +14,14 @@ def add_str_data(data: str): return __DATA__[data] -locals_count = 0 - - -class Local: - def __init__(self, name): - self.name = name - - def __repr__(self): - return self.name - - def __str__(self): - return self.name +__LOCALS__ = [] def add_local(): - global locals_count - locals_count += 1 - return Local(f'local_{locals_count}') + global __LOCALS__ + local = cil.LocalNode(f'local_{len(__LOCALS__)}') + __LOCALS__.append(local) + return local def add_label(): @@ -165,11 +155,11 @@ def substring_to_cil(): def func_to_cil_visitor(type_name, func): - global locals_count, __DATA_LOCALS__, __TYPEOF__, labels_count + global __LOCALS__, __DATA_LOCALS__, __TYPEOF__, labels_count name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] - locals_count = 0 + __LOCALS__ = [] labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} @@ -181,7 +171,7 @@ def func_to_cil_visitor(type_name, func): body.append(cil.ReturnNode(instruction.value)) - _locals = [cil.LocalNode(f'local_{i + 1}') for i in range(locals_count)] + _locals = __LOCALS__.copy() return cil.FuncNode(name, params, _locals, body) From 2defc9ebc2683a02ae820c1a98d8da1b6e1c9940 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 18:47:18 -0400 Subject: [PATCH 235/435] Add built_ind_code to ProgramNode --- src/code_generation/ast.py | 3 ++- src/code_generation/cil.py | 5 +++-- src/code_generation/code.py | 32 ++++++++++++++++++++------------ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 95dff7a0..8fed0b00 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -3,10 +3,11 @@ class Node: class ProgramNode(Node): - def __init__(self, types, data, code): + def __init__(self, types, data, code, built_in_code): self.types = types self.data = data self.code = code + self.built_in_code = built_in_code class TypeNode(Node): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 6c148ac5..cc66c688 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -63,6 +63,7 @@ def get_typeof(obj): def program_to_cil_visitor(program): types = [] code = [] + built_in_code = [] # completing .TYPE section for t in TypesByName: @@ -96,7 +97,7 @@ def program_to_cil_visitor(program): [cil.AllocateNode('Main', main_instance), cil.ArgNode(main_instance), cil.VCAllNode('Main', 'main', main_result)]) - code.append(main_function) + built_in_code.append(main_function) # completing .CODE and .DATA sections @@ -106,7 +107,7 @@ def program_to_cil_visitor(program): fun = func_to_cil_visitor(c.type, f) code.append(fun) - code += built_in_to_cil() + built_in_code += built_in_to_cil() data = [cil.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 68b4195c..50e51ac5 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -17,6 +17,8 @@ def program_cg_visitor(program: ProgramNode): type_code += f'{type_cg_visitor(t)}\n' for d in program.data: data_code += f'{data_cg_visitor(d)}\n' + for f in program.built_in_code: + func_code += f'{func_cg_visitor(f)}\n' for f in program.code: func_code += f'{func_cg_visitor(f)}\n' @@ -73,11 +75,12 @@ def instruction_cg_visitor(instruction: InstructionNode): def assign_cg_visitor(assign: AssignNode): return f'{assign.id} = {assign.val} ;' -def less_eq_cg_visitor(lesseq:LessEqNode): + +def less_eq_cg_visitor(lesseq: LessEqNode): return f'{lesseq.result} = {lesseq.left} <= {lesseq.right} ;' -def less_cg_visitor(less:LessNode): +def less_cg_visitor(less: LessNode): return f'{less.result} = {less.left} < {less.right} ;' @@ -140,7 +143,8 @@ def arg_cg_visitor(arg: ArgNode): def cond_goto_cg_visitor(cgoto: ConditionalGotoNode): return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' -def not_cg_visitor(n:NotNode): + +def not_cg_visitor(n: NotNode): return f'{n.result} = ~ {n.value}' @@ -183,15 +187,19 @@ def read_cg_visitor(read: ReadNode): def print_cg_visitor(print: PrintNode): return f'PRINT {print.str} ;' -def abort_cg_visitor(abort:AbortNode): + +def abort_cg_visitor(abort: AbortNode): return 'ABORT ;' -def read_int_cg_visitor(ri:ReadIntNode): + +def read_int_cg_visitor(ri: ReadIntNode): return f'{ri.result} = READINT ;' -def copy_cg_visitor(copy:CopyNode): + +def copy_cg_visitor(copy: CopyNode): return f'{copy.result} = COPY {copy.val} ;' + __visitors__ = { AssignNode: assign_cg_visitor, PlusNode: plus_cg_visitor, @@ -219,10 +227,10 @@ def copy_cg_visitor(copy:CopyNode): StrNode: str_cg_visitor, ReadNode: read_cg_visitor, PrintNode: print_cg_visitor, - NotNode: not_cg_visitor, - AbortNode:abort_cg_visitor, - ReadIntNode: read_int_cg_visitor, - CopyNode:copy_cg_visitor, - LessEqNode:less_eq_cg_visitor, - LessNode:less_cg_visitor + NotNode: not_cg_visitor, + AbortNode: abort_cg_visitor, + ReadIntNode: read_int_cg_visitor, + CopyNode: copy_cg_visitor, + LessEqNode: less_eq_cg_visitor, + LessNode: less_cg_visitor } From 770202dd56baabd6f043372b553aa422c059fe8d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 18:50:21 -0400 Subject: [PATCH 236/435] Add "locals" variable to InstructionNode The "locales" variable saves the locals that are used for the instruction --- src/code_generation/ast.py | 75 +++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 8fed0b00..131f176c 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -32,13 +32,18 @@ def __init__(self, name, params, locals, body): class InstructionNode(Node): - pass + def __init__(self): + self.locals = [] + + def check_local(self, var): + if type(var) is LocalNode: + self.locals.append(var) class LocalNode(Node): def __init__(self, id): self.id = id - + def __str__(self): return self.id @@ -53,15 +58,22 @@ def __init__(self, id): class AssignNode(InstructionNode): def __init__(self, id, val): + super().__init__() self.id = id self.val = val + self.check_local(id) + self.check_local(val) class ArithNode(InstructionNode): def __init__(self, left, right, result): + super().__init__() self.left = left self.right = right self.result = result + self.check_local(left) + self.check_local(right) + self.check_local(result) class PlusNode(ArithNode): @@ -79,16 +91,23 @@ class StarNode(ArithNode): class DivNode(ArithNode): pass + class LessEqNode(ArithNode): pass + class LessNode(ArithNode): pass + class NotNode(InstructionNode): def __init__(self, value, result): + super().__init__() self.value = value self.result = result + self.check_local(value) + self.check_local(result) + class GetAttrNode(InstructionNode): def __init__(self, obj, attr, result): @@ -99,9 +118,12 @@ def __init__(self, obj, attr, result): class SetAttrNode(InstructionNode): def __init__(self, obj, attr, val): + super().__init__() self.val = val self.obj = obj self.attr = attr + self.check_local(obj) + self.check_local(val) class SetIndexNode(InstructionNode): @@ -119,27 +141,35 @@ def __init__(self, array, index, result): class AllocateNode(InstructionNode): - def __init__(self, type, addr): - self.type = type + def __init__(self, _type, addr): + super().__init__() + self.type = _type self.addr = addr - + self.check_local(addr) + + class AbortNode(InstructionNode): pass + class ReadIntNode(InstructionNode): def __init__(self, result): - self.result=result - + self.result = result + + class CopyNode(InstructionNode): def __init__(self, val, result): - self.result=result - self.val=val + self.result = result + self.val = val class TypeOfNode(InstructionNode): def __init__(self, result, var): + super().__init__() self.result = result self.var = var + self.check_local(result) + self.check_local(var) class ArrayNode(InstructionNode): @@ -156,41 +186,54 @@ def __init__(self, method, result): class VCAllNode(InstructionNode): def __init__(self, type, method, result): + super().__init__() self.method = method self.type = type self.result = result + self.check_local(result) + self.check_local(type) class ArgNode(InstructionNode): def __init__(self, val): + super().__init__() self.val = val + self.check_local(val) class ConditionalGotoNode(InstructionNode): def __init__(self, predicate, label): + super().__init__() self.predicate = predicate self.label = label + self.check_local(predicate) class GotoNode(InstructionNode): def __init__(self, label): + super().__init__() self.label = label class LabelNode(InstructionNode): def __init__(self, label_name): + super().__init__() self.label_name = label_name class ReturnNode(InstructionNode): def __init__(self, ret_value): + super().__init__() self.ret_value = ret_value + self.check_local(ret_value) class LoadNode(InstructionNode): def __init__(self, addr, result): + super().__init__() self.result = result self.addr = addr + self.check_local(result) class LengthNode(InstructionNode): @@ -207,25 +250,31 @@ def __init__(self, str_a, str_b, result): class SubStringNode(InstructionNode): - def __init__(self,str, i, len, result): + def __init__(self, str, i, len, result): self.result = result self.i = i self.len = len - self.str=str + self.str = str class StrNode(InstructionNode): def __init__(self, val, str): + super().__init__() self.str = str self.val = val + self.check_local(val) + self.check_local(str) class ReadNode(InstructionNode): def __init__(self, val): - self.val=val - + super().__init__() + self.val = val + self.check_local(val) class PrintNode(InstructionNode): def __init__(self, str): + super().__init__() self.str = str + self.check_local(str) From 8c7f6256c9b0d5fc9beb6c756ba1c8a43ffbd87f Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 22 May 2020 18:58:02 -0400 Subject: [PATCH 237/435] Add optimization of LOCALS Initial implementation --- src/code_generation/cil.py | 5 ++- src/code_generation/optimization.py | 55 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/code_generation/optimization.py diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index cc66c688..6182dda4 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,6 +1,7 @@ import code_generation.ast as cil import lexer_parser.ast as lp_ast from semantic.types import * +from .optimization import optimization_locals __DATA__ = {} @@ -112,7 +113,9 @@ def program_to_cil_visitor(program): data = [cil.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] - return cil.ProgramNode(types, data, code) + cil_program = cil.ProgramNode(types, data, code, built_in_code) + optimization_locals(cil_program) + return cil_program def built_in_to_cil(): diff --git a/src/code_generation/optimization.py b/src/code_generation/optimization.py new file mode 100644 index 00000000..91b2587a --- /dev/null +++ b/src/code_generation/optimization.py @@ -0,0 +1,55 @@ +from .ast import * + + +def optimization_locals(program: ProgramNode): + # Each local have a start and end index + # Index is the instruction index + for function in program.code: + intervals = {} + unnecessary = [] + for local in function.locals: + # Search initial index of local + start = 0 + for index, instruction in enumerate(function.body): + if local in instruction.locals: + start = index + break + else: + # If local is not in any statement then it is marked as unused + unnecessary.append(local) + continue + # Search end index of local + end = start + for index, instruction in enumerate(function.body[start:]): + if local in instruction.locals: + end = start + index + intervals[local] = (start, end) + + # Build and sort new tuples (start,end,localID) + a = [] + for x in intervals.keys(): + s, e = intervals[x] + a.append((s, e, x)) + # Keep final locals + final_locals = [] + if len(a) != 0: + final_locals.append(a[0]) + for l in a[1:]: + s, e, x = l + for index in range(len(final_locals)): + s2, e2, y = final_locals[index] + if e2 < s: + unnecessary.append(x) + x.id = y.id + final_locals[index] = (s2, e, y) + break + elif e < s2: + unnecessary.append(x) + x.id = y.id + final_locals[index] = (s, e2, y) + break + else: + final_locals.append(l) + # Remove unnnecessary locals + for u in unnecessary: + function.locals.remove(u) From 0783169c3ed5f94c110a56d8adc1d249f03f20a1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 23 May 2020 19:47:56 -0400 Subject: [PATCH 238/435] fixing bugs --- src/code_generation/cil.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 52173042..31138c3b 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -4,7 +4,6 @@ __DATA__ = {} - def add_str_data(data: str): try: return __DATA__[data] @@ -14,8 +13,7 @@ def add_str_data(data: str): return __DATA__[data] -locals_count = 0 - +locals_count = 0 def add_local(): global locals_count @@ -58,6 +56,10 @@ def get_typeof(obj): return type_local, True + +__ATTR__ = {} +__CURRENT_TYPE__=None + def program_to_cil_visitor(program): types = [] code = [] @@ -66,8 +68,10 @@ def program_to_cil_visitor(program): for t in TypesByName: _type = cil.TypeNode(t) value = TypesByName[t] + __ATTR__[t]=[] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) + __ATTR__[t].append(attr.id) for met in value.get_all_inherited_methods(): _type.methods[met.id] = met.owner @@ -142,7 +146,7 @@ def substring_to_cil(): return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'),cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l','result'), cil.ReturnNode('result')]) def func_to_cil_visitor(type_name, func): - global locals_count, __DATA_LOCALS__, __TYPEOF__, labels_count + global locals_count, __DATA_LOCALS__, __TYPEOF__, labels_count, __CURRENT_TYPE__ name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] @@ -150,6 +154,7 @@ def func_to_cil_visitor(type_name, func): labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} + __CURRENT_TYPE__=type_name body = [] instruction = expression_to_cil_visitor( @@ -200,10 +205,13 @@ def case_to_cil_visitor(case): def assign_to_cil_visitor(assign): + expr = expression_to_cil_visitor(assign.expr) - value = [add_local()] - body = expr.body + [cil.AssignNode(assign.id, expr.value)] - return CIL_block(body, value) + if assign.id in __ATTR__[__CURRENT_TYPE__]: + body=expr.body + [cil.SetAttrNode('self', assign.id, expr.value)] + else: + body = expr.body + [cil.AssignNode(assign.id, expr.value)] + return CIL_block(body, assign.id) def arith_to_cil_visitor(arith): @@ -239,7 +247,7 @@ def if_to_cil_visitor(_if): label_2 = add_label() value = add_local() - body = predicate.body+ [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + body = predicate.body + [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ cil.AssignNode(value, then.value), cil.LabelNode(label_2)] @@ -253,11 +261,12 @@ def loop_to_cil_visitor(loop): value = add_local() + predicate_label=add_label() loop_label = add_label() end_label = add_label() - body = [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), - cil.LabelNode(loop_label)] + loop_block.body + [cil.LabelNode(end_label), cil.AssignNode(value, 0)] + body = [cil.LabelNode(predicate_label)] + predicate.body + [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), + cil.LabelNode(loop_label)] + loop_block.body + [cil.GotoNode(predicate_label),cil.LabelNode(end_label), cil.AssignNode(value, 0)] return CIL_block(body, value) @@ -305,6 +314,9 @@ def bool_to_cil_visitor(bool): def id_to_cil_visitor(id): + if id.id in __ATTR__[__CURRENT_TYPE__]: + result=add_local() + return CIL_block([cil.GetAttrNode('self', id.id, result)], result) return CIL_block([], id.id) From f82dae79dcc68bed49c0a5c922a5725622e68ce8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 24 May 2020 13:36:46 -0400 Subject: [PATCH 239/435] Add header to semantic files --- src/semantic/__init__.py | 6 ++++++ src/semantic/semantic.py | 6 ++++++ src/semantic/types.py | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/semantic/__init__.py b/src/semantic/__init__.py index 226d5515..739fdfa0 100644 --- a/src/semantic/__init__.py +++ b/src/semantic/__init__.py @@ -1,2 +1,8 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + from .semantic import semantic_check from .types import TypesByName diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index d8b11eef..a5a227e3 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + from .types import * diff --git a/src/semantic/types.py b/src/semantic/types.py index b5d3cfd7..fefe1b77 100644 --- a/src/semantic/types.py +++ b/src/semantic/types.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + from errors import add_semantic_error from lexer_parser.ast import * From ac6185e9baed8e2b92c73915300e42b111249c7a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 24 May 2020 13:38:03 -0400 Subject: [PATCH 240/435] Add header to lexer/parser files --- src/lexer_parser/__init__.py | 6 ++++++ src/lexer_parser/ast.py | 6 ++++++ src/lexer_parser/lexer.py | 6 ++++++ src/lexer_parser/parser.py | 18 ++++++++++++++---- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/lexer_parser/__init__.py b/src/lexer_parser/__init__.py index 49e147dc..af0921b1 100644 --- a/src/lexer_parser/__init__.py +++ b/src/lexer_parser/__init__.py @@ -1,2 +1,8 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + from .lexer import lexer from .parser import parser diff --git a/src/lexer_parser/ast.py b/src/lexer_parser/ast.py index 869bb850..680e8743 100644 --- a/src/lexer_parser/ast.py +++ b/src/lexer_parser/ast.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + class AstNode: def __init__(self): self.lineno = 0 diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index 43dbc0b2..ba184d8a 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + import ply.lex as lex from errors import add_lexer_error diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index 9e3b25f1..d3567e2c 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + import ply.yacc as yacc from errors import add_parser_error @@ -131,17 +137,20 @@ def p_expr_func_all(p): if p[7] is None: p[7] = [] p[0] = FuncCallNode(p[5], p[7], p[1], p[3]) - p[0].add_location(p.lineno(5), find_column(p.lexer.lexdata, p.lexpos(5))) + p[0].add_location(p.lineno(5), find_column( + p.lexer.lexdata, p.lexpos(5))) elif len(p) == 7: if p[5] is None: p[5] = [] p[0] = FuncCallNode(p[3], p[5], p[1]) - p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) + p[0].add_location(p.lineno(3), find_column( + p.lexer.lexdata, p.lexpos(3))) else: if p[3] is None: p[3] = [] p[0] = FuncCallNode(p[1], p[3]) - p[0].add_location(p.lineno(1), find_column(p.lexer.lexdata, p.lexpos(1))) + p[0].add_location(p.lineno(1), find_column( + p.lexer.lexdata, p.lexpos(1))) p[0].lineno = p.lineno(0) @@ -286,7 +295,8 @@ def p_block_list(p): def p_error(p): if p: - add_parser_error(p.lineno, find_column(p.lexer.lexdata, p.lexpos), f'ERROR at or near \'{p.value}\'') + add_parser_error(p.lineno, find_column( + p.lexer.lexdata, p.lexpos), f'ERROR at or near \'{p.value}\'') else: add_parser_error(0, 0, "ERROR at or near EOF") From 18fae4c99bcb9ce98997f2ceb1f7c10eb9cf619d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 24 May 2020 13:39:48 -0400 Subject: [PATCH 241/435] Add header to eerors files --- src/errors/__init__.py | 6 ++++++ src/errors/errors.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/errors/__init__.py b/src/errors/__init__.py index 0179aa8a..6320c4b7 100644 --- a/src/errors/__init__.py +++ b/src/errors/__init__.py @@ -1 +1,7 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + from .errors import * diff --git a/src/errors/errors.py b/src/errors/errors.py index 079babe4..2fac0c43 100644 --- a/src/errors/errors.py +++ b/src/errors/errors.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + LEXER_ERRORS = [] PARSER_ERRORS = [] SEMANTIC_ERRORS = [] From 15070d84d3263a97b3302b39a4392ae94260d8e1 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 24 May 2020 13:41:15 -0400 Subject: [PATCH 242/435] Add headers to main and utils files --- src/main.py | 6 ++++++ src/utils.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/main.py b/src/main.py index 2f97fe85..d9e02dc5 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + import sys import errors as err diff --git a/src/utils.py b/src/utils.py index 743031b0..30bf6c2e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,3 +1,9 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + def find_column(text, pos): line_start = text.rfind('\n', 0, pos) + 1 return (pos - line_start) + 1 From 33aaf1d58733c9612217a8c767dfdc12a6e0152d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 24 May 2020 13:46:40 -0400 Subject: [PATCH 243/435] Clean --- src/__init__.py | 0 src/lexer_parser/lexer.py | 2 +- src/{ => lexer_parser}/utils.py | 0 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 src/__init__.py rename src/{ => lexer_parser}/utils.py (100%) diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index ba184d8a..fbe2569f 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -7,7 +7,7 @@ import ply.lex as lex from errors import add_lexer_error -from utils import * +from .utils import * states = ( ('commentLine', 'exclusive'), diff --git a/src/utils.py b/src/lexer_parser/utils.py similarity index 100% rename from src/utils.py rename to src/lexer_parser/utils.py From 4b2418af5b6a77bf747981b1291ff3d12ed3ffb6 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 25 May 2020 18:06:51 -0400 Subject: [PATCH 244/435] fixing style --- src/code_generation/cil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 31138c3b..e89947f6 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -154,7 +154,7 @@ def func_to_cil_visitor(type_name, func): labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} - __CURRENT_TYPE__=type_name + __CURRENT_TYPE__ = type_name body = [] instruction = expression_to_cil_visitor( @@ -275,7 +275,7 @@ def equal_to_cil_visitor(equal): l = expression_to_cil_visitor(equal.lvalue) r = expression_to_cil_visitor(equal.rvalue) - cil_result = add_label() + cil_result = add_local() end_label = add_label() value = add_local() From ca4c0f4c71732f6bdb99c67dd569afb0e38aec0d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Mon, 25 May 2020 18:18:43 -0400 Subject: [PATCH 245/435] fix getattrnode --- src/code_generation/ast.py | 3 + src/lexer_parser/parsetab.py | 115 +++++++++++++++++------------------ 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 131f176c..27bce84b 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -111,9 +111,12 @@ def __init__(self, value, result): class GetAttrNode(InstructionNode): def __init__(self, obj, attr, result): + super().__init__() self.attr = attr self.obj = obj self.result = result + self.check_local(obj) + self.check_local(result) class SetAttrNode(InstructionNode): diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index e821d12b..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} @@ -27,59 +26,59 @@ del _lr_goto_items _lr_productions = [ ("S' -> program","S'",1,None,None,None), - ('program -> class_list','program',1,'p_program','parser.py',20), - ('empty -> ','empty',0,'p_empty','parser.py',25), - ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',30), - ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',31), - ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',40), - ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',41), - ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',51), - ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',52), - ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',53), - ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',61), - ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',62), - ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',72), - ('params -> param_list','params',1,'p_params_ne','parser.py',78), - ('params -> empty','params',1,'p_params_e','parser.py',83), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',88), - ('param_list -> param empty','param_list',2,'p_param_list','parser.py',89), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',97), - ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',103), - ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',104), - ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',105), - ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',106), - ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',121), - ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',127), - ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',128), - ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',129), - ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',150), - ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',151), - ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',152), - ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',153), - ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',154), - ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',155), - ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',156), - ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',176), - ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',177), - ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',178), - ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',190), - ('expr -> atom','expr',1,'p_expr_atom','parser.py',195), - ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',200), - ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',201), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',209), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',210), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',218), - ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',224), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',225), - ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',230), - ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',231), - ('atom -> INT','atom',1,'p_atom_int','parser.py',239), - ('atom -> ID','atom',1,'p_atom_id','parser.py',245), - ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',251), - ('atom -> block','atom',1,'p_atom_block','parser.py',257), - ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',262), - ('atom -> STRING','atom',1,'p_atom_atring','parser.py',268), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',274), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',279), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',280), + ('program -> class_list','program',1,'p_program','parser.py',26), + ('empty -> ','empty',0,'p_empty','parser.py',31), + ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',36), + ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',37), + ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',46), + ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',47), + ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',57), + ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',58), + ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',59), + ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',67), + ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',68), + ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',78), + ('params -> param_list','params',1,'p_params_ne','parser.py',84), + ('params -> empty','params',1,'p_params_e','parser.py',89), + ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',94), + ('param_list -> param empty','param_list',2,'p_param_list','parser.py',95), + ('param -> ID COLON TYPE','param',3,'p_param','parser.py',103), + ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',109), + ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',110), + ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',111), + ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',112), + ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',127), + ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',133), + ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',134), + ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',135), + ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',159), + ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',160), + ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',161), + ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',162), + ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',163), + ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',164), + ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',165), + ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',185), + ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',186), + ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',187), + ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',199), + ('expr -> atom','expr',1,'p_expr_atom','parser.py',204), + ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',209), + ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',210), + ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',218), + ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',219), + ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',227), + ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',233), + ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',234), + ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',239), + ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',240), + ('atom -> INT','atom',1,'p_atom_int','parser.py',248), + ('atom -> ID','atom',1,'p_atom_id','parser.py',254), + ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',260), + ('atom -> block','atom',1,'p_atom_block','parser.py',266), + ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',271), + ('atom -> STRING','atom',1,'p_atom_atring','parser.py',277), + ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',283), + ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',288), + ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',289), ] From d5505e9bbebc89491cbd58411f5d55296fcc9df6 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 26 May 2020 16:29:36 -0400 Subject: [PATCH 246/435] Add vars to locals --- src/code_generation/ast.py | 24 ++++++------ src/code_generation/cil.py | 73 +++++++++++++++++++++++++++++-------- src/code_generation/code.py | 8 ++-- 3 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/code_generation/ast.py b/src/code_generation/ast.py index 27bce84b..1b6077f6 100644 --- a/src/code_generation/ast.py +++ b/src/code_generation/ast.py @@ -57,11 +57,11 @@ def __init__(self, id): class AssignNode(InstructionNode): - def __init__(self, id, val): + def __init__(self, result, val): super().__init__() - self.id = id + self.result = result self.val = val - self.check_local(id) + self.check_local(result) self.check_local(val) @@ -144,11 +144,11 @@ def __init__(self, array, index, result): class AllocateNode(InstructionNode): - def __init__(self, _type, addr): + def __init__(self, _type, result): super().__init__() self.type = _type - self.addr = addr - self.check_local(addr) + self.result = result + self.check_local(result) class AbortNode(InstructionNode): @@ -261,19 +261,19 @@ def __init__(self, str, i, len, result): class StrNode(InstructionNode): - def __init__(self, val, str): + def __init__(self, val, result): super().__init__() - self.str = str + self.result = result self.val = val self.check_local(val) - self.check_local(str) + self.check_local(result) class ReadNode(InstructionNode): - def __init__(self, val): + def __init__(self, result): super().__init__() - self.val = val - self.check_local(val) + self.result = result + self.check_local(result) class PrintNode(InstructionNode): diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 287f3545..c8e68267 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -1,7 +1,7 @@ import code_generation.ast as cil import lexer_parser.ast as lp_ast from semantic.types import * -from .optimization import optimization_locals +from .optimization import optimization_locals, remove_unused_locals __DATA__ = {} @@ -14,15 +14,23 @@ def add_str_data(data: str): return __DATA__[data] -__LOCALS__ = [] +__LOCALS__ = {} def add_local(): global __LOCALS__ - local = cil.LocalNode(f'local_{len(__LOCALS__)}') - __LOCALS__.append(local) + id=f'local_{len(__LOCALS__)}' + local = cil.LocalNode(id) + __LOCALS__[id]=local return local +def add_named_local(id): + global __LOCALS__ + local=cil.LocalNode(id) + __LOCALS__[id]=local + return local + +labels_count = 0 def add_label(): global labels_count @@ -62,7 +70,7 @@ def get_typeof(obj): __ATTR__ = {} -__CURRENT_TYPE__=None +__CURRENT_TYPE__ = None def program_to_cil_visitor(program): types = [] @@ -119,7 +127,8 @@ def program_to_cil_visitor(program): for data_value in __DATA__.keys()] cil_program = cil.ProgramNode(types, data, code, built_in_code) - optimization_locals(cil_program) + remove_unused_locals(cil_program) + #optimization_locals(cil_program) return cil_program @@ -144,7 +153,7 @@ def in_int_to_cil(): def type_name_to_cil(): - return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type')], [cil.TypeOfNode('type', 'self'), cil.ReturnNode('type')]) + return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.StrNode('type', 'str'),cil.ReturnNode('str')]) def copy_to_cil(): @@ -164,11 +173,18 @@ def substring_to_cil(): def func_to_cil_visitor(type_name, func): + ''' + Converts from FunctionNode in parsing AST to FuncionNode in cil AST. \n + 1) Builds ParamNodes for each param in FunctionNode.params\n + 2) Builds function body by putting together each instruction's body\n + 3) Creates an array of necessary local variables + + ''' global __LOCALS__, __DATA_LOCALS__, __TYPEOF__, labels_count, __CURRENT_TYPE__ name = f'{type_name}_{func.id}' params = [cil.ParamNode('self')] params += [cil.ParamNode(id) for (id, t) in func.params] - __LOCALS__ = [] + __LOCALS__ = {} labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} @@ -182,10 +198,14 @@ def func_to_cil_visitor(type_name, func): body.append(cil.ReturnNode(instruction.value)) _locals = __LOCALS__.copy() - return cil.FuncNode(name, params, _locals, body) + return cil.FuncNode(name, params, [_locals[k] for k in _locals.keys()], body) def expression_to_cil_visitor(expression): + ''' + Selects the appropriate CIL converter for each expression type and calls it. \n + If there is no appropriate CIL converter it throws the exception \'There is no visitor for [type(expression)]\' + ''' try: return __visitor__[type(expression)](expression) except: @@ -193,11 +213,21 @@ def expression_to_cil_visitor(expression): def case_to_cil_visitor(case): + ''' + CaseNode CIL converter.\n + 1) Attaches the body of case expression to instruction body.\n + 2) Finds out string repr of case expression dynamic type.\n + 3) For each branch it builts a labeled body in which it is compared branch type to case expression type.\n + 4) Inside the labeled body the branch expression body is attached. + + ''' body = [] expr_cil = expression_to_cil_visitor(case.expr) body += expr_cil.body t = add_local() body.append(cil.TypeOfNode(t, expr_cil.value)) + str_t = add_local() + body.append(cil.StrNode(t, str_t)) types = [] labels = [] for c in case.case_list: @@ -210,9 +240,10 @@ def case_to_cil_visitor(case): for i, branch in enumerate(case.case_list): predicate = add_local() - body.append(cil.MinusNode(t, branch.type, predicate)) + body.append(cil.MinusNode(str_t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) - body.append(cil.AssignNode(branch.id, expr_cil.value)) + val=add_named_local(branch.id) + body.append(cil.AssignNode(val, expr_cil.value)) branch_cil = expression_to_cil_visitor( branch.expr) body += branch_cil.body @@ -223,13 +254,20 @@ def case_to_cil_visitor(case): def assign_to_cil_visitor(assign): + + ''' + AssignNode CIL converter.\n + 1) Pendiente + ''' expr = expression_to_cil_visitor(assign.expr) if assign.id in __ATTR__[__CURRENT_TYPE__]: body=expr.body + [cil.SetAttrNode('self', assign.id, expr.value)] + return CIL_block(body, expr.value) else: - body = expr.body + [cil.AssignNode(assign.id, expr.value)] - return CIL_block(body, assign.id) + val=add_named_local(assign.id) + body = expr.body + [cil.AssignNode(val, expr.value)] + return CIL_block(body, val) def arith_to_cil_visitor(arith): @@ -335,7 +373,11 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result=add_local() return CIL_block([cil.GetAttrNode('self', id.id, result)], result) - return CIL_block([], id.id) + try: + val=__LOCALS__[id.id] + return CIL_block([], val) + except: + return CIL_block([], id.id) def new_to_cil_visitor(new_node): @@ -388,7 +430,8 @@ def let_to_cil_visitor(let): if attr.expr: attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body - body.append(cil.AssignNode(attr.id, attr_cil.value)) + val=add_named_local(attr.id) + body.append(cil.AssignNode(val, attr_cil.value)) expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body diff --git a/src/code_generation/code.py b/src/code_generation/code.py index 50e51ac5..bd9d88f4 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/code.py @@ -73,7 +73,7 @@ def instruction_cg_visitor(instruction: InstructionNode): def assign_cg_visitor(assign: AssignNode): - return f'{assign.id} = {assign.val} ;' + return f'{assign.result} = {assign.val} ;' def less_eq_cg_visitor(lesseq: LessEqNode): @@ -117,7 +117,7 @@ def set_index_cg_visitor(setindex: SetIndexNode): def allocate_cg_visitor(allocate: AllocateNode): - return f'{allocate.addr} = ALLOCATE {allocate.type} ;' + return f'{allocate.result} = ALLOCATE {allocate.type} ;' def typeof_cg_visitor(typeof: TypeOfNode): @@ -177,11 +177,11 @@ def substring_cg_visitor(substring: SubStringNode): def str_cg_visitor(str: StrNode): - return f'{str.str} = STR {str.val} ;' + return f'{str.result} = STR {str.val} ;' def read_cg_visitor(read: ReadNode): - return f'{read.val} = READ ;' + return f'{read.result} = READ ;' def print_cg_visitor(print: PrintNode): From a1b42266cb714d982750e6f71957895b13857c9a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 26 May 2020 16:29:51 -0400 Subject: [PATCH 247/435] removing unnecessary instructions and locals --- src/code_generation/optimization.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/code_generation/optimization.py b/src/code_generation/optimization.py index 91b2587a..f3a4d5be 100644 --- a/src/code_generation/optimization.py +++ b/src/code_generation/optimization.py @@ -53,3 +53,32 @@ def optimization_locals(program: ProgramNode): # Remove unnnecessary locals for u in unnecessary: function.locals.remove(u) + +def remove_unused_locals(program: ProgramNode): + for function in program.code: + used_locals=[] + for instruction in function.body: + for local in instruction.locals: + if local not in used_locals: + try: + if instruction.result.id!=local.id: + used_locals.append(local) + except: + used_locals.append(local) + body=(function.body).copy() + for instruction in function.body: + for local in instruction.locals: + try: + if instruction.result.id==local.id and local not in used_locals and type(InstructionNode)!=VCAllNode and type(InstructionNode)!=CallNode: + body.remove(instruction) + except: + pass + + function.body=body + function.locals=used_locals + + + + + + \ No newline at end of file From d02a92545fd65df1e03de4c4250e819162a0aa42 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 26 May 2020 16:33:17 -0400 Subject: [PATCH 248/435] removing commented portion of code --- src/code_generation/cil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index c8e68267..1f5df781 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -128,7 +128,7 @@ def program_to_cil_visitor(program): cil_program = cil.ProgramNode(types, data, code, built_in_code) remove_unused_locals(cil_program) - #optimization_locals(cil_program) + optimization_locals(cil_program) return cil_program From fd916798f92cdb0947f3aa49e6664454e06d8cdc Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 26 May 2020 18:18:00 -0400 Subject: [PATCH 249/435] merging add_local and add_named_local into one --- src/code_generation/cil.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/code_generation/cil.py b/src/code_generation/cil.py index 1f5df781..35ed63e7 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/cil.py @@ -17,19 +17,14 @@ def add_str_data(data: str): __LOCALS__ = {} -def add_local(): +def add_local(id=None): global __LOCALS__ - id=f'local_{len(__LOCALS__)}' + if id is None: + id=f'local_{len(__LOCALS__)}' local = cil.LocalNode(id) __LOCALS__[id]=local return local -def add_named_local(id): - global __LOCALS__ - local=cil.LocalNode(id) - __LOCALS__[id]=local - return local - labels_count = 0 def add_label(): @@ -242,7 +237,7 @@ def case_to_cil_visitor(case): predicate = add_local() body.append(cil.MinusNode(str_t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) - val=add_named_local(branch.id) + val=add_local(branch.id) body.append(cil.AssignNode(val, expr_cil.value)) branch_cil = expression_to_cil_visitor( branch.expr) @@ -265,7 +260,7 @@ def assign_to_cil_visitor(assign): body=expr.body + [cil.SetAttrNode('self', assign.id, expr.value)] return CIL_block(body, expr.value) else: - val=add_named_local(assign.id) + val=add_local(assign.id) body = expr.body + [cil.AssignNode(val, expr.value)] return CIL_block(body, val) @@ -430,7 +425,7 @@ def let_to_cil_visitor(let): if attr.expr: attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body - val=add_named_local(attr.id) + val=add_local(attr.id) body.append(cil.AssignNode(val, attr_cil.value)) expr_cil = expression_to_cil_visitor(let.expr) From 0ab77eff2992f43987aec96b83c7647b86a697aa Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 27 May 2020 13:33:21 -0400 Subject: [PATCH 250/435] adding some functions to mips ast --- src/code_generation/{ => CIL}/ast.py | 0 src/code_generation/{ => CIL}/cil.py | 2 +- src/code_generation/{ => CIL}/code.py | 2 +- src/code_generation/{ => CIL}/optimization.py | 0 src/code_generation/MIPS/ast.py | 190 ++++++++++++++++++ src/code_generation/code_gen.py | 4 +- 6 files changed, 194 insertions(+), 4 deletions(-) rename src/code_generation/{ => CIL}/ast.py (100%) rename src/code_generation/{ => CIL}/cil.py (99%) rename src/code_generation/{ => CIL}/code.py (99%) rename src/code_generation/{ => CIL}/optimization.py (100%) create mode 100644 src/code_generation/MIPS/ast.py diff --git a/src/code_generation/ast.py b/src/code_generation/CIL/ast.py similarity index 100% rename from src/code_generation/ast.py rename to src/code_generation/CIL/ast.py diff --git a/src/code_generation/cil.py b/src/code_generation/CIL/cil.py similarity index 99% rename from src/code_generation/cil.py rename to src/code_generation/CIL/cil.py index 35ed63e7..df3106ac 100644 --- a/src/code_generation/cil.py +++ b/src/code_generation/CIL/cil.py @@ -1,4 +1,4 @@ -import code_generation.ast as cil +import code_generation.CIL.ast as cil import lexer_parser.ast as lp_ast from semantic.types import * from .optimization import optimization_locals, remove_unused_locals diff --git a/src/code_generation/code.py b/src/code_generation/CIL/code.py similarity index 99% rename from src/code_generation/code.py rename to src/code_generation/CIL/code.py index bd9d88f4..b6b7c264 100644 --- a/src/code_generation/code.py +++ b/src/code_generation/CIL/code.py @@ -1,4 +1,4 @@ -from code_generation.ast import * +from code_generation.CIL.ast import * def cil_to_code(ast): diff --git a/src/code_generation/optimization.py b/src/code_generation/CIL/optimization.py similarity index 100% rename from src/code_generation/optimization.py rename to src/code_generation/CIL/optimization.py diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py new file mode 100644 index 00000000..78895005 --- /dev/null +++ b/src/code_generation/MIPS/ast.py @@ -0,0 +1,190 @@ +class Node: + pass + +class BinaryNode(Node): + def __init__(self, des, src1, src2): + self.des=des + self.src1=src1 + self.src2=src2 + +class AdduNode(BinaryNode): + def __str__(self): + return f'addu {self.des}, {self.src1}, {self.src2}' + + +class MuloNode(BinaryNode): + def __str__(self): + return f'mulo {self.des}, {self.src1}, {self.src2}' + + +class DivuNode(BinaryNode): + def __str__(self): + return f'divu {self.des}, {self.src1}, {self.src2}' + + +class SubuNode(BinaryNode): + def __str__(self): + return f'subu {self.des}, {self.src1}, {self.src2}' + + +class SeqNode(BinaryNode): + def __str__(self): + return f'seq {self.des}, {self.src1}, {self.src2}' + + +class SneNode(BinaryNode): + def __str__(self): + return f'sne {self.des}, {self.src1}, {self.src2}' + + +class SgeuNode(BinaryNode): + def __str__(self): + return f'sgeu {self.des}, {self.src1}, {self.src2}' + + +class SgtuNode(BinaryNode): + def __str__(self): + return f'sgtu {self.des}, {self.src1}, {self.src2}' + + +class SleuNode(BinaryNode): + def __str__(self): + return f'sleu {self.des}, {self.src1}, {self.src2}' + + +class SltuNode(BinaryNode): + def __str__(self): + return f'sltu {self.des}, {self.src1}, {self.src2}' + + +class BNode(Node): + def __init__(self, lab): + self.lab=lab + + def __str__(self): + return f'b {self.lab}' + + +class BeqzNode(Node): + def __init__(self,src, lab): + self.src=src + self.lab=lab + + def __str__(self): + return f'beqz {self.src}, {self.lab}' + + +class JNode(Node): + def __init__(self, lab): + self.lab=lab + + def __str__(self): + return f'j {self.lab}' + +class JrNode(Node): + def __init__(self, src): + self.src=src + + def __str__(self): + return f'jr {self.src}' + +class AddressNode(Node): + pass + +class ConstAddrNode(AddressNode): + def __init__(self, const): + self.const=const + + def __str__(self): + return self.const + +class RegAddrNode(AddressNode): + def __init__(self, reg, const=None): + self.const=const + self.reg=reg + + def __str__(self): + if self.const: + return f'{self.const}({self.reg})' + else: + return f'({self.reg})' + +class SymbolAddrNode(AddressNode): + def __init__(self, symbol, const=None, reg=None): + self.symbol=symbol + self.const=const + self.reg=reg + + def __str__(self): + if self.const and self.reg: + return f'{self.symbol} + {self.const}({self.reg})' + if self.const: + return f'{self.symbol} + {self.const}' + return self.symbol + +class LoadAddrNode(Node): + def __init__(self, des, addr): + self.des=des + self.addr=addr + +class LaNode(LoadAddrNode): + def __str__(self): + return f'la {self.des}, {self.addr}' + + +class LbuNode(LoadAddrNode): + def __str__(self): + return f'lbu {self.des}, {self.addr}' + +class LhuNode(LoadAddrNode): + def __str__(self): + return f'lhu {self.des}, {self.addr}' + +class LwNode(LoadAddrNode): + def __str__(self): + return f'lw {self.des}, {self.addr}' + +class Ulhu(LoadAddrNode): + def __str__(self): + return f'ulhu {self.des}, {self.addr}' + +class Ulw(LoadAddrNode): + def __str__(self): + return f'ulw {self.des}, {self.addr}' + +class LoadConstNode(Node): + def __init__(self, des, const): + self.des=des + self.const=const + +class LuiNode(LoadConstNode): + def __str__(self): + return f'lui {self.des}, {self.const}' + +class LiNode(LoadConstNode): + def __str__(self): + return f'li {self.des}, {self.const}' + +class Move(Node): + def __init__(self, src, des): + self.des=des + self.src=src + + def __str__(self): + return f'move {self.des}, {self.src}' + +class UnaryNode(Node): + def __init__(self, des, src): + self.des=des + self.src=src + +class NotNode(UnaryNode): + def __str__(self): + return f'la {self.des}, {self.src}' + +class SyscallNode(Node): + def __str__(self): + return 'syscall' + + + \ No newline at end of file diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py index 13b0f4ee..75e12096 100644 --- a/src/code_generation/code_gen.py +++ b/src/code_generation/code_gen.py @@ -1,5 +1,5 @@ -from .cil import ast_to_cil -from .code import cil_to_code +from .CIL.cil import ast_to_cil +from .CIL.code import cil_to_code def generate_code(ast): From 7a783a0a69eabe9d7c80bdeddeabbb9d06445aba Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 27 May 2020 16:43:44 -0400 Subject: [PATCH 251/435] removing code printing visitor and adding str to ast nodes --- src/code_generation/CIL/ast.py | 147 +++++++++++++++++++- src/code_generation/CIL/code.py | 236 -------------------------------- src/code_generation/code_gen.py | 3 +- 3 files changed, 141 insertions(+), 245 deletions(-) delete mode 100644 src/code_generation/CIL/code.py diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 1b6077f6..3f8e5751 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -8,6 +8,24 @@ def __init__(self, types, data, code, built_in_code): self.data = data self.code = code self.built_in_code = built_in_code + + def __str__(self): + type_code = '' + data_code = '' + func_code = '' + for t in self.types: + if t.type == 'SELF_TYPE': + continue + type_code += f'{str(t)}\n' + for d in self.data: + data_code += f'{str(d)}\n' + for f in self.built_in_code: + func_code += f'{str(f)}\n' + for f in self.code: + func_code += f'{str(f)}\n' + + return f'.TYPES \n\n{type_code}\n.DATA\n\n{data_code}\n.CODE\n\n{func_code}\n' + class TypeNode(Node): @@ -15,12 +33,26 @@ def __init__(self, type): self.attributes = [] self.methods = {} self.type = type + + def __str__(self): + attr_code = '' + method_code = '' + for attr in self.attributes: + attr_code += f'\tattribute {attr};\n' + + for name in self.methods: + method_code += f'\tmethod {name}:{self.methods[name]}_{name};\n' + + return f'type {self.type} {{\n{attr_code}{method_code}}}\n' class DataNode(Node): def __init__(self, id, val): self.id = id self.val = val + + def __str__(self): + return f'{self.id} = \"{self.val}\" ;' class FuncNode(Node): @@ -29,6 +61,21 @@ def __init__(self, name, params, locals, body): self.params = params self.locals = locals self.body = body + + def __str__(self): + params_code = '' + locals_code = '' + body_code = '' + for param in self.params: + params_code += f'\t{str(param)}\n' + + for local in self.locals: + locals_code += f'\tLOCAL {local} ;\n' + + for instruction in self.body: + body_code += f'\t{str(instruction)}\n' + + return f'function {self.name} {{\n{params_code}{locals_code}{body_code}}}\n' class InstructionNode(Node): @@ -54,6 +101,9 @@ def __repr__(self): class ParamNode(Node): def __init__(self, id): self.id = id + + def __str__(self): + return f'PARAM {self.id} ;' class AssignNode(InstructionNode): @@ -63,6 +113,9 @@ def __init__(self, result, val): self.val = val self.check_local(result) self.check_local(val) + + def __str__(self): + return f'{self.result} = {self.val} ;' class ArithNode(InstructionNode): @@ -77,27 +130,34 @@ def __init__(self, left, right, result): class PlusNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} + {self.right} ;' + class MinusNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} - {self.right} ;' class StarNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} * {self.right} ;' class DivNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} / {self.right} ;' class LessEqNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} <= {self.right} ;' class LessNode(ArithNode): - pass + def __str__(self): + return f'{self.result} = {self.left} < {self.right} ;' class NotNode(InstructionNode): @@ -107,6 +167,9 @@ def __init__(self, value, result): self.result = result self.check_local(value) self.check_local(result) + + def __str__(self): + return f'{self.result} = ~ {self.value}' class GetAttrNode(InstructionNode): @@ -117,6 +180,9 @@ def __init__(self, obj, attr, result): self.result = result self.check_local(obj) self.check_local(result) + + def __str__(self): + return f'{self.result} = GETATTR {self.obj} {self.attr} ;' class SetAttrNode(InstructionNode): @@ -127,6 +193,9 @@ def __init__(self, obj, attr, val): self.attr = attr self.check_local(obj) self.check_local(val) + + def __str__(self): + return f'SETATTR {self.obj} {self.attr} {self.val} ;' class SetIndexNode(InstructionNode): @@ -134,6 +203,9 @@ def __init__(self, array, index, val): self.val = val self.array = array self.index = index + + def __str__(self): + return f'SETINDEX {self.array} {self.index} {self.val} ;' class GetIndexNode(InstructionNode): @@ -141,6 +213,9 @@ def __init__(self, array, index, result): self.result = result self.array = array self.index = index + + def __str__(self): + return f'{self.result} = GETINDEX {self.array} {self.index} ;' class AllocateNode(InstructionNode): @@ -149,21 +224,31 @@ def __init__(self, _type, result): self.type = _type self.result = result self.check_local(result) + + def __str__(self): + return f'{self.result} = ALLOCATE {self.type} ;' class AbortNode(InstructionNode): - pass + def __str__(self): + return 'ABORT ;' class ReadIntNode(InstructionNode): def __init__(self, result): self.result = result + + def __str__(self): + return f'{self.result} = READINT ;' class CopyNode(InstructionNode): def __init__(self, val, result): self.result = result self.val = val + + def __str__(self): + return f'{self.result} = COPY {self.val} ;' class TypeOfNode(InstructionNode): @@ -173,18 +258,27 @@ def __init__(self, result, var): self.var = var self.check_local(result) self.check_local(var) + + def __str__(self): + return f'{self.result} = TYPEOF {self.var} ;' class ArrayNode(InstructionNode): def __init__(self, len, result): self.len = len self.result = result + + def __str__(self): + return f'{self.result} = ARRAY {self.len} ;' class CallNode(InstructionNode): def __init__(self, method, result): self.method = method self.result = result + + def __str__(self): + return f'{self.result} = CALL {self.method} ;' class VCAllNode(InstructionNode): @@ -195,6 +289,9 @@ def __init__(self, type, method, result): self.result = result self.check_local(result) self.check_local(type) + + def __str__(self): + return f'{self.result} = VCALL {self.type} {self.method} ;' class ArgNode(InstructionNode): @@ -202,6 +299,9 @@ def __init__(self, val): super().__init__() self.val = val self.check_local(val) + + def __str__(self): + return f'ARG {self.val} ;' class ConditionalGotoNode(InstructionNode): @@ -210,18 +310,27 @@ def __init__(self, predicate, label): self.predicate = predicate self.label = label self.check_local(predicate) + + def __str__(self): + return f'IF {self.predicate} GOTO {self.label} ;' class GotoNode(InstructionNode): def __init__(self, label): super().__init__() self.label = label + + def __str__(self): + return f'GOTO {self.label} ;' class LabelNode(InstructionNode): def __init__(self, label_name): super().__init__() self.label_name = label_name + + def __str__(self): + return f'LABEL {self.label_name} ;' class ReturnNode(InstructionNode): @@ -229,6 +338,9 @@ def __init__(self, ret_value): super().__init__() self.ret_value = ret_value self.check_local(ret_value) + + def __str__(self): + return f'RETURN {self.ret_value} ;' if self.ret_value else f'RETURN ;' class LoadNode(InstructionNode): @@ -237,12 +349,18 @@ def __init__(self, addr, result): self.result = result self.addr = addr self.check_local(result) + + def __str__(self): + return f'{self.result} = LOAD {self.addr} ;' class LengthNode(InstructionNode): def __init__(self, str, result): self.result = result self.str = str + + def __str__(self): + return f'{self.result} = LENGTH {self.str} ;' class ConcatNode(InstructionNode): @@ -250,6 +368,9 @@ def __init__(self, str_a, str_b, result): self.result = result self.str_a = str_a self.str_b = str_b + + def __str__(self): + return f'{self.result} = CONCAT {self.str_a} {self.str_b} ;' class SubStringNode(InstructionNode): @@ -258,6 +379,9 @@ def __init__(self, str, i, len, result): self.i = i self.len = len self.str = str + + def __str__(self): + return f'{self.result} = SUBSTRING {self.str_a} {self.str_b} ;' class StrNode(InstructionNode): @@ -267,6 +391,9 @@ def __init__(self, val, result): self.val = val self.check_local(val) self.check_local(result) + + def __str__(self): + return f'{self.result} = STR {self.val} ;' class ReadNode(InstructionNode): @@ -274,6 +401,9 @@ def __init__(self, result): super().__init__() self.result = result self.check_local(result) + + def __str__(self): + return f'{self.result} = READ ;' class PrintNode(InstructionNode): @@ -281,3 +411,6 @@ def __init__(self, str): super().__init__() self.str = str self.check_local(str) + + def __str__(self): + return f'PRINT {self.str} ;' diff --git a/src/code_generation/CIL/code.py b/src/code_generation/CIL/code.py deleted file mode 100644 index b6b7c264..00000000 --- a/src/code_generation/CIL/code.py +++ /dev/null @@ -1,236 +0,0 @@ -from code_generation.CIL.ast import * - - -def cil_to_code(ast): - if type(ast) == ProgramNode: - return program_cg_visitor(ast) - raise Exception(f'AST root must be program') - - -def program_cg_visitor(program: ProgramNode): - type_code = '' - data_code = '' - func_code = '' - for t in program.types: - if t.type == 'SELF_TYPE': - continue - type_code += f'{type_cg_visitor(t)}\n' - for d in program.data: - data_code += f'{data_cg_visitor(d)}\n' - for f in program.built_in_code: - func_code += f'{func_cg_visitor(f)}\n' - for f in program.code: - func_code += f'{func_cg_visitor(f)}\n' - - return f'.TYPES \n\n{type_code}\n.DATA\n\n{data_code}\n.CODE\n\n{func_code}\n' - - -def type_cg_visitor(type: TypeNode): - attr_code = '' - method_code = '' - for attr in type.attributes: - attr_code += f'\tattribute {attr};\n' - - for name in type.methods: - method_code += f'\tmethod {name}:{type.methods[name]}_{name};\n' - - return f'type {type.type} {{\n{attr_code}{method_code}}}\n' - - -def data_cg_visitor(data: DataNode): - return f'{data.id} = \"{data.val}\" ;' - - -def func_cg_visitor(func: FuncNode): - params_code = '' - locals_code = '' - body_code = '' - for param in func.params: - params_code += f'\t{param_cg_visitor(param)}\n' - - for local in func.locals: - locals_code += f'\t{local_cg_visitor(local)}\n' - - for instruction in func.body: - body_code += f'\t{instruction_cg_visitor(instruction)}\n' - - return f'function {func.name} {{\n{params_code}{locals_code}{body_code}}}\n' - - -def param_cg_visitor(param: ParamNode): - return f'PARAM {param.id} ;' - - -def local_cg_visitor(local: LocalNode): - return f'LOCAL {local.id} ;' - - -def instruction_cg_visitor(instruction: InstructionNode): - try: - return __visitors__[type(instruction)](instruction) - except KeyError: - print(f'Not visitor for {instruction}') - - -def assign_cg_visitor(assign: AssignNode): - return f'{assign.result} = {assign.val} ;' - - -def less_eq_cg_visitor(lesseq: LessEqNode): - return f'{lesseq.result} = {lesseq.left} <= {lesseq.right} ;' - - -def less_cg_visitor(less: LessNode): - return f'{less.result} = {less.left} < {less.right} ;' - - -def plus_cg_visitor(plus: PlusNode): - return f'{plus.result} = {plus.left} + {plus.right} ;' - - -def minus_cg_visitor(minus: MinusNode): - return f'{minus.result} = {minus.left} - {minus.right} ;' - - -def star_cg_visitor(star: StarNode): - return f'{star.result} = {star.left} * {star.right} ;' - - -def div_cg_visitor(div: DivNode): - return f'{div.result} = {div.left} / {div.right} ;' - - -def get_attr_cg_visitor(getattr: GetAttrNode): - return f'{getattr.result} = GETATTR {getattr.obj} {getattr.attr} ;' - - -def set_attr_cg_visitor(setattr: SetAttrNode): - return f'SETATTR {setattr.obj} {setattr.attr} {setattr.val} ;' - - -def get_index_cg_visitor(getindex: GetIndexNode): - return f'{getindex.result} = GETINDEX {getindex.array} {getindex.index} ;' - - -def set_index_cg_visitor(setindex: SetIndexNode): - return f'SETINDEX {setindex.array} {setindex.index} {setindex.val} ;' - - -def allocate_cg_visitor(allocate: AllocateNode): - return f'{allocate.result} = ALLOCATE {allocate.type} ;' - - -def typeof_cg_visitor(typeof: TypeOfNode): - return f'{typeof.result} = TYPEOF {typeof.var} ;' - - -def array_cg_visitor(array: ArrayNode): - return f'{array.result} = ARRAY {array.len} ;' - - -def call_cg_visitor(call: CallNode): - return f'{call.result} = CALL {call.method} ;' - - -def vcall_cg_visitor(vcall: VCAllNode): - return f'{vcall.result} = VCALL {vcall.type} {vcall.method} ;' - - -def arg_cg_visitor(arg: ArgNode): - return f'ARG {arg.val} ;' - - -def cond_goto_cg_visitor(cgoto: ConditionalGotoNode): - return f'IF {cgoto.predicate} GOTO {cgoto.label} ;' - - -def not_cg_visitor(n: NotNode): - return f'{n.result} = ~ {n.value}' - - -def goto_cg_visitor(goto: GotoNode): - return f'GOTO {goto.label} ;' - - -def label_cg_visitor(label: LabelNode): - return f'LABEL {label.label_name} ;' - - -def return_cg_visitor(ret: ReturnNode): - return f'RETURN {ret.ret_value} ;' if ret.ret_value else f'RETURN ;' - - -def load_cg_visitor(load: LoadNode): - return f'{load.result} = LOAD {load.addr} ;' - - -def length_cg_visitor(length: LengthNode): - return f'{length.result} = LENGTH {length.str} ;' - - -def concat_cg_visitor(concat: ConcatNode): - return f'{concat.result} = CONCAT {concat.str_a} {concat.str_b} ;' - - -def substring_cg_visitor(substring: SubStringNode): - return f'{substring.result} = SUBSTRING {substring.str_a} {substring.str_b} ;' - - -def str_cg_visitor(str: StrNode): - return f'{str.result} = STR {str.val} ;' - - -def read_cg_visitor(read: ReadNode): - return f'{read.result} = READ ;' - - -def print_cg_visitor(print: PrintNode): - return f'PRINT {print.str} ;' - - -def abort_cg_visitor(abort: AbortNode): - return 'ABORT ;' - - -def read_int_cg_visitor(ri: ReadIntNode): - return f'{ri.result} = READINT ;' - - -def copy_cg_visitor(copy: CopyNode): - return f'{copy.result} = COPY {copy.val} ;' - - -__visitors__ = { - AssignNode: assign_cg_visitor, - PlusNode: plus_cg_visitor, - MinusNode: minus_cg_visitor, - StarNode: star_cg_visitor, - DivNode: div_cg_visitor, - GetAttrNode: get_attr_cg_visitor, - SetAttrNode: set_attr_cg_visitor, - GetIndexNode: get_index_cg_visitor, - SetIndexNode: set_index_cg_visitor, - AllocateNode: allocate_cg_visitor, - TypeOfNode: typeof_cg_visitor, - ArrayNode: array_cg_visitor, - CallNode: call_cg_visitor, - VCAllNode: vcall_cg_visitor, - ArgNode: arg_cg_visitor, - ConditionalGotoNode: cond_goto_cg_visitor, - GotoNode: goto_cg_visitor, - LabelNode: label_cg_visitor, - ReturnNode: return_cg_visitor, - LoadNode: load_cg_visitor, - LengthNode: length_cg_visitor, - ConcatNode: concat_cg_visitor, - SubStringNode: substring_cg_visitor, - StrNode: str_cg_visitor, - ReadNode: read_cg_visitor, - PrintNode: print_cg_visitor, - NotNode: not_cg_visitor, - AbortNode: abort_cg_visitor, - ReadIntNode: read_int_cg_visitor, - CopyNode: copy_cg_visitor, - LessEqNode: less_eq_cg_visitor, - LessNode: less_cg_visitor -} diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py index 75e12096..d6282297 100644 --- a/src/code_generation/code_gen.py +++ b/src/code_generation/code_gen.py @@ -1,7 +1,6 @@ from .CIL.cil import ast_to_cil -from .CIL.code import cil_to_code def generate_code(ast): cil_ast = ast_to_cil(ast) - return cil_to_code(cil_ast) + return str(cil_ast) From c757dee40d17db19698aa34ef1adad0e207f412a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 11:29:44 -0400 Subject: [PATCH 252/435] adding the last built in functions --- src/code_generation/CIL/cil.py | 2 +- src/code_generation/MIPS/ast.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index df3106ac..a7314d61 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -128,7 +128,7 @@ def program_to_cil_visitor(program): def built_in_to_cil(): - return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil()] + return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil()] def out_string_to_cil(): diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 78895005..06710918 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -26,7 +26,6 @@ class SubuNode(BinaryNode): def __str__(self): return f'subu {self.des}, {self.src1}, {self.src2}' - class SeqNode(BinaryNode): def __str__(self): return f'seq {self.des}, {self.src1}, {self.src2}' From 5349ea7a4a7eaf049938992c13ba485e46d5c40d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 11:30:53 -0400 Subject: [PATCH 253/435] fixing bug --- src/code_generation/CIL/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 3f8e5751..20a0acaa 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -381,7 +381,7 @@ def __init__(self, str, i, len, result): self.str = str def __str__(self): - return f'{self.result} = SUBSTRING {self.str_a} {self.str_b} ;' + return f'{self.result} = SUBSTRING {self.str} {self.i} {self.len};' class StrNode(InstructionNode): From c9b65d7b88b113b25af8203393ab567359eae34b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 16:06:26 -0400 Subject: [PATCH 254/435] adding mips.py --- src/code_generation/MIPS/mips.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/code_generation/MIPS/mips.py diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py new file mode 100644 index 00000000..1f015776 --- /dev/null +++ b/src/code_generation/MIPS/mips.py @@ -0,0 +1,6 @@ +from code_generation.CIL import ast as cil + +def program_to_mips_visitor(program:cil.ProgramNode): + data_section=[f'{d.id}: .asciiz \"{d.val}\"' for d in program.data].join('\n') + + \ No newline at end of file From af6bec7683a6352cb4dcaf734fa71d7204775943 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 16:43:00 -0400 Subject: [PATCH 255/435] adding vcallvisitor --- src/code_generation/MIPS/ast.py | 9 +++++++-- src/code_generation/MIPS/mips.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 06710918..aa8e5fed 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -72,11 +72,11 @@ def __init__(self,src, lab): def __str__(self): return f'beqz {self.src}, {self.lab}' - -class JNode(Node): +class LabelJumpNode(Node): def __init__(self, lab): self.lab=lab +class JNode(LabelJumpNode): def __str__(self): return f'j {self.lab}' @@ -86,6 +86,11 @@ def __init__(self, src): def __str__(self): return f'jr {self.src}' + +class JalNode(LabelJumpNode): + def __str__(self): + return f'jal {self.lab}' + class AddressNode(Node): pass diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 1f015776..8e6087f0 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -1,6 +1,34 @@ from code_generation.CIL import ast as cil +from . import ast as mips + +__METHOD_MAPPING__={} +__ADDRS__= {} + +def save_caller_registers(): + pass + +def save_callee_registers(): + pass + +def restore_caller_registers(): + pass + +def restore_callee_registers(): + pass + def program_to_mips_visitor(program:cil.ProgramNode): + global __METHOD_MAPPING__ + + #filling method mapping + for t in program.types: + for m in t.methods: + __METHOD_MAPPING__[(t,m)]=t.methods[m] + data_section=[f'{d.id}: .asciiz \"{d.val}\"' for d in program.data].join('\n') + #continue +def vcall_to_mips_visitor(vcall:cil.VCAllNode): + return save_caller_registers() + [mips.JalNode(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.Move('v0',__ADDRS__[vcall.result])] + \ No newline at end of file From ee03ff983c811ddd4d1714c98334019835314804 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 16:49:07 -0400 Subject: [PATCH 256/435] adding empty functions --- src/code_generation/MIPS/mips.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 8e6087f0..9f35810f 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -15,6 +15,10 @@ def restore_caller_registers(): def restore_callee_registers(): pass + +def push_stack(src): + pass + def program_to_mips_visitor(program:cil.ProgramNode): @@ -30,5 +34,3 @@ def program_to_mips_visitor(program:cil.ProgramNode): def vcall_to_mips_visitor(vcall:cil.VCAllNode): return save_caller_registers() + [mips.JalNode(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.Move('v0',__ADDRS__[vcall.result])] - - \ No newline at end of file From 1d9aaf7d14abea1ccaf8438d5bb1b9f100a28b89 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 28 May 2020 17:08:15 -0400 Subject: [PATCH 257/435] Add new MIPS instructions implementations --- src/code_generation/MIPS/ast.py | 149 ++++++++++++++++++++----------- src/code_generation/MIPS/mips.py | 33 ++++--- 2 files changed, 117 insertions(+), 65 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index aa8e5fed..0cb41481 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -1,35 +1,65 @@ +class Instruction: + def __init__(self, name, arguments=None): + self.name = name + self.arguments = arguments + + def __str__(self): + if self.arguments is None: + return f"{name}" + elif len(self.arguments) == 3: + return f"{name} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" + elif len(self.arguments) == 2: + return f"{name} {self.arguments[0]}, {self.arguments[1]}" + elif len(self.arguments) == 1: + return f"{name} {self.arguments[0]}" + + +# =============== +# Data Directives +# =============== + +class AsciizInst(Instruction): + def __init__(self, arguments): + super().__init__(".asciiz", arguments) + +# OLD AST + + class Node: pass + class BinaryNode(Node): def __init__(self, des, src1, src2): - self.des=des - self.src1=src1 - self.src2=src2 + self.des = des + self.src1 = src1 + self.src2 = src2 + class AdduNode(BinaryNode): def __str__(self): return f'addu {self.des}, {self.src1}, {self.src2}' - - + + class MuloNode(BinaryNode): def __str__(self): return f'mulo {self.des}, {self.src1}, {self.src2}' - + class DivuNode(BinaryNode): def __str__(self): return f'divu {self.des}, {self.src1}, {self.src2}' - - + + class SubuNode(BinaryNode): def __str__(self): return f'subu {self.des}, {self.src1}, {self.src2}' - + + class SeqNode(BinaryNode): def __str__(self): return f'seq {self.des}, {self.src1}, {self.src2}' - + class SneNode(BinaryNode): def __str__(self): @@ -58,137 +88,154 @@ def __str__(self): class BNode(Node): def __init__(self, lab): - self.lab=lab - + self.lab = lab + def __str__(self): return f'b {self.lab}' class BeqzNode(Node): - def __init__(self,src, lab): - self.src=src - self.lab=lab - + def __init__(self, src, lab): + self.src = src + self.lab = lab + def __str__(self): return f'beqz {self.src}, {self.lab}' + class LabelJumpNode(Node): def __init__(self, lab): - self.lab=lab - + self.lab = lab + + class JNode(LabelJumpNode): def __str__(self): return f'j {self.lab}' - + + class JrNode(Node): def __init__(self, src): - self.src=src - + self.src = src + def __str__(self): return f'jr {self.src}' - + + class JalNode(LabelJumpNode): def __str__(self): return f'jal {self.lab}' - + class AddressNode(Node): pass + class ConstAddrNode(AddressNode): def __init__(self, const): - self.const=const - + self.const = const + def __str__(self): return self.const - + + class RegAddrNode(AddressNode): def __init__(self, reg, const=None): - self.const=const - self.reg=reg - + self.const = const + self.reg = reg + def __str__(self): if self.const: return f'{self.const}({self.reg})' else: return f'({self.reg})' - + + class SymbolAddrNode(AddressNode): def __init__(self, symbol, const=None, reg=None): - self.symbol=symbol - self.const=const - self.reg=reg - + self.symbol = symbol + self.const = const + self.reg = reg + def __str__(self): if self.const and self.reg: return f'{self.symbol} + {self.const}({self.reg})' if self.const: return f'{self.symbol} + {self.const}' return self.symbol - + + class LoadAddrNode(Node): def __init__(self, des, addr): - self.des=des - self.addr=addr + self.des = des + self.addr = addr + class LaNode(LoadAddrNode): def __str__(self): return f'la {self.des}, {self.addr}' - - + + class LbuNode(LoadAddrNode): def __str__(self): return f'lbu {self.des}, {self.addr}' + class LhuNode(LoadAddrNode): def __str__(self): return f'lhu {self.des}, {self.addr}' + class LwNode(LoadAddrNode): def __str__(self): return f'lw {self.des}, {self.addr}' + class Ulhu(LoadAddrNode): def __str__(self): return f'ulhu {self.des}, {self.addr}' + class Ulw(LoadAddrNode): def __str__(self): return f'ulw {self.des}, {self.addr}' + class LoadConstNode(Node): def __init__(self, des, const): - self.des=des - self.const=const - + self.des = des + self.const = const + + class LuiNode(LoadConstNode): def __str__(self): return f'lui {self.des}, {self.const}' + class LiNode(LoadConstNode): def __str__(self): return f'li {self.des}, {self.const}' + class Move(Node): def __init__(self, src, des): - self.des=des - self.src=src - + self.des = des + self.src = src + def __str__(self): return f'move {self.des}, {self.src}' + class UnaryNode(Node): def __init__(self, des, src): - self.des=des - self.src=src - + self.des = des + self.src = src + + class NotNode(UnaryNode): def __str__(self): return f'la {self.des}, {self.src}' + class SyscallNode(Node): def __str__(self): return 'syscall' - - - \ No newline at end of file diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 9f35810f..4af6de4e 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -1,36 +1,41 @@ from code_generation.CIL import ast as cil from . import ast as mips -__METHOD_MAPPING__={} -__ADDRS__= {} +__METHOD_MAPPING__ = {} +__ADDRS__ = {} + def save_caller_registers(): pass + def save_callee_registers(): pass + def restore_caller_registers(): pass + def restore_callee_registers(): pass + def push_stack(src): pass - - -def program_to_mips_visitor(program:cil.ProgramNode): + +def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__ - - #filling method mapping + + # filling method mapping for t in program.types: for m in t.methods: - __METHOD_MAPPING__[(t,m)]=t.methods[m] - - data_section=[f'{d.id}: .asciiz \"{d.val}\"' for d in program.data].join('\n') - #continue - -def vcall_to_mips_visitor(vcall:cil.VCAllNode): - return save_caller_registers() + [mips.JalNode(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.Move('v0',__ADDRS__[vcall.result])] + __METHOD_MAPPING__[(t, m)] = t.methods[m] + + data_section = [mips.AsciizInst(d.val) for d in program.data] + # continue + + +def vcall_to_mips_visitor(vcall: cil.VCAllNode): + return save_caller_registers() + [mips.JalNode(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.Move('v0', __ADDRS__[vcall.result])] From 66233522a9b06fdb15e3ad8592875351e2d804b8 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 17:51:12 -0400 Subject: [PATCH 258/435] adding stack instruction --- src/code_generation/MIPS/ast.py | 253 +++++-------------------------- src/code_generation/MIPS/mips.py | 46 ++++-- 2 files changed, 74 insertions(+), 225 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 0cb41481..244a4aa5 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -21,221 +21,44 @@ def __str__(self): class AsciizInst(Instruction): def __init__(self, arguments): super().__init__(".asciiz", arguments) + -# OLD AST +# ============================ +# Jump and Branch Instructions +# ============================ -class Node: - pass - - -class BinaryNode(Node): - def __init__(self, des, src1, src2): - self.des = des - self.src1 = src1 - self.src2 = src2 - - -class AdduNode(BinaryNode): - def __str__(self): - return f'addu {self.des}, {self.src1}, {self.src2}' - - -class MuloNode(BinaryNode): - def __str__(self): - return f'mulo {self.des}, {self.src1}, {self.src2}' - - -class DivuNode(BinaryNode): - def __str__(self): - return f'divu {self.des}, {self.src1}, {self.src2}' - - -class SubuNode(BinaryNode): - def __str__(self): - return f'subu {self.des}, {self.src1}, {self.src2}' - - -class SeqNode(BinaryNode): - def __str__(self): - return f'seq {self.des}, {self.src1}, {self.src2}' - - -class SneNode(BinaryNode): - def __str__(self): - return f'sne {self.des}, {self.src1}, {self.src2}' - - -class SgeuNode(BinaryNode): - def __str__(self): - return f'sgeu {self.des}, {self.src1}, {self.src2}' - - -class SgtuNode(BinaryNode): - def __str__(self): - return f'sgtu {self.des}, {self.src1}, {self.src2}' - - -class SleuNode(BinaryNode): - def __str__(self): - return f'sleu {self.des}, {self.src1}, {self.src2}' - - -class SltuNode(BinaryNode): - def __str__(self): - return f'sltu {self.des}, {self.src1}, {self.src2}' - - -class BNode(Node): - def __init__(self, lab): - self.lab = lab - - def __str__(self): - return f'b {self.lab}' - - -class BeqzNode(Node): - def __init__(self, src, lab): - self.src = src - self.lab = lab - - def __str__(self): - return f'beqz {self.src}, {self.lab}' - - -class LabelJumpNode(Node): - def __init__(self, lab): - self.lab = lab - - -class JNode(LabelJumpNode): - def __str__(self): - return f'j {self.lab}' - - -class JrNode(Node): - def __init__(self, src): - self.src = src - - def __str__(self): - return f'jr {self.src}' - - -class JalNode(LabelJumpNode): - def __str__(self): - return f'jal {self.lab}' - - -class AddressNode(Node): - pass - - -class ConstAddrNode(AddressNode): - def __init__(self, const): - self.const = const - - def __str__(self): - return self.const - - -class RegAddrNode(AddressNode): - def __init__(self, reg, const=None): - self.const = const - self.reg = reg - - def __str__(self): - if self.const: - return f'{self.const}({self.reg})' - else: - return f'({self.reg})' - - -class SymbolAddrNode(AddressNode): - def __init__(self, symbol, const=None, reg=None): - self.symbol = symbol - self.const = const - self.reg = reg - - def __str__(self): - if self.const and self.reg: - return f'{self.symbol} + {self.const}({self.reg})' - if self.const: - return f'{self.symbol} + {self.const}' - return self.symbol - - -class LoadAddrNode(Node): - def __init__(self, des, addr): - self.des = des - self.addr = addr - - -class LaNode(LoadAddrNode): - def __str__(self): - return f'la {self.des}, {self.addr}' - - -class LbuNode(LoadAddrNode): - def __str__(self): - return f'lbu {self.des}, {self.addr}' - - -class LhuNode(LoadAddrNode): - def __str__(self): - return f'lhu {self.des}, {self.addr}' - - -class LwNode(LoadAddrNode): - def __str__(self): - return f'lw {self.des}, {self.addr}' - - -class Ulhu(LoadAddrNode): - def __str__(self): - return f'ulhu {self.des}, {self.addr}' - - -class Ulw(LoadAddrNode): - def __str__(self): - return f'ulw {self.des}, {self.addr}' - - -class LoadConstNode(Node): - def __init__(self, des, const): - self.des = des - self.const = const - - -class LuiNode(LoadConstNode): - def __str__(self): - return f'lui {self.des}, {self.const}' - - -class LiNode(LoadConstNode): - def __str__(self): - return f'li {self.des}, {self.const}' - - -class Move(Node): - def __init__(self, src, des): - self.des = des - self.src = src - - def __str__(self): - return f'move {self.des}, {self.src}' - - -class UnaryNode(Node): - def __init__(self, des, src): - self.des = des - self.src = src - - -class NotNode(UnaryNode): - def __str__(self): - return f'la {self.des}, {self.src}' - - -class SyscallNode(Node): - def __str__(self): - return 'syscall' +class JalInstruction(Instruction): + def __init__(self, arguments): + super().__init__('jal', arguments) + + +# ============================= +# Load, Store and Data Movement +# ============================= + +class MoveInstruction(Instruction): + def __init__(self, arguments): + super().__init__('move', arguments) + +class SwInstruction(Instruction): + def __init__(self, arguments): + super().__init__('sw', arguments) + +class LwInstruction(Instruction): + def __init__(self, arguments): + super().__init__('lw', arguments) + + + +# ======================= +# Arithmetic Instructions +# ======================= + +class SubuInstruction(Instruction): + def __init__(self, arguments): + super().__init__('subu', arguments) + +class AdduInstruction(Instruction): + def __init__(self, arguments): + super().__init__('addu', arguments) \ No newline at end of file diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4af6de4e..91114f06 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -5,24 +5,50 @@ __ADDRS__ = {} +def save_callee_registers(): + allocate_stack(40) + for i in range(8): + push_stack(f'$s{i}', (7-i)*4) + push_stack('$fp', 4) + push_stack('$ra') + + + def save_caller_registers(): - pass + allocate_stack(40) + for i in range(10): + push_stack(f'$t{i}', (9-i)*4) -def save_callee_registers(): - pass +def restore_callee_registers(): + for i in range(8): + push_stack(f'$s{i}', (7-i)*4) + pop_stack('$fp', 4) + pop_stack('$ra') + restore_stack(40) def restore_caller_registers(): - pass - + for i in range(10): + pop_stack(f'$t{i}', (9-i)*4) + restore_stack(40) -def restore_callee_registers(): - pass +def restore_stack(bytes): + return [mips.AdduInstruction('$sp', '$sp', bytes)] + +def allocate_stack(bytes): + return [mips.SubuInstruction('$sp', '$sp', bytes)] +def push_stack(src, pos=0): + if pos: + return [mips.SwInstruction(src, f'{pos}($sp)')] + return [mips.SwInstruction(src, '($sp)')] -def push_stack(src): - pass +def pop_stack(src, pos=0): + if pos: + return [mips.LwInstruction(src, f'{pos}($sp)')] + return [mips.LwInstruction(src, '($sp)')] + def program_to_mips_visitor(program: cil.ProgramNode): @@ -38,4 +64,4 @@ def program_to_mips_visitor(program: cil.ProgramNode): def vcall_to_mips_visitor(vcall: cil.VCAllNode): - return save_caller_registers() + [mips.JalNode(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.Move('v0', __ADDRS__[vcall.result])] + return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['v0', __ADDRS__[vcall.result]])] From 8527162e1630f1a7a0b53e337aee014fcce44062 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 17:57:54 -0400 Subject: [PATCH 259/435] adding param and arg visitors --- src/code_generation/MIPS/mips.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 91114f06..4f81b636 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -64,4 +64,11 @@ def program_to_mips_visitor(program: cil.ProgramNode): def vcall_to_mips_visitor(vcall: cil.VCAllNode): - return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['v0', __ADDRS__[vcall.result]])] + return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] + + +def arg_to_mips_visitor(arg:cil.ArgNode): + return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) + +def param_to_mips_visitor(param:cil.ParamNode): + return pop_stack(__ADDRS__[param.id]) + restore_stack(4) \ No newline at end of file From b5f5737aafae999acaa440424ce6ba1917f6e696 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 28 May 2020 18:01:29 -0400 Subject: [PATCH 260/435] Add utilities for types in MIPS --- src/code_generation/MIPS/mips.py | 4 ++++ src/code_generation/MIPS/utilities.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/code_generation/MIPS/utilities.py diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4af6de4e..0294567b 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -1,5 +1,6 @@ from code_generation.CIL import ast as cil from . import ast as mips +from .utilities import * __METHOD_MAPPING__ = {} __ADDRS__ = {} @@ -28,6 +29,9 @@ def push_stack(src): def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__ + # Initialize Types Codes + init_types_codes(program.types) + # filling method mapping for t in program.types: for m in t.methods: diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py new file mode 100644 index 00000000..3bcaeaa4 --- /dev/null +++ b/src/code_generation/MIPS/utilities.py @@ -0,0 +1,15 @@ + + +__TYPES_CODES__ = {} + + +def init_types_codes(types): + for i, t in enumerate(types): + __TYPES_CODES__[t] = i + + +def get_type_code(type): + try: + return __TYPES_CODES__[type] + except KeyError: + return None From e6e12df3e467bb1d0d0ba67a8d8efed2f42b0d1e Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 28 May 2020 18:01:46 -0400 Subject: [PATCH 261/435] Rebuild parsetab.py --- src/lexer_parser/parsetab.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 9f87869e..99fc4683 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From fad23dd44529172fef6946f7eaa3b151e0577da1 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 May 2020 18:07:42 -0400 Subject: [PATCH 262/435] Fix property 'name' access on Instruction --- src/code_generation/MIPS/ast.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 0cb41481..7cb5d692 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -5,13 +5,13 @@ def __init__(self, name, arguments=None): def __str__(self): if self.arguments is None: - return f"{name}" + return f"{self.name}" elif len(self.arguments) == 3: - return f"{name} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" + return f"{self.name} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" elif len(self.arguments) == 2: - return f"{name} {self.arguments[0]}, {self.arguments[1]}" + return f"{self.name} {self.arguments[0]}, {self.arguments[1]}" elif len(self.arguments) == 1: - return f"{name} {self.arguments[0]}" + return f"{self.name} {self.arguments[0]}" # =============== From 103de294ad1b9c4690542989bdfc75492a887a3d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 28 May 2020 18:16:27 -0400 Subject: [PATCH 263/435] Add documentation to utilities.py --- src/code_generation/MIPS/utilities.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 3bcaeaa4..fca4fa15 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -4,12 +4,30 @@ def init_types_codes(types): + """ + Objects in MIPS code are memory space, therefore we need to know the type + of this object. But we cannot save the type name, therefore, we configure + a unique number for each type which will be identified in MIPS. + """ for i, t in enumerate(types): __TYPES_CODES__[t] = i def get_type_code(type): + """ + If the type is valid, it returns the number that identifies that type in + MIPS. In other case, returns None. + """ try: return __TYPES_CODES__[type] except KeyError: return None + + +def get_type_size(type): + """ + The size of the any type in memory is size of they attributes and one space + more for save the type identifier.Each attribute needs 4 bytes of space and + the type identifier also. + """ + return len(type.attributes) + 1 From 236b48f3f6e6c9db1cf60e3604aeed4dbc373f4f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 28 May 2020 18:25:35 -0400 Subject: [PATCH 264/435] adding function to mips visitor --- src/code_generation/MIPS/mips.py | 44 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4f81b636..8ff7db7f 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -23,14 +23,14 @@ def save_caller_registers(): def restore_callee_registers(): for i in range(8): push_stack(f'$s{i}', (7-i)*4) - pop_stack('$fp', 4) - pop_stack('$ra') + peek_stack('$fp', 4) + peek_stack('$ra') restore_stack(40) def restore_caller_registers(): for i in range(10): - pop_stack(f'$t{i}', (9-i)*4) + peek_stack(f'$t{i}', (9-i)*4) restore_stack(40) def restore_stack(bytes): @@ -44,7 +44,7 @@ def push_stack(src, pos=0): return [mips.SwInstruction(src, f'{pos}($sp)')] return [mips.SwInstruction(src, '($sp)')] -def pop_stack(src, pos=0): +def peek_stack(src, pos=0): if pos: return [mips.LwInstruction(src, f'{pos}($sp)')] return [mips.LwInstruction(src, '($sp)')] @@ -61,7 +61,34 @@ def program_to_mips_visitor(program: cil.ProgramNode): data_section = [mips.AsciizInst(d.val) for d in program.data] # continue - + text_section=[] + + for function in program.built_in_code + program.code: + text_section+=function_to_mips_visitor(function) + + +def function_to_mips_visitor(function): + code=save_callee_registers() + for i,param in enumerate(function.params): + __ADDRS__[param.id]=(len(function.params)-1-i)*4 + + + code+=allocate_stack(len(function.locals)*4) + for i,local in enumerate(function.locals): + __ADDRS__[local.id]=(len(function.locals)-1-i)*4 + + for inst in function.body: + code+=instruction_to_mips_visitor(inst) + + code+=restore_callee_registers() + code += restore_stack(len(function.locals)*4) + + +def instruction_to_mips_visitor(inst): + try: + return __visitors__[type(inst)] + except KeyError: + raise Exception(f'There is no visitor for {type(inst)}') def vcall_to_mips_visitor(vcall: cil.VCAllNode): return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] @@ -70,5 +97,8 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): def arg_to_mips_visitor(arg:cil.ArgNode): return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) -def param_to_mips_visitor(param:cil.ParamNode): - return pop_stack(__ADDRS__[param.id]) + restore_stack(4) \ No newline at end of file + +__visitors__={ + cil.VCAllNode :vcall_to_mips_visitor, + cil.ArgNode:arg_to_mips_visitor +} \ No newline at end of file From ddf6868247f335645300932d50c40b401cd763bc Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 28 May 2020 19:56:08 -0400 Subject: [PATCH 265/435] Reformat code --- src/code_generation/MIPS/mips.py | 58 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 17497ce0..ae023622 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -11,8 +11,7 @@ def save_callee_registers(): for i in range(8): push_stack(f'$s{i}', (7-i)*4) push_stack('$fp', 4) - push_stack('$ra') - + push_stack('$ra') def save_caller_registers(): @@ -34,22 +33,25 @@ def restore_caller_registers(): peek_stack(f'$t{i}', (9-i)*4) restore_stack(40) + def restore_stack(bytes): return [mips.AdduInstruction('$sp', '$sp', bytes)] - + + def allocate_stack(bytes): return [mips.SubuInstruction('$sp', '$sp', bytes)] + def push_stack(src, pos=0): if pos: return [mips.SwInstruction(src, f'{pos}($sp)')] return [mips.SwInstruction(src, '($sp)')] + def peek_stack(src, pos=0): if pos: return [mips.LwInstruction(src, f'{pos}($sp)')] return [mips.LwInstruction(src, '($sp)')] - def program_to_mips_visitor(program: cil.ProgramNode): @@ -65,44 +67,44 @@ def program_to_mips_visitor(program: cil.ProgramNode): data_section = [mips.AsciizInst(d.val) for d in program.data] # continue - text_section=[] - + text_section = [] + for function in program.built_in_code + program.code: - text_section+=function_to_mips_visitor(function) - - + text_section += function_to_mips_visitor(function) + + def function_to_mips_visitor(function): - code=save_callee_registers() - for i,param in enumerate(function.params): - __ADDRS__[param.id]=(len(function.params)-1-i)*4 - - - code+=allocate_stack(len(function.locals)*4) - for i,local in enumerate(function.locals): - __ADDRS__[local.id]=(len(function.locals)-1-i)*4 - + code = save_callee_registers() + for i, param in enumerate(function.params): + __ADDRS__[param.id] = (len(function.params)-1-i)*4 + + code += allocate_stack(len(function.locals)*4) + for i, local in enumerate(function.locals): + __ADDRS__[local.id] = (len(function.locals)-1-i)*4 + for inst in function.body: - code+=instruction_to_mips_visitor(inst) - - code+=restore_callee_registers() + code += instruction_to_mips_visitor(inst) + + code += restore_callee_registers() code += restore_stack(len(function.locals)*4) - - + + def instruction_to_mips_visitor(inst): try: return __visitors__[type(inst)] except KeyError: raise Exception(f'There is no visitor for {type(inst)}') + def vcall_to_mips_visitor(vcall: cil.VCAllNode): return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] -def arg_to_mips_visitor(arg:cil.ArgNode): +def arg_to_mips_visitor(arg: cil.ArgNode): return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) -__visitors__={ - cil.VCAllNode :vcall_to_mips_visitor, - cil.ArgNode:arg_to_mips_visitor -} \ No newline at end of file +__visitors__ = { + cil.VCAllNode: vcall_to_mips_visitor, + cil.ArgNode: arg_to_mips_visitor +} From d928acae1e63e50923502f7fa99820404494369b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 May 2020 20:10:18 -0400 Subject: [PATCH 266/435] Add arithmetic operation to MIPS --- src/code_generation/MIPS/ast.py | 66 ++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 238afd37..a8ac009b 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -55,10 +55,66 @@ def __init__(self, arguments): # Arithmetic Instructions # ======================= -class SubuInstruction(Instruction): - def __init__(self, arguments): - super().__init__('subu', arguments) +class SubInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('sub', arguments) if signed else super().__init__('subu', arguments) -class AdduInstruction(Instruction): +class AddInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('add', arguments) if signed else super().__init__('addu', arguments) + +class MultInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('mult', arguments) if signed else super().__init__('multu', arguments) + +class DivInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('div', arguments) if signed else super().__init__('divu', arguments) + +class NegInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('neg', arguments) if signed else super().__init__('negu', arguments) + +class NorInstruction(Instruction): + def __init__(self, arguments): + super().__init__('nor', arguments) + +class NotInstruction(Instruction): + def __init__(self, arguments): + super().__init__('not', arguments) + +class OrInstruction(Instruction): + def __init__(self, arguments): + super().__init__('or', arguments) + +class RemInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('rem', arguments) if signed else super().__init__('remu', arguments) + +class RolInstruction(Instruction): + def __init__(self, arguments): + super().__init__('rol', arguments) + +class RorInstruction(Instruction): + def __init__(self, arguments): + super().__init__('ror', arguments) + +class SllInstruction(Instruction): + def __init__(self, arguments): + super().__init__('sll', arguments) + +class SraInstruction(Instruction): + def __init__(self, arguments): + super().__init__('sra', arguments) + +class SrlInstruction(Instruction): + def __init__(self, arguments): + super().__init__('srl', arguments) + +class XorInstruction(Instruction): + def __init__(self, arguments): + super().__init__('xor', arguments) + +class AbsInstruction(Instruction): def __init__(self, arguments): - super().__init__('addu', arguments) \ No newline at end of file + super().__init__('abs', arguments) \ No newline at end of file From 489db93cd93f7de557dc1314c350bdc85f880b3f Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 May 2020 20:19:30 -0400 Subject: [PATCH 267/435] Add comparison instructions to MIPS --- src/code_generation/MIPS/ast.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index a8ac009b..3c52ebed 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -117,4 +117,33 @@ def __init__(self, arguments): class AbsInstruction(Instruction): def __init__(self, arguments): - super().__init__('abs', arguments) \ No newline at end of file + super().__init__('abs', arguments) + + +# ======================= +# Comparison Instructions +# ======================= + +class SeqInstruction(Instruction): + def __init__(self, arguments): + super().__init__('seq', arguments) + +class SneInstruction(Instruction): + def __init__(self, arguments): + super().__init__('sne', arguments) + +class SgeInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('sge', arguments) if signed else super().__init__('sgeu', arguments) + +class SgtInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('sgt', arguments) if signed else super().__init__('sgtu', arguments) + +class SleInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('sle', arguments) if signed else super().__init__('sleu', arguments) + +class SltInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('slt', arguments) if signed else super().__init__('sltu', arguments) \ No newline at end of file From 29684a4d2187566b382c2464b61e6b457b10a3df Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 May 2020 20:34:02 -0400 Subject: [PATCH 268/435] Add branch and jump instructions to MIPS --- src/code_generation/MIPS/ast.py | 50 +++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 3c52ebed..430a7f9f 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -48,8 +48,8 @@ def __init__(self, arguments): class LwInstruction(Instruction): def __init__(self, arguments): super().__init__('lw', arguments) - - + + # ======================= # Arithmetic Instructions @@ -120,6 +120,7 @@ def __init__(self, arguments): super().__init__('abs', arguments) + # ======================= # Comparison Instructions # ======================= @@ -146,4 +147,47 @@ def __init__(self, arguments, signed = True): class SltInstruction(Instruction): def __init__(self, arguments, signed = True): - super().__init__('slt', arguments) if signed else super().__init__('sltu', arguments) \ No newline at end of file + super().__init__('slt', arguments) if signed else super().__init__('sltu', arguments) + + + +# ============================ +# Branch and Jump Instructions +# ============================ + +class BInstruction(Instruction): + def __init__(self, arguments): + super().__init__('b', arguments) + +class BeqInstruction(Instruction): + def __init__(self, arguments): + super().__init__('beq', arguments) + +class BneInstruction(Instruction): + def __init__(self, arguments): + super().__init__('bne', arguments) + +class BgeInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('bge', arguments) if signed else super().__init__('bgeu', arguments) + +class BgtInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('bgt', arguments) if signed else super().__init__('bgtu', arguments) + +class BleInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('ble', arguments) if signed else super().__init__('bleu', arguments) + +class BltInstruction(Instruction): + def __init__(self, arguments, signed = True): + super().__init__('blt', arguments) if signed else super().__init__('bltu', arguments) + + +class JInstruction(Instruction): + def __init__(self, arguments): + super().__init__('j', arguments) + +class JrInstruction(Instruction): + def __init__(self, arguments): + super().__init__('jr', arguments) \ No newline at end of file From 96a481b79cf43431aecb71addd1988d3b517e2a8 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 May 2020 20:46:19 -0400 Subject: [PATCH 269/435] Move aux methods to utilities.py --- src/code_generation/MIPS/mips.py | 49 +-------------------------- src/code_generation/MIPS/utilities.py | 48 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 17497ce0..47384665 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -5,53 +5,6 @@ __METHOD_MAPPING__ = {} __ADDRS__ = {} - -def save_callee_registers(): - allocate_stack(40) - for i in range(8): - push_stack(f'$s{i}', (7-i)*4) - push_stack('$fp', 4) - push_stack('$ra') - - - -def save_caller_registers(): - allocate_stack(40) - for i in range(10): - push_stack(f'$t{i}', (9-i)*4) - - -def restore_callee_registers(): - for i in range(8): - push_stack(f'$s{i}', (7-i)*4) - peek_stack('$fp', 4) - peek_stack('$ra') - restore_stack(40) - - -def restore_caller_registers(): - for i in range(10): - peek_stack(f'$t{i}', (9-i)*4) - restore_stack(40) - -def restore_stack(bytes): - return [mips.AdduInstruction('$sp', '$sp', bytes)] - -def allocate_stack(bytes): - return [mips.SubuInstruction('$sp', '$sp', bytes)] - -def push_stack(src, pos=0): - if pos: - return [mips.SwInstruction(src, f'{pos}($sp)')] - return [mips.SwInstruction(src, '($sp)')] - -def peek_stack(src, pos=0): - if pos: - return [mips.LwInstruction(src, f'{pos}($sp)')] - return [mips.LwInstruction(src, '($sp)')] - - - def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__ @@ -72,7 +25,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): def function_to_mips_visitor(function): - code=save_callee_registers() + code=save_callee_registers() #revisar que save_callee_registers no tiene valor de retorno for i,param in enumerate(function.params): __ADDRS__[param.id]=(len(function.params)-1-i)*4 diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index fca4fa15..4195c0a0 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -31,3 +31,51 @@ def get_type_size(type): the type identifier also. """ return len(type.attributes) + 1 + + +def save_callee_registers(): + allocate_stack(40) + for i in range(8): + push_stack(f'$s{i}', (7-i)*4) + push_stack('$fp', 4) + push_stack('$ra') + + +def save_caller_registers(): + allocate_stack(40) + for i in range(10): + push_stack(f'$t{i}', (9-i)*4) + + +def restore_callee_registers(): + for i in range(8): + push_stack(f'$s{i}', (7-i)*4) + peek_stack('$fp', 4) + peek_stack('$ra') + restore_stack(40) + + +def restore_caller_registers(): + for i in range(10): + peek_stack(f'$t{i}', (9-i)*4) + restore_stack(40) + + +def restore_stack(bytes): + return [mips.AdduInstruction('$sp', '$sp', bytes)] + + +def allocate_stack(bytes): + return [mips.SubuInstruction('$sp', '$sp', bytes)] + + +def push_stack(src, pos=0): + if pos: + return [mips.SwInstruction(src, f'{pos}($sp)')] + return [mips.SwInstruction(src, '($sp)')] + + +def peek_stack(src, pos=0): + if pos: + return [mips.LwInstruction(src, f'{pos}($sp)')] + return [mips.LwInstruction(src, '($sp)')] From 8024d7a17a56ed40d0f357bb83a77ebf8f672c2a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 10:38:21 -0400 Subject: [PATCH 270/435] Reformat code --- src/code_generation/MIPS/mips.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index ffb49858..4fe75c3f 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -5,6 +5,7 @@ __METHOD_MAPPING__ = {} __ADDRS__ = {} + def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__ @@ -25,15 +26,15 @@ def program_to_mips_visitor(program: cil.ProgramNode): def function_to_mips_visitor(function): - code=save_callee_registers() #revisar que save_callee_registers no tiene valor de retorno - for i,param in enumerate(function.params): - __ADDRS__[param.id]=(len(function.params)-1-i)*4 - - - code+=allocate_stack(len(function.locals)*4) - for i,local in enumerate(function.locals): - __ADDRS__[local.id]=(len(function.locals)-1-i)*4 - + # revisar que save_callee_registers no tiene valor de retorno + code = save_callee_registers() + for i, param in enumerate(function.params): + __ADDRS__[param.id] = (len(function.params)-1-i)*4 + + code += allocate_stack(len(function.locals)*4) + for i, local in enumerate(function.locals): + __ADDRS__[local.id] = (len(function.locals)-1-i)*4 + for inst in function.body: code += instruction_to_mips_visitor(inst) From c8cb1d78ccb005a4bb499cfe596549477809c58d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 10:57:42 -0400 Subject: [PATCH 271/435] adding return values to aux methods --- src/code_generation/MIPS/utilities.py | 33 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 4195c0a0..8f9838fa 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -1,4 +1,4 @@ - +from . import ast as mips __TYPES_CODES__ = {} @@ -34,31 +34,38 @@ def get_type_size(type): def save_callee_registers(): - allocate_stack(40) + code=allocate_stack(40) for i in range(8): - push_stack(f'$s{i}', (7-i)*4) - push_stack('$fp', 4) - push_stack('$ra') + code+=push_stack(f'$s{i}', (7-i)*4) + code+=push_stack('$fp', 4) + code+=push_stack('$ra') + return code def save_caller_registers(): - allocate_stack(40) + code=allocate_stack(40) for i in range(10): - push_stack(f'$t{i}', (9-i)*4) + code+=push_stack(f'$t{i}', (9-i)*4) + + return code def restore_callee_registers(): + code=[] for i in range(8): - push_stack(f'$s{i}', (7-i)*4) - peek_stack('$fp', 4) - peek_stack('$ra') - restore_stack(40) + code+=peek_stack(f'$s{i}', (7-i)*4) + code+=peek_stack('$fp', 4) + code+=peek_stack('$ra') + code+=restore_stack(40) + return code def restore_caller_registers(): + code=[] for i in range(10): - peek_stack(f'$t{i}', (9-i)*4) - restore_stack(40) + code+=peek_stack(f'$t{i}', (9-i)*4) + code+=restore_stack(40) + return code def restore_stack(bytes): From 72ce930261fe265ddf51dd953ba786126ee700a7 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 10:58:31 -0400 Subject: [PATCH 272/435] adding return value to func to mips visitor --- src/code_generation/MIPS/mips.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index ffb49858..fa950857 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -25,10 +25,10 @@ def program_to_mips_visitor(program: cil.ProgramNode): def function_to_mips_visitor(function): - code=save_callee_registers() #revisar que save_callee_registers no tiene valor de retorno for i,param in enumerate(function.params): __ADDRS__[param.id]=(len(function.params)-1-i)*4 + code=save_callee_registers() code+=allocate_stack(len(function.locals)*4) for i,local in enumerate(function.locals): @@ -39,6 +39,8 @@ def function_to_mips_visitor(function): code += restore_callee_registers() code += restore_stack(len(function.locals)*4) + + return code def instruction_to_mips_visitor(inst): From 771e542bf0331e9af6c8e04092f9d5ae28c2200b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 11:05:12 -0400 Subject: [PATCH 273/435] Add ALLOCATE to MIPS visitor - Add LiInstruction - Add SyscallInstruction - Reformat code --- src/code_generation/MIPS/ast.py | 89 +++++++++++++++++++-------- src/code_generation/MIPS/mips.py | 22 +++++++ src/code_generation/MIPS/utilities.py | 6 +- 3 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 430a7f9f..4e30161c 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -21,7 +21,6 @@ def __str__(self): class AsciizInst(Instruction): def __init__(self, arguments): super().__init__(".asciiz", arguments) - # ============================ @@ -31,96 +30,116 @@ def __init__(self, arguments): class JalInstruction(Instruction): def __init__(self, arguments): super().__init__('jal', arguments) - + # ============================= # Load, Store and Data Movement # ============================= - + class MoveInstruction(Instruction): def __init__(self, arguments): super().__init__('move', arguments) - + + class SwInstruction(Instruction): def __init__(self, arguments): super().__init__('sw', arguments) - + + class LwInstruction(Instruction): def __init__(self, arguments): super().__init__('lw', arguments) +class LiInstruction(Instruction): + def __init__(self, arguments): + super().__init__('li', arguments) + # ======================= # Arithmetic Instructions # ======================= - + class SubInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('sub', arguments) if signed else super().__init__('subu', arguments) - + + class AddInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('add', arguments) if signed else super().__init__('addu', arguments) + class MultInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('mult', arguments) if signed else super().__init__('multu', arguments) + class DivInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('div', arguments) if signed else super().__init__('divu', arguments) + class NegInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('neg', arguments) if signed else super().__init__('negu', arguments) + class NorInstruction(Instruction): def __init__(self, arguments): super().__init__('nor', arguments) + class NotInstruction(Instruction): def __init__(self, arguments): super().__init__('not', arguments) + class OrInstruction(Instruction): def __init__(self, arguments): super().__init__('or', arguments) + class RemInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('rem', arguments) if signed else super().__init__('remu', arguments) + class RolInstruction(Instruction): def __init__(self, arguments): super().__init__('rol', arguments) + class RorInstruction(Instruction): def __init__(self, arguments): super().__init__('ror', arguments) + class SllInstruction(Instruction): def __init__(self, arguments): super().__init__('sll', arguments) + class SraInstruction(Instruction): def __init__(self, arguments): super().__init__('sra', arguments) - + + class SrlInstruction(Instruction): def __init__(self, arguments): super().__init__('srl', arguments) + class XorInstruction(Instruction): def __init__(self, arguments): super().__init__('xor', arguments) + class AbsInstruction(Instruction): def __init__(self, arguments): super().__init__('abs', arguments) - # ======================= # Comparison Instructions # ======================= @@ -129,28 +148,32 @@ class SeqInstruction(Instruction): def __init__(self, arguments): super().__init__('seq', arguments) + class SneInstruction(Instruction): def __init__(self, arguments): super().__init__('sne', arguments) + class SgeInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('sge', arguments) if signed else super().__init__('sgeu', arguments) + class SgtInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('sgt', arguments) if signed else super().__init__('sgtu', arguments) + class SleInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('sle', arguments) if signed else super().__init__('sleu', arguments) + class SltInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('slt', arguments) if signed else super().__init__('sltu', arguments) - # ============================ # Branch and Jump Instructions # ============================ @@ -159,28 +182,34 @@ class BInstruction(Instruction): def __init__(self, arguments): super().__init__('b', arguments) + class BeqInstruction(Instruction): def __init__(self, arguments): super().__init__('beq', arguments) + class BneInstruction(Instruction): def __init__(self, arguments): super().__init__('bne', arguments) + class BgeInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('bge', arguments) if signed else super().__init__('bgeu', arguments) + class BgtInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('bgt', arguments) if signed else super().__init__('bgtu', arguments) + class BleInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('ble', arguments) if signed else super().__init__('bleu', arguments) + class BltInstruction(Instruction): - def __init__(self, arguments, signed = True): + def __init__(self, arguments, signed=True): super().__init__('blt', arguments) if signed else super().__init__('bltu', arguments) @@ -188,6 +217,16 @@ class JInstruction(Instruction): def __init__(self, arguments): super().__init__('j', arguments) + class JrInstruction(Instruction): def __init__(self, arguments): - super().__init__('jr', arguments) \ No newline at end of file + super().__init__('jr', arguments) + +# ================== +# Exception Handling +# ================== + + +class SyscallInstruction(Instruction): + def __init__(self): + super().__init__('syscall') diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4fe75c3f..03afe0ef 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -57,7 +57,29 @@ def arg_to_mips_visitor(arg: cil.ArgNode): return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) +def allocate_to_mips_visitor(allocate: cil.AllocateNode): + """ + CIL: + x = ALLOCATE T + MIPS: + li $a0, [syze(T)] + li $v0, 9 + syscall + move [addr(x)], $v0 + """ + size = get_type_size(allocate.type) + address = __ADDRS__[allocate.result] + code = [ + mips.LiInstruction(('$a0', size)), + mips.LiInstruction(('$v0', 9)), + mips.SyscallInstruction(), + mips.MoveInstruction((address, '$v0')) + ] + return code + + __visitors__ = { cil.VCAllNode: vcall_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor + cil.AllocateNode: allocate_to_mips_visitor } diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 4195c0a0..32519562 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -30,7 +30,7 @@ def get_type_size(type): more for save the type identifier.Each attribute needs 4 bytes of space and the type identifier also. """ - return len(type.attributes) + 1 + return (len(type.attributes) + 1) * 4 def save_callee_registers(): @@ -38,8 +38,8 @@ def save_callee_registers(): for i in range(8): push_stack(f'$s{i}', (7-i)*4) push_stack('$fp', 4) - push_stack('$ra') - + push_stack('$ra') + def save_caller_registers(): allocate_stack(40) From a1b3b3488b08d227fee50b21f88db4cebc7190b9 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 11:10:46 -0400 Subject: [PATCH 274/435] finishing function to mips visitor --- src/code_generation/MIPS/ast.py | 4 ++++ src/code_generation/MIPS/mips.py | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 430a7f9f..7b5e2ea8 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -32,6 +32,10 @@ class JalInstruction(Instruction): def __init__(self, arguments): super().__init__('jal', arguments) +class JrInstruction(Instruction): + def __init__(self, arguments): + super().__init__('jr', arguments) + # ============================= # Load, Store and Data Movement diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index fa950857..f1b2ef00 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -36,10 +36,12 @@ def function_to_mips_visitor(function): for inst in function.body: code += instruction_to_mips_visitor(inst) - + + + code+=restore_stack(len(function.params)*4) code += restore_callee_registers() code += restore_stack(len(function.locals)*4) - + code.append(mips.JrInstruction('$ra')) return code From 5777761aa31581b4e2ab79fec7ce771a7071d79c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 11:15:01 -0400 Subject: [PATCH 275/435] Add COPY to MIPS visitor --- src/code_generation/MIPS/mips.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 03afe0ef..14bedb1a 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -75,11 +75,24 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): mips.SyscallInstruction(), mips.MoveInstruction((address, '$v0')) ] - return code + return code + + +def copy_to_mips_visitor(copy: cil.CopyNode): + """ + CIL: + x = COPY y + MIPS: + move [addr(x)], [addr(y)] + """ + x_addr = __ADDRS__[copy.result] + y_addr = __ADDRS__[copy.val] + return [mips.MoveInstruction((x_addr, y_addr))] __visitors__ = { cil.VCAllNode: vcall_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor - cil.AllocateNode: allocate_to_mips_visitor + cil.AllocateNode: allocate_to_mips_visitor, + cil.CopyNode: copy_to_mips_visitor } From 72e71ab93937ebd82135d2da0554067b3202c12c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 11:20:50 -0400 Subject: [PATCH 276/435] Add Comment instruction For insert comments inside MIPS code --- src/code_generation/MIPS/ast.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 4e30161c..1c088d78 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -14,6 +14,11 @@ def __str__(self): return f"{self.name} {self.arguments[0]}" +class Comment(Instruction): + def __init__(self, text): + super().__init__('#', (text)) + + # =============== # Data Directives # =============== From 92e35bdf67d9dbdcddde826aceda807a6f91026f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 11:21:19 -0400 Subject: [PATCH 277/435] Adding documentation --- src/code_generation/MIPS/mips.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f1b2ef00..04219e60 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -24,7 +24,19 @@ def program_to_mips_visitor(program: cil.ProgramNode): text_section += function_to_mips_visitor(function) + def function_to_mips_visitor(function): + ''' + Converts a function CIL to a piece of MIPS code:\n + 1) Assigns the right stack address to each param id\n + 2) Saves callee registers\n + 3) Assigns and allocates a chunk in the stack for each local\n + 4) Appends MIPS translation of each instruction in CIL body\n + 5) Restores param's space in stack\n + 6) Restores callee registers\n + 7) Restores local's stack space\n + 8) Jumps to the next instruction which address is in ra register\n + ''' for i,param in enumerate(function.params): __ADDRS__[param.id]=(len(function.params)-1-i)*4 @@ -46,17 +58,33 @@ def function_to_mips_visitor(function): def instruction_to_mips_visitor(inst): + ''' + Resolves visitor for each type + ''' try: return __visitors__[type(inst)] except KeyError: raise Exception(f'There is no visitor for {type(inst)}') + def vcall_to_mips_visitor(vcall: cil.VCAllNode): + ''' + Converts an VCall CIL node to a piece of MIPS code:\n + 1) Saves caller registers\n + 2) Jumps to function label and sets the value of ra\n + 3) Restore caller registers\n + 4) Takes the result from v0 + ''' return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] def arg_to_mips_visitor(arg: cil.ArgNode): + ''' + Converts an Arg CIL node to a piece of MIPS code:\n + 1) Allocates a 4-bytes space in stack\n + 2) Pushes the arg value in the stack\n + ''' return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) From 5009403ad6c5d9300aa1b3ae6d962555e05611ce Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 11:38:27 -0400 Subject: [PATCH 278/435] fixing push stack --- src/code_generation/MIPS/mips.py | 4 ++-- src/code_generation/MIPS/utilities.py | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index cc9a3903..9857db93 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -39,13 +39,13 @@ def function_to_mips_visitor(function): 8) Jumps to the next instruction which address is in ra register\n ''' for i,param in enumerate(function.params): - __ADDRS__[param.id]=(len(function.params)-1-i)*4 + __ADDRS__[param.id]=f'{(len(function.params)-1-i)*4}($sp)' code=save_callee_registers() code+=allocate_stack(len(function.locals)*4) for i,local in enumerate(function.locals): - __ADDRS__[local.id]=(len(function.locals)-1-i)*4 + __ADDRS__[local.id]=f'{(len(function.locals)-1-i)*4}($sp)' for inst in function.body: code += instruction_to_mips_visitor(inst) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index aa02fa67..850481c1 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -77,9 +77,17 @@ def allocate_stack(bytes): def push_stack(src, pos=0): - if pos: - return [mips.SwInstruction(src, f'{pos}($sp)')] - return [mips.SwInstruction(src, '($sp)')] + code=[] + if src[0]!='$': + code=[peek_stack('$t0', src)] + if pos: + return code+[mips.SwInstruction('$t0', f'{pos}($sp)')] + return code+[mips.SwInstruction('$t0', '($sp)')] + else: + if pos: + return code+[mips.SwInstruction(src, f'{pos}($sp)')] + return code+[mips.SwInstruction(src, '($sp)')] + def peek_stack(src, pos=0): From 8cd9510b48ada5e5736d3aa793c4515678ca23cc Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 29 May 2020 11:43:06 -0400 Subject: [PATCH 279/435] adding comment lines to mips visitors --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 9857db93..8d2178bb 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -77,7 +77,7 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): 3) Restore caller registers\n 4) Takes the result from v0 ''' - return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] + return [mips.Comment('[result] = VCALL [type] [method] ;')] + save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] def arg_to_mips_visitor(arg: cil.ArgNode): @@ -86,7 +86,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - return allocate_stack(4) + push_stack(__ADDRS__[arg.val]) + return [mips.Comment('ARG [arg] ;')] + allocate_stack(4) + push_stack(__ADDRS__[arg.val]) def allocate_to_mips_visitor(allocate: cil.AllocateNode): From 5161d26fbdc9d34adff6063457cdf7c6951ede16 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 12:27:22 -0400 Subject: [PATCH 280/435] Many things --- src/code_generation/MIPS/mips.py | 29 ++++++++++++++------- src/code_generation/MIPS/utilities.py | 37 ++++++++------------------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 14bedb1a..4a9b9f8b 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -1,5 +1,5 @@ from code_generation.CIL import ast as cil -from . import ast as mips +from code_generation.MIPS import ast as mips from .utilities import * __METHOD_MAPPING__ = {} @@ -10,7 +10,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__ # Initialize Types Codes - init_types_codes(program.types) + init_types(program.types) # filling method mapping for t in program.types: @@ -65,15 +65,16 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): li $a0, [syze(T)] li $v0, 9 syscall - move [addr(x)], $v0 + sw $v0, [addr(x)] """ - size = get_type_size(allocate.type) + size = allocate.type.size_mips address = __ADDRS__[allocate.result] code = [ + mips.Comment(str(allocate)), mips.LiInstruction(('$a0', size)), mips.LiInstruction(('$v0', 9)), mips.SyscallInstruction(), - mips.MoveInstruction((address, '$v0')) + mips.SwInstruction(('$v0', address)) ] return code @@ -83,16 +84,26 @@ def copy_to_mips_visitor(copy: cil.CopyNode): CIL: x = COPY y MIPS: - move [addr(x)], [addr(y)] + lw $t0, [addr(y)] + sw $t0, [addr(x)] """ x_addr = __ADDRS__[copy.result] y_addr = __ADDRS__[copy.val] - return [mips.MoveInstruction((x_addr, y_addr))] + return [ + mips.Comment(str(copy)), + mips.LwInstruction(('$t0', y_addr)), + mips.SwInstruction(('$t0', x_addr)) + ] + + +def getattr_to_mips_visitor(getattr: cil.GetAttrNode): + pass __visitors__ = { cil.VCAllNode: vcall_to_mips_visitor, - cil.ArgNode: arg_to_mips_visitor + cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, - cil.CopyNode: copy_to_mips_visitor + cil.CopyNode: copy_to_mips_visitor, + cil.GetAttrNode: getattr_to_mips_visitor } diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 32519562..c33b0223 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -1,36 +1,19 @@ +from code_generation.MIPS import ast as mips -__TYPES_CODES__ = {} - - -def init_types_codes(types): +def init_types(types): """ - Objects in MIPS code are memory space, therefore we need to know the type + Objects in MIPS code are memory space (size_mips), therefore we need to know the type of this object. But we cannot save the type name, therefore, we configure - a unique number for each type which will be identified in MIPS. - """ - for i, t in enumerate(types): - __TYPES_CODES__[t] = i - + a unique number for each type which will be identified in MIPS (code_mips)\n -def get_type_code(type): - """ - If the type is valid, it returns the number that identifies that type in - MIPS. In other case, returns None. """ - try: - return __TYPES_CODES__[type] - except KeyError: - return None - - -def get_type_size(type): - """ - The size of the any type in memory is size of they attributes and one space - more for save the type identifier.Each attribute needs 4 bytes of space and - the type identifier also. - """ - return (len(type.attributes) + 1) * 4 + for i, t in enumerate(types): + t.code_mips = i + t.size_mips = (len(t.attributes) + 1) * 4 + t.attr_index_mips = {} + for i, a in enumerate(t.attributes): + t.attr_index_mips[a] = i + 1 def save_callee_registers(): From d8f417e5af19aefe451e95210c3e1479bb33bbc0 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 29 May 2020 16:22:48 -0400 Subject: [PATCH 281/435] Fix redefined JrInstruction node --- src/code_generation/MIPS/ast.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index ca5355ff..079ebb14 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -26,19 +26,6 @@ def __init__(self, text): class AsciizInst(Instruction): def __init__(self, arguments): super().__init__(".asciiz", arguments) - - -# ============================ -# Jump and Branch Instructions -# ============================ - -class JalInstruction(Instruction): - def __init__(self, arguments): - super().__init__('jal', arguments) - -class JrInstruction(Instruction): - def __init__(self, arguments): - super().__init__('jr', arguments) # ============================= @@ -231,6 +218,13 @@ class JrInstruction(Instruction): def __init__(self, arguments): super().__init__('jr', arguments) +class JalInstruction(Instruction): + def __init__(self, arguments): + super().__init__('jal', arguments) + +class JalrInstruction(Instruction): + def __init__(self, arguments): + super().__init__('jalr', arguments) # ================== # Exception Handling # ================== From 4f4833e7aa825a62240851f37bb5a35927596fca Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 29 May 2020 17:17:02 -0400 Subject: [PATCH 282/435] Add arithmetic instructions to cil to mips visitors --- src/code_generation/MIPS/mips.py | 99 +++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 9e3bef48..7851dfa3 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -131,11 +131,108 @@ def copy_to_mips_visitor(copy: cil.CopyNode): def getattr_to_mips_visitor(getattr: cil.GetAttrNode): pass +def plus_to_mips_visitor(plus: cil.PlusNode): + """ + CIL: + x = y + z + MIPS: + add x, y, z + """ + + return [ + mips.Comment(str(plus)), + mips.AddInstruction((plus.result, plus.left, plus.right)) + ] + +def minus_to_mips_visitor(minus: cil.MinusNode): + """ + CIL: + x = y - z + MIPS: + sub x, y, z + """ + + return [ + mips.Comment(str(minus)), + mips.SubInstruction((minus.result, minus.left, minus.right)) + ] + +def star_to_mips_visitor(star: cil.StarNode): + """ + CIL: + x = y * z + MIPS: + mult x, y, z + """ + + return [ + mips.Comment(str(star)), + mips.MultInstruction((star.result, star.left, star.right)) + ] + +def div_to_mips_visitor(div: cil.DivNode): + """ + CIL: + x = y / z + MIPS: + div x, y, z + """ + + return [ + mips.Comment(str(div)), + mips.DivInstruction((div.result, div.left, div.right)) + ] + +def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): + """ + CIL: + x = y <= z + MIPS: + sle x, y, z + """ + + return [ + mips.Comment(str(lesseq)), + mips.SleInstruction((lesseq.result, lesseq.left, lesseq.right)) + ] + +def less_to_mips_visitor(less: cil.LessNode): + """ + CIL: + x = y < z + MIPS: + slt x, y, z + """ + + return [ + mips.Comment(str(less)), + mips.SleInstruction((less.result, less.left, less.right)) + ] + +def not_to_mips_visitor(notn: cil.NotNode): + """ + CIL: + x = ~ y + MIPS: + not x, y + """ + + return [ + mips.Comment(str(notn)), + mips.NotInstruction((notn.result, notn.value)) + ] __visitors__ = { cil.VCAllNode: vcall_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, - cil.GetAttrNode: getattr_to_mips_visitor + cil.GetAttrNode: getattr_to_mips_visitor, + cil.PlusNode: plus_to_mips_visitor, + cil.MinusNode: minus_to_mips_visitor, + cil.StarNode: star_to_mips_visitor, + cil.DivNode: div_to_mips_visitor, + cil.LessEqNode: lesseq_to_mips_visitor, + cil.LessNode: less_to_mips_visitor, + cil.NotNode: not_to_mips_visitor, } From e186217736079bbe2a718496eca5053c7fade59b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 17:43:02 -0400 Subject: [PATCH 283/435] Add attr_index to GETATTR and SETATTR and Reformat code --- src/code_generation/CIL/ast.py | 68 +++++++++++++++++----------------- src/code_generation/CIL/cil.py | 43 +++++++++++---------- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 20a0acaa..6d024f06 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -8,7 +8,7 @@ def __init__(self, types, data, code, built_in_code): self.data = data self.code = code self.built_in_code = built_in_code - + def __str__(self): type_code = '' data_code = '' @@ -27,13 +27,12 @@ def __str__(self): return f'.TYPES \n\n{type_code}\n.DATA\n\n{data_code}\n.CODE\n\n{func_code}\n' - class TypeNode(Node): def __init__(self, type): self.attributes = [] self.methods = {} self.type = type - + def __str__(self): attr_code = '' method_code = '' @@ -50,7 +49,7 @@ class DataNode(Node): def __init__(self, id, val): self.id = id self.val = val - + def __str__(self): return f'{self.id} = \"{self.val}\" ;' @@ -61,7 +60,7 @@ def __init__(self, name, params, locals, body): self.params = params self.locals = locals self.body = body - + def __str__(self): params_code = '' locals_code = '' @@ -101,7 +100,7 @@ def __repr__(self): class ParamNode(Node): def __init__(self, id): self.id = id - + def __str__(self): return f'PARAM {self.id} ;' @@ -113,7 +112,7 @@ def __init__(self, result, val): self.val = val self.check_local(result) self.check_local(val) - + def __str__(self): return f'{self.result} = {self.val} ;' @@ -134,7 +133,6 @@ def __str__(self): return f'{self.result} = {self.left} + {self.right} ;' - class MinusNode(ArithNode): def __str__(self): return f'{self.result} = {self.left} - {self.right} ;' @@ -167,33 +165,35 @@ def __init__(self, value, result): self.result = result self.check_local(value) self.check_local(result) - + def __str__(self): return f'{self.result} = ~ {self.value}' class GetAttrNode(InstructionNode): - def __init__(self, obj, attr, result): + def __init__(self, obj, attr, result, attr_index=0): super().__init__() self.attr = attr self.obj = obj self.result = result + self.attr_index = attr_index self.check_local(obj) self.check_local(result) - + def __str__(self): return f'{self.result} = GETATTR {self.obj} {self.attr} ;' class SetAttrNode(InstructionNode): - def __init__(self, obj, attr, val): + def __init__(self, obj, attr, val, attr_index=0): super().__init__() self.val = val self.obj = obj self.attr = attr + self.attr_index = attr_index self.check_local(obj) self.check_local(val) - + def __str__(self): return f'SETATTR {self.obj} {self.attr} {self.val} ;' @@ -203,7 +203,7 @@ def __init__(self, array, index, val): self.val = val self.array = array self.index = index - + def __str__(self): return f'SETINDEX {self.array} {self.index} {self.val} ;' @@ -213,7 +213,7 @@ def __init__(self, array, index, result): self.result = result self.array = array self.index = index - + def __str__(self): return f'{self.result} = GETINDEX {self.array} {self.index} ;' @@ -224,7 +224,7 @@ def __init__(self, _type, result): self.type = _type self.result = result self.check_local(result) - + def __str__(self): return f'{self.result} = ALLOCATE {self.type} ;' @@ -237,7 +237,7 @@ def __str__(self): class ReadIntNode(InstructionNode): def __init__(self, result): self.result = result - + def __str__(self): return f'{self.result} = READINT ;' @@ -246,7 +246,7 @@ class CopyNode(InstructionNode): def __init__(self, val, result): self.result = result self.val = val - + def __str__(self): return f'{self.result} = COPY {self.val} ;' @@ -258,7 +258,7 @@ def __init__(self, result, var): self.var = var self.check_local(result) self.check_local(var) - + def __str__(self): return f'{self.result} = TYPEOF {self.var} ;' @@ -267,7 +267,7 @@ class ArrayNode(InstructionNode): def __init__(self, len, result): self.len = len self.result = result - + def __str__(self): return f'{self.result} = ARRAY {self.len} ;' @@ -276,7 +276,7 @@ class CallNode(InstructionNode): def __init__(self, method, result): self.method = method self.result = result - + def __str__(self): return f'{self.result} = CALL {self.method} ;' @@ -289,7 +289,7 @@ def __init__(self, type, method, result): self.result = result self.check_local(result) self.check_local(type) - + def __str__(self): return f'{self.result} = VCALL {self.type} {self.method} ;' @@ -299,7 +299,7 @@ def __init__(self, val): super().__init__() self.val = val self.check_local(val) - + def __str__(self): return f'ARG {self.val} ;' @@ -310,7 +310,7 @@ def __init__(self, predicate, label): self.predicate = predicate self.label = label self.check_local(predicate) - + def __str__(self): return f'IF {self.predicate} GOTO {self.label} ;' @@ -319,7 +319,7 @@ class GotoNode(InstructionNode): def __init__(self, label): super().__init__() self.label = label - + def __str__(self): return f'GOTO {self.label} ;' @@ -328,7 +328,7 @@ class LabelNode(InstructionNode): def __init__(self, label_name): super().__init__() self.label_name = label_name - + def __str__(self): return f'LABEL {self.label_name} ;' @@ -338,7 +338,7 @@ def __init__(self, ret_value): super().__init__() self.ret_value = ret_value self.check_local(ret_value) - + def __str__(self): return f'RETURN {self.ret_value} ;' if self.ret_value else f'RETURN ;' @@ -349,7 +349,7 @@ def __init__(self, addr, result): self.result = result self.addr = addr self.check_local(result) - + def __str__(self): return f'{self.result} = LOAD {self.addr} ;' @@ -358,7 +358,7 @@ class LengthNode(InstructionNode): def __init__(self, str, result): self.result = result self.str = str - + def __str__(self): return f'{self.result} = LENGTH {self.str} ;' @@ -368,7 +368,7 @@ def __init__(self, str_a, str_b, result): self.result = result self.str_a = str_a self.str_b = str_b - + def __str__(self): return f'{self.result} = CONCAT {self.str_a} {self.str_b} ;' @@ -379,7 +379,7 @@ def __init__(self, str, i, len, result): self.i = i self.len = len self.str = str - + def __str__(self): return f'{self.result} = SUBSTRING {self.str} {self.i} {self.len};' @@ -391,7 +391,7 @@ def __init__(self, val, result): self.val = val self.check_local(val) self.check_local(result) - + def __str__(self): return f'{self.result} = STR {self.val} ;' @@ -401,7 +401,7 @@ def __init__(self, result): super().__init__() self.result = result self.check_local(result) - + def __str__(self): return f'{self.result} = READ ;' @@ -411,6 +411,6 @@ def __init__(self, str): super().__init__() self.str = str self.check_local(str) - + def __str__(self): return f'PRINT {self.str} ;' diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index a7314d61..40b5571f 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -5,6 +5,7 @@ __DATA__ = {} + def add_str_data(data: str): try: return __DATA__[data] @@ -20,13 +21,15 @@ def add_str_data(data: str): def add_local(id=None): global __LOCALS__ if id is None: - id=f'local_{len(__LOCALS__)}' + id = f'local_{len(__LOCALS__)}' local = cil.LocalNode(id) - __LOCALS__[id]=local + __LOCALS__[id] = local return local + labels_count = 0 + def add_label(): global labels_count labels_count += 1 @@ -63,10 +66,10 @@ def get_typeof(obj): return type_local, True - __ATTR__ = {} __CURRENT_TYPE__ = None + def program_to_cil_visitor(program): types = [] code = [] @@ -76,7 +79,7 @@ def program_to_cil_visitor(program): for t in TypesByName: _type = cil.TypeNode(t) value = TypesByName[t] - __ATTR__[t]=[] + __ATTR__[t] = [] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) __ATTR__[t].append(attr.id) @@ -148,7 +151,7 @@ def in_int_to_cil(): def type_name_to_cil(): - return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.StrNode('type', 'str'),cil.ReturnNode('str')]) + return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.StrNode('type', 'str'), cil.ReturnNode('str')]) def copy_to_cil(): @@ -173,7 +176,7 @@ def func_to_cil_visitor(type_name, func): 1) Builds ParamNodes for each param in FunctionNode.params\n 2) Builds function body by putting together each instruction's body\n 3) Creates an array of necessary local variables - + ''' global __LOCALS__, __DATA_LOCALS__, __TYPEOF__, labels_count, __CURRENT_TYPE__ name = f'{type_name}_{func.id}' @@ -237,7 +240,7 @@ def case_to_cil_visitor(case): predicate = add_local() body.append(cil.MinusNode(str_t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) - val=add_local(branch.id) + val = add_local(branch.id) body.append(cil.AssignNode(val, expr_cil.value)) branch_cil = expression_to_cil_visitor( branch.expr) @@ -249,18 +252,19 @@ def case_to_cil_visitor(case): def assign_to_cil_visitor(assign): - ''' AssignNode CIL converter.\n 1) Pendiente ''' - + expr = expression_to_cil_visitor(assign.expr) if assign.id in __ATTR__[__CURRENT_TYPE__]: - body=expr.body + [cil.SetAttrNode('self', assign.id, expr.value)] + index = __ATTR__[__CURRENT_TYPE__].index(assign.id) + body = expr.body + \ + [cil.SetAttrNode('self', assign.id, expr.value, index)] return CIL_block(body, expr.value) else: - val=add_local(assign.id) + val = add_local(assign.id) body = expr.body + [cil.AssignNode(val, expr.value)] return CIL_block(body, val) @@ -312,12 +316,12 @@ def loop_to_cil_visitor(loop): value = add_local() - predicate_label=add_label() + predicate_label = add_label() loop_label = add_label() end_label = add_label() body = [cil.LabelNode(predicate_label)] + predicate.body + [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), - cil.LabelNode(loop_label)] + loop_block.body + [cil.GotoNode(predicate_label),cil.LabelNode(end_label), cil.AssignNode(value, 0)] + cil.LabelNode(loop_label)] + loop_block.body + [cil.GotoNode(predicate_label), cil.LabelNode(end_label), cil.AssignNode(value, 0)] return CIL_block(body, value) @@ -366,10 +370,11 @@ def bool_to_cil_visitor(bool): def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: - result=add_local() - return CIL_block([cil.GetAttrNode('self', id.id, result)], result) + result = add_local() + index = __ATTR__[__CURRENT_TYPE__].index(id.id) + return CIL_block([cil.GetAttrNode('self', id.id, result, index)], result) try: - val=__LOCALS__[id.id] + val = __LOCALS__[id.id] return CIL_block([], val) except: return CIL_block([], id.id) @@ -388,12 +393,12 @@ def new_to_cil_visitor(new_node): body.append(cil.AllocateNode(t, value)) init_attr = TypesByName[t].get_all_attributes() - for attr in init_attr: + for index, attr in enumerate(init_attr): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body - body.append(cil.SetAttrNode(value, attr.id, attr_cil.value)) + body.append(cil.SetAttrNode(value, attr.id, attr_cil.value, index)) return CIL_block(body, value) @@ -425,7 +430,7 @@ def let_to_cil_visitor(let): if attr.expr: attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body - val=add_local(attr.id) + val = add_local(attr.id) body.append(cil.AssignNode(val, attr_cil.value)) expr_cil = expression_to_cil_visitor(let.expr) From 977824f5b7e03feb2bbec4ee497642167037f9e8 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 18:11:19 -0400 Subject: [PATCH 284/435] Add GETATTR to MIPS visitor --- src/code_generation/MIPS/mips.py | 46 +++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 9e3bef48..bd383b2c 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -25,7 +25,6 @@ def program_to_mips_visitor(program: cil.ProgramNode): text_section += function_to_mips_visitor(function) - def function_to_mips_visitor(function): ''' Converts a function CIL to a piece of MIPS code:\n @@ -38,23 +37,22 @@ def function_to_mips_visitor(function): 7) Restores local's stack space\n 8) Jumps to the next instruction which address is in ra register\n ''' - for i,param in enumerate(function.params): - __ADDRS__[param.id]=f'{(len(function.params)-1-i)*4}($sp)' - - code=save_callee_registers() - - code+=allocate_stack(len(function.locals)*4) - for i,local in enumerate(function.locals): - __ADDRS__[local.id]=f'{(len(function.locals)-1-i)*4}($sp)' - + for i, param in enumerate(function.params): + __ADDRS__[param.id] = f'{(len(function.params)-1-i)*4}($sp)' + + code = save_callee_registers() + + code += allocate_stack(len(function.locals)*4) + for i, local in enumerate(function.locals): + __ADDRS__[local.id] = f'{(len(function.locals)-1-i)*4}($sp)' + for inst in function.body: code += instruction_to_mips_visitor(inst) - - - code+=restore_stack(len(function.params)*4) + + code += restore_stack(len(function.params)*4) code += restore_callee_registers() code += restore_stack(len(function.locals)*4) - code.append(mips.JrInstruction('$ra')) + code.append(mips.JrInstruction('$ra')) return code @@ -68,7 +66,6 @@ def instruction_to_mips_visitor(inst): raise Exception(f'There is no visitor for {type(inst)}') - def vcall_to_mips_visitor(vcall: cil.VCAllNode): ''' Converts an VCall CIL node to a piece of MIPS code:\n @@ -129,7 +126,24 @@ def copy_to_mips_visitor(copy: cil.CopyNode): def getattr_to_mips_visitor(getattr: cil.GetAttrNode): - pass + """ + CIL: + x = GETATTR y attr + MIPS: + lw $t0, [addr(y)] + lw $t1, [attr_shift($t0)] + sw $t1, [addr(x)] + """ + + x_addr = __ADDRS__[getattr.result] + y_addr = __ADDRS__[getattr.obj] + attr_shift = (getattr.attr_index + 1) * 4 + return [ + mips.Comment(str(getattr)), + mips.LwInstruction(('$t0', y_addr)), + mips.LwInstruction(('$t1', f'{attr_shift}($t0)')), + mips.SwInstruction(('$t1', x_addr)) + ] __visitors__ = { From bd90d6f312d69e898331a1baf520fa5f850aecf5 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 18:16:10 -0400 Subject: [PATCH 285/435] Reformat code --- src/code_generation/MIPS/mips.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 798da81e..5b34bd3b 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -145,6 +145,7 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): mips.SwInstruction(('$t1', x_addr)) ] + def plus_to_mips_visitor(plus: cil.PlusNode): """ CIL: @@ -158,6 +159,7 @@ def plus_to_mips_visitor(plus: cil.PlusNode): mips.AddInstruction((plus.result, plus.left, plus.right)) ] + def minus_to_mips_visitor(minus: cil.MinusNode): """ CIL: @@ -171,6 +173,7 @@ def minus_to_mips_visitor(minus: cil.MinusNode): mips.SubInstruction((minus.result, minus.left, minus.right)) ] + def star_to_mips_visitor(star: cil.StarNode): """ CIL: @@ -184,6 +187,7 @@ def star_to_mips_visitor(star: cil.StarNode): mips.MultInstruction((star.result, star.left, star.right)) ] + def div_to_mips_visitor(div: cil.DivNode): """ CIL: @@ -197,6 +201,7 @@ def div_to_mips_visitor(div: cil.DivNode): mips.DivInstruction((div.result, div.left, div.right)) ] + def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): """ CIL: @@ -210,6 +215,7 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): mips.SleInstruction((lesseq.result, lesseq.left, lesseq.right)) ] + def less_to_mips_visitor(less: cil.LessNode): """ CIL: @@ -223,6 +229,7 @@ def less_to_mips_visitor(less: cil.LessNode): mips.SleInstruction((less.result, less.left, less.right)) ] + def not_to_mips_visitor(notn: cil.NotNode): """ CIL: @@ -236,6 +243,7 @@ def not_to_mips_visitor(notn: cil.NotNode): mips.NotInstruction((notn.result, notn.value)) ] + __visitors__ = { cil.VCAllNode: vcall_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, From d9b72e6f91c5b55b997d6d9df57767e724d332e9 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 18:35:37 -0400 Subject: [PATCH 286/435] Add SETATTR to MIPS visitor --- src/code_generation/MIPS/mips.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 5b34bd3b..ba3de0a8 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -146,6 +146,26 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): ] +def setattr_to_mips_visitor(setattr: cil.SetAttrNode): + """ + CIL: + SETATTR y attr x + MIPS: + lw $t0, [addr(x)] + lw $t1, [addr(y)] + sw $t0, [attr_shift($t0)] + """ + x_addr = __ADDRS__[setattr.val] + y_addr = __ADDRS__[setattr.obj] + attr_shift = (setattr.attr_index + 1) * 4 + return [ + mips.Comment(str(setattr)), + mips.LwInstruction(('$t0', x_addr)), + mips.LwInstruction(('$t1', y_addr)), + mips.SwInstruction(('$t0', f'{attr_shift}($t0)')) + ] + + def plus_to_mips_visitor(plus: cil.PlusNode): """ CIL: @@ -250,6 +270,7 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, cil.GetAttrNode: getattr_to_mips_visitor, + cil.SetAttrNode: setattr_to_mips_visitor, cil.PlusNode: plus_to_mips_visitor, cil.MinusNode: minus_to_mips_visitor, cil.StarNode: star_to_mips_visitor, From 5cdd8ad096e5921dffd00de3700200fb9b724b38 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 29 May 2020 18:57:20 -0400 Subject: [PATCH 287/435] Fix arithmetic operators --- src/code_generation/MIPS/mips.py | 43 ++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index ba3de0a8..90a08935 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -171,12 +171,21 @@ def plus_to_mips_visitor(plus: cil.PlusNode): CIL: x = y + z MIPS: - add x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + add $t0, $t1, $t2 + sw $t0, [addr(x)] """ + x_addr = __ADDRS__[plus.result] + y_addr = __ADDRS__[plus.left] + z_addr = __ADDRS__[plus.right] return [ mips.Comment(str(plus)), - mips.AddInstruction((plus.result, plus.left, plus.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.AddInstruction(('$t0', '$t1', '$t2')) + mips.SwInstruction(('$t0', x_addr)) ] @@ -185,12 +194,18 @@ def minus_to_mips_visitor(minus: cil.MinusNode): CIL: x = y - z MIPS: - sub x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + sub $t0, $t1, $t2 + sw $t0, [addr(x)] """ return [ mips.Comment(str(minus)), - mips.SubInstruction((minus.result, minus.left, minus.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.SubInstruction(('$t0', '$t1', '$t2')) + mips.SwInstruction(('$t0', x_addr)) ] @@ -199,12 +214,18 @@ def star_to_mips_visitor(star: cil.StarNode): CIL: x = y * z MIPS: - mult x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + mult $t0, $t1, $t2 + sw $t0, [addr(x)] """ return [ mips.Comment(str(star)), - mips.MultInstruction((star.result, star.left, star.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.MultInstruction(('$t0', '$t1', '$t2')) + mips.SwInstruction(('$t0', x_addr)) ] @@ -213,12 +234,18 @@ def div_to_mips_visitor(div: cil.DivNode): CIL: x = y / z MIPS: - div x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + div $t0, $t1, $t2 + sw $t0, [addr(x)] """ return [ mips.Comment(str(div)), - mips.DivInstruction((div.result, div.left, div.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.DivInstruction(('$t0', '$t1', '$t2')) + mips.SwInstruction(('$t0', x_addr)) ] From 8024632011131dce984292d6bf87e1cfeb613e67 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 29 May 2020 19:48:24 -0400 Subject: [PATCH 288/435] Re Fix arithmetic operators --- src/code_generation/MIPS/mips.py | 57 ++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 90a08935..f3cdf98c 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -184,7 +184,7 @@ def plus_to_mips_visitor(plus: cil.PlusNode): mips.Comment(str(plus)), mips.LwInstruction(('$t1', y_addr)), mips.LwInstruction(('$t2', z_addr)), - mips.AddInstruction(('$t0', '$t1', '$t2')) + mips.AddInstruction(('$t0', '$t1', '$t2')), mips.SwInstruction(('$t0', x_addr)) ] @@ -199,12 +199,14 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - + x_addr = __ADDRS__[minus.result] + y_addr = __ADDRS__[minus.left] + z_addr = __ADDRS__[minus.right] return [ mips.Comment(str(minus)), mips.LwInstruction(('$t1', y_addr)), mips.LwInstruction(('$t2', z_addr)), - mips.SubInstruction(('$t0', '$t1', '$t2')) + mips.SubInstruction(('$t0', '$t1', '$t2')), mips.SwInstruction(('$t0', x_addr)) ] @@ -219,12 +221,14 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - + x_addr = __ADDRS__[star.result] + y_addr = __ADDRS__[star.left] + z_addr = __ADDRS__[star.right] return [ mips.Comment(str(star)), mips.LwInstruction(('$t1', y_addr)), mips.LwInstruction(('$t2', z_addr)), - mips.MultInstruction(('$t0', '$t1', '$t2')) + mips.MultInstruction(('$t0', '$t1', '$t2')), mips.SwInstruction(('$t0', x_addr)) ] @@ -239,12 +243,14 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - + x_addr = __ADDRS__[div.result] + y_addr = __ADDRS__[div.left] + z_addr = __ADDRS__[div.right] return [ mips.Comment(str(div)), mips.LwInstruction(('$t1', y_addr)), mips.LwInstruction(('$t2', z_addr)), - mips.DivInstruction(('$t0', '$t1', '$t2')) + mips.DivInstruction(('$t0', '$t1', '$t2')), mips.SwInstruction(('$t0', x_addr)) ] @@ -254,12 +260,21 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): CIL: x = y <= z MIPS: - sle x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + sle $t0, $t1, $t2 + sw $t0, [addr(x)] """ + x_addr = __ADDRS__[lesseq.result] + y_addr = __ADDRS__[lesseq.left] + z_addr = __ADDRS__[lesseq.right] return [ mips.Comment(str(lesseq)), - mips.SleInstruction((lesseq.result, lesseq.left, lesseq.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.SleInstruction(('$t0', '$t1', '$t2')), + mips.SwInstruction(('$t0', x_addr)) ] @@ -268,12 +283,21 @@ def less_to_mips_visitor(less: cil.LessNode): CIL: x = y < z MIPS: - slt x, y, z + lw $t1, [addr(y)] + lw $t2, [addr(z)] + slt $t0, $t1, $t2 + sw $t0, [addr(x)] """ + x_addr = __ADDRS__[less.result] + y_addr = __ADDRS__[less.left] + z_addr = __ADDRS__[less.right] return [ mips.Comment(str(less)), - mips.SleInstruction((less.result, less.left, less.right)) + mips.LwInstruction(('$t1', y_addr)), + mips.LwInstruction(('$t2', z_addr)), + mips.SleInstruction(('$t0', '$t1', '$t2')), + mips.SwInstruction(('$t0', x_addr)) ] @@ -282,12 +306,17 @@ def not_to_mips_visitor(notn: cil.NotNode): CIL: x = ~ y MIPS: - not x, y + lw $t1, [addr(y)] + not $t0, $t1 + sw $t0, [addr(x)] """ - + x_addr = __ADDRS__[notn.result] + y_addr = __ADDRS__[notn.value] return [ mips.Comment(str(notn)), - mips.NotInstruction((notn.result, notn.value)) + mips.LwInstruction(('$t1', y_addr)), + mips.NotInstruction(('$t0', '$t1')), + mips.SwInstruction(('$t0', x_addr)) ] From 41bb4fa6043aafe2a858dbcaf5e00c585191dabb Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 1 Jun 2020 17:26:04 -0400 Subject: [PATCH 289/435] Add MIPSProgram class --- src/code_generation/MIPS/ast.py | 16 +++++++++++++++- src/code_generation/MIPS/mips.py | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 079ebb14..ca851f44 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -1,3 +1,15 @@ + +class MIPSProgram: + def __init__(self, data_section, text_section): + self.data = data_section + self.text = text_section + + def __str__(self): + d = '\n'.join([str(x) for x in self.data]) + t = '\n'.join([str(x) for x in self.text]) + return '\n'.join([t, d]) + + class Instruction: def __init__(self, name, arguments=None): self.name = name @@ -26,7 +38,7 @@ def __init__(self, text): class AsciizInst(Instruction): def __init__(self, arguments): super().__init__(".asciiz", arguments) - + # ============================= # Load, Store and Data Movement @@ -218,10 +230,12 @@ class JrInstruction(Instruction): def __init__(self, arguments): super().__init__('jr', arguments) + class JalInstruction(Instruction): def __init__(self, arguments): super().__init__('jal', arguments) + class JalrInstruction(Instruction): def __init__(self, arguments): super().__init__('jalr', arguments) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f3cdf98c..827629c6 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -24,6 +24,8 @@ def program_to_mips_visitor(program: cil.ProgramNode): for function in program.built_in_code + program.code: text_section += function_to_mips_visitor(function) + return mips.MIPSProgram(data_section, text_section) + def function_to_mips_visitor(function): ''' From d86a819c93f2df11543a2f6a118b0b4e66307ede Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 1 Jun 2020 18:58:49 -0400 Subject: [PATCH 290/435] Change MIPS AST and output format - Change MIPS AST - Change output format to .mips - Make better arguments for MIPS AST nodes - Add get_type function to utils.py - Add MIPS code to generate_code function --- src/code_generation/MIPS/ast.py | 274 ++++++++++++++++++-------- src/code_generation/MIPS/mips.py | 99 +++++----- src/code_generation/MIPS/utilities.py | 52 +++-- src/code_generation/code_gen.py | 4 +- src/main.py | 2 +- 5 files changed, 274 insertions(+), 157 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index ca851f44..9b850374 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -5,25 +5,59 @@ def __init__(self, data_section, text_section): self.text = text_section def __str__(self): - d = '\n'.join([str(x) for x in self.data]) - t = '\n'.join([str(x) for x in self.text]) - return '\n'.join([t, d]) + return f'{self.text}{self.data}' + + +class MIPSTextSection: + def __init__(self, fucntions): + self.fucntions = fucntions + + def __str__(self): + functions_text = '\n'.join([str(f) for f in self.fucntions]) + return f'\n.text\n{functions_text}\n' + + +class MIPSDataSection: + def __init__(self, data): + self.data = data + + def __str__(self): + data_text = '\n'.join([str(d) for d in self.data]) + return f'\n.data\n{data_text}\n' + + +class MIPSFunction: + def __init__(self, name, instructions): + self.name = name + self.instructions = instructions + + def __str__(self): + return '\n'.join([f'# FUNCTION: {self.name}']+[str(i) for i in self.instructions]) + + +class MIPSDataItem: + def __init__(self, label, instruction): + self.label = label + self.instruction = instruction + + def __str__(self): + return f'{self.label}: {str(self.instruction)}' class Instruction: - def __init__(self, name, arguments=None): + def __init__(self, name, *arguments): self.name = name self.arguments = arguments def __str__(self): - if self.arguments is None: - return f"{self.name}" + if len(self.arguments) == 0: + return f"\t{self.name}" elif len(self.arguments) == 3: - return f"{self.name} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" + return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" elif len(self.arguments) == 2: - return f"{self.name} {self.arguments[0]}, {self.arguments[1]}" + return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}" elif len(self.arguments) == 1: - return f"{self.name} {self.arguments[0]}" + return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}" class Comment(Instruction): @@ -36,8 +70,8 @@ def __init__(self, text): # =============== class AsciizInst(Instruction): - def __init__(self, arguments): - super().__init__(".asciiz", arguments) + def __init__(self, *arguments): + super().__init__(".asciiz", *arguments) # ============================= @@ -45,23 +79,23 @@ def __init__(self, arguments): # ============================= class MoveInstruction(Instruction): - def __init__(self, arguments): - super().__init__('move', arguments) + def __init__(self, *arguments): + super().__init__('move', *arguments) class SwInstruction(Instruction): - def __init__(self, arguments): - super().__init__('sw', arguments) + def __init__(self, *arguments): + super().__init__('sw', *arguments) class LwInstruction(Instruction): - def __init__(self, arguments): - super().__init__('lw', arguments) + def __init__(self, *arguments): + super().__init__('lw', *arguments) class LiInstruction(Instruction): - def __init__(self, arguments): - super().__init__('li', arguments) + def __init__(self, *arguments): + super().__init__('li', *arguments) # ======================= @@ -69,83 +103,113 @@ def __init__(self, arguments): # ======================= class SubInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('sub', arguments) if signed else super().__init__('subu', arguments) + def __init__(self, *arguments): + super().__init__('sub', *arguments) + + +class SubuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('subu', *arguments) class AddInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('add', arguments) if signed else super().__init__('addu', arguments) + def __init__(self, *arguments): + super().__init__('add', *arguments) + + +class AdduInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('addu', *arguments) class MultInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('mult', arguments) if signed else super().__init__('multu', arguments) + def __init__(self, *arguments): + super().__init__('mult', *arguments) + + +class MultuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('multu', *arguments) class DivInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('div', arguments) if signed else super().__init__('divu', arguments) + def __init__(self, *arguments): + super().__init__('div', *arguments) + + +class DivuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('divu', *arguments) class NegInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('neg', arguments) if signed else super().__init__('negu', arguments) + def __init__(self, *arguments): + super().__init__('neg', *arguments) + + +class NeguInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('negu', *arguments) class NorInstruction(Instruction): - def __init__(self, arguments): - super().__init__('nor', arguments) + def __init__(self, *arguments): + super().__init__('nor', *arguments) class NotInstruction(Instruction): - def __init__(self, arguments): - super().__init__('not', arguments) + def __init__(self, *arguments): + super().__init__('not', *arguments) class OrInstruction(Instruction): - def __init__(self, arguments): - super().__init__('or', arguments) + def __init__(self, *arguments): + super().__init__('or', *arguments) class RemInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('rem', arguments) if signed else super().__init__('remu', arguments) + def __init__(self, *arguments): + super().__init__('rem', *arguments) + + +class RemuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('remu', *arguments) class RolInstruction(Instruction): - def __init__(self, arguments): - super().__init__('rol', arguments) + def __init__(self, *arguments): + super().__init__('rol', *arguments) class RorInstruction(Instruction): - def __init__(self, arguments): - super().__init__('ror', arguments) + def __init__(self, *arguments): + super().__init__('ror', *arguments) class SllInstruction(Instruction): - def __init__(self, arguments): - super().__init__('sll', arguments) + def __init__(self, *arguments): + super().__init__('sll', *arguments) class SraInstruction(Instruction): - def __init__(self, arguments): - super().__init__('sra', arguments) + def __init__(self, *arguments): + super().__init__('sra', *arguments) class SrlInstruction(Instruction): - def __init__(self, arguments): - super().__init__('srl', arguments) + def __init__(self, *arguments): + super().__init__('srl', *arguments) class XorInstruction(Instruction): - def __init__(self, arguments): - super().__init__('xor', arguments) + def __init__(self, *arguments): + super().__init__('xor', *arguments) class AbsInstruction(Instruction): - def __init__(self, arguments): - super().__init__('abs', arguments) + def __init__(self, *arguments): + super().__init__('abs', *arguments) # ======================= @@ -153,33 +217,53 @@ def __init__(self, arguments): # ======================= class SeqInstruction(Instruction): - def __init__(self, arguments): - super().__init__('seq', arguments) + def __init__(self, *arguments): + super().__init__('seq', *arguments) class SneInstruction(Instruction): - def __init__(self, arguments): - super().__init__('sne', arguments) + def __init__(self, *arguments): + super().__init__('sne', *arguments) class SgeInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('sge', arguments) if signed else super().__init__('sgeu', arguments) + def __init__(self, *arguments): + super().__init__('sge', *arguments) + + +class SgeuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('sgeu', *arguments) class SgtInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('sgt', arguments) if signed else super().__init__('sgtu', arguments) + def __init__(self, *arguments): + super().__init__('sgt', *arguments) + + +class SgtuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('sgtu', *arguments) class SleInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('sle', arguments) if signed else super().__init__('sleu', arguments) + def __init__(self, *arguments): + super().__init__('sle', *arguments) + + +class SleuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('sleu', *arguments) class SltInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('slt', arguments) if signed else super().__init__('sltu', arguments) + def __init__(self, *arguments): + super().__init__('slt', *arguments) + + +class SltuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('sltu', *arguments) # ============================ @@ -187,58 +271,78 @@ def __init__(self, arguments, signed=True): # ============================ class BInstruction(Instruction): - def __init__(self, arguments): - super().__init__('b', arguments) + def __init__(self, *arguments): + super().__init__('b', *arguments) class BeqInstruction(Instruction): - def __init__(self, arguments): - super().__init__('beq', arguments) + def __init__(self, *arguments): + super().__init__('beq', *arguments) class BneInstruction(Instruction): - def __init__(self, arguments): - super().__init__('bne', arguments) + def __init__(self, *arguments): + super().__init__('bne', *arguments) class BgeInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('bge', arguments) if signed else super().__init__('bgeu', arguments) + def __init__(self, *arguments): + super().__init__('bge', *arguments) + + +class BgeuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('bgeu', *arguments) class BgtInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('bgt', arguments) if signed else super().__init__('bgtu', arguments) + def __init__(self, *arguments): + super().__init__('bgt', *arguments) + + +class BgtuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('bgtu', *arguments) class BleInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('ble', arguments) if signed else super().__init__('bleu', arguments) + def __init__(self, *arguments): + super().__init__('ble', *arguments) + + +class BleuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('bleu', *arguments) class BltInstruction(Instruction): - def __init__(self, arguments, signed=True): - super().__init__('blt', arguments) if signed else super().__init__('bltu', arguments) + def __init__(self, *arguments): + super().__init__('blt', *arguments) + + +class BltuInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('bltu', *arguments) class JInstruction(Instruction): - def __init__(self, arguments): - super().__init__('j', arguments) + def __init__(self, *arguments): + super().__init__('j', *arguments) class JrInstruction(Instruction): - def __init__(self, arguments): - super().__init__('jr', arguments) + def __init__(self, *arguments): + super().__init__('jr', *arguments) class JalInstruction(Instruction): - def __init__(self, arguments): - super().__init__('jal', arguments) + def __init__(self, *arguments): + super().__init__('jal', *arguments) class JalrInstruction(Instruction): - def __init__(self, arguments): - super().__init__('jalr', arguments) + def __init__(self, *arguments): + super().__init__('jalr', *arguments) # ================== # Exception Handling # ================== diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 827629c6..ab076eb7 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -17,13 +17,13 @@ def program_to_mips_visitor(program: cil.ProgramNode): for m in t.methods: __METHOD_MAPPING__[(t, m)] = t.methods[m] - data_section = [mips.AsciizInst(d.val) for d in program.data] + data = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) + for d in program.data] + data_section = mips.MIPSDataSection(data) # continue - text_section = [] - - for function in program.built_in_code + program.code: - text_section += function_to_mips_visitor(function) - + functions = [function_to_mips_visitor( + f) for f in program.built_in_code + program.code] + text_section = mips.MIPSTextSection(functions) return mips.MIPSProgram(data_section, text_section) @@ -55,7 +55,7 @@ def function_to_mips_visitor(function): code += restore_callee_registers() code += restore_stack(len(function.locals)*4) code.append(mips.JrInstruction('$ra')) - return code + return mips.MIPSFunction(function.name, code) def instruction_to_mips_visitor(inst): @@ -63,9 +63,10 @@ def instruction_to_mips_visitor(inst): Resolves visitor for each type ''' try: - return __visitors__[type(inst)] + return __visitors__[type(inst)](inst) except KeyError: - raise Exception(f'There is no visitor for {type(inst)}') + print(f'There is no visitor for {type(inst)}') + return [] def vcall_to_mips_visitor(vcall: cil.VCAllNode): @@ -76,7 +77,7 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): 3) Restore caller registers\n 4) Takes the result from v0 ''' - return save_caller_registers() + [mips.JalInstruction([__METHOD_MAPPING__[(vcall.type, vcall.method)]])] + restore_caller_registers() + [mips.MoveInstruction(['$v0', __ADDRS__[vcall.result]])] + return save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.MoveInstruction('$v0', __ADDRS__[vcall.result])] def arg_to_mips_visitor(arg: cil.ArgNode): @@ -98,14 +99,14 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): syscall sw $v0, [addr(x)] """ - size = allocate.type.size_mips + size = get_type(allocate.type).size_mips address = __ADDRS__[allocate.result] code = [ mips.Comment(str(allocate)), - mips.LiInstruction(('$a0', size)), - mips.LiInstruction(('$v0', 9)), + mips.LiInstruction('$a0', size), + mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction(('$v0', address)) + mips.SwInstruction('$v0', address) ] return code @@ -122,8 +123,8 @@ def copy_to_mips_visitor(copy: cil.CopyNode): y_addr = __ADDRS__[copy.val] return [ mips.Comment(str(copy)), - mips.LwInstruction(('$t0', y_addr)), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t0', y_addr), + mips.SwInstruction('$t0', x_addr) ] @@ -142,9 +143,9 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), - mips.LwInstruction(('$t0', y_addr)), - mips.LwInstruction(('$t1', f'{attr_shift}($t0)')), - mips.SwInstruction(('$t1', x_addr)) + mips.LwInstruction('$t0', y_addr), + mips.LwInstruction('$t1', f'{attr_shift}($t0)'), + mips.SwInstruction('$t1', x_addr) ] @@ -162,9 +163,9 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): attr_shift = (setattr.attr_index + 1) * 4 return [ mips.Comment(str(setattr)), - mips.LwInstruction(('$t0', x_addr)), - mips.LwInstruction(('$t1', y_addr)), - mips.SwInstruction(('$t0', f'{attr_shift}($t0)')) + mips.LwInstruction('$t0', x_addr), + mips.LwInstruction('$t1', y_addr), + mips.SwInstruction('$t0', f'{attr_shift}($t0)') ] @@ -184,10 +185,10 @@ def plus_to_mips_visitor(plus: cil.PlusNode): z_addr = __ADDRS__[plus.right] return [ mips.Comment(str(plus)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.AddInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.AddInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -206,10 +207,10 @@ def minus_to_mips_visitor(minus: cil.MinusNode): z_addr = __ADDRS__[minus.right] return [ mips.Comment(str(minus)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.SubInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.SubInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -228,10 +229,10 @@ def star_to_mips_visitor(star: cil.StarNode): z_addr = __ADDRS__[star.right] return [ mips.Comment(str(star)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.MultInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.MultInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -250,10 +251,10 @@ def div_to_mips_visitor(div: cil.DivNode): z_addr = __ADDRS__[div.right] return [ mips.Comment(str(div)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.DivInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.DivInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -273,10 +274,10 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): z_addr = __ADDRS__[lesseq.right] return [ mips.Comment(str(lesseq)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.SleInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.SleInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -296,10 +297,10 @@ def less_to_mips_visitor(less: cil.LessNode): z_addr = __ADDRS__[less.right] return [ mips.Comment(str(less)), - mips.LwInstruction(('$t1', y_addr)), - mips.LwInstruction(('$t2', z_addr)), - mips.SleInstruction(('$t0', '$t1', '$t2')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.SleInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', x_addr) ] @@ -316,9 +317,9 @@ def not_to_mips_visitor(notn: cil.NotNode): y_addr = __ADDRS__[notn.value] return [ mips.Comment(str(notn)), - mips.LwInstruction(('$t1', y_addr)), - mips.NotInstruction(('$t0', '$t1')), - mips.SwInstruction(('$t0', x_addr)) + mips.LwInstruction('$t1', y_addr), + mips.NotInstruction('$t0', '$t1'), + mips.SwInstruction('$t0', x_addr) ] diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 1b9bed02..3fcf8000 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -1,6 +1,9 @@ from code_generation.MIPS import ast as mips +__TYPES__ = {} + + def init_types(types): """ Objects in MIPS code are memory space (size_mips), therefore we need to know the type @@ -14,40 +17,48 @@ def init_types(types): t.attr_index_mips = {} for i, a in enumerate(t.attributes): t.attr_index_mips[a] = i + 1 + __TYPES__[t.type] = t + + +def get_type(name): + try: + return __TYPES__[name] + except KeyError: + return None def save_callee_registers(): - code=allocate_stack(40) + code = allocate_stack(40) for i in range(8): - code+=push_stack(f'$s{i}', (7-i)*4) - code+=push_stack('$fp', 4) - code+=push_stack('$ra') - return code - + code += push_stack(f'$s{i}', (7-i)*4) + code += push_stack('$fp', 4) + code += push_stack('$ra') + return code + def save_caller_registers(): - code=allocate_stack(40) + code = allocate_stack(40) for i in range(10): - code+=push_stack(f'$t{i}', (9-i)*4) - + code += push_stack(f'$t{i}', (9-i)*4) + return code def restore_callee_registers(): - code=[] + code = [] for i in range(8): - code+=peek_stack(f'$s{i}', (7-i)*4) - code+=peek_stack('$fp', 4) - code+=peek_stack('$ra') - code+=restore_stack(40) + code += peek_stack(f'$s{i}', (7-i)*4) + code += peek_stack('$fp', 4) + code += peek_stack('$ra') + code += restore_stack(40) return code def restore_caller_registers(): - code=[] + code = [] for i in range(10): - code+=peek_stack(f'$t{i}', (9-i)*4) - code+=restore_stack(40) + code += peek_stack(f'$t{i}', (9-i)*4) + code += restore_stack(40) return code @@ -60,9 +71,9 @@ def allocate_stack(bytes): def push_stack(src, pos=0): - code=[] - if src[0]!='$': - code=[peek_stack('$t0', src)] + code = [] + if src[0] != '$': + code = [peek_stack('$t0', src)] if pos: return code+[mips.SwInstruction('$t0', f'{pos}($sp)')] return code+[mips.SwInstruction('$t0', '($sp)')] @@ -70,7 +81,6 @@ def push_stack(src, pos=0): if pos: return code+[mips.SwInstruction(src, f'{pos}($sp)')] return code+[mips.SwInstruction(src, '($sp)')] - def peek_stack(src, pos=0): diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py index d6282297..51be3df8 100644 --- a/src/code_generation/code_gen.py +++ b/src/code_generation/code_gen.py @@ -1,6 +1,8 @@ from .CIL.cil import ast_to_cil +from .MIPS.mips import program_to_mips_visitor def generate_code(ast): cil_ast = ast_to_cil(ast) - return str(cil_ast) + mips_program = program_to_mips_visitor(cil_ast) + return str(mips_program) diff --git a/src/main.py b/src/main.py index 7e20b04e..a6974aa3 100644 --- a/src/main.py +++ b/src/main.py @@ -46,7 +46,7 @@ def main(): exit(1) cil_code = generate_code(ast) - output_file = input_file[0:-2] + 'cil' + output_file = input_file[0:-2] + 'mips' with open(output_file, "w") as output: output.write(cil_code) From 3e61f1a9b7faab8adc2c3fb7753ffb751e1b3502 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 1 Jun 2020 18:59:33 -0400 Subject: [PATCH 291/435] Update .gitignore - Add MIPS files to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d231c54d..b63045ff 100644 --- a/.gitignore +++ b/.gitignore @@ -411,3 +411,4 @@ dmypy.json .idea .vscode *.cil +*.mips From 38699da64823323fd78f8e57ef2798e555bc580c Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 2 Jun 2020 13:33:22 -0400 Subject: [PATCH 292/435] adding comments --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 46cc88ce..178f7bd5 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -77,7 +77,7 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): 3) Restore caller registers\n 4) Takes the result from v0 ''' - return save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.MoveInstruction('$v0', __ADDRS__[vcall.result])] + return [mips.Comment(str(vcall))]+save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.MoveInstruction('$v0', __ADDRS__[vcall.result])] def arg_to_mips_visitor(arg: cil.ArgNode): @@ -86,7 +86,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - return [mips.Comment('ARG [arg] ;')] + allocate_stack(4) + push_stack(__ADDRS__[arg.val]) + return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(__ADDRS__[arg.val]) def allocate_to_mips_visitor(allocate: cil.AllocateNode): From b98e1a8cfd6f95dc03463fd5c1e0f190be0b85aa Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 2 Jun 2020 13:54:59 -0400 Subject: [PATCH 293/435] adding print visitor --- src/code_generation/CIL/cil.py | 8 +++----- src/code_generation/MIPS/mips.py | 23 ++++++++++++++++++++--- src/lexer_parser/parsetab.py | 5 ++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 40b5571f..24108a6d 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -139,7 +139,7 @@ def out_string_to_cil(): def out_int_to_cil(): - return cil.FuncNode('IO_out_int', [cil.ParamNode('self'), cil.ParamNode('int')], [cil.LocalNode('str')], [cil.StrNode('int', 'str'), cil.PrintNode('int'), cil.ReturnNode('self')]) + return cil.FuncNode('IO_out_int', [cil.ParamNode('self'), cil.ParamNode('int')], [], [cil.PrintNode('int'), cil.ReturnNode('self')]) def in_string_to_cil(): @@ -151,7 +151,7 @@ def in_int_to_cil(): def type_name_to_cil(): - return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.StrNode('type', 'str'), cil.ReturnNode('str')]) + return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.ReturnNode('type')]) def copy_to_cil(): @@ -224,8 +224,6 @@ def case_to_cil_visitor(case): body += expr_cil.body t = add_local() body.append(cil.TypeOfNode(t, expr_cil.value)) - str_t = add_local() - body.append(cil.StrNode(t, str_t)) types = [] labels = [] for c in case.case_list: @@ -238,7 +236,7 @@ def case_to_cil_visitor(case): for i, branch in enumerate(case.case_list): predicate = add_local() - body.append(cil.MinusNode(str_t, branch.type, predicate)) + body.append(cil.MinusNode(t, branch.type, predicate)) body.append(cil.ConditionalGotoNode(predicate, labels[i])) val = add_local(branch.id) body.append(cil.AssignNode(val, expr_cil.value)) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 178f7bd5..155b8b7b 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -14,8 +14,9 @@ def program_to_mips_visitor(program: cil.ProgramNode): # filling method mapping for t in program.types: + print(t) for m in t.methods: - __METHOD_MAPPING__[(t, m)] = t.methods[m] + __METHOD_MAPPING__[(t.type, m)] = t.methods[m] data = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) for d in program.data] @@ -67,8 +68,23 @@ def instruction_to_mips_visitor(inst): except KeyError: print(f'There is no visitor for {type(inst)}') return [] - - + + +def print_to_mips_visitor(p:cil.PrintNode): + code = [ mips.Comment(str(p)), mips.MoveInstruction('$a0', __ADDRS__[p.str])] + if p.str=='int': + code+=[ + mips.LiInstruction('$v0', 1), + mips.SyscallInstruction(), + ] + elif p.str=='str': + code+=[ + mips.LiInstruction('$v0', 4), + mips.SyscallInstruction(), + ] + + return code + def vcall_to_mips_visitor(vcall: cil.VCAllNode): ''' Converts an VCall CIL node to a piece of MIPS code:\n @@ -337,4 +353,5 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.LessEqNode: lesseq_to_mips_visitor, cil.LessNode: less_to_mips_visitor, cil.NotNode: not_to_mips_visitor, + cil.PrintNode: print_to_mips_visitor } diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 99fc4683..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From b50aca21f3bfe0ed523f77207f160ed63e372947 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 2 Jun 2020 16:39:00 -0400 Subject: [PATCH 294/435] adding read and read int mips visitors --- src/code_generation/CIL/cil.py | 21 ++++++--- src/code_generation/MIPS/ast.py | 9 +++- src/code_generation/MIPS/mips.py | 61 +++++++++++++++++++++------ src/code_generation/MIPS/utilities.py | 13 ++++++ 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 24108a6d..aa564048 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -143,31 +143,38 @@ def out_int_to_cil(): def in_string_to_cil(): - return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [cil.LocalNode('str')], [cil.ReadNode('str'), cil.ReturnNode('str')]) + str=cil.LocalNode('str') + return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [str], [cil.ReadNode(str), cil.ReturnNode(str)]) def in_int_to_cil(): - return cil.FuncNode('IO_in_int', [cil.ParamNode('self')], [cil.LocalNode('int')], [cil.ReadIntNode('int'), cil.ReturnNode('int')]) + i=cil.LocalNode('int') + return cil.FuncNode('IO_in_int', [cil.ParamNode('self')], [i], [cil.ReadIntNode(i), cil.ReturnNode(i)]) def type_name_to_cil(): - return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [cil.LocalNode('type'), cil.LocalNode('str')], [cil.TypeOfNode('type', 'self'), cil.ReturnNode('type')]) + t=cil.LocalNode('type') + return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [t], [cil.TypeOfNode(t, 'self'), cil.ReturnNode(t)]) def copy_to_cil(): - return cil.FuncNode('Object_copy', [cil.ParamNode('self')], [cil.LocalNode('copy')], [cil.CopyNode('self', 'copy'), cil.ReturnNode('copy')]) + copy=cil.LocalNode('copy') + return cil.FuncNode('Object_copy', [cil.ParamNode('self')], [copy], [cil.CopyNode('self', copy), cil.ReturnNode(copy)]) def length_to_cil(): - return cil.FuncNode('length_String', [cil.ParamNode('self')], [cil.LocalNode('result')], [cil.LengthNode('self', 'result'), cil.ReturnNode('result')]) + result=cil.LocalNode('result') + return cil.FuncNode('length_String', [cil.ParamNode('self')], [result], [cil.LengthNode('self', result), cil.ReturnNode(result)]) def concat_to_cil(): - return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [cil.LocalNode('result')], [cil.ConcatNode('self', 'x', 'result'), cil.ReturnNode('result')]) + result=cil.LocalNode('result') + return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [result], [cil.ConcatNode('self', 'x', result), cil.ReturnNode(result)]) def substring_to_cil(): - return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'), cil.ParamNode('l')], [cil.LocalNode('result')], [cil.SubStringNode('self', 'i', 'l', 'result'), cil.ReturnNode('result')]) + result=cil.LocalNode('result') + return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'), cil.ParamNode('l')], [result], [cil.SubStringNode('self', 'i', 'l', result), cil.ReturnNode(result)]) def func_to_cil_visitor(type_name, func): diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 9b850374..eeea145e 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -72,6 +72,10 @@ def __init__(self, text): class AsciizInst(Instruction): def __init__(self, *arguments): super().__init__(".asciiz", *arguments) + +class SpaceInst(Instruction): + def __init__(self, *arguments): + super().__init__(".space", *arguments) # ============================= @@ -96,7 +100,10 @@ def __init__(self, *arguments): class LiInstruction(Instruction): def __init__(self, *arguments): super().__init__('li', *arguments) - + +class LaInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('la', *arguments) # ======================= # Arithmetic Instructions diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 155b8b7b..0036c909 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -4,10 +4,13 @@ __METHOD_MAPPING__ = {} __ADDRS__ = {} +__BUFFSIZE__= 1024 +__DATA__= [] + def program_to_mips_visitor(program: cil.ProgramNode): - global __METHOD_MAPPING__ + global __METHOD_MAPPING__, __DATA__ # Initialize Types Codes init_types(program.types) @@ -18,13 +21,13 @@ def program_to_mips_visitor(program: cil.ProgramNode): for m in t.methods: __METHOD_MAPPING__[(t.type, m)] = t.methods[m] - data = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) + __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) for d in program.data] - data_section = mips.MIPSDataSection(data) - # continue + functions = [function_to_mips_visitor( f) for f in program.built_in_code + program.code] text_section = mips.MIPSTextSection(functions) + data_section = mips.MIPSDataSection(__DATA__) return mips.MIPSProgram(data_section, text_section) @@ -71,19 +74,48 @@ def instruction_to_mips_visitor(inst): def print_to_mips_visitor(p:cil.PrintNode): - code = [ mips.Comment(str(p)), mips.MoveInstruction('$a0', __ADDRS__[p.str])] + code = [ mips.Comment(str(p)), mips.MoveInstruction('$a0', __ADDRS__[p.str]) ] if p.str=='int': - code+=[ - mips.LiInstruction('$v0', 1), - mips.SyscallInstruction(), + code += [ + mips.LiInstruction('$v0', 1), + mips.SyscallInstruction(), ] elif p.str=='str': - code+=[ - mips.LiInstruction('$v0', 4), - mips.SyscallInstruction(), + code += [ + mips.LiInstruction('$v0', 4), + mips.SyscallInstruction(), ] return code + +def return_to_mips_visitor(ret:cil.ReturnNode): + val, is_integer=get_address(__ADDRS__, ret.ret_value) + code=[mips.Comment(str(ret))] + if is_integer: + code.append(mips.LiInstruction('$v0', val)) + else: + code.append(mips.LwInstruction('$v0', val)) + return code + +def read_to_mips_visitor(read:cil.ReadNode): + __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) + code = [ + mips.Comment(str(read)), + mips.LaInstruction('$a0', read.result), + mips.LiInstruction('$a1', __BUFFSIZE__), + mips.LiInstruction('$v0', 8), + mips.SyscallInstruction() + ] + return code + +def read_int_to_mips_visitor(read:cil.ReadIntNode): + code = [ + mips.Comment(str(read)), + mips.LiInstruction('$v0', 5), + mips.SyscallInstruction() + ] + return code + def vcall_to_mips_visitor(vcall: cil.VCAllNode): ''' @@ -93,7 +125,7 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): 3) Restore caller registers\n 4) Takes the result from v0 ''' - return [mips.Comment(str(vcall))]+save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.MoveInstruction('$v0', __ADDRS__[vcall.result])] + return [mips.Comment(str(vcall))]+save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.SwInstruction('$v0', __ADDRS__[vcall.result])] def arg_to_mips_visitor(arg: cil.ArgNode): @@ -353,5 +385,8 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.LessEqNode: lesseq_to_mips_visitor, cil.LessNode: less_to_mips_visitor, cil.NotNode: not_to_mips_visitor, - cil.PrintNode: print_to_mips_visitor + cil.PrintNode: print_to_mips_visitor, + cil.ReturnNode: return_to_mips_visitor, + cil.ReadNode: read_to_mips_visitor, + cil.ReadIntNode: read_int_to_mips_visitor } diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 3fcf8000..c4f7990a 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -87,3 +87,16 @@ def peek_stack(src, pos=0): if pos: return [mips.LwInstruction(src, f'{pos}($sp)')] return [mips.LwInstruction(src, '($sp)')] + + +def get_address(dict, key): + if type(key) is int: + return key, True + try: + if type(key) is str: + return dict[key], False + return dict[key.id], False + except: + raise Exception('Local not found in stack') + + From 7470be17e48b25b23c863d663079ce112c23e5d8 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 14:15:07 -0400 Subject: [PATCH 295/435] adding mips label --- src/code_generation/MIPS/ast.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index eeea145e..84f9c948 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -25,6 +25,12 @@ def __str__(self): data_text = '\n'.join([str(d) for d in self.data]) return f'\n.data\n{data_text}\n' +class MIPSLabel: + def __init__(self, name): + self.name=name + + def __str__(self): + return f'{self.name}:\n' class MIPSFunction: def __init__(self, name, instructions): @@ -105,6 +111,10 @@ class LaInstruction(Instruction): def __init__(self, *arguments): super().__init__('la', *arguments) +class LbInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('lb', *arguments) + # ======================= # Arithmetic Instructions # ======================= @@ -330,6 +340,10 @@ def __init__(self, *arguments): class BltuInstruction(Instruction): def __init__(self, *arguments): super().__init__('bltu', *arguments) + +class BeqzInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('beqz', *arguments) class JInstruction(Instruction): From c349ae1b906167f761d286d237a11a182afcf052 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 14:16:19 -0400 Subject: [PATCH 296/435] Removing print --- src/code_generation/MIPS/mips.py | 68 ++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 0036c909..1d125b48 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -17,7 +17,6 @@ def program_to_mips_visitor(program: cil.ProgramNode): # filling method mapping for t in program.types: - print(t) for m in t.methods: __METHOD_MAPPING__[(t.type, m)] = t.methods[m] @@ -43,6 +42,7 @@ def function_to_mips_visitor(function): 7) Restores local's stack space\n 8) Jumps to the next instruction which address is in ra register\n ''' + for i, param in enumerate(function.params): __ADDRS__[param.id] = f'{(len(function.params)-1-i)*4}($sp)' @@ -70,7 +70,8 @@ def instruction_to_mips_visitor(inst): return __visitors__[type(inst)](inst) except KeyError: print(f'There is no visitor for {type(inst)}') - return [] + return [] + def print_to_mips_visitor(p:cil.PrintNode): @@ -116,6 +117,48 @@ def read_int_to_mips_visitor(read:cil.ReadIntNode): ] return code +def length_to_mips_visitor(length:cil.LengthNode): + val, _= get_address(__ADDRS__, length.str) + result_val, _=get_address(__ADDRS__, length.result) + + code = [ + mips.Comment(str(length)), + mips.LbInstruction('$t0', val), + mips.LiInstruction('$t1', 0), + mips.MIPSLabel('length_loop'), + mips.BeqzInstruction('$t0', 'end_length_loop'), + mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('length_loop'), + mips.MIPSLabel('end_length_loop'), + mips.SwInstruction('$t1', result_val) + ] + return code + +def concat_to_mips_visitor(concat:cil.ConcatNode): + __DATA__.append(mips.MIPSDataItem(concat.result, mips.SpaceInst(2 * __BUFFSIZE__))) + a,_ = get_address(__ADDRS__, concat.str_a) + b,_ = get_address(__ADDRS__, concat.str_b) + + code = [ + mips.Comment(str(concat)), + mips.LwInstruction('$t0', a), + mips.SwInstruction('$t0', concat.result), + mips.LbInstruction('$t1', concat.result), + mips.MIPSLabel('length_loop'), + mips.BeqzInstruction('$t1', 'end_length_loop'), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('length_loop'), + mips.MIPSLabel('end_length_loop'), + mips.LwInstruction('$t2', b), + mips.SwInstruction('$t2', '($t1)') + ] + + return code + +def load_to_mips_visitor(load:cil.LoadNode): + __ADDRS__[load.result]=load.addr + return [] def vcall_to_mips_visitor(vcall: cil.VCAllNode): ''' @@ -125,8 +168,7 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): 3) Restore caller registers\n 4) Takes the result from v0 ''' - return [mips.Comment(str(vcall))]+save_caller_registers() + [mips.JalInstruction(__METHOD_MAPPING__[(vcall.type, vcall.method)])] + restore_caller_registers() + [mips.SwInstruction('$v0', __ADDRS__[vcall.result])] - + pass def arg_to_mips_visitor(arg: cil.ArgNode): ''' @@ -134,7 +176,8 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(__ADDRS__[arg.val]) + addr,_=get_address(__ADDRS__, arg.val) + return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr) def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -148,7 +191,7 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address = __ADDRS__[allocate.result] + address, _ = get_address(__ADDRS__, allocate.result) code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), @@ -167,8 +210,8 @@ def copy_to_mips_visitor(copy: cil.CopyNode): lw $t0, [addr(y)] sw $t0, [addr(x)] """ - x_addr = __ADDRS__[copy.result] - y_addr = __ADDRS__[copy.val] + x_addr, _ = get_address(__ADDRS__, copy.result) + y_addr, _=get_address(__ADDRS__, copy.val) return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), @@ -186,8 +229,8 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr = __ADDRS__[getattr.result] - y_addr = __ADDRS__[getattr.obj] + x_addr, _ = get_address(__ADDRS__,getattr.result) + y_addr, _ = get_address(__ADDRS__,getattr.obj) attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), @@ -388,5 +431,8 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.PrintNode: print_to_mips_visitor, cil.ReturnNode: return_to_mips_visitor, cil.ReadNode: read_to_mips_visitor, - cil.ReadIntNode: read_int_to_mips_visitor + cil.ReadIntNode: read_int_to_mips_visitor, + cil.LengthNode: length_to_mips_visitor, + cil.ConcatNode: concat_to_mips_visitor, + cil.LoadNode:load_to_mips_visitor } From 2fb7004796a81abde213dd37088f03206419091d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 14:18:18 -0400 Subject: [PATCH 297/435] removing wrong vcall visitor --- src/code_generation/MIPS/mips.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 1d125b48..f62c61ef 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -160,16 +160,6 @@ def load_to_mips_visitor(load:cil.LoadNode): __ADDRS__[load.result]=load.addr return [] -def vcall_to_mips_visitor(vcall: cil.VCAllNode): - ''' - Converts an VCall CIL node to a piece of MIPS code:\n - 1) Saves caller registers\n - 2) Jumps to function label and sets the value of ra\n - 3) Restore caller registers\n - 4) Takes the result from v0 - ''' - pass - def arg_to_mips_visitor(arg: cil.ArgNode): ''' Converts an Arg CIL node to a piece of MIPS code:\n @@ -415,7 +405,6 @@ def not_to_mips_visitor(notn: cil.NotNode): __visitors__ = { - cil.VCAllNode: vcall_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, From a3c40ca21209c11dc5aa37cfeccbc53cc6e97760 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 14:25:41 -0400 Subject: [PATCH 298/435] Add size_vt property to types --- src/code_generation/MIPS/utilities.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index c4f7990a..62602349 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -14,6 +14,7 @@ def init_types(types): for i, t in enumerate(types): t.code_mips = i t.size_mips = (len(t.attributes) + 1) * 4 + t.size_vt = (len(t.methods) + 1) * 4 t.attr_index_mips = {} for i, a in enumerate(t.attributes): t.attr_index_mips[a] = i + 1 @@ -98,5 +99,3 @@ def get_address(dict, key): return dict[key.id], False except: raise Exception('Local not found in stack') - - From e6fbc8513697b526cb5df7286ad340fb71fc8543 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 14:26:11 -0400 Subject: [PATCH 299/435] Recalculate parsetab.py --- src/lexer_parser/parsetab.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 9f87869e..99fc4683 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 53f58d65e017d5567fdc342413f2be852fc2120a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 14:58:34 -0400 Subject: [PATCH 300/435] Reformat code --- src/code_generation/MIPS/mips.py | 140 ++++++++++++++++--------------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f62c61ef..f77b46cc 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -4,9 +4,8 @@ __METHOD_MAPPING__ = {} __ADDRS__ = {} -__BUFFSIZE__= 1024 -__DATA__= [] - +__BUFFSIZE__ = 1024 +__DATA__ = [] def program_to_mips_visitor(program: cil.ProgramNode): @@ -21,8 +20,8 @@ def program_to_mips_visitor(program: cil.ProgramNode): __METHOD_MAPPING__[(t.type, m)] = t.methods[m] __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) - for d in program.data] - + for d in program.data] + functions = [function_to_mips_visitor( f) for f in program.built_in_code + program.code] text_section = mips.MIPSTextSection(functions) @@ -42,7 +41,7 @@ def function_to_mips_visitor(function): 7) Restores local's stack space\n 8) Jumps to the next instruction which address is in ra register\n ''' - + for i, param in enumerate(function.params): __ADDRS__[param.id] = f'{(len(function.params)-1-i)*4}($sp)' @@ -71,102 +70,111 @@ def instruction_to_mips_visitor(inst): except KeyError: print(f'There is no visitor for {type(inst)}') return [] - - - -def print_to_mips_visitor(p:cil.PrintNode): - code = [ mips.Comment(str(p)), mips.MoveInstruction('$a0', __ADDRS__[p.str]) ] - if p.str=='int': + + +def print_to_mips_visitor(p: cil.PrintNode): + code = [mips.Comment(str(p)), mips.MoveInstruction( + '$a0', __ADDRS__[p.str])] + if p.str == 'int': code += [ mips.LiInstruction('$v0', 1), mips.SyscallInstruction(), - ] - elif p.str=='str': + ] + elif p.str == 'str': code += [ mips.LiInstruction('$v0', 4), - mips.SyscallInstruction(), + mips.SyscallInstruction(), ] - + return code -def return_to_mips_visitor(ret:cil.ReturnNode): - val, is_integer=get_address(__ADDRS__, ret.ret_value) - code=[mips.Comment(str(ret))] + +def return_to_mips_visitor(ret: cil.ReturnNode): + val, is_integer = get_address(__ADDRS__, ret.ret_value) + code = [mips.Comment(str(ret))] if is_integer: code.append(mips.LiInstruction('$v0', val)) else: - code.append(mips.LwInstruction('$v0', val)) + code.append(mips.LwInstruction('$v0', val)) return code -def read_to_mips_visitor(read:cil.ReadNode): - __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) - code = [ - mips.Comment(str(read)), - mips.LaInstruction('$a0', read.result), - mips.LiInstruction('$a1', __BUFFSIZE__), - mips.LiInstruction('$v0', 8), - mips.SyscallInstruction() + +def read_to_mips_visitor(read: cil.ReadNode): + __DATA__.append(mips.MIPSDataItem( + read.result, mips.SpaceInst(__BUFFSIZE__))) + code = [ + mips.Comment(str(read)), + mips.LaInstruction('$a0', read.result), + mips.LiInstruction('$a1', __BUFFSIZE__), + mips.LiInstruction('$v0', 8), + mips.SyscallInstruction() ] return code -def read_int_to_mips_visitor(read:cil.ReadIntNode): - code = [ - mips.Comment(str(read)), - mips.LiInstruction('$v0', 5), - mips.SyscallInstruction() + +def read_int_to_mips_visitor(read: cil.ReadIntNode): + code = [ + mips.Comment(str(read)), + mips.LiInstruction('$v0', 5), + mips.SyscallInstruction() ] return code -def length_to_mips_visitor(length:cil.LengthNode): - val, _= get_address(__ADDRS__, length.str) - result_val, _=get_address(__ADDRS__, length.result) - + +def length_to_mips_visitor(length: cil.LengthNode): + val, _ = get_address(__ADDRS__, length.str) + result_val, _ = get_address(__ADDRS__, length.result) + code = [ mips.Comment(str(length)), mips.LbInstruction('$t0', val), mips.LiInstruction('$t1', 0), mips.MIPSLabel('length_loop'), mips.BeqzInstruction('$t0', 'end_length_loop'), - mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t0', '$t0', 1), mips.AdduInstruction('$t1', '$t1', 1), - mips.BInstruction('length_loop'), - mips.MIPSLabel('end_length_loop'), + mips.BInstruction('length_loop'), + mips.MIPSLabel('end_length_loop'), mips.SwInstruction('$t1', result_val) - ] + ] return code -def concat_to_mips_visitor(concat:cil.ConcatNode): - __DATA__.append(mips.MIPSDataItem(concat.result, mips.SpaceInst(2 * __BUFFSIZE__))) - a,_ = get_address(__ADDRS__, concat.str_a) - b,_ = get_address(__ADDRS__, concat.str_b) - + +def concat_to_mips_visitor(concat: cil.ConcatNode): + __DATA__.append(mips.MIPSDataItem( + concat.result, mips.SpaceInst(2 * __BUFFSIZE__))) + a, _ = get_address(__ADDRS__, concat.str_a) + b, _ = get_address(__ADDRS__, concat.str_b) + code = [ mips.Comment(str(concat)), mips.LwInstruction('$t0', a), - mips.SwInstruction('$t0', concat.result), + mips.SwInstruction('$t0', concat.result), mips.LbInstruction('$t1', concat.result), mips.MIPSLabel('length_loop'), mips.BeqzInstruction('$t1', 'end_length_loop'), - mips.AdduInstruction('$t1', '$t1', 1), - mips.BInstruction('length_loop'), - mips.MIPSLabel('end_length_loop'), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('length_loop'), + mips.MIPSLabel('end_length_loop'), mips.LwInstruction('$t2', b), - mips.SwInstruction('$t2', '($t1)') + mips.SwInstruction('$t2', '($t1)') ] - + return code - -def load_to_mips_visitor(load:cil.LoadNode): - __ADDRS__[load.result]=load.addr + + +def load_to_mips_visitor(load: cil.LoadNode): + __ADDRS__[load.result] = load.addr return [] - + + def arg_to_mips_visitor(arg: cil.ArgNode): ''' Converts an Arg CIL node to a piece of MIPS code:\n 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr,_=get_address(__ADDRS__, arg.val) + addr, _ = get_address(__ADDRS__, arg.val) return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr) @@ -201,7 +209,7 @@ def copy_to_mips_visitor(copy: cil.CopyNode): sw $t0, [addr(x)] """ x_addr, _ = get_address(__ADDRS__, copy.result) - y_addr, _=get_address(__ADDRS__, copy.val) + y_addr, _ = get_address(__ADDRS__, copy.val) return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), @@ -219,8 +227,8 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr, _ = get_address(__ADDRS__,getattr.result) - y_addr, _ = get_address(__ADDRS__,getattr.obj) + x_addr, _ = get_address(__ADDRS__, getattr.result) + y_addr, _ = get_address(__ADDRS__, getattr.obj) attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), @@ -417,11 +425,11 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.LessEqNode: lesseq_to_mips_visitor, cil.LessNode: less_to_mips_visitor, cil.NotNode: not_to_mips_visitor, - cil.PrintNode: print_to_mips_visitor, + cil.PrintNode: print_to_mips_visitor, cil.ReturnNode: return_to_mips_visitor, - cil.ReadNode: read_to_mips_visitor, - cil.ReadIntNode: read_int_to_mips_visitor, - cil.LengthNode: length_to_mips_visitor, - cil.ConcatNode: concat_to_mips_visitor, - cil.LoadNode:load_to_mips_visitor + cil.ReadNode: read_to_mips_visitor, + cil.ReadIntNode: read_int_to_mips_visitor, + cil.LengthNode: length_to_mips_visitor, + cil.ConcatNode: concat_to_mips_visitor, + cil.LoadNode: load_to_mips_visitor } From 506a3ca15c0ed8110444efc135ee0035e54c6ca2 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 15:22:09 -0400 Subject: [PATCH 301/435] Fix print format --- src/code_generation/MIPS/ast.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 84f9c948..0a84b1ee 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -22,7 +22,7 @@ def __init__(self, data): self.data = data def __str__(self): - data_text = '\n'.join([str(d) for d in self.data]) + data_text = '\n'.join([f'\t{str(d)}' for d in self.data]) return f'\n.data\n{data_text}\n' class MIPSLabel: @@ -38,7 +38,7 @@ def __init__(self, name, instructions): self.instructions = instructions def __str__(self): - return '\n'.join([f'# FUNCTION: {self.name}']+[str(i) for i in self.instructions]) + return '\n'.join([f'# FUNCTION: {self.name}']+[f'\t{str(i)}' for i in self.instructions]) class MIPSDataItem: @@ -47,7 +47,7 @@ def __init__(self, label, instruction): self.instruction = instruction def __str__(self): - return f'{self.label}: {str(self.instruction)}' + return f'{self.label}:\n\t\t{str(self.instruction)}' class Instruction: @@ -57,13 +57,13 @@ def __init__(self, name, *arguments): def __str__(self): if len(self.arguments) == 0: - return f"\t{self.name}" + return f"{self.name}" elif len(self.arguments) == 3: - return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" + return f"{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}, {self.arguments[2]}" elif len(self.arguments) == 2: - return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}" + return f"{'{:10}'.format(self.name)} {self.arguments[0]}, {self.arguments[1]}" elif len(self.arguments) == 1: - return f"\t{'{:10}'.format(self.name)} {self.arguments[0]}" + return f"{'{:10}'.format(self.name)} {self.arguments[0]}" class Comment(Instruction): From 8a89507f742f17e3ec4e4df97ce4ce5586a8fdb9 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 15:22:25 -0400 Subject: [PATCH 302/435] Add virtual table space in .data section --- src/code_generation/MIPS/mips.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f77b46cc..5c555a26 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -13,6 +13,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): # Initialize Types Codes init_types(program.types) + vt_code = build_virtual_tables(program) # filling method mapping for t in program.types: @@ -25,10 +26,15 @@ def program_to_mips_visitor(program: cil.ProgramNode): functions = [function_to_mips_visitor( f) for f in program.built_in_code + program.code] text_section = mips.MIPSTextSection(functions) - data_section = mips.MIPSDataSection(__DATA__) + data_section = mips.MIPSDataSection(vt_code + __DATA__) return mips.MIPSProgram(data_section, text_section) +def build_virtual_tables(program: cil.ProgramNode): + code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst(t.size_vt)) for t in program.types] + return code + + def function_to_mips_visitor(function): ''' Converts a function CIL to a piece of MIPS code:\n From a040a290a821d22cd488445e3fb0af9b6e3b2030 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 16:18:01 -0400 Subject: [PATCH 303/435] adding substring mips visitor --- src/code_generation/MIPS/ast.py | 5 ++++ src/code_generation/MIPS/mips.py | 39 ++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 84f9c948..879004dd 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -114,6 +114,11 @@ def __init__(self, *arguments): class LbInstruction(Instruction): def __init__(self, *arguments): super().__init__('lb', *arguments) + + +class SbInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('sb', *arguments) # ======================= # Arithmetic Instructions diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f62c61ef..595f3e80 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -99,7 +99,8 @@ def return_to_mips_visitor(ret:cil.ReturnNode): return code def read_to_mips_visitor(read:cil.ReadNode): - __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) + __DATA__.append(mips.MIPSDataItem(read.result.id, mips.SpaceInst(__BUFFSIZE__))) + __ADDRS__[read.result.id]=read.result.id code = [ mips.Comment(str(read)), mips.LaInstruction('$a0', read.result), @@ -109,11 +110,39 @@ def read_to_mips_visitor(read:cil.ReadNode): ] return code + +def substring_to_mips_visitor(ss:cil.SubStringNode): + addr, _=get_address(__ADDRS__, ss.str) + i, _=get_address(__ADDRS__, ss.i) + l, _=get_address(__ADDRS__, ss.len) + __DATA__.append(mips.MIPSDataItem(ss.result.id, mips.SpaceInst(__BUFFSIZE__))) + __ADDRS__[ss.result.id]=ss.result.id + code = [ + mips.Comment(str(ss)), + mips.LaInstruction('$t0', addr), + mips.LaInstruction('$t1', ss.result.id), + mips.LwInstruction('$t4', i), + mips.LwInstruction('$t2', l), + mips.AdduInstruction('$t0', '$t0', '$t4'), + mips.MIPSLabel('substring_loop'), + mips.BeqzInstruction('$t2', 'end_substring_loop'), + mips.LbInstruction('$t3', '($t0)'), + mips.SbInstruction('$t3', '($t1)'), + mips.SubuInstruction('$t2', '$t2', 1), + mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('substring_loop'), + mips.MIPSLabel('end_substring_loop') + ] + return code + def read_int_to_mips_visitor(read:cil.ReadIntNode): + addr,_=get_address(__ADDRS__, read.result) code = [ mips.Comment(str(read)), mips.LiInstruction('$v0', 5), - mips.SyscallInstruction() + mips.SyscallInstruction(), + mips.SwInstruction('$v0', addr) ] return code @@ -136,7 +165,8 @@ def length_to_mips_visitor(length:cil.LengthNode): return code def concat_to_mips_visitor(concat:cil.ConcatNode): - __DATA__.append(mips.MIPSDataItem(concat.result, mips.SpaceInst(2 * __BUFFSIZE__))) + __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) + __ADDRS__[concat.result.id]=concat.result.id a,_ = get_address(__ADDRS__, concat.str_a) b,_ = get_address(__ADDRS__, concat.str_b) @@ -423,5 +453,6 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.ReadIntNode: read_int_to_mips_visitor, cil.LengthNode: length_to_mips_visitor, cil.ConcatNode: concat_to_mips_visitor, - cil.LoadNode:load_to_mips_visitor + cil.LoadNode:load_to_mips_visitor, + cil.SubStringNode:substring_to_mips_visitor } From b3da12f814591ee1474ffca27f600d61a4c03385 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 16:52:37 -0400 Subject: [PATCH 304/435] Add main label to MIPS --- src/code_generation/MIPS/mips.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 5c555a26..15467968 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -23,15 +23,19 @@ def program_to_mips_visitor(program: cil.ProgramNode): __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) for d in program.data] + main_code = function_to_mips_visitor(program.built_in_code[0]) + main_code.instructions.insert(0, mips.MIPSLabel('main')) functions = [function_to_mips_visitor( - f) for f in program.built_in_code + program.code] + f) for f in program.built_in_code[1:] + program.code] + functions.insert(0, main_code) text_section = mips.MIPSTextSection(functions) data_section = mips.MIPSDataSection(vt_code + __DATA__) return mips.MIPSProgram(data_section, text_section) def build_virtual_tables(program: cil.ProgramNode): - code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst(t.size_vt)) for t in program.types] + code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst( + t.size_vt)) for t in program.types] return code From 70c817519cf9f169a9f3d471085ffa25c0ce56b0 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 17:08:14 -0400 Subject: [PATCH 305/435] fix bug --- src/code_generation/MIPS/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 62602349..02430765 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -74,7 +74,7 @@ def allocate_stack(bytes): def push_stack(src, pos=0): code = [] if src[0] != '$': - code = [peek_stack('$t0', src)] + code = peek_stack('$t0', src) if pos: return code+[mips.SwInstruction('$t0', f'{pos}($sp)')] return code+[mips.SwInstruction('$t0', '($sp)')] From 580b07212fa2650d3a91321c9ebd2f40059f5bfe Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 17:12:29 -0400 Subject: [PATCH 306/435] Skip SELF_TYPE in virtual table --- src/code_generation/MIPS/mips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 7e023918..90edda4d 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -35,7 +35,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): def build_virtual_tables(program: cil.ProgramNode): code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst( - t.size_vt)) for t in program.types] + t.size_vt)) for t in program.types[1:]] return code From 77f0ed1788528397978965e4ea53f23b23706f00 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 17:30:00 -0400 Subject: [PATCH 307/435] fix address access --- src/code_generation/MIPS/mips.py | 94 +++++++++++++-------------- src/code_generation/MIPS/utilities.py | 14 ++-- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 8c6b7e0e..336cdd8e 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -3,7 +3,6 @@ from .utilities import * __METHOD_MAPPING__ = {} -__ADDRS__ = {} __BUFFSIZE__ = 1024 __DATA__ = [] @@ -49,13 +48,13 @@ def function_to_mips_visitor(function): ''' for i, param in enumerate(function.params): - __ADDRS__[param.id] = f'{(len(function.params)-1-i)*4}($sp)' + save_address(param.id, f'{(len(function.params)-1-i)*4}($sp)') code = save_callee_registers() code += allocate_stack(len(function.locals)*4) for i, local in enumerate(function.locals): - __ADDRS__[local.id] = f'{(len(function.locals)-1-i)*4}($sp)' + save_address(local.id, f'{(len(function.locals)-1-i)*4}($sp)') for inst in function.body: code += instruction_to_mips_visitor(inst) @@ -79,8 +78,9 @@ def instruction_to_mips_visitor(inst): def print_to_mips_visitor(p: cil.PrintNode): + addr=get_address(p.str) code = [mips.Comment(str(p)), mips.MoveInstruction( - '$a0', __ADDRS__[p.str])] + '$a0',addr)] if p.str == 'int': code += [ mips.LiInstruction('$v0', 1), @@ -96,17 +96,17 @@ def print_to_mips_visitor(p: cil.PrintNode): def return_to_mips_visitor(ret: cil.ReturnNode): - val, is_integer = get_address(__ADDRS__, ret.ret_value) code = [mips.Comment(str(ret))] - if is_integer: - code.append(mips.LiInstruction('$v0', val)) + if type(ret.ret_value) is int: + code.append(mips.LiInstruction('$v0', ret.ret_value)) else: + val = get_address(ret.ret_value) code.append(mips.LwInstruction('$v0', val)) return code def read_to_mips_visitor(read:cil.ReadNode): __DATA__.append(mips.MIPSDataItem(read.result.id, mips.SpaceInst(__BUFFSIZE__))) - __ADDRS__[read.result.id]=read.result.id + save_address(read.result, read.result.id) code = [ mips.Comment(str(read)), mips.LaInstruction('$a0', read.result), @@ -118,11 +118,11 @@ def read_to_mips_visitor(read:cil.ReadNode): def substring_to_mips_visitor(ss:cil.SubStringNode): - addr, _=get_address(__ADDRS__, ss.str) - i, _=get_address(__ADDRS__, ss.i) - l, _=get_address(__ADDRS__, ss.len) + addr=get_address(ss.str) + i=get_address(ss.i) + l=get_address(ss.len) __DATA__.append(mips.MIPSDataItem(ss.result.id, mips.SpaceInst(__BUFFSIZE__))) - __ADDRS__[ss.result.id]=ss.result.id + save_address(ss.result, ss.result.id) code = [ mips.Comment(str(ss)), mips.LaInstruction('$t0', addr), @@ -143,7 +143,7 @@ def substring_to_mips_visitor(ss:cil.SubStringNode): return code def read_int_to_mips_visitor(read:cil.ReadIntNode): - addr,_=get_address(__ADDRS__, read.result) + addr=get_address(read.result) code = [ mips.Comment(str(read)), mips.LiInstruction('$v0', 5), @@ -154,8 +154,8 @@ def read_int_to_mips_visitor(read:cil.ReadIntNode): def length_to_mips_visitor(length: cil.LengthNode): - val, _ = get_address(__ADDRS__, length.str) - result_val, _ = get_address(__ADDRS__, length.result) + val= get_address(length.str) + result_val= get_address(length.result) code = [ mips.Comment(str(length)), @@ -173,9 +173,9 @@ def length_to_mips_visitor(length: cil.LengthNode): def concat_to_mips_visitor(concat:cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) - __ADDRS__[concat.result.id]=concat.result.id - a,_ = get_address(__ADDRS__, concat.str_a) - b,_ = get_address(__ADDRS__, concat.str_b) + save_address(concat.result, concat.result.id) + a = get_address(concat.str_a) + b = get_address(concat.str_b) code = [ mips.Comment(str(concat)), @@ -195,7 +195,7 @@ def concat_to_mips_visitor(concat:cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - __ADDRS__[load.result] = load.addr + save_address(load.result, load.addr) return [] @@ -205,7 +205,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr, _ = get_address(__ADDRS__, arg.val) + addr= get_address(arg.val) return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr) @@ -220,7 +220,7 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address, _ = get_address(__ADDRS__, allocate.result) + address = get_address(allocate.result) code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), @@ -239,8 +239,8 @@ def copy_to_mips_visitor(copy: cil.CopyNode): lw $t0, [addr(y)] sw $t0, [addr(x)] """ - x_addr, _ = get_address(__ADDRS__, copy.result) - y_addr, _ = get_address(__ADDRS__, copy.val) + x_addr = get_address( copy.result) + y_addr = get_address( copy.val) return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), @@ -258,8 +258,8 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr, _ = get_address(__ADDRS__, getattr.result) - y_addr, _ = get_address(__ADDRS__, getattr.obj) + x_addr = get_address( getattr.result) + y_addr = get_address( getattr.obj) attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), @@ -278,8 +278,8 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): lw $t1, [addr(y)] sw $t0, [attr_shift($t0)] """ - x_addr = __ADDRS__[setattr.val] - y_addr = __ADDRS__[setattr.obj] + x_addr = get_address(setattr.val) + y_addr = get_address(setattr.obj) attr_shift = (setattr.attr_index + 1) * 4 return [ mips.Comment(str(setattr)), @@ -300,9 +300,9 @@ def plus_to_mips_visitor(plus: cil.PlusNode): sw $t0, [addr(x)] """ - x_addr = __ADDRS__[plus.result] - y_addr = __ADDRS__[plus.left] - z_addr = __ADDRS__[plus.right] + x_addr = get_address(plus.result) + y_addr = get_address(plus.left) + z_addr = get_address(plus.right) return [ mips.Comment(str(plus)), mips.LwInstruction('$t1', y_addr), @@ -322,9 +322,9 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = __ADDRS__[minus.result] - y_addr = __ADDRS__[minus.left] - z_addr = __ADDRS__[minus.right] + x_addr = get_address(minus.result) + y_addr = get_address(minus.left) + z_addr = get_address(minus.right) return [ mips.Comment(str(minus)), mips.LwInstruction('$t1', y_addr), @@ -344,9 +344,9 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = __ADDRS__[star.result] - y_addr = __ADDRS__[star.left] - z_addr = __ADDRS__[star.right] + x_addr = get_address(star.result) + y_addr = get_address(star.left) + z_addr = get_address(star.right) return [ mips.Comment(str(star)), mips.LwInstruction('$t1', y_addr), @@ -366,9 +366,9 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = __ADDRS__[div.result] - y_addr = __ADDRS__[div.left] - z_addr = __ADDRS__[div.right] + x_addr = get_address(div.result) + y_addr = get_address(div.left) + z_addr = get_address(div.right) return [ mips.Comment(str(div)), mips.LwInstruction('$t1', y_addr), @@ -389,9 +389,9 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): sw $t0, [addr(x)] """ - x_addr = __ADDRS__[lesseq.result] - y_addr = __ADDRS__[lesseq.left] - z_addr = __ADDRS__[lesseq.right] + x_addr = get_address(lesseq.result) + y_addr = get_address(lesseq.left) + z_addr = get_address(lesseq.right) return [ mips.Comment(str(lesseq)), mips.LwInstruction('$t1', y_addr), @@ -412,9 +412,9 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = __ADDRS__[less.result] - y_addr = __ADDRS__[less.left] - z_addr = __ADDRS__[less.right] + x_addr = get_address(less.result) + y_addr = get_address(less.left) + z_addr = get_address(less.right) return [ mips.Comment(str(less)), mips.LwInstruction('$t1', y_addr), @@ -433,8 +433,8 @@ def not_to_mips_visitor(notn: cil.NotNode): not $t0, $t1 sw $t0, [addr(x)] """ - x_addr = __ADDRS__[notn.result] - y_addr = __ADDRS__[notn.value] + x_addr = get_address(notn.result) + y_addr = get_address(notn.value) return [ mips.Comment(str(notn)), mips.LwInstruction('$t1', y_addr), diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 02430765..54a43ff8 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -2,6 +2,7 @@ __TYPES__ = {} +__ADDRS__ = {} def init_types(types): @@ -89,13 +90,16 @@ def peek_stack(src, pos=0): return [mips.LwInstruction(src, f'{pos}($sp)')] return [mips.LwInstruction(src, '($sp)')] +def restore_addresses(): + __ADDRS__ = {} -def get_address(dict, key): - if type(key) is int: - return key, True +def get_address(key): try: if type(key) is str: - return dict[key], False - return dict[key.id], False + return __ADDRS__[key] + return __ADDRS__[key.id] except: raise Exception('Local not found in stack') + +def save_address(key, value): + __ADDRS__[key]=value \ No newline at end of file From bd91c9d9b384408ce4dfa9049de5e27494c66f6b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 17:30:45 -0400 Subject: [PATCH 308/435] updating table --- src/lexer_parser/parsetab.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 99fc4683..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 2ab46f9586565dc31d86ec60137fedc7d89f87ce Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 17:47:11 -0400 Subject: [PATCH 309/435] fixing stack ops --- src/code_generation/MIPS/mips.py | 8 ++-- src/code_generation/MIPS/utilities.py | 59 +++++++++++++++++---------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 336cdd8e..ccb08ae2 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -48,13 +48,15 @@ def function_to_mips_visitor(function): ''' for i, param in enumerate(function.params): - save_address(param.id, f'{(len(function.params)-1-i)*4}($sp)') + pos=(len(function.params)-1-i) + save_address(param.id, pos*4) code = save_callee_registers() code += allocate_stack(len(function.locals)*4) for i, local in enumerate(function.locals): - save_address(local.id, f'{(len(function.locals)-1-i)*4}($sp)') + pos=(len(function.locals)-1-i) + save_address(local.id, pos*4) for inst in function.body: code += instruction_to_mips_visitor(inst) @@ -206,7 +208,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr= get_address(arg.val) - return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr) + return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr, '($sp)') def allocate_to_mips_visitor(allocate: cil.AllocateNode): diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 54a43ff8..0220e610 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -31,8 +31,13 @@ def get_type(name): def save_callee_registers(): code = allocate_stack(40) - for i in range(8): - code += push_stack(f'$s{i}', (7-i)*4) + n=8 + for i in range(n): + pos= (n-1-i)*4 + if pos: + code += push_stack(f'$s{i}', f'{pos}($sp)') + else: + code += push_stack(f'$s{i}', '($sp)') code += push_stack('$fp', 4) code += push_stack('$ra') return code @@ -40,26 +45,38 @@ def save_callee_registers(): def save_caller_registers(): code = allocate_stack(40) - for i in range(10): - code += push_stack(f'$t{i}', (9-i)*4) + n=10 + for i in range(n): + pos =(n-1-i)*4 + if pos: + code += push_stack(f'$t{i}', f'{pos}($sp)') + else: + code += push_stack(f'$t{i}', '($sp)') return code def restore_callee_registers(): code = [] - for i in range(8): - code += peek_stack(f'$s{i}', (7-i)*4) - code += peek_stack('$fp', 4) - code += peek_stack('$ra') + n=8 + for i in range(n): + pos=(n-1-i)*4 + if pos: + code += peek_stack(f'$s{i}', f'{pos}($sp)') + else: + code += peek_stack(f'$s{i}', '($sp)') + code += peek_stack('$fp', '4($sp)') + code += peek_stack('$ra', '($sp)') code += restore_stack(40) return code def restore_caller_registers(): code = [] - for i in range(10): - code += peek_stack(f'$t{i}', (9-i)*4) + n=10 + for i in range(n): + pos=(n-1-i)*4 + code += peek_stack(f'$t{i}', f'{pos}($sp)') code += restore_stack(40) return code @@ -72,23 +89,17 @@ def allocate_stack(bytes): return [mips.SubuInstruction('$sp', '$sp', bytes)] -def push_stack(src, pos=0): +def push_stack(src, pos): code = [] if src[0] != '$': code = peek_stack('$t0', src) - if pos: - return code+[mips.SwInstruction('$t0', f'{pos}($sp)')] - return code+[mips.SwInstruction('$t0', '($sp)')] + return code+[mips.SwInstruction('$t0', pos)] else: - if pos: - return code+[mips.SwInstruction(src, f'{pos}($sp)')] - return code+[mips.SwInstruction(src, '($sp)')] + return code+[mips.SwInstruction(src, pos)] -def peek_stack(src, pos=0): - if pos: - return [mips.LwInstruction(src, f'{pos}($sp)')] - return [mips.LwInstruction(src, '($sp)')] +def peek_stack(src, pos): + return [mips.LwInstruction(src, pos)] def restore_addresses(): __ADDRS__ = {} @@ -102,4 +113,10 @@ def get_address(key): raise Exception('Local not found in stack') def save_address(key, value): + if type(value) is int: + if value: + __ADDRS__[key]=f'{value}($sp)' + else: + __ADDRS__[key]=f'($sp)' + __ADDRS__[key]=value \ No newline at end of file From 7b45131ba1fbc33d1749fa73291d79b78afca06f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 3 Jun 2020 17:56:09 -0400 Subject: [PATCH 310/435] fix bug --- src/code_generation/MIPS/utilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 0220e610..e2bd2031 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -38,8 +38,8 @@ def save_callee_registers(): code += push_stack(f'$s{i}', f'{pos}($sp)') else: code += push_stack(f'$s{i}', '($sp)') - code += push_stack('$fp', 4) - code += push_stack('$ra') + code += push_stack('$fp', f'4($sp)') + code += push_stack('$ra', '($sp)') return code From 5bdb40b496ee7e6e552d8aaf6ff8562cd21c4427 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 3 Jun 2020 18:14:32 -0400 Subject: [PATCH 311/435] Build parsetab.py --- src/lexer_parser/parsetab.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 9f87869e..99fc4683 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 8060f0e5ec38ecc801df399d7e72a9e7f6c38727 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 5 Jun 2020 14:46:42 -0400 Subject: [PATCH 312/435] Add registers to Instruction class - Reformat code --- src/code_generation/MIPS/ast.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index d868990f..b82ca255 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -1,3 +1,5 @@ +import re + class MIPSProgram: def __init__(self, data_section, text_section): @@ -25,13 +27,15 @@ def __str__(self): data_text = '\n'.join([f'\t{str(d)}' for d in self.data]) return f'\n.data\n{data_text}\n' + class MIPSLabel: def __init__(self, name): - self.name=name - + self.name = name + def __str__(self): return f'{self.name}:\n' + class MIPSFunction: def __init__(self, name, instructions): self.name = name @@ -54,6 +58,18 @@ class Instruction: def __init__(self, name, *arguments): self.name = name self.arguments = arguments + self.registers = [] + patterns = [re.compile(r'\$(?P..)'), + re.compile(r'[0-9]+\(\$(?P..)\)')] + for a in self.arguments: + for p in patterns: + match = p.match(str(a)) + if match: + register = match.group('register') + if register not in self.registers: + self.registers.append(register) + break + print(self.registers) def __str__(self): if len(self.arguments) == 0: @@ -78,7 +94,8 @@ def __init__(self, text): class AsciizInst(Instruction): def __init__(self, *arguments): super().__init__(".asciiz", *arguments) - + + class SpaceInst(Instruction): def __init__(self, *arguments): super().__init__(".space", *arguments) @@ -106,15 +123,17 @@ def __init__(self, *arguments): class LiInstruction(Instruction): def __init__(self, *arguments): super().__init__('li', *arguments) - + + class LaInstruction(Instruction): def __init__(self, *arguments): super().__init__('la', *arguments) + class LbInstruction(Instruction): def __init__(self, *arguments): super().__init__('lb', *arguments) - + class SbInstruction(Instruction): def __init__(self, *arguments): @@ -124,6 +143,7 @@ def __init__(self, *arguments): # Arithmetic Instructions # ======================= + class SubInstruction(Instruction): def __init__(self, *arguments): super().__init__('sub', *arguments) @@ -345,7 +365,8 @@ def __init__(self, *arguments): class BltuInstruction(Instruction): def __init__(self, *arguments): super().__init__('bltu', *arguments) - + + class BeqzInstruction(Instruction): def __init__(self, *arguments): super().__init__('beqz', *arguments) From 6adb775537800eff42d672fb94dd6733215f33a4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 5 Jun 2020 14:47:32 -0400 Subject: [PATCH 313/435] Reformat code in utilities.py --- src/code_generation/MIPS/utilities.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index e2bd2031..945ba24b 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -31,9 +31,9 @@ def get_type(name): def save_callee_registers(): code = allocate_stack(40) - n=8 + n = 8 for i in range(n): - pos= (n-1-i)*4 + pos = (n-1-i)*4 if pos: code += push_stack(f'$s{i}', f'{pos}($sp)') else: @@ -45,9 +45,9 @@ def save_callee_registers(): def save_caller_registers(): code = allocate_stack(40) - n=10 + n = 10 for i in range(n): - pos =(n-1-i)*4 + pos = (n-1-i)*4 if pos: code += push_stack(f'$t{i}', f'{pos}($sp)') else: @@ -58,9 +58,9 @@ def save_caller_registers(): def restore_callee_registers(): code = [] - n=8 + n = 8 for i in range(n): - pos=(n-1-i)*4 + pos = (n-1-i)*4 if pos: code += peek_stack(f'$s{i}', f'{pos}($sp)') else: @@ -73,9 +73,9 @@ def restore_callee_registers(): def restore_caller_registers(): code = [] - n=10 + n = 10 for i in range(n): - pos=(n-1-i)*4 + pos = (n-1-i)*4 code += peek_stack(f'$t{i}', f'{pos}($sp)') code += restore_stack(40) return code @@ -101,9 +101,11 @@ def push_stack(src, pos): def peek_stack(src, pos): return [mips.LwInstruction(src, pos)] + def restore_addresses(): __ADDRS__ = {} + def get_address(key): try: if type(key) is str: @@ -112,11 +114,12 @@ def get_address(key): except: raise Exception('Local not found in stack') + def save_address(key, value): if type(value) is int: if value: - __ADDRS__[key]=f'{value}($sp)' + __ADDRS__[key] = f'{value}($sp)' else: - __ADDRS__[key]=f'($sp)' - - __ADDRS__[key]=value \ No newline at end of file + __ADDRS__[key] = f'($sp)' + + __ADDRS__[key] = value From 3bf86a947b678bcc23ba85dcf65218d710bef148 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Fri, 5 Jun 2020 14:50:40 -0400 Subject: [PATCH 314/435] Reorder program to MIPS --- src/code_generation/MIPS/mips.py | 119 +++++++++++++++++-------------- 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f5571ee8..6dac6fba 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -10,31 +10,38 @@ def program_to_mips_visitor(program: cil.ProgramNode): global __METHOD_MAPPING__, __DATA__ - # Initialize Types Codes + # Initialize Types init_types(program.types) - vt_code = build_virtual_tables(program) + + # Build .data section + vt_space_code = reserve_virtual_tables_space(program) + __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) + for d in program.data] + data_section = mips.MIPSDataSection(vt_space_code + __DATA__) # filling method mapping for t in program.types: for m in t.methods: __METHOD_MAPPING__[(t.type, m)] = t.methods[m] - __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) - for d in program.data] - + # Build .text section main_code = function_to_mips_visitor(program.built_in_code[0]) main_code.instructions.insert(0, mips.MIPSLabel('main')) - functions = [function_to_mips_visitor( - f) for f in program.built_in_code[1:] + program.code] + functions = [function_to_mips_visitor(f) + for f in program.built_in_code[1:] + program.code] functions.insert(0, main_code) text_section = mips.MIPSTextSection(functions) - data_section = mips.MIPSDataSection(vt_code + __DATA__) return mips.MIPSProgram(data_section, text_section) -def build_virtual_tables(program: cil.ProgramNode): - code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst( - t.size_vt)) for t in program.types[1:]] +def reserve_virtual_tables_space(program: cil.ProgramNode): + """ + Each virtual table has a space in the .data section. The + space is 4 bytes for each function, where the address of + the real function is stored. + """ + code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst(t.size_vt)) + for t in program.types[1:]] return code @@ -52,14 +59,14 @@ def function_to_mips_visitor(function): ''' for i, param in enumerate(function.params): - pos=(len(function.params)-1-i) + pos = (len(function.params)-1-i) save_address(param.id, pos*4) code = save_callee_registers() code += allocate_stack(len(function.locals)*4) for i, local in enumerate(function.locals): - pos=(len(function.locals)-1-i) + pos = (len(function.locals)-1-i) save_address(local.id, pos*4) for inst in function.body: @@ -84,9 +91,9 @@ def instruction_to_mips_visitor(inst): def print_to_mips_visitor(p: cil.PrintNode): - addr=get_address(p.str) + addr = get_address(p.str) code = [mips.Comment(str(p)), mips.MoveInstruction( - '$a0',addr)] + '$a0', addr)] if p.str == 'int': code += [ mips.LiInstruction('$v0', 1), @@ -110,28 +117,31 @@ def return_to_mips_visitor(ret: cil.ReturnNode): code.append(mips.LwInstruction('$v0', val)) return code -def read_to_mips_visitor(read:cil.ReadNode): - __DATA__.append(mips.MIPSDataItem(read.result.id, mips.SpaceInst(__BUFFSIZE__))) + +def read_to_mips_visitor(read: cil.ReadNode): + __DATA__.append(mips.MIPSDataItem( + read.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(read.result, read.result.id) - code = [ - mips.Comment(str(read)), - mips.LaInstruction('$a0', read.result), - mips.LiInstruction('$a1', __BUFFSIZE__), - mips.LiInstruction('$v0', 8), - mips.SyscallInstruction() + code = [ + mips.Comment(str(read)), + mips.LaInstruction('$a0', read.result), + mips.LiInstruction('$a1', __BUFFSIZE__), + mips.LiInstruction('$v0', 8), + mips.SyscallInstruction() ] return code -def substring_to_mips_visitor(ss:cil.SubStringNode): - addr=get_address(ss.str) - i=get_address(ss.i) - l=get_address(ss.len) - __DATA__.append(mips.MIPSDataItem(ss.result.id, mips.SpaceInst(__BUFFSIZE__))) +def substring_to_mips_visitor(ss: cil.SubStringNode): + addr = get_address(ss.str) + i = get_address(ss.i) + l = get_address(ss.len) + __DATA__.append(mips.MIPSDataItem( + ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) code = [ mips.Comment(str(ss)), - mips.LaInstruction('$t0', addr), + mips.LaInstruction('$t0', addr), mips.LaInstruction('$t1', ss.result.id), mips.LwInstruction('$t4', i), mips.LwInstruction('$t2', l), @@ -139,7 +149,7 @@ def substring_to_mips_visitor(ss:cil.SubStringNode): mips.MIPSLabel('substring_loop'), mips.BeqzInstruction('$t2', 'end_substring_loop'), mips.LbInstruction('$t3', '($t0)'), - mips.SbInstruction('$t3', '($t1)'), + mips.SbInstruction('$t3', '($t1)'), mips.SubuInstruction('$t2', '$t2', 1), mips.AdduInstruction('$t0', '$t0', 1), mips.AdduInstruction('$t1', '$t1', 1), @@ -148,20 +158,21 @@ def substring_to_mips_visitor(ss:cil.SubStringNode): ] return code -def read_int_to_mips_visitor(read:cil.ReadIntNode): - addr=get_address(read.result) - code = [ - mips.Comment(str(read)), - mips.LiInstruction('$v0', 5), - mips.SyscallInstruction(), - mips.SwInstruction('$v0', addr) + +def read_int_to_mips_visitor(read: cil.ReadIntNode): + addr = get_address(read.result) + code = [ + mips.Comment(str(read)), + mips.LiInstruction('$v0', 5), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', addr) ] return code def length_to_mips_visitor(length: cil.LengthNode): - val= get_address(length.str) - result_val= get_address(length.result) + val = get_address(length.str) + result_val = get_address(length.result) code = [ mips.Comment(str(length)), @@ -177,12 +188,14 @@ def length_to_mips_visitor(length: cil.LengthNode): ] return code -def concat_to_mips_visitor(concat:cil.ConcatNode): - __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) + +def concat_to_mips_visitor(concat: cil.ConcatNode): + __DATA__.append(mips.MIPSDataItem(concat.result.id, + mips.SpaceInst(2 * __BUFFSIZE__))) save_address(concat.result, concat.result.id) a = get_address(concat.str_a) b = get_address(concat.str_b) - + code = [ mips.Comment(str(concat)), mips.LwInstruction('$t0', a), @@ -211,7 +224,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr= get_address(arg.val) + addr = get_address(arg.val) return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr, '($sp)') @@ -245,8 +258,8 @@ def copy_to_mips_visitor(copy: cil.CopyNode): lw $t0, [addr(y)] sw $t0, [addr(x)] """ - x_addr = get_address( copy.result) - y_addr = get_address( copy.val) + x_addr = get_address(copy.result) + y_addr = get_address(copy.val) return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), @@ -264,8 +277,8 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr = get_address( getattr.result) - y_addr = get_address( getattr.obj) + x_addr = get_address(getattr.result) + y_addr = get_address(getattr.obj) attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), @@ -464,10 +477,10 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.NotNode: not_to_mips_visitor, cil.PrintNode: print_to_mips_visitor, cil.ReturnNode: return_to_mips_visitor, - cil.ReadNode: read_to_mips_visitor, - cil.ReadIntNode: read_int_to_mips_visitor, - cil.LengthNode: length_to_mips_visitor, - cil.ConcatNode: concat_to_mips_visitor, - cil.LoadNode:load_to_mips_visitor, - cil.SubStringNode:substring_to_mips_visitor + cil.ReadNode: read_to_mips_visitor, + cil.ReadIntNode: read_int_to_mips_visitor, + cil.LengthNode: length_to_mips_visitor, + cil.ConcatNode: concat_to_mips_visitor, + cil.LoadNode: load_to_mips_visitor, + cil.SubStringNode: substring_to_mips_visitor } From 54c87cc5e7bd96bbf074a55ff7cd4f7a11f5039a Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 9 Jun 2020 11:17:11 -0400 Subject: [PATCH 315/435] Change CIL Function to MIPS code (Initial changes) The MIPSFunction class is the responsible for saving and restoring registers used by the instructions --- src/code_generation/MIPS/ast.py | 89 +++++++++++-- src/code_generation/MIPS/mips.py | 184 +++++++++++++------------- src/code_generation/MIPS/utilities.py | 69 ---------- 3 files changed, 170 insertions(+), 172 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index b82ca255..c58cdaa8 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -31,18 +31,87 @@ def __str__(self): class MIPSLabel: def __init__(self, name): self.name = name + self.callee_saved_reg = set() + self.caller_saved_reg = set() def __str__(self): return f'{self.name}:\n' class MIPSFunction: - def __init__(self, name, instructions): + def __init__(self, name, params, locals): self.name = name - self.instructions = instructions + self.ADDR = {} + self.init_instructions = [] + self.instructions = [] + self.end_instructions = [] + self.caller_saved_reg = set() + self.callee_saved_reg = set() + + self.init_instructions.append(MoveInstruction('$fp', '$sp')) + + self.params_count = len(params) + for i, p in enumerate(params, 1): + self.ADDR[p.id] = f'{(self.params_count - i) * 4}($fp)' + + for i, l in enumerate(locals, 1): + self.ADDR[str(l)] = f'-{i * 4}($fp)' + + self.fp_shift = len(locals) + self.init_instructions.append( + Comment(f'{self.fp_shift} LOCALS = {self.fp_shift * 4} bytes')) + self.fp_shift += 1 + self.init_instructions.append(SwInstruction( + '$ra', f'-{self.fp_shift * 4}($fp)')) + + def append_instruction(self, instruction): + """ + Add new instruction to function block. For a correct operation, the + instructions must be addes continuisly, in the same order that they + were declared in CIL. + """ + # Update used registers + self.__update_callee_saved_reg__(instruction.callee_saved_reg) + self.__update_caller_saved_reg__(instruction.caller_saved_reg) + # Update function instrcutions + self.instructions.append(instruction) + + def end(self): + """ + It points the end of the CIL function, and adds the last necessary + actions. + """ + self.init_instructions.append(SubuInstruction( + '$sp', '$sp', f'{self.fp_shift * 4}')) + self.end_instructions.append(AdduInstruction( + '$sp', '$sp', f'{self.fp_shift * 4}')) + + def get_address(self, id): + """ + Return thememory address where it store the \"id\" identifier of CIL + """ + try: + return self.ADDR[id] + except KeyError: + raise Exception(f'Unsaved id {id}') + + def __update_callee_saved_reg__(self, registers: set): + diff = registers.difference(self.callee_saved_reg) + for reg in diff: + self.fp_shift += 1 + self.init_instructions.append(SwInstruction( + f'${reg}', f'-{self.fp_shift * 4}($fp)')) + self.end_instructions.append(SwInstruction( + f'-{self.fp_shift * 4}($fp)', f'${reg}')) + self.callee_saved_reg.update(diff) + + def __update_caller_saved_reg__(self, registers: set): + self.caller_saved_reg.update(registers) def __str__(self): - return '\n'.join([f'# FUNCTION: {self.name}']+[f'\t{str(i)}' for i in self.instructions]) + instructions = self.init_instructions + \ + self.instructions + self.end_instructions + return '\n'.join([f'{self.name}:']+[f'\t{str(i)}' for i in instructions]) class MIPSDataItem: @@ -58,18 +127,22 @@ class Instruction: def __init__(self, name, *arguments): self.name = name self.arguments = arguments - self.registers = [] + self.caller_saved_reg = set() + self.callee_saved_reg = set() patterns = [re.compile(r'\$(?P..)'), re.compile(r'[0-9]+\(\$(?P..)\)')] + caller_pattern = re.compile(r't[0-9]|a[0-3]|v[0-1]') + callee_pattern = re.compile(r's[0-7]') for a in self.arguments: for p in patterns: match = p.match(str(a)) if match: - register = match.group('register') - if register not in self.registers: - self.registers.append(register) + reg = match.group('register') + if caller_pattern.match(reg): + self.caller_saved_reg.add(reg) + elif callee_pattern.match(reg): + self.callee_saved_reg.add(reg) break - print(self.registers) def __str__(self): if len(self.arguments) == 0: diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 6dac6fba..e51a7ccc 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -2,13 +2,13 @@ from code_generation.MIPS import ast as mips from .utilities import * -__METHOD_MAPPING__ = {} __BUFFSIZE__ = 1024 __DATA__ = [] +CURRENT_FUNCTION = None def program_to_mips_visitor(program: cil.ProgramNode): - global __METHOD_MAPPING__, __DATA__ + global __DATA__ # Initialize Types init_types(program.types) @@ -19,17 +19,9 @@ def program_to_mips_visitor(program: cil.ProgramNode): for d in program.data] data_section = mips.MIPSDataSection(vt_space_code + __DATA__) - # filling method mapping - for t in program.types: - for m in t.methods: - __METHOD_MAPPING__[(t.type, m)] = t.methods[m] - # Build .text section - main_code = function_to_mips_visitor(program.built_in_code[0]) - main_code.instructions.insert(0, mips.MIPSLabel('main')) functions = [function_to_mips_visitor(f) - for f in program.built_in_code[1:] + program.code] - functions.insert(0, main_code) + for f in program.built_in_code + program.code] text_section = mips.MIPSTextSection(functions) return mips.MIPSProgram(data_section, text_section) @@ -46,43 +38,31 @@ def reserve_virtual_tables_space(program: cil.ProgramNode): def function_to_mips_visitor(function): - ''' - Converts a function CIL to a piece of MIPS code:\n - 1) Assigns the right stack address to each param id\n - 2) Saves callee registers\n - 3) Assigns and allocates a chunk in the stack for each local\n - 4) Appends MIPS translation of each instruction in CIL body\n - 5) Restores param's space in stack\n - 6) Restores callee registers\n - 7) Restores local's stack space\n - 8) Jumps to the next instruction which address is in ra register\n - ''' - - for i, param in enumerate(function.params): - pos = (len(function.params)-1-i) - save_address(param.id, pos*4) - - code = save_callee_registers() - - code += allocate_stack(len(function.locals)*4) - for i, local in enumerate(function.locals): - pos = (len(function.locals)-1-i) - save_address(local.id, pos*4) - - for inst in function.body: - code += instruction_to_mips_visitor(inst) - - code += restore_stack(len(function.params)*4) - code += restore_callee_registers() - code += restore_stack(len(function.locals)*4) - code.append(mips.JrInstruction('$ra')) - return mips.MIPSFunction(function.name, code) + """ + Convert a CIL function to a block of MIPS code. + 1- Initialize function context + 2- Set CURRENT_FUNCTION for the use of other functions + 3- Add each CIL instruction to function. + 4- Mark as ended the CIL function + """ + global CURRENT_FUNCTION + # 1 + f = mips.MIPSFunction(function.name, function.params, function.locals) + # 2 + CURRENT_FUNCTION = f + # 3 + for cil_inst in function.body: + for mips_inst in instruction_to_mips_visitor(cil_inst): + CURRENT_FUNCTION.append_instruction(mips_inst) + # 4 + f.end() + return f def instruction_to_mips_visitor(inst): - ''' + """ Resolves visitor for each type - ''' + """ try: return __visitors__[type(inst)](inst) except KeyError: @@ -91,30 +71,44 @@ def instruction_to_mips_visitor(inst): def print_to_mips_visitor(p: cil.PrintNode): - addr = get_address(p.str) - code = [mips.Comment(str(p)), mips.MoveInstruction( - '$a0', addr)] + """ + CIL: + PRINT z; + MIPS if z is int: + move $a0, addr(z) + li $v0, 1 + syscall + MIPS if z is str: + move $a0, addr(z) + li $v0, 4 + syscall + """ + addr_z = CURRENT_FUNCTION.get_address(p.str) + code = [mips.Comment(str(p)), + mips.MoveInstruction('$a0', addr_z)] # move $a0, addr(z) if p.str == 'int': - code += [ - mips.LiInstruction('$v0', 1), - mips.SyscallInstruction(), - ] + code.append(mips.LiInstruction('$v0', 1)) # li $v0, 1 elif p.str == 'str': - code += [ - mips.LiInstruction('$v0', 4), - mips.SyscallInstruction(), - ] - + code.append(mips.LiInstruction('$v0', 4)) # li $v0, 4 + code.append(mips.SyscallInstruction()) # syscall return code def return_to_mips_visitor(ret: cil.ReturnNode): + """ + CIL: + RETURN x; + MIPS if x is int: + li $v0, x + MIPS ix x is not int: + lw $v0, addr(x) + """ code = [mips.Comment(str(ret))] if type(ret.ret_value) is int: - code.append(mips.LiInstruction('$v0', ret.ret_value)) + code.append(mips.LiInstruction('$v0', ret.ret_value)) # li $v0, x else: - val = get_address(ret.ret_value) - code.append(mips.LwInstruction('$v0', val)) + addr_x = CURRENT_FUNCTION.get_address(str(ret.ret_value)) + code.append(mips.LwInstruction('$v0', addr_x)) # lw $v0, addr(x) return code @@ -133,9 +127,9 @@ def read_to_mips_visitor(read: cil.ReadNode): def substring_to_mips_visitor(ss: cil.SubStringNode): - addr = get_address(ss.str) - i = get_address(ss.i) - l = get_address(ss.len) + addr = CURRENT_FUNCTION.get_address(ss.str) + i = CURRENT_FUNCTION.get_address(ss.i) + l = CURRENT_FUNCTION.get_address(ss.len) __DATA__.append(mips.MIPSDataItem( ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) @@ -160,7 +154,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): def read_int_to_mips_visitor(read: cil.ReadIntNode): - addr = get_address(read.result) + addr = CURRENT_FUNCTION.get_address(str(read.result)) code = [ mips.Comment(str(read)), mips.LiInstruction('$v0', 5), @@ -171,8 +165,8 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): def length_to_mips_visitor(length: cil.LengthNode): - val = get_address(length.str) - result_val = get_address(length.result) + val = CURRENT_FUNCTION.get_address(length.str) + result_val = CURRENT_FUNCTION.get_address(str(length.result)) code = [ mips.Comment(str(length)), @@ -193,8 +187,8 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) save_address(concat.result, concat.result.id) - a = get_address(concat.str_a) - b = get_address(concat.str_b) + a = CURRENT_FUNCTION.get_address(concat.str_a) + b = CURRENT_FUNCTION.get_address(concat.str_b) code = [ mips.Comment(str(concat)), @@ -224,7 +218,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr = get_address(arg.val) + addr = CURRENT_FUNCTION.get_address(str(arg.val)) return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr, '($sp)') @@ -239,7 +233,7 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address = get_address(allocate.result) + address = CURRENT_FUNCTION.ADDR[allocate.result] code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), @@ -258,8 +252,8 @@ def copy_to_mips_visitor(copy: cil.CopyNode): lw $t0, [addr(y)] sw $t0, [addr(x)] """ - x_addr = get_address(copy.result) - y_addr = get_address(copy.val) + x_addr = CURRENT_FUNCTION.get_address(str(copy.result)) + y_addr = CURRENT_FUNCTION.get_address(copy.val) return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), @@ -277,8 +271,8 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr = get_address(getattr.result) - y_addr = get_address(getattr.obj) + x_addr = CURRENT_FUNCTION.get_address(str(getattr.result)) + y_addr = CURRENT_FUNCTION.get_address(getattr.obj) attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), @@ -297,8 +291,8 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): lw $t1, [addr(y)] sw $t0, [attr_shift($t0)] """ - x_addr = get_address(setattr.val) - y_addr = get_address(setattr.obj) + x_addr = CURRENT_FUNCTION.get_address(str(setattr.val)) + y_addr = CURRENT_FUNCTION.get_address(str(setattr.obj)) attr_shift = (setattr.attr_index + 1) * 4 return [ mips.Comment(str(setattr)), @@ -319,9 +313,9 @@ def plus_to_mips_visitor(plus: cil.PlusNode): sw $t0, [addr(x)] """ - x_addr = get_address(plus.result) - y_addr = get_address(plus.left) - z_addr = get_address(plus.right) + x_addr = CURRENT_FUNCTION.get_address(str(plus.result)) + y_addr = CURRENT_FUNCTION.get_address(str(plus.left)) + z_addr = CURRENT_FUNCTION.get_address(str(plus.right)) return [ mips.Comment(str(plus)), mips.LwInstruction('$t1', y_addr), @@ -341,9 +335,9 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = get_address(minus.result) - y_addr = get_address(minus.left) - z_addr = get_address(minus.right) + x_addr = CURRENT_FUNCTION.get_address(minus.result) + y_addr = CURRENT_FUNCTION.get_address(minus.left) + z_addr = CURRENT_FUNCTION.get_address(minus.right) return [ mips.Comment(str(minus)), mips.LwInstruction('$t1', y_addr), @@ -363,9 +357,9 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = get_address(star.result) - y_addr = get_address(star.left) - z_addr = get_address(star.right) + x_addr = CURRENT_FUNCTION.get_address(star.result) + y_addr = CURRENT_FUNCTION.get_address(star.left) + z_addr = CURRENT_FUNCTION.get_address(star.right) return [ mips.Comment(str(star)), mips.LwInstruction('$t1', y_addr), @@ -385,9 +379,9 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = get_address(div.result) - y_addr = get_address(div.left) - z_addr = get_address(div.right) + x_addr = CURRENT_FUNCTION.get_address(div.result) + y_addr = CURRENT_FUNCTION.get_address(div.left) + z_addr = CURRENT_FUNCTION.get_address(div.right) return [ mips.Comment(str(div)), mips.LwInstruction('$t1', y_addr), @@ -408,9 +402,9 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): sw $t0, [addr(x)] """ - x_addr = get_address(lesseq.result) - y_addr = get_address(lesseq.left) - z_addr = get_address(lesseq.right) + x_addr = CURRENT_FUNCTION.get_address(lesseq.result) + y_addr = CURRENT_FUNCTION.get_address(lesseq.left) + z_addr = CURRENT_FUNCTION.get_address(lesseq.right) return [ mips.Comment(str(lesseq)), mips.LwInstruction('$t1', y_addr), @@ -431,9 +425,9 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = get_address(less.result) - y_addr = get_address(less.left) - z_addr = get_address(less.right) + x_addr = CURRENT_FUNCTION.get_address(less.result) + y_addr = CURRENT_FUNCTION.get_address(less.left) + z_addr = CURRENT_FUNCTION.get_address(less.right) return [ mips.Comment(str(less)), mips.LwInstruction('$t1', y_addr), @@ -452,8 +446,8 @@ def not_to_mips_visitor(notn: cil.NotNode): not $t0, $t1 sw $t0, [addr(x)] """ - x_addr = get_address(notn.result) - y_addr = get_address(notn.value) + x_addr = CURRENT_FUNCTION.get_address(notn.result) + y_addr = CURRENT_FUNCTION.get_address(notn.value) return [ mips.Comment(str(notn)), mips.LwInstruction('$t1', y_addr), diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 945ba24b..3b121076 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -29,62 +29,6 @@ def get_type(name): return None -def save_callee_registers(): - code = allocate_stack(40) - n = 8 - for i in range(n): - pos = (n-1-i)*4 - if pos: - code += push_stack(f'$s{i}', f'{pos}($sp)') - else: - code += push_stack(f'$s{i}', '($sp)') - code += push_stack('$fp', f'4($sp)') - code += push_stack('$ra', '($sp)') - return code - - -def save_caller_registers(): - code = allocate_stack(40) - n = 10 - for i in range(n): - pos = (n-1-i)*4 - if pos: - code += push_stack(f'$t{i}', f'{pos}($sp)') - else: - code += push_stack(f'$t{i}', '($sp)') - - return code - - -def restore_callee_registers(): - code = [] - n = 8 - for i in range(n): - pos = (n-1-i)*4 - if pos: - code += peek_stack(f'$s{i}', f'{pos}($sp)') - else: - code += peek_stack(f'$s{i}', '($sp)') - code += peek_stack('$fp', '4($sp)') - code += peek_stack('$ra', '($sp)') - code += restore_stack(40) - return code - - -def restore_caller_registers(): - code = [] - n = 10 - for i in range(n): - pos = (n-1-i)*4 - code += peek_stack(f'$t{i}', f'{pos}($sp)') - code += restore_stack(40) - return code - - -def restore_stack(bytes): - return [mips.AdduInstruction('$sp', '$sp', bytes)] - - def allocate_stack(bytes): return [mips.SubuInstruction('$sp', '$sp', bytes)] @@ -102,19 +46,6 @@ def peek_stack(src, pos): return [mips.LwInstruction(src, pos)] -def restore_addresses(): - __ADDRS__ = {} - - -def get_address(key): - try: - if type(key) is str: - return __ADDRS__[key] - return __ADDRS__[key.id] - except: - raise Exception('Local not found in stack') - - def save_address(key, value): if type(value) is int: if value: From bfb21b46ccf23781b3defba8381fecfbf16c8e67 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 28 Jun 2020 15:31:13 -0400 Subject: [PATCH 316/435] Move type to external module Others: - Reformat imports --- src/code_generation/CIL/__init__.py | 7 + src/code_generation/CIL/cil.py | 201 +++++++++++++------------- src/code_generation/MIPS/__init__.py | 7 + src/code_generation/__init__.py | 8 +- src/code_generation/code_gen.py | 10 +- src/cool_types/__init__.py | 24 +++ src/{semantic => cool_types}/types.py | 5 +- src/lexer_parser/__init__.py | 1 + src/semantic/__init__.py | 1 - src/semantic/semantic.py | 170 +++++++++++----------- 10 files changed, 243 insertions(+), 191 deletions(-) create mode 100644 src/code_generation/CIL/__init__.py create mode 100644 src/code_generation/MIPS/__init__.py create mode 100644 src/cool_types/__init__.py rename src/{semantic => cool_types}/types.py (98%) diff --git a/src/code_generation/CIL/__init__.py b/src/code_generation/CIL/__init__.py new file mode 100644 index 00000000..92306e29 --- /dev/null +++ b/src/code_generation/CIL/__init__.py @@ -0,0 +1,7 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + +from .cil import ast_to_cil diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index aa564048..5ce15956 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -1,6 +1,6 @@ -import code_generation.CIL.ast as cil -import lexer_parser.ast as lp_ast -from semantic.types import * +from . import ast as CilAST +import lexer_parser.ast as CoolAST +import cool_types as CT from .optimization import optimization_locals, remove_unused_locals __DATA__ = {} @@ -22,7 +22,7 @@ def add_local(id=None): global __LOCALS__ if id is None: id = f'local_{len(__LOCALS__)}' - local = cil.LocalNode(id) + local = CilAST.LocalNode(id) __LOCALS__[id] = local return local @@ -37,7 +37,7 @@ def add_label(): def ast_to_cil(ast): - if type(ast) == lp_ast.ProgramNode: + if type(ast) == CoolAST.ProgramNode: return program_to_cil_visitor(ast) raise Exception(f'AST root must be program') @@ -76,9 +76,9 @@ def program_to_cil_visitor(program): built_in_code = [] # completing .TYPE section - for t in TypesByName: - _type = cil.TypeNode(t) - value = TypesByName[t] + for t in CT.TypesByName: + _type = CilAST.TypeNode(t) + value = CT.TypesByName[t] __ATTR__[t] = [] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) @@ -105,26 +105,26 @@ def program_to_cil_visitor(program): """ main_instance = '__main__' main_result = 'main_result' - main_function = cil.FuncNode('main', [], [cil.LocalNode(main_instance), cil.LocalNode(main_result)], - [cil.AllocateNode('Main', main_instance), - cil.ArgNode(main_instance), - cil.VCAllNode('Main', 'main', main_result)]) + main_function = CilAST.FuncNode('main', [], [CilAST.LocalNode(main_instance), CilAST.LocalNode(main_result)], + [CilAST.AllocateNode('Main', main_instance), + CilAST.ArgNode(main_instance), + CilAST.VCAllNode('Main', 'main', main_result)]) built_in_code.append(main_function) # completing .CODE and .DATA sections for c in program.classes: for f in c.feature_nodes: - if type(f) == DefFuncNode: + if type(f) == CoolAST.DefFuncNode: fun = func_to_cil_visitor(c.type, f) code.append(fun) built_in_code += built_in_to_cil() - data = [cil.DataNode(__DATA__[data_value], data_value) + data = [CilAST.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] - cil_program = cil.ProgramNode(types, data, code, built_in_code) + cil_program = CilAST.ProgramNode(types, data, code, built_in_code) remove_unused_locals(cil_program) optimization_locals(cil_program) return cil_program @@ -135,51 +135,51 @@ def built_in_to_cil(): def out_string_to_cil(): - return cil.FuncNode('IO_out_string', [cil.ParamNode('self'), cil.ParamNode('str')], [], [cil.PrintNode('str'), cil.ReturnNode('self')]) + return CilAST.FuncNode('IO_out_string', [CilAST.ParamNode('self'), CilAST.ParamNode('str')], [], [CilAST.PrintNode('str'), CilAST.ReturnNode('self')]) def out_int_to_cil(): - return cil.FuncNode('IO_out_int', [cil.ParamNode('self'), cil.ParamNode('int')], [], [cil.PrintNode('int'), cil.ReturnNode('self')]) + return CilAST.FuncNode('IO_out_int', [CilAST.ParamNode('self'), CilAST.ParamNode('int')], [], [CilAST.PrintNode('int'), CilAST.ReturnNode('self')]) def in_string_to_cil(): - str=cil.LocalNode('str') - return cil.FuncNode('IO_in_string', [cil.ParamNode('self')], [str], [cil.ReadNode(str), cil.ReturnNode(str)]) + str = CilAST.LocalNode('str') + return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self')], [str], [CilAST.ReadNode(str), CilAST.ReturnNode(str)]) def in_int_to_cil(): - i=cil.LocalNode('int') - return cil.FuncNode('IO_in_int', [cil.ParamNode('self')], [i], [cil.ReadIntNode(i), cil.ReturnNode(i)]) + i = CilAST.LocalNode('int') + return CilAST.FuncNode('IO_in_int', [CilAST.ParamNode('self')], [i], [CilAST.ReadIntNode(i), CilAST.ReturnNode(i)]) def type_name_to_cil(): - t=cil.LocalNode('type') - return cil.FuncNode('Object_type_name', [cil.ParamNode('self')], [t], [cil.TypeOfNode(t, 'self'), cil.ReturnNode(t)]) + t = CilAST.LocalNode('type') + return CilAST.FuncNode('Object_type_name', [CilAST.ParamNode('self')], [t], [CilAST.TypeOfNode(t, 'self'), CilAST.ReturnNode(t)]) def copy_to_cil(): - copy=cil.LocalNode('copy') - return cil.FuncNode('Object_copy', [cil.ParamNode('self')], [copy], [cil.CopyNode('self', copy), cil.ReturnNode(copy)]) + copy = CilAST.LocalNode('copy') + return CilAST.FuncNode('Object_copy', [CilAST.ParamNode('self')], [copy], [CilAST.CopyNode('self', copy), CilAST.ReturnNode(copy)]) def length_to_cil(): - result=cil.LocalNode('result') - return cil.FuncNode('length_String', [cil.ParamNode('self')], [result], [cil.LengthNode('self', result), cil.ReturnNode(result)]) + result = CilAST.LocalNode('result') + return CilAST.FuncNode('length_String', [CilAST.ParamNode('self')], [result], [CilAST.LengthNode('self', result), CilAST.ReturnNode(result)]) def concat_to_cil(): - result=cil.LocalNode('result') - return cil.FuncNode('concat_String', [cil.ParamNode('self'), cil.ParamNode('x')], [result], [cil.ConcatNode('self', 'x', result), cil.ReturnNode(result)]) + result = CilAST.LocalNode('result') + return CilAST.FuncNode('concat_String', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) def substring_to_cil(): - result=cil.LocalNode('result') - return cil.FuncNode('substr_String', [cil.ParamNode('self'), cil.ParamNode('i'), cil.ParamNode('l')], [result], [cil.SubStringNode('self', 'i', 'l', result), cil.ReturnNode(result)]) + result = CilAST.LocalNode('result') + return CilAST.FuncNode('substr_String', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) def func_to_cil_visitor(type_name, func): ''' - Converts from FunctionNode in parsing AST to FuncionNode in cil AST. \n + Converts from FunctionNode in COOL AST to FuncionNode in CIL AST. \n 1) Builds ParamNodes for each param in FunctionNode.params\n 2) Builds function body by putting together each instruction's body\n 3) Creates an array of necessary local variables @@ -187,8 +187,8 @@ def func_to_cil_visitor(type_name, func): ''' global __LOCALS__, __DATA_LOCALS__, __TYPEOF__, labels_count, __CURRENT_TYPE__ name = f'{type_name}_{func.id}' - params = [cil.ParamNode('self')] - params += [cil.ParamNode(id) for (id, t) in func.params] + params = [CilAST.ParamNode('self')] + params += [CilAST.ParamNode(id) for (id, t) in func.params] __LOCALS__ = {} labels_count = 0 __DATA_LOCALS__ = {} @@ -200,10 +200,10 @@ def func_to_cil_visitor(type_name, func): func.expressions) body += instruction.body - body.append(cil.ReturnNode(instruction.value)) + body.append(CilAST.ReturnNode(instruction.value)) _locals = __LOCALS__.copy() - return cil.FuncNode(name, params, [_locals[k] for k in _locals.keys()], body) + return CilAST.FuncNode(name, params, [_locals[k] for k in _locals.keys()], body) def expression_to_cil_visitor(expression): @@ -230,7 +230,7 @@ def case_to_cil_visitor(case): expr_cil = expression_to_cil_visitor(case.expr) body += expr_cil.body t = add_local() - body.append(cil.TypeOfNode(t, expr_cil.value)) + body.append(CilAST.TypeOfNode(t, expr_cil.value)) types = [] labels = [] for c in case.case_list: @@ -243,15 +243,15 @@ def case_to_cil_visitor(case): for i, branch in enumerate(case.case_list): predicate = add_local() - body.append(cil.MinusNode(t, branch.type, predicate)) - body.append(cil.ConditionalGotoNode(predicate, labels[i])) + body.append(CilAST.MinusNode(t, branch.type, predicate)) + body.append(CilAST.ConditionalGotoNode(predicate, labels[i])) val = add_local(branch.id) - body.append(cil.AssignNode(val, expr_cil.value)) + body.append(CilAST.AssignNode(val, expr_cil.value)) branch_cil = expression_to_cil_visitor( branch.expr) body += branch_cil.body value = branch_cil.value - body.append(cil.LabelNode(labels[i])) + body.append(CilAST.LabelNode(labels[i])) return CIL_block(body, value) @@ -266,11 +266,11 @@ def assign_to_cil_visitor(assign): if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) body = expr.body + \ - [cil.SetAttrNode('self', assign.id, expr.value, index)] + [CilAST.SetAttrNode('self', assign.id, expr.value, index)] return CIL_block(body, expr.value) else: val = add_local(assign.id) - body = expr.body + [cil.AssignNode(val, expr.value)] + body = expr.body + [CilAST.AssignNode(val, expr.value)] return CIL_block(body, val) @@ -282,14 +282,14 @@ def arith_to_cil_visitor(arith): body = l.body + r.body - if type(arith) == lp_ast.PlusNode: - body.append(cil.PlusNode(l.value, r.value, cil_result)) - elif type(arith) == lp_ast.MinusNode: - body.append(cil.MinusNode(l.value, r.value, cil_result)) - elif type(arith) == lp_ast.StarNode: - body.append(cil.StarNode(l.value, r.value, cil_result)) - elif type(arith) == lp_ast.DivNode: - body.append(cil.DivNode(l.value, r.value, cil_result)) + if type(arith) == CoolAST.PlusNode: + body.append(CilAST.PlusNode(l.value, r.value, cil_result)) + elif type(arith) == CoolAST.MinusNode: + body.append(CilAST.MinusNode(l.value, r.value, cil_result)) + elif type(arith) == CoolAST.StarNode: + body.append(CilAST.StarNode(l.value, r.value, cil_result)) + elif type(arith) == CoolAST.DivNode: + body.append(CilAST.DivNode(l.value, r.value, cil_result)) return CIL_block(body, cil_result) @@ -307,9 +307,9 @@ def if_to_cil_visitor(_if): label_2 = add_label() value = add_local() - body = predicate.body + [cil.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ - cil.AssignNode(value, else_expression.value), cil.GotoNode(label_2), cil.LabelNode(label_1)] + then.body + [ - cil.AssignNode(value, then.value), cil.LabelNode(label_2)] + body = predicate.body + [CilAST.ConditionalGotoNode(predicate.value, label_1)] + else_expression.body + [ + CilAST.AssignNode(value, else_expression.value), CilAST.GotoNode(label_2), CilAST.LabelNode(label_1)] + then.body + [ + CilAST.AssignNode(value, then.value), CilAST.LabelNode(label_2)] return CIL_block(body, value) @@ -325,8 +325,8 @@ def loop_to_cil_visitor(loop): loop_label = add_label() end_label = add_label() - body = [cil.LabelNode(predicate_label)] + predicate.body + [cil.ConditionalGotoNode(predicate.value, loop_label), cil.GotoNode(end_label), - cil.LabelNode(loop_label)] + loop_block.body + [cil.GotoNode(predicate_label), cil.LabelNode(end_label), cil.AssignNode(value, 0)] + body = [CilAST.LabelNode(predicate_label)] + predicate.body + [CilAST.ConditionalGotoNode(predicate.value, loop_label), CilAST.GotoNode(end_label), + CilAST.LabelNode(loop_label)] + loop_block.body + [CilAST.GotoNode(predicate_label), CilAST.LabelNode(end_label), CilAST.AssignNode(value, 0)] return CIL_block(body, value) @@ -339,10 +339,10 @@ def equal_to_cil_visitor(equal): end_label = add_label() value = add_local() - body = l.body + r.body + [cil.MinusNode(l.value, r.value, cil_result), cil.AssignNode(value, 0), - cil.ConditionalGotoNode( - cil_result, end_label), cil.AssignNode(value, 1), - cil.LabelNode(end_label)] + body = l.body + r.body + [CilAST.MinusNode(l.value, r.value, cil_result), CilAST.AssignNode(value, 0), + CilAST.ConditionalGotoNode( + cil_result, end_label), CilAST.AssignNode(value, 1), + CilAST.LabelNode(end_label)] return CIL_block(body, value) @@ -352,7 +352,7 @@ def lessthan_to_cil_visitor(lessthan): r = expression_to_cil_visitor(lessthan.rvalue) value = add_local() - body = l.body + r.body + [cil.LessNode(l.value, r.value, value)] + body = l.body + r.body + [CilAST.LessNode(l.value, r.value, value)] return CIL_block(body, value) @@ -361,7 +361,7 @@ def lesseqthan_to_cil_visitor(lessthan): r = expression_to_cil_visitor(lessthan.rvalue) value = add_local() - body = l.body + r.body + [cil.LessEqNode(l.value, r.value, value)] + body = l.body + r.body + [CilAST.LessEqNode(l.value, r.value, value)] return CIL_block(body, value) @@ -377,7 +377,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([cil.GetAttrNode('self', id.id, result, index)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index)], result) try: val = __LOCALS__[id.id] return CIL_block([], val) @@ -391,19 +391,20 @@ def new_to_cil_visitor(new_node): body = [] if t == 'SELF_TYPE': - t, need_typeof = get_typeof(t, 'self') + t, need_typeof = get_typeof(__CURRENT_TYPE__) if need_typeof: - body.append(cil.TypeOfNode(t, 'self')) + body.append(CilAST.TypeOfNode(t, __CURRENT_TYPE__)) - body.append(cil.AllocateNode(t, value)) - init_attr = TypesByName[t].get_all_attributes() + body.append(CilAST.AllocateNode(t, value)) + init_attr = CT.TypesByName[t].get_all_attributes() for index, attr in enumerate(init_attr): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body - body.append(cil.SetAttrNode(value, attr.id, attr_cil.value, index)) + body.append(CilAST.SetAttrNode( + value, attr.id, attr_cil.value, index)) return CIL_block(body, value) @@ -422,7 +423,7 @@ def string_to_cil_visitor(str): str_id, need_load = add_data_local(str_addr) if need_load: - body = [cil.LoadNode(str_addr, str_id)] + body = [CilAST.LoadNode(str_addr, str_id)] else: body = [] @@ -436,7 +437,7 @@ def let_to_cil_visitor(let): attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body val = add_local(attr.id) - body.append(cil.AssignNode(val, attr_cil.value)) + body.append(CilAST.AssignNode(val, attr_cil.value)) expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body @@ -451,8 +452,8 @@ def logic_not_to_cil_visitor(not_node): value = add_local() end_label = add_label() - body = expr_cil.body + [cil.AssignNode(value, 0), cil.ConditionalGotoNode(expr_cil.value, end_label), - cil.AssignNode(value, 1), cil.LabelNode(end_label)] + body = expr_cil.body + [CilAST.AssignNode(value, 0), CilAST.ConditionalGotoNode(expr_cil.value, end_label), + CilAST.AssignNode(value, 1), CilAST.LabelNode(end_label)] return CIL_block(body, value) @@ -463,7 +464,7 @@ def not_to_cil_visitor(not_node): value = add_local() - body = expr_cil.body + [cil.NotNode(expr_cil.value, value)] + body = expr_cil.body + [CilAST.NotNode(expr_cil.value, value)] return CIL_block(body, value) @@ -499,45 +500,45 @@ def func_call_to_cil_visitor(call): t, need_typeof = get_typeof(obj) if need_typeof: - body.append(cil.TypeOfNode(t, obj)) + body.append(CilAST.TypeOfNode(t, obj)) - body.append(cil.ArgNode(obj)) + body.append(CilAST.ArgNode(obj)) for arg in arg_values: - body.append(cil.ArgNode(arg)) + body.append(CilAST.ArgNode(arg)) result = add_local() if not call.type: - body.append(cil.VCAllNode(t, call.id, result)) + body.append(CilAST.VCAllNode(t, call.id, result)) else: - body.append(cil.VCAllNode(call.type, call.id, result)) + body.append(CilAST.VCAllNode(call.type, call.id, result)) return CIL_block(body, result) __visitor__ = { - lp_ast.AssignNode: assign_to_cil_visitor, - lp_ast.BlockNode: block_to_cil_visitor, - lp_ast.BoolNode: bool_to_cil_visitor, - lp_ast.IfNode: if_to_cil_visitor, - lp_ast.WhileNode: loop_to_cil_visitor, - lp_ast.EqNode: equal_to_cil_visitor, - lp_ast.LogicNegationNode: logic_not_to_cil_visitor, - lp_ast.LetNode: let_to_cil_visitor, - lp_ast.NewNode: new_to_cil_visitor, - lp_ast.IntNode: integer_to_cil_visitor, - lp_ast.StringNode: string_to_cil_visitor, - lp_ast.PlusNode: arith_to_cil_visitor, - lp_ast.MinusNode: arith_to_cil_visitor, - lp_ast.StarNode: arith_to_cil_visitor, - lp_ast.DivNode: arith_to_cil_visitor, - lp_ast.VarNode: id_to_cil_visitor, - lp_ast.FuncCallNode: func_call_to_cil_visitor, - lp_ast.IsVoidNode: is_void_to_cil_visitor, - lp_ast.NegationNode: not_to_cil_visitor, - lp_ast.LessThanNode: lessthan_to_cil_visitor, - lp_ast.LessEqNode: lesseqthan_to_cil_visitor, - lp_ast.CaseNode: case_to_cil_visitor, + CoolAST.AssignNode: assign_to_cil_visitor, + CoolAST.BlockNode: block_to_cil_visitor, + CoolAST.BoolNode: bool_to_cil_visitor, + CoolAST.IfNode: if_to_cil_visitor, + CoolAST.WhileNode: loop_to_cil_visitor, + CoolAST.EqNode: equal_to_cil_visitor, + CoolAST.LogicNegationNode: logic_not_to_cil_visitor, + CoolAST.LetNode: let_to_cil_visitor, + CoolAST.NewNode: new_to_cil_visitor, + CoolAST.IntNode: integer_to_cil_visitor, + CoolAST.StringNode: string_to_cil_visitor, + CoolAST.PlusNode: arith_to_cil_visitor, + CoolAST.MinusNode: arith_to_cil_visitor, + CoolAST.StarNode: arith_to_cil_visitor, + CoolAST.DivNode: arith_to_cil_visitor, + CoolAST.VarNode: id_to_cil_visitor, + CoolAST.FuncCallNode: func_call_to_cil_visitor, + CoolAST.IsVoidNode: is_void_to_cil_visitor, + CoolAST.NegationNode: not_to_cil_visitor, + CoolAST.LessThanNode: lessthan_to_cil_visitor, + CoolAST.LessEqNode: lesseqthan_to_cil_visitor, + CoolAST.CaseNode: case_to_cil_visitor, } diff --git a/src/code_generation/MIPS/__init__.py b/src/code_generation/MIPS/__init__.py new file mode 100644 index 00000000..cf99c9bb --- /dev/null +++ b/src/code_generation/MIPS/__init__.py @@ -0,0 +1,7 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + +from .mips import program_to_mips_visitor diff --git a/src/code_generation/__init__.py b/src/code_generation/__init__.py index f0ac8303..37fc8e2e 100644 --- a/src/code_generation/__init__.py +++ b/src/code_generation/__init__.py @@ -1 +1,7 @@ -from .code_gen import generate_code \ No newline at end of file +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + +from .code_gen import generate_code diff --git a/src/code_generation/code_gen.py b/src/code_generation/code_gen.py index 51be3df8..87d44432 100644 --- a/src/code_generation/code_gen.py +++ b/src/code_generation/code_gen.py @@ -1,5 +1,11 @@ -from .CIL.cil import ast_to_cil -from .MIPS.mips import program_to_mips_visitor +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + +from .CIL import ast_to_cil +from .MIPS import program_to_mips_visitor def generate_code(ast): diff --git a/src/cool_types/__init__.py b/src/cool_types/__init__.py new file mode 100644 index 00000000..5cabe365 --- /dev/null +++ b/src/cool_types/__init__.py @@ -0,0 +1,24 @@ +""" +Copyright (c) 2020 School of Math and Computer Science, University of Havana + +COOL compiler project +""" + +from .types import ( + CoolType, + CoolTypeMethod, + CoolTypeMethod, + SelfType, + ObjectType, + BoolType, + IntType, + StringType, + IOType, + TypesByName, + type_by_name, + check_inherits, + check_type_declaration, + check_type_hierarchy, + get_attribute, + pronounced_join +) diff --git a/src/semantic/types.py b/src/cool_types/types.py similarity index 98% rename from src/semantic/types.py rename to src/cool_types/types.py index fabb6ff4..5318f3b7 100644 --- a/src/semantic/types.py +++ b/src/cool_types/types.py @@ -5,7 +5,6 @@ """ from errors import add_semantic_error -from lexer_parser.ast import * class CoolType: @@ -153,7 +152,7 @@ def check_inherits(type_a: CoolType, type_b: CoolType): return True -def check_type_declaration(node: ProgramNode): +def check_type_declaration(node): for c in node.classes: try: _ = TypesByName[c.type] @@ -165,7 +164,7 @@ def check_type_declaration(node: ProgramNode): return True -def check_type_hierarchy(node: ProgramNode): +def check_type_hierarchy(node): for c in node.classes: cType = TypesByName[c.type] if c.parent_type: diff --git a/src/lexer_parser/__init__.py b/src/lexer_parser/__init__.py index af0921b1..6eeb14f4 100644 --- a/src/lexer_parser/__init__.py +++ b/src/lexer_parser/__init__.py @@ -6,3 +6,4 @@ from .lexer import lexer from .parser import parser +import ast as CoolAST diff --git a/src/semantic/__init__.py b/src/semantic/__init__.py index 739fdfa0..d883ab27 100644 --- a/src/semantic/__init__.py +++ b/src/semantic/__init__.py @@ -5,4 +5,3 @@ """ from .semantic import semantic_check -from .types import TypesByName diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index a5a227e3..eb22d027 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -4,7 +4,9 @@ COOL compiler project """ -from .types import * +import cool_types as CT +from lexer_parser.ast import * +from errors import add_semantic_error def program_visitor(program: ProgramNode): @@ -17,27 +19,27 @@ def program_visitor(program: ProgramNode): 5) Check recursive each delared class ''' # 1) and 2) - if not (check_type_declaration(program) and check_type_hierarchy(program)): + if not (CT.check_type_declaration(program) and CT.check_type_hierarchy(program)): return # 3) try: - TypesByName['Main'] + CT.TypesByName['Main'] except KeyError: add_semantic_error(0, 0, f'Main class undeclared') return # 4) - types_already_check = [ObjectType, IntType, StringNode, BoolType, IOType] + types_already_check = [CT.ObjectType, CT.IntType, CT.StringType, CT.BoolType, CT.IOType] classes = program.classes.copy() while len(classes) != 0: c: DefClassNode = classes.pop() if c.parent_type is not None: - parent_type = TypesByName[c.parent_type] + parent_type = CT.TypesByName[c.parent_type] if parent_type not in types_already_check: classes = [c] + classes continue - classType = TypesByName[c.type] + classType = CT.TypesByName[c.type] for f in c.feature_nodes: if type(f) is DefFuncNode: param_types = [param[1] for param in f.params] @@ -56,7 +58,7 @@ def program_visitor(program: ProgramNode): class_visitor(c, None, {}) -def class_visitor(_class: DefClassNode, current_class: CoolType, local_scope: dict): +def class_visitor(_class: DefClassNode, current_class: CT.CoolType, local_scope: dict): ''' Check class @@ -66,7 +68,7 @@ class MY_TYPE inherits INHERITS_TYPE{ 1) Check each feature in FEATURE_LIST ''' - current_class = TypesByName[_class.type] + current_class = CT.TypesByName[_class.type] local_scope = local_scope.copy() local_scope['self'] = current_class # 1) @@ -77,7 +79,7 @@ class MY_TYPE inherits INHERITS_TYPE{ def_func_visitor(feature, current_class, local_scope) -def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_scope: dict): +def def_attr_class_visitor(attr: DefAttrNode, current_class: CT.CoolType, local_scope: dict): ''' Check class attribute @@ -90,16 +92,16 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CoolType, local_sco if attr.expr: # 1) expr_type = expression_visitor(attr.expr, current_class, local_scope) - attr_type = type_by_name(attr.type) + attr_type = CT.type_by_name(attr.type) # 2) - if attr_type is not None and not check_inherits(expr_type, attr_type): + if attr_type is not None and not CT.check_inherits(expr_type, attr_type): add_semantic_error( attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') else: return attr_type -def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_scope: dict): +def def_attribute_visitor(def_attr: DefAttrNode, current_class: CT.CoolType, local_scope: dict): ''' Check attribute (except class attribute) @@ -112,7 +114,7 @@ def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_ 3) Type of the attribute is TYPE ''' # 1) - id_type = type_by_name(def_attr.type) + id_type = CT.type_by_name(def_attr.type) if id_type is None: add_semantic_error(def_attr.lineno, def_attr.colno, f'unknown type \'{def_attr.type}\'') @@ -122,14 +124,14 @@ def def_attribute_visitor(def_attr: DefAttrNode, current_class: CoolType, local_ expr_type = expression_visitor( def_attr.expr, current_class, local_scope) # 2.2) - if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: + if not CT.check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(def_attr.lineno, def_attr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') # 3) return id_type -def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope: dict): +def def_func_visitor(function: DefFuncNode, current_class: CT.CoolType, local_scope: dict): ''' Check function declaration @@ -145,23 +147,23 @@ def def_func_visitor(function: DefFuncNode, current_class: CoolType, local_scope local_scope = local_scope.copy() # 1) for arg in function.params: - local_scope[arg[0]] = type_by_name(arg[1]) + local_scope[arg[0]] = CT.type_by_name(arg[1]) # 2) body_type = expression_visitor( function.expressions, current_class, local_scope) - return_type = type_by_name(function.return_type) + return_type = CT.type_by_name(function.return_type) # 3) - if return_type == SelfType: + if return_type == CT.SelfType: return_type = current_class # 4) - if check_inherits(body_type, return_type): + if CT.check_inherits(body_type, return_type): return return_type elif body_type is not None: add_semantic_error(function.lineno, function.colno, f'invalid returned type \'{function.return_type}\'') -def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: dict): +def assignment_visitor(assign: AssignNode, current_class: CT.CoolType, local_scope: dict): ''' Check assigment @@ -180,7 +182,7 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: id_type = local_scope[assign.id] except KeyError: # 1.2) - attr, _ = get_attribute(current_class, assign.id) + attr, _ = CT.get_attribute(current_class, assign.id) if attr is None: add_semantic_error(assign.id.lineno, assign.id.colno, f'unknown variable \'{assign.id}\'') @@ -190,7 +192,7 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: # 2) expr_type = expression_visitor(assign.expr, current_class, local_scope) # 3) - if not check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: + if not CT.check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(assign.expr.lineno, assign.expr.colno, f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') # 4) @@ -198,7 +200,7 @@ def assignment_visitor(assign: AssignNode, current_class: CoolType, local_scope: return expr_type -def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_scope: dict): +def func_call_visitor(func_call: FuncCallNode, current_class: CT.CoolType, local_scope: dict): ''' Check function call @@ -238,23 +240,23 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc # 2.2) if func_call.type: # 2.2.1) - specific_type = type_by_name(func_call.type) + specific_type = CT.type_by_name(func_call.type) if specific_type is None: add_semantic_error( func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') # 2.2.2) - elif check_inherits(object_type, specific_type): + elif CT.check_inherits(object_type, specific_type): method, msg = specific_type.get_method_without_hierarchy( func_call.id, args_types) # 2.2.3) - if method is not None and method.returnedType == SelfType: + if method is not None and method.returnedType == CT.SelfType: method.returnedType = specific_type else: add_semantic_error(func_call.lineno, func_call.colno, f'type {object_type} not inherits from {specific_type}') else: method, msg = object_type.get_method(func_call.id, args_types) - if method is not None and method.returnedType == SelfType: + if method is not None and method.returnedType == CT.SelfType: method.returnedType = object_type # 3) else: @@ -262,7 +264,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc if method is None and msg is not None: add_semantic_error(func_call.lineno, func_call.colno, msg) # 3.1) - elif method.returnedType == SelfType: + elif method.returnedType == CT.SelfType: func_call.returned_type = current_class else: # 4) @@ -270,7 +272,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CoolType, local_sc return func_call.returned_type -def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): +def if_visitor(if_struct: IfNode, current_class: CT.CoolType, local_scope: dict): ''' Check \"if\" stament @@ -284,9 +286,9 @@ def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): # 1) predicate_type = expression_visitor( if_struct.if_expr, current_class, local_scope) - if predicate_type != BoolType and predicate_type is not None: + if predicate_type != CT.BoolType and predicate_type is not None: add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, - f'\'if\' condition must be a {BoolType}') + f'\'if\' condition must be a {CT.BoolType}') # 2) then_type = expression_visitor( if_struct.then_expr, current_class, local_scope) @@ -294,11 +296,11 @@ def if_visitor(if_struct: IfNode, current_class: CoolType, local_scope: dict): else_type = expression_visitor( if_struct.else_expr, current_class, local_scope) # 4) - if_struct.returned_type = pronounced_join(then_type, else_type) + if_struct.returned_type = CT.pronounced_join(then_type, else_type) return if_struct.returned_type -def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dict): +def loop_expr_visitor(loop: WhileNode, current_class: CT.CoolType, local_scope: dict): ''' Check loop @@ -310,17 +312,17 @@ def loop_expr_visitor(loop: WhileNode, current_class: CoolType, local_scope: dic ''' # 1) predicate_type = expression_visitor(loop.cond, current_class, local_scope) - if predicate_type != BoolType and predicate_type is not None: + if predicate_type != CT.BoolType and predicate_type is not None: add_semantic_error(loop.cond.lineno, loop.cond.colno, - f'\"loop\" condition must be a {BoolType}') + f'\"loop\" condition must be a {CT.BoolType}') # 2) expression_visitor(loop.body, current_class, local_scope) # 3) - loop.returned_type = ObjectType - return ObjectType + loop.returned_type = CT.ObjectType + return CT.ObjectType -def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: dict): +def block_expr_visitor(block: BlockNode, current_class: CT.CoolType, local_scope: dict): ''' Check block @@ -338,7 +340,7 @@ def block_expr_visitor(block: BlockNode, current_class: CoolType, local_scope: d return final_type -def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): +def let_visitor(let: LetNode, current_class: CT.CoolType, local_scope: dict): ''' Check let @@ -364,7 +366,7 @@ def let_visitor(let: LetNode, current_class: CoolType, local_scope: dict): return let.returned_type -def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict): +def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: dict): ''' Check case @@ -393,7 +395,7 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict # 2) branch_0 = case.case_list[0] # 2.1) - branch_0_type = type_by_name(branch_0.type) + branch_0_type = CT.type_by_name(branch_0.type) temp = local_scope.copy() if branch_0_type is None: add_semantic_error(branch_0.line, branch_0.column, @@ -408,21 +410,21 @@ def case_expr_visitor(case: CaseNode, current_class: CoolType, local_scope: dict for branch in case.case_list[1:]: temp = local_scope.copy() # 3.1) - branch_type = type_by_name(branch.type) + branch_type = CT.type_by_name(branch.type) if branch_type is None: add_semantic_error(branch_0.line, branch_0.column, f"unknow type \"{branch.type}\"") # 3.2) temp[branch.id] = branch_type # 3.3) - current_type = pronounced_join( + current_type = CT.pronounced_join( current_type, expression_visitor(branch.expr, current_class, temp)) # 4) case.returned_type = current_type return case.returned_type -def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, local_scope: dict): +def arithmetic_operator_visitor(operator: BinaryNode, current_class: CT.CoolType, local_scope: dict): ''' Check arithmetic operator (binary) @@ -435,21 +437,21 @@ def arithmetic_operator_visitor(operator: BinaryNode, current_class: CoolType, l # 1) lvalue_type = expression_visitor( operator.lvalue, current_class, local_scope) - if lvalue_type != IntType and lvalue_type is not None: + if lvalue_type != CT.IntType and lvalue_type is not None: add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, - f'invalid left value type {lvalue_type}, must be a {IntType}') + f'invalid left value type {lvalue_type}, must be a {CT.IntType}') # 2) rvalue_type = expression_visitor( operator.rvalue, current_class, local_scope) - if rvalue_type != IntType and rvalue_type is not None: + if rvalue_type != CT.IntType and rvalue_type is not None: add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, - f'invalid left value type {rvalue_type}, must be a {IntType}') + f'invalid left value type {rvalue_type}, must be a {CT.IntType}') # 3) - operator.returned_type = IntType - return IntType + operator.returned_type = CT.IntType + return CT.IntType -def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: dict): +def comparison_visitor(cmp: BinaryNode, current_class: CT.CoolType, local_scope: dict): ''' Check comparison @@ -461,20 +463,20 @@ def comparison_visitor(cmp: BinaryNode, current_class: CoolType, local_scope: di ''' # 1) lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) - if lvalue_type != IntType and lvalue_type is not None: + if lvalue_type != CT.IntType and lvalue_type is not None: add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, - f'lvalue type must be a {IntType}') + f'lvalue type must be a {CT.IntType}') # 2) rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) - if rvalue_type != IntType and rvalue_type is not None: + if rvalue_type != CT.IntType and rvalue_type is not None: add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, - f'rvalue type must be a {IntType}') + f'rvalue type must be a {CT.IntType}') # 3) - cmp.returned_type = BoolType - return BoolType + cmp.returned_type = CT.BoolType + return CT.BoolType -def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): +def equal_visitor(equal: EqNode, current_class: CT.CoolType, local_scope: dict): ''' Check equal @@ -490,16 +492,16 @@ def equal_visitor(equal: EqNode, current_class: CoolType, local_scope: dict): # 2) rvalue_type = expression_visitor(equal.rvalue, current_class, local_scope) # 3) - static_types = [IntType, BoolType, StringType] + static_types = [CT.IntType, CT.BoolType, CT.StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: add_semantic_error(equal.lineno, equal.colno, f'impossible compare {lvalue_type} and {rvalue_type} types') # 4) - equal.returned_type = BoolType - return BoolType + equal.returned_type = CT.BoolType + return CT.BoolType -def negation_visitor(negation: NegationNode, current_class: CoolType, local_scope: dict): +def negation_visitor(negation: NegationNode, current_class: CT.CoolType, local_scope: dict): ''' Check binary negation @@ -512,14 +514,14 @@ def negation_visitor(negation: NegationNode, current_class: CoolType, local_scop # 1) value_type = expression_visitor(negation.val, current_class, local_scope) # 2) - if value_type != IntType and value_type is not None: + if value_type != CT.IntType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, - f'type {value_type} invalid. The \'~\' operator can only be used with type {IntType}') + f'type {value_type} invalid. The \'~\' operator can only be used with type {CT.IntType}') # 3) - return IntType + return CT.IntType -def logic_negation_visitor(negation: LogicNegationNode, current_class: CoolType, local_scope: dict): +def logic_negation_visitor(negation: LogicNegationNode, current_class: CT.CoolType, local_scope: dict): ''' Check logic negation @@ -533,14 +535,14 @@ def logic_negation_visitor(negation: LogicNegationNode, current_class: CoolType, # 1) value_type = expression_visitor(negation.val, current_class, local_scope) # 2) - if value_type != BoolType and value_type is not None: + if value_type != CT.BoolType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, - f'type {value_type} invalid. The \'not\' operator can only be used with type {BoolType}') + f'type {value_type} invalid. The \'not\' operator can only be used with type {CT.BoolType}') # 3) - return BoolType + return CT.BoolType -def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scope: dict): +def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CT.CoolType, local_scope: dict): ''' Check isvoid @@ -552,11 +554,11 @@ def is_void_expr_visitor(isvoid: IsVoidNode, current_class: CoolType, local_scop # 1) expression_visitor(isvoid.val, current_class, local_scope) # 2) - isvoid.returned_type = BoolType - return BoolType + isvoid.returned_type = CT.BoolType + return CT.BoolType -def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): +def var_visitor(var: VarNode, current_class: CT.CoolType, local_scope: dict): ''' Check var @@ -571,7 +573,7 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): var.returned_type = local_scope[var.id] else: # 2) - attribute, _ = get_attribute(current_class, var.id) + attribute, _ = CT.get_attribute(current_class, var.id) if attribute is not None: var.returned_type = attribute.attrType else: @@ -581,7 +583,7 @@ def var_visitor(var: VarNode, current_class: CoolType, local_scope: dict): return var.returned_type -def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): +def new_expr_visitor(new: NewNode, current_class: CT.CoolType, local_scope: dict): ''' Check new @@ -592,12 +594,12 @@ def new_expr_visitor(new: NewNode, current_class: CoolType, local_scope: dict): 3) Type of new is TYPE ''' # 1) - t = type_by_name(new.type) + t = CT.type_by_name(new.type) if not t: add_semantic_error( new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') # 2) - if t == SelfType: + if t == CT.SelfType: new.returned_type = current_class else: new.returned_type = t @@ -614,8 +616,8 @@ def int_visitor(expr: IntNode, current_class, local_scope): 1) Type os int is Int :) ''' # 1) - expr.returned_type = IntType - return IntType + expr.returned_type = CT.IntType + return CT.IntType def bool_visitor(expr: BoolNode, current_class, local_scope): @@ -627,8 +629,8 @@ def bool_visitor(expr: BoolNode, current_class, local_scope): 1) Type of bool is Bool :) ''' # 1) - expr.returned_type = BoolType - return BoolType + expr.returned_type = CT.BoolType + return CT.BoolType def string_visitor(expr: StringNode, current_class, local_scope): @@ -639,8 +641,8 @@ def string_visitor(expr: StringNode, current_class, local_scope): 1) Type of string is String :) ''' - expr.returned_type = StringType - return StringType + expr.returned_type = CT.StringType + return CT.StringType __visitors__ = { @@ -670,7 +672,7 @@ def string_visitor(expr: StringNode, current_class, local_scope): } -def expression_visitor(expression, current_class: CoolType, local_scope: dict) -> CoolType: +def expression_visitor(expression, current_class: CT.CoolType, local_scope: dict) -> CT.CoolType: ''' This is the main function to check any expression. This function search the right function for check the expression. From 6e1f27f80db4a82e628426f9d5ef320600279e23 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 22 Sep 2020 18:45:13 -0400 Subject: [PATCH 317/435] Initial implementation of VCALL to MIPS - Remove unnecessary vt_space_code - Add __VT__ for link between methods calls and his implementations --- src/code_generation/MIPS/mips.py | 49 +++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index e51a7ccc..777bd054 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -5,19 +5,37 @@ __BUFFSIZE__ = 1024 __DATA__ = [] CURRENT_FUNCTION = None +__VT__ = {} def program_to_mips_visitor(program: cil.ProgramNode): - global __DATA__ + global __DATA__, __VT__ + + # Build Virtual Table + q = program.types.copy() + t = q.pop(0) + if t.type != 'SELF_TYPE': + raise Exception("unexpected first type") + + while len(q): + t = q.pop(0) + for method, type_impl in t.methods.items(): + if type_impl == t.type: + __VT__[(t.type, method)] = f'{type_impl}_{method}' + else: + try: + __VT__[(t.type, method)] = __VT__[(type_impl, method)] + except KeyError: + q.append(t) # Initialize Types init_types(program.types) # Build .data section - vt_space_code = reserve_virtual_tables_space(program) + # vt_space_code = reserve_virtual_tables_space(program) __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) for d in program.data] - data_section = mips.MIPSDataSection(vt_space_code + __DATA__) + data_section = mips.MIPSDataSection(__DATA__) # Build .text section functions = [function_to_mips_visitor(f) @@ -456,6 +474,28 @@ def not_to_mips_visitor(notn: cil.NotNode): ] +def vcal_to_mips_visitor(vcall: cil.VCAllNode): + """ + CIL: + result = VCALL [type] [method] + MIPS: + 1 - Put the parameters into $a0-$a3. If there are more than four parameters, + the additional parameters are pushed onto the stack. + 2 - Save any of the caller-saved registers ($t0 - $t9) which are used by the + caller. + 3 - Execute a jal (or jalr) to jump to the function. + 4 - Restore the caller-saved registers. + 5 - If any arguments were passed on the stack (instead of in $a0-$a3), pop + them off of the stack. + 6 - Extract the return value, if any, from register $v0. + """ + t = get_type(vcall.type) + return [ + # 3 + mips.JalInstruction(__VT__[(vcall.type, vcall.method)]) + ] + + __visitors__ = { cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, @@ -476,5 +516,6 @@ def not_to_mips_visitor(notn: cil.NotNode): cil.LengthNode: length_to_mips_visitor, cil.ConcatNode: concat_to_mips_visitor, cil.LoadNode: load_to_mips_visitor, - cil.SubStringNode: substring_to_mips_visitor + cil.SubStringNode: substring_to_mips_visitor, + cil.VCAllNode: vcal_to_mips_visitor } From d8b28b391bd069df002366a5f0bedc0d0e846138 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 22 Sep 2020 19:02:06 -0400 Subject: [PATCH 318/435] Parameters are already pushed - Parameters are already pushed by ARG instructions, previous of the VCALL instruction --- src/code_generation/MIPS/mips.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 777bd054..53bbd7a8 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -479,19 +479,17 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): CIL: result = VCALL [type] [method] MIPS: - 1 - Put the parameters into $a0-$a3. If there are more than four parameters, - the additional parameters are pushed onto the stack. - 2 - Save any of the caller-saved registers ($t0 - $t9) which are used by the + 1 - Save any of the caller-saved registers ($t0 - $t9) which are used by the caller. - 3 - Execute a jal (or jalr) to jump to the function. - 4 - Restore the caller-saved registers. - 5 - If any arguments were passed on the stack (instead of in $a0-$a3), pop + 2 - Execute a jal (or jalr) to jump to the function. + 3 - Restore the caller-saved registers. + 4 - If any arguments were passed on the stack (instead of in $a0-$a3), pop them off of the stack. - 6 - Extract the return value, if any, from register $v0. + 5 - Extract the return value, if any, from register $v0. """ t = get_type(vcall.type) return [ - # 3 + # 2 mips.JalInstruction(__VT__[(vcall.type, vcall.method)]) ] From 527f9bad50389cab3fca9849b5970555f10e6f93 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 23 Sep 2020 08:22:08 -0400 Subject: [PATCH 319/435] Use $a0-$a3 registers for function arguments --- src/code_generation/MIPS/ast.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index c58cdaa8..7cdb6f4e 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -51,8 +51,16 @@ def __init__(self, name, params, locals): self.init_instructions.append(MoveInstruction('$fp', '$sp')) self.params_count = len(params) - for i, p in enumerate(params, 1): - self.ADDR[p.id] = f'{(self.params_count - i) * 4}($fp)' + # Store first 4 arguments in $a0 - $a3 registers + i = 0 + while i < self.params_count and i < 4: + p = params[i] + self.ADDR[p.id] = f'$a{i}' + i += 1 + # Save the rest on the stack + if i < self.params_count: + for j, p in enumerate(params[i:]): + self.ADDR[p.id] = f'{j * 4}($fp)' for i, l in enumerate(locals, 1): self.ADDR[str(l)] = f'-{i * 4}($fp)' From 9b8056495aed754efc855ca83a6d0f79ed294e68 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 23 Sep 2020 08:22:52 -0400 Subject: [PATCH 320/435] Remove $a0-$a3 and $v0-$v1 from caller --- src/code_generation/MIPS/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 7cdb6f4e..f96d3cca 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -139,7 +139,7 @@ def __init__(self, name, *arguments): self.callee_saved_reg = set() patterns = [re.compile(r'\$(?P..)'), re.compile(r'[0-9]+\(\$(?P..)\)')] - caller_pattern = re.compile(r't[0-9]|a[0-3]|v[0-1]') + caller_pattern = re.compile(r't[0-9]') callee_pattern = re.compile(r's[0-7]') for a in self.arguments: for p in patterns: From c8aa76a1f87c3b87ba3e56e15e990403067b0679 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 23 Sep 2020 08:25:20 -0400 Subject: [PATCH 321/435] Optimize plus and minus operations --- src/code_generation/MIPS/mips.py | 48 ++++++++++++++++++--------- src/code_generation/MIPS/utilities.py | 9 ++++- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 53bbd7a8..b51b8a18 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -334,13 +334,22 @@ def plus_to_mips_visitor(plus: cil.PlusNode): x_addr = CURRENT_FUNCTION.get_address(str(plus.result)) y_addr = CURRENT_FUNCTION.get_address(str(plus.left)) z_addr = CURRENT_FUNCTION.get_address(str(plus.right)) - return [ - mips.Comment(str(plus)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), - mips.AddInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + instructions = [ + mips.Comment(str(plus)) ] + if not is_register(y_addr): + instructions.append(mips.LwInstruction('$t1', y_addr)) + y_addr = '$t1' + if not is_register(z_addr): + instructions.append(mips.LwInstruction('$t2', z_addr)) + z_addr = '$t2' + if is_register(x_addr): + instructions.append(mips.AddInstruction(x_addr, y_addr, z_addr)) + else: + instructions.append(mips.AddInstruction('$t0', y_addr, z_addr)) + instructions.append(mips.SwInstruction('$t0', x_addr)) + + return instructions def minus_to_mips_visitor(minus: cil.MinusNode): @@ -353,16 +362,25 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(minus.result) - y_addr = CURRENT_FUNCTION.get_address(minus.left) - z_addr = CURRENT_FUNCTION.get_address(minus.right) - return [ - mips.Comment(str(minus)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), - mips.SubInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + x_addr = CURRENT_FUNCTION.get_address(str(minus.result)) + y_addr = CURRENT_FUNCTION.get_address(str(minus.left)) + z_addr = CURRENT_FUNCTION.get_address(str(minus.right)) + instructions = [ + mips.Comment(str(minus)) ] + if not is_register(y_addr): + instructions.append(mips.LwInstruction('$t1', y_addr)) + y_addr = '$t1' + if not is_register(z_addr): + instructions.append(mips.LwInstruction('$t2', z_addr)) + z_addr = '$t2' + if is_register(x_addr): + instructions.append(mips.SubInstruction(x_addr, y_addr, z_addr)) + else: + instructions.append(mips.SubInstruction('$t0', y_addr, z_addr)) + instructions.append(mips.SwInstruction('$t0', x_addr)) + + return instructions def star_to_mips_visitor(star: cil.StarNode): diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 3b121076..d61e6be2 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -1,5 +1,5 @@ from code_generation.MIPS import ast as mips - +import re __TYPES__ = {} __ADDRS__ = {} @@ -54,3 +54,10 @@ def save_address(key, value): __ADDRS__[key] = f'($sp)' __ADDRS__[key] = value + + +register_pattern = re.compile(r'\$v[0-1]|\$a[0-3]|\$t[0-9]|\$s[0-7]') + + +def is_register(addr: str): + return register_pattern.match(addr) != None From 554d02e15437f14a122c1137a12c56310904d2cf Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 24 Sep 2020 15:29:49 -0400 Subject: [PATCH 322/435] Fix call type in CIL --- src/code_generation/CIL/cil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 5ce15956..94a41db0 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -483,13 +483,16 @@ def block_to_cil_visitor(block): def func_call_to_cil_visitor(call): body = [] + t = None if call.object: obj_cil = expression_to_cil_visitor( call.object) body += obj_cil.body obj = obj_cil.value + t = call.object.returned_type.name else: obj = 'self' + t = __CURRENT_TYPE__ arg_values = [] @@ -498,9 +501,6 @@ def func_call_to_cil_visitor(call): body += arg_cil.body arg_values.append(arg_cil.value) - t, need_typeof = get_typeof(obj) - if need_typeof: - body.append(CilAST.TypeOfNode(t, obj)) body.append(CilAST.ArgNode(obj)) From dd8145ca1ff56a476e1803fab6ef812993696689 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 24 Sep 2020 17:25:37 -0400 Subject: [PATCH 323/435] Add free_stack function --- src/code_generation/MIPS/utilities.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index d61e6be2..14789cdf 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -33,6 +33,10 @@ def allocate_stack(bytes): return [mips.SubuInstruction('$sp', '$sp', bytes)] +def free_stack(bytes): + return [mips.AdduInstruction('$sp', '$sp', bytes)] + + def push_stack(src, pos): code = [] if src[0] != '$': From 8a033cb4ff4124b6570c9fe2ed32cddbf4eb99e4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 24 Sep 2020 17:27:37 -0400 Subject: [PATCH 324/435] Add MIPS instructions of VCALL - Save caller-saed registers - Excecute JAL - Restore the caller-saved registers --- src/code_generation/MIPS/mips.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index b51b8a18..001f1131 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -500,16 +500,30 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): 1 - Save any of the caller-saved registers ($t0 - $t9) which are used by the caller. 2 - Execute a jal (or jalr) to jump to the function. - 3 - Restore the caller-saved registers. - 4 - If any arguments were passed on the stack (instead of in $a0-$a3), pop + 3 - If any arguments were passed on the stack (instead of in $a0-$a3), pop them off of the stack. + 4 - Restore the caller-saved registers. 5 - Extract the return value, if any, from register $v0. """ t = get_type(vcall.type) - return [ - # 2 - mips.JalInstruction(__VT__[(vcall.type, vcall.method)]) - ] + instructios = [] + instructios.append(mips.Comment(str(vcall))) + # 1 + size = len(CURRENT_FUNCTION.caller_saved_reg) * 4 + instructios.extend(allocate_stack(size)) + s = size + for reg in CURRENT_FUNCTION.caller_saved_reg: + s -= 4 + instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) + # 2 + instructios.append(mips.JalInstruction(__VT__[(vcall.type, vcall.method)])) + # 4 + s = size + for reg in CURRENT_FUNCTION.caller_saved_reg: + s -= 4 + instructios.extend(peek_stack(f'${reg}', f'{s}($sp)')) + instructios.extend(free_stack(size)) + return instructios __visitors__ = { From 597b8fa83957388b0ba73dfba4fcb5e96c2db7ab Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 02:13:29 +0100 Subject: [PATCH 325/435] Add .vscode to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4acafde1..f60cd936 100644 --- a/.gitignore +++ b/.gitignore @@ -408,3 +408,4 @@ dmypy.json # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) +.vscode \ No newline at end of file From 6d81b04a62955918bbbc1d4c337aceed85992f29 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sun, 25 Oct 2020 17:31:09 -0400 Subject: [PATCH 326/435] Fix bugs Use TimeoutExpired instead of TimeoutError --- tests/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 9d58ac3f..cd31854e 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -37,7 +37,7 @@ def compare_errors(compiler_path: str, cool_file_path: str, error_file_path: str try: sp = subprocess.run(['bash', compiler_path, cool_file_path], capture_output=True, timeout=timeout) return_code, output = sp.returncode, sp.stdout.decode() - except TimeoutError: + except subprocess.TimeoutExpired: assert False, COMPILER_TIMEOUT compiler_output = output.split('\n') From 32e2c20899fa10f2ebe18ad414ab99db8702f76d Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sun, 25 Oct 2020 18:37:27 -0400 Subject: [PATCH 327/435] Add first semantic test --- tests/semantic/class1.cl | 9 +++++++++ tests/semantic/class1_error.txt | 2 ++ tests/semantic/hello_world.cl | 5 ----- tests/semantic_test.py | 7 ++++--- tests/utils/utils.py | 8 ++++++++ 5 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 tests/semantic/class1.cl create mode 100644 tests/semantic/class1_error.txt delete mode 100755 tests/semantic/hello_world.cl diff --git a/tests/semantic/class1.cl b/tests/semantic/class1.cl new file mode 100644 index 00000000..ed83da9d --- /dev/null +++ b/tests/semantic/class1.cl @@ -0,0 +1,9 @@ +-- Classes may not be redefined. + +class Repeat { + sum(a: Int, b: Int): Int { a + b }; +}; + +class Repeat { + mult(a: Int, b: Int): Int { a * b }; +}; \ No newline at end of file diff --git a/tests/semantic/class1_error.txt b/tests/semantic/class1_error.txt new file mode 100644 index 00000000..19c50767 --- /dev/null +++ b/tests/semantic/class1_error.txt @@ -0,0 +1,2 @@ +(7, 5) - SemanticError: Classes may not be redefined + diff --git a/tests/semantic/hello_world.cl b/tests/semantic/hello_world.cl deleted file mode 100755 index 0c818f90..00000000 --- a/tests/semantic/hello_world.cl +++ /dev/null @@ -1,5 +0,0 @@ -class Main inherits IO { - main(): IO { - out_string("Hello, World.\n") - }; -}; diff --git a/tests/semantic_test.py b/tests/semantic_test.py index 6c71f896..cac9cd78 100644 --- a/tests/semantic_test.py +++ b/tests/semantic_test.py @@ -1,6 +1,6 @@ import pytest import os -from utils import compare_errors +from utils import compare_errors, first_error_only_line tests_dir = __file__.rpartition('/')[0] + '/semantic/' tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] @@ -8,6 +8,7 @@ @pytest.mark.semantic @pytest.mark.error @pytest.mark.run(order=3) -@pytest.mark.parametrize("cool_file", []) +@pytest.mark.parametrize("cool_file", tests) def test_semantic_errors(compiler_path, cool_file): - compare_errors(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_error.txt') \ No newline at end of file + compare_errors(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_error.txt', \ + cmp=first_error_only_line) \ No newline at end of file diff --git a/tests/utils/utils.py b/tests/utils/utils.py index cd31854e..76c9ef26 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -26,6 +26,14 @@ def first_error(compiler_output: list, errors: list): assert line == oline and column == ocolumn and error_type == oerror_type,\ UNEXPECTED_ERROR % (error_type, line, column, oerror_type, oline, ocolumn) +def first_error_only_line(compiler_output: list, errors: list): + line, column, error_type, _ = parse_error(errors[0]) + + oline, ocolumn, oerror_type, _ = parse_error(compiler_output[0]) + + assert line == oline and error_type == oerror_type,\ + UNEXPECTED_ERROR % (error_type, line, column, oerror_type, oline, ocolumn) + def get_file_name(path: str): try: From 89627cc0be4440b31961c73e0ae6d020eda47944 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sun, 25 Oct 2020 18:46:15 -0400 Subject: [PATCH 328/435] Update utils --- tests/utils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 76c9ef26..a3fa13ce 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -6,14 +6,14 @@ TEST_MUST_FAIL = 'El test %s debe fallar al compilar' TEST_MUST_COMPILE = 'El test %s debe compilar' BAD_ERROR_FORMAT = '''El error no esta en formato: (,) - : - o no se encuentra en la 3ra linea''' + o no se encuentra en la 3ra linea\n\n%s''' UNEXPECTED_ERROR = 'Se esperaba un %s en (%d, %d). Su error fue un %s en (%d, %d)' ERROR_FORMAT = r'^\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*-\s*(\w+)\s*:(.*)$' def parse_error(error: str): merror = re.fullmatch(ERROR_FORMAT, error) - assert merror, BAD_ERROR_FORMAT + assert merror, BAD_ERROR_FORMAT % error return (t(x) for t, x in zip([int, int, str, str], merror.groups())) From fc91a3b3730f714c3056d66b3222d59e8ceb08e5 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Mon, 26 Oct 2020 15:04:53 -0400 Subject: [PATCH 329/435] Add new tests --- tests/semantic/features1.cl | 19 +++++++++++++++++++ tests/semantic/features1_error.txt | 2 ++ tests/semantic/features2.cl | 19 +++++++++++++++++++ tests/semantic/features2_error.txt | 2 ++ tests/semantic/inheritance1.cl | 19 +++++++++++++++++++ tests/semantic/inheritance1_error.txt | 2 ++ tests/semantic/inheritance2.cl | 19 +++++++++++++++++++ tests/semantic/inheritance2_error.txt | 2 ++ tests/semantic/inheritance3.cl | 13 +++++++++++++ tests/semantic/inheritance3_error.txt | 2 ++ tests/semantic/inheritance4.cl | 19 +++++++++++++++++++ tests/semantic/inheritance4_error.txt | 3 +++ tests/semantic/inheritance5.cl | 21 +++++++++++++++++++++ tests/semantic/inheritance5_error.txt | 4 ++++ 14 files changed, 146 insertions(+) create mode 100755 tests/semantic/features1.cl create mode 100755 tests/semantic/features1_error.txt create mode 100755 tests/semantic/features2.cl create mode 100755 tests/semantic/features2_error.txt create mode 100755 tests/semantic/inheritance1.cl create mode 100755 tests/semantic/inheritance1_error.txt create mode 100755 tests/semantic/inheritance2.cl create mode 100755 tests/semantic/inheritance2_error.txt create mode 100755 tests/semantic/inheritance3.cl create mode 100644 tests/semantic/inheritance3_error.txt create mode 100755 tests/semantic/inheritance4.cl create mode 100644 tests/semantic/inheritance4_error.txt create mode 100755 tests/semantic/inheritance5.cl create mode 100644 tests/semantic/inheritance5_error.txt diff --git a/tests/semantic/features1.cl b/tests/semantic/features1.cl new file mode 100755 index 00000000..96dd8ebc --- /dev/null +++ b/tests/semantic/features1.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + x: String <- ":)"; +}; \ No newline at end of file diff --git a/tests/semantic/features1_error.txt b/tests/semantic/features1_error.txt new file mode 100755 index 00000000..8534b6ca --- /dev/null +++ b/tests/semantic/features1_error.txt @@ -0,0 +1,2 @@ +features1.cl:18: Attribute x is multiply defined in class. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/features2.cl b/tests/semantic/features2.cl new file mode 100755 index 00000000..2db177f7 --- /dev/null +++ b/tests/semantic/features2.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { "3" }; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/tests/semantic/features2_error.txt b/tests/semantic/features2_error.txt new file mode 100755 index 00000000..7a91695f --- /dev/null +++ b/tests/semantic/features2_error.txt @@ -0,0 +1,2 @@ +features2.cl:18: Method x is multiply defined. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/inheritance1.cl b/tests/semantic/inheritance1.cl new file mode 100755 index 00000000..5adb59d9 --- /dev/null +++ b/tests/semantic/inheritance1.cl @@ -0,0 +1,19 @@ +--It is illegal to redefine attribute names. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + x: Int; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/tests/semantic/inheritance1_error.txt b/tests/semantic/inheritance1_error.txt new file mode 100755 index 00000000..1840980c --- /dev/null +++ b/tests/semantic/inheritance1_error.txt @@ -0,0 +1,2 @@ +inheritance1.cl:16: Attribute x is an attribute of an inherited class. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/inheritance2.cl b/tests/semantic/inheritance2.cl new file mode 100755 index 00000000..2ed46f37 --- /dev/null +++ b/tests/semantic/inheritance2.cl @@ -0,0 +1,19 @@ +--If C inherits from P, then P must have a class definition somewhere in the program. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class Alo { + x: Int <- 3; + + x(): String { "3" }; +}; + +class B inherits A { + div(a: Int, b: Int): Int { a / b}; + + x: String <- "2"; +}; \ No newline at end of file diff --git a/tests/semantic/inheritance2_error.txt b/tests/semantic/inheritance2_error.txt new file mode 100755 index 00000000..fed9ee58 --- /dev/null +++ b/tests/semantic/inheritance2_error.txt @@ -0,0 +1,2 @@ +inheritance2.cl:15: Class B inherits from an undefined class A. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/inheritance3.cl b/tests/semantic/inheritance3.cl new file mode 100755 index 00000000..83a4e132 --- /dev/null +++ b/tests/semantic/inheritance3.cl @@ -0,0 +1,13 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits A { + x: Int <- 3; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/tests/semantic/inheritance3_error.txt b/tests/semantic/inheritance3_error.txt new file mode 100644 index 00000000..b6c973a6 --- /dev/null +++ b/tests/semantic/inheritance3_error.txt @@ -0,0 +1,2 @@ +inheritance3.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/inheritance4.cl b/tests/semantic/inheritance4.cl new file mode 100755 index 00000000..efe6e9a6 --- /dev/null +++ b/tests/semantic/inheritance4.cl @@ -0,0 +1,19 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/tests/semantic/inheritance4_error.txt b/tests/semantic/inheritance4_error.txt new file mode 100644 index 00000000..d249a97d --- /dev/null +++ b/tests/semantic/inheritance4_error.txt @@ -0,0 +1,3 @@ +inheritance4.cl:15: Class B, or an ancestor of B, is involved in an inheritance cycle. +inheritance4.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/inheritance5.cl b/tests/semantic/inheritance5.cl new file mode 100755 index 00000000..6650368c --- /dev/null +++ b/tests/semantic/inheritance5.cl @@ -0,0 +1,21 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits C { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; + +class C inherits A { }; \ No newline at end of file diff --git a/tests/semantic/inheritance5_error.txt b/tests/semantic/inheritance5_error.txt new file mode 100644 index 00000000..d3a920f5 --- /dev/null +++ b/tests/semantic/inheritance5_error.txt @@ -0,0 +1,4 @@ +inheritance5.cl:21: Class C, or an ancestor of C, is involved in an inheritance cycle. +inheritance5.cl:15: Class B, or an ancestor of B, is involved in an inheritance cycle. +inheritance5.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. +Compilation halted due to static semantic errors. \ No newline at end of file From 207281fd9a98b4f023084ebf5f41dbc750d19e90 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Mon, 26 Oct 2020 17:30:47 -0400 Subject: [PATCH 330/435] Add new tests --- tests/semantic/attributes1.cl | 13 ++++++++++ tests/semantic/attributes1_error.txt | 2 ++ tests/semantic/attributes2.cl | 13 ++++++++++ tests/semantic/attributes2_error.txt | 2 ++ tests/semantic/attributes3.cl | 25 ++++++++++++++++++ tests/semantic/attributes3_error.txt | 3 +++ tests/semantic/attributes4.cl | 39 ++++++++++++++++++++++++++++ tests/semantic/attributes4_error.txt | 3 +++ tests/semantic/methods1.cl | 12 +++++++++ tests/semantic/methods1_error.txt | 2 ++ tests/semantic/methods2.cl | 12 +++++++++ tests/semantic/methods2_error.txt | 2 ++ tests/semantic/methods3.cl | 14 ++++++++++ tests/semantic/methods3_error.txt | 2 ++ tests/semantic/methods4.cl | 19 ++++++++++++++ tests/semantic/methods4_error.txt | 2 ++ tests/semantic/methods5.cl | 20 ++++++++++++++ tests/semantic/methods5_error.txt | 2 ++ tests/semantic/methods6.cl | 27 +++++++++++++++++++ tests/semantic/methods6_error.txt | 2 ++ 20 files changed, 216 insertions(+) create mode 100644 tests/semantic/attributes1.cl create mode 100644 tests/semantic/attributes1_error.txt create mode 100644 tests/semantic/attributes2.cl create mode 100644 tests/semantic/attributes2_error.txt create mode 100644 tests/semantic/attributes3.cl create mode 100644 tests/semantic/attributes3_error.txt create mode 100644 tests/semantic/attributes4.cl create mode 100644 tests/semantic/attributes4_error.txt create mode 100644 tests/semantic/methods1.cl create mode 100644 tests/semantic/methods1_error.txt create mode 100644 tests/semantic/methods2.cl create mode 100644 tests/semantic/methods2_error.txt create mode 100644 tests/semantic/methods3.cl create mode 100644 tests/semantic/methods3_error.txt create mode 100644 tests/semantic/methods4.cl create mode 100644 tests/semantic/methods4_error.txt create mode 100644 tests/semantic/methods5.cl create mode 100644 tests/semantic/methods5_error.txt create mode 100644 tests/semantic/methods6.cl create mode 100644 tests/semantic/methods6_error.txt diff --git a/tests/semantic/attributes1.cl b/tests/semantic/attributes1.cl new file mode 100644 index 00000000..3fa0440e --- /dev/null +++ b/tests/semantic/attributes1.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: B <- new A; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/attributes1_error.txt b/tests/semantic/attributes1_error.txt new file mode 100644 index 00000000..31f9ae60 --- /dev/null +++ b/tests/semantic/attributes1_error.txt @@ -0,0 +1,2 @@ +attributes1.cl:10: Inferred type A of initialization of attribute test2 does not conform to declared type B. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/attributes2.cl b/tests/semantic/attributes2.cl new file mode 100644 index 00000000..7937c2cc --- /dev/null +++ b/tests/semantic/attributes2.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: C <- new D; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/attributes2_error.txt b/tests/semantic/attributes2_error.txt new file mode 100644 index 00000000..b9955d65 --- /dev/null +++ b/tests/semantic/attributes2_error.txt @@ -0,0 +1,2 @@ +attributes2.cl:10: Inferred type D of initialization of attribute test2 does not conform to declared type C. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/attributes3.cl b/tests/semantic/attributes3.cl new file mode 100644 index 00000000..8a67decd --- /dev/null +++ b/tests/semantic/attributes3.cl @@ -0,0 +1,25 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class B inherits A { + b: Bool <- true; +}; +class C inherits B { + c: String <- "C"; +}; +class D inherits B { + d: IO <- new Main.main(); +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/tests/semantic/attributes3_error.txt b/tests/semantic/attributes3_error.txt new file mode 100644 index 00000000..7de7d436 --- /dev/null +++ b/tests/semantic/attributes3_error.txt @@ -0,0 +1,3 @@ +attributes3.cl:9: Undeclared identifier b. +attributes3.cl:9: Predicate of 'if' does not have type Bool. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/attributes4.cl b/tests/semantic/attributes4.cl new file mode 100644 index 00000000..a7f63adb --- /dev/null +++ b/tests/semantic/attributes4.cl @@ -0,0 +1,39 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; +}; +class B inherits A { + b: Bool <- true; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class D inherits B { + d: IO <- new Main.main(); + test3(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1, c: String <- "C" in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; +class C inherits B { + c: String <- "C"; + test2(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/tests/semantic/attributes4_error.txt b/tests/semantic/attributes4_error.txt new file mode 100644 index 00000000..e567b7a2 --- /dev/null +++ b/tests/semantic/attributes4_error.txt @@ -0,0 +1,3 @@ +attributes4.cl:32: Undeclared identifier d. +attributes4.cl:28: Inferred return type Object of method test2 does not conform to declared return type IO. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods1.cl b/tests/semantic/methods1.cl new file mode 100644 index 00000000..d1203197 --- /dev/null +++ b/tests/semantic/methods1.cl @@ -0,0 +1,12 @@ +--The identifiers used in the formal parameter list must be distinct + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, a: B): Int { 4 }; +}; \ No newline at end of file diff --git a/tests/semantic/methods1_error.txt b/tests/semantic/methods1_error.txt new file mode 100644 index 00000000..9eef7594 --- /dev/null +++ b/tests/semantic/methods1_error.txt @@ -0,0 +1,2 @@ +methods1.cl:11: Formal parameter a is multiply defined. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods2.cl b/tests/semantic/methods2.cl new file mode 100644 index 00000000..3865f0e1 --- /dev/null +++ b/tests/semantic/methods2.cl @@ -0,0 +1,12 @@ +--The type of the method body must conform to the declared return type. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): C { new D }; +}; \ No newline at end of file diff --git a/tests/semantic/methods2_error.txt b/tests/semantic/methods2_error.txt new file mode 100644 index 00000000..be015863 --- /dev/null +++ b/tests/semantic/methods2_error.txt @@ -0,0 +1,2 @@ +methods2.cl:11: Inferred return type D of method test does not conform to declared return type C. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods3.cl b/tests/semantic/methods3.cl new file mode 100644 index 00000000..b92faeb9 --- /dev/null +++ b/tests/semantic/methods3.cl @@ -0,0 +1,14 @@ +--A formal parameter hides any definition of an attribute of the same name. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: C <- new C; + test(a: D): D { a }; + test2(a: B): C { a }; +}; \ No newline at end of file diff --git a/tests/semantic/methods3_error.txt b/tests/semantic/methods3_error.txt new file mode 100644 index 00000000..b617d069 --- /dev/null +++ b/tests/semantic/methods3_error.txt @@ -0,0 +1,2 @@ +methods3.cl:13: Inferred return type B of method test2 does not conform to declared return type C. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods4.cl b/tests/semantic/methods4.cl new file mode 100644 index 00000000..be8fa36e --- /dev/null +++ b/tests/semantic/methods4.cl @@ -0,0 +1,19 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(x: Int, y: Object): Int { x }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/methods4_error.txt b/tests/semantic/methods4_error.txt new file mode 100644 index 00000000..8ef739ff --- /dev/null +++ b/tests/semantic/methods4_error.txt @@ -0,0 +1,2 @@ +methods4.cl:12: In redefined method f, parameter type Object is different from original type Int +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods5.cl b/tests/semantic/methods5.cl new file mode 100644 index 00000000..3905dfdd --- /dev/null +++ b/tests/semantic/methods5.cl @@ -0,0 +1,20 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(a: Int, b: Int): Object { a - b }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + diff --git a/tests/semantic/methods5_error.txt b/tests/semantic/methods5_error.txt new file mode 100644 index 00000000..b7c4c000 --- /dev/null +++ b/tests/semantic/methods5_error.txt @@ -0,0 +1,2 @@ +methods5.cl:12: In redefined method f, return type Object is different from original return type Int. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/methods6.cl b/tests/semantic/methods6.cl new file mode 100644 index 00000000..dd2b73da --- /dev/null +++ b/tests/semantic/methods6.cl @@ -0,0 +1,27 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int, w: Int, z: Int): Int { v + w + z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/methods6_error.txt b/tests/semantic/methods6_error.txt new file mode 100644 index 00000000..6a3c2db9 --- /dev/null +++ b/tests/semantic/methods6_error.txt @@ -0,0 +1,2 @@ +methods6.cl:22: Incompatible number of formal parameters in redefined method g. +Compilation halted due to static semantic errors. From 0fd6d4ed641a2e995f662017f5f2221968722b27 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Mon, 26 Oct 2020 18:15:26 -0400 Subject: [PATCH 331/435] Add new tests --- tests/semantic/assignment1.cl | 7 +++++++ tests/semantic/assignment1_error.txt | 2 ++ tests/semantic/assignment2.cl | 13 +++++++++++++ tests/semantic/assignment2_error.txt | 2 ++ tests/semantic/assignment3.cl | 14 ++++++++++++++ tests/semantic/assignment3_error.txt | 2 ++ tests/semantic/self1.cl | 11 +++++++++++ tests/semantic/self1_error.txt | 3 +++ tests/semantic/self2.cl | 10 ++++++++++ tests/semantic/self2_error.txt | 2 ++ tests/semantic/self3.cl | 10 ++++++++++ tests/semantic/self3_error.txt | 2 ++ tests/semantic/self4.cl | 10 ++++++++++ tests/semantic/self4_error.txt | 2 ++ 14 files changed, 90 insertions(+) create mode 100644 tests/semantic/assignment1.cl create mode 100644 tests/semantic/assignment1_error.txt create mode 100644 tests/semantic/assignment2.cl create mode 100644 tests/semantic/assignment2_error.txt create mode 100644 tests/semantic/assignment3.cl create mode 100644 tests/semantic/assignment3_error.txt create mode 100644 tests/semantic/self1.cl create mode 100644 tests/semantic/self1_error.txt create mode 100644 tests/semantic/self2.cl create mode 100644 tests/semantic/self2_error.txt create mode 100644 tests/semantic/self3.cl create mode 100644 tests/semantic/self3_error.txt create mode 100644 tests/semantic/self4.cl create mode 100644 tests/semantic/self4_error.txt diff --git a/tests/semantic/assignment1.cl b/tests/semantic/assignment1.cl new file mode 100644 index 00000000..19ab7021 --- /dev/null +++ b/tests/semantic/assignment1.cl @@ -0,0 +1,7 @@ +--The static type of the expression must conform to the declared type of the identifier + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- "String"; +}; diff --git a/tests/semantic/assignment1_error.txt b/tests/semantic/assignment1_error.txt new file mode 100644 index 00000000..ed6e1492 --- /dev/null +++ b/tests/semantic/assignment1_error.txt @@ -0,0 +1,2 @@ +assignment1.cl:6: Inferred type String of initialization of attribute test does not conform to declared type Int. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/assignment2.cl b/tests/semantic/assignment2.cl new file mode 100644 index 00000000..cace221a --- /dev/null +++ b/tests/semantic/assignment2.cl @@ -0,0 +1,13 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A): B { a <- new C }; + test2(a: A): D { a <- new C }; +}; diff --git a/tests/semantic/assignment2_error.txt b/tests/semantic/assignment2_error.txt new file mode 100644 index 00000000..1c38bb43 --- /dev/null +++ b/tests/semantic/assignment2_error.txt @@ -0,0 +1,2 @@ +assignment2.cl:12: Inferred return type C of method test2 does not conform to declared return type D. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/assignment3.cl b/tests/semantic/assignment3.cl new file mode 100644 index 00000000..eba0d69e --- /dev/null +++ b/tests/semantic/assignment3.cl @@ -0,0 +1,14 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A; + b: B <- a <- new C; + d: D <- a <- new C; +}; diff --git a/tests/semantic/assignment3_error.txt b/tests/semantic/assignment3_error.txt new file mode 100644 index 00000000..a87aef54 --- /dev/null +++ b/tests/semantic/assignment3_error.txt @@ -0,0 +1,2 @@ +assignment3.cl:13: Inferred type C of initialization of attribute d does not conform to declared type D. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/self1.cl b/tests/semantic/self1.cl new file mode 100644 index 00000000..3387fd26 --- /dev/null +++ b/tests/semantic/self1.cl @@ -0,0 +1,11 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: Main): IO { self <- a }; +}; diff --git a/tests/semantic/self1_error.txt b/tests/semantic/self1_error.txt new file mode 100644 index 00000000..bf85479c --- /dev/null +++ b/tests/semantic/self1_error.txt @@ -0,0 +1,3 @@ +self1.cl:10: Cannot assign to 'self'. +self1.cl:10: Type Main of assigned expression does not conform to declared type SELF_TYPE of identifier self. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/self2.cl b/tests/semantic/self2.cl new file mode 100644 index 00000000..2e6921a9 --- /dev/null +++ b/tests/semantic/self2.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(): IO { let self: Main <- new Main in self }; +}; diff --git a/tests/semantic/self2_error.txt b/tests/semantic/self2_error.txt new file mode 100644 index 00000000..5a355e34 --- /dev/null +++ b/tests/semantic/self2_error.txt @@ -0,0 +1,2 @@ +self2.cl:9: 'self' cannot be bound in a 'let' expression. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/self3.cl b/tests/semantic/self3.cl new file mode 100644 index 00000000..81709b4b --- /dev/null +++ b/tests/semantic/self3.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(self: IO): IO { self }; +}; diff --git a/tests/semantic/self3_error.txt b/tests/semantic/self3_error.txt new file mode 100644 index 00000000..e0f578cc --- /dev/null +++ b/tests/semantic/self3_error.txt @@ -0,0 +1,2 @@ +self3.cl:9: 'self' cannot be the name of a formal parameter. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/self4.cl b/tests/semantic/self4.cl new file mode 100644 index 00000000..7c2b960c --- /dev/null +++ b/tests/semantic/self4.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + self: IO <- self; +}; \ No newline at end of file diff --git a/tests/semantic/self4_error.txt b/tests/semantic/self4_error.txt new file mode 100644 index 00000000..ec0ba80d --- /dev/null +++ b/tests/semantic/self4_error.txt @@ -0,0 +1,2 @@ +elf4.cl:9: 'self' cannot be the name of an attribute. +Compilation halted due to static semantic errors. From 1e2cb2e3f1324f41679cb39aebddda0f3be41afa Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 16:06:47 -0400 Subject: [PATCH 332/435] Add dispatch tests --- tests/semantic/dispatch1.cl | 33 +++++++++++++++++++++++++++ tests/semantic/dispatch1_error.txt | 3 +++ tests/semantic/dispatch2.cl | 34 ++++++++++++++++++++++++++++ tests/semantic/dispatch2_error.txt | 2 ++ tests/semantic/dispatch3.cl | 36 ++++++++++++++++++++++++++++++ tests/semantic/dispatch3_error.txt | 2 ++ tests/semantic/dispatch4.cl | 36 ++++++++++++++++++++++++++++++ tests/semantic/dispatch4_error.txt | 2 ++ tests/semantic/dispatch5.cl | 31 +++++++++++++++++++++++++ tests/semantic/dispatch5_error.txt | 3 +++ tests/semantic/dispatch6.cl | 32 ++++++++++++++++++++++++++ tests/semantic/dispatch6_error.txt | 3 +++ 12 files changed, 217 insertions(+) create mode 100644 tests/semantic/dispatch1.cl create mode 100644 tests/semantic/dispatch1_error.txt create mode 100644 tests/semantic/dispatch2.cl create mode 100644 tests/semantic/dispatch2_error.txt create mode 100644 tests/semantic/dispatch3.cl create mode 100644 tests/semantic/dispatch3_error.txt create mode 100644 tests/semantic/dispatch4.cl create mode 100644 tests/semantic/dispatch4_error.txt create mode 100644 tests/semantic/dispatch5.cl create mode 100644 tests/semantic/dispatch5_error.txt create mode 100644 tests/semantic/dispatch6.cl create mode 100644 tests/semantic/dispatch6_error.txt diff --git a/tests/semantic/dispatch1.cl b/tests/semantic/dispatch1.cl new file mode 100644 index 00000000..1c0457fa --- /dev/null +++ b/tests/semantic/dispatch1.cl @@ -0,0 +1,33 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.back("Hello ").back("World!"); +}; \ No newline at end of file diff --git a/tests/semantic/dispatch1_error.txt b/tests/semantic/dispatch1_error.txt new file mode 100644 index 00000000..847a21e7 --- /dev/null +++ b/tests/semantic/dispatch1_error.txt @@ -0,0 +1,3 @@ +dispatch1.cl:32: Dispatch to undefined method back. +dispatch1.cl:32: Inferred type Object of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/dispatch2.cl b/tests/semantic/dispatch2.cl new file mode 100644 index 00000000..5182912b --- /dev/null +++ b/tests/semantic/dispatch2.cl @@ -0,0 +1,34 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the dispatch and the definition of f must have the same number of arguments +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- new D.back("Hello ").g(2, 2); +}; \ No newline at end of file diff --git a/tests/semantic/dispatch2_error.txt b/tests/semantic/dispatch2_error.txt new file mode 100644 index 00000000..28469acd --- /dev/null +++ b/tests/semantic/dispatch2_error.txt @@ -0,0 +1,2 @@ +dispatch2.cl:33: Method g called with wrong number of arguments. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/dispatch3.cl b/tests/semantic/dispatch3.cl new file mode 100644 index 00000000..ecb1535d --- /dev/null +++ b/tests/semantic/dispatch3.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the static type of the ith actual parameter must conform to the declared type of the ith formal parameter. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.alphabet(new D, new D, new D.back("Hello ")).back("World!"); +}; \ No newline at end of file diff --git a/tests/semantic/dispatch3_error.txt b/tests/semantic/dispatch3_error.txt new file mode 100644 index 00000000..8d89cf0d --- /dev/null +++ b/tests/semantic/dispatch3_error.txt @@ -0,0 +1,2 @@ +dispatch3.cl:35: In call of method alphabet, type B of parameter c does not conform to declared type C. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/dispatch4.cl b/tests/semantic/dispatch4.cl new file mode 100644 index 00000000..9cadd833 --- /dev/null +++ b/tests/semantic/dispatch4.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +If f has return type B and B is a class name, then the static type of the dispatch is B. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: D <- new D.alphabet(new D, new D.back("Hello "), new C).back("World!"); +}; \ No newline at end of file diff --git a/tests/semantic/dispatch4_error.txt b/tests/semantic/dispatch4_error.txt new file mode 100644 index 00000000..b019ee5f --- /dev/null +++ b/tests/semantic/dispatch4_error.txt @@ -0,0 +1,2 @@ +dispatch4.cl:35: Inferred type B of initialization of attribute test does not conform to declared type D. +Compilation halted due to static semantic errors. \ No newline at end of file diff --git a/tests/semantic/dispatch5.cl b/tests/semantic/dispatch5.cl new file mode 100644 index 00000000..b4437b1b --- /dev/null +++ b/tests/semantic/dispatch5.cl @@ -0,0 +1,31 @@ +(* +(,...,) is shorthand for self.(,...,). +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + + back(s: String): B { { + out_string(s); + g(2); + sum(1, 2, 3); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/dispatch5_error.txt b/tests/semantic/dispatch5_error.txt new file mode 100644 index 00000000..4dd096aa --- /dev/null +++ b/tests/semantic/dispatch5_error.txt @@ -0,0 +1,3 @@ +dispatch5.cl:24: Dispatch to undefined method sum. +Compilation halted due to static semantic errors. + diff --git a/tests/semantic/dispatch6.cl b/tests/semantic/dispatch6.cl new file mode 100644 index 00000000..fcc033f2 --- /dev/null +++ b/tests/semantic/dispatch6.cl @@ -0,0 +1,32 @@ +(* +e@B.f() invokes the method +f in class B on the object that is the value of e. For this form of dispatch, the static type to the left of +“@”must conform to the type specified to the right of “@”. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + sum(v: Int, w: Int, z: Int): Int { v - w - z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- new D; + b: Int <- new D@B.sum(1, 2, 3); + test: Int <- a@B.sum(1, 2, 3); +}; diff --git a/tests/semantic/dispatch6_error.txt b/tests/semantic/dispatch6_error.txt new file mode 100644 index 00000000..155015b7 --- /dev/null +++ b/tests/semantic/dispatch6_error.txt @@ -0,0 +1,3 @@ +dispatch6.cl:31: Expression type A does not conform to declared static dispatch type B. +dispatch6.cl:31: Inferred type Object of initialization of attribute test does not conform to declared type Int. +Compilation halted due to static semantic errors. From b2508fdd4ae06caa5e976b55d543c214d62361e6 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 16:32:56 -0400 Subject: [PATCH 333/435] Add conditionals tests --- tests/semantic/conditionals1.cl | 14 ++++++++++++++ tests/semantic/conditionals1_error.txt | 2 ++ tests/semantic/conditionals2.cl | 24 ++++++++++++++++++++++++ tests/semantic/conditionals2_error.txt | 3 +++ 4 files changed, 43 insertions(+) create mode 100644 tests/semantic/conditionals1.cl create mode 100644 tests/semantic/conditionals1_error.txt create mode 100644 tests/semantic/conditionals2.cl create mode 100644 tests/semantic/conditionals2_error.txt diff --git a/tests/semantic/conditionals1.cl b/tests/semantic/conditionals1.cl new file mode 100644 index 00000000..3446a8b0 --- /dev/null +++ b/tests/semantic/conditionals1.cl @@ -0,0 +1,14 @@ +--The predicate must have static type Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- if new F then new D else new C fi; +}; \ No newline at end of file diff --git a/tests/semantic/conditionals1_error.txt b/tests/semantic/conditionals1_error.txt new file mode 100644 index 00000000..cb1a36de --- /dev/null +++ b/tests/semantic/conditionals1_error.txt @@ -0,0 +1,2 @@ +conditionals1.cl:13: Predicate of 'if' does not have type Bool. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/conditionals2.cl b/tests/semantic/conditionals2.cl new file mode 100644 index 00000000..9d6313d7 --- /dev/null +++ b/tests/semantic/conditionals2.cl @@ -0,0 +1,24 @@ +(* +Let T and F be the static types of the branches of the conditional. Then the static type of the +conditional is T t F. (think: Walk towards Object from each of T and F until the paths meet.) +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if true then + new C + else + if false then new D + else new E fi + fi; + + test: B <- if not true then new F else new E fi; +}; diff --git a/tests/semantic/conditionals2_error.txt b/tests/semantic/conditionals2_error.txt new file mode 100644 index 00000000..2ebc5c0d --- /dev/null +++ b/tests/semantic/conditionals2_error.txt @@ -0,0 +1,3 @@ +conditionals2.cl:23: Inferred type A of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. + From b5c8a96c9a9227188e0852ecc060ca10e9098df7 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 16:53:13 -0400 Subject: [PATCH 334/435] Add loops test --- tests/semantic/loops1.cl | 8 ++++++++ tests/semantic/loops1_error.txt | 2 ++ tests/semantic/loops2.cl | 9 +++++++++ tests/semantic/loops2_error.txt | 2 ++ 4 files changed, 21 insertions(+) create mode 100644 tests/semantic/loops1.cl create mode 100644 tests/semantic/loops1_error.txt create mode 100644 tests/semantic/loops2.cl create mode 100644 tests/semantic/loops2_error.txt diff --git a/tests/semantic/loops1.cl b/tests/semantic/loops1.cl new file mode 100644 index 00000000..de3a624d --- /dev/null +++ b/tests/semantic/loops1.cl @@ -0,0 +1,8 @@ +--The predicate must have static type Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while "true" loop i <- i + 1 pool; +}; \ No newline at end of file diff --git a/tests/semantic/loops1_error.txt b/tests/semantic/loops1_error.txt new file mode 100644 index 00000000..7f729e0c --- /dev/null +++ b/tests/semantic/loops1_error.txt @@ -0,0 +1,2 @@ +loops1.cl:7: Loop condition does not have type Bool. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/loops2.cl b/tests/semantic/loops2.cl new file mode 100644 index 00000000..dea69fa1 --- /dev/null +++ b/tests/semantic/loops2.cl @@ -0,0 +1,9 @@ +--The static type of a loop expression is Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while not false loop i <- i + 1 pool; + test2: Int <- while not false loop i <- i + 1 pool; +}; diff --git a/tests/semantic/loops2_error.txt b/tests/semantic/loops2_error.txt new file mode 100644 index 00000000..1c28fd76 --- /dev/null +++ b/tests/semantic/loops2_error.txt @@ -0,0 +1,2 @@ +loops2.cl:8: Inferred type Object of initialization of attribute test2 does not conform to declared type Int. +Compilation halted due to static semantic errors. From b24b4287534bb7c633aa9507bfe1e0ab143d71d7 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 17:04:51 -0400 Subject: [PATCH 335/435] Add blocks tests --- tests/semantic/blocks1.cl | 31 +++++++++++++++++++++++++++++++ tests/semantic/blocks1_error.txt | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 tests/semantic/blocks1.cl create mode 100644 tests/semantic/blocks1_error.txt diff --git a/tests/semantic/blocks1.cl b/tests/semantic/blocks1.cl new file mode 100644 index 00000000..1e928908 --- /dev/null +++ b/tests/semantic/blocks1.cl @@ -0,0 +1,31 @@ +--The static type of a block is the static type of the last expression. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- { + new A; + { + new B; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/tests/semantic/blocks1_error.txt b/tests/semantic/blocks1_error.txt new file mode 100644 index 00000000..9aa57fa7 --- /dev/null +++ b/tests/semantic/blocks1_error.txt @@ -0,0 +1,2 @@ +blocks1.cl:13: Inferred type F of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. From 0cd7cd3e2ec360017772de38c4e48d1daa8c6eb8 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 17:18:40 -0400 Subject: [PATCH 336/435] Add let tests --- tests/semantic/let1.cl | 15 +++++++++++++++ tests/semantic/let1_error.txt | 2 ++ tests/semantic/let2.cl | 15 +++++++++++++++ tests/semantic/let2_error.txt | 2 ++ 4 files changed, 34 insertions(+) create mode 100644 tests/semantic/let1.cl create mode 100644 tests/semantic/let1_error.txt create mode 100644 tests/semantic/let2.cl create mode 100644 tests/semantic/let2_error.txt diff --git a/tests/semantic/let1.cl b/tests/semantic/let1.cl new file mode 100644 index 00000000..26ef6302 --- /dev/null +++ b/tests/semantic/let1.cl @@ -0,0 +1,15 @@ +--The type of an initialization expression must conform to the declared type of the identifier. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: C <- new E in b; +}; \ No newline at end of file diff --git a/tests/semantic/let1_error.txt b/tests/semantic/let1_error.txt new file mode 100644 index 00000000..4ea1cd1e --- /dev/null +++ b/tests/semantic/let1_error.txt @@ -0,0 +1,2 @@ +let1.cl:14: Inferred type E of initialization of b does not conform to identifier's declared type C. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/let2.cl b/tests/semantic/let2.cl new file mode 100644 index 00000000..c5956ead --- /dev/null +++ b/tests/semantic/let2.cl @@ -0,0 +1,15 @@ +--The type of let is the type of the body. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: A <- new E in b; +}; \ No newline at end of file diff --git a/tests/semantic/let2_error.txt b/tests/semantic/let2_error.txt new file mode 100644 index 00000000..5d82f85f --- /dev/null +++ b/tests/semantic/let2_error.txt @@ -0,0 +1,2 @@ +let2.cl:14: Inferred type A of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. From 378ac6e2c4f3d4d8497171f4238816c9309770bc Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 17:38:34 -0400 Subject: [PATCH 337/435] Add case tests --- tests/semantic/case1.cl | 23 +++++++++++++++++++++++ tests/semantic/case1_error.txt | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 tests/semantic/case1.cl create mode 100644 tests/semantic/case1_error.txt diff --git a/tests/semantic/case1.cl b/tests/semantic/case1.cl new file mode 100644 index 00000000..82c6a4d6 --- /dev/null +++ b/tests/semantic/case1.cl @@ -0,0 +1,23 @@ +--For each branch, let Ti be the static type of . The static type of a case expression is Join 1≤i≤n Ti. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: B <- case 0 of + b: Bool => new F; + i: Int => new E; + esac; +}; diff --git a/tests/semantic/case1_error.txt b/tests/semantic/case1_error.txt new file mode 100644 index 00000000..da077812 --- /dev/null +++ b/tests/semantic/case1_error.txt @@ -0,0 +1,2 @@ +case1.cl:19: Inferred type A of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. From 55568e261971ded53239edfc09560ba084bd36b6 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 17:47:09 -0400 Subject: [PATCH 338/435] Add isvoid tests --- tests/semantic/isvoid1.cl | 26 ++++++++++++++++++++++++++ tests/semantic/isvoid1_error.txt | 2 ++ 2 files changed, 28 insertions(+) create mode 100644 tests/semantic/isvoid1.cl create mode 100644 tests/semantic/isvoid1_error.txt diff --git a/tests/semantic/isvoid1.cl b/tests/semantic/isvoid1.cl new file mode 100644 index 00000000..072720d8 --- /dev/null +++ b/tests/semantic/isvoid1.cl @@ -0,0 +1,26 @@ +--evaluates to true if expr is void and evaluates to false if expr is not void. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if isvoid new F then + new C + else + if false then new D + else new E fi + fi; + + test: B <- isvoid if isvoid new F then + new C + else + if false then new D + else new E fi + fi; +}; \ No newline at end of file diff --git a/tests/semantic/isvoid1_error.txt b/tests/semantic/isvoid1_error.txt new file mode 100644 index 00000000..102029c6 --- /dev/null +++ b/tests/semantic/isvoid1_error.txt @@ -0,0 +1,2 @@ +isvoid1.cl:20: Inferred type Bool of initialization of attribute test does not conform to declared type B. +Compilation halted due to static semantic errors. From 99705358a4765f57d6b4c60efe50269bc2baa439 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 18:22:21 -0400 Subject: [PATCH 339/435] Add aritmetics tests --- tests/semantic/arithmetic1.cl | 11 +++++++++++ tests/semantic/arithmetic1_error.txt | 2 ++ tests/semantic/arithmetic2.cl | 11 +++++++++++ tests/semantic/arithmetic2_error.txt | 2 ++ tests/semantic/arithmetic3.cl | 11 +++++++++++ tests/semantic/arithmetic3_error.txt | 2 ++ tests/semantic/arithmetic4.cl | 11 +++++++++++ tests/semantic/arithmetic4_error.txt | 2 ++ tests/semantic/arithmetic5.cl | 11 +++++++++++ tests/semantic/arithmetic5_error.txt | 2 ++ tests/semantic/arithmetic6.cl | 11 +++++++++++ tests/semantic/arithmetic6_error.txt | 2 ++ tests/semantic/arithmetic7.cl | 12 ++++++++++++ tests/semantic/arithmetic7_error.txt | 2 ++ tests/semantic/arithmetic8.cl | 13 +++++++++++++ tests/semantic/arithmetic8_error.txt | 2 ++ 16 files changed, 107 insertions(+) create mode 100644 tests/semantic/arithmetic1.cl create mode 100644 tests/semantic/arithmetic1_error.txt create mode 100644 tests/semantic/arithmetic2.cl create mode 100644 tests/semantic/arithmetic2_error.txt create mode 100644 tests/semantic/arithmetic3.cl create mode 100644 tests/semantic/arithmetic3_error.txt create mode 100644 tests/semantic/arithmetic4.cl create mode 100644 tests/semantic/arithmetic4_error.txt create mode 100644 tests/semantic/arithmetic5.cl create mode 100644 tests/semantic/arithmetic5_error.txt create mode 100644 tests/semantic/arithmetic6.cl create mode 100644 tests/semantic/arithmetic6_error.txt create mode 100644 tests/semantic/arithmetic7.cl create mode 100644 tests/semantic/arithmetic7_error.txt create mode 100644 tests/semantic/arithmetic8.cl create mode 100644 tests/semantic/arithmetic8_error.txt diff --git a/tests/semantic/arithmetic1.cl b/tests/semantic/arithmetic1.cl new file mode 100644 index 00000000..bf94eb19 --- /dev/null +++ b/tests/semantic/arithmetic1.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 * 2 / 3 - 4 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x + new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic1_error.txt b/tests/semantic/arithmetic1_error.txt new file mode 100644 index 00000000..23e05e4d --- /dev/null +++ b/tests/semantic/arithmetic1_error.txt @@ -0,0 +1,2 @@ +arithmetic1.cl:10: non-Int arguments: Int + String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic2.cl b/tests/semantic/arithmetic2.cl new file mode 100644 index 00000000..59532573 --- /dev/null +++ b/tests/semantic/arithmetic2.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 + 2 * 3 / 4 - new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x - new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic2_error.txt b/tests/semantic/arithmetic2_error.txt new file mode 100644 index 00000000..7cc386e5 --- /dev/null +++ b/tests/semantic/arithmetic2_error.txt @@ -0,0 +1,2 @@ +arithmetic2.cl:10: non-Int arguments: Int - String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic3.cl b/tests/semantic/arithmetic3.cl new file mode 100644 index 00000000..b208957f --- /dev/null +++ b/tests/semantic/arithmetic3.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 - 2 + 3 * 4 / new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x / new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic3_error.txt b/tests/semantic/arithmetic3_error.txt new file mode 100644 index 00000000..1f509371 --- /dev/null +++ b/tests/semantic/arithmetic3_error.txt @@ -0,0 +1,2 @@ +arithmetic3.cl:10: non-Int arguments: Int / String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic4.cl b/tests/semantic/arithmetic4.cl new file mode 100644 index 00000000..2c7dd4fc --- /dev/null +++ b/tests/semantic/arithmetic4.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic4_error.txt b/tests/semantic/arithmetic4_error.txt new file mode 100644 index 00000000..dc482aa5 --- /dev/null +++ b/tests/semantic/arithmetic4_error.txt @@ -0,0 +1,2 @@ +arithmetic4.cl:10: non-Int arguments: Int * String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic5.cl b/tests/semantic/arithmetic5.cl new file mode 100644 index 00000000..bc08c6e8 --- /dev/null +++ b/tests/semantic/arithmetic5.cl @@ -0,0 +1,11 @@ +--The static type of the expression is Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic5_error.txt b/tests/semantic/arithmetic5_error.txt new file mode 100644 index 00000000..f4be8904 --- /dev/null +++ b/tests/semantic/arithmetic5_error.txt @@ -0,0 +1,2 @@ +arithmetic5.cl:9: Inferred type Int of initialization of attribute test does not conform to declared type Bool. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic6.cl b/tests/semantic/arithmetic6.cl new file mode 100644 index 00000000..a0c3d03f --- /dev/null +++ b/tests/semantic/arithmetic6.cl @@ -0,0 +1,11 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; diff --git a/tests/semantic/arithmetic6_error.txt b/tests/semantic/arithmetic6_error.txt new file mode 100644 index 00000000..d8950f8e --- /dev/null +++ b/tests/semantic/arithmetic6_error.txt @@ -0,0 +1,2 @@ +arithmetic6.cl:10: non-Int arguments: Int <= String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic7.cl b/tests/semantic/arithmetic7.cl new file mode 100644 index 00000000..c00c75cd --- /dev/null +++ b/tests/semantic/arithmetic7.cl @@ -0,0 +1,12 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; + diff --git a/tests/semantic/arithmetic7_error.txt b/tests/semantic/arithmetic7_error.txt new file mode 100644 index 00000000..651fa4d2 --- /dev/null +++ b/tests/semantic/arithmetic7_error.txt @@ -0,0 +1,2 @@ +arithmetic7.cl:10: non-Int arguments: Int < String +Compilation halted due to static semantic errors. diff --git a/tests/semantic/arithmetic8.cl b/tests/semantic/arithmetic8.cl new file mode 100644 index 00000000..3210bdb8 --- /dev/null +++ b/tests/semantic/arithmetic8.cl @@ -0,0 +1,13 @@ + --The rules are exactly the same as for the binary arithmetic operations, except that the result is a Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; + + diff --git a/tests/semantic/arithmetic8_error.txt b/tests/semantic/arithmetic8_error.txt new file mode 100644 index 00000000..c05a0871 --- /dev/null +++ b/tests/semantic/arithmetic8_error.txt @@ -0,0 +1,2 @@ +arithmetic8.cl:9: Inferred type Bool of initialization of attribute test does not conform to declared type Int. +Compilation halted due to static semantic errors. From 293816e879005258c3f8c20e2038cadad21f1388 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Tue, 27 Oct 2020 18:39:24 -0400 Subject: [PATCH 340/435] Add equility tests --- tests/semantic/eq1.cl | 17 +++++++++++++++++ tests/semantic/eq1_error.txt | 2 ++ tests/semantic/eq2.cl | 17 +++++++++++++++++ tests/semantic/eq2_error.txt | 2 ++ tests/semantic/eq3.cl | 17 +++++++++++++++++ tests/semantic/eq3_error.txt | 2 ++ tests/semantic/eq4.cl | 17 +++++++++++++++++ tests/semantic/eq4_error.txt | 2 ++ 8 files changed, 76 insertions(+) create mode 100644 tests/semantic/eq1.cl create mode 100644 tests/semantic/eq1_error.txt create mode 100644 tests/semantic/eq2.cl create mode 100644 tests/semantic/eq2_error.txt create mode 100644 tests/semantic/eq3.cl create mode 100644 tests/semantic/eq3_error.txt create mode 100644 tests/semantic/eq4.cl create mode 100644 tests/semantic/eq4_error.txt diff --git a/tests/semantic/eq1.cl b/tests/semantic/eq1.cl new file mode 100644 index 00000000..88f2a7ff --- /dev/null +++ b/tests/semantic/eq1.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + test: Bool <- 1 = new A; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; +}; \ No newline at end of file diff --git a/tests/semantic/eq1_error.txt b/tests/semantic/eq1_error.txt new file mode 100644 index 00000000..bbc8ab78 --- /dev/null +++ b/tests/semantic/eq1_error.txt @@ -0,0 +1,2 @@ +eq1.cl:14: Illegal comparison with a basic type. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/eq2.cl b/tests/semantic/eq2.cl new file mode 100644 index 00000000..d7685278 --- /dev/null +++ b/tests/semantic/eq2.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + test: Bool <- "1" = new B; + z: Bool <- true = not false; +}; diff --git a/tests/semantic/eq2_error.txt b/tests/semantic/eq2_error.txt new file mode 100644 index 00000000..74c1d66a --- /dev/null +++ b/tests/semantic/eq2_error.txt @@ -0,0 +1,2 @@ +eq2.cl:15: Illegal comparison with a basic type. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/eq3.cl b/tests/semantic/eq3.cl new file mode 100644 index 00000000..4dad693e --- /dev/null +++ b/tests/semantic/eq3.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; + test: Bool <- "true" = not false; +}; diff --git a/tests/semantic/eq3_error.txt b/tests/semantic/eq3_error.txt new file mode 100644 index 00000000..ec1051bd --- /dev/null +++ b/tests/semantic/eq3_error.txt @@ -0,0 +1,2 @@ +eq3.cl:16: Illegal comparison with a basic type. +Compilation halted due to static semantic errors. diff --git a/tests/semantic/eq4.cl b/tests/semantic/eq4.cl new file mode 100644 index 00000000..11afc119 --- /dev/null +++ b/tests/semantic/eq4.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. The result is a Bool. +*) + +class A { }; +class B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- new A = new B; + test: Int <- new A = new B; +}; diff --git a/tests/semantic/eq4_error.txt b/tests/semantic/eq4_error.txt new file mode 100644 index 00000000..47aeb7c3 --- /dev/null +++ b/tests/semantic/eq4_error.txt @@ -0,0 +1,2 @@ +eq4.cl:16: Inferred type Bool of initialization of attribute test does not conform to declared type Int. +Compilation halted due to static semantic errors. From 0a1ee3795314b7804fff7151d5287aaa7478febd Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Wed, 28 Oct 2020 16:50:40 -0400 Subject: [PATCH 341/435] Format all semantic errors --- tests/semantic/arithmetic1_error.txt | 3 +-- tests/semantic/arithmetic2_error.txt | 3 +-- tests/semantic/arithmetic3_error.txt | 3 +-- tests/semantic/arithmetic4_error.txt | 3 +-- tests/semantic/arithmetic5_error.txt | 3 +-- tests/semantic/arithmetic6_error.txt | 3 +-- tests/semantic/arithmetic7_error.txt | 3 +-- tests/semantic/arithmetic8_error.txt | 3 +-- tests/semantic/assignment1_error.txt | 3 +-- tests/semantic/assignment2_error.txt | 3 +-- tests/semantic/assignment3_error.txt | 3 +-- tests/semantic/attributes1_error.txt | 3 +-- tests/semantic/attributes2_error.txt | 3 +-- tests/semantic/attributes3_error.txt | 4 +--- tests/semantic/attributes4_error.txt | 4 +--- tests/semantic/blocks1_error.txt | 3 +-- tests/semantic/case1_error.txt | 3 +-- tests/semantic/conditionals1_error.txt | 3 +-- tests/semantic/conditionals2_error.txt | 3 +-- tests/semantic/dispatch1_error.txt | 4 +--- tests/semantic/dispatch2_error.txt | 3 +-- tests/semantic/dispatch3_error.txt | 3 +-- tests/semantic/dispatch4_error.txt | 3 +-- tests/semantic/dispatch5_error.txt | 4 +--- tests/semantic/dispatch6_error.txt | 4 +--- tests/semantic/eq1_error.txt | 3 +-- tests/semantic/eq2_error.txt | 3 +-- tests/semantic/eq3_error.txt | 3 +-- tests/semantic/eq4_error.txt | 3 +-- tests/semantic/features1_error.txt | 3 +-- tests/semantic/features2_error.txt | 3 +-- tests/semantic/inheritance1_error.txt | 3 +-- tests/semantic/inheritance2_error.txt | 3 +-- tests/semantic/inheritance3_error.txt | 3 +-- tests/semantic/inheritance4_error.txt | 4 +--- tests/semantic/inheritance5_error.txt | 5 +---- tests/semantic/isvoid1_error.txt | 3 +-- tests/semantic/let1_error.txt | 3 +-- tests/semantic/let2_error.txt | 3 +-- tests/semantic/loops1_error.txt | 3 +-- tests/semantic/loops2_error.txt | 3 +-- tests/semantic/methods1_error.txt | 3 +-- tests/semantic/methods2_error.txt | 3 +-- tests/semantic/methods3_error.txt | 3 +-- tests/semantic/methods4_error.txt | 3 +-- tests/semantic/methods5_error.txt | 3 +-- tests/semantic/methods6_error.txt | 3 +-- tests/semantic/self1_error.txt | 4 +--- tests/semantic/self2_error.txt | 3 +-- tests/semantic/self3_error.txt | 3 +-- tests/semantic/self4_error.txt | 3 +-- 51 files changed, 51 insertions(+), 111 deletions(-) diff --git a/tests/semantic/arithmetic1_error.txt b/tests/semantic/arithmetic1_error.txt index 23e05e4d..a74ebf3d 100644 --- a/tests/semantic/arithmetic1_error.txt +++ b/tests/semantic/arithmetic1_error.txt @@ -1,2 +1 @@ -arithmetic1.cl:10: non-Int arguments: Int + String -Compilation halted due to static semantic errors. +(10, 27) - TypeError: non-Int arguments: Int + String diff --git a/tests/semantic/arithmetic2_error.txt b/tests/semantic/arithmetic2_error.txt index 7cc386e5..2c7952af 100644 --- a/tests/semantic/arithmetic2_error.txt +++ b/tests/semantic/arithmetic2_error.txt @@ -1,2 +1 @@ -arithmetic2.cl:10: non-Int arguments: Int - String -Compilation halted due to static semantic errors. +(10, 27) - TypeError: non-Int arguments: Int - String diff --git a/tests/semantic/arithmetic3_error.txt b/tests/semantic/arithmetic3_error.txt index 1f509371..81d88331 100644 --- a/tests/semantic/arithmetic3_error.txt +++ b/tests/semantic/arithmetic3_error.txt @@ -1,2 +1 @@ -arithmetic3.cl:10: non-Int arguments: Int / String -Compilation halted due to static semantic errors. +(10, 27) - TypeError: non-Int arguments: Int / String diff --git a/tests/semantic/arithmetic4_error.txt b/tests/semantic/arithmetic4_error.txt index dc482aa5..1ca6df02 100644 --- a/tests/semantic/arithmetic4_error.txt +++ b/tests/semantic/arithmetic4_error.txt @@ -1,2 +1 @@ -arithmetic4.cl:10: non-Int arguments: Int * String -Compilation halted due to static semantic errors. +(10, 27) - TypeError: non-Int arguments: Int * String \ No newline at end of file diff --git a/tests/semantic/arithmetic5_error.txt b/tests/semantic/arithmetic5_error.txt index f4be8904..dd534684 100644 --- a/tests/semantic/arithmetic5_error.txt +++ b/tests/semantic/arithmetic5_error.txt @@ -1,2 +1 @@ -arithmetic5.cl:9: Inferred type Int of initialization of attribute test does not conform to declared type Bool. -Compilation halted due to static semantic errors. +(9, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. diff --git a/tests/semantic/arithmetic6_error.txt b/tests/semantic/arithmetic6_error.txt index d8950f8e..2e43dfc1 100644 --- a/tests/semantic/arithmetic6_error.txt +++ b/tests/semantic/arithmetic6_error.txt @@ -1,2 +1 @@ -arithmetic6.cl:10: non-Int arguments: Int <= String -Compilation halted due to static semantic errors. +(10, 22) - TypeError: non-Int arguments: Int <= String diff --git a/tests/semantic/arithmetic7_error.txt b/tests/semantic/arithmetic7_error.txt index 651fa4d2..6f353711 100644 --- a/tests/semantic/arithmetic7_error.txt +++ b/tests/semantic/arithmetic7_error.txt @@ -1,2 +1 @@ -arithmetic7.cl:10: non-Int arguments: Int < String -Compilation halted due to static semantic errors. +(10, 22) - TypeError: non-Int arguments: Int < String diff --git a/tests/semantic/arithmetic8_error.txt b/tests/semantic/arithmetic8_error.txt index c05a0871..ebcaa379 100644 --- a/tests/semantic/arithmetic8_error.txt +++ b/tests/semantic/arithmetic8_error.txt @@ -1,2 +1 @@ -arithmetic8.cl:9: Inferred type Bool of initialization of attribute test does not conform to declared type Int. -Compilation halted due to static semantic errors. +(9, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/tests/semantic/assignment1_error.txt b/tests/semantic/assignment1_error.txt index ed6e1492..6eb88301 100644 --- a/tests/semantic/assignment1_error.txt +++ b/tests/semantic/assignment1_error.txt @@ -1,2 +1 @@ -assignment1.cl:6: Inferred type String of initialization of attribute test does not conform to declared type Int. -Compilation halted due to static semantic errors. +(6, 18) - TypeError: Inferred type String of initialization of attribute test does not conform to declared type Int. diff --git a/tests/semantic/assignment2_error.txt b/tests/semantic/assignment2_error.txt index 1c38bb43..ed10b7f3 100644 --- a/tests/semantic/assignment2_error.txt +++ b/tests/semantic/assignment2_error.txt @@ -1,2 +1 @@ -assignment2.cl:12: Inferred return type C of method test2 does not conform to declared return type D. -Compilation halted due to static semantic errors. +(12, 22) - TypeError: Inferred return type C of method test2 does not conform to declared return type D. diff --git a/tests/semantic/assignment3_error.txt b/tests/semantic/assignment3_error.txt index a87aef54..bc9a718c 100644 --- a/tests/semantic/assignment3_error.txt +++ b/tests/semantic/assignment3_error.txt @@ -1,2 +1 @@ -assignment3.cl:13: Inferred type C of initialization of attribute d does not conform to declared type D. -Compilation halted due to static semantic errors. \ No newline at end of file +(13, 13) - TypeError: Inferred type C of initialization of attribute d does not conform to declared type D. \ No newline at end of file diff --git a/tests/semantic/attributes1_error.txt b/tests/semantic/attributes1_error.txt index 31f9ae60..9cb8460c 100644 --- a/tests/semantic/attributes1_error.txt +++ b/tests/semantic/attributes1_error.txt @@ -1,2 +1 @@ -attributes1.cl:10: Inferred type A of initialization of attribute test2 does not conform to declared type B. -Compilation halted due to static semantic errors. +(10, 17) - TypeError: Inferred type A of initialization of attribute test2 does not conform to declared type B. diff --git a/tests/semantic/attributes2_error.txt b/tests/semantic/attributes2_error.txt index b9955d65..6d601b7c 100644 --- a/tests/semantic/attributes2_error.txt +++ b/tests/semantic/attributes2_error.txt @@ -1,2 +1 @@ -attributes2.cl:10: Inferred type D of initialization of attribute test2 does not conform to declared type C. -Compilation halted due to static semantic errors. +(10, 17) - TypeError: Inferred type D of initialization of attribute test2 does not conform to declared type C. diff --git a/tests/semantic/attributes3_error.txt b/tests/semantic/attributes3_error.txt index 7de7d436..6195c816 100644 --- a/tests/semantic/attributes3_error.txt +++ b/tests/semantic/attributes3_error.txt @@ -1,3 +1 @@ -attributes3.cl:9: Undeclared identifier b. -attributes3.cl:9: Predicate of 'if' does not have type Bool. -Compilation halted due to static semantic errors. +(9, 16) - NameError: Undeclared identifier b. diff --git a/tests/semantic/attributes4_error.txt b/tests/semantic/attributes4_error.txt index e567b7a2..fa5fcfa8 100644 --- a/tests/semantic/attributes4_error.txt +++ b/tests/semantic/attributes4_error.txt @@ -1,3 +1 @@ -attributes4.cl:32: Undeclared identifier d. -attributes4.cl:28: Inferred return type Object of method test2 does not conform to declared return type IO. -Compilation halted due to static semantic errors. +(32, 49) - NameError: Undeclared identifier d. \ No newline at end of file diff --git a/tests/semantic/blocks1_error.txt b/tests/semantic/blocks1_error.txt index 9aa57fa7..2f0e2caf 100644 --- a/tests/semantic/blocks1_error.txt +++ b/tests/semantic/blocks1_error.txt @@ -1,2 +1 @@ -blocks1.cl:13: Inferred type F of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(13, 16) - TypeError: Inferred type F of initialization of attribute test does not conform to declared type B. diff --git a/tests/semantic/case1_error.txt b/tests/semantic/case1_error.txt index da077812..f05ce31b 100644 --- a/tests/semantic/case1_error.txt +++ b/tests/semantic/case1_error.txt @@ -1,2 +1 @@ -case1.cl:19: Inferred type A of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(19, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/tests/semantic/conditionals1_error.txt b/tests/semantic/conditionals1_error.txt index cb1a36de..b8634535 100644 --- a/tests/semantic/conditionals1_error.txt +++ b/tests/semantic/conditionals1_error.txt @@ -1,2 +1 @@ -conditionals1.cl:13: Predicate of 'if' does not have type Bool. -Compilation halted due to static semantic errors. +(13, 16) - TypeError: Predicate of 'if' does not have type Bool. diff --git a/tests/semantic/conditionals2_error.txt b/tests/semantic/conditionals2_error.txt index 2ebc5c0d..d6f5fc30 100644 --- a/tests/semantic/conditionals2_error.txt +++ b/tests/semantic/conditionals2_error.txt @@ -1,3 +1,2 @@ -conditionals2.cl:23: Inferred type A of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(23, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/tests/semantic/dispatch1_error.txt b/tests/semantic/dispatch1_error.txt index 847a21e7..7fb22edc 100644 --- a/tests/semantic/dispatch1_error.txt +++ b/tests/semantic/dispatch1_error.txt @@ -1,3 +1 @@ -dispatch1.cl:32: Dispatch to undefined method back. -dispatch1.cl:32: Inferred type Object of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(32, 37) - AttributeError: Dispatch to undefined method back. diff --git a/tests/semantic/dispatch2_error.txt b/tests/semantic/dispatch2_error.txt index 28469acd..a86c3534 100644 --- a/tests/semantic/dispatch2_error.txt +++ b/tests/semantic/dispatch2_error.txt @@ -1,2 +1 @@ -dispatch2.cl:33: Method g called with wrong number of arguments. -Compilation halted due to static semantic errors. +(33, 39) - SemanticError: Method g called with wrong number of arguments. diff --git a/tests/semantic/dispatch3_error.txt b/tests/semantic/dispatch3_error.txt index 8d89cf0d..0def5cf0 100644 --- a/tests/semantic/dispatch3_error.txt +++ b/tests/semantic/dispatch3_error.txt @@ -1,2 +1 @@ -dispatch3.cl:35: In call of method alphabet, type B of parameter c does not conform to declared type C. -Compilation halted due to static semantic errors. +(35, 45) - TypeError: In call of method alphabet, type B of parameter c does not conform to declared type C. diff --git a/tests/semantic/dispatch4_error.txt b/tests/semantic/dispatch4_error.txt index b019ee5f..9699f166 100644 --- a/tests/semantic/dispatch4_error.txt +++ b/tests/semantic/dispatch4_error.txt @@ -1,2 +1 @@ -dispatch4.cl:35: Inferred type B of initialization of attribute test does not conform to declared type D. -Compilation halted due to static semantic errors. \ No newline at end of file +(35, 16) - TypeError: Inferred type B of initialization of attribute test does not conform to declared type D. \ No newline at end of file diff --git a/tests/semantic/dispatch5_error.txt b/tests/semantic/dispatch5_error.txt index 4dd096aa..d26bf34a 100644 --- a/tests/semantic/dispatch5_error.txt +++ b/tests/semantic/dispatch5_error.txt @@ -1,3 +1 @@ -dispatch5.cl:24: Dispatch to undefined method sum. -Compilation halted due to static semantic errors. - +(24, 9) - AttributeError: Dispatch to undefined method sum. diff --git a/tests/semantic/dispatch6_error.txt b/tests/semantic/dispatch6_error.txt index 155015b7..ae9184b2 100644 --- a/tests/semantic/dispatch6_error.txt +++ b/tests/semantic/dispatch6_error.txt @@ -1,3 +1 @@ -dispatch6.cl:31: Expression type A does not conform to declared static dispatch type B. -dispatch6.cl:31: Inferred type Object of initialization of attribute test does not conform to declared type Int. -Compilation halted due to static semantic errors. +(31, 18) - TypeError: Expression type A does not conform to declared static dispatch type B. diff --git a/tests/semantic/eq1_error.txt b/tests/semantic/eq1_error.txt index bbc8ab78..f8142568 100644 --- a/tests/semantic/eq1_error.txt +++ b/tests/semantic/eq1_error.txt @@ -1,2 +1 @@ -eq1.cl:14: Illegal comparison with a basic type. -Compilation halted due to static semantic errors. +(14, 21) - TypeError: Illegal comparison with a basic type. diff --git a/tests/semantic/eq2_error.txt b/tests/semantic/eq2_error.txt index 74c1d66a..a44ab0d5 100644 --- a/tests/semantic/eq2_error.txt +++ b/tests/semantic/eq2_error.txt @@ -1,2 +1 @@ -eq2.cl:15: Illegal comparison with a basic type. -Compilation halted due to static semantic errors. +(15, 23) - TypeError: Illegal comparison with a basic type. diff --git a/tests/semantic/eq3_error.txt b/tests/semantic/eq3_error.txt index ec1051bd..c4e27eb8 100644 --- a/tests/semantic/eq3_error.txt +++ b/tests/semantic/eq3_error.txt @@ -1,2 +1 @@ -eq3.cl:16: Illegal comparison with a basic type. -Compilation halted due to static semantic errors. +(16, 26) - TypeError: Illegal comparison with a basic type. diff --git a/tests/semantic/eq4_error.txt b/tests/semantic/eq4_error.txt index 47aeb7c3..3ead21d0 100644 --- a/tests/semantic/eq4_error.txt +++ b/tests/semantic/eq4_error.txt @@ -1,2 +1 @@ -eq4.cl:16: Inferred type Bool of initialization of attribute test does not conform to declared type Int. -Compilation halted due to static semantic errors. +(16, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/tests/semantic/features1_error.txt b/tests/semantic/features1_error.txt index 8534b6ca..40033e9b 100755 --- a/tests/semantic/features1_error.txt +++ b/tests/semantic/features1_error.txt @@ -1,2 +1 @@ -features1.cl:18: Attribute x is multiply defined in class. -Compilation halted due to static semantic errors. \ No newline at end of file +(18, 5) - SemanticError: Attribute x is multiply defined in class. \ No newline at end of file diff --git a/tests/semantic/features2_error.txt b/tests/semantic/features2_error.txt index 7a91695f..117e0604 100755 --- a/tests/semantic/features2_error.txt +++ b/tests/semantic/features2_error.txt @@ -1,2 +1 @@ -features2.cl:18: Method x is multiply defined. -Compilation halted due to static semantic errors. +(18, 5) - SemanticError: Method x is multiply defined. \ No newline at end of file diff --git a/tests/semantic/inheritance1_error.txt b/tests/semantic/inheritance1_error.txt index 1840980c..ec5b504e 100755 --- a/tests/semantic/inheritance1_error.txt +++ b/tests/semantic/inheritance1_error.txt @@ -1,2 +1 @@ -inheritance1.cl:16: Attribute x is an attribute of an inherited class. -Compilation halted due to static semantic errors. \ No newline at end of file +(16, 5) - SemanticError: Attribute x is an attribute of an inherited class. \ No newline at end of file diff --git a/tests/semantic/inheritance2_error.txt b/tests/semantic/inheritance2_error.txt index fed9ee58..1ec7669b 100755 --- a/tests/semantic/inheritance2_error.txt +++ b/tests/semantic/inheritance2_error.txt @@ -1,2 +1 @@ -inheritance2.cl:15: Class B inherits from an undefined class A. -Compilation halted due to static semantic errors. \ No newline at end of file +(15, 18) - TypeError: Class B inherits from an undefined class A. \ No newline at end of file diff --git a/tests/semantic/inheritance3_error.txt b/tests/semantic/inheritance3_error.txt index b6c973a6..d17ca7f4 100644 --- a/tests/semantic/inheritance3_error.txt +++ b/tests/semantic/inheritance3_error.txt @@ -1,2 +1 @@ -inheritance3.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. -Compilation halted due to static semantic errors. \ No newline at end of file +(9, 18) - SemanticError: Class A, or an ancestor of A, is involved in an inheritance cycle. \ No newline at end of file diff --git a/tests/semantic/inheritance4_error.txt b/tests/semantic/inheritance4_error.txt index d249a97d..b437ec66 100644 --- a/tests/semantic/inheritance4_error.txt +++ b/tests/semantic/inheritance4_error.txt @@ -1,3 +1 @@ -inheritance4.cl:15: Class B, or an ancestor of B, is involved in an inheritance cycle. -inheritance4.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. -Compilation halted due to static semantic errors. \ No newline at end of file +(15, 18) - SemanticError: Class B, or an ancestor of B, is involved in an inheritance cycle. \ No newline at end of file diff --git a/tests/semantic/inheritance5_error.txt b/tests/semantic/inheritance5_error.txt index d3a920f5..da72ba54 100644 --- a/tests/semantic/inheritance5_error.txt +++ b/tests/semantic/inheritance5_error.txt @@ -1,4 +1 @@ -inheritance5.cl:21: Class C, or an ancestor of C, is involved in an inheritance cycle. -inheritance5.cl:15: Class B, or an ancestor of B, is involved in an inheritance cycle. -inheritance5.cl:9: Class A, or an ancestor of A, is involved in an inheritance cycle. -Compilation halted due to static semantic errors. \ No newline at end of file +(21, 18) - SemanticError: Class C, or an ancestor of C, is involved in an inheritance cycle. \ No newline at end of file diff --git a/tests/semantic/isvoid1_error.txt b/tests/semantic/isvoid1_error.txt index 102029c6..0922de90 100644 --- a/tests/semantic/isvoid1_error.txt +++ b/tests/semantic/isvoid1_error.txt @@ -1,2 +1 @@ -isvoid1.cl:20: Inferred type Bool of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(20, 16) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type B. diff --git a/tests/semantic/let1_error.txt b/tests/semantic/let1_error.txt index 4ea1cd1e..16ecf780 100644 --- a/tests/semantic/let1_error.txt +++ b/tests/semantic/let1_error.txt @@ -1,2 +1 @@ -let1.cl:14: Inferred type E of initialization of b does not conform to identifier's declared type C. -Compilation halted due to static semantic errors. +(14, 76) - TypeError: Inferred type E of initialization of b does not conform to identifier's declared type C. diff --git a/tests/semantic/let2_error.txt b/tests/semantic/let2_error.txt index 5d82f85f..b1e8a365 100644 --- a/tests/semantic/let2_error.txt +++ b/tests/semantic/let2_error.txt @@ -1,2 +1 @@ -let2.cl:14: Inferred type A of initialization of attribute test does not conform to declared type B. -Compilation halted due to static semantic errors. +(14, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/tests/semantic/loops1_error.txt b/tests/semantic/loops1_error.txt index 7f729e0c..b160214b 100644 --- a/tests/semantic/loops1_error.txt +++ b/tests/semantic/loops1_error.txt @@ -1,2 +1 @@ -loops1.cl:7: Loop condition does not have type Bool. -Compilation halted due to static semantic errors. +(7, 27) - TypeError: Loop condition does not have type Bool. \ No newline at end of file diff --git a/tests/semantic/loops2_error.txt b/tests/semantic/loops2_error.txt index 1c28fd76..9711cdf6 100644 --- a/tests/semantic/loops2_error.txt +++ b/tests/semantic/loops2_error.txt @@ -1,2 +1 @@ -loops2.cl:8: Inferred type Object of initialization of attribute test2 does not conform to declared type Int. -Compilation halted due to static semantic errors. +(8, 19) - TypeError: Inferred type Object of initialization of attribute test2 does not conform to declared type Int. diff --git a/tests/semantic/methods1_error.txt b/tests/semantic/methods1_error.txt index 9eef7594..06ab88a9 100644 --- a/tests/semantic/methods1_error.txt +++ b/tests/semantic/methods1_error.txt @@ -1,2 +1 @@ -methods1.cl:11: Formal parameter a is multiply defined. -Compilation halted due to static semantic errors. +(11, 16) - SemanticError: Formal parameter a is multiply defined. diff --git a/tests/semantic/methods2_error.txt b/tests/semantic/methods2_error.txt index be015863..f7e4a330 100644 --- a/tests/semantic/methods2_error.txt +++ b/tests/semantic/methods2_error.txt @@ -1,2 +1 @@ -methods2.cl:11: Inferred return type D of method test does not conform to declared return type C. -Compilation halted due to static semantic errors. +(11, 27) - TypeError: Inferred return type D of method test does not conform to declared return type C. diff --git a/tests/semantic/methods3_error.txt b/tests/semantic/methods3_error.txt index b617d069..1165b759 100644 --- a/tests/semantic/methods3_error.txt +++ b/tests/semantic/methods3_error.txt @@ -1,2 +1 @@ -methods3.cl:13: Inferred return type B of method test2 does not conform to declared return type C. -Compilation halted due to static semantic errors. +(13, 22) - TypeError: Inferred return type B of method test2 does not conform to declared return type C. diff --git a/tests/semantic/methods4_error.txt b/tests/semantic/methods4_error.txt index 8ef739ff..9f1486de 100644 --- a/tests/semantic/methods4_error.txt +++ b/tests/semantic/methods4_error.txt @@ -1,2 +1 @@ -methods4.cl:12: In redefined method f, parameter type Object is different from original type Int -Compilation halted due to static semantic errors. +(12, 15) - SemanticError: In redefined method f, parameter type Object is different from original type Int. diff --git a/tests/semantic/methods5_error.txt b/tests/semantic/methods5_error.txt index b7c4c000..8b6bdf36 100644 --- a/tests/semantic/methods5_error.txt +++ b/tests/semantic/methods5_error.txt @@ -1,2 +1 @@ -methods5.cl:12: In redefined method f, return type Object is different from original return type Int. -Compilation halted due to static semantic errors. +(12, 24) - SemanticError: In redefined method f, return type Object is different from original return type Int. diff --git a/tests/semantic/methods6_error.txt b/tests/semantic/methods6_error.txt index 6a3c2db9..8e32663b 100644 --- a/tests/semantic/methods6_error.txt +++ b/tests/semantic/methods6_error.txt @@ -1,2 +1 @@ -methods6.cl:22: Incompatible number of formal parameters in redefined method g. -Compilation halted due to static semantic errors. +(22, 5) - SemanticError: Incompatible number of formal parameters in redefined method g. diff --git a/tests/semantic/self1_error.txt b/tests/semantic/self1_error.txt index bf85479c..6beb3cda 100644 --- a/tests/semantic/self1_error.txt +++ b/tests/semantic/self1_error.txt @@ -1,3 +1 @@ -self1.cl:10: Cannot assign to 'self'. -self1.cl:10: Type Main of assigned expression does not conform to declared type SELF_TYPE of identifier self. -Compilation halted due to static semantic errors. +(10, 30) - SemanticError: Cannot assign to 'self'. diff --git a/tests/semantic/self2_error.txt b/tests/semantic/self2_error.txt index 5a355e34..20c883c9 100644 --- a/tests/semantic/self2_error.txt +++ b/tests/semantic/self2_error.txt @@ -1,2 +1 @@ -self2.cl:9: 'self' cannot be bound in a 'let' expression. -Compilation halted due to static semantic errors. +(9, 22) - SemanticError: 'self' cannot be bound in a 'let' expression. diff --git a/tests/semantic/self3_error.txt b/tests/semantic/self3_error.txt index e0f578cc..0ae38200 100644 --- a/tests/semantic/self3_error.txt +++ b/tests/semantic/self3_error.txt @@ -1,2 +1 @@ -self3.cl:9: 'self' cannot be the name of a formal parameter. -Compilation halted due to static semantic errors. +(9, 10) - SemanticError: 'self' cannot be the name of a formal parameter. diff --git a/tests/semantic/self4_error.txt b/tests/semantic/self4_error.txt index ec0ba80d..c19ca400 100644 --- a/tests/semantic/self4_error.txt +++ b/tests/semantic/self4_error.txt @@ -1,2 +1 @@ -elf4.cl:9: 'self' cannot be the name of an attribute. -Compilation halted due to static semantic errors. +(9, 5) - SemanticError: 'self' cannot be the name of an attribute. From 17f4233b8027bc9c6e492a651e10e82a28a0567a Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Fri, 30 Oct 2020 12:00:00 -0400 Subject: [PATCH 342/435] Update travis.yml --- .travis.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27b0b96d..1f4f9da7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,4 +20,11 @@ jobs: - cd src - make clean - make - - make test TAG=parser \ No newline at end of file + - make test TAG=parser + - stage: "Semantic" + name: "Semantic" + script: + - cd src + - make clean + - make + - make test TAG=semantic \ No newline at end of file From 3ac170a09247d1b4ed7f9ccf4b871bb9d171c619 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Fri, 30 Oct 2020 12:30:10 -0400 Subject: [PATCH 343/435] Add basic types tests --- tests/semantic/basics1.cl | 10 ++++++++++ tests/semantic/basics1_error.txt | 1 + tests/semantic/basics2.cl | 9 +++++++++ tests/semantic/basics2_error.txt | 1 + tests/semantic/basics3.cl | 9 +++++++++ tests/semantic/basics3_error.txt | 1 + tests/semantic/basics4.cl | 9 +++++++++ tests/semantic/basics4_error.txt | 1 + tests/semantic/basics5.cl | 9 +++++++++ tests/semantic/basics5_error.txt | 1 + tests/semantic/basics6.cl | 9 +++++++++ tests/semantic/basics6_error.txt | 1 + tests/semantic/basics7.cl | 9 +++++++++ tests/semantic/basics7_error.txt | 1 + tests/semantic/basics8.cl | 9 +++++++++ tests/semantic/basics8_error.txt | 1 + 16 files changed, 81 insertions(+) create mode 100644 tests/semantic/basics1.cl create mode 100644 tests/semantic/basics1_error.txt create mode 100644 tests/semantic/basics2.cl create mode 100644 tests/semantic/basics2_error.txt create mode 100644 tests/semantic/basics3.cl create mode 100644 tests/semantic/basics3_error.txt create mode 100644 tests/semantic/basics4.cl create mode 100644 tests/semantic/basics4_error.txt create mode 100644 tests/semantic/basics5.cl create mode 100644 tests/semantic/basics5_error.txt create mode 100644 tests/semantic/basics6.cl create mode 100644 tests/semantic/basics6_error.txt create mode 100644 tests/semantic/basics7.cl create mode 100644 tests/semantic/basics7_error.txt create mode 100644 tests/semantic/basics8.cl create mode 100644 tests/semantic/basics8_error.txt diff --git a/tests/semantic/basics1.cl b/tests/semantic/basics1.cl new file mode 100644 index 00000000..32ae1656 --- /dev/null +++ b/tests/semantic/basics1.cl @@ -0,0 +1,10 @@ +-- It is an error to redefine the IO class. + +class IO { + scan(): String { ":)" }; + print(s: String): IO { new IO }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/tests/semantic/basics1_error.txt b/tests/semantic/basics1_error.txt new file mode 100644 index 00000000..676f5049 --- /dev/null +++ b/tests/semantic/basics1_error.txt @@ -0,0 +1 @@ +(3, 7) - SemanticError: Redefinition of basic class IO. diff --git a/tests/semantic/basics2.cl b/tests/semantic/basics2.cl new file mode 100644 index 00000000..cf2b1cd2 --- /dev/null +++ b/tests/semantic/basics2.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Int { + is_prime(): Bool { false }; +}; diff --git a/tests/semantic/basics2_error.txt b/tests/semantic/basics2_error.txt new file mode 100644 index 00000000..69a3b681 --- /dev/null +++ b/tests/semantic/basics2_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Int. diff --git a/tests/semantic/basics3.cl b/tests/semantic/basics3.cl new file mode 100644 index 00000000..fef017a8 --- /dev/null +++ b/tests/semantic/basics3.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Int { + is_prime(): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics3_error.txt b/tests/semantic/basics3_error.txt new file mode 100644 index 00000000..d8f80cb1 --- /dev/null +++ b/tests/semantic/basics3_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Int. diff --git a/tests/semantic/basics4.cl b/tests/semantic/basics4.cl new file mode 100644 index 00000000..9266ec79 --- /dev/null +++ b/tests/semantic/basics4.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics4_error.txt b/tests/semantic/basics4_error.txt new file mode 100644 index 00000000..d5cd4c3d --- /dev/null +++ b/tests/semantic/basics4_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class String. diff --git a/tests/semantic/basics5.cl b/tests/semantic/basics5.cl new file mode 100644 index 00000000..bad5eff1 --- /dev/null +++ b/tests/semantic/basics5.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics5_error.txt b/tests/semantic/basics5_error.txt new file mode 100644 index 00000000..8437accf --- /dev/null +++ b/tests/semantic/basics5_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class String. diff --git a/tests/semantic/basics6.cl b/tests/semantic/basics6.cl new file mode 100644 index 00000000..47266ebe --- /dev/null +++ b/tests/semantic/basics6.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics6_error.txt b/tests/semantic/basics6_error.txt new file mode 100644 index 00000000..b4d22da1 --- /dev/null +++ b/tests/semantic/basics6_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Bool. diff --git a/tests/semantic/basics7.cl b/tests/semantic/basics7.cl new file mode 100644 index 00000000..0f30aaec --- /dev/null +++ b/tests/semantic/basics7.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics7_error.txt b/tests/semantic/basics7_error.txt new file mode 100644 index 00000000..92660ab9 --- /dev/null +++ b/tests/semantic/basics7_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Bool. diff --git a/tests/semantic/basics8.cl b/tests/semantic/basics8.cl new file mode 100644 index 00000000..3b9697d4 --- /dev/null +++ b/tests/semantic/basics8.cl @@ -0,0 +1,9 @@ +-- It is an error redefine Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Object { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/tests/semantic/basics8_error.txt b/tests/semantic/basics8_error.txt new file mode 100644 index 00000000..652f47b3 --- /dev/null +++ b/tests/semantic/basics8_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Object. From 7a476e5fd031ed33c8c59ca6b5850a63a6cd9b6a Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sat, 31 Oct 2020 15:38:37 -0400 Subject: [PATCH 344/435] New arithmetic tests --- tests/semantic/arithmetic10.cl | 15 +++++++++++++++ tests/semantic/arithmetic10_error.txt | 1 + tests/semantic/arithmetic11.cl | 14 ++++++++++++++ tests/semantic/arithmetic11_error.txt | 1 + tests/semantic/arithmetic12.cl | 14 ++++++++++++++ tests/semantic/arithmetic12_error.txt | 1 + tests/semantic/arithmetic9.cl | 15 +++++++++++++++ tests/semantic/arithmetic9_error.txt | 1 + 8 files changed, 62 insertions(+) create mode 100644 tests/semantic/arithmetic10.cl create mode 100644 tests/semantic/arithmetic10_error.txt create mode 100644 tests/semantic/arithmetic11.cl create mode 100644 tests/semantic/arithmetic11_error.txt create mode 100644 tests/semantic/arithmetic12.cl create mode 100644 tests/semantic/arithmetic12_error.txt create mode 100644 tests/semantic/arithmetic9.cl create mode 100644 tests/semantic/arithmetic9_error.txt diff --git a/tests/semantic/arithmetic10.cl b/tests/semantic/arithmetic10.cl new file mode 100644 index 00000000..bbfe6cdb --- /dev/null +++ b/tests/semantic/arithmetic10.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in ~new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic10_error.txt b/tests/semantic/arithmetic10_error.txt new file mode 100644 index 00000000..b2be0476 --- /dev/null +++ b/tests/semantic/arithmetic10_error.txt @@ -0,0 +1 @@ +(13, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. \ No newline at end of file diff --git a/tests/semantic/arithmetic11.cl b/tests/semantic/arithmetic11.cl new file mode 100644 index 00000000..fc067dc1 --- /dev/null +++ b/tests/semantic/arithmetic11.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic11_error.txt b/tests/semantic/arithmetic11_error.txt new file mode 100644 index 00000000..bb4b8e1c --- /dev/null +++ b/tests/semantic/arithmetic11_error.txt @@ -0,0 +1 @@ +(13, 24) - TypeError: Argument of 'not' has type Int instead of Bool. \ No newline at end of file diff --git a/tests/semantic/arithmetic12.cl b/tests/semantic/arithmetic12.cl new file mode 100644 index 00000000..2e012fc4 --- /dev/null +++ b/tests/semantic/arithmetic12.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic12_error.txt b/tests/semantic/arithmetic12_error.txt new file mode 100644 index 00000000..d25eab65 --- /dev/null +++ b/tests/semantic/arithmetic12_error.txt @@ -0,0 +1 @@ +(12, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. \ No newline at end of file diff --git a/tests/semantic/arithmetic9.cl b/tests/semantic/arithmetic9.cl new file mode 100644 index 00000000..95579e13 --- /dev/null +++ b/tests/semantic/arithmetic9.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 + ~new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/tests/semantic/arithmetic9_error.txt b/tests/semantic/arithmetic9_error.txt new file mode 100644 index 00000000..99fafbbf --- /dev/null +++ b/tests/semantic/arithmetic9_error.txt @@ -0,0 +1 @@ +(14, 25) - TypeError: Argument of '~' has type String instead of Int. \ No newline at end of file From 2ea55b63d032dcfa482ebbb942fe0ee3e657704f Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sat, 31 Oct 2020 15:43:56 -0400 Subject: [PATCH 345/435] Add new case tests --- tests/semantic/case2.cl | 23 +++++++++++++++++++++++ tests/semantic/case2_error.txt | 1 + 2 files changed, 24 insertions(+) create mode 100644 tests/semantic/case2.cl create mode 100644 tests/semantic/case2_error.txt diff --git a/tests/semantic/case2.cl b/tests/semantic/case2.cl new file mode 100644 index 00000000..ae97b41d --- /dev/null +++ b/tests/semantic/case2.cl @@ -0,0 +1,23 @@ +-- The variables declared on each branch of a case must all have distinct types. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Bool => new E; + esac; +}; \ No newline at end of file diff --git a/tests/semantic/case2_error.txt b/tests/semantic/case2_error.txt new file mode 100644 index 00000000..302fec38 --- /dev/null +++ b/tests/semantic/case2_error.txt @@ -0,0 +1 @@ +(21, 20) - SemanticError: Duplicate branch Bool in case statement. \ No newline at end of file From f7a512e8d2b70eadf97e2ced5f0e7a374ea38281 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sat, 31 Oct 2020 16:11:40 -0400 Subject: [PATCH 346/435] Add new type tests --- tests/semantic/case3.cl | 23 ++++++++++++++++++++++ tests/semantic/case3_error.txt | 1 + tests/semantic/features3.cl | 15 +++++++++++++++ tests/semantic/features3_error.txt | 1 + tests/semantic/let3.cl | 15 +++++++++++++++ tests/semantic/let3_error.txt | 1 + tests/semantic/methods7.cl | 12 ++++++++++++ tests/semantic/methods7_error.txt | 1 + tests/semantic/methods8.cl | 12 ++++++++++++ tests/semantic/methods8_error.txt | 1 + tests/semantic/new1.cl | 31 ++++++++++++++++++++++++++++++ tests/semantic/new1_error.txt | 1 + 12 files changed, 114 insertions(+) create mode 100644 tests/semantic/case3.cl create mode 100644 tests/semantic/case3_error.txt create mode 100755 tests/semantic/features3.cl create mode 100755 tests/semantic/features3_error.txt create mode 100644 tests/semantic/let3.cl create mode 100644 tests/semantic/let3_error.txt create mode 100644 tests/semantic/methods7.cl create mode 100644 tests/semantic/methods7_error.txt create mode 100644 tests/semantic/methods8.cl create mode 100644 tests/semantic/methods8_error.txt create mode 100644 tests/semantic/new1.cl create mode 100644 tests/semantic/new1_error.txt diff --git a/tests/semantic/case3.cl b/tests/semantic/case3.cl new file mode 100644 index 00000000..da79bbfe --- /dev/null +++ b/tests/semantic/case3.cl @@ -0,0 +1,23 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Ball => new E; + esac; +}; \ No newline at end of file diff --git a/tests/semantic/case3_error.txt b/tests/semantic/case3_error.txt new file mode 100644 index 00000000..fea261e5 --- /dev/null +++ b/tests/semantic/case3_error.txt @@ -0,0 +1 @@ +(21, 20) - TypeError: Class Ball of case branch is undefined. \ No newline at end of file diff --git a/tests/semantic/features3.cl b/tests/semantic/features3.cl new file mode 100755 index 00000000..a3b59259 --- /dev/null +++ b/tests/semantic/features3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + c: Cadena; +}; \ No newline at end of file diff --git a/tests/semantic/features3_error.txt b/tests/semantic/features3_error.txt new file mode 100755 index 00000000..53f1abe2 --- /dev/null +++ b/tests/semantic/features3_error.txt @@ -0,0 +1 @@ +(14, 8) - TypeError: Class Cadena of attribute c is undefined. \ No newline at end of file diff --git a/tests/semantic/let3.cl b/tests/semantic/let3.cl new file mode 100644 index 00000000..8c0670ab --- /dev/null +++ b/tests/semantic/let3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: Cadena in new B; +}; \ No newline at end of file diff --git a/tests/semantic/let3_error.txt b/tests/semantic/let3_error.txt new file mode 100644 index 00000000..39c5315d --- /dev/null +++ b/tests/semantic/let3_error.txt @@ -0,0 +1 @@ +(14, 71) - TypeError: Class Cadena of let-bound identifier b is undefined. \ No newline at end of file diff --git a/tests/semantic/methods7.cl b/tests/semantic/methods7.cl new file mode 100644 index 00000000..e5a01f68 --- /dev/null +++ b/tests/semantic/methods7.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: Ball): Int { 4 }; +}; \ No newline at end of file diff --git a/tests/semantic/methods7_error.txt b/tests/semantic/methods7_error.txt new file mode 100644 index 00000000..472cbd9d --- /dev/null +++ b/tests/semantic/methods7_error.txt @@ -0,0 +1 @@ +(11, 19) - TypeError: Class Ball of formal parameter b is undefined. \ No newline at end of file diff --git a/tests/semantic/methods8.cl b/tests/semantic/methods8.cl new file mode 100644 index 00000000..3fccab54 --- /dev/null +++ b/tests/semantic/methods8.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): Integrer { 4 }; +}; \ No newline at end of file diff --git a/tests/semantic/methods8_error.txt b/tests/semantic/methods8_error.txt new file mode 100644 index 00000000..dc9302ec --- /dev/null +++ b/tests/semantic/methods8_error.txt @@ -0,0 +1 @@ +(11, 23) - TypeError: Undefined return type Integrer in method test. \ No newline at end of file diff --git a/tests/semantic/new1.cl b/tests/semantic/new1.cl new file mode 100644 index 00000000..d007fc03 --- /dev/null +++ b/tests/semantic/new1.cl @@ -0,0 +1,31 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: F <- { + new A; + { + new Ball; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/tests/semantic/new1_error.txt b/tests/semantic/new1_error.txt new file mode 100644 index 00000000..612a3d42 --- /dev/null +++ b/tests/semantic/new1_error.txt @@ -0,0 +1 @@ +(16, 17) - TypeError: 'new' used with undefined class Ball. \ No newline at end of file From 53b60b7879f1d213068c062b249d68ddbc808d37 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sun, 22 Nov 2020 15:07:23 -0500 Subject: [PATCH 347/435] Add codegen test engine --- tests/codegen/arith_output.txt | 0 tests/codegen/atoi2_output.txt | 0 tests/codegen/atoi_output.txt | 0 tests/codegen/book_list_output.txt | 0 tests/codegen/cells_output.txt | 0 tests/codegen/complex_output.txt | 0 tests/codegen/fib_output.txt | 0 tests/codegen/graph_output.txt | 0 tests/codegen/hairyscary_output.txt | 0 tests/codegen/hello_world_output.txt | 0 tests/codegen/helloworld_output.txt | 0 tests/codegen/io_output.txt | 0 tests/codegen/life_output.txt | 0 tests/codegen/list_output.txt | 0 tests/codegen/new_complex_output.txt | 0 tests/codegen/palindrome_output.txt | 0 tests/codegen/primes_output.txt | 0 tests/codegen/print-cool_output.txt | 0 tests/codegen/sort-list_output.txt | 0 tests/codegen/test_output.txt | 0 tests/codegen_test.py | 4 +-- tests/utils/utils.py | 45 +++++++++++++++++++++------- 22 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 tests/codegen/arith_output.txt create mode 100644 tests/codegen/atoi2_output.txt create mode 100644 tests/codegen/atoi_output.txt create mode 100644 tests/codegen/book_list_output.txt create mode 100644 tests/codegen/cells_output.txt create mode 100644 tests/codegen/complex_output.txt create mode 100644 tests/codegen/fib_output.txt create mode 100644 tests/codegen/graph_output.txt create mode 100644 tests/codegen/hairyscary_output.txt create mode 100644 tests/codegen/hello_world_output.txt create mode 100644 tests/codegen/helloworld_output.txt create mode 100644 tests/codegen/io_output.txt create mode 100644 tests/codegen/life_output.txt create mode 100644 tests/codegen/list_output.txt create mode 100644 tests/codegen/new_complex_output.txt create mode 100644 tests/codegen/palindrome_output.txt create mode 100644 tests/codegen/primes_output.txt create mode 100644 tests/codegen/print-cool_output.txt create mode 100644 tests/codegen/sort-list_output.txt create mode 100644 tests/codegen/test_output.txt diff --git a/tests/codegen/arith_output.txt b/tests/codegen/arith_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/atoi2_output.txt b/tests/codegen/atoi2_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/atoi_output.txt b/tests/codegen/atoi_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/book_list_output.txt b/tests/codegen/book_list_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/cells_output.txt b/tests/codegen/cells_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/complex_output.txt b/tests/codegen/complex_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/fib_output.txt b/tests/codegen/fib_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/graph_output.txt b/tests/codegen/graph_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/hairyscary_output.txt b/tests/codegen/hairyscary_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/hello_world_output.txt b/tests/codegen/hello_world_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/helloworld_output.txt b/tests/codegen/helloworld_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/io_output.txt b/tests/codegen/io_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/life_output.txt b/tests/codegen/life_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/list_output.txt b/tests/codegen/list_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/new_complex_output.txt b/tests/codegen/new_complex_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/palindrome_output.txt b/tests/codegen/palindrome_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/primes_output.txt b/tests/codegen/primes_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/print-cool_output.txt b/tests/codegen/print-cool_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/sort-list_output.txt b/tests/codegen/sort-list_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/test_output.txt b/tests/codegen/test_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen_test.py b/tests/codegen_test.py index 6d864cb0..d8aadb7d 100644 --- a/tests/codegen_test.py +++ b/tests/codegen_test.py @@ -1,6 +1,6 @@ import pytest import os -from utils import compare_errors +from utils import compare_outputs tests_dir = __file__.rpartition('/')[0] + '/codegen/' tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] @@ -12,4 +12,4 @@ @pytest.mark.run(order=4) @pytest.mark.parametrize("cool_file", tests) def test_codegen(compiler_path, cool_file): - compare_errors(compiler_path, tests_dir + cool_file, None) \ No newline at end of file + compare_outputs(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_output.txt') \ No newline at end of file diff --git a/tests/utils/utils.py b/tests/utils/utils.py index a3fa13ce..3c47c982 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -3,11 +3,13 @@ COMPILER_TIMEOUT = 'El compilador tarda mucho en responder.' +SPIM_TIMEOUT = 'El spim tarda mucho en responder.' TEST_MUST_FAIL = 'El test %s debe fallar al compilar' TEST_MUST_COMPILE = 'El test %s debe compilar' BAD_ERROR_FORMAT = '''El error no esta en formato: (,) - : o no se encuentra en la 3ra linea\n\n%s''' UNEXPECTED_ERROR = 'Se esperaba un %s en (%d, %d). Su error fue un %s en (%d, %d)' +UNEXPECTED_OUTPUT = 'La saida de %s no es la esperada:\n%s\nEsperada:\n%s' ERROR_FORMAT = r'^\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*-\s*(\w+)\s*:(.*)$' @@ -48,17 +50,40 @@ def compare_errors(compiler_path: str, cool_file_path: str, error_file_path: str except subprocess.TimeoutExpired: assert False, COMPILER_TIMEOUT + assert return_code == 1, TEST_MUST_FAIL % get_file_name(cool_file_path) + + fd = open(error_file_path, 'r') + errors = fd.read().split('\n') + fd.close() + + # checking the errors of compiler compiler_output = output.split('\n') + cmp(compiler_output[2:], errors) + +SPIM_HEADER = r'''^SPIM Version .+ of .+ +Copyright .+\, James R\. Larus\. +All Rights Reserved\. +See the file README for a full copyright notice\. +(?:Loaded: .+\n)*''' +def compare_outputs(compiler_path: str, cool_file_path: str, output_file_path: str, timeout=100): + try: + sp = subprocess.run(['bash', compiler_path, cool_file_path], capture_output=True, timeout=timeout) + assert sp.returncode == 0, TEST_MUST_COMPILE % get_file_name(cool_file_path) + except subprocess.TimeoutExpired: + assert False, COMPILER_TIMEOUT + + spim_file = cool_file_path[:-2] + 'mips' - if error_file_path: - assert return_code == 1, TEST_MUST_FAIL % get_file_name(cool_file_path) + try: + sp = subprocess.run(['spim', '-file', spim_file], capture_output=True, timeout=timeout) + mo = re.match(SPIM_HEADER, sp.stdout.decode()) + if mo: + output = mo.string[mo.end():] + except subprocess.TimeoutExpired: + assert False, SPIM_TIMEOUT - fd = open(error_file_path, 'r') - errors = fd.read().split('\n') - fd.close() + fd = open(output_file_path, 'r') + eoutput = fd.read() + fd.close() - # checking the errors of compiler - cmp(compiler_output[2:], errors) - else: - print(return_code, output) - assert return_code == 0, TEST_MUST_COMPILE % get_file_name(cool_file_path) \ No newline at end of file + assert output == eoutput, UNEXPECTED_OUTPUT % (spim_file, repr(output), repr(eoutput)) From 4c2e051321e846482d1a43e21df3f0d08e399ef5 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Sun, 22 Nov 2020 19:44:43 -0500 Subject: [PATCH 348/435] Update clean rule of makefile --- src/makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/makefile b/src/makefile index 021189d6..30df993f 100644 --- a/src/makefile +++ b/src/makefile @@ -5,6 +5,7 @@ main: clean: rm -rf build/* + rm -rf ../tests/*/*.mips test: pytest ../tests -v --tb=short -m=${TAG} From 24bb3813732de6c0df12ae5829bc9e766b382710 Mon Sep 17 00:00:00 2001 From: "d.garcia" Date: Mon, 23 Nov 2020 03:33:40 -0500 Subject: [PATCH 349/435] Add codegen tests --- tests/codegen/arith_input.txt | 13 + tests/codegen/arith_output.txt | 158 ++++ tests/codegen/atoi2.cl | 92 --- .../{atoi2_output.txt => atoi_input.txt} | 0 tests/codegen/atoi_output.txt | 1 + ...loworld_output.txt => book_list_input.txt} | 0 tests/codegen/book_list_output.txt | 7 + .../{test_output.txt => cells_input.txt} | 0 tests/codegen/cells_output.txt | 21 + tests/codegen/complex_input.txt | 0 tests/codegen/complex_output.txt | 1 + tests/codegen/fib_input.txt | 1 + tests/codegen/fib_output.txt | 2 + tests/codegen/graph_input.txt | 5 + tests/codegen/graph_output.txt | 7 + tests/codegen/hairyscary_input.txt | 0 tests/codegen/hairyscary_output.txt | 1 + tests/codegen/hello_world_input.txt | 0 tests/codegen/hello_world_output.txt | 1 + tests/codegen/helloworld.cl | 6 - tests/codegen/io_input.txt | 0 tests/codegen/io_output.txt | 5 + tests/codegen/life_input.txt | 66 ++ tests/codegen/life_output.txt | 778 ++++++++++++++++++ tests/codegen/list_input.txt | 0 tests/codegen/list_output.txt | 5 + tests/codegen/new_complex_input.txt | 0 tests/codegen/new_complex_output.txt | 2 + tests/codegen/palindrome_input.txt | 1 + tests/codegen/palindrome_output.txt | 2 + tests/codegen/primes_input.txt | 0 tests/codegen/primes_output.txt | 96 +++ tests/codegen/print-cool_input.txt | 0 tests/codegen/print-cool_output.txt | 1 + tests/codegen/sort-list_input.txt | 1 + tests/codegen/sort-list_output.txt | 10 + tests/codegen/test.cl | 19 - tests/codegen_test.py | 3 +- tests/utils/utils.py | 6 +- 39 files changed, 1191 insertions(+), 120 deletions(-) create mode 100644 tests/codegen/arith_input.txt delete mode 100644 tests/codegen/atoi2.cl rename tests/codegen/{atoi2_output.txt => atoi_input.txt} (100%) rename tests/codegen/{helloworld_output.txt => book_list_input.txt} (100%) rename tests/codegen/{test_output.txt => cells_input.txt} (100%) create mode 100644 tests/codegen/complex_input.txt create mode 100644 tests/codegen/fib_input.txt create mode 100644 tests/codegen/graph_input.txt create mode 100644 tests/codegen/hairyscary_input.txt create mode 100644 tests/codegen/hello_world_input.txt delete mode 100644 tests/codegen/helloworld.cl create mode 100644 tests/codegen/io_input.txt create mode 100644 tests/codegen/life_input.txt create mode 100644 tests/codegen/list_input.txt create mode 100644 tests/codegen/new_complex_input.txt create mode 100644 tests/codegen/palindrome_input.txt create mode 100644 tests/codegen/primes_input.txt create mode 100644 tests/codegen/print-cool_input.txt create mode 100644 tests/codegen/sort-list_input.txt delete mode 100755 tests/codegen/test.cl diff --git a/tests/codegen/arith_input.txt b/tests/codegen/arith_input.txt new file mode 100644 index 00000000..83e05b1e --- /dev/null +++ b/tests/codegen/arith_input.txt @@ -0,0 +1,13 @@ +a +1 +b +c +0 +d +e +f +g +h +j +5 +q diff --git a/tests/codegen/arith_output.txt b/tests/codegen/arith_output.txt index e69de29b..44b4ce73 100644 --- a/tests/codegen/arith_output.txt +++ b/tests/codegen/arith_output.txt @@ -0,0 +1,158 @@ +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + + +Please enter a number... number 1 is odd! +Class type is now B + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number -1 is odd! +Class type is now C + + To add a number to -1 ...enter a: + To negate -1 ...enter b: + To find the difference between -1 and another number...enter c: + To find the factorial of -1 ...enter d: + To square -1 ...enter e: + To cube -1 ...enter f: + To find out if -1 is a multiple of 3...enter g: + To divide -1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + + +Please enter a number... number 1 is odd! +Class type is now D + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is not divisible by 3. +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is equal to 0 times 8 with a remainder of 1 +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + diff --git a/tests/codegen/atoi2.cl b/tests/codegen/atoi2.cl deleted file mode 100644 index 577aa29f..00000000 --- a/tests/codegen/atoi2.cl +++ /dev/null @@ -1,92 +0,0 @@ -class JustThere { -- class can have no features. -}; - -class A2I { - - c2i(char : String) : Int { - if char = "0" then 0 else - if char = "1" then 1 else - if char = "2" then 2 else - if char = "3" then 3 else - if char = "4" then 4 else - if char = "5" then 5 else - if char = "6" then 6 else - if char = "7" then 7 else - if char = "8" then 8 else - if char = "9" then 9 else - { abort(); 0; } -- Here the formal list is optional. - fi fi fi fi fi fi fi fi fi fi - }; - - - i2c(i : Int) : String { - if i = 0 then "0" else - if i = 1 then "1" else - if i = 2 then "2" else - if i = 3 then "3" else - if i = 4 then "4" else - if i = 5 then "5" else - if i = 6 then "6" else - if i = 7 then "7" else - if i = 8 then "8" else - if i = 9 then "9" else - { abort(); ""; } -- demonstrates an expression block - fi fi fi fi fi fi fi fi fi fi - }; - - a2i(s : String) : Int { - if s.length() = 0 then 0 else - if s.substr(0,1) = "-" then ~a2i_aux(s.substr(1,s.length()-1)) else - if s.substr(0,1) = "+" then a2i_aux(s.substr(1,s.length()-1)) else - a2i_aux(s) - fi fi fi - }; - - a2i_aux(s : String) : Int { - (let int : Int <- 0 in - { - (let j : Int <- s.length() in - (let i : Int <- 0 in - while i < j loop - { - int <- int * 10 + c2i(s.substr(i,1)); -- demonstrates dispatch - i <- i + 1; - } - pool - ) - ); - int; - } - ) - }; - - i2a(i : Int) : String { - if i = 0 then "0" else - if 0 < i then i2a_aux(i) else - "-".concat(i2a_aux(i * ~1)) - fi fi - }; - - - i2a_aux(i : Int) : String { - if i = 0 then "" else - (let next : Int <- i / 10 in - i2a_aux(next).concat(i2c(i - next * 10)) - ) - fi - }; - -}; - -class Main inherits IO { - main () : Object { - let a : Int <- (new A2I).a2i("678987"), - b : String <- (new A2I).i2a(678987) in -- the let expression. Translated to let a: ... in let b: ... in expr. - { - out_int(a) ; - out_string(" == ") ; - out_string(b) ; - out_string("\n"); - } - } ; -} ; diff --git a/tests/codegen/atoi2_output.txt b/tests/codegen/atoi_input.txt similarity index 100% rename from tests/codegen/atoi2_output.txt rename to tests/codegen/atoi_input.txt diff --git a/tests/codegen/atoi_output.txt b/tests/codegen/atoi_output.txt index e69de29b..51b815a4 100644 --- a/tests/codegen/atoi_output.txt +++ b/tests/codegen/atoi_output.txt @@ -0,0 +1 @@ +678987 == 678987 diff --git a/tests/codegen/helloworld_output.txt b/tests/codegen/book_list_input.txt similarity index 100% rename from tests/codegen/helloworld_output.txt rename to tests/codegen/book_list_input.txt diff --git a/tests/codegen/book_list_output.txt b/tests/codegen/book_list_output.txt index e69de29b..3408320b 100644 --- a/tests/codegen/book_list_output.txt +++ b/tests/codegen/book_list_output.txt @@ -0,0 +1,7 @@ +title: The Top 100 CD_ROMs +author: Ulanoff +periodical: PC Magazine +- dynamic type was Article - +title: Compilers, Principles, Techniques, and Tools +author: Aho, Sethi, and Ullman +- dynamic type was Book - diff --git a/tests/codegen/test_output.txt b/tests/codegen/cells_input.txt similarity index 100% rename from tests/codegen/test_output.txt rename to tests/codegen/cells_input.txt diff --git a/tests/codegen/cells_output.txt b/tests/codegen/cells_output.txt index e69de29b..6304902c 100644 --- a/tests/codegen/cells_output.txt +++ b/tests/codegen/cells_output.txt @@ -0,0 +1,21 @@ + X +........XXX........ +.......X...X....... +......XXX.XXX...... +.....X.......X..... +....XXX.....XXX.... +...X...X...X...X... +..XXX.XXX.XXX.XXX.. +.X...............X. +XXX.............XXX +...X...........X... +..XXX.........XXX.. +.X...X.......X...X. +XXX.XXX.....XXX.XXX +.......X...X....... +......XXX.XXX...... +.....X.......X..... +....XXX.....XXX.... +...X...X...X...X... +..XXX.XXX.XXX.XXX.. +.X...............X. diff --git a/tests/codegen/complex_input.txt b/tests/codegen/complex_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/complex_output.txt b/tests/codegen/complex_output.txt index e69de29b..18b77c1f 100644 --- a/tests/codegen/complex_output.txt +++ b/tests/codegen/complex_output.txt @@ -0,0 +1 @@ +=) diff --git a/tests/codegen/fib_input.txt b/tests/codegen/fib_input.txt new file mode 100644 index 00000000..f599e28b --- /dev/null +++ b/tests/codegen/fib_input.txt @@ -0,0 +1 @@ +10 diff --git a/tests/codegen/fib_output.txt b/tests/codegen/fib_output.txt index e69de29b..d402da6a 100644 --- a/tests/codegen/fib_output.txt +++ b/tests/codegen/fib_output.txt @@ -0,0 +1,2 @@ +Enter n to find nth fibonacci number! +89 diff --git a/tests/codegen/graph_input.txt b/tests/codegen/graph_input.txt new file mode 100644 index 00000000..b67d9021 --- /dev/null +++ b/tests/codegen/graph_input.txt @@ -0,0 +1,5 @@ +1 2,100 +2 3,200 1,150 +3 2,10 +4 3,55 5,100 +5 1,1 2,2 3,3 4,4 5,5 diff --git a/tests/codegen/graph_output.txt b/tests/codegen/graph_output.txt index e69de29b..ef446522 100644 --- a/tests/codegen/graph_output.txt +++ b/tests/codegen/graph_output.txt @@ -0,0 +1,7 @@ +5 (5,5)5 (5,4)4 (5,3)3 (5,2)2 (5,1)1 +4 (4,5)100 (4,3)55 +3 (3,2)10 +2 (2,1)150 (2,3)200 +1 (1,2)100 + + (5,5)5 (5,4)4 (5,3)3 (5,2)2 (5,1)1 (4,5)100 (4,3)55 (3,2)10 (2,1)150 (2,3)200 (1,2)100 diff --git a/tests/codegen/hairyscary_input.txt b/tests/codegen/hairyscary_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/hairyscary_output.txt b/tests/codegen/hairyscary_output.txt index e69de29b..8985c22f 100644 --- a/tests/codegen/hairyscary_output.txt +++ b/tests/codegen/hairyscary_output.txt @@ -0,0 +1 @@ +17141611714163171416511714161171416317141653117141611714163171416511714161171416317141653171416117141631714165171416 \ No newline at end of file diff --git a/tests/codegen/hello_world_input.txt b/tests/codegen/hello_world_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/hello_world_output.txt b/tests/codegen/hello_world_output.txt index e69de29b..349db2bf 100644 --- a/tests/codegen/hello_world_output.txt +++ b/tests/codegen/hello_world_output.txt @@ -0,0 +1 @@ +Hello, World. diff --git a/tests/codegen/helloworld.cl b/tests/codegen/helloworld.cl deleted file mode 100644 index 61d42108..00000000 --- a/tests/codegen/helloworld.cl +++ /dev/null @@ -1,6 +0,0 @@ -class Main { - main():IO { - new IO.out_string("Hello world!\n") - }; -}; - diff --git a/tests/codegen/io_input.txt b/tests/codegen/io_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/io_output.txt b/tests/codegen/io_output.txt index e69de29b..f846f596 100644 --- a/tests/codegen/io_output.txt +++ b/tests/codegen/io_output.txt @@ -0,0 +1,5 @@ +A: Hello world +B: Hello world +C: Hello world +D: Hello world +Done. diff --git a/tests/codegen/life_input.txt b/tests/codegen/life_input.txt new file mode 100644 index 00000000..07e01672 --- /dev/null +++ b/tests/codegen/life_input.txt @@ -0,0 +1,66 @@ +y +1 +n +y +2 +n +y +3 +n +y +4 +n +y +5 +n +y +6 +n +y +7 +n +y +8 +n +y +9 +n +y +10 +n +y +11 +n +y +12 +n +y +13 +n +y +14 +n +y +15 +n +y +16 +n +y +17 +n +y +18 +n +y +19 +n +y +20 +n +y +21 +y +y +n +n \ No newline at end of file diff --git a/tests/codegen/life_output.txt b/tests/codegen/life_output.txt index e69de29b..5a9b9f73 100644 --- a/tests/codegen/life_output.txt +++ b/tests/codegen/life_output.txt @@ -0,0 +1,778 @@ +Welcome to the Game of Life. +There are many initial states to choose from. + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +XXXX +XXXX + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X + X + X +X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X + X + X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X + X + X + X +X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X +X X + + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X X +X X + X X + + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X X + X X +X X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXXX +XXXXX +XXXXX +XXXXX +XXXXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXXX + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X +XXXXX + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X X + X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X X + X X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXX +X +X +XXXX +X +X +XXXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXX + X + X + X + X + X +XXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +X X +X X + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +X X +X X + XX +X X +X X + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XXX +X +X + XX + X + X +XXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + +-XX- +X-X- +X--- +-XX- +---X +-X-X +-XX- + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + +-XX- +X-X- +X-X- +-XX- +-X-X +-X-X +-XX- + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: \ No newline at end of file diff --git a/tests/codegen/list_input.txt b/tests/codegen/list_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/list_output.txt b/tests/codegen/list_output.txt index e69de29b..fca72490 100644 --- a/tests/codegen/list_output.txt +++ b/tests/codegen/list_output.txt @@ -0,0 +1,5 @@ +5 4 3 2 1 +4 3 2 1 +3 2 1 +2 1 +1 diff --git a/tests/codegen/new_complex_input.txt b/tests/codegen/new_complex_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/new_complex_output.txt b/tests/codegen/new_complex_output.txt index e69de29b..0e8da112 100644 --- a/tests/codegen/new_complex_output.txt +++ b/tests/codegen/new_complex_output.txt @@ -0,0 +1,2 @@ +=) +=) diff --git a/tests/codegen/palindrome_input.txt b/tests/codegen/palindrome_input.txt new file mode 100644 index 00000000..8e1b6414 --- /dev/null +++ b/tests/codegen/palindrome_input.txt @@ -0,0 +1 @@ +anitalabalatina diff --git a/tests/codegen/palindrome_output.txt b/tests/codegen/palindrome_output.txt index e69de29b..7a009595 100644 --- a/tests/codegen/palindrome_output.txt +++ b/tests/codegen/palindrome_output.txt @@ -0,0 +1,2 @@ +enter a string +that was a palindrome diff --git a/tests/codegen/primes_input.txt b/tests/codegen/primes_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/primes_output.txt b/tests/codegen/primes_output.txt index e69de29b..a4d0fcb3 100644 --- a/tests/codegen/primes_output.txt +++ b/tests/codegen/primes_output.txt @@ -0,0 +1,96 @@ +2 is trivially prime. +3 is prime. +5 is prime. +7 is prime. +11 is prime. +13 is prime. +17 is prime. +19 is prime. +23 is prime. +29 is prime. +31 is prime. +37 is prime. +41 is prime. +43 is prime. +47 is prime. +53 is prime. +59 is prime. +61 is prime. +67 is prime. +71 is prime. +73 is prime. +79 is prime. +83 is prime. +89 is prime. +97 is prime. +101 is prime. +103 is prime. +107 is prime. +109 is prime. +113 is prime. +127 is prime. +131 is prime. +137 is prime. +139 is prime. +149 is prime. +151 is prime. +157 is prime. +163 is prime. +167 is prime. +173 is prime. +179 is prime. +181 is prime. +191 is prime. +193 is prime. +197 is prime. +199 is prime. +211 is prime. +223 is prime. +227 is prime. +229 is prime. +233 is prime. +239 is prime. +241 is prime. +251 is prime. +257 is prime. +263 is prime. +269 is prime. +271 is prime. +277 is prime. +281 is prime. +283 is prime. +293 is prime. +307 is prime. +311 is prime. +313 is prime. +317 is prime. +331 is prime. +337 is prime. +347 is prime. +349 is prime. +353 is prime. +359 is prime. +367 is prime. +373 is prime. +379 is prime. +383 is prime. +389 is prime. +397 is prime. +401 is prime. +409 is prime. +419 is prime. +421 is prime. +431 is prime. +433 is prime. +439 is prime. +443 is prime. +449 is prime. +457 is prime. +461 is prime. +463 is prime. +467 is prime. +479 is prime. +487 is prime. +491 is prime. +499 is prime. +Abort called from class String diff --git a/tests/codegen/print-cool_input.txt b/tests/codegen/print-cool_input.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/codegen/print-cool_output.txt b/tests/codegen/print-cool_output.txt index e69de29b..2b58f898 100644 --- a/tests/codegen/print-cool_output.txt +++ b/tests/codegen/print-cool_output.txt @@ -0,0 +1 @@ +cool diff --git a/tests/codegen/sort-list_input.txt b/tests/codegen/sort-list_input.txt new file mode 100644 index 00000000..f599e28b --- /dev/null +++ b/tests/codegen/sort-list_input.txt @@ -0,0 +1 @@ +10 diff --git a/tests/codegen/sort-list_output.txt b/tests/codegen/sort-list_output.txt index e69de29b..9878d57e 100644 --- a/tests/codegen/sort-list_output.txt +++ b/tests/codegen/sort-list_output.txt @@ -0,0 +1,10 @@ +How many numbers to sort? 0 +1 +2 +3 +4 +5 +6 +7 +8 +9 diff --git a/tests/codegen/test.cl b/tests/codegen/test.cl deleted file mode 100755 index 9c2e0fd8..00000000 --- a/tests/codegen/test.cl +++ /dev/null @@ -1,19 +0,0 @@ -class Main inherits IO { - - main () : Object { - { - let x:A <- new B in out_string( x.f().m() ); - let x:A <- new A in out_string( x.f().m() ); - } - - }; -}; - -class A { - m () : String { "A" }; - f () : A { new A }; -}; - -class B inherits A { - m () : String { "B" }; -}; diff --git a/tests/codegen_test.py b/tests/codegen_test.py index d8aadb7d..eee6e6e1 100644 --- a/tests/codegen_test.py +++ b/tests/codegen_test.py @@ -12,4 +12,5 @@ @pytest.mark.run(order=4) @pytest.mark.parametrize("cool_file", tests) def test_codegen(compiler_path, cool_file): - compare_outputs(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_output.txt') \ No newline at end of file + compare_outputs(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_input.txt',\ + tests_dir + cool_file[:-3] + '_output.txt') \ No newline at end of file diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 3c47c982..9b66c6e3 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -65,7 +65,7 @@ def compare_errors(compiler_path: str, cool_file_path: str, error_file_path: str All Rights Reserved\. See the file README for a full copyright notice\. (?:Loaded: .+\n)*''' -def compare_outputs(compiler_path: str, cool_file_path: str, output_file_path: str, timeout=100): +def compare_outputs(compiler_path: str, cool_file_path: str, input_file_path: str, output_file_path: str, timeout=100): try: sp = subprocess.run(['bash', compiler_path, cool_file_path], capture_output=True, timeout=timeout) assert sp.returncode == 0, TEST_MUST_COMPILE % get_file_name(cool_file_path) @@ -75,7 +75,9 @@ def compare_outputs(compiler_path: str, cool_file_path: str, output_file_path: s spim_file = cool_file_path[:-2] + 'mips' try: - sp = subprocess.run(['spim', '-file', spim_file], capture_output=True, timeout=timeout) + fd = open(input_file_path, 'rb') + sp = subprocess.run(['spim', '-file', spim_file], input=fd.read(), capture_output=True, timeout=timeout) + fd.close() mo = re.match(SPIM_HEADER, sp.stdout.decode()) if mo: output = mo.string[mo.end():] From 1c2f7ac307d84c47339408d6adadae93b95ae993 Mon Sep 17 00:00:00 2001 From: leynier Date: Mon, 23 Nov 2020 13:43:07 -0500 Subject: [PATCH 350/435] Add GitHub Action workflow --- .github/workflows/tests.yml | 80 +++++++++++++++++++++++++++++++++++ .travis.yml => old.travis.yml | 0 tests/codegen_test.py | 1 + 3 files changed, 81 insertions(+) create mode 100644 .github/workflows/tests.yml rename .travis.yml => old.travis.yml (100%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..d905131d --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,80 @@ +name: Tests + +on: [push, pull_request] + +jobs: + lexer: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + + - name: Install requirements + run: pip install -r requirements.txt + + - name: Run tests + run: | + cd src + make clean + make + make test TAG=lexer + + parser: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + + - name: Install requirements + run: pip install -r requirements.txt + + - name: Run tests + run: | + cd src + make clean + make + make test TAG=parser + + semantic: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + + - name: Install requirements + run: pip install -r requirements.txt + + - name: Run tests + run: | + cd src + make clean + make + make test TAG=semantic + + codegen: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + + - name: Install requirements + run: pip install -r requirements.txt + + - name: Run tests + run: | + cd src + make clean + make + make test TAG=codegen diff --git a/.travis.yml b/old.travis.yml similarity index 100% rename from .travis.yml rename to old.travis.yml diff --git a/tests/codegen_test.py b/tests/codegen_test.py index eee6e6e1..48df768f 100644 --- a/tests/codegen_test.py +++ b/tests/codegen_test.py @@ -8,6 +8,7 @@ # @pytest.mark.lexer # @pytest.mark.parser # @pytest.mark.semantic +@pytest.mark.codegen @pytest.mark.ok @pytest.mark.run(order=4) @pytest.mark.parametrize("cool_file", tests) From af0b28b5f5978e656e63d1cd80fddc20979a32e8 Mon Sep 17 00:00:00 2001 From: leynier Date: Mon, 23 Nov 2020 14:04:49 -0500 Subject: [PATCH 351/435] Add spim installation --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d905131d..62ff3680 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -72,6 +72,9 @@ jobs: - name: Install requirements run: pip install -r requirements.txt + - name: Install spim + run: sudo apt-get install spim + - name: Run tests run: | cd src From 5e2304872d83f9ac72c0e58e0a0555e598038795 Mon Sep 17 00:00:00 2001 From: leynier Date: Mon, 23 Nov 2020 14:11:13 -0500 Subject: [PATCH 352/435] Fix typo --- tests/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 9b66c6e3..961cf7cb 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -9,7 +9,7 @@ BAD_ERROR_FORMAT = '''El error no esta en formato: (,) - : o no se encuentra en la 3ra linea\n\n%s''' UNEXPECTED_ERROR = 'Se esperaba un %s en (%d, %d). Su error fue un %s en (%d, %d)' -UNEXPECTED_OUTPUT = 'La saida de %s no es la esperada:\n%s\nEsperada:\n%s' +UNEXPECTED_OUTPUT = 'La salida de %s no es la esperada:\n%s\nEsperada:\n%s' ERROR_FORMAT = r'^\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*-\s*(\w+)\s*:(.*)$' From 8520336d19d8f16dc50e08a34ef309e7768021a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leynier=20Guti=C3=A9rrez=20Gonz=C3=A1lez?= Date: Mon, 23 Nov 2020 14:15:35 -0500 Subject: [PATCH 353/435] Merge pull request #1 from leynier/imgbot [ImgBot] Optimize images --- img/img1.png | Bin 94958 -> 68716 bytes img/img10.png | Bin 316713 -> 265456 bytes img/img11.png | Bin 38557 -> 31831 bytes img/img12.png | Bin 32246 -> 26011 bytes img/img2.png | Bin 85245 -> 76362 bytes img/img3.png | Bin 19549 -> 15696 bytes img/img4.png | Bin 32921 -> 28133 bytes img/img5.png | Bin 10845 -> 9326 bytes img/img6.png | Bin 45153 -> 37487 bytes img/img7.png | Bin 72884 -> 61620 bytes img/img8.png | Bin 64287 -> 53330 bytes img/img9.png | Bin 60553 -> 50596 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/img/img1.png b/img/img1.png index 7b6186cc99d83fe90dce0db2d9e8e328cf6f91eb..ccb88735330d7467dff39096bb3664b4fb86be0a 100644 GIT binary patch literal 68716 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

E4{BYqHAQl=&rCK_e1U%x1B{KA&z@q^~=h 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

  • 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 z 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%0DB4sn5&;Y?f&zF6akNpB8Ft3 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�I6H`+R#5-dS5+K=O z+6W$$pJWs~fzcK2j>9<53|S$VS1EGc2OI;32+8L?4F=hm_TfU606>h3oFMu7)6?rh zc8?*x#M%N069L}-P$|e17z|1&1QT)6ZvqIp(;^`SU=~^&oDdKr9R%!;IaNu*!=(d< z?kFlMLMK#MDDvP8yr=^LCR^f0{~`mwo3liW==KQwT0TWl>K>Ms{NDJ_XK3Eyt@3|; zv~GLyGfUIC&~7sRNA*J&UEBzW8iX^YjG5rZzr>>M-(ZZ^500!ZI@64Wy6k-;@9pEi zNBs7z`nRe_UznrjMOQPN2AZ3-@(T-X?9qK5!@Ub0P7jpkB>;B=0x6;W{|13bcLE^2VPIeYXzcD?43#8;@E<^jF`2_l3?v?@G4m82q@klbKLP-6|9&@_7_f|@7^$c{mC8`3M{l=f zWs=m;5W!sq)Efg>LRVMU91+ZBYqorQG5Bn%fGTIAU+1mvS&S!8U7`{Ia&0?;e;?f* z7`yUXB^)5#*}W#w-R30Hltpum!3hoy4#q!q<**fOL2=ug2!tte-O<+<;ODojA@M?Y z`oi5%hT|!|89-oA^zD<|*TuD^XKQ^g$jT0n6q3M=mEIB$Sx*05C%M?!e^hs`VO3+Q zzRmkH2r^DiK%)Gu5^vuG=$h!`>fjcj2t1y4p}}i^WR`NfU8e~;YfN)K->iR`GI%M z-R+bB(Z|)5K-UhU55S-EGBV_@*xRVs(dmOd1oc)9JZ-ODr6lk#lQ@wGJ-B$W5&VnB zpds8yNRtPH4#F#Rj0ou>Cs0QuTzUgY|5}N&Q;G8`zzilfHWySH2v{NrKbZ}LvGJG^ z)j3hDIdqF4Wtt(d9!WeHhM=g&hG;E7dfcT;+X>KA@ERB#tP4F!MSzqEmK{>f;vysI z@hu@^gmMBRnH6CDsBi%+qrU*P9*g)DmOtr_)nh1F{%yf%hXK~titp+ zZ!o_iCB<4O0~KfIHPq+8sC<_S(WHa*^lfAYyS6*;-iD1P z7JqGHr~GT(rvNLE+B{H(NFO}Giy;W5TL%6m(835WKR?Kl&V?@SJc61Q!x`)WXiG8l z-&a_JDGpfr&|NVdRcAkbyck3abpHe|FE7#nS5cV&TZMcU1Pxl^VKGOWNlrq-5Yh^8 z$-GC>Me9GuM51!aH22}dXl{rzf6<^NKhD5P2nR82!UBL6k>*3=|VQW-0=+5lFJYPyj-L7xiWp4E;b6 z>;LhC*YImB)*L9$2!shW)53*}Tb3{fc#rcE%W_}1)B2hiDe4;i5CVnAAZJKC{x=5@ z&jw3QEkzx%ybHzQ(j4fAw(jP~h~^*B zR$-_F_3Lgjp<_;TS#C zh*kz8JsfVRNzWg-UwjErRODGVlqUI_6Ik5XX@@wc@jH@IQb=7!FNu#8MTs)!c8m+? zScN$`IQquN{b(7{exLoo)#`)`QKP_;n?PD^RQNVl7Ze4#Vdp3)De?KVbaXh78rhbV z6NvB$Vqj%cLeqn{tb7yLy!{&mqK_C zD6#Q2u-*?UzJQJlO2{)DPf6*p_c$=JdJCFIe*U$El!ITvBaV;H!Q>Kzv1mqsdBs+k zArpk##|4uNgNY{~nyP0+f2$znP6NFKW`ni>^G<`LcMLdRu{l5*!&}$8a|a*^u zOVrdH1!R-zjLi+D1yG?_Z*Mt7EMlTfMua~kTu~5UB8;kW=Z+n~>h59+38vrLRPTnK zcsC}kF9+a8j zTi_+-5Z zK=a6G6ce!L0B(}N%G<=5te?pEaxL++Z-_kW_|uuh8aTs(X=!?D>iElwB*zK)2{ z1`R&p0xdCYDg521;4YqwaClv>Io?%+Dm^jPULD?e*K5uT|0W0+_|UM$S;QS}ajG+L zDK2!Iej%OIGJxOCdtG_?&{{Y;X30LNHY_@;jlsR zip7hY51b|BOQj+|^4G5-Fs%169YgzVY+wNIjL7>-V#0&luBaiy%(v`oE9n&y9DG4e z4*P3DO%321nfl>Eh^a3FLClJlyVG^Gbye=?oF(*OMfm#gD_Pn$- zamL=hAUS#LA;lJ)R4C|G9NCaw3IhaiP!`d@T#i=+WUiiXaiFIF3m-wDBJo(YQx_PU zuA|XMv1yt55LF2nEuhe$RwrZU zFz|_j`(f2-w5-A#2`mvAm-vJP<(K^27zJfyTm%dA!l+AffiUWaZ;g$WH8rAtxx0G= z>&nW`>FAVTK8^q~Wo0@7pBpAaAYyyg?cU}s4T8(e94d#irsntW<46UJg=>b?7n_<6 ziz=&u$WIz4;wD4g?7TXw2EjDqPVw!tG37zKiRuI!XUHNSr>mpjX^y9fad8yHzsO!; z)dPbN-@4ErVx%_Pj1vEGP7a9-kJQGVo1o#KheY@&su8F)5O(2TcXKlz;1VQ0Lj42& z4I~WUKE>QX90o|?Gz223qZAxU2LI`~dS{(Uy*6B_(E5}P68}Pe87c++YpbEn^7M1 z0kFTuKW^Bcc#nI9%p<`gf%u@yOX>-#QM2~U0nC2?L3+fNF5bydcO1K!p^kP)69)?N zopHi9P;5qK5Hu=)A#a(RlahrROwYnSW?P!falT!EEE>jjRB zd_8&42Z71H>-}%^Ur_QG85p#^cM$9m08^FBbPu{Gl1b9M1LO_5rAR3G` z)6>o1z%bR(kA2wS=^MG{IA)#JF7#MQa}!S!j!tnIB?ZOe!b0TOJ<{yI z)nOAdqkc_JDznq0hyISpSyU)cB3=mP(*s8wT?2;axZcpNx~DJukbrk*Td_h4k?Veb zH`cQ#X<2OXlY_Q2p{eC}L#ML6{WLFcLuu*HG39C!`$QtgpDu7)?EKJj1{;mH^!K+n zq*`at#Jkk8*s%d_0^6=#<7^2!me%DApkY%HWy@@-$!7S7hs3yF4FTI=O_(aN(Hef- zLbu{7N-9%&+=oc=y`@9^JtbhKnPtvwAz=#-tnL)E{U3%86o7dp%A)B^e~0t94kxMq z&maB=`p^G>Ei}eZKmP2=6CA#{50C?g)n+NoN}{eJxX-hc4ELyC#7=3hz<1f%xJ^%! zDBovsgbOA^r=8R_6;&j0?XUiIh0Bjk&{6iYV#xCx0k_rj*E`yKVinKE`|V!zZDbC) z%p?+*{*G@xn}5&x(3?-AFZb?%#M<^&Z;?MY=4Uh@Ue^^wmcNX>3a5M4Seu}B{l!uK-TU`( zSR6cPc1uxG1iGS<4)q!qG5J@DO3Nxm+yW08n`j8@(nltiZ!bQNYLKsXE@9QU+S8EX z`0qJb4IMpuz;>4K&F#p^XqV>;3Q|?DoM$mIGG5O7THwDgRJK#sOw2GgKGw^i$}<|^ zzNP-D(}+p6jrEpV;}Op1tqw?Xn7$Ue`^l>pgM#pOe*DlF5%s)sbSYV@by{>8 zb=bfV``>Y@rq{oVOy_acSp`V6Z;sqR;PJ}eC!It~cn(?L3@c&W(ZY8~ z{F-*~kKQ?b$C|R2OUEmxgq>}DWs6E84Q@pCJQ}X>JvGZJ^~~zx4U4#&(;mhwmzUJG z=x?EveyulT=HtDf+cLxCayr3jg{d^&Us3T@Qi{ylO8w{;9Y(2D#R8MX#n$ff>}d%t9m|eN1NXh8Or@|ZdAk)3z;&ic!QtLV=zBw-6P!9&5)kl zySaK<+X*8|l`&1zVlRBgU$WLbhGk1biSXf#I|fcfe)hrw2&(4i)tO1UURP)r=8SJ? z7k&pTCpQU&T}4vCz@^3*+%buRjSaennc1j%wTFsw_uGm_HXp@9*W&Gcyu}%I?|Rld zfBf)jUxn9S62kC8Oed%B%neGtltR%KyUPn5SY;tJc|+M97XmIDb=7Fnz|{I2O*mSu zu;jNTNmykpTdJQwUYK(u|343D-{l-QtX8HYrf4w}^ra4d)?f$TxVT^kE{?R(#K-LX z;gq7bHS9VuA0e)@d3JC{yxS7{YG!)R%IUq$UVluL+v_>gyqVcKXXnvgXL*B>jvu5> z`DPhC0Z`%XE3&p$LCKEsFYlU>$8(X8)`;lQiTRq)6L8_O+wyy0_K3gu!SOL;r` z?(V}Txw572&(c$*S>b7a^2W~fb)3YUdc48aJEvPmWQOFqN|j=yF>_lB?Ih_qCT-&f|Ux_4~HLW-{_9dK*=ZXD(g>=#^MoBaO8wRQ^`POdY?VTm? z8~$z4x$mtIjP7gHYE5-XIPP3*`unWB^Z{#sA@L^@qyC1^@16XYD#q}U)adO#{+E>& zj496FX8)YWIKa9PR)P8_hP9d}-8oub96$eg-&l;MZZPTR#zR&3Vs1vd1`FT~e*M%@ zbI{eKz(bLpM9|FNGQfXH7e_pxbZBG^&SbNO-lIF1D62J(B0E^h`+zQoz7$oz`9ubd z5dZAD<;KOl;d!2>ree-E40f-r#S4#-Vj}Iz)apFnW9p*r+KN+_>Khi<)O75$9z41@ zs;a;aG-@?l!S6OP5Lm^x2@0EalsdS>lE*|}^0wD<#MnTN^tw+4Q48-8aTKdCj zlb*isCck`T7Nk{UO<==;!Lmv=z}_IASB2VEaI|=W&>e;9i1G7PZ!eVywCP^rkle6{ zfog_{Qld_)`uDT}R;sIGR{0U)VqU5-<}|d;o4tKS>1Mif(s1{oqZR#_m^ zet-jz=FT#z8U?soj)un0?n;_%!XCP0DOje-sj8+HC9rBS?Do`3G_eA* zc`CIw*n)&G3=UOd4nbQ!9PO9(_Phx~PbXU6QyekE?*~*v zg1MR;-?;%p8d^VO&hqP5FN$Ik);}3>2(d#R*+NKT0iaiI7SxUHkUQ~G8(X1yoWL6l zR^WF$iGzCnUc=j+n;=$*i6I{lsGZBm7&kzX$i_M&q139`d3Ll*1AbGwVYAz(Ja1HF zcZFb7NI#0|+JICz2H@-R=kLcNmd}l;PTbt0>|OIuGRd4K?X9sKD|o5GeG7Ixg@gg^ zDzRDo@*xa-e6#*%Vhi0{ozq<4=$GJ#kgK|@5C=9{VhVU{co!xy3<)Yy$Tq~jRRSXF zs~rbQ8Z5nud~LU$ivu0tLkW|FcgYdMfW>LIy}?1gNnxNpBsmoPjdZ;(?3=FimxT-n z&bM_o=9St+XGeI3rc_SMGw{{EKGF8N)JuEEa!%HPu%iLbPGG__q=i!2tB|d>p#w;r(5TNa!FCXvFW#W zNfB#lb4}W$^{O2DgjCqqPHLZ9OsDGiv=zSP&+gMG1#11rT-3bt`Ed)hT?kag#D6c_ z2$O<&;9E>!PoCL`gwD#Ayja!#z-Qeb`|bF4vNi$nBR0#l^Q4B`Z<}ZI@y((?&RYN= zBU6%-(LEq29J-7Nj5L!)$jKsk+FEExsQQEBhUMfL9YRC zE&)P7S*!_YM+MCZLgeH1Yd>Spf%Ab~Ym3g)PE+vV_KgWmJU_E@5OmXIUm1y|cQO+d z*&7YZp*R5{Orv6)t=a*^S7bGWny;QJ!&(!iir;v9Z&m2Dp(a2a;J$Y2kKWj5X+hZ5 z-!#j-3l0D!9f@ud5b}OV%LXk1!{5mDQclJ}95{4r$QVj9 znx3mV>>U9Pw^DT_{j+)wH;#*3jtLr6*9l!Ts0cjOb$H^dh8<51D2Mmr3CpD3b^PgC zU5MBqd+>I7P}F>a4h<#NK71K9R@M^defI-?Ay|dBh(M--vLNwrQU<;YiOYM%U!Zv5 z;D1TL#LBZ%`uH)^p1ddr5ma=dU|Ih^X5ra_#xL$dJ}y?&o0PoxyJ2xb%9g0FSXWVTbme$qZnj zCbzlFg(f;wQgB5ZA5#|*24u>!mkLPd-~uMgR*xtW?D>u1YO2j~{$zj|A%SPbQ=CB1 zS??`p1uXEQ1qzuT2uZncgM&@rb1k5vvBrAWmAvANOG-(!Kw%g0PRvLT8Kih~IxhH6 zUtZR0PyYjdZ|DXrdcNB^Oq7@&zf;w7DvHTBE@{=B!UZtc*uaZo$^Aap$M(FG!`=FZ zAt&&o=iix^^(de&@C32cX6T4166P8gc6%%j64ObxH=jNYYAv8bQF4#+slR&hjjekP zC>IbiylJz&_HKOpyI3P_%F&L29-PjL71*C{rV`2}&|kkY6O}e4@WiblSd<4fH30A2 zhbwDYiSW03Ilf*#nY{uP=_=e@t=GD};6217Futte{&~nA!-m5)9soLtmQL;V0wUxN z0gniXjY_EV0N4B)2Bl9+wLrI4W>&jO@#;yQ8cxSGlq(1D)LG$*4$ zxMc@_+P&Jzs|f*VuMX-tWN{DnuWDy%2F3UDy;@6@vh~~ z*XFP!o$!-$*g)9d^rW*Fuy-ocM9{svZ2@Pr8NA0DVm$(tf8pM#RQzYQlF;XE(CR_BGUBGzbje+DxkAfQdkd2(df8@6YP&n~(Uh+)cIUc3rMefmxfMl?Ny<`V`A-82|JBIls&7ZHR? z(*xrtXL`JU8<^ozR8$0cuXU|CkYQf!Y;SJ|$1Z}6`QYGK9i2Fk{Bd+d%CSDi4^d{L z+H(~1!qeI)&02c7?}!UZ{|Y|1S>n>{0RX^A0vgdjtUnbhGE;_2WK2dQ#!NSzl%6!t zOmZ6Wya9gWW^I_A-(;F4;$622N(Q}-7y#mc-|6&W^uNNLu)z(Uw17Jk0b8IeR z1ZhcFwsM3Fr2d_+Ao!uVXx<$MpiPR5RLWc@0C0N<1%`+ZYiynoliyk%k&a;ifund> zA#&(|L#W+sXH+o43KJb|D>o`ygL#R;fLo6n8Y|siLRUyHQWPvrR)I1JkTz3E$y<0(Fg*pm?$q{yUHTVBJ=Mfj~1+3WZiw2Xn(eQ&y>_AHjp zid7@tfTg84VC|30WGhDdVW(a`5D3ZlCHy+v0`08U5pcA#FPaXLKWSg|D6umqDi~Pr zvI-F4xvOQI#rh-#GnbwI3}%+O{=ME@dP+Q|{d#S{m6LsJy?*oHIHGzyOgTf<_Du60 zLgQXz90eT?)1w0+RpR$D)MFho$+_4I1M=2d^{P9!S1Z|EXc76C-o{4z&GCgBflkX= zxj!{hQW90)d0lbx+DJ+*mkiJVhYIvkb-6Y52#2xzb6W@?-ONZ$!(hM(j({kL7#N!h z>6R4|2%?VyECycNqt{z2XC~q8{rvF~*_$1!bTE=^_Gc7&chfn7jkB+Wx`?dT6kdMa zk@r=ROxY$oj4q*D!pJPd_~c%Avf$;fp{ZY+zw2eQwp#fK*3T4kje=|^W}coKtBbnI z-Dn^jw?rYwrck$3G&b|jFHn2%Ey3=Uj$c7k0aZ&AUz($myU1Q#+;}X-iWA`h@wu z4KEu-pr?2+g_mXpcGT1~qYHVP%3_l?;^FC*TmVw?&Sa$X_{DX9fqxd`Qb@T4eyn?W zc}`{t+wXa2vq1i|pnF`$3|(wsl5l)drb22;Y@*}d?E^wFU-vYS`?1fq>o)~1J?{4C zES6oxXs_C*F?Z`Y(Oi-%YgCcfd=knC4ka;eLopYTP?e1IV2N<&&9^cJ|B-3K1tt;_ zu-m`nPFuakcxdGaq=kTXFv~kQNZ5b_b`u|;pX(Q+dKI!X|NWkYddva_9pV;xy*gHZ)bEic$$2Eq|tAZA4jiVrV=^)U|>+7zy~=D0TSr=&nnx2ypWIn zpzYJ()+y3;3#qI}6gwyi@V8IJcc(7xy|p-!@QQA|s{a`K7(}wEO#@)eWI{;>NR)_3 zh?f!tqXB06@e<;EX|k=RAeeFK`PtRbgv2Ga^Dtp{Mu5&0V$kMSHS8pG_j0+ zw3Y%xdeUv+U@Srj~`26f*yl(w{o z2NYZdg^5Au2G|BiS!Pg1F_^w-ay5Kq=(PB*okg4t$ob9;Y*hy{%BXrj=Obacp> z_R3rnx`JPd)<8K7WnCMnoGSMtevqBe4aD-`l)yna1Js~$- zjv2f~Go=IS%eNa4Di7;DmKQ2El}C8&rvAc{Rd;?uC+jmvLZaw*UPhD>^4tjt?(QB+ zIb`@Y$z@YQu!NA0_kc8jUc`$e>veLj5)?EcdwhIh=eOR8gZ;1dm_vn@`NsT*RYmF$ z&{2oGMB9ZUs{0h-Zp}4H6 z^pr=pQwpE<)1VASfzf~YDnlV|QX1eXEbC~uerBh;=2?GydS23^^Gd@SfMn zuuuk$h^Qelr4&T{9FOnzbFn>MutI#zlEGjB95teKicxznUVun{=W6K$-4AWi?E@QJ z_1@caJAHy3rV?=i^#IC6qepT^x352`1iuHL23`PHm0u9}K;4rr$H-_y>P;`iQL8Q( z34jpV`HzEaysaI=1iOHbx|FUKV%tqecOOgd;{1AyD;8+)y~MP4qNaGUdX`s*ImF}t z`~?T8S3U=Nt#f9O$22P+gzz-N-Sc$A7^8iyQ30-8BP8-Gxx;XT_~G@uDrs!sU*aWr z&uKwDdRCHc3nZS%`C}+YGxNqlpK{wAeTg8HL=*Z;xoGfxIJ9p3 zh|*n>5Pi5h@)t{sc3)0QWo#BlmX@k>l7m$*U?UI?CT1i!IYeJSIwl4~T1AB*<|o*Y z{B>Xr%=Y$_o=hi`6knPC8RZf>#&##|UA|``P>H2^_fPFrDNQ&?8r=|lF@^j#=TBAR z_y$H#wPyW5;LgQ<250e~cxnd)L`}pK7qjM2h_|8d_3i#dPO!>)#LJ)l+$FyPC_Z=# zZgf_E58zMdr_1>5y{|n|?!M40v}%J69PVW|0Ogy#Be`jFF0Y2YLzte=4IoN2F0Wk- z&K}Bv1ys^Qxw&ss;ggop&!f&(PO+ac!PVy~LDWCsXNH+PL46G#-xmV^W1iG5_`?^%hJ>)Wzj7aPb95@rEd~X3c!L zJocR+yA*pUjfq07+l{vAqjcRb3i+T~ zrZAt-+=DmsW>gfl64w2To4>uTLbgCVI`dQ_^dN^lIqBDYOFHza!1dMM?JGf2off(= zI;_w-u7U(!fS#v>(4#s)oGV&7uWqLVv^S0djIH|QUK<%)%+s~CF%Er~eKzjnTB{^aBVJ2VGN}O*z0;E4}Qxz%D%v;Hz zuKvX9cUoP38VfsQ|Es?=)M)gQBojS^EnpGftw%msju#w!qPt|#)7bKMZ>j;yeD%+j zMh3y7N5c<~T<0z|-ab6}lBYk=paKPg_=WX0^b0_lu=i#Db>I&=) z{_nXxz&79b`||%i7=afzZ~yZef3NPP{`cX*$pRrO*7CdXd2od$04T|;%azJn1pOZX CVrHfQ diff --git a/img/img11.png b/img/img11.png index d7c024940a48a307f4a78a0bbd87281e67c53f29..b1934ce70a2f7e5fa333dc032a7b3b02cb91976a 100644 GIT binary patch literal 31831 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%0Dmqh=W_A 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 aPf+fC6tJ4hIeWj{$r2*6!li<`U;Y<;ywZOF diff --git a/img/img3.png b/img/img3.png index 864d620b661d5450ede65f154511709d73466dcf..d0df59cfb3bd1c0b785ba284073e14b619f0a46b 100644 GIT binary patch literal 15696 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 bpf}V_TSjO+T+}h}FhJ_FyjYcpLBRh3!!c(K diff --git a/img/img5.png b/img/img5.png index 5fdc0e6542e005096a3f6c8040ca8bc59a296ba8..c40009a03a39282626ed71ed10bf38ec30e1839d 100644 GIT binary patch literal 9326 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 literal 10845 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 KelF{r5}E+E%5i7_ literal 45153 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 B0z?1+ diff --git a/img/img7.png b/img/img7.png index 665342b7234734a3b63c7332fab375e15b63b33d..511c8ea628d218f56a3e31957d0d0437d9f296ea 100644 GIT binary patch literal 61620 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≤A8S?#`tMbyHlyZxexnZ;r2@b* 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 aj;_uD|Gh%lf+lpkYu)Px*Gk~`p8OAai=+4e literal 72884 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 HI!FHpreSkg diff --git a/img/img8.png b/img/img8.png index aad895da3a6d195369860d7d4a514349b14a48b5..54b34a91168afe5de8eb4b821f7d3eb789a86178 100644 GIT binary patch literal 53330 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�y2&1XR&XAI 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 Cw&jTc literal 60553 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 From 38c5398038c284d508a7b1a4405f9efcf9abb0c7 Mon Sep 17 00:00:00 2001 From: Alejandro Piad Date: Tue, 24 Nov 2020 09:44:20 -0500 Subject: [PATCH 354/435] Delete old.travis.yml --- old.travis.yml | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 old.travis.yml diff --git a/old.travis.yml b/old.travis.yml deleted file mode 100644 index 1f4f9da7..00000000 --- a/old.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: python -python: - - "3.7" -# command to install dependencies -install: - - pip install -r requirements.txt -# command to run tests -jobs: - include: - - stage: "Lexer" - name: "Lexer" - script: - - cd src - - make clean - - make - - make test TAG=lexer - - stage: "Parser" - name: "Parser" - script: - - cd src - - make clean - - make - - make test TAG=parser - - stage: "Semantic" - name: "Semantic" - script: - - cd src - - make clean - - make - - make test TAG=semantic \ No newline at end of file From bd3ed4e9f6204214b82cd3e68aa3ee229beef4d4 Mon Sep 17 00:00:00 2001 From: Alejandro Piad Date: Tue, 24 Nov 2020 09:48:30 -0500 Subject: [PATCH 355/435] Update Readme.md --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 5b1cbbce..55093d31 100644 --- a/Readme.md +++ b/Readme.md @@ -106,13 +106,13 @@ En este proyecto se realizarán entregas parciales a lo largo del curso. Para re ### 2. Asegúrese de tener la siguiente configuración antes de hacer click en **Create pull request**. - **base repository**: `matcom/cool-compiler-2020` (repositorio original) - - **branch**: `entrega-parser` + - **branch**: `entrega-final` - **head repository**: `/cool-compiler-2020` (repositorio propio) - **branch**: `master` (o la que corresponda) > Asegúrese que se indica **Able to merge**. De lo contrario, existen cambios en el repositorio original que usted no tiene, y debe actualizarlos. -> **NOTA**: Asegúrese que el _pull request_ se hace a la rama `entrega-parser`. +> **NOTA**: Asegúrese que el _pull request_ se hace a la rama `entrega-final`. ![](img/img6.png) From c0d1ad2597fc14013c2466f4e94b3ec3df3c3adc Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 21:15:19 +0100 Subject: [PATCH 356/435] [semantic] Fix error message - Fix error message in arithmetic_operator_visitor --- src/errors/errors.py | 4 +++- src/semantic/semantic.py | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/errors/errors.py b/src/errors/errors.py index 2fac0c43..dfa5186a 100644 --- a/src/errors/errors.py +++ b/src/errors/errors.py @@ -8,6 +8,8 @@ PARSER_ERRORS = [] SEMANTIC_ERRORS = [] +ERR_TYPE = "TypeError" + def add_lexer_error(line, column, message): LEXER_ERRORS.append(f'({line}, {column}) - LexicographicError: {message}') @@ -18,4 +20,4 @@ def add_parser_error(line, column, message): def add_semantic_error(line, column, message): - SEMANTIC_ERRORS.append(f'({line}, {column}) - SemanticError: {message}') + SEMANTIC_ERRORS.append(f'({line}, {column}) - {message}') diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index eb22d027..ae2ca172 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -6,7 +6,7 @@ import cool_types as CT from lexer_parser.ast import * -from errors import add_semantic_error +from errors import * def program_visitor(program: ProgramNode): @@ -30,7 +30,8 @@ def program_visitor(program: ProgramNode): return # 4) - types_already_check = [CT.ObjectType, CT.IntType, CT.StringType, CT.BoolType, CT.IOType] + types_already_check = [CT.ObjectType, CT.IntType, + CT.StringType, CT.BoolType, CT.IOType] classes = program.classes.copy() while len(classes) != 0: c: DefClassNode = classes.pop() @@ -439,13 +440,13 @@ def arithmetic_operator_visitor(operator: BinaryNode, current_class: CT.CoolType operator.lvalue, current_class, local_scope) if lvalue_type != CT.IntType and lvalue_type is not None: add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, - f'invalid left value type {lvalue_type}, must be a {CT.IntType}') + f'{ERR_TYPE}: non-Int arguments: {lvalue_type} + {CT.IntType}') # 2) rvalue_type = expression_visitor( operator.rvalue, current_class, local_scope) if rvalue_type != CT.IntType and rvalue_type is not None: add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, - f'invalid left value type {rvalue_type}, must be a {CT.IntType}') + f'{ERR_TYPE}: non-Int arguments: {CT.IntType} + {rvalue_type}') # 3) operator.returned_type = CT.IntType return CT.IntType From f617a647aa3cbcf43802d848d850f0cf3ac17d82 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 22:04:48 +0100 Subject: [PATCH 357/435] Change find_column --- src/lexer_parser/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lexer_parser/utils.py b/src/lexer_parser/utils.py index 30bf6c2e..25e652d2 100644 --- a/src/lexer_parser/utils.py +++ b/src/lexer_parser/utils.py @@ -4,6 +4,8 @@ COOL compiler project """ + def find_column(text, pos): line_start = text.rfind('\n', 0, pos) + 1 - return (pos - line_start) + 1 + tabs = text.count('\t', line_start, pos) + return (pos - line_start) + 1 + 3 * tabs From 2be0fd642cd8728e51a19974bb241b52b7df883d Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 22:05:29 +0100 Subject: [PATCH 358/435] [semantic] Fix arithmetic-operator position --- src/semantic/semantic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index ae2ca172..c75e50f2 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -439,13 +439,13 @@ def arithmetic_operator_visitor(operator: BinaryNode, current_class: CT.CoolType lvalue_type = expression_visitor( operator.lvalue, current_class, local_scope) if lvalue_type != CT.IntType and lvalue_type is not None: - add_semantic_error(operator.lvalue.lineno, operator.lvalue.colno, + add_semantic_error(operator.lineno, operator.colno, f'{ERR_TYPE}: non-Int arguments: {lvalue_type} + {CT.IntType}') # 2) rvalue_type = expression_visitor( operator.rvalue, current_class, local_scope) if rvalue_type != CT.IntType and rvalue_type is not None: - add_semantic_error(operator.rvalue.lineno, operator.rvalue.colno, + add_semantic_error(operator.lineno, operator.colno, f'{ERR_TYPE}: non-Int arguments: {CT.IntType} + {rvalue_type}') # 3) operator.returned_type = CT.IntType From 19869e21f772df22a8d5288744de04fd89cdcb47 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 22:13:57 +0100 Subject: [PATCH 359/435] Fix error message - Fix error message if type of attribute not exist --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index c75e50f2..8ed81a39 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -118,7 +118,7 @@ def def_attribute_visitor(def_attr: DefAttrNode, current_class: CT.CoolType, loc id_type = CT.type_by_name(def_attr.type) if id_type is None: add_semantic_error(def_attr.lineno, def_attr.colno, - f'unknown type \'{def_attr.type}\'') + f'{ERR_TYPE}: Class {def_attr.type} of let-bound identifier {def_attr.id} is undefined') # 2) if def_attr.expr: # 2.1) From 6827d6c5e6f7835bc4649d9c4286bcf4151bcda0 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 22:25:41 +0100 Subject: [PATCH 360/435] Check 'self' cannot be bound in a 'let' expression --- src/errors/errors.py | 1 + src/lexer_parser/parser.py | 2 +- src/semantic/semantic.py | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/errors/errors.py b/src/errors/errors.py index dfa5186a..3af41dfc 100644 --- a/src/errors/errors.py +++ b/src/errors/errors.py @@ -9,6 +9,7 @@ SEMANTIC_ERRORS = [] ERR_TYPE = "TypeError" +ERR_SEMANTIC = "SemanticError" def add_lexer_error(line, column, message): diff --git a/src/lexer_parser/parser.py b/src/lexer_parser/parser.py index d3567e2c..27fe948a 100644 --- a/src/lexer_parser/parser.py +++ b/src/lexer_parser/parser.py @@ -71,7 +71,7 @@ def p_def_attr_declaration(p): except IndexError: p[0] = DefAttrNode(p[1], p[3]) - p[0].add_location(p.lineno(3), find_column(p.lexer.lexdata, p.lexpos(3))) + p[0].add_location(p.lineno(0), find_column(p.lexer.lexdata, p.lexpos(0))) def p_def_func(p): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 8ed81a39..eda27c6c 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -356,6 +356,9 @@ def let_visitor(let: LetNode, current_class: CT.CoolType, local_scope: dict): local_scope = local_scope.copy() # 1) for attribute in let.let_attrs: + if attribute.id == 'self': + add_semantic_error( + attribute.lineno, attribute.colno, f'{ERR_SEMANTIC}: \'self\' cannot be bound in a \'let\' expression.') attribute_type = expression_visitor( attribute, current_class, local_scope) if attribute_type is None: From a7ed947fd7008c37339411586b111f9be3cd38ca Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Wed, 25 Nov 2020 22:31:54 +0100 Subject: [PATCH 361/435] Fix error message - Fix error message: Inferred type 'A 'of initialization of attribute d does not conform to declared type 'B' --- src/semantic/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index eda27c6c..9e357ada 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -97,7 +97,7 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CT.CoolType, local_ # 2) if attr_type is not None and not CT.check_inherits(expr_type, attr_type): add_semantic_error( - attr.lineno, attr.colno, f'cannot save type \'{expr_type}\' inside type \'{attr_type}\'') + attr.lineno, attr.expr.colno, f'{ERR_TYPE}: Inferred type {expr_type} of initialization of attribute d does not conform to declared type {attr_type}.') else: return attr_type From 1b39e335016d609d449817fd17f476a16e177802 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 26 Nov 2020 00:08:00 +0100 Subject: [PATCH 362/435] Check inheritance cycle --- src/cool_types/types.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 5318f3b7..7bc5ead8 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -4,7 +4,7 @@ COOL compiler project """ -from errors import add_semantic_error +from errors import * class CoolType: @@ -14,6 +14,7 @@ def __init__(self, name, parent_type, inherit=True): self.attributes = {} self.methods = {} self.inherit = inherit + self.childs = [] def __can_be_define__(self, id): if id in self.methods.keys(): @@ -172,6 +173,13 @@ def check_type_hierarchy(node): parentType = TypesByName[c.parent_type] if parentType.inherit: cType.parent = parentType + type_x = parentType + while type_x: + if type_x: + if type_x == cType: + add_semantic_error(c.lineno, c.colno,f'{ERR_SEMANTIC}: Class {cType.name}, or an ancestor of {cType.name}, is involved in an inheritance cycle.') + return False + type_x = type_x.parent else: add_semantic_error( c.lineno, c.colno, f'can\'t be inherit from class {parentType.name}') @@ -218,6 +226,7 @@ def pronounced_join(type_a, type_b): 'Bool': BoolType } +ObjectType.childs = [IOType, IntType, StringType, BoolType] ObjectType.add_method('abort', [], 'Object') ObjectType.add_method('type_name', [], 'String') ObjectType.add_method('copy', [], 'SELF_TYPE') From ec58b2059d4b3f10f255027d5cfd80d172e68479 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 26 Nov 2020 00:12:38 +0100 Subject: [PATCH 363/435] Fir error message --- src/cool_types/types.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 7bc5ead8..b71e7b13 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -177,12 +177,13 @@ def check_type_hierarchy(node): while type_x: if type_x: if type_x == cType: - add_semantic_error(c.lineno, c.colno,f'{ERR_SEMANTIC}: Class {cType.name}, or an ancestor of {cType.name}, is involved in an inheritance cycle.') + add_semantic_error( + c.lineno, c.colno, f'{ERR_SEMANTIC}: Class {cType.name}, or an ancestor of {cType.name}, is involved in an inheritance cycle.') return False type_x = type_x.parent else: add_semantic_error( - c.lineno, c.colno, f'can\'t be inherit from class {parentType.name}') + c.lineno, c.colno, f'{ERR_SEMANTIC}: Class {cType} cannot inherit class {parentType.name}.') return False except KeyError: add_semantic_error(c.lineno, c.colno, From 1143f406ffb96c52d69424ba0006da1bc3ce0fd4 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 26 Nov 2020 21:41:24 +0100 Subject: [PATCH 364/435] Fix semantic --- src/cool_types/types.py | 18 ++++++++--------- src/errors/errors.py | 2 ++ src/semantic/semantic.py | 42 +++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index b71e7b13..e34beedf 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -28,7 +28,7 @@ def add_method(self, id, arg_types_name, returned_type): for arg in arg_types_name: arg_type = type_by_name(arg) if arg_type is None: - return False, f'unknown type \'{arg}\'' + return False, f'{ERR_TYPE}: Class {arg} of formal parameter is undefined.' arg_types.append(arg_type) _returned_type = type_by_name(returned_type) if _returned_type is None: @@ -71,18 +71,16 @@ def get_method(self, id, args_types): if self.parent: return self.parent.get_method(id, args_types) else: - return None, f'unknown method \'{id}\'' + return None, f'{ERR_ATTRIBUTE}: Dispatch to undefined method {id}.' def get_method_without_hierarchy(self, id, args_types): try: method = self.methods[id] if len(args_types) != len(method.args): - return None, f'method \'{self.name}.{id}\' formal parameter count ({len(method.args)}) ' \ - f'does not match actual parameter count ({len(args_types)})' + return None, f'{ERR_SEMANTIC}: Method {id} called with wrong number of arguments.' for i, a in enumerate(args_types): if not check_inherits(a, method.args[i]): - return None, f'method \'{self.name}.{id}\' parameter #{i} type mismatch. Actual: \'{a}\' should ' \ - f'be a subtype of \'{method.args[i]}\' ' + return None, f'{ERR_TYPE}: In call of method {id}, type {a} does not conform to declared type {method.args[i]}.' return method, None except KeyError: raise Exception(f'type {self.name} don\'t have a method {id}') @@ -90,10 +88,10 @@ def get_method_without_hierarchy(self, id, args_types): def add_attr(self, id, attr_type, expression): attribute, owner_type = get_attribute(self, id) if attribute is not None: - return False, f'attribute \'{id}\' already declared in class \'{owner_type.name}\'' + return False, f'{ERR_SEMANTIC}: Attribute {id} is an attribute of an inherited class.' try: _ = self.attributes[id] - return False, f'attribute \'{id}\' already declared in class \'{self.name}\'' + return False, f'{ERR_SEMANTIC}: Attribute {id} is an attribute of an inherited class.' except KeyError: _attr_type = type_by_name(attr_type) if _attr_type is None: @@ -158,7 +156,7 @@ def check_type_declaration(node): try: _ = TypesByName[c.type] add_semantic_error(c.lineno, c.colno, - f'duplicated declaration of type \'{c.type}\'') + f'{ERR_SEMANTIC}: Redefinition of basic class {c.type}.') return False except KeyError: TypesByName[c.type] = CoolType(c.type, None) @@ -187,7 +185,7 @@ def check_type_hierarchy(node): return False except KeyError: add_semantic_error(c.lineno, c.colno, - f'unknown parent type {c.parent_type}') + f'{ERR_TYPE}: Class {cType} inherits from an undefined class {c.parent_type}.') return False else: cType.parent = ObjectType diff --git a/src/errors/errors.py b/src/errors/errors.py index 3af41dfc..bff07d66 100644 --- a/src/errors/errors.py +++ b/src/errors/errors.py @@ -10,6 +10,8 @@ ERR_TYPE = "TypeError" ERR_SEMANTIC = "SemanticError" +ERR_ATTRIBUTE = "AttributeError" +ERR_NAME = "NameError" def add_lexer_error(line, column, message): diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 9e357ada..9eec6efe 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -90,6 +90,9 @@ def def_attr_class_visitor(attr: DefAttrNode, current_class: CT.CoolType, local_ 1) Check EXPR 2) Check type(EXPR) <= TYPE ''' + if attr.id == 'self': + add_semantic_error(attr.lineno, attr.colno, + f'{ERR_SEMANTIC}: \'self\' cannot be the name of an attribute.') if attr.expr: # 1) expr_type = expression_visitor(attr.expr, current_class, local_scope) @@ -127,7 +130,7 @@ def def_attribute_visitor(def_attr: DefAttrNode, current_class: CT.CoolType, loc # 2.2) if not CT.check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(def_attr.lineno, def_attr.colno, - f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + f'{ERR_TYPE}: Inferred type {expr_type} of initialization of {def_attr.id} does not conform to identifier\'s declared type {id_type}.') # 3) return id_type @@ -147,7 +150,16 @@ def def_func_visitor(function: DefFuncNode, current_class: CT.CoolType, local_sc ''' local_scope = local_scope.copy() # 1) + arg_names = set() for arg in function.params: + if arg[0] == 'self': + add_semantic_error(function.lineno, function.colno, + f'{ERR_SEMANTIC}: \'self\' cannot be the name of a formal parameter.') + if arg[0] in arg_names: + add_semantic_error( + function.lineno, function.colno, f'{ERR_SEMANTIC}: Formal parameter {arg[0]} is multiply defined.') + return + arg_names.add(arg[0]) local_scope[arg[0]] = CT.type_by_name(arg[1]) # 2) body_type = expression_visitor( @@ -161,7 +173,7 @@ def def_func_visitor(function: DefFuncNode, current_class: CT.CoolType, local_sc return return_type elif body_type is not None: add_semantic_error(function.lineno, function.colno, - f'invalid returned type \'{function.return_type}\'') + f'{ERR_TYPE}: Inferred return type {body_type} of method {function.id} does not conform to declared return type {return_type}.') def assignment_visitor(assign: AssignNode, current_class: CT.CoolType, local_scope: dict): @@ -177,6 +189,9 @@ def assignment_visitor(assign: AssignNode, current_class: CT.CoolType, local_sco 3) Check type(EXPR) <= type(ID) 4) Type of assigment is type(EXPR) ''' + if assign.id == 'self': + add_semantic_error(assign.lineno, assign.colno, + f'{ERR_SEMANTIC}: Cannot assign to \'self\'.') # 1) try: # 1.1) @@ -186,7 +201,7 @@ def assignment_visitor(assign: AssignNode, current_class: CT.CoolType, local_sco attr, _ = CT.get_attribute(current_class, assign.id) if attr is None: add_semantic_error(assign.id.lineno, assign.id.colno, - f'unknown variable \'{assign.id}\'') + f'{ERR_NAME}: Undeclared identifier {assign.id}.') id_type = None else: id_type = attr.attrType @@ -195,7 +210,7 @@ def assignment_visitor(assign: AssignNode, current_class: CT.CoolType, local_sco # 3) if not CT.check_inherits(expr_type, id_type) and id_type is not None and expr_type is not None: add_semantic_error(assign.expr.lineno, assign.expr.colno, - f'Type \'{expr_type}\' cannot be stored in type \'{id_type}\'') + f'{ERR_TYPE}: Inferred type {expr_type} of initialization of {assign.id} does not conform to identifier\'s declared type {id_type}.') # 4) assign.returned_type = expr_type return expr_type @@ -289,7 +304,7 @@ def if_visitor(if_struct: IfNode, current_class: CT.CoolType, local_scope: dict) if_struct.if_expr, current_class, local_scope) if predicate_type != CT.BoolType and predicate_type is not None: add_semantic_error(if_struct.if_expr.lineno, if_struct.if_expr.colno, - f'\'if\' condition must be a {CT.BoolType}') + f'{ERR_TYPE}: Predicate of \'if\' does not have type {CT.BoolType}.') # 2) then_type = expression_visitor( if_struct.then_expr, current_class, local_scope) @@ -315,7 +330,7 @@ def loop_expr_visitor(loop: WhileNode, current_class: CT.CoolType, local_scope: predicate_type = expression_visitor(loop.cond, current_class, local_scope) if predicate_type != CT.BoolType and predicate_type is not None: add_semantic_error(loop.cond.lineno, loop.cond.colno, - f'\"loop\" condition must be a {CT.BoolType}') + f'{ERR_TYPE}: Loop condition does not have type {CT.BoolType}.') # 2) expression_visitor(loop.body, current_class, local_scope) # 3) @@ -393,11 +408,13 @@ def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: d 4) Type of case is the pronounced join of all branch expressions types, then is the current type at final of step 3) ''' + branch_types = set() # 1) expr_0 = expression_visitor(case.expr, current_class, local_scope) # 2) branch_0 = case.case_list[0] + branch_types.add(branch_0.type) # 2.1) branch_0_type = CT.type_by_name(branch_0.type) temp = local_scope.copy() @@ -412,11 +429,14 @@ def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: d # 3) for branch in case.case_list[1:]: + if branch.type in branch_types: + add_semantic_error(branch.lineno, branch.colno, + f'{ERR_SEMANTIC}: Duplicate branch {branch.type} in case statement.') temp = local_scope.copy() # 3.1) branch_type = CT.type_by_name(branch.type) if branch_type is None: - add_semantic_error(branch_0.line, branch_0.column, + add_semantic_error(branch.lineno, branch.colno, f"unknow type \"{branch.type}\"") # 3.2) temp[branch.id] = branch_type @@ -469,12 +489,12 @@ def comparison_visitor(cmp: BinaryNode, current_class: CT.CoolType, local_scope: lvalue_type = expression_visitor(cmp.lvalue, current_class, local_scope) if lvalue_type != CT.IntType and lvalue_type is not None: add_semantic_error(cmp.lvalue.lineno, cmp.lvalue.colno, - f'lvalue type must be a {CT.IntType}') + f'{ERR_TYPE}: non-{CT.IntType} arguments: {lvalue_type} < {CT.IntType}') # 2) rvalue_type = expression_visitor(cmp.rvalue, current_class, local_scope) if rvalue_type != CT.IntType and rvalue_type is not None: add_semantic_error(cmp.rvalue.lineno, cmp.rvalue.colno, - f'rvalue type must be a {CT.IntType}') + f'{ERR_TYPE}: non-{CT.IntType} arguments: {CT.IntType} < {rvalue_type}') # 3) cmp.returned_type = CT.BoolType return CT.BoolType @@ -499,7 +519,7 @@ def equal_visitor(equal: EqNode, current_class: CT.CoolType, local_scope: dict): static_types = [CT.IntType, CT.BoolType, CT.StringType] if (lvalue_type in static_types or rvalue_type in static_types) and lvalue_type != rvalue_type: add_semantic_error(equal.lineno, equal.colno, - f'impossible compare {lvalue_type} and {rvalue_type} types') + f'{ERR_TYPE}: Illegal comparison with a basic type.') # 4) equal.returned_type = CT.BoolType return CT.BoolType @@ -582,7 +602,7 @@ def var_visitor(var: VarNode, current_class: CT.CoolType, local_scope: dict): var.returned_type = attribute.attrType else: add_semantic_error(var.lineno, var.colno, - f'unknown variable \'{var.id}\'') + f'{ERR_NAME}: Undeclared identifier {var.id}.') # 3) return var.returned_type From 35bd9db9b57b94eb32419607acb76c2b5ac929ad Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 26 Nov 2020 21:46:31 +0100 Subject: [PATCH 365/435] Return caller type in get_method --- src/cool_types/types.py | 8 ++++---- src/semantic/semantic.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index e34beedf..79ce9790 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -71,17 +71,17 @@ def get_method(self, id, args_types): if self.parent: return self.parent.get_method(id, args_types) else: - return None, f'{ERR_ATTRIBUTE}: Dispatch to undefined method {id}.' + return None, None, f'{ERR_ATTRIBUTE}: Dispatch to undefined method {id}.' def get_method_without_hierarchy(self, id, args_types): try: method = self.methods[id] if len(args_types) != len(method.args): - return None, f'{ERR_SEMANTIC}: Method {id} called with wrong number of arguments.' + return None, None, f'{ERR_SEMANTIC}: Method {id} called with wrong number of arguments.' for i, a in enumerate(args_types): if not check_inherits(a, method.args[i]): - return None, f'{ERR_TYPE}: In call of method {id}, type {a} does not conform to declared type {method.args[i]}.' - return method, None + return None, None, f'{ERR_TYPE}: In call of method {id}, type {a} does not conform to declared type {method.args[i]}.' + return method, self, None except KeyError: raise Exception(f'type {self.name} don\'t have a method {id}') diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 9eec6efe..97a6f721 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -262,7 +262,7 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CT.CoolType, local func_call.lineno, func_call.colno, f'unknown type \'{func_call.type}\'') # 2.2.2) elif CT.check_inherits(object_type, specific_type): - method, msg = specific_type.get_method_without_hierarchy( + method, _, msg = specific_type.get_method_without_hierarchy( func_call.id, args_types) # 2.2.3) if method is not None and method.returnedType == CT.SelfType: @@ -271,12 +271,12 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CT.CoolType, local add_semantic_error(func_call.lineno, func_call.colno, f'type {object_type} not inherits from {specific_type}') else: - method, msg = object_type.get_method(func_call.id, args_types) + method, _, msg = object_type.get_method(func_call.id, args_types) if method is not None and method.returnedType == CT.SelfType: method.returnedType = object_type # 3) else: - method, msg = current_class.get_method(func_call.id, args_types) + method, _, msg = current_class.get_method(func_call.id, args_types) if method is None and msg is not None: add_semantic_error(func_call.lineno, func_call.colno, msg) # 3.1) From 4058a500059a40003d71885f32e442a7b319b661 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Thu, 26 Nov 2020 23:09:20 +0100 Subject: [PATCH 366/435] Finally semantic check --- src/cool_types/types.py | 22 +++++++++++++++++++--- src/semantic/semantic.py | 13 +++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 79ce9790..e96bac32 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -18,10 +18,26 @@ def __init__(self, name, parent_type, inherit=True): def __can_be_define__(self, id): if id in self.methods.keys(): - return False, f'method {id} already declared in class {self.name}' + return False, f'{ERR_SEMANTIC}: Method {id} is multiply defined.' return True, None def add_method(self, id, arg_types_name, returned_type): + current_type = self + while current_type: + try: + m = current_type.methods[id] + if len(m.args) != len(arg_types_name): + return False, f'{ERR_SEMANTIC}: invalid redefinition of {id}' + for i in range(0, len(arg_types_name)): + current_type = TypesByName[arg_types_name[i]] + if current_type != m.args[i]: + return False, f'{ERR_SEMANTIC}: In redefined method {id}, parameter type {current_type} is different from original type {m.args[i]}.' + _returned_type = type_by_name(returned_type) + if m.returnedType != _returned_type: + return False, f'{ERR_SEMANTIC}: In redefined method {id}, return type {_returned_type} is different from original return type {m.returnedType}.' + break + except KeyError: + current_type = current_type.parent ok, msg = self.__can_be_define__(id) if ok: arg_types = [] @@ -32,7 +48,7 @@ def add_method(self, id, arg_types_name, returned_type): arg_types.append(arg_type) _returned_type = type_by_name(returned_type) if _returned_type is None: - return False, f'unknown type \'{returned_type}\'' + return False, f'{ERR_TYPE}: Undefined return type {returned_type} in method {id}.' self.methods[id] = CoolTypeMethod(id, arg_types, _returned_type) return True, None else: @@ -95,7 +111,7 @@ def add_attr(self, id, attr_type, expression): except KeyError: _attr_type = type_by_name(attr_type) if _attr_type is None: - return False, f'unknown type \'{attr_type}\'' + return False, f'{ERR_TYPE}: Class {attr_type} of attribute {id} is undefined.' self.attributes[id] = CoolTypeAttribute(id, _attr_type, expression) return True, None diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 97a6f721..585b2eca 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -269,7 +269,8 @@ def func_call_visitor(func_call: FuncCallNode, current_class: CT.CoolType, local method.returnedType = specific_type else: add_semantic_error(func_call.lineno, func_call.colno, - f'type {object_type} not inherits from {specific_type}') + f'{ERR_TYPE}: Expression type {object_type} does not conform to declared static dispatch type {specific_type}.') + return None else: method, _, msg = object_type.get_method(func_call.id, args_types) if method is not None and method.returnedType == CT.SelfType: @@ -420,7 +421,7 @@ def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: d temp = local_scope.copy() if branch_0_type is None: add_semantic_error(branch_0.line, branch_0.column, - f"unknow type \"{branch_0.type}\"") + f'{ERR_TYPE}: Class {branch_0.type} of case branch is undefined.') else: # 2.2) temp[branch_0.id] = branch_0_type @@ -437,7 +438,7 @@ def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: d branch_type = CT.type_by_name(branch.type) if branch_type is None: add_semantic_error(branch.lineno, branch.colno, - f"unknow type \"{branch.type}\"") + f'{ERR_TYPE}: Class {branch.type} of case branch is undefined.') # 3.2) temp[branch.id] = branch_type # 3.3) @@ -540,7 +541,7 @@ def negation_visitor(negation: NegationNode, current_class: CT.CoolType, local_s # 2) if value_type != CT.IntType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, - f'type {value_type} invalid. The \'~\' operator can only be used with type {CT.IntType}') + f'{ERR_TYPE}: Argument of \'~\' has type {value_type} instead of {CT.IntType}.') # 3) return CT.IntType @@ -561,7 +562,7 @@ def logic_negation_visitor(negation: LogicNegationNode, current_class: CT.CoolTy # 2) if value_type != CT.BoolType and value_type is not None: add_semantic_error(negation.lineno, negation.colno, - f'type {value_type} invalid. The \'not\' operator can only be used with type {CT.BoolType}') + f'{ERR_TYPE}: Argument of \'not\' has type {CT.IntType} instead of {value_type}.') # 3) return CT.BoolType @@ -621,7 +622,7 @@ def new_expr_visitor(new: NewNode, current_class: CT.CoolType, local_scope: dict t = CT.type_by_name(new.type) if not t: add_semantic_error( - new.lineno, new.colno, f'Type {new.type} does not exist. Cannot create instance.') + new.lineno, new.colno, f'{ERR_TYPE}: \'new\' used with undefined class {new.type}.') # 2) if t == CT.SelfType: new.returned_type = current_class From 33036a8a99a8ff94f55b18b05c30cd1031c2ca77 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 27 Nov 2020 15:43:16 -0500 Subject: [PATCH 367/435] hello_world partially working --- src/code_generation/CIL/cil.py | 21 ++++++--- src/code_generation/MIPS/mips.py | 61 ++++++++++++++++++++++++--- src/code_generation/MIPS/utilities.py | 2 +- src/lexer_parser/parsetab.py | 5 +-- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 94a41db0..f009d393 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -103,9 +103,9 @@ def program_to_cil_visitor(program): main_result = VCALL Main main ; } """ - main_instance = '__main__' - main_result = 'main_result' - main_function = CilAST.FuncNode('main', [], [CilAST.LocalNode(main_instance), CilAST.LocalNode(main_result)], + main_instance = add_local('__main__') + main_result = add_local('main_result') + main_function = CilAST.FuncNode('main', [], [CilAST.LocalNode('__main__'), CilAST.LocalNode('main_result')], [CilAST.AllocateNode('Main', main_instance), CilAST.ArgNode(main_instance), CilAST.VCAllNode('Main', 'main', main_result)]) @@ -398,13 +398,24 @@ def new_to_cil_visitor(new_node): body.append(CilAST.AllocateNode(t, value)) init_attr = CT.TypesByName[t].get_all_attributes() + # + t_data=add_str_data(t) + t_local=add_local() + # + + + body.append(CilAST.LoadNode(t_data, t_local)) + body.append(CilAST.SetAttrNode(value, '@type', t_data)) + body.append(CilAST.SetAttrNode(value, '@size', (len(init_attr)+2)*4)) + + for index, attr in enumerate(init_attr): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body body.append(CilAST.SetAttrNode( - value, attr.id, attr_cil.value, index)) + value, attr.id, attr_cil.value, index+2)) return CIL_block(body, value) @@ -489,7 +500,7 @@ def func_call_to_cil_visitor(call): call.object) body += obj_cil.body obj = obj_cil.value - t = call.object.returned_type.name + _, t, _ = call.object.returned_type.get_method(call.id, [arg.returned_type for arg in call.args]) else: obj = 'self' t = __CURRENT_TYPE__ diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 001f1131..1112a2d6 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -245,13 +245,13 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): CIL: x = ALLOCATE T MIPS: - li $a0, [syze(T)] + li $a0, [size(T)] li $v0, 9 syscall sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address = CURRENT_FUNCTION.ADDR[allocate.result] + address = CURRENT_FUNCTION.get_address(allocate.result.id) code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), @@ -261,6 +261,22 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): ] return code +def type_of_to_mips_visitor(typeof: cil.TypeOfNode): + """ + CIL: + t = TYPEOF x + MIPS: + lw $t0, [addr(x)] + sw ($t0), [addr(t)] + """ + x_addr = CURRENT_FUNCTION.get_address(str(typeof.var)) + t_addr = CURRENT_FUNCTION.get_address(str(typeof.result)) + return [ + mips.Comment(str(typeof)), + mips.LwInstruction('$t0', x_addr), + mips.SwInstruction('($t0)', t_addr) + ] + def copy_to_mips_visitor(copy: cil.CopyNode): """ @@ -275,7 +291,22 @@ def copy_to_mips_visitor(copy: cil.CopyNode): return [ mips.Comment(str(copy)), mips.LwInstruction('$t0', y_addr), - mips.SwInstruction('$t0', x_addr) + mips.LwInstruction('$t1', '4($t0)'), + mips.MoveInstruction('$a0', '$t1'), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', x_addr), + mips.LiInstruction('$t2', '0'), + mips.MIPSLabel('length_loop'), + mips.BeqInstruction('$t1', '$t2','end_length_loop'), + + mips.MoveInstruction('$t3',x_addr), + mips.AdduInstruction('$t3', '$t3', '$t2'), + mips.MoveInstruction(x_addr, '$t3'), + + mips.AdduInstruction('$t2', '$t2', 4), + mips.BInstruction('length_loop'), + mips.MIPSLabel('end_length_loop'), ] @@ -307,8 +338,9 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): MIPS: lw $t0, [addr(x)] lw $t1, [addr(y)] - sw $t0, [attr_shift($t0)] + sw $t0, [attr_shift($t1)] """ + x_addr = CURRENT_FUNCTION.get_address(str(setattr.val)) y_addr = CURRENT_FUNCTION.get_address(str(setattr.obj)) attr_shift = (setattr.attr_index + 1) * 4 @@ -525,6 +557,23 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): instructios.extend(free_stack(size)) return instructios +def assign_to_mips_visitor(assign:cil.AssignNode): + """ + CIL: + x = y + MIPS: + lw $t0, [y_addr] + sw $t0, [x_addr] + """ + y_addr= CURRENT_FUNCTION.get_address(assign.val.id) + x_addr=CURRENT_FUNCTION.get_address(assign.result.id) + + return [ + mips.Comment(str(assign)), + mips.LwInstruction('$t0', y_addr), + mips.SwInstruction('$t0', x_addr) + ] + __visitors__ = { cil.ArgNode: arg_to_mips_visitor, @@ -547,5 +596,7 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): cil.ConcatNode: concat_to_mips_visitor, cil.LoadNode: load_to_mips_visitor, cil.SubStringNode: substring_to_mips_visitor, - cil.VCAllNode: vcal_to_mips_visitor + cil.VCAllNode: vcal_to_mips_visitor, + cil.AssignNode: assign_to_mips_visitor, + cil.TypeOfNode:type_of_to_mips_visitor } diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 14789cdf..827467ed 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -14,7 +14,7 @@ def init_types(types): """ for i, t in enumerate(types): t.code_mips = i - t.size_mips = (len(t.attributes) + 1) * 4 + t.size_mips = (len(t.attributes) + 2) * 4 t.size_vt = (len(t.methods) + 1) * 4 t.attr_index_mips = {} for i, a in enumerate(t.attributes): diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 99fc4683..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 142c25f38a6ab4dbac618eedcb4aa1a69ff9ea29 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 28 Nov 2020 20:48:52 +0100 Subject: [PATCH 368/435] Some changes --- src/code_generation/CIL/cil.py | 4 +- src/code_generation/MIPS/ast.py | 48 +++--- src/code_generation/MIPS/mips.py | 209 ++++++++++++++------------ src/code_generation/MIPS/utilities.py | 7 +- src/lexer_parser/parsetab.py | 5 +- 5 files changed, 149 insertions(+), 124 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index f009d393..d1660b9d 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -143,8 +143,8 @@ def out_int_to_cil(): def in_string_to_cil(): - str = CilAST.LocalNode('str') - return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self')], [str], [CilAST.ReadNode(str), CilAST.ReturnNode(str)]) + _str = CilAST.LocalNode('str') + return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self')], [_str], [CilAST.ReadNode(_str), CilAST.ReturnNode(_str)]) def in_int_to_cil(): diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index f96d3cca..9deee3ae 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -38,32 +38,47 @@ def __str__(self): return f'{self.name}:\n' +class Recipient: + def __init__(self, register: str, shift: int = 0): + self.register = register + self.shift = shift + + def __call__(self) -> str: + # Get content + if self.shift != 0: + return f'{self.shift}({self.register})' + return f'({self.register})' + + def __str__(self): + return self.register + + +LOCATION_REG = 'register' +LCOATION_ADDR = 'address' + + class MIPSFunction: def __init__(self, name, params, locals): self.name = name - self.ADDR = {} self.init_instructions = [] self.instructions = [] self.end_instructions = [] self.caller_saved_reg = set() self.callee_saved_reg = set() + self.args_count = 0 + self.offset = {} + self.init_instructions.append(MoveInstruction('$fp', '$sp')) self.params_count = len(params) - # Store first 4 arguments in $a0 - $a3 registers - i = 0 - while i < self.params_count and i < 4: - p = params[i] - self.ADDR[p.id] = f'$a{i}' - i += 1 - # Save the rest on the stack - if i < self.params_count: - for j, p in enumerate(params[i:]): - self.ADDR[p.id] = f'{j * 4}($fp)' + + # Save args on the stack + for i, p in enumerate(params): + self.offset[p.id] = i*4 for i, l in enumerate(locals, 1): - self.ADDR[str(l)] = f'-{i * 4}($fp)' + self.offset[str(l)] = -i * 4 self.fp_shift = len(locals) self.init_instructions.append( @@ -94,15 +109,6 @@ def end(self): self.end_instructions.append(AdduInstruction( '$sp', '$sp', f'{self.fp_shift * 4}')) - def get_address(self, id): - """ - Return thememory address where it store the \"id\" identifier of CIL - """ - try: - return self.ADDR[id] - except KeyError: - raise Exception(f'Unsaved id {id}') - def __update_callee_saved_reg__(self, registers: set): diff = registers.difference(self.callee_saved_reg) for reg in diff: diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 1112a2d6..786ad8bf 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -92,18 +92,21 @@ def print_to_mips_visitor(p: cil.PrintNode): """ CIL: PRINT z; - MIPS if z is int: - move $a0, addr(z) - li $v0, 1 - syscall MIPS if z is str: - move $a0, addr(z) - li $v0, 4 + move $a0, $fp + addu $a0, $a0, shift(z) + li $v0, 4 + syscall + MIPS if z is int: + move $a0, $fp + addu $a0, $a0, shift(z) + li $v0, 1 syscall """ - addr_z = CURRENT_FUNCTION.get_address(p.str) + offset = CURRENT_FUNCTION.offset(p.str) code = [mips.Comment(str(p)), - mips.MoveInstruction('$a0', addr_z)] # move $a0, addr(z) + mips.MoveInstruction('$a0', '$fp'), + mips.AdduInstruction('$a0', '$a0', offset)] if p.str == 'int': code.append(mips.LiInstruction('$v0', 1)) # li $v0, 1 elif p.str == 'str': @@ -116,34 +119,39 @@ def return_to_mips_visitor(ret: cil.ReturnNode): """ CIL: RETURN x; - MIPS if x is int: - li $v0, x - MIPS ix x is not int: - lw $v0, addr(x) - """ - code = [mips.Comment(str(ret))] - if type(ret.ret_value) is int: - code.append(mips.LiInstruction('$v0', ret.ret_value)) # li $v0, x - else: - addr_x = CURRENT_FUNCTION.get_address(str(ret.ret_value)) - code.append(mips.LwInstruction('$v0', addr_x)) # lw $v0, addr(x) - return code + MIPS: + lw $v0, shift(x) + """ + offset = CURRENT_FUNCTION.offset[str(ret.ret_value)] + return [ + mips.Comment(str(ret)), + mips.LwInstruction('$v0', f'{offset}($fp)') + ] def read_to_mips_visitor(read: cil.ReadNode): - __DATA__.append(mips.MIPSDataItem( - read.result.id, mips.SpaceInst(__BUFFSIZE__))) - save_address(read.result, read.result.id) - code = [ - mips.Comment(str(read)), - mips.LaInstruction('$a0', read.result), - mips.LiInstruction('$a1', __BUFFSIZE__), + """ + CIL: + x = READ ; + MIPS: + addu $a0, $fp, shift(x) + li $a1, 1024 + li $v0, 8 + syscall + subu $sp, $a0, 1024 + """ + offset = CURRENT_FUNCTION.offset(str(read.result)) + + return [ + mips.AdduInstruction('$a0', '$fp', offset), + mips.LiInstruction('$a1', 1024), mips.LiInstruction('$v0', 8), - mips.SyscallInstruction() + mips.SyscallInstruction(), + mips.SubuInstruction('$sp', '$a0', 1024) ] - return code +# TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): addr = CURRENT_FUNCTION.get_address(ss.str) i = CURRENT_FUNCTION.get_address(ss.i) @@ -171,6 +179,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): return code +# TODO: Check def read_int_to_mips_visitor(read: cil.ReadIntNode): addr = CURRENT_FUNCTION.get_address(str(read.result)) code = [ @@ -182,13 +191,14 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): return code +# TODO: Check def length_to_mips_visitor(length: cil.LengthNode): - val = CURRENT_FUNCTION.get_address(length.str) - result_val = CURRENT_FUNCTION.get_address(str(length.result)) + val = CURRENT_FUNCTION[length.str] + result_val = CURRENT_FUNCTION[str(length.result)] code = [ mips.Comment(str(length)), - mips.LbInstruction('$t0', val), + mips.LbInstruction('$t0', val()), mips.LiInstruction('$t1', 0), mips.MIPSLabel('length_loop'), mips.BeqzInstruction('$t0', 'end_length_loop'), @@ -196,21 +206,22 @@ def length_to_mips_visitor(length: cil.LengthNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.SwInstruction('$t1', result_val) + mips.SwInstruction('$t1', result_val()) ] return code +# TODO: Check def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) save_address(concat.result, concat.result.id) - a = CURRENT_FUNCTION.get_address(concat.str_a) - b = CURRENT_FUNCTION.get_address(concat.str_b) + a = CURRENT_FUNCTION[concat.str_a] + b = CURRENT_FUNCTION[concat.str_b] code = [ mips.Comment(str(concat)), - mips.LwInstruction('$t0', a), + mips.LwInstruction('$t0', a()), mips.SwInstruction('$t0', concat.result), mips.LbInstruction('$t1', concat.result), mips.MIPSLabel('length_loop'), @@ -218,7 +229,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.LwInstruction('$t2', b), + mips.LwInstruction('$t2', b()), mips.SwInstruction('$t2', '($t1)') ] @@ -236,7 +247,16 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr = CURRENT_FUNCTION.get_address(str(arg.val)) + addr = CURRENT_FUNCTION[str(arg.val)] + location = CURRENT_FUNCTION.location[str(arg.val)] + mips_code = [mips.Comment(str(arg))] + if CURRENT_FUNCTION.args_count < 4: + mips_code.append(mips.LwInstruction( + f'$a{CURRENT_FUNCTION.args_count}', addr())) + else: + mips_code += allocate_stack(4) + push_stack(addr(), '($sp)') + pass + CURRENT_FUNCTION.args_count += 1 return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr, '($sp)') @@ -251,16 +271,17 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address = CURRENT_FUNCTION.get_address(allocate.result.id) + address = CURRENT_FUNCTION[str(allocate.result)] code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', address) + mips.SwInstruction('$v0', address()) ] return code + def type_of_to_mips_visitor(typeof: cil.TypeOfNode): """ CIL: @@ -269,45 +290,45 @@ def type_of_to_mips_visitor(typeof: cil.TypeOfNode): lw $t0, [addr(x)] sw ($t0), [addr(t)] """ - x_addr = CURRENT_FUNCTION.get_address(str(typeof.var)) - t_addr = CURRENT_FUNCTION.get_address(str(typeof.result)) + x_addr = CURRENT_FUNCTION[str(typeof.var)] + t_addr = CURRENT_FUNCTION[str(typeof.result)] return [ mips.Comment(str(typeof)), - mips.LwInstruction('$t0', x_addr), - mips.SwInstruction('($t0)', t_addr) + mips.LwInstruction('$t0', x_addr()), + mips.SwInstruction('$t0', t_addr()) ] -def copy_to_mips_visitor(copy: cil.CopyNode): - """ - CIL: - x = COPY y - MIPS: - lw $t0, [addr(y)] - sw $t0, [addr(x)] - """ - x_addr = CURRENT_FUNCTION.get_address(str(copy.result)) - y_addr = CURRENT_FUNCTION.get_address(copy.val) - return [ - mips.Comment(str(copy)), - mips.LwInstruction('$t0', y_addr), - mips.LwInstruction('$t1', '4($t0)'), - mips.MoveInstruction('$a0', '$t1'), - mips.LiInstruction('$v0', 9), - mips.SyscallInstruction(), - mips.SwInstruction('$v0', x_addr), - mips.LiInstruction('$t2', '0'), - mips.MIPSLabel('length_loop'), - mips.BeqInstruction('$t1', '$t2','end_length_loop'), - - mips.MoveInstruction('$t3',x_addr), - mips.AdduInstruction('$t3', '$t3', '$t2'), - mips.MoveInstruction(x_addr, '$t3'), - - mips.AdduInstruction('$t2', '$t2', 4), - mips.BInstruction('length_loop'), - mips.MIPSLabel('end_length_loop'), - ] +# def copy_to_mips_visitor(copy: cil.CopyNode): +# """ +# CIL: +# x = COPY y +# MIPS: +# lw $t0, [addr(y)] +# sw $t0, [addr(x)] +# """ +# x_addr = CURRENT_FUNCTION.get_address(str(copy.result)) +# y_addr = CURRENT_FUNCTION.get_address(copy.val) +# return [ +# mips.Comment(str(copy)), +# mips.LwInstruction('$t0', y_addr), +# mips.LwInstruction('$t1', '4($t0)'), +# mips.MoveInstruction('$a0', '$t1'), +# mips.LiInstruction('$v0', 9), +# mips.SyscallInstruction(), +# mips.SwInstruction('$v0', x_addr), +# mips.LiInstruction('$t2', '0'), +# mips.MIPSLabel('length_loop'), +# mips.BeqInstruction('$t1', '$t2', 'end_length_loop'), + +# mips.MoveInstruction('$t3', x_addr), +# mips.AdduInstruction('$t3', '$t3', '$t2'), +# mips.MoveInstruction(x_addr, '$t3'), + +# mips.AdduInstruction('$t2', '$t2', 4), +# mips.BInstruction('length_loop'), +# mips.MIPSLabel('end_length_loop'), +# ] def getattr_to_mips_visitor(getattr: cil.GetAttrNode): @@ -320,14 +341,14 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(str(getattr.result)) - y_addr = CURRENT_FUNCTION.get_address(getattr.obj) + x_addr = CURRENT_FUNCTION[str(getattr.result)] + y_addr = CURRENT_FUNCTION[str(getattr.obj)] attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), - mips.LwInstruction('$t0', y_addr), + mips.LwInstruction('$t0', y_addr()), mips.LwInstruction('$t1', f'{attr_shift}($t0)'), - mips.SwInstruction('$t1', x_addr) + mips.SwInstruction('$t1', x_addr()) ] @@ -340,14 +361,14 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): lw $t1, [addr(y)] sw $t0, [attr_shift($t1)] """ - - x_addr = CURRENT_FUNCTION.get_address(str(setattr.val)) - y_addr = CURRENT_FUNCTION.get_address(str(setattr.obj)) + + x_addr = CURRENT_FUNCTION[str(setattr.val)] + y_addr = CURRENT_FUNCTION[str(setattr.obj)] attr_shift = (setattr.attr_index + 1) * 4 return [ mips.Comment(str(setattr)), - mips.LwInstruction('$t0', x_addr), - mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t0', x_addr()), + mips.LwInstruction('$t1', y_addr()), mips.SwInstruction('$t0', f'{attr_shift}($t0)') ] @@ -363,9 +384,9 @@ def plus_to_mips_visitor(plus: cil.PlusNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(str(plus.result)) - y_addr = CURRENT_FUNCTION.get_address(str(plus.left)) - z_addr = CURRENT_FUNCTION.get_address(str(plus.right)) + x_addr = CURRENT_FUNCTION[str(plus.result)] + y_addr = CURRENT_FUNCTION[str(plus.left)] + z_addr = CURRENT_FUNCTION[str(plus.right)] instructions = [ mips.Comment(str(plus)) ] @@ -537,6 +558,7 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): 4 - Restore the caller-saved registers. 5 - Extract the return value, if any, from register $v0. """ + CURRENT_FUNCTION.args_count = 0 t = get_type(vcall.type) instructios = [] instructios.append(mips.Comment(str(vcall))) @@ -557,7 +579,8 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): instructios.extend(free_stack(size)) return instructios -def assign_to_mips_visitor(assign:cil.AssignNode): + +def assign_to_mips_visitor(assign: cil.AssignNode): """ CIL: x = y @@ -565,9 +588,9 @@ def assign_to_mips_visitor(assign:cil.AssignNode): lw $t0, [y_addr] sw $t0, [x_addr] """ - y_addr= CURRENT_FUNCTION.get_address(assign.val.id) - x_addr=CURRENT_FUNCTION.get_address(assign.result.id) - + y_addr = CURRENT_FUNCTION.get_address(assign.val.id) + x_addr = CURRENT_FUNCTION.get_address(assign.result.id) + return [ mips.Comment(str(assign)), mips.LwInstruction('$t0', y_addr), @@ -596,7 +619,7 @@ def assign_to_mips_visitor(assign:cil.AssignNode): cil.ConcatNode: concat_to_mips_visitor, cil.LoadNode: load_to_mips_visitor, cil.SubStringNode: substring_to_mips_visitor, - cil.VCAllNode: vcal_to_mips_visitor, - cil.AssignNode: assign_to_mips_visitor, - cil.TypeOfNode:type_of_to_mips_visitor + cil.VCAllNode: vcal_to_mips_visitor, + cil.AssignNode: assign_to_mips_visitor, + cil.TypeOfNode: type_of_to_mips_visitor } diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 827467ed..0e9a4cb8 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -38,12 +38,7 @@ def free_stack(bytes): def push_stack(src, pos): - code = [] - if src[0] != '$': - code = peek_stack('$t0', src) - return code+[mips.SwInstruction('$t0', pos)] - else: - return code+[mips.SwInstruction(src, pos)] + return peek_stack('$t0', src)+[mips.SwInstruction('$t0', pos)] def peek_stack(src, pos): diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 9f87869e..99fc4683 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 7abaee416ecd7fc4cc88cf897aa8db2b7a234f71 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 28 Nov 2020 22:16:57 +0100 Subject: [PATCH 369/435] Check substring --- src/code_generation/MIPS/mips.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a5cdfd52..718fb026 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -101,9 +101,7 @@ def print_to_mips_visitor(p: cil.PrintNode): li $v0, 4 syscall """ - - - + offset = CURRENT_FUNCTION.offset(p.str) code = [mips.Comment(str(p)), mips.LwInstruction('$a0', f'{offset}(fp)')] @@ -134,7 +132,7 @@ def read_to_mips_visitor(read: cil.ReadNode): CIL: x = READ ; MIPS: - + .data x: .space 1024 .text @@ -143,12 +141,12 @@ def read_to_mips_visitor(read: cil.ReadNode): li $v0, 8 syscall sw $a0, shift(x) - - + + """ offset = CURRENT_FUNCTION.offset(str(read.result)) __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(1024))) - + return [ mips.LaInstruction('$a0', str(read.result)), mips.LiInstruction('$a1', 1024), @@ -160,18 +158,18 @@ def read_to_mips_visitor(read: cil.ReadNode): # TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): - addr = CURRENT_FUNCTION.get_address(ss.str) - i = CURRENT_FUNCTION.get_address(ss.i) - l = CURRENT_FUNCTION.get_address(ss.len) + str_offset = CURRENT_FUNCTION.offset[ss.str] + i_offset = CURRENT_FUNCTION.offset[ss.i] + len_offset = CURRENT_FUNCTION.offset[ss.len] __DATA__.append(mips.MIPSDataItem( ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) - code = [ + return [ mips.Comment(str(ss)), - mips.LaInstruction('$t0', addr), + mips.LwInstruction('$t0', f'{str_offset}($fp)'), mips.LaInstruction('$t1', ss.result.id), - mips.LwInstruction('$t4', i), - mips.LwInstruction('$t2', l), + mips.LwInstruction('$t4', f'{i_offset}($fp)'), + mips.LwInstruction('$t2', f'{len_offset}($fp)'), mips.AdduInstruction('$t0', '$t0', '$t4'), mips.MIPSLabel('substring_loop'), mips.BeqzInstruction('$t2', 'end_substring_loop'), @@ -183,7 +181,6 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.BInstruction('substring_loop'), mips.MIPSLabel('end_substring_loop') ] - return code # TODO: Check @@ -244,7 +241,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - offset=CURRENT_FUNCTION.offset[load.result] + offset = CURRENT_FUNCTION.offset[load.result] return [ mips.Comment(str(load)), mips.LaInstruction('$t0', load.addr), @@ -612,7 +609,7 @@ def assign_to_mips_visitor(assign: cil.AssignNode): __visitors__ = { cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, - cil.CopyNode: copy_to_mips_visitor, + # cil.CopyNode: copy_to_mips_visitor, cil.GetAttrNode: getattr_to_mips_visitor, cil.SetAttrNode: setattr_to_mips_visitor, cil.PlusNode: plus_to_mips_visitor, From bf0471a36ff328720cb10d0c336cd595e98dc5fa Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 16:46:03 -0500 Subject: [PATCH 370/435] adding read and int --- src/code_generation/MIPS/mips.py | 51 ++++++++++++++++----------- src/code_generation/MIPS/utilities.py | 1 + 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 786ad8bf..a5cdfd52 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -93,20 +93,20 @@ def print_to_mips_visitor(p: cil.PrintNode): CIL: PRINT z; MIPS if z is str: - move $a0, $fp - addu $a0, $a0, shift(z) - li $v0, 4 - syscall + lw $a0, shift(z) + li $v0, 4 + syscall MIPS if z is int: - move $a0, $fp - addu $a0, $a0, shift(z) - li $v0, 1 - syscall + lw $a0, 4($sp) + li $v0, 4 + syscall """ + + + offset = CURRENT_FUNCTION.offset(p.str) code = [mips.Comment(str(p)), - mips.MoveInstruction('$a0', '$fp'), - mips.AdduInstruction('$a0', '$a0', offset)] + mips.LwInstruction('$a0', f'{offset}(fp)')] if p.str == 'int': code.append(mips.LiInstruction('$v0', 1)) # li $v0, 1 elif p.str == 'str': @@ -134,20 +134,27 @@ def read_to_mips_visitor(read: cil.ReadNode): CIL: x = READ ; MIPS: - addu $a0, $fp, shift(x) - li $a1, 1024 - li $v0, 8 - syscall - subu $sp, $a0, 1024 + + .data + x: .space 1024 + .text + la $a0, x + li $a1, 1024 + li $v0, 8 + syscall + sw $a0, shift(x) + + """ offset = CURRENT_FUNCTION.offset(str(read.result)) - + __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(1024))) + return [ - mips.AdduInstruction('$a0', '$fp', offset), + mips.LaInstruction('$a0', str(read.result)), mips.LiInstruction('$a1', 1024), mips.LiInstruction('$v0', 8), mips.SyscallInstruction(), - mips.SubuInstruction('$sp', '$a0', 1024) + mips.SwInstruction('$a0', f'{offset}($fp)') ] @@ -237,8 +244,12 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - save_address(load.result, load.addr) - return [] + offset=CURRENT_FUNCTION.offset[load.result] + return [ + mips.Comment(str(load)), + mips.LaInstruction('$t0', load.addr), + mips.SwInstruction('$t0', f'{offset}($sp)') + ] def arg_to_mips_visitor(arg: cil.ArgNode): diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 0e9a4cb8..8bcbdb13 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -46,6 +46,7 @@ def peek_stack(src, pos): def save_address(key, value): + if type(value) is int: if value: __ADDRS__[key] = f'{value}($sp)' From 4c770f4aba1532e9c48fd666cd2a91cc16c567fb Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 28 Nov 2020 22:55:20 +0100 Subject: [PATCH 371/435] Make concat --- src/code_generation/MIPS/mips.py | 39 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 35f253b9..e8828cd1 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -214,30 +214,35 @@ def length_to_mips_visitor(length: cil.LengthNode): return code -# TODO: Check def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) - save_address(concat.result, concat.result.id) - a = CURRENT_FUNCTION[concat.str_a] - b = CURRENT_FUNCTION[concat.str_b] + result_offset = CURRENT_FUNCTION.offset[concat.result.id] + a_offset = CURRENT_FUNCTION.offset[concat.str_a] + b_offset = CURRENT_FUNCTION.offset[concat.str_b] - code = [ + return [ mips.Comment(str(concat)), - mips.LwInstruction('$t0', a()), - mips.SwInstruction('$t0', concat.result), - mips.LbInstruction('$t1', concat.result), - mips.MIPSLabel('length_loop'), - mips.BeqzInstruction('$t1', 'end_length_loop'), + mips.LaInstruction('$t0', 0), + mips.LaInstruction('$t1', 0), + mips.LaInstruction('$t2', 0), + mips.MIPSLabel('concat_loop_a'), + mips.LbInstruction('$a0', '($t1)'), + mips.BeqzInstruction('$a0', 'concat_loop_b'), + mips.SbInstruction('$a0', '($t0)'), + mips.AdduInstruction('$t0', '$t0', 1), mips.AdduInstruction('$t1', '$t1', 1), - mips.BInstruction('length_loop'), - mips.MIPSLabel('end_length_loop'), - mips.LwInstruction('$t2', b()), - mips.SwInstruction('$t2', '($t1)') + mips.BInstruction('concat_loop_a'), + mips.MIPSLabel('concat_loop_b'), + mips.LbInstruction('$a0', '($t2)'), + mips.BeqzInstruction('$a0', 'end_concat'), + mips.SbInstruction('$a0', '($t0)'), + mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t2', '$t2', 1), + mips.BInstruction('concat_loop_b'), + mips.MIPSLabel('end_concat') ] - return code - def load_to_mips_visitor(load: cil.LoadNode): offset = CURRENT_FUNCTION.offset[load.result] @@ -255,7 +260,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg))] + mips.LwInstruction('$t0', f'{offset}($fp)')+ mips.SubuInstruction('$sp', '$sp', 4) + mips.SwInstruction('$t0','($sp)') + return [mips.Comment(str(arg))] + mips.LwInstruction('$t0', f'{offset}($fp)') + mips.SubuInstruction('$sp', '$sp', 4) + mips.SwInstruction('$t0', '($sp)') def allocate_to_mips_visitor(allocate: cil.AllocateNode): From ba22b1e43b536212be28d3ed872bdd8a7e620bc1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:04:35 -0500 Subject: [PATCH 372/435] arg_to_mips --- src/code_generation/MIPS/mips.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a5cdfd52..e9a15a47 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -186,7 +186,6 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): return code -# TODO: Check def read_int_to_mips_visitor(read: cil.ReadIntNode): addr = CURRENT_FUNCTION.get_address(str(read.result)) code = [ @@ -258,17 +257,8 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr = CURRENT_FUNCTION[str(arg.val)] - location = CURRENT_FUNCTION.location[str(arg.val)] - mips_code = [mips.Comment(str(arg))] - if CURRENT_FUNCTION.args_count < 4: - mips_code.append(mips.LwInstruction( - f'$a{CURRENT_FUNCTION.args_count}', addr())) - else: - mips_code += allocate_stack(4) + push_stack(addr(), '($sp)') - pass - CURRENT_FUNCTION.args_count += 1 - return [mips.Comment(str(arg))] + allocate_stack(4) + push_stack(addr, '($sp)') + addr = CURRENT_FUNCTION.offset[str(arg.val)] + return [mips.Comment(str(arg))] + mips.SubuInstruction('$sp', '$sp', 4) + mips.LwInstruction('$t0', f'{offset}($fp)') + mips.SwInstruction('$t0','($sp)') def allocate_to_mips_visitor(allocate: cil.AllocateNode): From d11c8597450e8fab7b7659964a6ed4a527d4b834 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:10:06 -0500 Subject: [PATCH 373/435] fixing arg to mips --- src/code_generation/MIPS/mips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index e9a15a47..471ccb67 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -258,7 +258,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg))] + mips.SubuInstruction('$sp', '$sp', 4) + mips.LwInstruction('$t0', f'{offset}($fp)') + mips.SwInstruction('$t0','($sp)') + return [mips.Comment(str(arg))] + mips.LwInstruction('$t0', f'{offset}($fp)')+ mips.SubuInstruction('$sp', '$sp', 4) + mips.SwInstruction('$t0','($sp)') def allocate_to_mips_visitor(allocate: cil.AllocateNode): From de7e05283f891fdc82fdc79c52e954426b55c0d5 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:13:58 -0500 Subject: [PATCH 374/435] add allocate_to_mips --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 471ccb67..548cbdd9 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -272,13 +272,13 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): sw $v0, [addr(x)] """ size = get_type(allocate.type).size_mips - address = CURRENT_FUNCTION[str(allocate.result)] + address = CURRENT_FUNCTION.offset[str(allocate.result)] code = [ mips.Comment(str(allocate)), mips.LiInstruction('$a0', size), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', address()) + mips.SwInstruction('$v0', f'{address}($fp)') ] return code From d172f21eb83aa927e4deef1304dead1fd8f6c60a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:14:50 -0500 Subject: [PATCH 375/435] add type_of to mips --- src/code_generation/MIPS/mips.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 548cbdd9..4cd888e5 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -291,12 +291,12 @@ def type_of_to_mips_visitor(typeof: cil.TypeOfNode): lw $t0, [addr(x)] sw ($t0), [addr(t)] """ - x_addr = CURRENT_FUNCTION[str(typeof.var)] - t_addr = CURRENT_FUNCTION[str(typeof.result)] + x_addr = CURRENT_FUNCTION.offset[str(typeof.var)] + t_addr = CURRENT_FUNCTION.offset[str(typeof.result)] return [ mips.Comment(str(typeof)), - mips.LwInstruction('$t0', x_addr()), - mips.SwInstruction('$t0', t_addr()) + mips.LwInstruction('$t0', f'{x_addr}($fp)'), + mips.SwInstruction('$t0', f'{t_addr}($fp)') ] From 9c5a9be2490cc16e5b4eea5db5cdbd4a2c75e9b4 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:16:41 -0500 Subject: [PATCH 376/435] add get_attr to mips --- src/code_generation/MIPS/mips.py | 40 ++++---------------------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4cd888e5..02b0efe5 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -300,38 +300,6 @@ def type_of_to_mips_visitor(typeof: cil.TypeOfNode): ] -# def copy_to_mips_visitor(copy: cil.CopyNode): -# """ -# CIL: -# x = COPY y -# MIPS: -# lw $t0, [addr(y)] -# sw $t0, [addr(x)] -# """ -# x_addr = CURRENT_FUNCTION.get_address(str(copy.result)) -# y_addr = CURRENT_FUNCTION.get_address(copy.val) -# return [ -# mips.Comment(str(copy)), -# mips.LwInstruction('$t0', y_addr), -# mips.LwInstruction('$t1', '4($t0)'), -# mips.MoveInstruction('$a0', '$t1'), -# mips.LiInstruction('$v0', 9), -# mips.SyscallInstruction(), -# mips.SwInstruction('$v0', x_addr), -# mips.LiInstruction('$t2', '0'), -# mips.MIPSLabel('length_loop'), -# mips.BeqInstruction('$t1', '$t2', 'end_length_loop'), - -# mips.MoveInstruction('$t3', x_addr), -# mips.AdduInstruction('$t3', '$t3', '$t2'), -# mips.MoveInstruction(x_addr, '$t3'), - -# mips.AdduInstruction('$t2', '$t2', 4), -# mips.BInstruction('length_loop'), -# mips.MIPSLabel('end_length_loop'), -# ] - - def getattr_to_mips_visitor(getattr: cil.GetAttrNode): """ CIL: @@ -342,14 +310,14 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): sw $t1, [addr(x)] """ - x_addr = CURRENT_FUNCTION[str(getattr.result)] - y_addr = CURRENT_FUNCTION[str(getattr.obj)] + x_addr = CURRENT_FUNCTION.offset[str(getattr.result)] + y_addr = CURRENT_FUNCTION.offset[str(getattr.obj)] attr_shift = (getattr.attr_index + 1) * 4 return [ mips.Comment(str(getattr)), - mips.LwInstruction('$t0', y_addr()), + mips.LwInstruction('$t0', f'{y_addr}($fp)'), mips.LwInstruction('$t1', f'{attr_shift}($t0)'), - mips.SwInstruction('$t1', x_addr()) + mips.SwInstruction('$t1', f'{x_addr}($fp)') ] From 7b3c1b6736c4c175758baff3bd80961483570603 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:18:05 -0500 Subject: [PATCH 377/435] add set_attr to mips --- src/code_generation/MIPS/mips.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 02b0efe5..fae6f04c 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -331,14 +331,14 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): sw $t0, [attr_shift($t1)] """ - x_addr = CURRENT_FUNCTION[str(setattr.val)] - y_addr = CURRENT_FUNCTION[str(setattr.obj)] + x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] + y_addr = CURRENT_FUNCTION.offset[str(setattr.obj)] attr_shift = (setattr.attr_index + 1) * 4 return [ mips.Comment(str(setattr)), - mips.LwInstruction('$t0', x_addr()), - mips.LwInstruction('$t1', y_addr()), - mips.SwInstruction('$t0', f'{attr_shift}($t0)') + mips.LwInstruction('$t0', f'{x_addr}($fp)'), + mips.LwInstruction('$t1', f'{y_addr}($fp)'), + mips.SwInstruction('$t0', f'{attr_shift}($t1)') ] From 8b17534d299895cdd540d05bcbf30ecf3c1d26a5 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:19:20 -0500 Subject: [PATCH 378/435] add assign to mips --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index fae6f04c..4cbe8421 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -557,8 +557,8 @@ def assign_to_mips_visitor(assign: cil.AssignNode): lw $t0, [y_addr] sw $t0, [x_addr] """ - y_addr = CURRENT_FUNCTION.get_address(assign.val.id) - x_addr = CURRENT_FUNCTION.get_address(assign.result.id) + y_addr = CURRENT_FUNCTION.offset[str(assign.val)] + x_addr = CURRENT_FUNCTION[str(assign.result)] return [ mips.Comment(str(assign)), From e9370a07f283f10abd20b21b27a94aeb7151ce1d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:31:50 -0500 Subject: [PATCH 379/435] fixing errors --- src/code_generation/CIL/cil.py | 6 ++--- src/code_generation/MIPS/mips.py | 38 +++++++++++++++++--------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index d1660b9d..36ca5bfb 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -163,17 +163,17 @@ def copy_to_cil(): def length_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('len_result') return CilAST.FuncNode('length_String', [CilAST.ParamNode('self')], [result], [CilAST.LengthNode('self', result), CilAST.ReturnNode(result)]) def concat_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('concat_result') return CilAST.FuncNode('concat_String', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) def substring_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('substring_result') return CilAST.FuncNode('substr_String', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 471ccb67..24901240 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -104,7 +104,7 @@ def print_to_mips_visitor(p: cil.PrintNode): - offset = CURRENT_FUNCTION.offset(p.str) + offset = CURRENT_FUNCTION.offset[str(p.str)] code = [mips.Comment(str(p)), mips.LwInstruction('$a0', f'{offset}(fp)')] if p.str == 'int': @@ -146,12 +146,12 @@ def read_to_mips_visitor(read: cil.ReadNode): """ - offset = CURRENT_FUNCTION.offset(str(read.result)) - __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(1024))) + offset = CURRENT_FUNCTION.offset[str(read.result)] + __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) return [ mips.LaInstruction('$a0', str(read.result)), - mips.LiInstruction('$a1', 1024), + mips.LiInstruction('$a1', __BUFFSIZE__), mips.LiInstruction('$v0', 8), mips.SyscallInstruction(), mips.SwInstruction('$a0', f'{offset}($fp)') @@ -160,9 +160,9 @@ def read_to_mips_visitor(read: cil.ReadNode): # TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): - addr = CURRENT_FUNCTION.get_address(ss.str) - i = CURRENT_FUNCTION.get_address(ss.i) - l = CURRENT_FUNCTION.get_address(ss.len) + addr = CURRENT_FUNCTION.offset[str(ss.str)] + i = CURRENT_FUNCTION.offset[str(ss.i)] + l = CURRENT_FUNCTION.offset[str(ss.len)] __DATA__.append(mips.MIPSDataItem( ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) @@ -187,7 +187,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): def read_int_to_mips_visitor(read: cil.ReadIntNode): - addr = CURRENT_FUNCTION.get_address(str(read.result)) + addr = CURRENT_FUNCTION.offset[str(read.result)] code = [ mips.Comment(str(read)), mips.LiInstruction('$v0', 5), @@ -199,12 +199,12 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): # TODO: Check def length_to_mips_visitor(length: cil.LengthNode): - val = CURRENT_FUNCTION[length.str] - result_val = CURRENT_FUNCTION[str(length.result)] + val = CURRENT_FUNCTION.offset[str(length.str)] + result_val = CURRENT_FUNCTION.offset[str(length.result)] code = [ mips.Comment(str(length)), - mips.LbInstruction('$t0', val()), + mips.LbInstruction('$t0', f'{val}($fp)'), mips.LiInstruction('$t1', 0), mips.MIPSLabel('length_loop'), mips.BeqzInstruction('$t0', 'end_length_loop'), @@ -212,7 +212,7 @@ def length_to_mips_visitor(length: cil.LengthNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.SwInstruction('$t1', result_val()) + mips.SwInstruction('$t1', f'{result_val}($fp)') ] return code @@ -222,12 +222,12 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) save_address(concat.result, concat.result.id) - a = CURRENT_FUNCTION[concat.str_a] - b = CURRENT_FUNCTION[concat.str_b] + a = CURRENT_FUNCTION.offset[str(concat.str_a)] + b = CURRENT_FUNCTION.offset[str(concat.str_b)] code = [ mips.Comment(str(concat)), - mips.LwInstruction('$t0', a()), + mips.LwInstruction('$t0', f'{a}($fp)'), mips.SwInstruction('$t0', concat.result), mips.LbInstruction('$t1', concat.result), mips.MIPSLabel('length_loop'), @@ -235,7 +235,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.LwInstruction('$t2', b()), + mips.LwInstruction('$t2', f'{b}($fp)'), mips.SwInstruction('$t2', '($t1)') ] @@ -243,7 +243,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - offset=CURRENT_FUNCTION.offset[load.result] + offset=CURRENT_FUNCTION.offset[str(load.result)] return [ mips.Comment(str(load)), mips.LaInstruction('$t0', load.addr), @@ -258,7 +258,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg))] + mips.LwInstruction('$t0', f'{offset}($fp)')+ mips.SubuInstruction('$sp', '$sp', 4) + mips.SwInstruction('$t0','($sp)') + return [mips.Comment(str(arg)),mips.LwInstruction('$t0', f'{addr}($fp)'),mips.SubuInstruction('$sp', '$sp', 4) , mips.SwInstruction('$t0','($sp)')] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -598,6 +598,8 @@ def assign_to_mips_visitor(assign: cil.AssignNode): mips.SwInstruction('$t0', x_addr) ] +def copy_to_mips_visitor(copy: cil.CopyNode): + return [] __visitors__ = { cil.ArgNode: arg_to_mips_visitor, From 9dd57a82e203e036568716eead7df270b9b21292 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 17:31:50 -0500 Subject: [PATCH 380/435] fixing errors --- src/code_generation/CIL/cil.py | 6 ++--- src/code_generation/MIPS/mips.py | 44 +++++++++++++++++--------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index d1660b9d..36ca5bfb 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -163,17 +163,17 @@ def copy_to_cil(): def length_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('len_result') return CilAST.FuncNode('length_String', [CilAST.ParamNode('self')], [result], [CilAST.LengthNode('self', result), CilAST.ReturnNode(result)]) def concat_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('concat_result') return CilAST.FuncNode('concat_String', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) def substring_to_cil(): - result = CilAST.LocalNode('result') + result = CilAST.LocalNode('substring_result') return CilAST.FuncNode('substr_String', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f9e73e03..7fbbd71e 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -101,8 +101,10 @@ def print_to_mips_visitor(p: cil.PrintNode): li $v0, 4 syscall """ - - offset = CURRENT_FUNCTION.offset(p.str) + + + + offset = CURRENT_FUNCTION.offset[str(p.str)] code = [mips.Comment(str(p)), mips.LwInstruction('$a0', f'{offset}(fp)')] if p.str == 'int': @@ -144,12 +146,12 @@ def read_to_mips_visitor(read: cil.ReadNode): """ - offset = CURRENT_FUNCTION.offset(str(read.result)) - __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(1024))) - + offset = CURRENT_FUNCTION.offset[str(read.result)] + __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) + return [ mips.LaInstruction('$a0', str(read.result)), - mips.LiInstruction('$a1', 1024), + mips.LiInstruction('$a1', __BUFFSIZE__), mips.LiInstruction('$v0', 8), mips.SyscallInstruction(), mips.SwInstruction('$a0', f'{offset}($fp)') @@ -158,9 +160,9 @@ def read_to_mips_visitor(read: cil.ReadNode): # TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): - str_offset = CURRENT_FUNCTION.offset[ss.str] - i_offset = CURRENT_FUNCTION.offset[ss.i] - len_offset = CURRENT_FUNCTION.offset[ss.len] + addr = CURRENT_FUNCTION.offset[str(ss.str)] + i = CURRENT_FUNCTION.offset[str(ss.i)] + l = CURRENT_FUNCTION.offset[str(ss.len)] __DATA__.append(mips.MIPSDataItem( ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) @@ -184,7 +186,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): def read_int_to_mips_visitor(read: cil.ReadIntNode): - addr = CURRENT_FUNCTION.get_address(str(read.result)) + addr = CURRENT_FUNCTION.offset[str(read.result)] code = [ mips.Comment(str(read)), mips.LiInstruction('$v0', 5), @@ -196,12 +198,12 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): # TODO: Check def length_to_mips_visitor(length: cil.LengthNode): - val = CURRENT_FUNCTION[length.str] - result_val = CURRENT_FUNCTION[str(length.result)] + val = CURRENT_FUNCTION.offset[str(length.str)] + result_val = CURRENT_FUNCTION.offset[str(length.result)] code = [ mips.Comment(str(length)), - mips.LbInstruction('$t0', val()), + mips.LbInstruction('$t0', f'{val}($fp)'), mips.LiInstruction('$t1', 0), mips.MIPSLabel('length_loop'), mips.BeqzInstruction('$t0', 'end_length_loop'), @@ -209,7 +211,7 @@ def length_to_mips_visitor(length: cil.LengthNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.SwInstruction('$t1', result_val()) + mips.SwInstruction('$t1', f'{result_val}($fp)') ] return code @@ -219,12 +221,12 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) save_address(concat.result, concat.result.id) - a = CURRENT_FUNCTION[concat.str_a] - b = CURRENT_FUNCTION[concat.str_b] + a = CURRENT_FUNCTION.offset[str(concat.str_a)] + b = CURRENT_FUNCTION.offset[str(concat.str_b)] code = [ mips.Comment(str(concat)), - mips.LwInstruction('$t0', a()), + mips.LwInstruction('$t0', f'{a}($fp)'), mips.SwInstruction('$t0', concat.result), mips.LbInstruction('$t1', concat.result), mips.MIPSLabel('length_loop'), @@ -232,7 +234,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), - mips.LwInstruction('$t2', b()), + mips.LwInstruction('$t2', f'{b}($fp)'), mips.SwInstruction('$t2', '($t1)') ] @@ -240,7 +242,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - offset = CURRENT_FUNCTION.offset[load.result] + offset=CURRENT_FUNCTION.offset[str(load.result)] return [ mips.Comment(str(load)), mips.LaInstruction('$t0', load.addr), @@ -255,7 +257,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg))] + mips.LwInstruction('$t0', f'{offset}($fp)')+ mips.SubuInstruction('$sp', '$sp', 4) + mips.SwInstruction('$t0','($sp)') + return [mips.Comment(str(arg)),mips.LwInstruction('$t0', f'{addr}($fp)'),mips.SubuInstruction('$sp', '$sp', 4) , mips.SwInstruction('$t0','($sp)')] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -563,6 +565,8 @@ def assign_to_mips_visitor(assign: cil.AssignNode): mips.SwInstruction('$t0', x_addr) ] +def copy_to_mips_visitor(copy: cil.CopyNode): + return [] __visitors__ = { cil.ArgNode: arg_to_mips_visitor, From ad1ea30cfaa3f75160d6e07b820a4192aeb46d65 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 18:07:17 -0500 Subject: [PATCH 381/435] add copy to mips --- src/code_generation/MIPS/mips.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 7fbbd71e..cbb54329 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -566,12 +566,32 @@ def assign_to_mips_visitor(assign: cil.AssignNode): ] def copy_to_mips_visitor(copy: cil.CopyNode): + x_addr = CURRENT_FUNCTION.offset[str(copy.val)] + y_addr=CURRENT_FUNCTION.offset[str(copy.result)] + return [ + mips.Comment(str(copy)), + mips.LwInstruction('$a0', f'{x_addr+8}($fp)', x_addr+8), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{y_addr}($fp)'), + mips.AdduInstruction('$t1','$fp',x_addr), + mips.AdduInstruction('$t2', '$fp', y_addr), + mips.MIPSLabel('copy_loop'), + mips.LwInstruction('$t0', '($t1)'), + mips.SwInstruction('$t0', '($t2)'), + mips.AdduInstruction('$t1', '$t1', 4), + mips.AdduInstruction('$t2', '$t2', 4), + mips.SubuInstruction('$a0', '$a0', 4), + mips.BeqzInstruction('$a0', 'end_copy_loop'), + mips.BInstruction('copy_loop'), + mips.MIPSLabel('end_copy_loop') + ] return [] __visitors__ = { cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, - # cil.CopyNode: copy_to_mips_visitor, + cil.CopyNode: copy_to_mips_visitor, cil.GetAttrNode: getattr_to_mips_visitor, cil.SetAttrNode: setattr_to_mips_visitor, cil.PlusNode: plus_to_mips_visitor, From 401f638f77ab5f118ee36b32979f9b9a7df83340 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 29 Nov 2020 01:24:15 +0100 Subject: [PATCH 382/435] Fix var names in substring visitor --- src/code_generation/MIPS/mips.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index c2440ee3..7725550b 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -101,9 +101,7 @@ def print_to_mips_visitor(p: cil.PrintNode): li $v0, 4 syscall """ - - - + offset = CURRENT_FUNCTION.offset[str(p.str)] code = [mips.Comment(str(p)), mips.LwInstruction('$a0', f'{offset}(fp)')] @@ -147,8 +145,9 @@ def read_to_mips_visitor(read: cil.ReadNode): """ offset = CURRENT_FUNCTION.offset[str(read.result)] - __DATA__.append(mips.MIPSDataItem(read.result, mips.SpaceInst(__BUFFSIZE__))) - + __DATA__.append(mips.MIPSDataItem( + read.result, mips.SpaceInst(__BUFFSIZE__))) + return [ mips.LaInstruction('$a0', str(read.result)), mips.LiInstruction('$a1', __BUFFSIZE__), @@ -160,9 +159,9 @@ def read_to_mips_visitor(read: cil.ReadNode): # TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): - addr = CURRENT_FUNCTION.offset[str(ss.str)] - i = CURRENT_FUNCTION.offset[str(ss.i)] - l = CURRENT_FUNCTION.offset[str(ss.len)] + str_offset = CURRENT_FUNCTION.offset[str(ss.str)] + i_offset = CURRENT_FUNCTION.offset[str(ss.i)] + len_offset = CURRENT_FUNCTION.offset[str(ss.len)] __DATA__.append(mips.MIPSDataItem( ss.result.id, mips.SpaceInst(__BUFFSIZE__))) save_address(ss.result, ss.result.id) @@ -247,7 +246,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): def load_to_mips_visitor(load: cil.LoadNode): - offset=CURRENT_FUNCTION.offset[str(load.result)] + offset = CURRENT_FUNCTION.offset[str(load.result)] return [ mips.Comment(str(load)), mips.LaInstruction('$t0', load.addr), @@ -262,7 +261,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 2) Pushes the arg value in the stack\n ''' addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg)),mips.LwInstruction('$t0', f'{addr}($fp)'),mips.SubuInstruction('$sp', '$sp', 4) , mips.SwInstruction('$t0','($sp)')] + return [mips.Comment(str(arg)), mips.LwInstruction('$t0', f'{addr}($fp)'), mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -570,16 +569,17 @@ def assign_to_mips_visitor(assign: cil.AssignNode): mips.SwInstruction('$t0', x_addr) ] + def copy_to_mips_visitor(copy: cil.CopyNode): x_addr = CURRENT_FUNCTION.offset[str(copy.val)] - y_addr=CURRENT_FUNCTION.offset[str(copy.result)] + y_addr = CURRENT_FUNCTION.offset[str(copy.result)] return [ mips.Comment(str(copy)), mips.LwInstruction('$a0', f'{x_addr+8}($fp)', x_addr+8), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.SwInstruction('$v0', f'{y_addr}($fp)'), - mips.AdduInstruction('$t1','$fp',x_addr), + mips.AdduInstruction('$t1', '$fp', x_addr), mips.AdduInstruction('$t2', '$fp', y_addr), mips.MIPSLabel('copy_loop'), mips.LwInstruction('$t0', '($t1)'), @@ -593,6 +593,7 @@ def copy_to_mips_visitor(copy: cil.CopyNode): ] return [] + __visitors__ = { cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, From 53b2b21385dc48a1dbc53f54d2665aabbf1a7c2b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 22:13:07 -0500 Subject: [PATCH 383/435] ya se imprime hello_world --- src/code_generation/MIPS/ast.py | 4 - src/code_generation/MIPS/mips.py | 20 +-- src/code_generation/MIPS/test.asm | 219 ++++++++++++++++++++++++++++++ src/lexer_parser/parsetab.py | 5 +- 4 files changed, 233 insertions(+), 15 deletions(-) create mode 100644 src/code_generation/MIPS/test.asm diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 9deee3ae..d5a1f529 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -53,10 +53,6 @@ def __str__(self): return self.register -LOCATION_REG = 'register' -LCOATION_ADDR = 'address' - - class MIPSFunction: def __init__(self, name, params, locals): self.name = name diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 7725550b..3d7fb935 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -33,7 +33,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): # Build .data section # vt_space_code = reserve_virtual_tables_space(program) - __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(d.val)) + __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(f'"{d.val}"')) for d in program.data] data_section = mips.MIPSDataSection(__DATA__) @@ -104,7 +104,7 @@ def print_to_mips_visitor(p: cil.PrintNode): offset = CURRENT_FUNCTION.offset[str(p.str)] code = [mips.Comment(str(p)), - mips.LwInstruction('$a0', f'{offset}(fp)')] + mips.LwInstruction('$a0', f'{offset}($fp)')] if p.str == 'int': code.append(mips.LiInstruction('$v0', 1)) # li $v0, 1 elif p.str == 'str': @@ -250,7 +250,7 @@ def load_to_mips_visitor(load: cil.LoadNode): return [ mips.Comment(str(load)), mips.LaInstruction('$t0', load.addr), - mips.SwInstruction('$t0', f'{offset}($sp)') + mips.SwInstruction('$t0', f'{offset}($fp)') ] @@ -536,19 +536,23 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): instructios.append(mips.Comment(str(vcall))) # 1 size = len(CURRENT_FUNCTION.caller_saved_reg) * 4 - instructios.extend(allocate_stack(size)) + instructios.append(mips.SubuInstruction('$sp', '$sp', size)) + #instructios.extend(allocate_stack(size)) s = size for reg in CURRENT_FUNCTION.caller_saved_reg: s -= 4 - instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) + instructios.append(mips.SwInstruction(f'${reg}', f'{s}($sp)')) + #instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) # 2 instructios.append(mips.JalInstruction(__VT__[(vcall.type, vcall.method)])) # 4 s = size for reg in CURRENT_FUNCTION.caller_saved_reg: s -= 4 - instructios.extend(peek_stack(f'${reg}', f'{s}($sp)')) - instructios.extend(free_stack(size)) + instructios.append(mips.LwInstruction(f'${reg}', f'{s}($sp)')) + #instructios.extend(peek_stack(f'${reg}', f'{s}($sp)')) + instructios.append(mips.AdduInstruction('$sp', '$sp', size)) + #instructios.extend(free_stack(size)) return instructios @@ -575,7 +579,7 @@ def copy_to_mips_visitor(copy: cil.CopyNode): y_addr = CURRENT_FUNCTION.offset[str(copy.result)] return [ mips.Comment(str(copy)), - mips.LwInstruction('$a0', f'{x_addr+8}($fp)', x_addr+8), + mips.LwInstruction('$a0', f'{x_addr+8}($fp)'), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.SwInstruction('$v0', f'{y_addr}($fp)'), diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm new file mode 100644 index 00000000..6c985e10 --- /dev/null +++ b/src/code_generation/MIPS/test.asm @@ -0,0 +1,219 @@ + +.text +main: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # __main__ = ALLOCATE Main ; + li $a0, 8 + li $v0, 9 + syscall + sw $v0, -4($fp) + # ARG __main__ ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # main_result = VCALL Main main ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal Main_main + lw $t0, 0($sp) + addu $sp, $sp, 4 + addu $sp, $sp, 12 +IO_out_int: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # PRINT int ; + lw $a0, 4($fp) + li $v0, 1 + syscall + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 4 +IO_out_string: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # PRINT str ; + lw $a0, 4($fp) + li $v0, 4 + syscall + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 4 +IO_in_string: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + la $a0, str + li $a1, 1024 + li $v0, 8 + syscall + sw $a0, -4($fp) + # RETURN str ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +IO_in_int: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # int = READINT ; + li $v0, 5 + syscall + sw $v0, -4 + # RETURN int ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +Object_type_name: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # type = TYPEOF self ; + lw $t0, 0($fp) + sw $t0, -4($fp) + # RETURN type ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +Object_copy: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # copy = COPY self ; + lw $a0, 8($fp) + li $v0, 9 + syscall + sw $v0, -4($fp) + addu $t1, $fp, 0 + addu $t2, $fp, -4 + copy_loop: + + lw $t0, ($t1) + sw $t0, ($t2) + addu $t1, $t1, 4 + addu $t2, $t2, 4 + subu $a0, $a0, 4 + beqz $a0, end_copy_loop + b copy_loop + end_copy_loop: + + # RETURN copy ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +length_String: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # len_result = LENGTH self ; + lb $t0, 0($fp) + li $t1, 0 + length_loop: + + beqz $t0, end_length_loop + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b length_loop + end_length_loop: + + sw $t1, -4($fp) + # RETURN len_result ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +concat_String: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # concat_result = CONCAT self x ; + la $t0, 0 + la $t1, 0 + la $t2, 0 + concat_loop_a: + + lb $a0, ($t1) + beqz $a0, concat_loop_b + sb $a0, ($t0) + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b concat_loop_a + concat_loop_b: + + lb $a0, ($t2) + beqz $a0, end_concat + sb $a0, ($t0) + addu $t0, $t0, 1 + addu $t2, $t2, 1 + b concat_loop_b + end_concat: + + # RETURN concat_result ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +substr_String: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # substring_result = SUBSTRING self i l; + lw $t0, 0($fp) + la $t1, substring_result + lw $t4, 4($fp) + lw $t2, 8($fp) + addu $t0, $t0, $t4 + substring_loop: + + beqz $t2, end_substring_loop + lb $t3, ($t0) + sb $t3, ($t1) + subu $t2, $t2, 1 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b substring_loop + end_substring_loop: + + # RETURN substring_result ; + lw $v0, -4($fp) + addu $sp, $sp, 8 +Main_main: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # local_0 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -4($fp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Main out_string ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal IO_out_string + lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + +.data + data_1: + .asciiz "Hello, World.\n" + str: + .space 1024 + concat_result: + .space 2048 + substring_result: + .space 1024 diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 99fc4683..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 24922688d013e92a12bba05121e01ec9701c667f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 22:27:50 -0500 Subject: [PATCH 384/435] finally --- src/code_generation/MIPS/ast.py | 18 +++--------------- src/code_generation/MIPS/mips.py | 6 +++--- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index d5a1f529..359232b3 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -38,21 +38,6 @@ def __str__(self): return f'{self.name}:\n' -class Recipient: - def __init__(self, register: str, shift: int = 0): - self.register = register - self.shift = shift - - def __call__(self) -> str: - # Get content - if self.shift != 0: - return f'{self.shift}({self.register})' - return f'({self.register})' - - def __str__(self): - return self.register - - class MIPSFunction: def __init__(self, name, params, locals): self.name = name @@ -104,6 +89,9 @@ def end(self): '$sp', '$sp', f'{self.fp_shift * 4}')) self.end_instructions.append(AdduInstruction( '$sp', '$sp', f'{self.fp_shift * 4}')) + + if(self.name!='Main_main'): + self.end_instructions.append(JrInstruction('$ra')) def __update_callee_saved_reg__(self, registers: set): diff = registers.difference(self.callee_saved_reg) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 3d7fb935..1daa6034 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -356,9 +356,9 @@ def plus_to_mips_visitor(plus: cil.PlusNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION[str(plus.result)] - y_addr = CURRENT_FUNCTION[str(plus.left)] - z_addr = CURRENT_FUNCTION[str(plus.right)] + x_addr = CURRENT_FUNCTION.offset[str(plus.result)] + y_addr = CURRENT_FUNCTION.offset[str(plus.left)] + z_addr = CURRENT_FUNCTION.offset[str(plus.right)] instructions = [ mips.Comment(str(plus)) ] From 9838fa787a9c28723e813e743f87573661f8b1c1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 28 Nov 2020 23:59:42 -0500 Subject: [PATCH 385/435] fixing bugs --- src/code_generation/CIL/cil.py | 27 ++++-- src/code_generation/MIPS/mips.py | 39 +++++--- src/code_generation/MIPS/test.asm | 143 +++++++++++++++++++++++++++--- 3 files changed, 175 insertions(+), 34 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 36ca5bfb..5a69f6ce 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -105,10 +105,17 @@ def program_to_cil_visitor(program): """ main_instance = add_local('__main__') main_result = add_local('main_result') - main_function = CilAST.FuncNode('main', [], [CilAST.LocalNode('__main__'), CilAST.LocalNode('main_result')], - [CilAST.AllocateNode('Main', main_instance), - CilAST.ArgNode(main_instance), - CilAST.VCAllNode('Main', 'main', main_result)]) + # + t_data=add_str_data('Main') + t_local=add_local() + # + main_function = CilAST.FuncNode('main', [], [t_local,CilAST.LocalNode('__main__'), CilAST.LocalNode('main_result')], + [ + CilAST.LoadNode(t_data, t_local), + CilAST.AllocateNode('Main', main_instance), + CilAST.SetAttrNode(main_instance, '@type', t_local), + CilAST.ArgNode(main_instance), + CilAST.VCAllNode('Main', 'main', main_result)]) built_in_code.append(main_function) # completing .CODE and .DATA sections @@ -164,17 +171,17 @@ def copy_to_cil(): def length_to_cil(): result = CilAST.LocalNode('len_result') - return CilAST.FuncNode('length_String', [CilAST.ParamNode('self')], [result], [CilAST.LengthNode('self', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_length', [CilAST.ParamNode('self')], [result], [CilAST.LengthNode('self', result), CilAST.ReturnNode(result)]) def concat_to_cil(): result = CilAST.LocalNode('concat_result') - return CilAST.FuncNode('concat_String', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_concat', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) def substring_to_cil(): result = CilAST.LocalNode('substring_result') - return CilAST.FuncNode('substr_String', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) def func_to_cil_visitor(type_name, func): @@ -401,12 +408,14 @@ def new_to_cil_visitor(new_node): # t_data=add_str_data(t) t_local=add_local() + size_local=add_local() # body.append(CilAST.LoadNode(t_data, t_local)) - body.append(CilAST.SetAttrNode(value, '@type', t_data)) - body.append(CilAST.SetAttrNode(value, '@size', (len(init_attr)+2)*4)) + body.append(CilAST.SetAttrNode(value, '@type', t_local)) + body.append(CilAST.AssignNode(size_local,(len(init_attr)+2)*4)) + body.append(CilAST.SetAttrNode(value, '@size', size_local)) for index, attr in enumerate(init_attr): diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 1daa6034..415275bc 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -260,8 +260,14 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - addr = CURRENT_FUNCTION.offset[str(arg.val)] - return [mips.Comment(str(arg)), mips.LwInstruction('$t0', f'{addr}($fp)'), mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] + code= [mips.Comment(str(arg))] + if isinstance(arg.val, int): + code.append(mips.LiInstruction('$t0', arg.val)) + else: + addr = CURRENT_FUNCTION.offset[str(arg.val)] + code.append(mips.LwInstruction('$t0', f'{addr}($fp)')) + + return code+ [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -387,9 +393,9 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(str(minus.result)) - y_addr = CURRENT_FUNCTION.get_address(str(minus.left)) - z_addr = CURRENT_FUNCTION.get_address(str(minus.right)) + x_addr = CURRENT_FUNCTION.offset[str(minus.result)] + y_addr = CURRENT_FUNCTION.offset[str(minus.left)] + z_addr = CURRENT_FUNCTION.offset[str(minus.right)] instructions = [ mips.Comment(str(minus)) ] @@ -530,8 +536,6 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): 4 - Restore the caller-saved registers. 5 - Extract the return value, if any, from register $v0. """ - CURRENT_FUNCTION.args_count = 0 - t = get_type(vcall.type) instructios = [] instructios.append(mips.Comment(str(vcall))) # 1 @@ -544,7 +548,7 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): instructios.append(mips.SwInstruction(f'${reg}', f'{s}($sp)')) #instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) # 2 - instructios.append(mips.JalInstruction(__VT__[(vcall.type, vcall.method)])) + instructios.append(mips.JalInstruction(__VT__[(str(vcall.type), str(vcall.method))])) # 4 s = size for reg in CURRENT_FUNCTION.caller_saved_reg: @@ -564,13 +568,20 @@ def assign_to_mips_visitor(assign: cil.AssignNode): lw $t0, [y_addr] sw $t0, [x_addr] """ - y_addr = CURRENT_FUNCTION.offset[str(assign.val)] - x_addr = CURRENT_FUNCTION[str(assign.result)] + + code=[mips.Comment(str(assign))] + x_addr = CURRENT_FUNCTION.offset[str(assign.result)] + + + + if isinstance(assign.val, int): + code.append(mips.LiInstruction('$t0', assign.val)) + else: + y_addr = CURRENT_FUNCTION.offset[str(assign.val)] + code.append(mips.LwInstruction('$t0', f'{y_addr}($fp)')) - return [ - mips.Comment(str(assign)), - mips.LwInstruction('$t0', y_addr), - mips.SwInstruction('$t0', x_addr) + return code+[ + mips.SwInstruction('$t0', f'{x_addr}($sp)') ] diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 6c985e10..0907b808 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -21,6 +21,7 @@ main: lw $t0, 0($sp) addu $sp, $sp, 4 addu $sp, $sp, 12 + jr $ra IO_out_int: move $fp, $sp # 0 LOCALS = 0 bytes @@ -33,6 +34,7 @@ IO_out_int: # RETURN self ; lw $v0, 0($fp) addu $sp, $sp, 4 + jr $ra IO_out_string: move $fp, $sp # 0 LOCALS = 0 bytes @@ -45,6 +47,7 @@ IO_out_string: # RETURN self ; lw $v0, 0($fp) addu $sp, $sp, 4 + jr $ra IO_in_string: move $fp, $sp # 1 LOCALS = 4 bytes @@ -58,6 +61,7 @@ IO_in_string: # RETURN str ; lw $v0, -4($fp) addu $sp, $sp, 8 + jr $ra IO_in_int: move $fp, $sp # 1 LOCALS = 4 bytes @@ -70,6 +74,7 @@ IO_in_int: # RETURN int ; lw $v0, -4($fp) addu $sp, $sp, 8 + jr $ra Object_type_name: move $fp, $sp # 1 LOCALS = 4 bytes @@ -81,6 +86,7 @@ Object_type_name: # RETURN type ; lw $v0, -4($fp) addu $sp, $sp, 8 + jr $ra Object_copy: move $fp, $sp # 1 LOCALS = 4 bytes @@ -107,7 +113,8 @@ Object_copy: # RETURN copy ; lw $v0, -4($fp) addu $sp, $sp, 8 -length_String: + jr $ra +String_length: move $fp, $sp # 1 LOCALS = 4 bytes sw $ra, -8($fp) @@ -127,7 +134,8 @@ length_String: # RETURN len_result ; lw $v0, -4($fp) addu $sp, $sp, 8 -concat_String: + jr $ra +String_concat: move $fp, $sp # 1 LOCALS = 4 bytes sw $ra, -8($fp) @@ -157,7 +165,8 @@ concat_String: # RETURN concat_result ; lw $v0, -4($fp) addu $sp, $sp, 8 -substr_String: + jr $ra +String_substr: move $fp, $sp # 1 LOCALS = 4 bytes sw $ra, -8($fp) @@ -182,13 +191,121 @@ substr_String: # RETURN substring_result ; lw $v0, -4($fp) addu $sp, $sp, 8 + jr $ra Main_main: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # local_0 = LOAD data_1 ; + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # local_0 = ALLOCATE Object ; + li $a0, 8 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_1 ; la $t0, data_1 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 8 ; + li $t0, 8 + sw $t0, -8($sp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Object type_name ; + subu $sp, $sp, 8 + sw $t1, 4($sp) + sw $t0, 0($sp) + jal Object_type_name + lw $t1, 4($sp) + lw $t0, 0($sp) + addu $sp, $sp, 8 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 4 ; + li $t0, 4 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL String substr ; + subu $sp, $sp, 8 + sw $t1, 4($sp) + sw $t0, 0($sp) + jal String_substr + lw $t1, 4($sp) + lw $t0, 0($sp) + addu $sp, $sp, 8 + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL Main out_string ; + subu $sp, $sp, 8 + sw $t1, 4($sp) + sw $t0, 0($sp) + jal IO_out_string + lw $t1, 4($sp) + lw $t0, 0($sp) + addu $sp, $sp, 8 + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Object type_name ; + subu $sp, $sp, 8 + sw $t1, 4($sp) + sw $t0, 0($sp) + jal Object_type_name + lw $t1, 4($sp) + lw $t0, 0($sp) + addu $sp, $sp, 8 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 3 ; + li $t0, 3 + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL String substr ; + subu $sp, $sp, 8 + sw $t1, 4($sp) + sw $t0, 0($sp) + jal String_substr + lw $t1, 4($sp) + lw $t0, 0($sp) + addu $sp, $sp, 8 + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = LOAD data_2 ; + la $t0, data_2 sw $t0, -4($fp) # ARG self ; lw $t0, 0($fp) @@ -199,18 +316,22 @@ Main_main: subu $sp, $sp, 4 sw $t0, ($sp) # local_0 = VCALL Main out_string ; - subu $sp, $sp, 4 + subu $sp, $sp, 8 + sw $t1, 4($sp) sw $t0, 0($sp) jal IO_out_string + lw $t1, 4($sp) lw $t0, 0($sp) - addu $sp, $sp, 4 + addu $sp, $sp, 8 # RETURN local_0 ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 12 .data data_1: - .asciiz "Hello, World.\n" + .asciiz "Object" + data_2: + .asciiz "\n" str: .space 1024 concat_result: From 089de95313f607c22f47e18c49250072aa4f3037 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 29 Nov 2020 15:14:52 +0100 Subject: [PATCH 386/435] Reformat cde --- src/code_generation/MIPS/mips.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 415275bc..2fed1d5e 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -260,14 +260,14 @@ def arg_to_mips_visitor(arg: cil.ArgNode): 1) Allocates a 4-bytes space in stack\n 2) Pushes the arg value in the stack\n ''' - code= [mips.Comment(str(arg))] + code = [mips.Comment(str(arg))] if isinstance(arg.val, int): - code.append(mips.LiInstruction('$t0', arg.val)) + code.append(mips.LiInstruction('$t0', arg.val)) else: addr = CURRENT_FUNCTION.offset[str(arg.val)] code.append(mips.LwInstruction('$t0', f'{addr}($fp)')) - - return code+ [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] + + return code + [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -541,14 +541,15 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): # 1 size = len(CURRENT_FUNCTION.caller_saved_reg) * 4 instructios.append(mips.SubuInstruction('$sp', '$sp', size)) - #instructios.extend(allocate_stack(size)) + # instructios.extend(allocate_stack(size)) s = size for reg in CURRENT_FUNCTION.caller_saved_reg: s -= 4 instructios.append(mips.SwInstruction(f'${reg}', f'{s}($sp)')) #instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) # 2 - instructios.append(mips.JalInstruction(__VT__[(str(vcall.type), str(vcall.method))])) + instructios.append(mips.JalInstruction( + __VT__[(str(vcall.type), str(vcall.method))])) # 4 s = size for reg in CURRENT_FUNCTION.caller_saved_reg: @@ -556,7 +557,7 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): instructios.append(mips.LwInstruction(f'${reg}', f'{s}($sp)')) #instructios.extend(peek_stack(f'${reg}', f'{s}($sp)')) instructios.append(mips.AdduInstruction('$sp', '$sp', size)) - #instructios.extend(free_stack(size)) + # instructios.extend(free_stack(size)) return instructios @@ -568,12 +569,10 @@ def assign_to_mips_visitor(assign: cil.AssignNode): lw $t0, [y_addr] sw $t0, [x_addr] """ - - code=[mips.Comment(str(assign))] + + code = [mips.Comment(str(assign))] x_addr = CURRENT_FUNCTION.offset[str(assign.result)] - - - + if isinstance(assign.val, int): code.append(mips.LiInstruction('$t0', assign.val)) else: From 897409d1358b71fe33e28dc0eb019612c05c4cd3 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 29 Nov 2020 17:13:40 +0100 Subject: [PATCH 387/435] Fix bugs --- src/code_generation/CIL/cil.py | 57 +++++++++++------------ src/code_generation/MIPS/ast.py | 9 +++- src/code_generation/MIPS/mips.py | 79 ++++++++++++++------------------ src/lexer_parser/parsetab.py | 5 +- 4 files changed, 72 insertions(+), 78 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 5a69f6ce..94274dab 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -94,28 +94,19 @@ def program_to_cil_visitor(program): """ Building main function - - function main { - LOCAL __main__ ; - LOCAL main_result ; - __main__ = ALLOCATE Main ; - ARG __main__ ; - main_result = VCALL Main main ; - } """ - main_instance = add_local('__main__') + main_init = new_to_cil_visitor(CoolAST.NewNode('Main')) + body = main_init.body main_result = add_local('main_result') - # - t_data=add_str_data('Main') - t_local=add_local() - # - main_function = CilAST.FuncNode('main', [], [t_local,CilAST.LocalNode('__main__'), CilAST.LocalNode('main_result')], - [ - CilAST.LoadNode(t_data, t_local), - CilAST.AllocateNode('Main', main_instance), - CilAST.SetAttrNode(main_instance, '@type', t_local), - CilAST.ArgNode(main_instance), - CilAST.VCAllNode('Main', 'main', main_result)]) + body.append(CilAST.ArgNode(main_init.value)) + body.append(CilAST.VCAllNode('Main', 'main', main_result)) + + main_instance = add_local('__main__') + main_type = add_local('main_type') + t_data = add_str_data('Main') + + main_function = CilAST.FuncNode( + 'main', [], [__LOCALS__[k] for k in __LOCALS__.keys()], body) built_in_code.append(main_function) # completing .CODE and .DATA sections @@ -184,6 +175,11 @@ def substring_to_cil(): return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) +def abort_to_cil(): + result = CilAST.LocalNode('abort_result') + return CilAST.FuncNode('Object_abort', [CilAST.ParamNode('self')], [result], CilAST.ReturnNode(result)) + + def func_to_cil_visitor(type_name, func): ''' Converts from FunctionNode in COOL AST to FuncionNode in CIL AST. \n @@ -393,6 +389,7 @@ def id_to_cil_visitor(id): def new_to_cil_visitor(new_node): + global __CURRENT_TYPE__ value = add_local() t = new_node.type body = [] @@ -406,18 +403,18 @@ def new_to_cil_visitor(new_node): init_attr = CT.TypesByName[t].get_all_attributes() # - t_data=add_str_data(t) - t_local=add_local() - size_local=add_local() + t_data = add_str_data(t) + t_local = add_local() + size_local = add_local() # - - + body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) - body.append(CilAST.AssignNode(size_local,(len(init_attr)+2)*4)) + body.append(CilAST.AssignNode(size_local, (len(init_attr)+2)*4)) body.append(CilAST.SetAttrNode(value, '@size', size_local)) - + old_current_type = __CURRENT_TYPE__ + __CURRENT_TYPE__ = new_node.type for index, attr in enumerate(init_attr): if attr.expression: attr_cil = expression_to_cil_visitor( @@ -425,7 +422,7 @@ def new_to_cil_visitor(new_node): body += attr_cil.body body.append(CilAST.SetAttrNode( value, attr.id, attr_cil.value, index+2)) - + __CURRENT_TYPE__ = old_current_type return CIL_block(body, value) @@ -509,7 +506,8 @@ def func_call_to_cil_visitor(call): call.object) body += obj_cil.body obj = obj_cil.value - _, t, _ = call.object.returned_type.get_method(call.id, [arg.returned_type for arg in call.args]) + _, t, _ = call.object.returned_type.get_method( + call.id, [arg.returned_type for arg in call.args]) else: obj = 'self' t = __CURRENT_TYPE__ @@ -521,7 +519,6 @@ def func_call_to_cil_visitor(call): body += arg_cil.body arg_values.append(arg_cil.value) - body.append(CilAST.ArgNode(obj)) for arg in arg_values: diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 359232b3..31053783 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -89,8 +89,8 @@ def end(self): '$sp', '$sp', f'{self.fp_shift * 4}')) self.end_instructions.append(AdduInstruction( '$sp', '$sp', f'{self.fp_shift * 4}')) - - if(self.name!='Main_main'): + + if(self.name != 'Main_main'): self.end_instructions.append(JrInstruction('$ra')) def __update_callee_saved_reg__(self, registers: set): @@ -235,6 +235,11 @@ def __init__(self, *arguments): super().__init__('addu', *arguments) +class MulInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('mul', *arguments) + + class MultInstruction(Instruction): def __init__(self, *arguments): super().__init__('mult', *arguments) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 2fed1d5e..0b8537a7 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -396,22 +396,13 @@ def minus_to_mips_visitor(minus: cil.MinusNode): x_addr = CURRENT_FUNCTION.offset[str(minus.result)] y_addr = CURRENT_FUNCTION.offset[str(minus.left)] z_addr = CURRENT_FUNCTION.offset[str(minus.right)] - instructions = [ - mips.Comment(str(minus)) + return [ + mips.Comment(str(minus)), + mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t2', z_addr), + mips.SubInstruction('$t0', y_addr, z_addr), + mips.SwInstruction('$t0', x_addr) ] - if not is_register(y_addr): - instructions.append(mips.LwInstruction('$t1', y_addr)) - y_addr = '$t1' - if not is_register(z_addr): - instructions.append(mips.LwInstruction('$t2', z_addr)) - z_addr = '$t2' - if is_register(x_addr): - instructions.append(mips.SubInstruction(x_addr, y_addr, z_addr)) - else: - instructions.append(mips.SubInstruction('$t0', y_addr, z_addr)) - instructions.append(mips.SwInstruction('$t0', x_addr)) - - return instructions def star_to_mips_visitor(star: cil.StarNode): @@ -424,15 +415,15 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(star.result) - y_addr = CURRENT_FUNCTION.get_address(star.left) - z_addr = CURRENT_FUNCTION.get_address(star.right) + x_offset = CURRENT_FUNCTION.offset[str(star.result)] + y_offset = CURRENT_FUNCTION.offset[str(star.left)] + z_offset = CURRENT_FUNCTION.offset[str(star.right)] return [ mips.Comment(str(star)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), - mips.MultInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + mips.LwInstruction('$t1', f'{y_offset}($fp)'), + mips.LwInstruction('$t2', f'{z_offset}($fp)'), + mips.MulInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -446,15 +437,15 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(div.result) - y_addr = CURRENT_FUNCTION.get_address(div.left) - z_addr = CURRENT_FUNCTION.get_address(div.right) + x_offset = CURRENT_FUNCTION.offset[str(div.result)] + y_offset = CURRENT_FUNCTION.offset[str(div.left)] + z_offset = CURRENT_FUNCTION.offset[str(div.right)] return [ mips.Comment(str(div)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), + mips.LwInstruction('$t1', f'{y_offset}($fp)'), + mips.LwInstruction('$t2', f'{z_offset}($fp)'), mips.DivInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -469,15 +460,15 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(lesseq.result) - y_addr = CURRENT_FUNCTION.get_address(lesseq.left) - z_addr = CURRENT_FUNCTION.get_address(lesseq.right) + x_offset = CURRENT_FUNCTION.offset[str(lesseq.result)] + y_offset = CURRENT_FUNCTION.offset[str(lesseq.left)] + z_offset = CURRENT_FUNCTION.offset[str(lesseq.right)] return [ mips.Comment(str(lesseq)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), + mips.LwInstruction('$t1', f'{y_offset}($fp)'), + mips.LwInstruction('$t2', f'{z_offset}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -492,15 +483,15 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(less.result) - y_addr = CURRENT_FUNCTION.get_address(less.left) - z_addr = CURRENT_FUNCTION.get_address(less.right) + x_offset = CURRENT_FUNCTION.offset[str(less.result)] + y_offset = CURRENT_FUNCTION.offset[str(less.left)] + z_offset = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), + mips.LwInstruction('$t1', f'{y_offset}($fp)'), + mips.LwInstruction('$t2', f'{z_offset}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) + mips.SwInstruction('$t0', f'{y_offset}($fp)') ] @@ -513,13 +504,13 @@ def not_to_mips_visitor(notn: cil.NotNode): not $t0, $t1 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(notn.result) - y_addr = CURRENT_FUNCTION.get_address(notn.value) + x_offset = CURRENT_FUNCTION.offset[str(notn.result)] + y_offset = CURRENT_FUNCTION.offset[str(notn.value)] return [ mips.Comment(str(notn)), - mips.LwInstruction('$t1', y_addr), + mips.LwInstruction('$t1', f'{x_offset}($fp)'), mips.NotInstruction('$t0', '$t1'), - mips.SwInstruction('$t0', x_addr) + mips.SwInstruction('$t0', f'{y_offset}($fp)') ] diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 9f87869e..99fc4683 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,11 +1,12 @@ # parsetab.py # This file is automatically generated. Do not edit. -_tabversion = '3.8' +# pylint: disable=W,C,R +_tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' +_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From 06c93389de6a398bdcd56d8ac22e3f59fcae226a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 29 Nov 2020 12:16:35 -0500 Subject: [PATCH 388/435] fixing bugs --- src/code_generation/MIPS/ast.py | 4 + src/code_generation/MIPS/mips.py | 163 +++++++++++++++++++------------ 2 files changed, 103 insertions(+), 64 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 359232b3..3024a98d 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -441,6 +441,10 @@ def __init__(self, *arguments): class BeqzInstruction(Instruction): def __init__(self, *arguments): super().__init__('beqz', *arguments) + +class BnezInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('bnez', *arguments) class JInstruction(Instruction): diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 2fed1d5e..cc224b3f 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -120,11 +120,13 @@ def return_to_mips_visitor(ret: cil.ReturnNode): MIPS: lw $v0, shift(x) """ - offset = CURRENT_FUNCTION.offset[str(ret.ret_value)] - return [ - mips.Comment(str(ret)), - mips.LwInstruction('$v0', f'{offset}($fp)') - ] + code= [mips.Comment(str(ret))] + if isinstance(ret.ret_value, int): + code.append(mips.LiInstruction('$v0', ret.ret_value)) + else: + offset = CURRENT_FUNCTION.offset[str(ret.ret_value)] + code.append(mips.LwInstruction('$v0', f'{offset}($fp)')) + return code def read_to_mips_visitor(read: cil.ReadNode): @@ -361,26 +363,23 @@ def plus_to_mips_visitor(plus: cil.PlusNode): add $t0, $t1, $t2 sw $t0, [addr(x)] """ - - x_addr = CURRENT_FUNCTION.offset[str(plus.result)] - y_addr = CURRENT_FUNCTION.offset[str(plus.left)] - z_addr = CURRENT_FUNCTION.offset[str(plus.right)] - instructions = [ - mips.Comment(str(plus)) - ] - if not is_register(y_addr): - instructions.append(mips.LwInstruction('$t1', y_addr)) - y_addr = '$t1' - if not is_register(z_addr): - instructions.append(mips.LwInstruction('$t2', z_addr)) - z_addr = '$t2' - if is_register(x_addr): - instructions.append(mips.AddInstruction(x_addr, y_addr, z_addr)) + code=[mips.Comment(str(plus))] + if isinstance(plus.left, int): + code.append(mips.LiInstruction('$t0', plus.left)) + else: + x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) + + + if isinstance(plus.right, int): + code.append(mips.LiInstruction('$t1', plus.right)) else: - instructions.append(mips.AddInstruction('$t0', y_addr, z_addr)) - instructions.append(mips.SwInstruction('$t0', x_addr)) + y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) + + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + return code + [mips.AddInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - return instructions def minus_to_mips_visitor(minus: cil.MinusNode): @@ -393,25 +392,23 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.offset[str(minus.result)] - y_addr = CURRENT_FUNCTION.offset[str(minus.left)] - z_addr = CURRENT_FUNCTION.offset[str(minus.right)] - instructions = [ - mips.Comment(str(minus)) - ] - if not is_register(y_addr): - instructions.append(mips.LwInstruction('$t1', y_addr)) - y_addr = '$t1' - if not is_register(z_addr): - instructions.append(mips.LwInstruction('$t2', z_addr)) - z_addr = '$t2' - if is_register(x_addr): - instructions.append(mips.SubInstruction(x_addr, y_addr, z_addr)) + code=[mips.Comment(str(plus))] + if isinstance(plus.left, int): + code.append(mips.LiInstruction('$t0', plus.left)) + else: + x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) + + + if isinstance(plus.right, int): + code.append(mips.LiInstruction('$t1', plus.right)) else: - instructions.append(mips.SubInstruction('$t0', y_addr, z_addr)) - instructions.append(mips.SwInstruction('$t0', x_addr)) + y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) + + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - return instructions def star_to_mips_visitor(star: cil.StarNode): @@ -424,16 +421,24 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(star.result) - y_addr = CURRENT_FUNCTION.get_address(star.left) - z_addr = CURRENT_FUNCTION.get_address(star.right) - return [ - mips.Comment(str(star)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), - mips.MultInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) - ] + code=[mips.Comment(str(plus))] + if isinstance(plus.left, int): + code.append(mips.LiInstruction('$t0', plus.left)) + else: + x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) + + + if isinstance(plus.right, int): + code.append(mips.LiInstruction('$t1', plus.right)) + else: + y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) + + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + + def div_to_mips_visitor(div: cil.DivNode): @@ -446,16 +451,24 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(div.result) - y_addr = CURRENT_FUNCTION.get_address(div.left) - z_addr = CURRENT_FUNCTION.get_address(div.right) - return [ - mips.Comment(str(div)), - mips.LwInstruction('$t1', y_addr), - mips.LwInstruction('$t2', z_addr), - mips.DivInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', x_addr) - ] + code=[mips.Comment(str(plus))] + if isinstance(plus.left, int): + code.append(mips.LiInstruction('$t0', plus.left)) + else: + x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) + + + if isinstance(plus.right, int): + code.append(mips.LiInstruction('$t1', plus.right)) + else: + y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) + + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + + def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): @@ -492,9 +505,9 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.get_address(less.result) - y_addr = CURRENT_FUNCTION.get_address(less.left) - z_addr = CURRENT_FUNCTION.get_address(less.right) + x_addr = CURRENT_FUNCTION.offset[str(less.result)] + y_addr = CURRENT_FUNCTION.offset[str(less.left)] + z_addr = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), mips.LwInstruction('$t1', y_addr), @@ -580,7 +593,7 @@ def assign_to_mips_visitor(assign: cil.AssignNode): code.append(mips.LwInstruction('$t0', f'{y_addr}($fp)')) return code+[ - mips.SwInstruction('$t0', f'{x_addr}($sp)') + mips.SwInstruction('$t0', f'{x_addr}($fp)') ] @@ -607,8 +620,30 @@ def copy_to_mips_visitor(copy: cil.CopyNode): ] return [] +def conditional_goto_to_mips_visitor(goto:cil.ConditionalGotoNode): + predicate_addr =CURRENT_FUNCTION.offset[str(goto.predicate)] + return [ + mips.Comment(str(goto)), + mips.LwInstruction('$t0', f'{predicate_addr}($fp)'), + mips.BnezInstruction('$t0', goto.label) + ] + +def goto_to_mips_visitor(goto:cil.GotoNode): + return [ + mips.Comment(str(goto)), + mips.BInstruction(goto.label) + ] + +def label_to_mips_visitor(label:cil.LabelNode): + return [ + mips.Comment(str(label)), + mips.MIPSLabel(label.label_name) + ] __visitors__ = { + cil.LabelNode: label_to_mips_visitor, + cil.GotoNode: goto_to_mips_visitor, + cil.ConditionalGotoNode:conditional_goto_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, From 9cf5245fe546dc3b9ce0047059d79a965efb4b41 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 29 Nov 2020 13:15:22 -0500 Subject: [PATCH 389/435] fixing bugs --- src/code_generation/CIL/cil.py | 2 +- src/code_generation/CIL/optimization.py | 2 +- src/code_generation/MIPS/mips.py | 2 +- src/code_generation/MIPS/test.asm | 1003 +++++++++++++++++++++-- 4 files changed, 928 insertions(+), 81 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 5a69f6ce..9b618bec 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -133,6 +133,7 @@ def program_to_cil_visitor(program): cil_program = CilAST.ProgramNode(types, data, code, built_in_code) remove_unused_locals(cil_program) + #aqui se esta perdiendo un vcall optimization_locals(cil_program) return cil_program @@ -197,7 +198,6 @@ def func_to_cil_visitor(type_name, func): params = [CilAST.ParamNode('self')] params += [CilAST.ParamNode(id) for (id, t) in func.params] __LOCALS__ = {} - labels_count = 0 __DATA_LOCALS__ = {} __TYPEOF__ = {} __CURRENT_TYPE__ = type_name diff --git a/src/code_generation/CIL/optimization.py b/src/code_generation/CIL/optimization.py index f3a4d5be..5b2aaa80 100644 --- a/src/code_generation/CIL/optimization.py +++ b/src/code_generation/CIL/optimization.py @@ -69,7 +69,7 @@ def remove_unused_locals(program: ProgramNode): for instruction in function.body: for local in instruction.locals: try: - if instruction.result.id==local.id and local not in used_locals and type(InstructionNode)!=VCAllNode and type(InstructionNode)!=CallNode: + if instruction.result.id==local.id and local not in used_locals and not isinstance(instruction, VCAllNode): body.remove(instruction) except: pass diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index cc224b3f..dc05be51 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -192,7 +192,7 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): mips.Comment(str(read)), mips.LiInstruction('$v0', 5), mips.SyscallInstruction(), - mips.SwInstruction('$v0', addr) + mips.SwInstruction('$v0', f'{addr}($fp)') ] return code diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 0907b808..e9ccf528 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -2,25 +2,34 @@ .text main: move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 + # 3 LOCALS = 12 bytes + sw $ra, -16($fp) + subu $sp, $sp, 16 + # local_2 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -4($fp) # __main__ = ALLOCATE Main ; - li $a0, 8 + li $a0, 12 li $v0, 9 syscall - sw $v0, -4($fp) - # ARG __main__ ; + sw $v0, -8($fp) + # SETATTR __main__ @type local_2 ; lw $t0, -4($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # ARG __main__ ; + lw $t0, -8($fp) subu $sp, $sp, 4 sw $t0, ($sp) # main_result = VCALL Main main ; - subu $sp, $sp, 4 - sw $t0, 0($sp) + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) jal Main_main - lw $t0, 0($sp) - addu $sp, $sp, 4 - addu $sp, $sp, 12 + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + addu $sp, $sp, 16 jr $ra IO_out_int: move $fp, $sp @@ -70,7 +79,7 @@ IO_in_int: # int = READINT ; li $v0, 5 syscall - sw $v0, -4 + sw $v0, -4($fp) # RETURN int ; lw $v0, -4($fp) addu $sp, $sp, 8 @@ -192,146 +201,984 @@ String_substr: lw $v0, -4($fp) addu $sp, $sp, 8 jr $ra -Main_main: +List_isNil: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List abort ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal Object_abort + lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 4 + jr $ra +List_cons: move $fp, $sp # 2 LOCALS = 8 bytes sw $ra, -12($fp) subu $sp, $sp, 12 - # local_0 = ALLOCATE Object ; - li $a0, 8 + # local_0 = ALLOCATE Cons ; + li $a0, 16 li $v0, 9 syscall sw $v0, -4($fp) - # local_1 = LOAD data_1 ; - la $t0, data_1 + # local_1 = LOAD data_2 ; + la $t0, data_2 sw $t0, -8($fp) # SETATTR local_0 @type local_1 ; lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 4($t1) - # local_1 = 8 ; - li $t0, 8 - sw $t0, -8($sp) + # local_1 = 16 ; + li $t0, 16 + sw $t0, -8($fp) # SETATTR local_0 @size local_1 ; lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 4($t1) - # ARG local_0 ; + # local_1 = local_0 ; lw $t0, -4($fp) + sw $t0, -8($fp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG hd ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = VCALL Object type_name ; + # local_0 = VCALL Cons init ; subu $sp, $sp, 8 - sw $t1, 4($sp) - sw $t0, 0($sp) - jal Object_type_name - lw $t1, 4($sp) - lw $t0, 0($sp) + sw $t0, 4($sp) + sw $t1, 0($sp) + jal Cons_init + lw $t0, 4($sp) + lw $t1, 0($sp) addu $sp, $sp, 8 - # ARG local_0 ; - lw $t0, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +List_car: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 4 ; - li $t0, 4 + # local_0 = VCALL List abort ; subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + sw $t0, 0($sp) + jal Object_abort + lw $t0, 0($sp) + addu $sp, $sp, 4 + # local_1 = ALLOCATE Int ; + li $a0, 8 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_2 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -8($fp) + # SETATTR local_1 @type local_2 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_2 = 8 ; + li $t0, 8 + sw $t0, -8($fp) + # SETATTR local_1 @size local_2 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # RETURN local_1 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +List_cdr: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = VCALL String substr ; + # local_0 = VCALL List abort ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal Object_abort + lw $t0, 0($sp) + addu $sp, $sp, 4 + # local_1 = ALLOCATE List ; + li $a0, 8 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_2 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -8($fp) + # SETATTR local_1 @type local_2 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_2 = 8 ; + li $t0, 8 + sw $t0, -8($fp) + # SETATTR local_1 @size local_2 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # RETURN local_1 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +List_rev: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) subu $sp, $sp, 8 - sw $t1, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List cdr ; + subu $sp, $sp, 4 sw $t0, 0($sp) - jal String_substr - lw $t1, 4($sp) + jal List_cdr lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) addu $sp, $sp, 8 + jr $ra +List_sort: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) + # local_0 = VCALL List cdr ; subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL Main out_string ; - subu $sp, $sp, 8 - sw $t1, 4($sp) sw $t0, 0($sp) - jal IO_out_string - lw $t1, 4($sp) + jal List_cdr lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) addu $sp, $sp, 8 - # ARG 0 ; - li $t0, 0 + jr $ra +List_insert: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = VCALL Object type_name ; - subu $sp, $sp, 8 - sw $t1, 4($sp) + # local_0 = VCALL List cdr ; + subu $sp, $sp, 4 sw $t0, 0($sp) - jal Object_type_name - lw $t1, 4($sp) + jal List_cdr lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) addu $sp, $sp, 8 - # ARG local_0 ; - lw $t0, -4($fp) + jr $ra +List_rcons: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + # local_0 = VCALL List cdr ; subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 3 ; - li $t0, 3 + sw $t0, 0($sp) + jal List_cdr + lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + jr $ra +List_print_list: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = VCALL String substr ; - subu $sp, $sp, 8 - sw $t1, 4($sp) + # local_0 = VCALL List abort ; + subu $sp, $sp, 4 sw $t0, 0($sp) - jal String_substr - lw $t1, 4($sp) + jal Object_abort lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) addu $sp, $sp, 8 - # ARG local_1 ; - lw $t0, -8($fp) + jr $ra +Cons_isNil: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 4 + jr $ra +Cons_init: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # SETATTR self xcar hd ; + lw $t0, 4($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self xcdr tl ; + lw $t0, 8($fp) + lw $t1, 0($fp) + sw $t0, 8($t1) + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 4 + jr $ra +Cons_car: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # local_0 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + jr $ra +Cons_cdr: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # local_0 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + jr $ra +Cons_rev: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # local_0 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -4($fp) + # ARG local_0 ; + lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) + # local_0 = VCALL List rev ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_rev + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # local_2 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -8($fp) # ARG local_0 ; lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -4($fp) - # ARG self ; + # ARG local_2 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List rcons ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_rcons + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +Cons_sort: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # local_0 = GETATTR self xcdr ; lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -4($fp) + # ARG local_0 ; + lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) + # local_0 = VCALL List sort ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_sort + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # local_2 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -8($fp) # ARG local_0 ; lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # local_0 = VCALL Main out_string ; + # ARG local_2 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List insert ; subu $sp, $sp, 8 - sw $t1, 4($sp) - sw $t0, 0($sp) - jal IO_out_string - lw $t1, 4($sp) - lw $t0, 0($sp) + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_insert + lw $t0, 4($sp) + lw $t1, 0($sp) addu $sp, $sp, 8 # RETURN local_0 ; lw $v0, -4($fp) addu $sp, $sp, 12 + jr $ra +Cons_insert: + move $fp, $sp + # 3 LOCALS = 12 bytes + sw $ra, -16($fp) + subu $sp, $sp, 16 + # local_0 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -4($fp) + # local_1 = i < local_0 ; + lw $t1, 4 + lw $t2, -4 + sle $t0, $t1, $t2 + sw $t0, -8 + # IF local_1 GOTO label_1 ; + lw $t0, -8($fp) + bnez $t0, label_1 + # local_0 = ALLOCATE Cons ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 16 ; + li $t0, 16 + sw $t0, -8($fp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_9 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -12($fp) + # local_1 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -8($fp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL List insert ; + subu $sp, $sp, 12 + sw $t1, 8($sp) + sw $t0, 4($sp) + sw $t2, 0($sp) + jal List_insert + lw $t1, 8($sp) + lw $t0, 4($sp) + lw $t2, 0($sp) + addu $sp, $sp, 12 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_9 ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Cons init ; + subu $sp, $sp, 12 + sw $t1, 8($sp) + sw $t0, 4($sp) + sw $t2, 0($sp) + jal Cons_init + lw $t1, 8($sp) + lw $t0, 4($sp) + lw $t2, 0($sp) + addu $sp, $sp, 12 + # local_9 = local_0 ; + lw $t0, -4($fp) + sw $t0, -12($fp) + # GOTO label_2 ; + b label_2 + # LABEL label_1 ; + label_1: + + # local_0 = ALLOCATE Cons ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 16 ; + li $t0, 16 + sw $t0, -8($fp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Cons init ; + subu $sp, $sp, 12 + sw $t1, 8($sp) + sw $t0, 4($sp) + sw $t2, 0($sp) + jal Cons_init + lw $t1, 8($sp) + lw $t0, 4($sp) + lw $t2, 0($sp) + addu $sp, $sp, 12 + # local_9 = local_0 ; + lw $t0, -4($fp) + sw $t0, -12($fp) + # LABEL label_2 ; + label_2: + + # RETURN local_9 ; + lw $v0, -12($fp) + addu $sp, $sp, 16 + jr $ra +Cons_rcons: + move $fp, $sp + # 3 LOCALS = 12 bytes + sw $ra, -16($fp) + subu $sp, $sp, 16 + # local_0 = ALLOCATE Cons ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 16 ; + li $t0, 16 + sw $t0, -8($fp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_3 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -12($fp) + # local_1 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -8($fp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL List rcons ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_rcons + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_3 ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Cons init ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal Cons_init + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +Cons_print_list: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # local_0 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -4($fp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL Cons out_int ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal IO_out_int + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # local_0 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -4($fp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_3 = VCALL Cons out_string ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal IO_out_string + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # local_0 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 8($t0) + sw $t1, -4($fp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List print_list ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal List_print_list + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + jr $ra +Nil_isNil: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 4 + jr $ra +Nil_rev: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 4 + jr $ra +Nil_sort: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 4 + jr $ra +Nil_insert: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Nil rcons ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal Nil_rcons + lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 + jr $ra +Nil_rcons: + move $fp, $sp + # 2 LOCALS = 8 bytes + sw $ra, -12($fp) + subu $sp, $sp, 12 + # local_0 = ALLOCATE Cons ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 16 ; + li $t0, 16 + sw $t0, -8($fp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Cons init ; + subu $sp, $sp, 8 + sw $t0, 4($sp) + sw $t1, 0($sp) + jal Cons_init + lw $t0, 4($sp) + lw $t1, 0($sp) + addu $sp, $sp, 8 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +Nil_print_list: + move $fp, $sp + # 0 LOCALS = 0 bytes + sw $ra, -4($fp) + subu $sp, $sp, 4 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 4 + jr $ra +Main_iota: + move $fp, $sp + # 3 LOCALS = 12 bytes + sw $ra, -16($fp) + subu $sp, $sp, 16 + # local_0 = ALLOCATE Nil ; + li $a0, 8 + li $v0, 9 + syscall + sw $v0, -4($fp) + # local_1 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_1 = 8 ; + li $t0, 8 + sw $t0, -8($fp) + # SETATTR local_0 @size local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # SETATTR self l local_0 ; + lw $t0, -4($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # local_0 = 0 ; + li $t0, 0 + sw $t0, -4($fp) + # LABEL label_3 ; + label_3: + + # local_1 = local_0 < i ; + lw $t1, -4 + lw $t2, 4 + sle $t0, $t1, $t2 + sw $t0, -8 + # IF local_1 GOTO label_4 ; + lw $t0, -8($fp) + bnez $t0, label_4 + # GOTO label_5 ; + b label_5 + # LABEL label_4 ; + label_4: + + # local_1 = ALLOCATE Cons ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -8($fp) + # local_6 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # SETATTR local_1 @type local_6 ; + lw $t0, -12($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # local_6 = 16 ; + li $t0, 16 + sw $t0, -12($fp) + # SETATTR local_1 @size local_6 ; + lw $t0, -12($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # local_6 = GETATTR self l ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -12($fp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_6 ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL Cons init ; + subu $sp, $sp, 12 + sw $t1, 8($sp) + sw $t0, 4($sp) + sw $t2, 0($sp) + jal Cons_init + lw $t1, 8($sp) + lw $t0, 4($sp) + lw $t2, 0($sp) + addu $sp, $sp, 12 + # SETATTR self l local_1 ; + lw $t0, -8($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # local_1 = local_0 + 1 ; + lw $t0, -4($fp) + li $t1, 1 + add $t2, $t0, $t1 + sw $t2, -8($fp) + # GOTO label_3 ; + b label_3 + # LABEL label_5 ; + label_5: + + # local_0 = GETATTR self l ; + lw $t0, 0($fp) + lw $t1, 4($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +Main_main: + move $fp, $sp + # 1 LOCALS = 4 bytes + sw $ra, -8($fp) + subu $sp, $sp, 8 + # local_0 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -4($fp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_1 = VCALL Main out_string ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal IO_out_string + lw $t0, 0($sp) + addu $sp, $sp, 4 + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Main in_int ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal IO_in_int + lw $t0, 0($sp) + addu $sp, $sp, 4 + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL Main iota ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal Main_iota + lw $t0, 0($sp) + addu $sp, $sp, 4 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List rev ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal List_rev + lw $t0, 0($sp) + addu $sp, $sp, 4 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List sort ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal List_sort + lw $t0, 0($sp) + addu $sp, $sp, 4 + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # local_0 = VCALL List print_list ; + subu $sp, $sp, 4 + sw $t0, 0($sp) + jal List_print_list + lw $t0, 0($sp) + addu $sp, $sp, 4 + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 8 .data data_1: - .asciiz "Object" + .asciiz "Main" data_2: + .asciiz "Cons" + data_3: + .asciiz "Int" + data_4: + .asciiz "List" + data_5: .asciiz "\n" + data_6: + .asciiz "Nil" + data_7: + .asciiz "How many numbers to sort? " str: .space 1024 concat_result: From c51a1442e134c54b81e0a1f108ebcbc2692bd2b6 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 14:41:05 -0500 Subject: [PATCH 390/435] Fix Typo Errors --- src/code_generation/MIPS/mips.py | 54 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a0c0a145..36c17656 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -392,21 +392,21 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code=[mips.Comment(str(minus))] + if isinstance(minus.left, int): + code.append(mips.LiInstruction('$t0', minus.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(minus.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + if isinstance(minus.right, int): + code.append(mips.LiInstruction('$t1', minus.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(minus.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + z_addr = CURRENT_FUNCTION.offset[str(minus.result)] return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] @@ -421,21 +421,21 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code=[mips.Comment(str(star))] + if isinstance(star.left, int): + code.append(mips.LiInstruction('$t0', star.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(star.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + if isinstance(star.right, int): + code.append(mips.LiInstruction('$t1', star.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(star.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + z_addr = CURRENT_FUNCTION.offset[str(star.result)] return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] @@ -451,21 +451,21 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code=[mips.Comment(str(div))] + if isinstance(div.left, int): + code.append(mips.LiInstruction('$t0', div.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(div.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + if isinstance(div.right, int): + code.append(mips.LiInstruction('$t1', div.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(div.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] + z_addr = CURRENT_FUNCTION.offset[str(div.result)] return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] @@ -510,10 +510,10 @@ def less_to_mips_visitor(less: cil.LessNode): z_addr = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), - mips.LwInstruction('$t1', f'{y_offset}($fp)'), - mips.LwInstruction('$t2', f'{z_offset}($fp)'), + mips.LwInstruction('$t1', f'{y_addr}($fp)'), + mips.LwInstruction('$t2', f'{z_addr}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', f'{y_offset}($fp)') + mips.SwInstruction('$t0', f'{y_addr}($fp)') ] From 75379fab3c4499d254e3453acd97e96a539ee20b Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 14:58:52 -0500 Subject: [PATCH 391/435] Bug Semantic Error on Class Declaration *Typo Errors on Arith --- src/code_generation/MIPS/mips.py | 3 +-- src/semantic/semantic.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 36c17656..f6e28420 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -513,7 +513,7 @@ def less_to_mips_visitor(less: cil.LessNode): mips.LwInstruction('$t1', f'{y_addr}($fp)'), mips.LwInstruction('$t2', f'{z_addr}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', f'{y_addr}($fp)') + mips.SwInstruction('$t0', f'{x_addr}($fp)') ] @@ -618,7 +618,6 @@ def copy_to_mips_visitor(copy: cil.CopyNode): mips.BInstruction('copy_loop'), mips.MIPSLabel('end_copy_loop') ] - return [] def conditional_goto_to_mips_visitor(goto:cil.ConditionalGotoNode): predicate_addr =CURRENT_FUNCTION.offset[str(goto.predicate)] diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index 585b2eca..a932c006 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -420,7 +420,7 @@ def case_expr_visitor(case: CaseNode, current_class: CT.CoolType, local_scope: d branch_0_type = CT.type_by_name(branch_0.type) temp = local_scope.copy() if branch_0_type is None: - add_semantic_error(branch_0.line, branch_0.column, + add_semantic_error(branch_0.lineno, branch_0.colno, f'{ERR_TYPE}: Class {branch_0.type} of case branch is undefined.') else: # 2.2) From e0389d33c6df8b963c4b5cf41d02260c77e29a2e Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 29 Nov 2020 21:18:25 +0100 Subject: [PATCH 392/435] Fix bug operators --- src/code_generation/MIPS/mips.py | 100 +++++++++++++++---------------- 1 file changed, 47 insertions(+), 53 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a0c0a145..2eec34c2 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -120,7 +120,7 @@ def return_to_mips_visitor(ret: cil.ReturnNode): MIPS: lw $v0, shift(x) """ - code= [mips.Comment(str(ret))] + code = [mips.Comment(str(ret))] if isinstance(ret.ret_value, int): code.append(mips.LiInstruction('$v0', ret.ret_value)) else: @@ -363,25 +363,23 @@ def plus_to_mips_visitor(plus: cil.PlusNode): add $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] + code = [mips.Comment(str(plus))] if isinstance(plus.left, int): code.append(mips.LiInstruction('$t0', plus.left)) else: x_addr = CURRENT_FUNCTION.offset[str(plus.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - + if isinstance(plus.right, int): code.append(mips.LiInstruction('$t1', plus.right)) else: y_addr = CURRENT_FUNCTION.offset[str(plus.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] return code + [mips.AddInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - def minus_to_mips_visitor(minus: cil.MinusNode): """ CIL: @@ -392,23 +390,21 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code = [mips.Comment(str(minus))] + if isinstance(minus.left, int): + code.append(mips.LiInstruction('$t0', minus.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(minus.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + + if isinstance(minus.right, int): + code.append(mips.LiInstruction('$t1', minus.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(minus.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] - return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + z_addr = CURRENT_FUNCTION.offset[str(minus.result)] + return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] def star_to_mips_visitor(star: cil.StarNode): @@ -421,24 +417,21 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code = [mips.Comment(str(star))] + if isinstance(star.left, int): + code.append(mips.LiInstruction('$t0', star.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(star.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + + if isinstance(star.right, int): + code.append(mips.LiInstruction('$t1', star.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(star.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] - return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - + z_addr = CURRENT_FUNCTION.offset[str(star.result)] + return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] def div_to_mips_visitor(div: cil.DivNode): @@ -451,24 +444,21 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] - if isinstance(plus.left, int): - code.append(mips.LiInstruction('$t0', plus.left)) + code = [mips.Comment(str(div))] + if isinstance(div.left, int): + code.append(mips.LiInstruction('$t0', div.left)) else: - x_addr = CURRENT_FUNCTION.offset[str(plus.left)] + x_addr = CURRENT_FUNCTION.offset[str(div.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - - if isinstance(plus.right, int): - code.append(mips.LiInstruction('$t1', plus.right)) + + if isinstance(div.right, int): + code.append(mips.LiInstruction('$t1', div.right)) else: - y_addr = CURRENT_FUNCTION.offset[str(plus.right)] + y_addr = CURRENT_FUNCTION.offset[str(div.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - - z_addr = CURRENT_FUNCTION.offset[str(plus.result)] - return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - + z_addr = CURRENT_FUNCTION.offset[str(div.result)] + return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): @@ -505,9 +495,9 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.offset[str(less.result)] - y_addr = CURRENT_FUNCTION.offset[str(less.left)] - z_addr = CURRENT_FUNCTION.offset[str(less.right)] + x_offset = CURRENT_FUNCTION.offset[str(less.result)] + y_offset = CURRENT_FUNCTION.offset[str(less.left)] + z_offset = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), mips.LwInstruction('$t1', f'{y_offset}($fp)'), @@ -620,30 +610,34 @@ def copy_to_mips_visitor(copy: cil.CopyNode): ] return [] -def conditional_goto_to_mips_visitor(goto:cil.ConditionalGotoNode): - predicate_addr =CURRENT_FUNCTION.offset[str(goto.predicate)] + +def conditional_goto_to_mips_visitor(goto: cil.ConditionalGotoNode): + predicate_addr = CURRENT_FUNCTION.offset[str(goto.predicate)] return [ mips.Comment(str(goto)), mips.LwInstruction('$t0', f'{predicate_addr}($fp)'), mips.BnezInstruction('$t0', goto.label) ] -def goto_to_mips_visitor(goto:cil.GotoNode): + +def goto_to_mips_visitor(goto: cil.GotoNode): return [ mips.Comment(str(goto)), mips.BInstruction(goto.label) ] - -def label_to_mips_visitor(label:cil.LabelNode): + + +def label_to_mips_visitor(label: cil.LabelNode): return [ mips.Comment(str(label)), mips.MIPSLabel(label.label_name) ] + __visitors__ = { cil.LabelNode: label_to_mips_visitor, cil.GotoNode: goto_to_mips_visitor, - cil.ConditionalGotoNode:conditional_goto_to_mips_visitor, + cil.ConditionalGotoNode: conditional_goto_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, From a97225eae2d46aa9080f3416f550ab00d4cb2070 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 29 Nov 2020 16:38:14 -0500 Subject: [PATCH 393/435] fix bugs --- src/code_generation/CIL/cil.py | 10 +++++----- src/code_generation/MIPS/mips.py | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 1a856ac3..42306a8b 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -269,7 +269,7 @@ def assign_to_cil_visitor(assign): if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) body = expr.body + \ - [CilAST.SetAttrNode('self', assign.id, expr.value, index)] + [CilAST.SetAttrNode('self', assign.id, expr.value, index+2)] return CIL_block(body, expr.value) else: val = add_local(assign.id) @@ -380,7 +380,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([CilAST.GetAttrNode('self', id.id, result, index)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index+2)], result) try: val = __LOCALS__[id.id] return CIL_block([], val) @@ -411,17 +411,17 @@ def new_to_cil_visitor(new_node): body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) body.append(CilAST.AssignNode(size_local, (len(init_attr)+2)*4)) - body.append(CilAST.SetAttrNode(value, '@size', size_local)) + body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) old_current_type = __CURRENT_TYPE__ __CURRENT_TYPE__ = new_node.type - for index, attr in enumerate(init_attr): + for index, attr in enumerate(init_attr, 2): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body body.append(CilAST.SetAttrNode( - value, attr.id, attr_cil.value, index+2)) + value, attr.id, attr_cil.value, index)) __CURRENT_TYPE__ = old_current_type return CIL_block(body, value) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a0c0a145..088cf56c 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -341,13 +341,16 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): lw $t1, [addr(y)] sw $t0, [attr_shift($t1)] """ - - x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] + code=[mips.Comment(str(setattr))] + if isinstance(setattr.val ,int): + code.append(mips.LiInstruction('$t0', setattr.val)) + else: + x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] + mips.LwInstruction('$t0', f'{x_addr}($fp)'), + y_addr = CURRENT_FUNCTION.offset[str(setattr.obj)] attr_shift = (setattr.attr_index + 1) * 4 - return [ - mips.Comment(str(setattr)), - mips.LwInstruction('$t0', f'{x_addr}($fp)'), + return code + [ mips.LwInstruction('$t1', f'{y_addr}($fp)'), mips.SwInstruction('$t0', f'{attr_shift}($t1)') ] @@ -510,10 +513,10 @@ def less_to_mips_visitor(less: cil.LessNode): z_addr = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), - mips.LwInstruction('$t1', f'{y_offset}($fp)'), - mips.LwInstruction('$t2', f'{z_offset}($fp)'), + mips.LwInstruction('$t1', f'{x_addr}($fp)'), + mips.LwInstruction('$t2', f'{z_addr}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', f'{y_offset}($fp)') + mips.SwInstruction('$t0', f'{y_addr}($fp)') ] From e9ebc48360d96ba63ff8fc3ad3d9d15dd09bf5be Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 17:07:52 -0500 Subject: [PATCH 394/435] Fix Merge Errors --- src/code_generation/MIPS/mips.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f6e28420..239a40c1 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -342,12 +342,16 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): sw $t0, [attr_shift($t1)] """ - x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] + code=[mips.Comment(str(setattr))] + if isinstance(setattr.val ,int): + code.append(mips.LiInstruction('$t0', setattr.val)) + else: + x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] + mips.LwInstruction('$t0', f'{x_addr}($fp)') + y_addr = CURRENT_FUNCTION.offset[str(setattr.obj)] attr_shift = (setattr.attr_index + 1) * 4 - return [ - mips.Comment(str(setattr)), - mips.LwInstruction('$t0', f'{x_addr}($fp)'), + return code + [ mips.LwInstruction('$t1', f'{y_addr}($fp)'), mips.SwInstruction('$t0', f'{attr_shift}($t1)') ] @@ -505,15 +509,15 @@ def less_to_mips_visitor(less: cil.LessNode): sw $t0, [addr(x)] """ - x_addr = CURRENT_FUNCTION.offset[str(less.result)] - y_addr = CURRENT_FUNCTION.offset[str(less.left)] - z_addr = CURRENT_FUNCTION.offset[str(less.right)] + x_offset = CURRENT_FUNCTION.offset[str(less.result)] + y_offset = CURRENT_FUNCTION.offset[str(less.left)] + z_offset = CURRENT_FUNCTION.offset[str(less.right)] return [ mips.Comment(str(less)), - mips.LwInstruction('$t1', f'{y_addr}($fp)'), - mips.LwInstruction('$t2', f'{z_addr}($fp)'), + mips.LwInstruction('$t1', f'{y_offset}($fp)'), + mips.LwInstruction('$t2', f'{z_offset}($fp)'), mips.SleInstruction('$t0', '$t1', '$t2'), - mips.SwInstruction('$t0', f'{x_addr}($fp)') + mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -619,7 +623,7 @@ def copy_to_mips_visitor(copy: cil.CopyNode): mips.MIPSLabel('end_copy_loop') ] -def conditional_goto_to_mips_visitor(goto:cil.ConditionalGotoNode): +def conditional_goto_to_mips_visitor(goto: cil.ConditionalGotoNode): predicate_addr =CURRENT_FUNCTION.offset[str(goto.predicate)] return [ mips.Comment(str(goto)), @@ -627,13 +631,13 @@ def conditional_goto_to_mips_visitor(goto:cil.ConditionalGotoNode): mips.BnezInstruction('$t0', goto.label) ] -def goto_to_mips_visitor(goto:cil.GotoNode): +def goto_to_mips_visitor(goto: cil.GotoNode): return [ mips.Comment(str(goto)), mips.BInstruction(goto.label) ] -def label_to_mips_visitor(label:cil.LabelNode): +def label_to_mips_visitor(label: cil.LabelNode): return [ mips.Comment(str(label)), mips.MIPSLabel(label.label_name) @@ -642,7 +646,7 @@ def label_to_mips_visitor(label:cil.LabelNode): __visitors__ = { cil.LabelNode: label_to_mips_visitor, cil.GotoNode: goto_to_mips_visitor, - cil.ConditionalGotoNode:conditional_goto_to_mips_visitor, + cil.ConditionalGotoNode: conditional_goto_to_mips_visitor, cil.ArgNode: arg_to_mips_visitor, cil.AllocateNode: allocate_to_mips_visitor, cil.CopyNode: copy_to_mips_visitor, From 06a57764e0c73c30fe48c8cefe66c06fa3e9f79c Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 29 Nov 2020 23:14:39 +0100 Subject: [PATCH 395/435] Fix arg --- src/code_generation/MIPS/ast.py | 1 + src/code_generation/MIPS/mips.py | 55 +++++++++++++++----------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 4c1c685f..aac768b9 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -49,6 +49,7 @@ def __init__(self, name, params, locals): self.args_count = 0 self.offset = {} + self.args_code = [] self.init_instructions.append(MoveInstruction('$fp', '$sp')) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 239a40c1..b2166c5e 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -120,7 +120,7 @@ def return_to_mips_visitor(ret: cil.ReturnNode): MIPS: lw $v0, shift(x) """ - code= [mips.Comment(str(ret))] + code = [mips.Comment(str(ret))] if isinstance(ret.ret_value, int): code.append(mips.LiInstruction('$v0', ret.ret_value)) else: @@ -268,8 +268,9 @@ def arg_to_mips_visitor(arg: cil.ArgNode): else: addr = CURRENT_FUNCTION.offset[str(arg.val)] code.append(mips.LwInstruction('$t0', f'{addr}($fp)')) - - return code + [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')] + CURRENT_FUNCTION.args_code.extend( + code + [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')]) + return [] def allocate_to_mips_visitor(allocate: cil.AllocateNode): @@ -342,8 +343,8 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): sw $t0, [attr_shift($t1)] """ - code=[mips.Comment(str(setattr))] - if isinstance(setattr.val ,int): + code = [mips.Comment(str(setattr))] + if isinstance(setattr.val, int): code.append(mips.LiInstruction('$t0', setattr.val)) else: x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] @@ -367,25 +368,23 @@ def plus_to_mips_visitor(plus: cil.PlusNode): add $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(plus))] + code = [mips.Comment(str(plus))] if isinstance(plus.left, int): code.append(mips.LiInstruction('$t0', plus.left)) else: x_addr = CURRENT_FUNCTION.offset[str(plus.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - + if isinstance(plus.right, int): code.append(mips.LiInstruction('$t1', plus.right)) else: y_addr = CURRENT_FUNCTION.offset[str(plus.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - + z_addr = CURRENT_FUNCTION.offset[str(plus.result)] return code + [mips.AddInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - def minus_to_mips_visitor(minus: cil.MinusNode): """ CIL: @@ -396,25 +395,23 @@ def minus_to_mips_visitor(minus: cil.MinusNode): sub $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(minus))] + code = [mips.Comment(str(minus))] if isinstance(minus.left, int): code.append(mips.LiInstruction('$t0', minus.left)) else: x_addr = CURRENT_FUNCTION.offset[str(minus.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - + if isinstance(minus.right, int): code.append(mips.LiInstruction('$t1', minus.right)) else: y_addr = CURRENT_FUNCTION.offset[str(minus.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - + z_addr = CURRENT_FUNCTION.offset[str(minus.result)] return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - def star_to_mips_visitor(star: cil.StarNode): """ CIL: @@ -425,26 +422,23 @@ def star_to_mips_visitor(star: cil.StarNode): mult $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(star))] + code = [mips.Comment(str(star))] if isinstance(star.left, int): code.append(mips.LiInstruction('$t0', star.left)) else: x_addr = CURRENT_FUNCTION.offset[str(star.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - + if isinstance(star.right, int): code.append(mips.LiInstruction('$t1', star.right)) else: y_addr = CURRENT_FUNCTION.offset[str(star.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - + z_addr = CURRENT_FUNCTION.offset[str(star.result)] return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - - def div_to_mips_visitor(div: cil.DivNode): """ CIL: @@ -455,26 +449,23 @@ def div_to_mips_visitor(div: cil.DivNode): div $t0, $t1, $t2 sw $t0, [addr(x)] """ - code=[mips.Comment(str(div))] + code = [mips.Comment(str(div))] if isinstance(div.left, int): code.append(mips.LiInstruction('$t0', div.left)) else: x_addr = CURRENT_FUNCTION.offset[str(div.left)] code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) - - + if isinstance(div.right, int): code.append(mips.LiInstruction('$t1', div.right)) else: y_addr = CURRENT_FUNCTION.offset[str(div.right)] code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) - + z_addr = CURRENT_FUNCTION.offset[str(div.result)] return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] - - def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): """ CIL: @@ -564,6 +555,8 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): s -= 4 instructios.append(mips.SwInstruction(f'${reg}', f'{s}($sp)')) #instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) + instructios.extend(CURRENT_FUNCTION.args_code) + CURRENT_FUNCTION.args_code.clear() # 2 instructios.append(mips.JalInstruction( __VT__[(str(vcall.type), str(vcall.method))])) @@ -623,26 +616,30 @@ def copy_to_mips_visitor(copy: cil.CopyNode): mips.MIPSLabel('end_copy_loop') ] + def conditional_goto_to_mips_visitor(goto: cil.ConditionalGotoNode): - predicate_addr =CURRENT_FUNCTION.offset[str(goto.predicate)] + predicate_addr = CURRENT_FUNCTION.offset[str(goto.predicate)] return [ mips.Comment(str(goto)), mips.LwInstruction('$t0', f'{predicate_addr}($fp)'), mips.BnezInstruction('$t0', goto.label) ] + def goto_to_mips_visitor(goto: cil.GotoNode): return [ mips.Comment(str(goto)), mips.BInstruction(goto.label) ] - + + def label_to_mips_visitor(label: cil.LabelNode): return [ mips.Comment(str(label)), mips.MIPSLabel(label.label_name) ] + __visitors__ = { cil.LabelNode: label_to_mips_visitor, cil.GotoNode: goto_to_mips_visitor, From e84ef5f5b22accc80b0f84dbfb489762db25a8fb Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 29 Nov 2020 17:18:39 -0500 Subject: [PATCH 396/435] removing extra index shift --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 088cf56c..4c266a5a 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -323,7 +323,7 @@ def getattr_to_mips_visitor(getattr: cil.GetAttrNode): x_addr = CURRENT_FUNCTION.offset[str(getattr.result)] y_addr = CURRENT_FUNCTION.offset[str(getattr.obj)] - attr_shift = (getattr.attr_index + 1) * 4 + attr_shift = getattr.attr_index * 4 return [ mips.Comment(str(getattr)), mips.LwInstruction('$t0', f'{y_addr}($fp)'), @@ -349,7 +349,7 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): mips.LwInstruction('$t0', f'{x_addr}($fp)'), y_addr = CURRENT_FUNCTION.offset[str(setattr.obj)] - attr_shift = (setattr.attr_index + 1) * 4 + attr_shift = setattr.attr_index * 4 return code + [ mips.LwInstruction('$t1', f'{y_addr}($fp)'), mips.SwInstruction('$t0', f'{attr_shift}($t1)') From 5bc053603924ef2545e5409317cb61120060492a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sun, 29 Nov 2020 17:25:00 -0500 Subject: [PATCH 397/435] removing unnecessary locals --- src/code_generation/CIL/cil.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 42306a8b..dd04627a 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -100,11 +100,7 @@ def program_to_cil_visitor(program): main_result = add_local('main_result') body.append(CilAST.ArgNode(main_init.value)) body.append(CilAST.VCAllNode('Main', 'main', main_result)) - - main_instance = add_local('__main__') - main_type = add_local('main_type') - t_data = add_str_data('Main') - + main_function = CilAST.FuncNode( 'main', [], [__LOCALS__[k] for k in __LOCALS__.keys()], body) built_in_code.append(main_function) From 4438f1b75331cc61391f5441cab12f2e1165f352 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 17:52:55 -0500 Subject: [PATCH 398/435] Fix less and lesseq mips visitors --- src/code_generation/MIPS/mips.py | 40 ++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 239a40c1..3786d51f 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -485,14 +485,22 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): sle $t0, $t1, $t2 sw $t0, [addr(x)] """ + instructions = [mips.Comment(str(lesseq))] + if isinstance(lesseq.left, int): + instructions.append(mips.LiInstruction('$t1', lesseq.left)) + else: + y_offset = CURRENT_FUNCTION.offset[str(lesseq.left)] + instructions.append(mips.LwInstruction('$t1', f'{y_offset}($fp)')) + + if isinstance(lesseq.right, int): + instructions.append(mips.LiInstruction('$t2', lesseq.right)) + else: + z_offset = CURRENT_FUNCTION.offset[str(lesseq.right)] + instructions.append(mips.LwInstruction('$t2', f'{z_offset}($fp)')) x_offset = CURRENT_FUNCTION.offset[str(lesseq.result)] - y_offset = CURRENT_FUNCTION.offset[str(lesseq.left)] - z_offset = CURRENT_FUNCTION.offset[str(lesseq.right)] - return [ - mips.Comment(str(lesseq)), - mips.LwInstruction('$t1', f'{y_offset}($fp)'), - mips.LwInstruction('$t2', f'{z_offset}($fp)'), + + return instructions + [ mips.SleInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -508,14 +516,22 @@ def less_to_mips_visitor(less: cil.LessNode): slt $t0, $t1, $t2 sw $t0, [addr(x)] """ + instructions = [mips.Comment(str(less))] + if isinstance(less.left, int): + instructions.append(mips.LiInstruction('$t1', less.left)) + else: + y_offset = CURRENT_FUNCTION.offset[str(less.left)] + instructions.append(mips.LwInstruction('$t1', f'{y_offset}($fp)')) + + if isinstance(less.right, int): + instructions.append(mips.LiInstruction('$t2', less.right)) + else: + z_offset = CURRENT_FUNCTION.offset[str(less.right)] + instructions.append(mips.LwInstruction('$t2', f'{z_offset}($fp)')) x_offset = CURRENT_FUNCTION.offset[str(less.result)] - y_offset = CURRENT_FUNCTION.offset[str(less.left)] - z_offset = CURRENT_FUNCTION.offset[str(less.right)] - return [ - mips.Comment(str(less)), - mips.LwInstruction('$t1', f'{y_offset}($fp)'), - mips.LwInstruction('$t2', f'{z_offset}($fp)'), + + return instructions + [ mips.SleInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] From c3c77f9a334ac7c8e74e9354620ffe87faa0559a Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 17:59:41 -0500 Subject: [PATCH 399/435] Fix Not mips visitor --- src/code_generation/MIPS/mips.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 3786d51f..a25072fa 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -343,7 +343,8 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): """ code=[mips.Comment(str(setattr))] - if isinstance(setattr.val ,int): + + if isinstance(setattr.val, int): code.append(mips.LiInstruction('$t0', setattr.val)) else: x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] @@ -546,13 +547,19 @@ def not_to_mips_visitor(notn: cil.NotNode): not $t0, $t1 sw $t0, [addr(x)] """ + instructions = [mips.Comment(str(notn))] + + if isinstance(notn.val, int): + instructions.append(mips.LiInstruction('$t0', notn.val)) + else: + y_offset = CURRENT_FUNCTION.offset[str(notn.val)] + mips.LwInstruction('$t0', f'{y_offset}($fp)') + x_offset = CURRENT_FUNCTION.offset[str(notn.result)] - y_offset = CURRENT_FUNCTION.offset[str(notn.value)] - return [ - mips.Comment(str(notn)), - mips.LwInstruction('$t1', f'{x_offset}($fp)'), + + return instructions + [ mips.NotInstruction('$t0', '$t1'), - mips.SwInstruction('$t0', f'{y_offset}($fp)') + mips.SwInstruction('$t0', f'{x_offset}($fp)') ] From 37b5567b55fdef09079f996e4dff60b601384591 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 29 Nov 2020 18:28:47 -0500 Subject: [PATCH 400/435] Fix Not mips member --- src/code_generation/MIPS/mips.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index a25072fa..54fb3b7a 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -549,10 +549,10 @@ def not_to_mips_visitor(notn: cil.NotNode): """ instructions = [mips.Comment(str(notn))] - if isinstance(notn.val, int): - instructions.append(mips.LiInstruction('$t0', notn.val)) + if isinstance(notn.value, int): + instructions.append(mips.LiInstruction('$t0', notn.value)) else: - y_offset = CURRENT_FUNCTION.offset[str(notn.val)] + y_offset = CURRENT_FUNCTION.offset[str(notn.value)] mips.LwInstruction('$t0', f'{y_offset}($fp)') x_offset = CURRENT_FUNCTION.offset[str(notn.result)] From bebbd7df96213a663fe0bbc4d7fe63cd22b3a492 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 03:45:43 +0100 Subject: [PATCH 401/435] Add value_id to new visitor --- src/code_generation/CIL/cil.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index dd04627a..2e342b04 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -95,7 +95,7 @@ def program_to_cil_visitor(program): """ Building main function """ - main_init = new_to_cil_visitor(CoolAST.NewNode('Main')) + main_init = new_to_cil_visitor(CoolAST.NewNode('Main'), 'self') body = main_init.body main_result = add_local('main_result') body.append(CilAST.ArgNode(main_init.value)) @@ -384,9 +384,12 @@ def id_to_cil_visitor(id): return CIL_block([], id.id) -def new_to_cil_visitor(new_node): +def new_to_cil_visitor(new_node, value_id=None): global __CURRENT_TYPE__ - value = add_local() + if value_id: + value = add_local(value_id) + else: + value = add_local() t = new_node.type body = [] From 91c0d98e47f56f590c2b62042e260cc3c681e477 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 03:46:38 +0100 Subject: [PATCH 402/435] Add abort to built in --- src/code_generation/CIL/cil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 2e342b04..3a549760 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -126,7 +126,7 @@ def program_to_cil_visitor(program): def built_in_to_cil(): - return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil()] + return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil()] def out_string_to_cil(): @@ -174,7 +174,7 @@ def substring_to_cil(): def abort_to_cil(): result = CilAST.LocalNode('abort_result') - return CilAST.FuncNode('Object_abort', [CilAST.ParamNode('self')], [result], CilAST.ReturnNode(result)) + return CilAST.FuncNode('Object_abort', [CilAST.ParamNode('self')], [result], [CilAST.ReturnNode(result)]) def func_to_cil_visitor(type_name, func): From a32c137a5543af1c9247b7789c69bd949ecbeebf Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 03:47:12 +0100 Subject: [PATCH 403/435] Fix star to mips visitor --- src/code_generation/MIPS/mips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index bbd3476c..792e0f1d 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -419,7 +419,7 @@ def star_to_mips_visitor(star: cil.StarNode): MIPS: lw $t1, [addr(y)] lw $t2, [addr(z)] - mult $t0, $t1, $t2 + mul $t0, $t1, $t2 sw $t0, [addr(x)] """ code = [mips.Comment(str(star))] @@ -436,7 +436,7 @@ def star_to_mips_visitor(star: cil.StarNode): code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) z_addr = CURRENT_FUNCTION.offset[str(star.result)] - return code + [mips.MultInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + return code + [mips.MulInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] def div_to_mips_visitor(div: cil.DivNode): From 5f0f90bc8af7cf90198c43b6248990c220b2a174 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 03:47:53 +0100 Subject: [PATCH 404/435] Check if goto condition is a constant --- src/code_generation/MIPS/mips.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 792e0f1d..d461bd1d 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -640,12 +640,14 @@ def copy_to_mips_visitor(copy: cil.CopyNode): def conditional_goto_to_mips_visitor(goto: cil.ConditionalGotoNode): - predicate_addr = CURRENT_FUNCTION.offset[str(goto.predicate)] - return [ - mips.Comment(str(goto)), - mips.LwInstruction('$t0', f'{predicate_addr}($fp)'), - mips.BnezInstruction('$t0', goto.label) - ] + instructions = [mips.Comment(str(goto))] + if isinstance(goto.predicate, int): + instructions.append(mips.LiInstruction('$t0', goto.predicate)) + else: + predicate_offset = CURRENT_FUNCTION.offset[str(goto.predicate)] + instructions.append(mips.LwInstruction( + '$t0', f'{predicate_offset}($fp)')) + return instructions + [mips.BnezInstruction('$t0', goto.label)] def goto_to_mips_visitor(goto: cil.GotoNode): From 1ce97c643d33cd2f94a4b3dd4ff6f336657df7bf Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 30 Nov 2020 11:24:40 -0500 Subject: [PATCH 405/435] Fix indexes CIL visitors --- src/code_generation/CIL/cil.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 3a549760..2e2eff7d 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -265,7 +265,7 @@ def assign_to_cil_visitor(assign): if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) body = expr.body + \ - [CilAST.SetAttrNode('self', assign.id, expr.value, index+2)] + [CilAST.SetAttrNode('self', assign.id, expr.value, index)] return CIL_block(body, expr.value) else: val = add_local(assign.id) @@ -376,7 +376,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([CilAST.GetAttrNode('self', id.id, result, index+2)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index)], result) try: val = __LOCALS__[id.id] return CIL_block([], val) @@ -410,17 +410,17 @@ def new_to_cil_visitor(new_node, value_id=None): body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) body.append(CilAST.AssignNode(size_local, (len(init_attr)+2)*4)) - body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) + body.append(CilAST.SetAttrNode(value, '@size', size_local)) old_current_type = __CURRENT_TYPE__ __CURRENT_TYPE__ = new_node.type - for index, attr in enumerate(init_attr, 2): + for index, attr in enumerate(init_attr): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body body.append(CilAST.SetAttrNode( - value, attr.id, attr_cil.value, index)) + value, attr.id, attr_cil.value, index+2)) __CURRENT_TYPE__ = old_current_type return CIL_block(body, value) From 1a6aaccc68729797fa2f4a14f9728204a002b5fe Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 19:13:36 +0100 Subject: [PATCH 406/435] Change ABORT node in CIL --- src/code_generation/CIL/ast.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 6d024f06..726955e4 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -230,8 +230,11 @@ def __str__(self): class AbortNode(InstructionNode): + def __init__(self, type_name: str = None): + self.type_name = type_name + def __str__(self): - return 'ABORT ;' + return f'ABORT {self.type_name} ;' class ReadIntNode(InstructionNode): From dfbb295fef43b3d2cc96b4923a6e782211e149d9 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 19:14:58 +0100 Subject: [PATCH 407/435] Fix bugs --- src/code_generation/CIL/cil.py | 19 +++-- src/code_generation/MIPS/ast.py | 68 +++++----------- src/code_generation/MIPS/mips.py | 134 ++++++++++++++++++++----------- src/cool_types/types.py | 1 + src/lexer_parser/lexer.py | 2 +- 5 files changed, 118 insertions(+), 106 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 3a549760..d488683a 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -100,7 +100,7 @@ def program_to_cil_visitor(program): main_result = add_local('main_result') body.append(CilAST.ArgNode(main_init.value)) body.append(CilAST.VCAllNode('Main', 'main', main_result)) - + main_function = CilAST.FuncNode( 'main', [], [__LOCALS__[k] for k in __LOCALS__.keys()], body) built_in_code.append(main_function) @@ -118,15 +118,17 @@ def program_to_cil_visitor(program): data = [CilAST.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] + data.append(CilAST.DataNode('data_abort', 'Abort called from class ')) + cil_program = CilAST.ProgramNode(types, data, code, built_in_code) remove_unused_locals(cil_program) - #aqui se esta perdiendo un vcall + # aqui se esta perdiendo un vcall optimization_locals(cil_program) return cil_program def built_in_to_cil(): - return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil()] + return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil(), abort_string_to_cil()] def out_string_to_cil(): @@ -173,8 +175,11 @@ def substring_to_cil(): def abort_to_cil(): - result = CilAST.LocalNode('abort_result') - return CilAST.FuncNode('Object_abort', [CilAST.ParamNode('self')], [result], [CilAST.ReturnNode(result)]) + return CilAST.FuncNode('Object_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode()]) + + +def abort_string_to_cil(): + return CilAST.FuncNode('String_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('String')]) def func_to_cil_visitor(type_name, func): @@ -368,8 +373,8 @@ def integer_to_cil_visitor(integer): return CIL_block([], integer.value) -def bool_to_cil_visitor(bool): - return CIL_block([], 1) if bool.value == 'true' else CIL_block([], 0) +def bool_to_cil_visitor(b: CoolAST.BoolNode): + return CIL_block([], 1) if b.value else CIL_block([], 0) def id_to_cil_visitor(id): diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index aac768b9..f2cd6810 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -31,8 +31,7 @@ def __str__(self): class MIPSLabel: def __init__(self, name): self.name = name - self.callee_saved_reg = set() - self.caller_saved_reg = set() + self.registers = set() def __str__(self): return f'{self.name}:\n' @@ -44,8 +43,7 @@ def __init__(self, name, params, locals): self.init_instructions = [] self.instructions = [] self.end_instructions = [] - self.caller_saved_reg = set() - self.callee_saved_reg = set() + self.used_regs = set(['ra']) self.args_count = 0 self.offset = {} @@ -57,17 +55,18 @@ def __init__(self, name, params, locals): # Save args on the stack for i, p in enumerate(params): - self.offset[p.id] = i*4 + self.offset[p.id] = (len(params) - i - 1)*4 for i, l in enumerate(locals, 1): self.offset[str(l)] = -i * 4 - self.fp_shift = len(locals) self.init_instructions.append( - Comment(f'{self.fp_shift} LOCALS = {self.fp_shift * 4} bytes')) - self.fp_shift += 1 - self.init_instructions.append(SwInstruction( - '$ra', f'-{self.fp_shift * 4}($fp)')) + SubuInstruction('$sp', '$sp', len(locals)*4)) + + self.end_instructions.append( + AdduInstruction('$sp', '$sp', len(locals)*4)) + if(self.name != 'Main_main'): + self.end_instructions.append(JrInstruction('$ra')) def append_instruction(self, instruction): """ @@ -76,40 +75,15 @@ def append_instruction(self, instruction): were declared in CIL. """ # Update used registers - self.__update_callee_saved_reg__(instruction.callee_saved_reg) - self.__update_caller_saved_reg__(instruction.caller_saved_reg) + self.update_used_reg(instruction.registers) # Update function instrcutions self.instructions.append(instruction) - def end(self): - """ - It points the end of the CIL function, and adds the last necessary - actions. - """ - self.init_instructions.append(SubuInstruction( - '$sp', '$sp', f'{self.fp_shift * 4}')) - self.end_instructions.append(AdduInstruction( - '$sp', '$sp', f'{self.fp_shift * 4}')) - - if(self.name != 'Main_main'): - self.end_instructions.append(JrInstruction('$ra')) - - def __update_callee_saved_reg__(self, registers: set): - diff = registers.difference(self.callee_saved_reg) - for reg in diff: - self.fp_shift += 1 - self.init_instructions.append(SwInstruction( - f'${reg}', f'-{self.fp_shift * 4}($fp)')) - self.end_instructions.append(SwInstruction( - f'-{self.fp_shift * 4}($fp)', f'${reg}')) - self.callee_saved_reg.update(diff) - - def __update_caller_saved_reg__(self, registers: set): - self.caller_saved_reg.update(registers) + def update_used_reg(self, registers: set): + self.used_regs.update(registers) def __str__(self): - instructions = self.init_instructions + \ - self.instructions + self.end_instructions + instructions = self.init_instructions + self.instructions return '\n'.join([f'{self.name}:']+[f'\t{str(i)}' for i in instructions]) @@ -126,21 +100,16 @@ class Instruction: def __init__(self, name, *arguments): self.name = name self.arguments = arguments - self.caller_saved_reg = set() - self.callee_saved_reg = set() + self.registers = set() patterns = [re.compile(r'\$(?P..)'), - re.compile(r'[0-9]+\(\$(?P..)\)')] - caller_pattern = re.compile(r't[0-9]') - callee_pattern = re.compile(r's[0-7]') + re.compile(r'[0-9]+\(\$(?P..)\)'), + re.compile(r'\-[0-9]+\(\$(?P..)\)')] for a in self.arguments: for p in patterns: match = p.match(str(a)) if match: reg = match.group('register') - if caller_pattern.match(reg): - self.caller_saved_reg.add(reg) - elif callee_pattern.match(reg): - self.callee_saved_reg.add(reg) + self.registers.add(reg) break def __str__(self): @@ -447,7 +416,8 @@ def __init__(self, *arguments): class BeqzInstruction(Instruction): def __init__(self, *arguments): super().__init__('beqz', *arguments) - + + class BnezInstruction(Instruction): def __init__(self, *arguments): super().__init__('bnez', *arguments) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index d461bd1d..8b44eada 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -35,6 +35,7 @@ def program_to_mips_visitor(program: cil.ProgramNode): # vt_space_code = reserve_virtual_tables_space(program) __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(f'"{d.val}"')) for d in program.data] + __DATA__.append(mips.MIPSDataItem('new_line', mips.AsciizInst(f'"\\n"'))) data_section = mips.MIPSDataSection(__DATA__) # Build .text section @@ -72,8 +73,6 @@ def function_to_mips_visitor(function): for cil_inst in function.body: for mips_inst in instruction_to_mips_visitor(cil_inst): CURRENT_FUNCTION.append_instruction(mips_inst) - # 4 - f.end() return f @@ -81,6 +80,7 @@ def instruction_to_mips_visitor(inst): """ Resolves visitor for each type """ + return __visitors__[type(inst)](inst) try: return __visitors__[type(inst)](inst) except KeyError: @@ -126,6 +126,7 @@ def return_to_mips_visitor(ret: cil.ReturnNode): else: offset = CURRENT_FUNCTION.offset[str(ret.ret_value)] code.append(mips.LwInstruction('$v0', f'{offset}($fp)')) + code.extend(CURRENT_FUNCTION.end_instructions) return code @@ -221,14 +222,14 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): __DATA__.append(mips.MIPSDataItem(concat.result.id, mips.SpaceInst(2 * __BUFFSIZE__))) result_offset = CURRENT_FUNCTION.offset[concat.result.id] - a_offset = CURRENT_FUNCTION.offset[concat.str_a] - b_offset = CURRENT_FUNCTION.offset[concat.str_b] + a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] + b_offset = CURRENT_FUNCTION.offset[str(concat.str_b)] return [ mips.Comment(str(concat)), - mips.LaInstruction('$t0', 0), - mips.LaInstruction('$t1', 0), - mips.LaInstruction('$t2', 0), + mips.LwInstruction('$t0', f'{result_offset}($fp)'), + mips.LwInstruction('$t1', f'{a_offset}($fp)'), + mips.LwInstruction('$t2', f'{b_offset}($fp)'), mips.MIPSLabel('concat_loop_a'), mips.LbInstruction('$a0', '($t1)'), mips.BeqzInstruction('$a0', 'concat_loop_b'), @@ -270,6 +271,7 @@ def arg_to_mips_visitor(arg: cil.ArgNode): code.append(mips.LwInstruction('$t0', f'{addr}($fp)')) CURRENT_FUNCTION.args_code.extend( code + [mips.SubuInstruction('$sp', '$sp', 4), mips.SwInstruction('$t0', '($sp)')]) + CURRENT_FUNCTION.args_count += 1 return [] @@ -348,7 +350,7 @@ def setattr_to_mips_visitor(setattr: cil.SetAttrNode): code.append(mips.LiInstruction('$t0', setattr.val)) else: x_addr = CURRENT_FUNCTION.offset[str(setattr.val)] - mips.LwInstruction('$t0', f'{x_addr}($fp)') + code.append(mips.LwInstruction('$t0', f'{x_addr}($fp)')) y_addr = CURRENT_FUNCTION.offset[str(setattr.obj)] attr_shift = setattr.attr_index * 4 @@ -382,7 +384,7 @@ def plus_to_mips_visitor(plus: cil.PlusNode): code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) z_addr = CURRENT_FUNCTION.offset[str(plus.result)] - return code + [mips.AddInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + return code + [mips.AddInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{z_addr}($fp)')] def minus_to_mips_visitor(minus: cil.MinusNode): @@ -409,7 +411,7 @@ def minus_to_mips_visitor(minus: cil.MinusNode): code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) z_addr = CURRENT_FUNCTION.offset[str(minus.result)] - return code + [mips.SubInstruction('$t2', '$t0', '$t1'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + return code + [mips.SubInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{z_addr}($fp)')] def star_to_mips_visitor(star: cil.StarNode): @@ -436,7 +438,7 @@ def star_to_mips_visitor(star: cil.StarNode): code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) z_addr = CURRENT_FUNCTION.offset[str(star.result)] - return code + [mips.MulInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + return code + [mips.MulInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{z_addr}($fp)')] def div_to_mips_visitor(div: cil.DivNode): @@ -463,7 +465,7 @@ def div_to_mips_visitor(div: cil.DivNode): code.append(mips.LwInstruction('$t1', f'{y_addr}($fp)')) z_addr = CURRENT_FUNCTION.offset[str(div.result)] - return code + [mips.DivInstruction('$t0', '$t1', '$t2'), mips.SwInstruction('$t2', f'{z_addr}($fp)')] + return code + [mips.DivInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{z_addr}($fp)')] def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): @@ -478,21 +480,21 @@ def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): """ instructions = [mips.Comment(str(lesseq))] if isinstance(lesseq.left, int): - instructions.append(mips.LiInstruction('$t1', lesseq.left)) + instructions.append(mips.LiInstruction('$t0', lesseq.left)) else: y_offset = CURRENT_FUNCTION.offset[str(lesseq.left)] - instructions.append(mips.LwInstruction('$t1', f'{y_offset}($fp)')) + instructions.append(mips.LwInstruction('$t0', f'{y_offset}($fp)')) if isinstance(lesseq.right, int): - instructions.append(mips.LiInstruction('$t2', lesseq.right)) + instructions.append(mips.LiInstruction('$t1', lesseq.right)) else: z_offset = CURRENT_FUNCTION.offset[str(lesseq.right)] - instructions.append(mips.LwInstruction('$t2', f'{z_offset}($fp)')) + instructions.append(mips.LwInstruction('$t1', f'{z_offset}($fp)')) x_offset = CURRENT_FUNCTION.offset[str(lesseq.result)] return instructions + [ - mips.SleInstruction('$t0', '$t1', '$t2'), + mips.SleInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -509,21 +511,21 @@ def less_to_mips_visitor(less: cil.LessNode): """ instructions = [mips.Comment(str(less))] if isinstance(less.left, int): - instructions.append(mips.LiInstruction('$t1', less.left)) + instructions.append(mips.LiInstruction('$t0', less.left)) else: y_offset = CURRENT_FUNCTION.offset[str(less.left)] - instructions.append(mips.LwInstruction('$t1', f'{y_offset}($fp)')) + instructions.append(mips.LwInstruction('$t0', f'{y_offset}($fp)')) if isinstance(less.right, int): - instructions.append(mips.LiInstruction('$t2', less.right)) + instructions.append(mips.LiInstruction('$t1', less.right)) else: z_offset = CURRENT_FUNCTION.offset[str(less.right)] - instructions.append(mips.LwInstruction('$t2', f'{z_offset}($fp)')) + instructions.append(mips.LwInstruction('$t1', f'{z_offset}($fp)')) x_offset = CURRENT_FUNCTION.offset[str(less.result)] return instructions + [ - mips.SleInstruction('$t0', '$t1', '$t2'), + mips.SltInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] @@ -548,12 +550,12 @@ def not_to_mips_visitor(notn: cil.NotNode): x_offset = CURRENT_FUNCTION.offset[str(notn.result)] return instructions + [ - mips.NotInstruction('$t0', '$t1'), + mips.NotInstruction('$t0', '$t0'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] -def vcal_to_mips_visitor(vcall: cil.VCAllNode): +def vcall_to_mips_visitor(vcall: cil.VCAllNode): """ CIL: result = VCALL [type] [method] @@ -566,31 +568,38 @@ def vcal_to_mips_visitor(vcall: cil.VCAllNode): 4 - Restore the caller-saved registers. 5 - Extract the return value, if any, from register $v0. """ - instructios = [] - instructios.append(mips.Comment(str(vcall))) - # 1 - size = len(CURRENT_FUNCTION.caller_saved_reg) * 4 - instructios.append(mips.SubuInstruction('$sp', '$sp', size)) - # instructios.extend(allocate_stack(size)) - s = size - for reg in CURRENT_FUNCTION.caller_saved_reg: - s -= 4 - instructios.append(mips.SwInstruction(f'${reg}', f'{s}($sp)')) - #instructios.extend(push_stack(f'${reg}', f'{s}($sp)')) - instructios.extend(CURRENT_FUNCTION.args_code) + instructions = [] + instructions.append(mips.Comment(str(vcall))) + try: + CURRENT_FUNCTION.used_regs.remove('v0') + except KeyError: + pass + save_reg_space = len(CURRENT_FUNCTION.used_regs) * 4 + instructions.append(mips.SubuInstruction('$sp', '$sp', save_reg_space)) + for i, reg in enumerate(CURRENT_FUNCTION.used_regs): + instructions.append(mips.SwInstruction(f'${reg}', f'{i*4}($sp)')) + + instructions.extend(CURRENT_FUNCTION.args_code) CURRENT_FUNCTION.args_code.clear() - # 2 - instructios.append(mips.JalInstruction( + + instructions.append(mips.JalInstruction( __VT__[(str(vcall.type), str(vcall.method))])) - # 4 - s = size - for reg in CURRENT_FUNCTION.caller_saved_reg: - s -= 4 - instructios.append(mips.LwInstruction(f'${reg}', f'{s}($sp)')) - #instructios.extend(peek_stack(f'${reg}', f'{s}($sp)')) - instructios.append(mips.AdduInstruction('$sp', '$sp', size)) - # instructios.extend(free_stack(size)) - return instructios + + instructions.append(mips.AdduInstruction( + '$sp', '$sp', CURRENT_FUNCTION.args_count * 4)) + CURRENT_FUNCTION.args_count = 0 + + for i, reg in enumerate(CURRENT_FUNCTION.used_regs): + instructions.append(mips.LwInstruction(f'${reg}', f'{i*4}($sp)')) + instructions.append(mips.AdduInstruction('$sp', '$sp', save_reg_space)) + + try: + ret_offset = CURRENT_FUNCTION.offset[str(vcall.result)] + instructions.append(mips.SwInstruction('$v0', f'{ret_offset}($fp)')) + except KeyError: + pass + + return instructions def assign_to_mips_visitor(assign: cil.AssignNode): @@ -664,6 +673,32 @@ def label_to_mips_visitor(label: cil.LabelNode): ] +def abort_to_mips_visitor(abort: cil.AbortNode): + instructions = [ + mips.Comment(str(abort)), + mips.LaInstruction('$a0', 'data_abort'), + mips.LiInstruction('$v0', 4), + mips.SyscallInstruction() + ] + if abort.type_name: + __DATA__.append(mips.MIPSDataItem( + f'abort_{abort.type_name}', mips.AsciizInst(f'"{abort.type_name}"'))) + instructions.append(mips.LaInstruction( + '$a0', f'abort_{abort.type_name}')) + else: + instructions.append(mips.LwInstruction('$a0', f'($fp)')) + + return instructions + [ + mips.LiInstruction('$v0', 4), + mips.SyscallInstruction(), + mips.LaInstruction('$a0', 'new_line'), + mips.LiInstruction('$v0', 4), + mips.SyscallInstruction(), + mips.LiInstruction('$v0', 10), + mips.SyscallInstruction() + ] + + __visitors__ = { cil.LabelNode: label_to_mips_visitor, cil.GotoNode: goto_to_mips_visitor, @@ -688,7 +723,8 @@ def label_to_mips_visitor(label: cil.LabelNode): cil.ConcatNode: concat_to_mips_visitor, cil.LoadNode: load_to_mips_visitor, cil.SubStringNode: substring_to_mips_visitor, - cil.VCAllNode: vcal_to_mips_visitor, + cil.VCAllNode: vcall_to_mips_visitor, cil.AssignNode: assign_to_mips_visitor, - cil.TypeOfNode: type_of_to_mips_visitor + cil.TypeOfNode: type_of_to_mips_visitor, + cil.AbortNode: abort_to_mips_visitor, } diff --git a/src/cool_types/types.py b/src/cool_types/types.py index e96bac32..94a135d4 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -252,3 +252,4 @@ def pronounced_join(type_a, type_b): StringType.add_method('length', [], 'Int') StringType.add_method('concat', ['String'], 'String') StringType.add_method('substr', ['Int', 'Int'], 'String') +StringType.add_method('abort', [], 'Object') diff --git a/src/lexer_parser/lexer.py b/src/lexer_parser/lexer.py index fbe2569f..f9ac7886 100644 --- a/src/lexer_parser/lexer.py +++ b/src/lexer_parser/lexer.py @@ -97,7 +97,7 @@ def t_TYPE(t): def t_BOOL(t): r'f[Aa][Ll][Ss][Ee]|t[Rr][Uu][Ee]' - t.value = (t.value.lower == 'true') + t.value = (t.value.lower() == 'true') return t From bd783f43f07353db1a02801144e8260e7136673b Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Mon, 30 Nov 2020 19:30:39 +0100 Subject: [PATCH 408/435] Fix index --- src/code_generation/CIL/cil.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 9f36146d..a7c66933 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -270,7 +270,7 @@ def assign_to_cil_visitor(assign): if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) body = expr.body + \ - [CilAST.SetAttrNode('self', assign.id, expr.value, index)] + [CilAST.SetAttrNode('self', assign.id, expr.value, index + 2)] return CIL_block(body, expr.value) else: val = add_local(assign.id) @@ -381,7 +381,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([CilAST.GetAttrNode('self', id.id, result, index)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index + 2)], result) try: val = __LOCALS__[id.id] return CIL_block([], val) @@ -415,17 +415,17 @@ def new_to_cil_visitor(new_node, value_id=None): body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) body.append(CilAST.AssignNode(size_local, (len(init_attr)+2)*4)) - body.append(CilAST.SetAttrNode(value, '@size', size_local)) + body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) old_current_type = __CURRENT_TYPE__ __CURRENT_TYPE__ = new_node.type - for index, attr in enumerate(init_attr): + for index, attr in enumerate(init_attr, 2): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body body.append(CilAST.SetAttrNode( - value, attr.id, attr_cil.value, index+2)) + value, attr.id, attr_cil.value, index)) __CURRENT_TYPE__ = old_current_type return CIL_block(body, value) From 22a28d704b14bf4ce56fda85ab49753998b62249 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Tue, 1 Dec 2020 01:50:30 +0100 Subject: [PATCH 409/435] Fix bugs --- src/code_generation/CIL/cil.py | 13 ++++++++++--- src/code_generation/MIPS/ast.py | 9 ++++++--- src/code_generation/MIPS/mips.py | 4 ++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index a7c66933..33c8b73b 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -100,6 +100,7 @@ def program_to_cil_visitor(program): main_result = add_local('main_result') body.append(CilAST.ArgNode(main_init.value)) body.append(CilAST.VCAllNode('Main', 'main', main_result)) + body.append(CilAST.ReturnNode(main_result)) main_function = CilAST.FuncNode( 'main', [], [__LOCALS__[k] for k in __LOCALS__.keys()], body) @@ -121,9 +122,9 @@ def program_to_cil_visitor(program): data.append(CilAST.DataNode('data_abort', 'Abort called from class ')) cil_program = CilAST.ProgramNode(types, data, code, built_in_code) - remove_unused_locals(cil_program) + # remove_unused_locals(cil_program) # aqui se esta perdiendo un vcall - optimization_locals(cil_program) + # optimization_locals(cil_program) return cil_program @@ -207,7 +208,13 @@ def func_to_cil_visitor(type_name, func): body.append(CilAST.ReturnNode(instruction.value)) _locals = __LOCALS__.copy() - return CilAST.FuncNode(name, params, [_locals[k] for k in _locals.keys()], body) + _l_keys = _locals.keys() + for k in _l_keys: + for p in func.params: + if k == p[0]: + __LOCALS__.pop(k) + + return CilAST.FuncNode(name, params, [__LOCALS__[k] for k in __LOCALS__.keys()], body) def expression_to_cil_visitor(expression): diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index f2cd6810..c197b501 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -43,7 +43,7 @@ def __init__(self, name, params, locals): self.init_instructions = [] self.instructions = [] self.end_instructions = [] - self.used_regs = set(['ra']) + self.used_regs = set(['ra', 'fp']) self.args_count = 0 self.offset = {} @@ -65,7 +65,10 @@ def __init__(self, name, params, locals): self.end_instructions.append( AdduInstruction('$sp', '$sp', len(locals)*4)) - if(self.name != 'Main_main'): + if self.name == 'main': + self.end_instructions.append(LiInstruction('$v0', 10)) + self.end_instructions.append(SyscallInstruction()) + else: self.end_instructions.append(JrInstruction('$ra')) def append_instruction(self, instruction): @@ -75,7 +78,7 @@ def append_instruction(self, instruction): were declared in CIL. """ # Update used registers - self.update_used_reg(instruction.registers) + # self.update_used_reg(instruction.registers) # Update function instrcutions self.instructions.append(instruction) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 8b44eada..cde4f8bf 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -574,6 +574,10 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): CURRENT_FUNCTION.used_regs.remove('v0') except KeyError: pass + try: + CURRENT_FUNCTION.used_regs.remove('sp') + except KeyError: + pass save_reg_space = len(CURRENT_FUNCTION.used_regs) * 4 instructions.append(mips.SubuInstruction('$sp', '$sp', save_reg_space)) for i, reg in enumerate(CURRENT_FUNCTION.used_regs): From c89a4845fa974387ee9b55cf1b135098b7e16e18 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 11:00:38 -0500 Subject: [PATCH 410/435] adding changes to virtual table --- src/code_generation/CIL/ast.py | 12 + src/code_generation/CIL/cil.py | 16 +- src/code_generation/MIPS/ast.py | 12 + src/code_generation/MIPS/mips.py | 65 +- src/code_generation/MIPS/test.asm | 1572 +++++++++---------------- src/code_generation/MIPS/utilities.py | 7 +- src/lexer_parser/parsetab.py | 5 +- 7 files changed, 642 insertions(+), 1047 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 726955e4..68dc73db 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -264,6 +264,18 @@ def __init__(self, result, var): def __str__(self): return f'{self.result} = TYPEOF {self.var} ;' + + +class GetTypeAddrNode(InstructionNode): + def __init__(self, result, var): + super().__init__() + self.result = result + self.var = var + self.check_local(result) + self.check_local(var) + + def __str__(self): + return f'{self.result} = GETTYPEADDR {self.var} ;' class ArrayNode(InstructionNode): diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 33c8b73b..90a6593d 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -277,7 +277,7 @@ def assign_to_cil_visitor(assign): if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) body = expr.body + \ - [CilAST.SetAttrNode('self', assign.id, expr.value, index + 2)] + [CilAST.SetAttrNode('self', assign.id, expr.value, index + 3)] return CIL_block(body, expr.value) else: val = add_local(assign.id) @@ -388,7 +388,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([CilAST.GetAttrNode('self', id.id, result, index + 2)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index + 3)], result) try: val = __LOCALS__[id.id] return CIL_block([], val) @@ -421,12 +421,12 @@ def new_to_cil_visitor(new_node, value_id=None): body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) - body.append(CilAST.AssignNode(size_local, (len(init_attr)+2)*4)) + body.append(CilAST.AssignNode(size_local, (len(init_attr)+3)*4)) body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) old_current_type = __CURRENT_TYPE__ __CURRENT_TYPE__ = new_node.type - for index, attr in enumerate(init_attr, 2): + for index, attr in enumerate(init_attr, 3): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) @@ -511,17 +511,17 @@ def block_to_cil_visitor(block): def func_call_to_cil_visitor(call): body = [] - t = None + t = add_local() if call.object: obj_cil = expression_to_cil_visitor( call.object) body += obj_cil.body obj = obj_cil.value - _, t, _ = call.object.returned_type.get_method( - call.id, [arg.returned_type for arg in call.args]) + # _, t, _ = call.object.returned_type.get_method( + # call.id, [arg.returned_type for arg in call.args]) else: obj = 'self' - t = __CURRENT_TYPE__ + body.append(CilAST.GetTypeAddrNode(t, obj)) arg_values = [] diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index c197b501..2e54eb4c 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -49,6 +49,7 @@ def __init__(self, name, params, locals): self.offset = {} self.args_code = [] + self.init_instructions.append(MoveInstruction('$fp', '$sp')) self.params_count = len(params) @@ -158,11 +159,22 @@ class SwInstruction(Instruction): def __init__(self, *arguments): super().__init__('sw', *arguments) +class UswInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('usw', *arguments) + + + + class LwInstruction(Instruction): def __init__(self, *arguments): super().__init__('lw', *arguments) +class UlwInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('ulw', *arguments) + class LiInstruction(Instruction): def __init__(self, *arguments): diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index cde4f8bf..9916fde7 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -29,13 +29,14 @@ def program_to_mips_visitor(program: cil.ProgramNode): q.append(t) # Initialize Types - init_types(program.types) + size_vt=init_types(program.types) # Build .data section - # vt_space_code = reserve_virtual_tables_space(program) + vt_space_code = reserve_virtual_tables_space(program, size_vt) __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(f'"{d.val}"')) for d in program.data] __DATA__.append(mips.MIPSDataItem('new_line', mips.AsciizInst(f'"\\n"'))) + __DATA__.extend(vt_space_code) data_section = mips.MIPSDataSection(__DATA__) # Build .text section @@ -44,18 +45,42 @@ def program_to_mips_visitor(program: cil.ProgramNode): text_section = mips.MIPSTextSection(functions) return mips.MIPSProgram(data_section, text_section) +__OFFSET_COUNT__= 0 +__OFFSET__={} -def reserve_virtual_tables_space(program: cil.ProgramNode): +def get_function_offset(function): + global __OFFSET_COUNT__ + try: + return __OFFSET__[function] + except KeyError: + __OFFSET__[function]=__OFFSET_COUNT__ + __OFFSET_COUNT__+=1 + return __OFFSET__[function] + +def main_instructions(): + instructions=[] + types=get_types() + for t in types.keys(): + __OFFSET_COUNT__=0 + for m in types[t].methods: + instructions.append(mips.LaInstruction('$t0', __VT__[(t, m)])) + instructions.append(mips.UswInstruction('$t0', f'vt_{t}+{get_function_offset(m)*4}')) + return instructions + +def reserve_virtual_tables_space(program: cil.ProgramNode, size_vt): """ Each virtual table has a space in the .data section. The space is 4 bytes for each function, where the address of the real function is stored. """ - code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst(t.size_vt)) + code = [mips.MIPSDataItem(f'vt_{t.type}', mips.SpaceInst(size_vt)) for t in program.types[1:]] + + return code + def function_to_mips_visitor(function): """ Convert a CIL function to a block of MIPS code. @@ -68,8 +93,12 @@ def function_to_mips_visitor(function): # 1 f = mips.MIPSFunction(function.name, function.params, function.locals) # 2 + CURRENT_FUNCTION = f # 3 + if f.name=='main': + for i in main_instructions(): + CURRENT_FUNCTION.append_instruction(i) for cil_inst in function.body: for mips_inst in instruction_to_mips_visitor(cil_inst): CURRENT_FUNCTION.append_instruction(mips_inst) @@ -289,10 +318,12 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): address = CURRENT_FUNCTION.offset[str(allocate.result)] code = [ mips.Comment(str(allocate)), - mips.LiInstruction('$a0', size), + mips.LiInstruction('$a0', size + 4), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{address}($fp)') + mips.SwInstruction('$v0', f'{address}($fp)'), + mips.LaInstruction('$t0', f'vt_{allocate.type}'), + mips.SwInstruction('$t0', f'8($v0)') ] return code @@ -585,9 +616,14 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): instructions.extend(CURRENT_FUNCTION.args_code) CURRENT_FUNCTION.args_code.clear() - - instructions.append(mips.JalInstruction( - __VT__[(str(vcall.type), str(vcall.method))])) + + try: + type_local=CURRENT_FUNCTION.offset[str(vcall.type)] + instructions.append(mips.LwInstruction('$t0', f'{type_local}($fp)')) + instructions.append(mips.UlwInstruction('$t1', f'{__OFFSET__[vcall.method]*4}($t0)')) + instructions.append(mips.JalrInstruction('$t1')) + except KeyError: + instructions.append(mips.JalInstruction(__VT__[(str(vcall.type), str(vcall.method))])) instructions.append(mips.AdduInstruction( '$sp', '$sp', CURRENT_FUNCTION.args_count * 4)) @@ -606,6 +642,16 @@ def vcall_to_mips_visitor(vcall: cil.VCAllNode): return instructions +def get_type_addr_to_mips_visitor(get_type:cil.GetTypeAddrNode): + x_addr = CURRENT_FUNCTION.offset[str(get_type.var)] + t_addr = CURRENT_FUNCTION.offset[str(get_type.result)] + return [ + mips.Comment(str(get_type)), + mips.LwInstruction('$t1', f'{x_addr}($fp)'), + mips.LwInstruction('$t0', f'8($t1)'), + mips.SwInstruction('$t0', f'{t_addr}($fp)') + ] + def assign_to_mips_visitor(assign: cil.AssignNode): """ CIL: @@ -731,4 +777,5 @@ def abort_to_mips_visitor(abort: cil.AbortNode): cil.AssignNode: assign_to_mips_visitor, cil.TypeOfNode: type_of_to_mips_visitor, cil.AbortNode: abort_to_mips_visitor, + cil.GetTypeAddrNode: get_type_addr_to_mips_visitor } diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index e9ccf528..097d4845 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -2,66 +2,509 @@ .text main: move $fp, $sp - # 3 LOCALS = 12 bytes - sw $ra, -16($fp) - subu $sp, $sp, 16 - # local_2 = LOAD data_1 ; - la $t0, data_1 - sw $t0, -4($fp) - # __main__ = ALLOCATE Main ; - li $a0, 12 + subu $sp, $sp, 204 + la $t0, Object_abort + usw $t0, vt_Object+0 + la $t0, Object_type_name + usw $t0, vt_Object+4 + la $t0, Object_copy + usw $t0, vt_Object+8 + la $t0, Object_abort + usw $t0, vt_IO+0 + la $t0, Object_type_name + usw $t0, vt_IO+4 + la $t0, Object_copy + usw $t0, vt_IO+8 + la $t0, IO_out_string + usw $t0, vt_IO+12 + la $t0, IO_out_int + usw $t0, vt_IO+16 + la $t0, IO_in_string + usw $t0, vt_IO+20 + la $t0, IO_in_int + usw $t0, vt_IO+24 + la $t0, Object_abort + usw $t0, vt_Int+0 + la $t0, Object_type_name + usw $t0, vt_Int+4 + la $t0, Object_copy + usw $t0, vt_Int+8 + la $t0, String_abort + usw $t0, vt_String+0 + la $t0, Object_type_name + usw $t0, vt_String+4 + la $t0, Object_copy + usw $t0, vt_String+8 + la $t0, String_length + usw $t0, vt_String+28 + la $t0, String_concat + usw $t0, vt_String+32 + la $t0, String_substr + usw $t0, vt_String+36 + la $t0, Object_abort + usw $t0, vt_Bool+0 + la $t0, Object_type_name + usw $t0, vt_Bool+4 + la $t0, Object_copy + usw $t0, vt_Bool+8 + la $t0, Object_abort + usw $t0, vt_Main+0 + la $t0, Object_type_name + usw $t0, vt_Main+4 + la $t0, Object_copy + usw $t0, vt_Main+8 + la $t0, IO_out_string + usw $t0, vt_Main+12 + la $t0, IO_out_int + usw $t0, vt_Main+16 + la $t0, IO_in_string + usw $t0, vt_Main+20 + la $t0, IO_in_int + usw $t0, vt_Main+24 + la $t0, Main_main + usw $t0, vt_Main+40 + # self = ALLOCATE Main ; + li $a0, 32 li $v0, 9 syscall - sw $v0, -8($fp) - # SETATTR __main__ @type local_2 ; - lw $t0, -4($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # ARG __main__ ; + sw $v0, -4($fp) + la $t0, vt_Main + sw $t0, 8($v0) + # local_1 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -8($fp) + # SETATTR self @type local_1 ; lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 0($t1) + # local_2 = 32 ; + li $t0, 32 + sw $t0, -12($fp) + # SETATTR self @size local_2 ; + lw $t0, -12($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # local_3 = GETTYPEADDR self ; + lw $t1, -4($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -20($fp) + # local_5 = VCALL local_3 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # SETATTR self out 2 ; + li $t0, 2 + lw $t1, -4($fp) + sw $t0, 12($t1) + # local_6 = GETATTR self out ; + lw $t0, -4($fp) + lw $t1, 12($t0) + sw $t1, -28($fp) + # SETATTR self testee local_6 ; + lw $t0, -28($fp) + lw $t1, -4($fp) + sw $t0, 16($t1) + # SETATTR self stop 500 ; + li $t0, 500 + lw $t1, -4($fp) + sw $t0, 24($t1) + # LABEL label_13 ; + label_13: + + # IF 1 GOTO label_14 ; + li $t0, 1 + bnez $t0, label_14 + # GOTO label_15 ; + b label_15 + # LABEL label_14 ; + label_14: + + # local_7 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -32($fp) + # local_8 = local_7 + 1 ; + lw $t0, -32($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -36($fp) + # SETATTR self testee local_8 ; + lw $t0, -36($fp) + lw $t1, -4($fp) + sw $t0, 16($t1) + # SETATTR self divisor 2 ; + li $t0, 2 + lw $t1, -4($fp) + sw $t0, 20($t1) + # LABEL label_6 ; + label_6: + + # local_9 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -40($fp) + # local_10 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -44($fp) + # local_11 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -48($fp) + # local_12 = local_10 * local_11 ; + lw $t0, -44($fp) + lw $t1, -48($fp) + mul $t0, $t0, $t1 + sw $t0, -52($fp) + # local_13 = local_9 < local_12 ; + lw $t0, -40($fp) + lw $t1, -52($fp) + slt $t0, $t0, $t1 + sw $t0, -56($fp) + # IF local_13 GOTO label_4 ; + lw $t0, -56($fp) + bnez $t0, label_4 + # local_14 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -60($fp) + # local_15 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -64($fp) + # local_16 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -68($fp) + # local_17 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -72($fp) + # local_18 = local_16 / local_17 ; + lw $t0, -68($fp) + lw $t1, -72($fp) + div $t0, $t0, $t1 + sw $t0, -76($fp) + # local_19 = local_15 * local_18 ; + lw $t0, -64($fp) + lw $t1, -76($fp) + mul $t0, $t0, $t1 + sw $t0, -80($fp) + # local_20 = local_14 - local_19 ; + lw $t0, -60($fp) + lw $t1, -80($fp) + sub $t0, $t0, $t1 + sw $t0, -84($fp) + # local_21 = local_20 - 0 ; + lw $t0, -84($fp) + li $t1, 0 + sub $t0, $t0, $t1 + sw $t0, -88($fp) + # local_22 = 0 ; + li $t0, 0 + sw $t0, -92($fp) + # IF local_21 GOTO label_1 ; + lw $t0, -88($fp) + bnez $t0, label_1 + # local_22 = 1 ; + li $t0, 1 + sw $t0, -92($fp) + # LABEL label_1 ; + label_1: + + # IF local_22 GOTO label_2 ; + lw $t0, -92($fp) + bnez $t0, label_2 + # local_23 = 1 ; + li $t0, 1 + sw $t0, -96($fp) + # GOTO label_3 ; + b label_3 + # LABEL label_2 ; + label_2: + + # local_23 = 0 ; + li $t0, 0 + sw $t0, -96($fp) + # LABEL label_3 ; + label_3: + + # local_24 = local_23 ; + lw $t0, -96($fp) + sw $t0, -100($fp) + # GOTO label_5 ; + b label_5 + # LABEL label_4 ; + label_4: + + # local_24 = 0 ; + li $t0, 0 + sw $t0, -100($fp) + # LABEL label_5 ; + label_5: + + # IF local_24 GOTO label_7 ; + lw $t0, -100($fp) + bnez $t0, label_7 + # GOTO label_8 ; + b label_8 + # LABEL label_7 ; + label_7: + + # local_25 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -104($fp) + # local_26 = local_25 + 1 ; + lw $t0, -104($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -108($fp) + # SETATTR self divisor local_26 ; + lw $t0, -108($fp) + lw $t1, -4($fp) + sw $t0, 20($t1) + # GOTO label_6 ; + b label_6 + # LABEL label_8 ; + label_8: + + # local_27 = 0 ; + li $t0, 0 + sw $t0, -112($fp) + # local_28 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -116($fp) + # local_29 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -120($fp) + # local_30 = GETATTR self divisor ; + lw $t0, -4($fp) + lw $t1, 20($t0) + sw $t1, -124($fp) + # local_31 = local_29 * local_30 ; + lw $t0, -120($fp) + lw $t1, -124($fp) + mul $t0, $t0, $t1 + sw $t0, -128($fp) + # local_32 = local_28 < local_31 ; + lw $t0, -116($fp) + lw $t1, -128($fp) + slt $t0, $t0, $t1 + sw $t0, -132($fp) + # IF local_32 GOTO label_9 ; + lw $t0, -132($fp) + bnez $t0, label_9 + # local_40 = 0 ; + li $t0, 0 + sw $t0, -164($fp) + # GOTO label_10 ; + b label_10 + # LABEL label_9 ; + label_9: + + # local_33 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -136($fp) + # SETATTR self out local_33 ; + lw $t0, -136($fp) + lw $t1, -4($fp) + sw $t0, 12($t1) + # local_34 = GETTYPEADDR self ; + lw $t1, -4($fp) + lw $t0, 8($t1) + sw $t0, -140($fp) + # local_35 = GETATTR self out ; + lw $t0, -4($fp) + lw $t1, 12($t0) + sw $t1, -144($fp) + # local_36 = VCALL local_34 out_int ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_35 ; + lw $t0, -144($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -140($fp) + ulw $t1, 16($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -148($fp) + # local_37 = GETTYPEADDR self ; + lw $t1, -4($fp) + lw $t0, 8($t1) + sw $t0, -152($fp) + # local_38 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -156($fp) + # local_39 = VCALL local_37 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_38 ; + lw $t0, -156($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -152($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -160($fp) + # local_40 = local_39 ; + lw $t0, -160($fp) + sw $t0, -164($fp) + # LABEL label_10 ; + label_10: + + # local_41 = GETATTR self stop ; + lw $t0, -4($fp) + lw $t1, 24($t0) + sw $t1, -168($fp) + # local_42 = GETATTR self testee ; + lw $t0, -4($fp) + lw $t1, 16($t0) + sw $t1, -172($fp) + # local_43 = local_41 <= local_42 ; + lw $t0, -168($fp) + lw $t1, -172($fp) + sle $t0, $t0, $t1 + sw $t0, -176($fp) + # IF local_43 GOTO label_11 ; + lw $t0, -176($fp) + bnez $t0, label_11 + # local_47 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -192($fp) + # local_48 = local_47 ; + lw $t0, -192($fp) + sw $t0, -196($fp) + # GOTO label_12 ; + b label_12 + # LABEL label_11 ; + label_11: + + # local_45 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -184($fp) + # local_44 = GETTYPEADDR local_45 ; + lw $t1, -184($fp) + lw $t0, 8($t1) + sw $t0, -180($fp) + # local_46 = VCALL local_44 abort ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_45 ; + lw $t0, -184($fp) subu $sp, $sp, 4 sw $t0, ($sp) + lw $t0, -180($fp) + ulw $t1, 0($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -188($fp) + # local_48 = local_46 ; + lw $t0, -188($fp) + sw $t0, -196($fp) + # LABEL label_12 ; + label_12: + + # GOTO label_13 ; + b label_13 + # LABEL label_15 ; + label_15: + + # local_49 = 0 ; + li $t0, 0 + sw $t0, -200($fp) + # SETATTR self m local_49 ; + lw $t0, -200($fp) + lw $t1, -4($fp) + sw $t0, 28($t1) # main_result = VCALL Main main ; subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) jal Main_main - lw $t0, 4($sp) - lw $t1, 0($sp) + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - addu $sp, $sp, 16 - jr $ra + sw $v0, -204($fp) + # RETURN main_result ; + lw $v0, -204($fp) + addu $sp, $sp, 204 + li $v0, 10 + syscall IO_out_int: move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 + subu $sp, $sp, 0 # PRINT int ; - lw $a0, 4($fp) + lw $a0, 0($fp) li $v0, 1 syscall # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 4 + lw $v0, 4($fp) + addu $sp, $sp, 0 jr $ra IO_out_string: move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 + subu $sp, $sp, 0 # PRINT str ; - lw $a0, 4($fp) + lw $a0, 0($fp) li $v0, 4 syscall # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 4 + lw $v0, 4($fp) + addu $sp, $sp, 0 jr $ra IO_in_string: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 la $a0, str li $a1, 1024 li $v0, 8 @@ -69,38 +512,32 @@ IO_in_string: sw $a0, -4($fp) # RETURN str ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra IO_in_int: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # int = READINT ; li $v0, 5 syscall sw $v0, -4($fp) # RETURN int ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra Object_type_name: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # type = TYPEOF self ; lw $t0, 0($fp) sw $t0, -4($fp) # RETURN type ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra Object_copy: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # copy = COPY self ; lw $a0, 8($fp) li $v0, 9 @@ -121,13 +558,11 @@ Object_copy: # RETURN copy ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra String_length: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # len_result = LENGTH self ; lb $t0, 0($fp) li $t1, 0 @@ -142,17 +577,15 @@ String_length: sw $t1, -4($fp) # RETURN len_result ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra String_concat: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # concat_result = CONCAT self x ; - la $t0, 0 - la $t1, 0 - la $t2, 0 + lw $t0, -4($fp) + lw $t1, 4($fp) + lw $t2, 0($fp) concat_loop_a: lb $a0, ($t1) @@ -173,18 +606,16 @@ String_concat: # RETURN concat_result ; lw $v0, -4($fp) - addu $sp, $sp, 8 + addu $sp, $sp, 4 jr $ra String_substr: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 + subu $sp, $sp, 4 # substring_result = SUBSTRING self i l; - lw $t0, 0($fp) + lw $t0, 8($fp) la $t1, substring_result lw $t4, 4($fp) - lw $t2, 8($fp) + lw $t2, 0($fp) addu $t0, $t0, $t4 substring_loop: @@ -199,989 +630,78 @@ String_substr: # RETURN substring_result ; lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -List_isNil: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List abort ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Object_abort - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN ; - li $v0, 0 addu $sp, $sp, 4 jr $ra -List_cons: +Object_abort: move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # local_0 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 + subu $sp, $sp, 0 + # ABORT None ; + la $a0, data_abort + li $v0, 4 syscall - sw $v0, -4($fp) - # local_1 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 16 ; - li $t0, 16 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = local_0 ; - lw $t0, -4($fp) - sw $t0, -8($fp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG hd ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Cons init ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal Cons_init - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -List_car: - move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List abort ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Object_abort - lw $t0, 0($sp) - addu $sp, $sp, 4 - # local_1 = ALLOCATE Int ; - li $a0, 8 - li $v0, 9 + lw $a0, ($fp) + li $v0, 4 syscall - sw $v0, -4($fp) - # local_2 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -8($fp) - # SETATTR local_1 @type local_2 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_2 = 8 ; - li $t0, 8 - sw $t0, -8($fp) - # SETATTR local_1 @size local_2 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # RETURN local_1 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -List_cdr: + la $a0, new_line + li $v0, 4 + syscall + li $v0, 10 + syscall +String_abort: move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List abort ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Object_abort - lw $t0, 0($sp) - addu $sp, $sp, 4 - # local_1 = ALLOCATE List ; - li $a0, 8 - li $v0, 9 + subu $sp, $sp, 0 + # ABORT String ; + la $a0, data_abort + li $v0, 4 syscall - sw $v0, -4($fp) - # local_2 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -8($fp) - # SETATTR local_1 @type local_2 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_2 = 8 ; - li $t0, 8 - sw $t0, -8($fp) - # SETATTR local_1 @size local_2 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # RETURN local_1 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -List_rev: + la $a0, abort_String + li $v0, 4 + syscall + la $a0, new_line + li $v0, 4 + syscall + li $v0, 10 + syscall +Main_main: move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List cdr ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_cdr - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 + subu $sp, $sp, 0 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 0 jr $ra -List_sort: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List cdr ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_cdr - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -List_insert: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List cdr ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_cdr - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -List_rcons: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List cdr ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_cdr - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -List_print_list: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List abort ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Object_abort - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -Cons_isNil: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # RETURN ; - li $v0, 0 - addu $sp, $sp, 4 - jr $ra -Cons_init: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # SETATTR self xcar hd ; - lw $t0, 4($fp) - lw $t1, 0($fp) - sw $t0, 4($t1) - # SETATTR self xcdr tl ; - lw $t0, 8($fp) - lw $t1, 0($fp) - sw $t0, 8($t1) - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 4 - jr $ra -Cons_car: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # local_0 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -4($fp) - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -Cons_cdr: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # local_0 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -4($fp) - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -Cons_rev: - move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # local_0 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -4($fp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List rev ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_rev - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # local_2 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -8($fp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_2 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List rcons ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_rcons - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -Cons_sort: - move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # local_0 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -4($fp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List sort ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_sort - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # local_2 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -8($fp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_2 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List insert ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_insert - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -Cons_insert: - move $fp, $sp - # 3 LOCALS = 12 bytes - sw $ra, -16($fp) - subu $sp, $sp, 16 - # local_0 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -4($fp) - # local_1 = i < local_0 ; - lw $t1, 4 - lw $t2, -4 - sle $t0, $t1, $t2 - sw $t0, -8 - # IF local_1 GOTO label_1 ; - lw $t0, -8($fp) - bnez $t0, label_1 - # local_0 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 - syscall - sw $v0, -4($fp) - # local_1 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 16 ; - li $t0, 16 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_9 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -12($fp) - # local_1 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -8($fp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL List insert ; - subu $sp, $sp, 12 - sw $t1, 8($sp) - sw $t0, 4($sp) - sw $t2, 0($sp) - jal List_insert - lw $t1, 8($sp) - lw $t0, 4($sp) - lw $t2, 0($sp) - addu $sp, $sp, 12 - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_9 ; - lw $t0, -12($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Cons init ; - subu $sp, $sp, 12 - sw $t1, 8($sp) - sw $t0, 4($sp) - sw $t2, 0($sp) - jal Cons_init - lw $t1, 8($sp) - lw $t0, 4($sp) - lw $t2, 0($sp) - addu $sp, $sp, 12 - # local_9 = local_0 ; - lw $t0, -4($fp) - sw $t0, -12($fp) - # GOTO label_2 ; - b label_2 - # LABEL label_1 ; - label_1: - - # local_0 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 - syscall - sw $v0, -4($fp) - # local_1 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 16 ; - li $t0, 16 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Cons init ; - subu $sp, $sp, 12 - sw $t1, 8($sp) - sw $t0, 4($sp) - sw $t2, 0($sp) - jal Cons_init - lw $t1, 8($sp) - lw $t0, 4($sp) - lw $t2, 0($sp) - addu $sp, $sp, 12 - # local_9 = local_0 ; - lw $t0, -4($fp) - sw $t0, -12($fp) - # LABEL label_2 ; - label_2: - - # RETURN local_9 ; - lw $v0, -12($fp) - addu $sp, $sp, 16 - jr $ra -Cons_rcons: - move $fp, $sp - # 3 LOCALS = 12 bytes - sw $ra, -16($fp) - subu $sp, $sp, 16 - # local_0 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 - syscall - sw $v0, -4($fp) - # local_1 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 16 ; - li $t0, 16 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_3 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -12($fp) - # local_1 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -8($fp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL List rcons ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_rcons - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_3 ; - lw $t0, -12($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Cons init ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal Cons_init - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 16 - jr $ra -Cons_print_list: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # local_0 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -4($fp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL Cons out_int ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal IO_out_int - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # local_0 = LOAD data_5 ; - la $t0, data_5 - sw $t0, -4($fp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_3 = VCALL Cons out_string ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal IO_out_string - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # local_0 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 8($t0) - sw $t1, -4($fp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List print_list ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal List_print_list - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -Nil_isNil: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # RETURN ; - li $v0, 0 - addu $sp, $sp, 4 - jr $ra -Nil_rev: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 4 - jr $ra -Nil_sort: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 4 - jr $ra -Nil_insert: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Nil rcons ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Nil_rcons - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 - jr $ra -Nil_rcons: - move $fp, $sp - # 2 LOCALS = 8 bytes - sw $ra, -12($fp) - subu $sp, $sp, 12 - # local_0 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 - syscall - sw $v0, -4($fp) - # local_1 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 16 ; - li $t0, 16 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Cons init ; - subu $sp, $sp, 8 - sw $t0, 4($sp) - sw $t1, 0($sp) - jal Cons_init - lw $t0, 4($sp) - lw $t1, 0($sp) - addu $sp, $sp, 8 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 12 - jr $ra -Nil_print_list: - move $fp, $sp - # 0 LOCALS = 0 bytes - sw $ra, -4($fp) - subu $sp, $sp, 4 - # RETURN ; - li $v0, 0 - addu $sp, $sp, 4 - jr $ra -Main_iota: - move $fp, $sp - # 3 LOCALS = 12 bytes - sw $ra, -16($fp) - subu $sp, $sp, 16 - # local_0 = ALLOCATE Nil ; - li $a0, 8 - li $v0, 9 - syscall - sw $v0, -4($fp) - # local_1 = LOAD data_6 ; - la $t0, data_6 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # local_1 = 8 ; - li $t0, 8 - sw $t0, -8($fp) - # SETATTR local_0 @size local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # SETATTR self l local_0 ; - lw $t0, -4($fp) - lw $t1, 0($fp) - sw $t0, 4($t1) - # local_0 = 0 ; - li $t0, 0 - sw $t0, -4($fp) - # LABEL label_3 ; - label_3: - - # local_1 = local_0 < i ; - lw $t1, -4 - lw $t2, 4 - sle $t0, $t1, $t2 - sw $t0, -8 - # IF local_1 GOTO label_4 ; - lw $t0, -8($fp) - bnez $t0, label_4 - # GOTO label_5 ; - b label_5 - # LABEL label_4 ; - label_4: - - # local_1 = ALLOCATE Cons ; - li $a0, 16 - li $v0, 9 - syscall - sw $v0, -8($fp) - # local_6 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -12($fp) - # SETATTR local_1 @type local_6 ; - lw $t0, -12($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # local_6 = 16 ; - li $t0, 16 - sw $t0, -12($fp) - # SETATTR local_1 @size local_6 ; - lw $t0, -12($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # local_6 = GETATTR self l ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -12($fp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_6 ; - lw $t0, -12($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL Cons init ; - subu $sp, $sp, 12 - sw $t1, 8($sp) - sw $t0, 4($sp) - sw $t2, 0($sp) - jal Cons_init - lw $t1, 8($sp) - lw $t0, 4($sp) - lw $t2, 0($sp) - addu $sp, $sp, 12 - # SETATTR self l local_1 ; - lw $t0, -8($fp) - lw $t1, 0($fp) - sw $t0, 4($t1) - # local_1 = local_0 + 1 ; - lw $t0, -4($fp) - li $t1, 1 - add $t2, $t0, $t1 - sw $t2, -8($fp) - # GOTO label_3 ; - b label_3 - # LABEL label_5 ; - label_5: - - # local_0 = GETATTR self l ; - lw $t0, 0($fp) - lw $t1, 4($t0) - sw $t1, -4($fp) - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 16 - jr $ra -Main_main: - move $fp, $sp - # 1 LOCALS = 4 bytes - sw $ra, -8($fp) - subu $sp, $sp, 8 - # local_0 = LOAD data_7 ; - la $t0, data_7 - sw $t0, -4($fp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_1 = VCALL Main out_string ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal IO_out_string - lw $t0, 0($sp) - addu $sp, $sp, 4 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Main in_int ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal IO_in_int - lw $t0, 0($sp) - addu $sp, $sp, 4 - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL Main iota ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal Main_iota - lw $t0, 0($sp) - addu $sp, $sp, 4 - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List rev ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_rev - lw $t0, 0($sp) - addu $sp, $sp, 4 - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List sort ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_sort - lw $t0, 0($sp) - addu $sp, $sp, 4 - # ARG local_0 ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # local_0 = VCALL List print_list ; - subu $sp, $sp, 4 - sw $t0, 0($sp) - jal List_print_list - lw $t0, 0($sp) - addu $sp, $sp, 4 - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 8 .data data_1: .asciiz "Main" data_2: - .asciiz "Cons" + .asciiz "2 is trivially prime.\n" data_3: - .asciiz "Int" + .asciiz " is prime.\n" data_4: - .asciiz "List" + .asciiz "halt" data_5: + .asciiz "continue" + data_abort: + .asciiz "Abort called from class " + new_line: .asciiz "\n" - data_6: - .asciiz "Nil" - data_7: - .asciiz "How many numbers to sort? " + vt_Object: + .space 36 + vt_IO: + .space 36 + vt_Int: + .space 36 + vt_String: + .space 36 + vt_Bool: + .space 36 + vt_Main: + .space 36 str: .space 1024 concat_result: .space 2048 substring_result: .space 1024 + abort_String: + .asciiz "String" diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 8bcbdb13..042806de 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -12,16 +12,21 @@ def init_types(types): a unique number for each type which will be identified in MIPS (code_mips)\n """ + size_vt=0 for i, t in enumerate(types): t.code_mips = i t.size_mips = (len(t.attributes) + 2) * 4 - t.size_vt = (len(t.methods) + 1) * 4 + size_vt = max(size_vt, (len(t.methods) + 1) * 4) t.attr_index_mips = {} for i, a in enumerate(t.attributes): t.attr_index_mips[a] = i + 1 __TYPES__[t.type] = t + return size_vt +def get_types(): + return __TYPES__ + def get_type(name): try: return __TYPES__[name] diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py index 99fc4683..9f87869e 100644 --- a/src/lexer_parser/parsetab.py +++ b/src/lexer_parser/parsetab.py @@ -1,12 +1,11 @@ # parsetab.py # This file is automatically generated. Do not edit. -# pylint: disable=W,C,R -_tabversion = '3.10' +_tabversion = '3.8' _lr_method = 'LALR' -_lr_signature = 'leftATleftNOTleftISVOIDleftLNOTleftLOWEREQLOWEREQUALleftPLUSMINUSleftSTARDIVleftDOTARROW ASSIGN AT BOOL CASE CBRACKET CLASS COLON COMMA CPAREN DIV DOT ELSE EQUAL ESAC FI ID IF IN INHERITS INT ISVOID LET LNOT LOOP LOWER LOWEREQ MINUS NEW NOT OBRACKET OF OPAREN PLUS POOL SEMICOLON STAR STRING THEN TYPE WHILEprogram : class_listempty :class_list : def_class SEMICOLON class_list\n | def_class SEMICOLONdef_class : CLASS TYPE OBRACKET feature_list CBRACKET\n | CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKETfeature_list : def_attr SEMICOLON feature_list\n | def_func SEMICOLON feature_list\n | emptydef_attr : ID COLON TYPE ASSIGN expr\n | ID COLON TYPEdef_func : ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKETparams : param_listparams : emptyparam_list : param COMMA param_list\n | param emptyparam : ID COLON TYPEexpr : LET let_attrs IN expr\n | CASE expr OF case_list ESAC\n | IF expr THEN expr ELSE expr FI\n | WHILE expr LOOP expr POOLexpr : ID ASSIGN exprexpr : expr AT TYPE DOT ID OPAREN arg_list CPAREN\n | expr DOT ID OPAREN arg_list CPAREN\n | ID OPAREN arg_list CPARENexpr : expr PLUS expr\n | expr MINUS expr\n | expr STAR expr\n | expr DIV expr\n | expr LOWER expr\n | expr LOWEREQ expr\n | expr EQUAL exprexpr : NOT expr\n | ISVOID expr\n | LNOT exprexpr : OPAREN expr CPARENexpr : atomlet_attrs : def_attr COMMA let_attrs\n | def_attrcase_list : case_elem SEMICOLON case_list\n | case_elem SEMICOLONcase_elem : ID COLON TYPE ARROW exprarg_list : arg_list_ne\n | emptyarg_list_ne : expr COMMA arg_list_ne\n | expr atom : INTatom : IDatom : NEW TYPEatom : blockatom : BOOLatom : STRINGblock : OBRACKET block_list CBRACKETblock_list : expr SEMICOLON block_list\n | expr SEMICOLON' +_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' _lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} From bb6897270a15551f6531a8cff2d59ffdf90c27cc Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 11:24:01 -0500 Subject: [PATCH 411/435] adding built in types to function call --- src/code_generation/CIL/cil.py | 10 +++++++--- src/code_generation/MIPS/test.asm | 10 ++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 90a6593d..2853d289 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -512,16 +512,20 @@ def block_to_cil_visitor(block): def func_call_to_cil_visitor(call): body = [] t = add_local() + returned=None if call.object: obj_cil = expression_to_cil_visitor( call.object) body += obj_cil.body obj = obj_cil.value - # _, t, _ = call.object.returned_type.get_method( - # call.id, [arg.returned_type for arg in call.args]) + _, returned, _ = call.object.returned_type.get_method( + call.id, [arg.returned_type for arg in call.args]) else: obj = 'self' - body.append(CilAST.GetTypeAddrNode(t, obj)) + if returned and returned.name in ("String", "Int", "Bool"): + call.type=returned.name + else: + body.append(CilAST.GetTypeAddrNode(t, obj)) arg_values = [] diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 097d4845..c308f6b2 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -423,11 +423,7 @@ main: # local_45 = LOAD data_4 ; la $t0, data_4 sw $t0, -184($fp) - # local_44 = GETTYPEADDR local_45 ; - lw $t1, -184($fp) - lw $t0, 8($t1) - sw $t0, -180($fp) - # local_46 = VCALL local_44 abort ; + # local_46 = VCALL String abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -435,9 +431,7 @@ main: lw $t0, -184($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -180($fp) - ulw $t1, 0($t0) - jalr $t1 + jal String_abort addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) From 2c865a5e2a4959852f5915e88239c4835daf1298 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 18:20:42 -0500 Subject: [PATCH 412/435] adding built_in special methods --- src/code_generation/CIL/cil.py | 47 ++- src/code_generation/MIPS/mips.py | 8 +- src/code_generation/MIPS/test.asm | 656 ++++++++++++------------------ src/cool_types/types.py | 7 + 4 files changed, 320 insertions(+), 398 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 2853d289..1e27b95d 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -114,8 +114,8 @@ def program_to_cil_visitor(program): fun = func_to_cil_visitor(c.type, f) code.append(fun) - built_in_code += built_in_to_cil() + built_in_code += built_in_to_cil() data = [CilAST.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] @@ -129,7 +129,7 @@ def program_to_cil_visitor(program): def built_in_to_cil(): - return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil(), abort_string_to_cil()] + return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil(), abort_string_to_cil(), abort_int_to_cil(), abort_bool_to_cil(), type_name_bool_to_cil(), type_name_int_to_cil(), type_name_string_to_cil()] def out_string_to_cil(): @@ -150,11 +150,43 @@ def in_int_to_cil(): return CilAST.FuncNode('IO_in_int', [CilAST.ParamNode('self')], [i], [CilAST.ReadIntNode(i), CilAST.ReturnNode(i)]) +def type_name_string_to_cil(): + str_addr=add_str_data('String') + t, need_load = add_data_local(str_addr) + + if need_load: + body = [CilAST.LoadNode(str_addr, t)] + else: + body = [] + + return CilAST.FuncNode('String_type_name', [CilAST.ParamNode('self')], [t], body+[CilAST.ReturnNode(t)]) + +def type_name_int_to_cil(): + str_addr=add_str_data('Int') + t, need_load = add_data_local(str_addr) + + if need_load: + body = [CilAST.LoadNode(str_addr, t)] + else: + body = [] + return CilAST.FuncNode('Int_type_name', [CilAST.ParamNode('self')], [t], body+[CilAST.ReturnNode(t)]) + +def type_name_bool_to_cil(): + str_addr=add_str_data('Bool') + t, need_load = add_data_local(str_addr) + + if need_load: + body = [CilAST.LoadNode(str_addr, t)] + else: + body = [] + return CilAST.FuncNode('Bool_type_name', [CilAST.ParamNode('self')], [t], body+[ CilAST.ReturnNode(t)]) + def type_name_to_cil(): t = CilAST.LocalNode('type') return CilAST.FuncNode('Object_type_name', [CilAST.ParamNode('self')], [t], [CilAST.TypeOfNode(t, 'self'), CilAST.ReturnNode(t)]) + def copy_to_cil(): copy = CilAST.LocalNode('copy') return CilAST.FuncNode('Object_copy', [CilAST.ParamNode('self')], [copy], [CilAST.CopyNode('self', copy), CilAST.ReturnNode(copy)]) @@ -182,6 +214,14 @@ def abort_to_cil(): def abort_string_to_cil(): return CilAST.FuncNode('String_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('String')]) +def abort_bool_to_cil(): + return CilAST.FuncNode('Bool_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('Bool')]) + +def abort_int_to_cil(): + return CilAST.FuncNode('Int_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('Int')]) + + + def func_to_cil_visitor(type_name, func): ''' @@ -518,8 +558,7 @@ def func_call_to_cil_visitor(call): call.object) body += obj_cil.body obj = obj_cil.value - _, returned, _ = call.object.returned_type.get_method( - call.id, [arg.returned_type for arg in call.args]) + returned=call.object.returned_type else: obj = 'self' if returned and returned.name in ("String", "Int", "Bool"): diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 9916fde7..f56080f2 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -191,6 +191,7 @@ def read_to_mips_visitor(read: cil.ReadNode): # TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): + result_offset=CURRENT_FUNCTION.offset[str(ss.result)] str_offset = CURRENT_FUNCTION.offset[str(ss.str)] i_offset = CURRENT_FUNCTION.offset[str(ss.i)] len_offset = CURRENT_FUNCTION.offset[str(ss.len)] @@ -212,7 +213,9 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.AdduInstruction('$t0', '$t0', 1), mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('substring_loop'), - mips.MIPSLabel('end_substring_loop') + mips.MIPSLabel('end_substring_loop'), + mips.LaInstruction('$t1', ss.result.id), + mips.SwInstruction('$t1', f'{result_offset}($fp)') ] @@ -341,7 +344,8 @@ def type_of_to_mips_visitor(typeof: cil.TypeOfNode): return [ mips.Comment(str(typeof)), mips.LwInstruction('$t0', f'{x_addr}($fp)'), - mips.SwInstruction('$t0', f'{t_addr}($fp)') + mips.LwInstruction('$t1', '($t0)'), + mips.SwInstruction('$t1', f'{t_addr}($fp)') ] diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index c308f6b2..1e1d3fd8 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -2,7 +2,7 @@ .text main: move $fp, $sp - subu $sp, $sp, 204 + subu $sp, $sp, 16 la $t0, Object_abort usw $t0, vt_Object+0 la $t0, Object_type_name @@ -23,15 +23,15 @@ main: usw $t0, vt_IO+20 la $t0, IO_in_int usw $t0, vt_IO+24 - la $t0, Object_abort + la $t0, Int_abort usw $t0, vt_Int+0 - la $t0, Object_type_name + la $t0, Int_type_name usw $t0, vt_Int+4 la $t0, Object_copy usw $t0, vt_Int+8 la $t0, String_abort usw $t0, vt_String+0 - la $t0, Object_type_name + la $t0, String_type_name usw $t0, vt_String+4 la $t0, Object_copy usw $t0, vt_String+8 @@ -41,9 +41,9 @@ main: usw $t0, vt_String+32 la $t0, String_substr usw $t0, vt_String+36 - la $t0, Object_abort + la $t0, Bool_abort usw $t0, vt_Bool+0 - la $t0, Object_type_name + la $t0, Bool_type_name usw $t0, vt_Bool+4 la $t0, Object_copy usw $t0, vt_Bool+8 @@ -64,7 +64,7 @@ main: la $t0, Main_main usw $t0, vt_Main+40 # self = ALLOCATE Main ; - li $a0, 32 + li $a0, 12 li $v0, 9 syscall sw $v0, -4($fp) @@ -77,384 +77,13 @@ main: lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 0($t1) - # local_2 = 32 ; - li $t0, 32 + # local_2 = 12 ; + li $t0, 12 sw $t0, -12($fp) # SETATTR self @size local_2 ; lw $t0, -12($fp) lw $t1, -4($fp) sw $t0, 4($t1) - # local_3 = GETTYPEADDR self ; - lw $t1, -4($fp) - lw $t0, 8($t1) - sw $t0, -16($fp) - # local_4 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -20($fp) - # local_5 = VCALL local_3 out_string ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -16($fp) - ulw $t1, 12($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -24($fp) - # SETATTR self out 2 ; - li $t0, 2 - lw $t1, -4($fp) - sw $t0, 12($t1) - # local_6 = GETATTR self out ; - lw $t0, -4($fp) - lw $t1, 12($t0) - sw $t1, -28($fp) - # SETATTR self testee local_6 ; - lw $t0, -28($fp) - lw $t1, -4($fp) - sw $t0, 16($t1) - # SETATTR self stop 500 ; - li $t0, 500 - lw $t1, -4($fp) - sw $t0, 24($t1) - # LABEL label_13 ; - label_13: - - # IF 1 GOTO label_14 ; - li $t0, 1 - bnez $t0, label_14 - # GOTO label_15 ; - b label_15 - # LABEL label_14 ; - label_14: - - # local_7 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -32($fp) - # local_8 = local_7 + 1 ; - lw $t0, -32($fp) - li $t1, 1 - add $t0, $t0, $t1 - sw $t0, -36($fp) - # SETATTR self testee local_8 ; - lw $t0, -36($fp) - lw $t1, -4($fp) - sw $t0, 16($t1) - # SETATTR self divisor 2 ; - li $t0, 2 - lw $t1, -4($fp) - sw $t0, 20($t1) - # LABEL label_6 ; - label_6: - - # local_9 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -40($fp) - # local_10 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -44($fp) - # local_11 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -48($fp) - # local_12 = local_10 * local_11 ; - lw $t0, -44($fp) - lw $t1, -48($fp) - mul $t0, $t0, $t1 - sw $t0, -52($fp) - # local_13 = local_9 < local_12 ; - lw $t0, -40($fp) - lw $t1, -52($fp) - slt $t0, $t0, $t1 - sw $t0, -56($fp) - # IF local_13 GOTO label_4 ; - lw $t0, -56($fp) - bnez $t0, label_4 - # local_14 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -60($fp) - # local_15 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -64($fp) - # local_16 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -68($fp) - # local_17 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -72($fp) - # local_18 = local_16 / local_17 ; - lw $t0, -68($fp) - lw $t1, -72($fp) - div $t0, $t0, $t1 - sw $t0, -76($fp) - # local_19 = local_15 * local_18 ; - lw $t0, -64($fp) - lw $t1, -76($fp) - mul $t0, $t0, $t1 - sw $t0, -80($fp) - # local_20 = local_14 - local_19 ; - lw $t0, -60($fp) - lw $t1, -80($fp) - sub $t0, $t0, $t1 - sw $t0, -84($fp) - # local_21 = local_20 - 0 ; - lw $t0, -84($fp) - li $t1, 0 - sub $t0, $t0, $t1 - sw $t0, -88($fp) - # local_22 = 0 ; - li $t0, 0 - sw $t0, -92($fp) - # IF local_21 GOTO label_1 ; - lw $t0, -88($fp) - bnez $t0, label_1 - # local_22 = 1 ; - li $t0, 1 - sw $t0, -92($fp) - # LABEL label_1 ; - label_1: - - # IF local_22 GOTO label_2 ; - lw $t0, -92($fp) - bnez $t0, label_2 - # local_23 = 1 ; - li $t0, 1 - sw $t0, -96($fp) - # GOTO label_3 ; - b label_3 - # LABEL label_2 ; - label_2: - - # local_23 = 0 ; - li $t0, 0 - sw $t0, -96($fp) - # LABEL label_3 ; - label_3: - - # local_24 = local_23 ; - lw $t0, -96($fp) - sw $t0, -100($fp) - # GOTO label_5 ; - b label_5 - # LABEL label_4 ; - label_4: - - # local_24 = 0 ; - li $t0, 0 - sw $t0, -100($fp) - # LABEL label_5 ; - label_5: - - # IF local_24 GOTO label_7 ; - lw $t0, -100($fp) - bnez $t0, label_7 - # GOTO label_8 ; - b label_8 - # LABEL label_7 ; - label_7: - - # local_25 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -104($fp) - # local_26 = local_25 + 1 ; - lw $t0, -104($fp) - li $t1, 1 - add $t0, $t0, $t1 - sw $t0, -108($fp) - # SETATTR self divisor local_26 ; - lw $t0, -108($fp) - lw $t1, -4($fp) - sw $t0, 20($t1) - # GOTO label_6 ; - b label_6 - # LABEL label_8 ; - label_8: - - # local_27 = 0 ; - li $t0, 0 - sw $t0, -112($fp) - # local_28 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -116($fp) - # local_29 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -120($fp) - # local_30 = GETATTR self divisor ; - lw $t0, -4($fp) - lw $t1, 20($t0) - sw $t1, -124($fp) - # local_31 = local_29 * local_30 ; - lw $t0, -120($fp) - lw $t1, -124($fp) - mul $t0, $t0, $t1 - sw $t0, -128($fp) - # local_32 = local_28 < local_31 ; - lw $t0, -116($fp) - lw $t1, -128($fp) - slt $t0, $t0, $t1 - sw $t0, -132($fp) - # IF local_32 GOTO label_9 ; - lw $t0, -132($fp) - bnez $t0, label_9 - # local_40 = 0 ; - li $t0, 0 - sw $t0, -164($fp) - # GOTO label_10 ; - b label_10 - # LABEL label_9 ; - label_9: - - # local_33 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -136($fp) - # SETATTR self out local_33 ; - lw $t0, -136($fp) - lw $t1, -4($fp) - sw $t0, 12($t1) - # local_34 = GETTYPEADDR self ; - lw $t1, -4($fp) - lw $t0, 8($t1) - sw $t0, -140($fp) - # local_35 = GETATTR self out ; - lw $t0, -4($fp) - lw $t1, 12($t0) - sw $t1, -144($fp) - # local_36 = VCALL local_34 out_int ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_35 ; - lw $t0, -144($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -140($fp) - ulw $t1, 16($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -148($fp) - # local_37 = GETTYPEADDR self ; - lw $t1, -4($fp) - lw $t0, 8($t1) - sw $t0, -152($fp) - # local_38 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -156($fp) - # local_39 = VCALL local_37 out_string ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, -4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_38 ; - lw $t0, -156($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -152($fp) - ulw $t1, 12($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -160($fp) - # local_40 = local_39 ; - lw $t0, -160($fp) - sw $t0, -164($fp) - # LABEL label_10 ; - label_10: - - # local_41 = GETATTR self stop ; - lw $t0, -4($fp) - lw $t1, 24($t0) - sw $t1, -168($fp) - # local_42 = GETATTR self testee ; - lw $t0, -4($fp) - lw $t1, 16($t0) - sw $t1, -172($fp) - # local_43 = local_41 <= local_42 ; - lw $t0, -168($fp) - lw $t1, -172($fp) - sle $t0, $t0, $t1 - sw $t0, -176($fp) - # IF local_43 GOTO label_11 ; - lw $t0, -176($fp) - bnez $t0, label_11 - # local_47 = LOAD data_5 ; - la $t0, data_5 - sw $t0, -192($fp) - # local_48 = local_47 ; - lw $t0, -192($fp) - sw $t0, -196($fp) - # GOTO label_12 ; - b label_12 - # LABEL label_11 ; - label_11: - - # local_45 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -184($fp) - # local_46 = VCALL String abort ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_45 ; - lw $t0, -184($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_abort - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -188($fp) - # local_48 = local_46 ; - lw $t0, -188($fp) - sw $t0, -196($fp) - # LABEL label_12 ; - label_12: - - # GOTO label_13 ; - b label_13 - # LABEL label_15 ; - label_15: - - # local_49 = 0 ; - li $t0, 0 - sw $t0, -200($fp) - # SETATTR self m local_49 ; - lw $t0, -200($fp) - lw $t1, -4($fp) - sw $t0, 28($t1) # main_result = VCALL Main main ; subu $sp, $sp, 8 sw $ra, 0($sp) @@ -468,10 +97,10 @@ main: lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -204($fp) + sw $v0, -16($fp) # RETURN main_result ; - lw $v0, -204($fp) - addu $sp, $sp, 204 + lw $v0, -16($fp) + addu $sp, $sp, 16 li $v0, 10 syscall IO_out_int: @@ -524,7 +153,8 @@ Object_type_name: subu $sp, $sp, 4 # type = TYPEOF self ; lw $t0, 0($fp) - sw $t0, -4($fp) + lw $t1, ($t0) + sw $t1, -4($fp) # RETURN type ; lw $v0, -4($fp) addu $sp, $sp, 4 @@ -622,6 +252,8 @@ String_substr: b substring_loop end_substring_loop: + la $t1, substring_result + sw $t1, -4($fp) # RETURN substring_result ; lw $v0, -4($fp) addu $sp, $sp, 4 @@ -656,25 +288,261 @@ String_abort: syscall li $v0, 10 syscall -Main_main: +Int_abort: move $fp, $sp subu $sp, $sp, 0 - # RETURN ; - li $v0, 0 - addu $sp, $sp, 0 + # ABORT Int ; + la $a0, data_abort + li $v0, 4 + syscall + la $a0, abort_Int + li $v0, 4 + syscall + la $a0, new_line + li $v0, 4 + syscall + li $v0, 10 + syscall +Bool_abort: + move $fp, $sp + subu $sp, $sp, 0 + # ABORT Bool ; + la $a0, data_abort + li $v0, 4 + syscall + la $a0, abort_Bool + li $v0, 4 + syscall + la $a0, new_line + li $v0, 4 + syscall + li $v0, 10 + syscall +Bool_type_name: + move $fp, $sp + subu $sp, $sp, 4 + # local_18 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -4($fp) + # RETURN local_18 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +Int_type_name: + move $fp, $sp + subu $sp, $sp, 4 + # local_19 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -4($fp) + # RETURN local_19 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +String_type_name: + move $fp, $sp + subu $sp, $sp, 4 + # local_20 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -4($fp) + # RETURN local_20 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +Main_main: + move $fp, $sp + subu $sp, $sp, 72 + # local_1 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -8($fp) + # local_4 = ALLOCATE Object ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -20($fp) + la $t0, vt_Object + sw $t0, 8($v0) + # local_5 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -24($fp) + # SETATTR local_4 @type local_5 ; + lw $t0, -24($fp) + lw $t1, -20($fp) + sw $t0, 0($t1) + # local_6 = 12 ; + li $t0, 12 + sw $t0, -28($fp) + # SETATTR local_4 @size local_6 ; + lw $t0, -28($fp) + lw $t1, -20($fp) + sw $t0, 4($t1) + # local_3 = GETTYPEADDR local_4 ; + lw $t1, -20($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_7 = VCALL local_3 type_name ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 4($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # local_8 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 4 ; + li $t0, 4 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_9 = VCALL local_1 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_8 ; + lw $t0, -36($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -8($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -40($fp) + # local_0 = GETTYPEADDR local_9 ; + lw $t1, -40($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_12 = VCALL Bool type_name ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal Bool_type_name + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_12 ; + lw $t0, -52($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 3 ; + li $t0, 3 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -56($fp) + # local_14 = VCALL local_0 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_9 ; + lw $t0, -40($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -60($fp) + # local_15 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -64($fp) + # local_16 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -68($fp) + # local_17 = VCALL local_15 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_16 ; + lw $t0, -68($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -64($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -72($fp) + # RETURN local_17 ; + lw $v0, -72($fp) + addu $sp, $sp, 72 jr $ra .data data_1: .asciiz "Main" data_2: - .asciiz "2 is trivially prime.\n" + .asciiz "Object" data_3: - .asciiz " is prime.\n" + .asciiz "\n" data_4: - .asciiz "halt" + .asciiz "Bool" data_5: - .asciiz "continue" + .asciiz "Int" + data_6: + .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: @@ -699,3 +567,7 @@ Main_main: .space 1024 abort_String: .asciiz "String" + abort_Int: + .asciiz "Int" + abort_Bool: + .asciiz "Bool" diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 94a135d4..8792afbb 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -252,4 +252,11 @@ def pronounced_join(type_a, type_b): StringType.add_method('length', [], 'Int') StringType.add_method('concat', ['String'], 'String') StringType.add_method('substr', ['Int', 'Int'], 'String') + +IntType.add_method('abort', [], 'Object') +BoolType.add_method('abort', [], 'Object') StringType.add_method('abort', [], 'Object') + +StringType.add_method('type_name', [], 'String') +IntType.add_method('type_name', [], 'String') +BoolType.add_method('type_name', [], 'String') \ No newline at end of file From 4fe8198dbbbb7830b7f50ff2fe59f5a54cc88017 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 18:24:32 -0500 Subject: [PATCH 413/435] fixing vt size --- src/code_generation/MIPS/test.asm | 1380 ++++++++++++++++++++++--- src/code_generation/MIPS/utilities.py | 2 +- 2 files changed, 1255 insertions(+), 127 deletions(-) diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 1e1d3fd8..b9e471a7 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -48,6 +48,104 @@ main: la $t0, Object_copy usw $t0, vt_Bool+8 la $t0, Object_abort + usw $t0, vt_List+0 + la $t0, Object_type_name + usw $t0, vt_List+4 + la $t0, Object_copy + usw $t0, vt_List+8 + la $t0, IO_out_string + usw $t0, vt_List+12 + la $t0, IO_out_int + usw $t0, vt_List+16 + la $t0, IO_in_string + usw $t0, vt_List+20 + la $t0, IO_in_int + usw $t0, vt_List+24 + la $t0, List_isNil + usw $t0, vt_List+40 + la $t0, List_cons + usw $t0, vt_List+44 + la $t0, List_car + usw $t0, vt_List+48 + la $t0, List_cdr + usw $t0, vt_List+52 + la $t0, List_rev + usw $t0, vt_List+56 + la $t0, List_sort + usw $t0, vt_List+60 + la $t0, List_insert + usw $t0, vt_List+64 + la $t0, List_rcons + usw $t0, vt_List+68 + la $t0, List_print_list + usw $t0, vt_List+72 + la $t0, Object_abort + usw $t0, vt_Cons+0 + la $t0, Object_type_name + usw $t0, vt_Cons+4 + la $t0, Object_copy + usw $t0, vt_Cons+8 + la $t0, IO_out_string + usw $t0, vt_Cons+12 + la $t0, IO_out_int + usw $t0, vt_Cons+16 + la $t0, IO_in_string + usw $t0, vt_Cons+20 + la $t0, IO_in_int + usw $t0, vt_Cons+24 + la $t0, Cons_isNil + usw $t0, vt_Cons+40 + la $t0, List_cons + usw $t0, vt_Cons+44 + la $t0, Cons_car + usw $t0, vt_Cons+48 + la $t0, Cons_cdr + usw $t0, vt_Cons+52 + la $t0, Cons_rev + usw $t0, vt_Cons+56 + la $t0, Cons_sort + usw $t0, vt_Cons+60 + la $t0, Cons_insert + usw $t0, vt_Cons+64 + la $t0, Cons_rcons + usw $t0, vt_Cons+68 + la $t0, Cons_print_list + usw $t0, vt_Cons+72 + la $t0, Cons_init + usw $t0, vt_Cons+76 + la $t0, Object_abort + usw $t0, vt_Nil+0 + la $t0, Object_type_name + usw $t0, vt_Nil+4 + la $t0, Object_copy + usw $t0, vt_Nil+8 + la $t0, IO_out_string + usw $t0, vt_Nil+12 + la $t0, IO_out_int + usw $t0, vt_Nil+16 + la $t0, IO_in_string + usw $t0, vt_Nil+20 + la $t0, IO_in_int + usw $t0, vt_Nil+24 + la $t0, Nil_isNil + usw $t0, vt_Nil+40 + la $t0, List_cons + usw $t0, vt_Nil+44 + la $t0, List_car + usw $t0, vt_Nil+48 + la $t0, List_cdr + usw $t0, vt_Nil+52 + la $t0, Nil_rev + usw $t0, vt_Nil+56 + la $t0, Nil_sort + usw $t0, vt_Nil+60 + la $t0, Nil_insert + usw $t0, vt_Nil+64 + la $t0, Nil_rcons + usw $t0, vt_Nil+68 + la $t0, Nil_print_list + usw $t0, vt_Nil+72 + la $t0, Object_abort usw $t0, vt_Main+0 la $t0, Object_type_name usw $t0, vt_Main+4 @@ -61,10 +159,12 @@ main: usw $t0, vt_Main+20 la $t0, IO_in_int usw $t0, vt_Main+24 + la $t0, Main_iota + usw $t0, vt_Main+80 la $t0, Main_main - usw $t0, vt_Main+40 + usw $t0, vt_Main+84 # self = ALLOCATE Main ; - li $a0, 12 + li $a0, 16 li $v0, 9 syscall sw $v0, -4($fp) @@ -77,8 +177,8 @@ main: lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 0($t1) - # local_2 = 12 ; - li $t0, 12 + # local_2 = 16 ; + li $t0, 16 sw $t0, -12($fp) # SETATTR self @size local_2 ; lw $t0, -12($fp) @@ -321,104 +421,127 @@ Bool_abort: Bool_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_18 = LOAD data_4 ; - la $t0, data_4 + # local_13 = LOAD data_8 ; + la $t0, data_8 sw $t0, -4($fp) - # RETURN local_18 ; + # RETURN local_13 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra Int_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_19 = LOAD data_5 ; - la $t0, data_5 + # local_14 = LOAD data_3 ; + la $t0, data_3 sw $t0, -4($fp) - # RETURN local_19 ; + # RETURN local_14 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra String_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_20 = LOAD data_6 ; - la $t0, data_6 + # local_15 = LOAD data_9 ; + la $t0, data_9 sw $t0, -4($fp) - # RETURN local_20 ; + # RETURN local_15 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra -Main_main: +List_isNil: move $fp, $sp - subu $sp, $sp, 72 - # local_1 = GETTYPEADDR self ; + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -8($fp) - # local_4 = ALLOCATE Object ; - li $a0, 12 - li $v0, 9 - syscall - sw $v0, -20($fp) - la $t0, vt_Object - sw $t0, 8($v0) - # local_5 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -24($fp) - # SETATTR local_4 @type local_5 ; - lw $t0, -24($fp) - lw $t1, -20($fp) - sw $t0, 0($t1) - # local_6 = 12 ; - li $t0, 12 - sw $t0, -28($fp) - # SETATTR local_4 @size local_6 ; - lw $t0, -28($fp) - lw $t1, -20($fp) - sw $t0, 4($t1) - # local_3 = GETTYPEADDR local_4 ; - lw $t1, -20($fp) - lw $t0, 8($t1) - sw $t0, -16($fp) - # local_7 = VCALL local_3 type_name ; + sw $t0, -4($fp) + # local_1 = VCALL local_0 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_4 ; - lw $t0, -20($fp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -16($fp) - ulw $t1, 4($t0) + lw $t0, -4($fp) + ulw $t1, 0($t0) jalr $t1 addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -32($fp) - # local_8 = VCALL String substr ; + sw $v0, -8($fp) + # RETURN 1 ; + li $v0, 1 + addu $sp, $sp, 8 + jr $ra +List_cons: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -4($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_1 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 0($t1) + # local_2 = 20 ; + li $t0, 20 + sw $t0, -12($fp) + # SETATTR local_0 @size local_2 ; + lw $t0, -12($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # new_cell = local_0 ; + lw $t0, -4($fp) + sw $t0, -16($fp) + # local_4 = GETTYPEADDR new_cell ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -20($fp) + # local_5 = VCALL local_4 init ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_7 ; - lw $t0, -32($fp) + # ARG new_cell ; + lw $t0, -16($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 4 ; - li $t0, 4 + # ARG hd ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_substr + lw $t0, -20($fp) + ulw $t1, 76($t0) + jalr $t1 addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -36($fp) - # local_9 = VCALL local_1 out_string ; + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +List_car: + move $fp, $sp + subu $sp, $sp, 20 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -426,86 +549,203 @@ Main_main: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_8 ; - lw $t0, -36($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -8($fp) - ulw $t1, 12($t0) + lw $t0, -4($fp) + ulw $t1, 0($t0) jalr $t1 - addu $sp, $sp, 8 + addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -40($fp) - # local_0 = GETTYPEADDR local_9 ; - lw $t1, -40($fp) + sw $v0, -8($fp) + # local_2 = ALLOCATE Int ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -12($fp) + la $t0, vt_Int + sw $t0, 8($v0) + # local_3 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -16($fp) + # SETATTR local_2 @type local_3 ; + lw $t0, -16($fp) + lw $t1, -12($fp) + sw $t0, 0($t1) + # local_4 = 12 ; + li $t0, 12 + sw $t0, -20($fp) + # SETATTR local_2 @size local_4 ; + lw $t0, -20($fp) + lw $t1, -12($fp) + sw $t0, 4($t1) + # RETURN local_2 ; + lw $v0, -12($fp) + addu $sp, $sp, 20 + jr $ra +List_cdr: + move $fp, $sp + subu $sp, $sp, 20 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) sw $t0, -4($fp) - # local_12 = VCALL Bool type_name ; + # local_1 = VCALL local_0 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG 0 ; - li $t0, 0 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal Bool_type_name + lw $t0, -4($fp) + ulw $t1, 0($t0) + jalr $t1 addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -52($fp) - # local_13 = VCALL String substr ; + sw $v0, -8($fp) + # local_2 = ALLOCATE List ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -12($fp) + la $t0, vt_List + sw $t0, 8($v0) + # local_3 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -16($fp) + # SETATTR local_2 @type local_3 ; + lw $t0, -16($fp) + lw $t1, -12($fp) + sw $t0, 0($t1) + # local_4 = 12 ; + li $t0, 12 + sw $t0, -20($fp) + # SETATTR local_2 @size local_4 ; + lw $t0, -20($fp) + lw $t1, -12($fp) + sw $t0, 4($t1) + # RETURN local_2 ; + lw $v0, -12($fp) + addu $sp, $sp, 20 + jr $ra +List_rev: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 cdr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_12 ; - lw $t0, -52($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 3 ; - li $t0, 3 + lw $t0, -4($fp) + ulw $t1, 52($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +List_sort: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 cdr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 + lw $t0, -4($fp) + ulw $t1, 52($t0) + jalr $t1 + addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -56($fp) - # local_14 = VCALL local_0 out_string ; + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +List_insert: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 cdr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_9 ; - lw $t0, -40($fp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_13 ; - lw $t0, -56($fp) + lw $t0, -4($fp) + ulw $t1, 52($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +List_rcons: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 cdr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) lw $t0, -4($fp) - ulw $t1, 12($t0) + ulw $t1, 52($t0) jalr $t1 - addu $sp, $sp, 8 + addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -60($fp) - # local_15 = GETTYPEADDR self ; + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +List_print_list: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -64($fp) - # local_16 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -68($fp) - # local_17 = VCALL local_15 out_string ; + sw $t0, -4($fp) + # local_1 = VCALL local_0 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -513,52 +753,940 @@ Main_main: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_16 ; - lw $t0, -68($fp) + lw $t0, -4($fp) + ulw $t1, 0($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +Cons_isNil: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN ; + li $v0, 0 + addu $sp, $sp, 0 + jr $ra +Cons_init: + move $fp, $sp + subu $sp, $sp, 0 + # SETATTR self xcar hd ; + lw $t0, 4($fp) + lw $t1, 8($fp) + sw $t0, 12($t1) + # SETATTR self xcdr tl ; + lw $t0, 0($fp) + lw $t1, 8($fp) + sw $t0, 16($t1) + # RETURN self ; + lw $v0, 8($fp) + addu $sp, $sp, 0 + jr $ra +Cons_car: + move $fp, $sp + subu $sp, $sp, 4 + # local_0 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +Cons_cdr: + move $fp, $sp + subu $sp, $sp, 4 + # local_0 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +Cons_rev: + move $fp, $sp + subu $sp, $sp, 24 + # local_2 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -12($fp) + # local_1 = GETTYPEADDR local_2 ; + lw $t1, -12($fp) + lw $t0, 8($t1) + sw $t0, -8($fp) + # local_3 = VCALL local_1 rev ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_2 ; + lw $t0, -12($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -64($fp) - ulw $t1, 12($t0) + lw $t0, -8($fp) + ulw $t1, 56($t0) jalr $t1 - addu $sp, $sp, 8 + addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -72($fp) - # RETURN local_17 ; - lw $v0, -72($fp) - addu $sp, $sp, 72 - jr $ra - -.data - data_1: - .asciiz "Main" - data_2: - .asciiz "Object" - data_3: - .asciiz "\n" - data_4: - .asciiz "Bool" - data_5: + sw $v0, -16($fp) + # local_0 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_4 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -20($fp) + # local_5 = VCALL local_0 rcons ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 68($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +Cons_sort: + move $fp, $sp + subu $sp, $sp, 24 + # local_2 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -12($fp) + # local_1 = GETTYPEADDR local_2 ; + lw $t1, -12($fp) + lw $t0, 8($t1) + sw $t0, -8($fp) + # local_3 = VCALL local_1 sort ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_2 ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -8($fp) + ulw $t1, 60($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -16($fp) + # local_0 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_4 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -20($fp) + # local_5 = VCALL local_0 insert ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 64($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +Cons_insert: + move $fp, $sp + subu $sp, $sp, 68 + # local_0 = GETATTR self xcar ; + lw $t0, 4($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # local_1 = i < local_0 ; + lw $t0, 0($fp) + lw $t1, -4($fp) + slt $t0, $t0, $t1 + sw $t0, -8($fp) + # IF local_1 GOTO label_1 ; + lw $t0, -8($fp) + bnez $t0, label_1 + # local_8 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -36($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_9 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -40($fp) + # SETATTR local_8 @type local_9 ; + lw $t0, -40($fp) + lw $t1, -36($fp) + sw $t0, 0($t1) + # local_10 = 20 ; + li $t0, 20 + sw $t0, -44($fp) + # SETATTR local_8 @size local_10 ; + lw $t0, -44($fp) + lw $t1, -36($fp) + sw $t0, 4($t1) + # local_7 = GETTYPEADDR local_8 ; + lw $t1, -36($fp) + lw $t0, 8($t1) + sw $t0, -32($fp) + # local_11 = GETATTR self xcar ; + lw $t0, 4($fp) + lw $t1, 12($t0) + sw $t1, -48($fp) + # local_13 = GETATTR self xcdr ; + lw $t0, 4($fp) + lw $t1, 16($t0) + sw $t1, -56($fp) + # local_12 = GETTYPEADDR local_13 ; + lw $t1, -56($fp) + lw $t0, 8($t1) + sw $t0, -52($fp) + # local_14 = VCALL local_12 insert ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -52($fp) + ulw $t1, 64($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -60($fp) + # local_15 = VCALL local_7 init ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_8 ; + lw $t0, -36($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_14 ; + lw $t0, -60($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -32($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -64($fp) + # local_16 = local_15 ; + lw $t0, -64($fp) + sw $t0, -68($fp) + # GOTO label_2 ; + b label_2 + # LABEL label_1 ; + label_1: + + # local_3 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_4 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -20($fp) + # SETATTR local_3 @type local_4 ; + lw $t0, -20($fp) + lw $t1, -16($fp) + sw $t0, 0($t1) + # local_5 = 20 ; + li $t0, 20 + sw $t0, -24($fp) + # SETATTR local_3 @size local_5 ; + lw $t0, -24($fp) + lw $t1, -16($fp) + sw $t0, 4($t1) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_6 = VCALL local_2 init ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -28($fp) + # local_16 = local_6 ; + lw $t0, -28($fp) + sw $t0, -68($fp) + # LABEL label_2 ; + label_2: + + # RETURN local_16 ; + lw $v0, -68($fp) + addu $sp, $sp, 68 + jr $ra +Cons_rcons: + move $fp, $sp + subu $sp, $sp, 36 + # local_1 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -8($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # SETATTR local_1 @type local_2 ; + lw $t0, -12($fp) + lw $t1, -8($fp) + sw $t0, 0($t1) + # local_3 = 20 ; + li $t0, 20 + sw $t0, -16($fp) + # SETATTR local_1 @size local_3 ; + lw $t0, -16($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # local_0 = GETTYPEADDR local_1 ; + lw $t1, -8($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_4 = GETATTR self xcar ; + lw $t0, 4($fp) + lw $t1, 12($t0) + sw $t1, -20($fp) + # local_6 = GETATTR self xcdr ; + lw $t0, 4($fp) + lw $t1, 16($t0) + sw $t1, -28($fp) + # local_5 = GETTYPEADDR local_6 ; + lw $t1, -28($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_7 = VCALL local_5 rcons ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_6 ; + lw $t0, -28($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -24($fp) + ulw $t1, 68($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # local_8 = VCALL local_0 init ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # RETURN local_8 ; + lw $v0, -36($fp) + addu $sp, $sp, 36 + jr $ra +Cons_print_list: + move $fp, $sp + subu $sp, $sp, 36 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = GETATTR self xcar ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -8($fp) + # local_2 = VCALL local_0 out_int ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 16($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # local_3 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -20($fp) + # local_5 = VCALL local_3 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_7 = GETATTR self xcdr ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -32($fp) + # local_6 = GETTYPEADDR local_7 ; + lw $t1, -32($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_8 = VCALL local_6 print_list ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 72($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # RETURN local_8 ; + lw $v0, -36($fp) + addu $sp, $sp, 36 + jr $ra +Nil_isNil: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN 1 ; + li $v0, 1 + addu $sp, $sp, 0 + jr $ra +Nil_rev: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 0 + jr $ra +Nil_sort: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 0 + jr $ra +Nil_insert: + move $fp, $sp + subu $sp, $sp, 8 + # local_0 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = VCALL local_0 rcons ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 68($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # RETURN local_1 ; + lw $v0, -8($fp) + addu $sp, $sp, 8 + jr $ra +Nil_rcons: + move $fp, $sp + subu $sp, $sp, 20 + # local_1 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -8($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # SETATTR local_1 @type local_2 ; + lw $t0, -12($fp) + lw $t1, -8($fp) + sw $t0, 0($t1) + # local_3 = 20 ; + li $t0, 20 + sw $t0, -16($fp) + # SETATTR local_1 @size local_3 ; + lw $t0, -16($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # local_0 = GETTYPEADDR local_1 ; + lw $t1, -8($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_4 = VCALL local_0 init ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # RETURN local_4 ; + lw $v0, -20($fp) + addu $sp, $sp, 20 + jr $ra +Nil_print_list: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN 1 ; + li $v0, 1 + addu $sp, $sp, 0 + jr $ra +Main_iota: + move $fp, $sp + subu $sp, $sp, 56 + # local_0 = ALLOCATE Nil ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -4($fp) + la $t0, vt_Nil + sw $t0, 8($v0) + # local_1 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -8($fp) + # SETATTR local_0 @type local_1 ; + lw $t0, -8($fp) + lw $t1, -4($fp) + sw $t0, 0($t1) + # local_2 = 12 ; + li $t0, 12 + sw $t0, -12($fp) + # SETATTR local_0 @size local_2 ; + lw $t0, -12($fp) + lw $t1, -4($fp) + sw $t0, 4($t1) + # SETATTR self l local_0 ; + lw $t0, -4($fp) + lw $t1, 4($fp) + sw $t0, 12($t1) + # j = 0 ; + li $t0, 0 + sw $t0, -16($fp) + # LABEL label_3 ; + label_3: + + # local_4 = j < i ; + lw $t0, -16($fp) + lw $t1, 0($fp) + slt $t0, $t0, $t1 + sw $t0, -20($fp) + # IF local_4 GOTO label_4 ; + lw $t0, -20($fp) + bnez $t0, label_4 + # GOTO label_5 ; + b label_5 + # LABEL label_4 ; + label_4: + + # local_6 = ALLOCATE Cons ; + li $a0, 20 + li $v0, 9 + syscall + sw $v0, -28($fp) + la $t0, vt_Cons + sw $t0, 8($v0) + # local_7 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -32($fp) + # SETATTR local_6 @type local_7 ; + lw $t0, -32($fp) + lw $t1, -28($fp) + sw $t0, 0($t1) + # local_8 = 20 ; + li $t0, 20 + sw $t0, -36($fp) + # SETATTR local_6 @size local_8 ; + lw $t0, -36($fp) + lw $t1, -28($fp) + sw $t0, 4($t1) + # local_5 = GETTYPEADDR local_6 ; + lw $t1, -28($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_9 = GETATTR self l ; + lw $t0, 4($fp) + lw $t1, 12($t0) + sw $t1, -40($fp) + # local_10 = VCALL local_5 init ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_6 ; + lw $t0, -28($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG j ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_9 ; + lw $t0, -40($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -24($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -44($fp) + # SETATTR self l local_10 ; + lw $t0, -44($fp) + lw $t1, 4($fp) + sw $t0, 12($t1) + # local_11 = j + 1 ; + lw $t0, -16($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -48($fp) + # j = local_11 ; + lw $t0, -48($fp) + sw $t0, -16($fp) + # GOTO label_3 ; + b label_3 + # LABEL label_5 ; + label_5: + + # local_12 = 0 ; + li $t0, 0 + sw $t0, -52($fp) + # local_13 = GETATTR self l ; + lw $t0, 4($fp) + lw $t1, 12($t0) + sw $t1, -56($fp) + # RETURN local_13 ; + lw $v0, -56($fp) + addu $sp, $sp, 56 + jr $ra +Main_main: + move $fp, $sp + subu $sp, $sp, 52 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -8($fp) + # local_2 = VCALL local_0 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -32($fp) + # local_8 = VCALL local_7 in_int ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -32($fp) + ulw $t1, 24($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_9 = VCALL local_6 iota ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_8 ; + lw $t0, -36($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 80($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -40($fp) + # local_5 = GETTYPEADDR local_9 ; + lw $t1, -40($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_10 = VCALL local_5 rev ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_9 ; + lw $t0, -40($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -24($fp) + ulw $t1, 56($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -44($fp) + # local_4 = GETTYPEADDR local_10 ; + lw $t1, -44($fp) + lw $t0, 8($t1) + sw $t0, -20($fp) + # local_11 = VCALL local_4 sort ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -20($fp) + ulw $t1, 60($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_3 = GETTYPEADDR local_11 ; + lw $t1, -48($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_12 = VCALL local_3 print_list ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 72($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # RETURN local_12 ; + lw $v0, -52($fp) + addu $sp, $sp, 52 + jr $ra + +.data + data_1: + .asciiz "Main" + data_2: + .asciiz "Cons" + data_3: .asciiz "Int" + data_4: + .asciiz "List" + data_5: + .asciiz "\n" data_6: + .asciiz "Nil" + data_7: + .asciiz "How many numbers to sort? " + data_8: + .asciiz "Bool" + data_9: .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: .asciiz "\n" vt_Object: - .space 36 + .space 360 vt_IO: - .space 36 + .space 360 vt_Int: - .space 36 + .space 360 vt_String: - .space 36 + .space 360 vt_Bool: - .space 36 + .space 360 + vt_List: + .space 360 + vt_Cons: + .space 360 + vt_Nil: + .space 360 vt_Main: - .space 36 + .space 360 str: .space 1024 concat_result: diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 042806de..7aeea52f 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -16,7 +16,7 @@ def init_types(types): for i, t in enumerate(types): t.code_mips = i t.size_mips = (len(t.attributes) + 2) * 4 - size_vt = max(size_vt, (len(t.methods) + 1) * 4) + size_vt +=(len(t.methods) + 1) * 4 t.attr_index_mips = {} for i, a in enumerate(t.attributes): t.attr_index_mips[a] = i + 1 From 6f7cc4631a19a982a9964850209e978557085e4a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 22:01:15 -0500 Subject: [PATCH 414/435] fixing concat --- src/code_generation/CIL/ast.py | 16 + src/code_generation/CIL/cil.py | 18 +- src/code_generation/MIPS/mips.py | 108 +- src/code_generation/MIPS/test.asm | 2391 +++++++++++++++++------------ 4 files changed, 1550 insertions(+), 983 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 68dc73db..407c2bac 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -156,7 +156,23 @@ def __str__(self): class LessNode(ArithNode): def __str__(self): return f'{self.result} = {self.left} < {self.right} ;' + +class EqNode(ArithNode): + def __str__(self): + return f'{self.result} = {self.left} == {self.right} ;' + +class EqStringNode(ArithNode): + def __str__(self): + return f'{self.result} = {self.left} == {self.right} ;' +class NotEqNode(ArithNode): + def __str__(self): + return f'{self.result} = {self.left} != {self.right} ;' + +class NotEqInstanceNode(ArithNode): + def __str__(self): + return f'{self.result} = {self.left} != {self.right} ;' + class NotNode(InstructionNode): def __init__(self, value, result): diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 1e27b95d..72ce9a56 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -294,7 +294,7 @@ def case_to_cil_visitor(case): for i, branch in enumerate(case.case_list): predicate = add_local() - body.append(CilAST.MinusNode(t, branch.type, predicate)) + body.append(CilAST.NotEqInstanceNode(t, branch.type, predicate)) body.append(CilAST.ConditionalGotoNode(predicate, labels[i])) val = add_local(branch.id) body.append(CilAST.AssignNode(val, expr_cil.value)) @@ -386,14 +386,20 @@ def equal_to_cil_visitor(equal): l = expression_to_cil_visitor(equal.lvalue) r = expression_to_cil_visitor(equal.rvalue) + ret_l=equal.lvalue.returned_type.name + ret_r=equal.rvalue.returned_type.name + cil_result = add_local() - end_label = add_label() value = add_local() - body = l.body + r.body + [CilAST.MinusNode(l.value, r.value, cil_result), CilAST.AssignNode(value, 0), - CilAST.ConditionalGotoNode( - cil_result, end_label), CilAST.AssignNode(value, 1), - CilAST.LabelNode(end_label)] + if ret_l == 'String' and ret_r=='String': + comparison=CilAST.EqStringNode(l.value, r.value, cil_result) + else: + comparison=CilAST.EqNode(l.value, r.value, cil_result) + + + + body = l.body + r.body + [comparison, CilAST.AssignNode(value, cil_result)] return CIL_block(body, value) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index f56080f2..87938977 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -237,11 +237,12 @@ def length_to_mips_visitor(length: cil.LengthNode): code = [ mips.Comment(str(length)), - mips.LbInstruction('$t0', f'{val}($fp)'), + mips.LwInstruction('$t2', f'{val}($fp)'), mips.LiInstruction('$t1', 0), mips.MIPSLabel('length_loop'), + mips.LbInstruction('$t0', '($t2)'), mips.BeqzInstruction('$t0', 'end_length_loop'), - mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t2', '$t2', 1), mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('length_loop'), mips.MIPSLabel('end_length_loop'), @@ -251,15 +252,15 @@ def length_to_mips_visitor(length: cil.LengthNode): def concat_to_mips_visitor(concat: cil.ConcatNode): - __DATA__.append(mips.MIPSDataItem(concat.result.id, + __DATA__.append(mips.MIPSDataItem(str(concat.result), mips.SpaceInst(2 * __BUFFSIZE__))) - result_offset = CURRENT_FUNCTION.offset[concat.result.id] + result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] b_offset = CURRENT_FUNCTION.offset[str(concat.str_b)] return [ mips.Comment(str(concat)), - mips.LwInstruction('$t0', f'{result_offset}($fp)'), + mips.LaInstruction('$t0', str(concat.result)), mips.LwInstruction('$t1', f'{a_offset}($fp)'), mips.LwInstruction('$t2', f'{b_offset}($fp)'), mips.MIPSLabel('concat_loop_a'), @@ -276,7 +277,9 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t0', '$t0', 1), mips.AdduInstruction('$t2', '$t2', 1), mips.BInstruction('concat_loop_b'), - mips.MIPSLabel('end_concat') + mips.MIPSLabel('end_concat'), + mips.LaInstruction('$t0', str(concat.result)), + mips.SwInstruction('$t0', f'{result_offset}($fp)') ] @@ -502,6 +505,93 @@ def div_to_mips_visitor(div: cil.DivNode): z_addr = CURRENT_FUNCTION.offset[str(div.result)] return code + [mips.DivInstruction('$t0', '$t0', '$t1'), mips.SwInstruction('$t0', f'{z_addr}($fp)')] +def eq_to_mips_visitor(eq:cil.EqNode): + instructions = [mips.Comment(str(eq))] + if isinstance(eq.left, int): + instructions.append(mips.LiInstruction('$t0', eq.left)) + else: + y_offset = CURRENT_FUNCTION.offset[str(eq.left)] + instructions.append(mips.LwInstruction('$t0', f'{y_offset}($fp)')) + + if isinstance(eq.right, int): + instructions.append(mips.LiInstruction('$t1', eq.right)) + else: + z_offset = CURRENT_FUNCTION.offset[str(eq.right)] + instructions.append(mips.LwInstruction('$t1', f'{z_offset}($fp)')) + + x_offset = CURRENT_FUNCTION.offset[str(eq.result)] + + return instructions + [ + mips.SeqInstruction('$t0', '$t0', '$t1'), + mips.SwInstruction('$t0', f'{x_offset}($fp)') + ] + +__EQUAL__=0 + +def eq_string_to_mips_visitor(eq:cil.EqNode): + global __EQUAL__ + y_offset = CURRENT_FUNCTION.offset[str(eq.left)] + z_offset = CURRENT_FUNCTION.offset[str(eq.right)] + x_offset = CURRENT_FUNCTION.offset[str(eq.result)] + __EQUAL__+=1 + return [ + mips.Comment(str(eq)), + mips.LwInstruction('$t0', f'{y_offset}($fp)'), + mips.LwInstruction('$t1', f'{z_offset}($fp)'), + mips.LiInstruction('$v0', 1), + mips.SwInstruction('$v0', f'{x_offset}($fp)'), + mips.MIPSLabel(f'equal_loop_{__EQUAL__}'), + mips.LbInstruction('$t2', '($t0)'), + mips.LbInstruction('$t3', '($t1)'), + mips.SeqInstruction('$t4', '$t2', '$t3'), + mips.BeqzInstruction('$t4', f'not_equal_{__EQUAL__}'), + mips.BeqzInstruction('$t2', f'end_loop_{__EQUAL__}'), + mips.AdduInstruction('$t0','$t0', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction(f'equal_loop_{__EQUAL__}'), + mips.BInstruction(f'end_loop_{__EQUAL__}'), + mips.MIPSLabel(f'not_equal_{__EQUAL__}'), + mips.LiInstruction('$v0', 0), + mips.SwInstruction('$v0', f'{x_offset}($fp)'), + mips.MIPSLabel(f'end_loop_{__EQUAL__}') + ] + + +def not_eq_to_mips_visitor(eq:cil.EqNode): + instructions = [mips.Comment(str(eq))] + if isinstance(eq.left, int): + instructions.append(mips.LiInstruction('$t0', eq.left)) + else: + y_offset = CURRENT_FUNCTION.offset[str(eq.left)] + instructions.append(mips.LwInstruction('$t0', f'{y_offset}($fp)')) + + if isinstance(eq.right, int): + instructions.append(mips.LiInstruction('$t1', eq.right)) + else: + z_offset = CURRENT_FUNCTION.offset[str(eq.right)] + instructions.append(mips.LwInstruction('$t1', f'{z_offset}($fp)')) + + x_offset = CURRENT_FUNCTION.offset[str(eq.result)] + + return instructions + [ + mips.SneInstruction('$t0', '$t0', '$t1'), + mips.SwInstruction('$t0', f'{x_offset}($fp)') + ] + +def not_eq_instance_to_mips_visitor(noteq:cil.NotEqNode): + y_offset = CURRENT_FUNCTION.offset[str(eq.left)] + z_offset = CURRENT_FUNCTION.offset[str(eq.right)] + x_offset = CURRENT_FUNCTION.offset[str(eq.result)] + + return [ + mips.Comment(str(eq)), + mips.LwInstruction('$t0', f'{y_offset}($fp)'), + mips.LwInstruction('$t1', '($t0)'), + mips.LwInstruction('$t0', f'{z_offset}($fp)'), + mips.LwInstruction('$t2', '($t0)'), + mips.SneInstruction('$t0', '$t1', '$t2'), + mips.SwInstruction('$t0', f'{x_offset}($fp)') + ] def lesseq_to_mips_visitor(lesseq: cil.LessEqNode): """ @@ -781,5 +871,9 @@ def abort_to_mips_visitor(abort: cil.AbortNode): cil.AssignNode: assign_to_mips_visitor, cil.TypeOfNode: type_of_to_mips_visitor, cil.AbortNode: abort_to_mips_visitor, - cil.GetTypeAddrNode: get_type_addr_to_mips_visitor + cil.GetTypeAddrNode: get_type_addr_to_mips_visitor, + cil.EqNode: eq_to_mips_visitor, + cil.NotEqNode:not_eq_to_mips_visitor, + cil.NotEqInstanceNode:not_eq_instance_to_mips_visitor, + cil.EqStringNode:eq_string_to_mips_visitor } diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index b9e471a7..c5325d59 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -48,103 +48,23 @@ main: la $t0, Object_copy usw $t0, vt_Bool+8 la $t0, Object_abort - usw $t0, vt_List+0 + usw $t0, vt_A2I+0 la $t0, Object_type_name - usw $t0, vt_List+4 + usw $t0, vt_A2I+4 la $t0, Object_copy - usw $t0, vt_List+8 - la $t0, IO_out_string - usw $t0, vt_List+12 - la $t0, IO_out_int - usw $t0, vt_List+16 - la $t0, IO_in_string - usw $t0, vt_List+20 - la $t0, IO_in_int - usw $t0, vt_List+24 - la $t0, List_isNil - usw $t0, vt_List+40 - la $t0, List_cons - usw $t0, vt_List+44 - la $t0, List_car - usw $t0, vt_List+48 - la $t0, List_cdr - usw $t0, vt_List+52 - la $t0, List_rev - usw $t0, vt_List+56 - la $t0, List_sort - usw $t0, vt_List+60 - la $t0, List_insert - usw $t0, vt_List+64 - la $t0, List_rcons - usw $t0, vt_List+68 - la $t0, List_print_list - usw $t0, vt_List+72 - la $t0, Object_abort - usw $t0, vt_Cons+0 - la $t0, Object_type_name - usw $t0, vt_Cons+4 - la $t0, Object_copy - usw $t0, vt_Cons+8 - la $t0, IO_out_string - usw $t0, vt_Cons+12 - la $t0, IO_out_int - usw $t0, vt_Cons+16 - la $t0, IO_in_string - usw $t0, vt_Cons+20 - la $t0, IO_in_int - usw $t0, vt_Cons+24 - la $t0, Cons_isNil - usw $t0, vt_Cons+40 - la $t0, List_cons - usw $t0, vt_Cons+44 - la $t0, Cons_car - usw $t0, vt_Cons+48 - la $t0, Cons_cdr - usw $t0, vt_Cons+52 - la $t0, Cons_rev - usw $t0, vt_Cons+56 - la $t0, Cons_sort - usw $t0, vt_Cons+60 - la $t0, Cons_insert - usw $t0, vt_Cons+64 - la $t0, Cons_rcons - usw $t0, vt_Cons+68 - la $t0, Cons_print_list - usw $t0, vt_Cons+72 - la $t0, Cons_init - usw $t0, vt_Cons+76 - la $t0, Object_abort - usw $t0, vt_Nil+0 - la $t0, Object_type_name - usw $t0, vt_Nil+4 - la $t0, Object_copy - usw $t0, vt_Nil+8 - la $t0, IO_out_string - usw $t0, vt_Nil+12 - la $t0, IO_out_int - usw $t0, vt_Nil+16 - la $t0, IO_in_string - usw $t0, vt_Nil+20 - la $t0, IO_in_int - usw $t0, vt_Nil+24 - la $t0, Nil_isNil - usw $t0, vt_Nil+40 - la $t0, List_cons - usw $t0, vt_Nil+44 - la $t0, List_car - usw $t0, vt_Nil+48 - la $t0, List_cdr - usw $t0, vt_Nil+52 - la $t0, Nil_rev - usw $t0, vt_Nil+56 - la $t0, Nil_sort - usw $t0, vt_Nil+60 - la $t0, Nil_insert - usw $t0, vt_Nil+64 - la $t0, Nil_rcons - usw $t0, vt_Nil+68 - la $t0, Nil_print_list - usw $t0, vt_Nil+72 + usw $t0, vt_A2I+8 + la $t0, A2I_c2i + usw $t0, vt_A2I+40 + la $t0, A2I_i2c + usw $t0, vt_A2I+44 + la $t0, A2I_a2i + usw $t0, vt_A2I+48 + la $t0, A2I_a2i_aux + usw $t0, vt_A2I+52 + la $t0, A2I_i2a + usw $t0, vt_A2I+56 + la $t0, A2I_i2a_aux + usw $t0, vt_A2I+60 la $t0, Object_abort usw $t0, vt_Main+0 la $t0, Object_type_name @@ -159,12 +79,10 @@ main: usw $t0, vt_Main+20 la $t0, IO_in_int usw $t0, vt_Main+24 - la $t0, Main_iota - usw $t0, vt_Main+80 la $t0, Main_main - usw $t0, vt_Main+84 + usw $t0, vt_Main+64 # self = ALLOCATE Main ; - li $a0, 16 + li $a0, 12 li $v0, 9 syscall sw $v0, -4($fp) @@ -177,8 +95,8 @@ main: lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 0($t1) - # local_2 = 16 ; - li $t0, 16 + # local_2 = 12 ; + li $t0, 12 sw $t0, -12($fp) # SETATTR self @size local_2 ; lw $t0, -12($fp) @@ -288,12 +206,13 @@ String_length: move $fp, $sp subu $sp, $sp, 4 # len_result = LENGTH self ; - lb $t0, 0($fp) + lw $t2, 0($fp) li $t1, 0 length_loop: + lb $t0, ($t2) beqz $t0, end_length_loop - addu $t0, $t0, 1 + addu $t2, $t2, 1 addu $t1, $t1, 1 b length_loop end_length_loop: @@ -307,7 +226,7 @@ String_concat: move $fp, $sp subu $sp, $sp, 4 # concat_result = CONCAT self x ; - lw $t0, -4($fp) + la $t0, concat_result lw $t1, 4($fp) lw $t2, 0($fp) concat_loop_a: @@ -328,6 +247,8 @@ String_concat: b concat_loop_b end_concat: + la $t0, concat_result + sw $t0, -4($fp) # RETURN concat_result ; lw $v0, -4($fp) addu $sp, $sp, 4 @@ -421,277 +342,959 @@ Bool_abort: Bool_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_13 = LOAD data_8 ; - la $t0, data_8 + # local_23 = LOAD data_19 ; + la $t0, data_19 sw $t0, -4($fp) - # RETURN local_13 ; + # RETURN local_23 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra Int_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_14 = LOAD data_3 ; - la $t0, data_3 + # local_24 = LOAD data_20 ; + la $t0, data_20 sw $t0, -4($fp) - # RETURN local_14 ; + # RETURN local_24 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra String_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_15 = LOAD data_9 ; - la $t0, data_9 + # local_25 = LOAD data_21 ; + la $t0, data_21 sw $t0, -4($fp) - # RETURN local_15 ; + # RETURN local_25 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra -List_isNil: +A2I_c2i: move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) + subu $sp, $sp, 168 + # local_0 = LOAD data_2 ; + la $t0, data_2 sw $t0, -4($fp) - # local_1 = VCALL local_0 abort ; + # local_1 = char == local_0 ; + lw $t0, 0($fp) + lw $t1, -4($fp) + li $v0, 1 + sw $v0, -8($fp) + equal_loop_1: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_1 + beqz $t2, end_loop_1 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_1 + b end_loop_1 + not_equal_1: + + li $v0, 0 + sw $v0, -8($fp) + end_loop_1: + + # local_2 = local_1 ; + lw $t0, -8($fp) + sw $t0, -12($fp) + # IF local_2 GOTO label_19 ; + lw $t0, -12($fp) + bnez $t0, label_19 + # local_3 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -16($fp) + # local_4 = char == local_3 ; + lw $t0, 0($fp) + lw $t1, -16($fp) + li $v0, 1 + sw $v0, -20($fp) + equal_loop_2: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_2 + beqz $t2, end_loop_2 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_2 + b end_loop_2 + not_equal_2: + + li $v0, 0 + sw $v0, -20($fp) + end_loop_2: + + # local_5 = local_4 ; + lw $t0, -20($fp) + sw $t0, -24($fp) + # IF local_5 GOTO label_17 ; + lw $t0, -24($fp) + bnez $t0, label_17 + # local_6 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -28($fp) + # local_7 = char == local_6 ; + lw $t0, 0($fp) + lw $t1, -28($fp) + li $v0, 1 + sw $v0, -32($fp) + equal_loop_3: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_3 + beqz $t2, end_loop_3 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_3 + b end_loop_3 + not_equal_3: + + li $v0, 0 + sw $v0, -32($fp) + end_loop_3: + + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_15 ; + lw $t0, -36($fp) + bnez $t0, label_15 + # local_9 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -40($fp) + # local_10 = char == local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + li $v0, 1 + sw $v0, -44($fp) + equal_loop_4: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_4 + beqz $t2, end_loop_4 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_4 + b end_loop_4 + not_equal_4: + + li $v0, 0 + sw $v0, -44($fp) + end_loop_4: + + # local_11 = local_10 ; + lw $t0, -44($fp) + sw $t0, -48($fp) + # IF local_11 GOTO label_13 ; + lw $t0, -48($fp) + bnez $t0, label_13 + # local_12 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -52($fp) + # local_13 = char == local_12 ; + lw $t0, 0($fp) + lw $t1, -52($fp) + li $v0, 1 + sw $v0, -56($fp) + equal_loop_5: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_5 + beqz $t2, end_loop_5 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_5 + b end_loop_5 + not_equal_5: + + li $v0, 0 + sw $v0, -56($fp) + end_loop_5: + + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # IF local_14 GOTO label_11 ; + lw $t0, -60($fp) + bnez $t0, label_11 + # local_15 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -64($fp) + # local_16 = char == local_15 ; + lw $t0, 0($fp) + lw $t1, -64($fp) + li $v0, 1 + sw $v0, -68($fp) + equal_loop_6: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_6 + beqz $t2, end_loop_6 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_6 + b end_loop_6 + not_equal_6: + + li $v0, 0 + sw $v0, -68($fp) + end_loop_6: + + # local_17 = local_16 ; + lw $t0, -68($fp) + sw $t0, -72($fp) + # IF local_17 GOTO label_9 ; + lw $t0, -72($fp) + bnez $t0, label_9 + # local_18 = LOAD data_8 ; + la $t0, data_8 + sw $t0, -76($fp) + # local_19 = char == local_18 ; + lw $t0, 0($fp) + lw $t1, -76($fp) + li $v0, 1 + sw $v0, -80($fp) + equal_loop_7: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_7 + beqz $t2, end_loop_7 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_7 + b end_loop_7 + not_equal_7: + + li $v0, 0 + sw $v0, -80($fp) + end_loop_7: + + # local_20 = local_19 ; + lw $t0, -80($fp) + sw $t0, -84($fp) + # IF local_20 GOTO label_7 ; + lw $t0, -84($fp) + bnez $t0, label_7 + # local_21 = LOAD data_9 ; + la $t0, data_9 + sw $t0, -88($fp) + # local_22 = char == local_21 ; + lw $t0, 0($fp) + lw $t1, -88($fp) + li $v0, 1 + sw $v0, -92($fp) + equal_loop_8: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_8 + beqz $t2, end_loop_8 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_8 + b end_loop_8 + not_equal_8: + + li $v0, 0 + sw $v0, -92($fp) + end_loop_8: + + # local_23 = local_22 ; + lw $t0, -92($fp) + sw $t0, -96($fp) + # IF local_23 GOTO label_5 ; + lw $t0, -96($fp) + bnez $t0, label_5 + # local_24 = LOAD data_10 ; + la $t0, data_10 + sw $t0, -100($fp) + # local_25 = char == local_24 ; + lw $t0, 0($fp) + lw $t1, -100($fp) + li $v0, 1 + sw $v0, -104($fp) + equal_loop_9: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_9 + beqz $t2, end_loop_9 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_9 + b end_loop_9 + not_equal_9: + + li $v0, 0 + sw $v0, -104($fp) + end_loop_9: + + # local_26 = local_25 ; + lw $t0, -104($fp) + sw $t0, -108($fp) + # IF local_26 GOTO label_3 ; + lw $t0, -108($fp) + bnez $t0, label_3 + # local_27 = LOAD data_11 ; + la $t0, data_11 + sw $t0, -112($fp) + # local_28 = char == local_27 ; + lw $t0, 0($fp) + lw $t1, -112($fp) + li $v0, 1 + sw $v0, -116($fp) + equal_loop_10: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_10 + beqz $t2, end_loop_10 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_10 + b end_loop_10 + not_equal_10: + + li $v0, 0 + sw $v0, -116($fp) + end_loop_10: + + # local_29 = local_28 ; + lw $t0, -116($fp) + sw $t0, -120($fp) + # IF local_29 GOTO label_1 ; + lw $t0, -120($fp) + bnez $t0, label_1 + # local_30 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_31 = VCALL local_30 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) # ARG self ; - lw $t0, 0($fp) + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) + lw $t0, -124($fp) ulw $t1, 0($t0) jalr $t1 addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN 1 ; - li $v0, 1 - addu $sp, $sp, 8 + sw $v0, -128($fp) + # local_32 = 0 ; + li $t0, 0 + sw $t0, -132($fp) + # GOTO label_2 ; + b label_2 + # LABEL label_1 ; + label_1: + + # local_32 = 9 ; + li $t0, 9 + sw $t0, -132($fp) + # LABEL label_2 ; + label_2: + + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_4 ; + b label_4 + # LABEL label_3 ; + label_3: + + # local_33 = 8 ; + li $t0, 8 + sw $t0, -136($fp) + # LABEL label_4 ; + label_4: + + # local_34 = local_33 ; + lw $t0, -136($fp) + sw $t0, -140($fp) + # GOTO label_6 ; + b label_6 + # LABEL label_5 ; + label_5: + + # local_34 = 7 ; + li $t0, 7 + sw $t0, -140($fp) + # LABEL label_6 ; + label_6: + + # local_35 = local_34 ; + lw $t0, -140($fp) + sw $t0, -144($fp) + # GOTO label_8 ; + b label_8 + # LABEL label_7 ; + label_7: + + # local_35 = 6 ; + li $t0, 6 + sw $t0, -144($fp) + # LABEL label_8 ; + label_8: + + # local_36 = local_35 ; + lw $t0, -144($fp) + sw $t0, -148($fp) + # GOTO label_10 ; + b label_10 + # LABEL label_9 ; + label_9: + + # local_36 = 5 ; + li $t0, 5 + sw $t0, -148($fp) + # LABEL label_10 ; + label_10: + + # local_37 = local_36 ; + lw $t0, -148($fp) + sw $t0, -152($fp) + # GOTO label_12 ; + b label_12 + # LABEL label_11 ; + label_11: + + # local_37 = 4 ; + li $t0, 4 + sw $t0, -152($fp) + # LABEL label_12 ; + label_12: + + # local_38 = local_37 ; + lw $t0, -152($fp) + sw $t0, -156($fp) + # GOTO label_14 ; + b label_14 + # LABEL label_13 ; + label_13: + + # local_38 = 3 ; + li $t0, 3 + sw $t0, -156($fp) + # LABEL label_14 ; + label_14: + + # local_39 = local_38 ; + lw $t0, -156($fp) + sw $t0, -160($fp) + # GOTO label_16 ; + b label_16 + # LABEL label_15 ; + label_15: + + # local_39 = 2 ; + li $t0, 2 + sw $t0, -160($fp) + # LABEL label_16 ; + label_16: + + # local_40 = local_39 ; + lw $t0, -160($fp) + sw $t0, -164($fp) + # GOTO label_18 ; + b label_18 + # LABEL label_17 ; + label_17: + + # local_40 = 1 ; + li $t0, 1 + sw $t0, -164($fp) + # LABEL label_18 ; + label_18: + + # local_41 = local_40 ; + lw $t0, -164($fp) + sw $t0, -168($fp) + # GOTO label_20 ; + b label_20 + # LABEL label_19 ; + label_19: + + # local_41 = 0 ; + li $t0, 0 + sw $t0, -168($fp) + # LABEL label_20 ; + label_20: + + # RETURN local_41 ; + lw $v0, -168($fp) + addu $sp, $sp, 168 jr $ra -List_cons: +A2I_i2c: move $fp, $sp - subu $sp, $sp, 24 - # local_0 = ALLOCATE Cons ; - li $a0, 20 - li $v0, 9 - syscall - sw $v0, -4($fp) - la $t0, vt_Cons - sw $t0, 8($v0) - # local_1 = LOAD data_2 ; - la $t0, data_2 + subu $sp, $sp, 172 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; + # IF local_1 GOTO label_39 ; lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 0($t1) - # local_2 = 20 ; - li $t0, 20 - sw $t0, -12($fp) - # SETATTR local_0 @size local_2 ; - lw $t0, -12($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # new_cell = local_0 ; - lw $t0, -4($fp) + bnez $t0, label_39 + # local_3 = i == 1 ; + lw $t0, 0($fp) + li $t1, 1 + seq $t0, $t0, $t1 sw $t0, -16($fp) - # local_4 = GETTYPEADDR new_cell ; - lw $t1, -16($fp) - lw $t0, 8($t1) + # local_4 = local_3 ; + lw $t0, -16($fp) sw $t0, -20($fp) - # local_5 = VCALL local_4 init ; + # IF local_4 GOTO label_37 ; + lw $t0, -20($fp) + bnez $t0, label_37 + # local_6 = i == 2 ; + lw $t0, 0($fp) + li $t1, 2 + seq $t0, $t0, $t1 + sw $t0, -28($fp) + # local_7 = local_6 ; + lw $t0, -28($fp) + sw $t0, -32($fp) + # IF local_7 GOTO label_35 ; + lw $t0, -32($fp) + bnez $t0, label_35 + # local_9 = i == 3 ; + lw $t0, 0($fp) + li $t1, 3 + seq $t0, $t0, $t1 + sw $t0, -40($fp) + # local_10 = local_9 ; + lw $t0, -40($fp) + sw $t0, -44($fp) + # IF local_10 GOTO label_33 ; + lw $t0, -44($fp) + bnez $t0, label_33 + # local_12 = i == 4 ; + lw $t0, 0($fp) + li $t1, 4 + seq $t0, $t0, $t1 + sw $t0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # IF local_13 GOTO label_31 ; + lw $t0, -56($fp) + bnez $t0, label_31 + # local_15 = i == 5 ; + lw $t0, 0($fp) + li $t1, 5 + seq $t0, $t0, $t1 + sw $t0, -64($fp) + # local_16 = local_15 ; + lw $t0, -64($fp) + sw $t0, -68($fp) + # IF local_16 GOTO label_29 ; + lw $t0, -68($fp) + bnez $t0, label_29 + # local_18 = i == 6 ; + lw $t0, 0($fp) + li $t1, 6 + seq $t0, $t0, $t1 + sw $t0, -76($fp) + # local_19 = local_18 ; + lw $t0, -76($fp) + sw $t0, -80($fp) + # IF local_19 GOTO label_27 ; + lw $t0, -80($fp) + bnez $t0, label_27 + # local_21 = i == 7 ; + lw $t0, 0($fp) + li $t1, 7 + seq $t0, $t0, $t1 + sw $t0, -88($fp) + # local_22 = local_21 ; + lw $t0, -88($fp) + sw $t0, -92($fp) + # IF local_22 GOTO label_25 ; + lw $t0, -92($fp) + bnez $t0, label_25 + # local_24 = i == 8 ; + lw $t0, 0($fp) + li $t1, 8 + seq $t0, $t0, $t1 + sw $t0, -100($fp) + # local_25 = local_24 ; + lw $t0, -100($fp) + sw $t0, -104($fp) + # IF local_25 GOTO label_23 ; + lw $t0, -104($fp) + bnez $t0, label_23 + # local_27 = i == 9 ; + lw $t0, 0($fp) + li $t1, 9 + seq $t0, $t0, $t1 + sw $t0, -112($fp) + # local_28 = local_27 ; + lw $t0, -112($fp) + sw $t0, -116($fp) + # IF local_28 GOTO label_21 ; + lw $t0, -116($fp) + bnez $t0, label_21 + # local_30 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_31 = VCALL local_30 abort ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG new_cell ; - lw $t0, -16($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG hd ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) # ARG self ; lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -20($fp) - ulw $t1, 76($t0) + lw $t0, -124($fp) + ulw $t1, 0($t0) jalr $t1 - addu $sp, $sp, 12 + addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -24($fp) - # RETURN local_5 ; - lw $v0, -24($fp) - addu $sp, $sp, 24 - jr $ra -List_car: - move $fp, $sp - subu $sp, $sp, 20 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 abort ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 0($t0) - jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -8($fp) - # local_2 = ALLOCATE Int ; - li $a0, 12 - li $v0, 9 - syscall - sw $v0, -12($fp) - la $t0, vt_Int - sw $t0, 8($v0) - # local_3 = LOAD data_3 ; + sw $v0, -128($fp) + # local_32 = LOAD data_12 ; + la $t0, data_12 + sw $t0, -132($fp) + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_22 ; + b label_22 + # LABEL label_21 ; + label_21: + + # local_29 = LOAD data_11 ; + la $t0, data_11 + sw $t0, -120($fp) + # local_33 = local_29 ; + lw $t0, -120($fp) + sw $t0, -136($fp) + # LABEL label_22 ; + label_22: + + # local_34 = local_33 ; + lw $t0, -136($fp) + sw $t0, -140($fp) + # GOTO label_24 ; + b label_24 + # LABEL label_23 ; + label_23: + + # local_26 = LOAD data_10 ; + la $t0, data_10 + sw $t0, -108($fp) + # local_34 = local_26 ; + lw $t0, -108($fp) + sw $t0, -140($fp) + # LABEL label_24 ; + label_24: + + # local_35 = local_34 ; + lw $t0, -140($fp) + sw $t0, -144($fp) + # GOTO label_26 ; + b label_26 + # LABEL label_25 ; + label_25: + + # local_23 = LOAD data_9 ; + la $t0, data_9 + sw $t0, -96($fp) + # local_35 = local_23 ; + lw $t0, -96($fp) + sw $t0, -144($fp) + # LABEL label_26 ; + label_26: + + # local_36 = local_35 ; + lw $t0, -144($fp) + sw $t0, -148($fp) + # GOTO label_28 ; + b label_28 + # LABEL label_27 ; + label_27: + + # local_20 = LOAD data_8 ; + la $t0, data_8 + sw $t0, -84($fp) + # local_36 = local_20 ; + lw $t0, -84($fp) + sw $t0, -148($fp) + # LABEL label_28 ; + label_28: + + # local_37 = local_36 ; + lw $t0, -148($fp) + sw $t0, -152($fp) + # GOTO label_30 ; + b label_30 + # LABEL label_29 ; + label_29: + + # local_17 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -72($fp) + # local_37 = local_17 ; + lw $t0, -72($fp) + sw $t0, -152($fp) + # LABEL label_30 ; + label_30: + + # local_38 = local_37 ; + lw $t0, -152($fp) + sw $t0, -156($fp) + # GOTO label_32 ; + b label_32 + # LABEL label_31 ; + label_31: + + # local_14 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -60($fp) + # local_38 = local_14 ; + lw $t0, -60($fp) + sw $t0, -156($fp) + # LABEL label_32 ; + label_32: + + # local_39 = local_38 ; + lw $t0, -156($fp) + sw $t0, -160($fp) + # GOTO label_34 ; + b label_34 + # LABEL label_33 ; + label_33: + + # local_11 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -48($fp) + # local_39 = local_11 ; + lw $t0, -48($fp) + sw $t0, -160($fp) + # LABEL label_34 ; + label_34: + + # local_40 = local_39 ; + lw $t0, -160($fp) + sw $t0, -164($fp) + # GOTO label_36 ; + b label_36 + # LABEL label_35 ; + label_35: + + # local_8 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -36($fp) + # local_40 = local_8 ; + lw $t0, -36($fp) + sw $t0, -164($fp) + # LABEL label_36 ; + label_36: + + # local_41 = local_40 ; + lw $t0, -164($fp) + sw $t0, -168($fp) + # GOTO label_38 ; + b label_38 + # LABEL label_37 ; + label_37: + + # local_5 = LOAD data_3 ; la $t0, data_3 - sw $t0, -16($fp) - # SETATTR local_2 @type local_3 ; - lw $t0, -16($fp) - lw $t1, -12($fp) - sw $t0, 0($t1) - # local_4 = 12 ; - li $t0, 12 - sw $t0, -20($fp) - # SETATTR local_2 @size local_4 ; - lw $t0, -20($fp) - lw $t1, -12($fp) - sw $t0, 4($t1) - # RETURN local_2 ; - lw $v0, -12($fp) - addu $sp, $sp, 20 + sw $t0, -24($fp) + # local_41 = local_5 ; + lw $t0, -24($fp) + sw $t0, -168($fp) + # LABEL label_38 ; + label_38: + + # local_42 = local_41 ; + lw $t0, -168($fp) + sw $t0, -172($fp) + # GOTO label_40 ; + b label_40 + # LABEL label_39 ; + label_39: + + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # local_42 = local_2 ; + lw $t0, -12($fp) + sw $t0, -172($fp) + # LABEL label_40 ; + label_40: + + # RETURN local_42 ; + lw $v0, -172($fp) + addu $sp, $sp, 172 jr $ra -List_cdr: +A2I_a2i: move $fp, $sp - subu $sp, $sp, 20 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 abort ; + subu $sp, $sp, 136 + # local_1 = VCALL String length ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; + # ARG s ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 0($t0) - jalr $t1 + jal String_length addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 sw $v0, -8($fp) - # local_2 = ALLOCATE List ; - li $a0, 12 - li $v0, 9 - syscall - sw $v0, -12($fp) - la $t0, vt_List - sw $t0, 8($v0) - # local_3 = LOAD data_4 ; - la $t0, data_4 + # local_2 = local_1 == 0 ; + lw $t0, -8($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -12($fp) + # local_3 = local_2 ; + lw $t0, -12($fp) sw $t0, -16($fp) - # SETATTR local_2 @type local_3 ; + # IF local_3 GOTO label_45 ; lw $t0, -16($fp) - lw $t1, -12($fp) - sw $t0, 0($t1) - # local_4 = 12 ; - li $t0, 12 - sw $t0, -20($fp) - # SETATTR local_2 @size local_4 ; - lw $t0, -20($fp) - lw $t1, -12($fp) - sw $t0, 4($t1) - # RETURN local_2 ; - lw $v0, -12($fp) - addu $sp, $sp, 20 - jr $ra -List_rev: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 cdr ; + bnez $t0, label_45 + # local_5 = VCALL String substr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; + # ARG s ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 52($t0) - jalr $t1 - addu $sp, $sp, 4 + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) - addu $sp, $sp, 8 - jr $ra -List_sort: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 cdr ; + sw $v0, -24($fp) + # local_6 = LOAD data_13 ; + la $t0, data_13 + sw $t0, -28($fp) + # local_7 = local_5 == local_6 ; + lw $t0, -24($fp) + lw $t1, -28($fp) + li $v0, 1 + sw $v0, -32($fp) + equal_loop_11: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_11 + beqz $t2, end_loop_11 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_11 + b end_loop_11 + not_equal_11: + + li $v0, 0 + sw $v0, -32($fp) + end_loop_11: + + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_43 ; + lw $t0, -36($fp) + bnez $t0, label_43 + # local_18 = VCALL String substr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; + # ARG s ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 52($t0) - jalr $t1 - addu $sp, $sp, 4 + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) - addu $sp, $sp, 8 - jr $ra -List_insert: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; + sw $v0, -76($fp) + # local_19 = LOAD data_14 ; + la $t0, data_14 + sw $t0, -80($fp) + # local_20 = local_18 == local_19 ; + lw $t0, -76($fp) + lw $t1, -80($fp) + li $v0, 1 + sw $v0, -84($fp) + equal_loop_12: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_12 + beqz $t2, end_loop_12 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_12 + b end_loop_12 + not_equal_12: + + li $v0, 0 + sw $v0, -84($fp) + end_loop_12: + + # local_21 = local_20 ; + lw $t0, -84($fp) + sw $t0, -88($fp) + # IF local_21 GOTO label_41 ; + lw $t0, -88($fp) + bnez $t0, label_41 + # local_29 = GETTYPEADDR self ; lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 cdr ; + sw $t0, -120($fp) + # local_30 = VCALL local_29 a2i_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -699,600 +1302,514 @@ List_insert: lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -120($fp) ulw $t1, 52($t0) jalr $t1 - addu $sp, $sp, 4 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) - addu $sp, $sp, 8 - jr $ra -List_rcons: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; + sw $v0, -124($fp) + # local_31 = local_30 ; + lw $t0, -124($fp) + sw $t0, -128($fp) + # GOTO label_42 ; + b label_42 + # LABEL label_41 ; + label_41: + + # local_22 = GETTYPEADDR self ; lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 cdr ; + sw $t0, -92($fp) + # local_25 = VCALL String length ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 52($t0) - jalr $t1 + jal String_length addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) - addu $sp, $sp, 8 - jr $ra -List_print_list: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 abort ; + sw $v0, -104($fp) + # local_26 = local_25 - 1 ; + lw $t0, -104($fp) + li $t1, 1 + sub $t0, $t0, $t1 + sw $t0, -108($fp) + # local_27 = VCALL String substr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; + # ARG s ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 0($t0) - jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) - addu $sp, $sp, 8 - jr $ra -Cons_isNil: - move $fp, $sp - subu $sp, $sp, 0 - # RETURN ; - li $v0, 0 - addu $sp, $sp, 0 - jr $ra -Cons_init: - move $fp, $sp - subu $sp, $sp, 0 - # SETATTR self xcar hd ; - lw $t0, 4($fp) - lw $t1, 8($fp) - sw $t0, 12($t1) - # SETATTR self xcdr tl ; - lw $t0, 0($fp) - lw $t1, 8($fp) - sw $t0, 16($t1) - # RETURN self ; - lw $v0, 8($fp) - addu $sp, $sp, 0 - jr $ra -Cons_car: - move $fp, $sp - subu $sp, $sp, 4 - # local_0 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -4($fp) - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 4 - jr $ra -Cons_cdr: - move $fp, $sp + # ARG 1 ; + li $t0, 1 subu $sp, $sp, 4 - # local_0 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -4($fp) - # RETURN local_0 ; - lw $v0, -4($fp) - addu $sp, $sp, 4 - jr $ra -Cons_rev: - move $fp, $sp - subu $sp, $sp, 24 - # local_2 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -12($fp) - # local_1 = GETTYPEADDR local_2 ; - lw $t1, -12($fp) - lw $t0, 8($t1) - sw $t0, -8($fp) - # local_3 = VCALL local_1 rev ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_2 ; - lw $t0, -12($fp) + sw $t0, ($sp) + # ARG local_26 ; + lw $t0, -108($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -8($fp) - ulw $t1, 56($t0) - jalr $t1 - addu $sp, $sp, 4 + jal String_substr + addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -16($fp) - # local_0 = GETTYPEADDR local_3 ; - lw $t1, -16($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_4 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -20($fp) - # local_5 = VCALL local_0 rcons ; + sw $v0, -112($fp) + # local_28 = VCALL local_22 a2i_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_3 ; - lw $t0, -16($fp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) + # ARG local_27 ; + lw $t0, -112($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 68($t0) + lw $t0, -92($fp) + ulw $t1, 52($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -24($fp) - # RETURN local_5 ; - lw $v0, -24($fp) - addu $sp, $sp, 24 - jr $ra -Cons_sort: - move $fp, $sp - subu $sp, $sp, 24 - # local_2 = GETATTR self xcdr ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -12($fp) - # local_1 = GETTYPEADDR local_2 ; - lw $t1, -12($fp) + sw $v0, -116($fp) + # local_31 = local_28 ; + lw $t0, -116($fp) + sw $t0, -128($fp) + # LABEL label_42 ; + label_42: + + # local_32 = local_31 ; + lw $t0, -128($fp) + sw $t0, -132($fp) + # GOTO label_44 ; + b label_44 + # LABEL label_43 ; + label_43: + + # local_9 = GETTYPEADDR self ; + lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -8($fp) - # local_3 = VCALL local_1 sort ; + sw $t0, -40($fp) + # local_12 = VCALL String length ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_2 ; - lw $t0, -12($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -8($fp) - ulw $t1, 60($t0) - jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -16($fp) - # local_0 = GETTYPEADDR local_3 ; - lw $t1, -16($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_4 = GETATTR self xcar ; + # ARG s ; lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -20($fp) - # local_5 = VCALL local_0 insert ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_3 ; - lw $t0, -16($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 64($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -24($fp) - # RETURN local_5 ; - lw $v0, -24($fp) - addu $sp, $sp, 24 - jr $ra -Cons_insert: - move $fp, $sp - subu $sp, $sp, 68 - # local_0 = GETATTR self xcar ; - lw $t0, 4($fp) - lw $t1, 12($t0) - sw $t1, -4($fp) - # local_1 = i < local_0 ; - lw $t0, 0($fp) - lw $t1, -4($fp) - slt $t0, $t0, $t1 - sw $t0, -8($fp) - # IF local_1 GOTO label_1 ; - lw $t0, -8($fp) - bnez $t0, label_1 - # local_8 = ALLOCATE Cons ; - li $a0, 20 - li $v0, 9 - syscall - sw $v0, -36($fp) - la $t0, vt_Cons - sw $t0, 8($v0) - # local_9 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -40($fp) - # SETATTR local_8 @type local_9 ; - lw $t0, -40($fp) - lw $t1, -36($fp) - sw $t0, 0($t1) - # local_10 = 20 ; - li $t0, 20 - sw $t0, -44($fp) - # SETATTR local_8 @size local_10 ; - lw $t0, -44($fp) - lw $t1, -36($fp) - sw $t0, 4($t1) - # local_7 = GETTYPEADDR local_8 ; - lw $t1, -36($fp) - lw $t0, 8($t1) - sw $t0, -32($fp) - # local_11 = GETATTR self xcar ; - lw $t0, 4($fp) - lw $t1, 12($t0) - sw $t1, -48($fp) - # local_13 = GETATTR self xcdr ; - lw $t0, 4($fp) - lw $t1, 16($t0) - sw $t1, -56($fp) - # local_12 = GETTYPEADDR local_13 ; - lw $t1, -56($fp) - lw $t0, 8($t1) - sw $t0, -52($fp) - # local_14 = VCALL local_12 insert ; + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = local_12 - 1 ; + lw $t0, -52($fp) + li $t1, 1 + sub $t0, $t0, $t1 + sw $t0, -56($fp) + # local_14 = VCALL String substr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_13 ; - lw $t0, -56($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG i ; - lw $t0, 0($fp) + # ARG 1 ; + li $t0, 1 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -52($fp) - ulw $t1, 64($t0) - jalr $t1 - addu $sp, $sp, 8 + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 sw $v0, -60($fp) - # local_15 = VCALL local_7 init ; + # local_15 = VCALL local_9 a2i_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_8 ; - lw $t0, -36($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_11 ; - lw $t0, -48($fp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) # ARG local_14 ; lw $t0, -60($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -32($fp) - ulw $t1, 76($t0) + lw $t0, -40($fp) + ulw $t1, 52($t0) jalr $t1 - addu $sp, $sp, 12 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 sw $v0, -64($fp) - # local_16 = local_15 ; - lw $t0, -64($fp) + # local_16 = ~ local_15 + not $t0, $t0 sw $t0, -68($fp) - # GOTO label_2 ; - b label_2 - # LABEL label_1 ; - label_1: + # local_32 = local_16 ; + lw $t0, -68($fp) + sw $t0, -132($fp) + # LABEL label_44 ; + label_44: - # local_3 = ALLOCATE Cons ; - li $a0, 20 - li $v0, 9 - syscall - sw $v0, -16($fp) - la $t0, vt_Cons - sw $t0, 8($v0) - # local_4 = LOAD data_2 ; - la $t0, data_2 + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_46 ; + b label_46 + # LABEL label_45 ; + label_45: + + # local_33 = 0 ; + li $t0, 0 + sw $t0, -136($fp) + # LABEL label_46 ; + label_46: + + # RETURN local_33 ; + lw $v0, -136($fp) + addu $sp, $sp, 136 + jr $ra +A2I_a2i_aux: + move $fp, $sp + subu $sp, $sp, 56 + # int = 0 ; + li $t0, 0 + sw $t0, -4($fp) + # local_2 = VCALL String length ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # j = local_2 ; + lw $t0, -12($fp) + sw $t0, -16($fp) + # i = 0 ; + li $t0, 0 sw $t0, -20($fp) - # SETATTR local_3 @type local_4 ; + # LABEL label_47 ; + label_47: + + # local_5 = i < j ; lw $t0, -20($fp) lw $t1, -16($fp) - sw $t0, 0($t1) - # local_5 = 20 ; - li $t0, 20 + slt $t0, $t0, $t1 sw $t0, -24($fp) - # SETATTR local_3 @size local_5 ; + # IF local_5 GOTO label_48 ; lw $t0, -24($fp) - lw $t1, -16($fp) - sw $t0, 4($t1) - # local_2 = GETTYPEADDR local_3 ; - lw $t1, -16($fp) + bnez $t0, label_48 + # GOTO label_49 ; + b label_49 + # LABEL label_48 ; + label_48: + + # local_6 = int * 10 ; + lw $t0, -4($fp) + li $t1, 10 + mul $t0, $t0, $t1 + sw $t0, -28($fp) + # local_7 = GETTYPEADDR self ; + lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -12($fp) - # local_6 = VCALL local_2 init ; + sw $t0, -32($fp) + # local_9 = VCALL String substr ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_3 ; - lw $t0, -16($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) # ARG i ; - lw $t0, 0($fp) + lw $t0, -20($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG self ; - lw $t0, 4($fp) + # ARG 1 ; + li $t0, 1 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -12($fp) - ulw $t1, 76($t0) - jalr $t1 + jal String_substr addu $sp, $sp, 12 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -28($fp) - # local_16 = local_6 ; - lw $t0, -28($fp) - sw $t0, -68($fp) - # LABEL label_2 ; - label_2: - - # RETURN local_16 ; - lw $v0, -68($fp) - addu $sp, $sp, 68 - jr $ra -Cons_rcons: - move $fp, $sp - subu $sp, $sp, 36 - # local_1 = ALLOCATE Cons ; - li $a0, 20 - li $v0, 9 - syscall - sw $v0, -8($fp) - la $t0, vt_Cons - sw $t0, 8($v0) - # local_2 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -12($fp) - # SETATTR local_1 @type local_2 ; - lw $t0, -12($fp) - lw $t1, -8($fp) - sw $t0, 0($t1) - # local_3 = 20 ; - li $t0, 20 - sw $t0, -16($fp) - # SETATTR local_1 @size local_3 ; - lw $t0, -16($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # local_0 = GETTYPEADDR local_1 ; - lw $t1, -8($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_4 = GETATTR self xcar ; - lw $t0, 4($fp) - lw $t1, 12($t0) - sw $t1, -20($fp) - # local_6 = GETATTR self xcdr ; - lw $t0, 4($fp) - lw $t1, 16($t0) - sw $t1, -28($fp) - # local_5 = GETTYPEADDR local_6 ; - lw $t1, -28($fp) - lw $t0, 8($t1) - sw $t0, -24($fp) - # local_7 = VCALL local_5 rcons ; + sw $v0, -40($fp) + # local_10 = VCALL local_7 c2i ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_6 ; - lw $t0, -28($fp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG i ; - lw $t0, 0($fp) + # ARG local_9 ; + lw $t0, -40($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -24($fp) - ulw $t1, 68($t0) + lw $t0, -32($fp) + ulw $t1, 40($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -32($fp) - # local_8 = VCALL local_0 init ; + sw $v0, -44($fp) + # local_11 = local_6 + local_10 ; + lw $t0, -28($fp) + lw $t1, -44($fp) + add $t0, $t0, $t1 + sw $t0, -48($fp) + # int = local_11 ; + lw $t0, -48($fp) + sw $t0, -4($fp) + # local_12 = i + 1 ; + lw $t0, -20($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -52($fp) + # i = local_12 ; + lw $t0, -52($fp) + sw $t0, -20($fp) + # GOTO label_47 ; + b label_47 + # LABEL label_49 ; + label_49: + + # local_13 = 0 ; + li $t0, 0 + sw $t0, -56($fp) + # RETURN int ; + lw $v0, -4($fp) + addu $sp, $sp, 56 + jr $ra +A2I_i2a: + move $fp, $sp + subu $sp, $sp, 60 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # IF local_1 GOTO label_52 ; + lw $t0, -8($fp) + bnez $t0, label_52 + # local_3 = 0 < i ; + li $t0, 0 + lw $t1, 0($fp) + slt $t0, $t0, $t1 + sw $t0, -16($fp) + # IF local_3 GOTO label_50 ; + lw $t0, -16($fp) + bnez $t0, label_50 + # local_7 = LOAD data_13 ; + la $t0, data_13 + sw $t0, -32($fp) + # local_8 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -36($fp) + # local_9 = ~ 1 + li $t0, 1 + not $t0, $t0 + sw $t0, -40($fp) + # local_10 = i * local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + mul $t0, $t0, $t1 + sw $t0, -44($fp) + # local_11 = VCALL local_8 i2a_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) + # ARG self ; + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_7 ; - lw $t0, -32($fp) + # ARG local_10 ; + lw $t0, -44($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 76($t0) + lw $t0, -36($fp) + ulw $t1, 60($t0) jalr $t1 - addu $sp, $sp, 12 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -36($fp) - # RETURN local_8 ; - lw $v0, -36($fp) - addu $sp, $sp, 36 - jr $ra -Cons_print_list: - move $fp, $sp - subu $sp, $sp, 36 - # local_0 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = GETATTR self xcar ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -8($fp) - # local_2 = VCALL local_0 out_int ; + sw $v0, -48($fp) + # local_12 = VCALL String concat ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG self ; - lw $t0, 0($fp) + # ARG local_7 ; + lw $t0, -32($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_1 ; - lw $t0, -8($fp) + # ARG local_11 ; + lw $t0, -48($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 16($t0) - jalr $t1 + jal String_concat addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -12($fp) - # local_3 = GETTYPEADDR self ; - lw $t1, 0($fp) + sw $v0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # GOTO label_51 ; + b label_51 + # LABEL label_50 ; + label_50: + + # local_4 = GETTYPEADDR self ; + lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -16($fp) - # local_4 = LOAD data_5 ; - la $t0, data_5 sw $t0, -20($fp) - # local_5 = VCALL local_3 out_string ; + # local_5 = VCALL local_4 i2a_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) # ARG self ; - lw $t0, 0($fp) + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) + # ARG i ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -16($fp) - ulw $t1, 12($t0) + lw $t0, -20($fp) + ulw $t1, 60($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 sw $v0, -24($fp) - # local_7 = GETATTR self xcdr ; + # local_13 = local_5 ; + lw $t0, -24($fp) + sw $t0, -56($fp) + # LABEL label_51 ; + label_51: + + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # GOTO label_53 ; + b label_53 + # LABEL label_52 ; + label_52: + + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # local_14 = local_2 ; + lw $t0, -12($fp) + sw $t0, -60($fp) + # LABEL label_53 ; + label_53: + + # RETURN local_14 ; + lw $v0, -60($fp) + addu $sp, $sp, 60 + jr $ra +A2I_i2a_aux: + move $fp, $sp + subu $sp, $sp, 56 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # IF local_1 GOTO label_54 ; + lw $t0, -8($fp) + bnez $t0, label_54 + # local_3 = i / 10 ; lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -32($fp) - # local_6 = GETTYPEADDR local_7 ; - lw $t1, -32($fp) + li $t1, 10 + div $t0, $t0, $t1 + sw $t0, -16($fp) + # next = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 4($fp) lw $t0, 8($t1) sw $t0, -28($fp) - # local_8 = VCALL local_6 print_list ; + # local_7 = VCALL local_6 i2a_aux ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_7 ; - lw $t0, -32($fp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG next ; + lw $t0, -20($fp) subu $sp, $sp, 4 sw $t0, ($sp) lw $t0, -28($fp) - ulw $t1, 72($t0) + ulw $t1, 60($t0) jalr $t1 - addu $sp, $sp, 4 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -36($fp) - # RETURN local_8 ; - lw $v0, -36($fp) - addu $sp, $sp, 36 - jr $ra -Nil_isNil: - move $fp, $sp - subu $sp, $sp, 0 - # RETURN 1 ; - li $v0, 1 - addu $sp, $sp, 0 - jr $ra -Nil_rev: - move $fp, $sp - subu $sp, $sp, 0 - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 0 - jr $ra -Nil_sort: - move $fp, $sp - subu $sp, $sp, 0 - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 0 - jr $ra -Nil_insert: - move $fp, $sp - subu $sp, $sp, 8 - # local_0 = GETTYPEADDR self ; + sw $v0, -32($fp) + # local_8 = GETTYPEADDR self ; lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = VCALL local_0 rcons ; + sw $t0, -36($fp) + # local_9 = next * 10 ; + lw $t0, -20($fp) + li $t1, 10 + mul $t0, $t0, $t1 + sw $t0, -40($fp) + # local_10 = i - local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + sub $t0, $t0, $t1 + sw $t0, -44($fp) + # local_11 = VCALL local_8 i2c ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -1300,41 +1817,76 @@ Nil_insert: lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG i ; - lw $t0, 0($fp) + # ARG local_10 ; + lw $t0, -44($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 68($t0) + lw $t0, -36($fp) + ulw $t1, 44($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # RETURN local_1 ; - lw $v0, -8($fp) + sw $v0, -48($fp) + # local_12 = VCALL String concat ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_concat addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # GOTO label_55 ; + b label_55 + # LABEL label_54 ; + label_54: + + # local_2 = LOAD data_12 ; + la $t0, data_12 + sw $t0, -12($fp) + # local_13 = local_2 ; + lw $t0, -12($fp) + sw $t0, -56($fp) + # LABEL label_55 ; + label_55: + + # RETURN local_13 ; + lw $v0, -56($fp) + addu $sp, $sp, 56 jr $ra -Nil_rcons: +Main_main: move $fp, $sp - subu $sp, $sp, 20 - # local_1 = ALLOCATE Cons ; - li $a0, 20 + subu $sp, $sp, 92 + # local_1 = ALLOCATE A2I ; + li $a0, 12 li $v0, 9 syscall sw $v0, -8($fp) - la $t0, vt_Cons + la $t0, vt_A2I sw $t0, 8($v0) - # local_2 = LOAD data_2 ; - la $t0, data_2 + # local_2 = LOAD data_15 ; + la $t0, data_15 sw $t0, -12($fp) # SETATTR local_1 @type local_2 ; lw $t0, -12($fp) lw $t1, -8($fp) sw $t0, 0($t1) - # local_3 = 20 ; - li $t0, 20 + # local_3 = 12 ; + li $t0, 12 sw $t0, -16($fp) # SETATTR local_1 @size local_3 ; lw $t0, -16($fp) @@ -1344,7 +1896,10 @@ Nil_rcons: lw $t1, -8($fp) lw $t0, 8($t1) sw $t0, -4($fp) - # local_4 = VCALL local_0 init ; + # local_4 = LOAD data_16 ; + la $t0, data_16 + sw $t0, -20($fp) + # local_5 = VCALL local_0 a2i ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -1352,172 +1907,74 @@ Nil_rcons: lw $t0, -8($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG i ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG self ; - lw $t0, 4($fp) + # ARG local_4 ; + lw $t0, -20($fp) subu $sp, $sp, 4 sw $t0, ($sp) lw $t0, -4($fp) - ulw $t1, 76($t0) + ulw $t1, 48($t0) jalr $t1 - addu $sp, $sp, 12 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -20($fp) - # RETURN local_4 ; - lw $v0, -20($fp) - addu $sp, $sp, 20 - jr $ra -Nil_print_list: - move $fp, $sp - subu $sp, $sp, 0 - # RETURN 1 ; - li $v0, 1 - addu $sp, $sp, 0 - jr $ra -Main_iota: - move $fp, $sp - subu $sp, $sp, 56 - # local_0 = ALLOCATE Nil ; + sw $v0, -24($fp) + # a = local_5 ; + lw $t0, -24($fp) + sw $t0, -28($fp) + # local_8 = ALLOCATE A2I ; li $a0, 12 li $v0, 9 syscall - sw $v0, -4($fp) - la $t0, vt_Nil + sw $v0, -36($fp) + la $t0, vt_A2I sw $t0, 8($v0) - # local_1 = LOAD data_6 ; - la $t0, data_6 - sw $t0, -8($fp) - # SETATTR local_0 @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) + # local_9 = LOAD data_15 ; + la $t0, data_15 + sw $t0, -40($fp) + # SETATTR local_8 @type local_9 ; + lw $t0, -40($fp) + lw $t1, -36($fp) sw $t0, 0($t1) - # local_2 = 12 ; + # local_10 = 12 ; li $t0, 12 - sw $t0, -12($fp) - # SETATTR local_0 @size local_2 ; - lw $t0, -12($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) - # SETATTR self l local_0 ; - lw $t0, -4($fp) - lw $t1, 4($fp) - sw $t0, 12($t1) - # j = 0 ; - li $t0, 0 - sw $t0, -16($fp) - # LABEL label_3 ; - label_3: - - # local_4 = j < i ; - lw $t0, -16($fp) - lw $t1, 0($fp) - slt $t0, $t0, $t1 - sw $t0, -20($fp) - # IF local_4 GOTO label_4 ; - lw $t0, -20($fp) - bnez $t0, label_4 - # GOTO label_5 ; - b label_5 - # LABEL label_4 ; - label_4: - - # local_6 = ALLOCATE Cons ; - li $a0, 20 - li $v0, 9 - syscall - sw $v0, -28($fp) - la $t0, vt_Cons - sw $t0, 8($v0) - # local_7 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -32($fp) - # SETATTR local_6 @type local_7 ; - lw $t0, -32($fp) - lw $t1, -28($fp) - sw $t0, 0($t1) - # local_8 = 20 ; - li $t0, 20 - sw $t0, -36($fp) - # SETATTR local_6 @size local_8 ; - lw $t0, -36($fp) - lw $t1, -28($fp) + sw $t0, -44($fp) + # SETATTR local_8 @size local_10 ; + lw $t0, -44($fp) + lw $t1, -36($fp) sw $t0, 4($t1) - # local_5 = GETTYPEADDR local_6 ; - lw $t1, -28($fp) + # local_7 = GETTYPEADDR local_8 ; + lw $t1, -36($fp) lw $t0, 8($t1) - sw $t0, -24($fp) - # local_9 = GETATTR self l ; - lw $t0, 4($fp) - lw $t1, 12($t0) - sw $t1, -40($fp) - # local_10 = VCALL local_5 init ; + sw $t0, -32($fp) + # local_11 = VCALL local_7 i2a ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_6 ; - lw $t0, -28($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG j ; - lw $t0, -16($fp) + # ARG local_8 ; + lw $t0, -36($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_9 ; - lw $t0, -40($fp) + # ARG 678987 ; + li $t0, 678987 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -24($fp) - ulw $t1, 76($t0) + lw $t0, -32($fp) + ulw $t1, 56($t0) jalr $t1 - addu $sp, $sp, 12 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -44($fp) - # SETATTR self l local_10 ; - lw $t0, -44($fp) - lw $t1, 4($fp) - sw $t0, 12($t1) - # local_11 = j + 1 ; - lw $t0, -16($fp) - li $t1, 1 - add $t0, $t0, $t1 - sw $t0, -48($fp) - # j = local_11 ; + sw $v0, -48($fp) + # b = local_11 ; lw $t0, -48($fp) - sw $t0, -16($fp) - # GOTO label_3 ; - b label_3 - # LABEL label_5 ; - label_5: - - # local_12 = 0 ; - li $t0, 0 sw $t0, -52($fp) - # local_13 = GETATTR self l ; - lw $t0, 4($fp) - lw $t1, 12($t0) - sw $t1, -56($fp) - # RETURN local_13 ; - lw $v0, -56($fp) - addu $sp, $sp, 56 - jr $ra -Main_main: - move $fp, $sp - subu $sp, $sp, 52 - # local_0 = GETTYPEADDR self ; + # local_13 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -4($fp) - # local_1 = LOAD data_7 ; - la $t0, data_7 - sw $t0, -8($fp) - # local_2 = VCALL local_0 out_string ; + sw $t0, -56($fp) + # local_14 = VCALL local_13 out_int ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -1525,27 +1982,26 @@ Main_main: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_1 ; - lw $t0, -8($fp) + # ARG a ; + lw $t0, -28($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 12($t0) + lw $t0, -56($fp) + ulw $t1, 16($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -12($fp) - # local_6 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -28($fp) - # local_7 = GETTYPEADDR self ; + sw $v0, -60($fp) + # local_15 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -32($fp) - # local_8 = VCALL local_7 in_int ; + sw $t0, -64($fp) + # local_16 = LOAD data_17 ; + la $t0, data_17 + sw $t0, -68($fp) + # local_17 = VCALL local_15 out_string ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -1553,15 +2009,23 @@ Main_main: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -32($fp) - ulw $t1, 24($t0) + # ARG local_16 ; + lw $t0, -68($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -64($fp) + ulw $t1, 12($t0) jalr $t1 - addu $sp, $sp, 4 + addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -36($fp) - # local_9 = VCALL local_6 iota ; + sw $v0, -72($fp) + # local_18 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -76($fp) + # local_19 = VCALL local_18 out_string ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) @@ -1569,124 +2033,111 @@ Main_main: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_8 ; - lw $t0, -36($fp) + # ARG b ; + lw $t0, -52($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -28($fp) - ulw $t1, 80($t0) + lw $t0, -76($fp) + ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -40($fp) - # local_5 = GETTYPEADDR local_9 ; - lw $t1, -40($fp) + sw $v0, -80($fp) + # local_20 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -24($fp) - # local_10 = VCALL local_5 rev ; + sw $t0, -84($fp) + # local_21 = LOAD data_18 ; + la $t0, data_18 + sw $t0, -88($fp) + # local_22 = VCALL local_20 out_string ; subu $sp, $sp, 8 sw $ra, 0($sp) sw $fp, 4($sp) - # ARG local_9 ; - lw $t0, -40($fp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -24($fp) - ulw $t1, 56($t0) - jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -44($fp) - # local_4 = GETTYPEADDR local_10 ; - lw $t1, -44($fp) - lw $t0, 8($t1) - sw $t0, -20($fp) - # local_11 = VCALL local_4 sort ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_10 ; - lw $t0, -44($fp) + # ARG local_21 ; + lw $t0, -88($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -20($fp) - ulw $t1, 60($t0) + lw $t0, -84($fp) + ulw $t1, 12($t0) jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -48($fp) - # local_3 = GETTYPEADDR local_11 ; - lw $t1, -48($fp) - lw $t0, 8($t1) - sw $t0, -16($fp) - # local_12 = VCALL local_3 print_list ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_11 ; - lw $t0, -48($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -16($fp) - ulw $t1, 72($t0) - jalr $t1 - addu $sp, $sp, 4 lw $ra, 0($sp) lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -52($fp) - # RETURN local_12 ; - lw $v0, -52($fp) - addu $sp, $sp, 52 + sw $v0, -92($fp) + # RETURN local_22 ; + lw $v0, -92($fp) + addu $sp, $sp, 92 jr $ra .data data_1: .asciiz "Main" data_2: - .asciiz "Cons" + .asciiz "0" data_3: - .asciiz "Int" + .asciiz "1" data_4: - .asciiz "List" + .asciiz "2" data_5: - .asciiz "\n" + .asciiz "3" data_6: - .asciiz "Nil" + .asciiz "4" data_7: - .asciiz "How many numbers to sort? " + .asciiz "5" data_8: - .asciiz "Bool" + .asciiz "6" data_9: + .asciiz "7" + data_10: + .asciiz "8" + data_11: + .asciiz "9" + data_12: + .asciiz "" + data_13: + .asciiz "-" + data_14: + .asciiz "+" + data_15: + .asciiz "A2I" + data_16: + .asciiz "678987" + data_17: + .asciiz " == " + data_18: + .asciiz "\n" + data_19: + .asciiz "Bool" + data_20: + .asciiz "Int" + data_21: .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: .asciiz "\n" vt_Object: - .space 360 + .space 188 vt_IO: - .space 360 + .space 188 vt_Int: - .space 360 + .space 188 vt_String: - .space 360 + .space 188 vt_Bool: - .space 360 - vt_List: - .space 360 - vt_Cons: - .space 360 - vt_Nil: - .space 360 + .space 188 + vt_A2I: + .space 188 vt_Main: - .space 360 + .space 188 str: .space 1024 concat_result: From 0edd6ad5c0a4776eaadf0b1b4546e213a689f0c3 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Tue, 1 Dec 2020 22:27:07 -0500 Subject: [PATCH 415/435] fixing returned_type --- src/code_generation/CIL/cil.py | 2 +- src/code_generation/MIPS/test.asm | 2115 ++++++----------------------- src/semantic/semantic.py | 2 + 3 files changed, 448 insertions(+), 1671 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 72ce9a56..2d66d9a9 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -385,7 +385,7 @@ def loop_to_cil_visitor(loop): def equal_to_cil_visitor(equal): l = expression_to_cil_visitor(equal.lvalue) r = expression_to_cil_visitor(equal.rvalue) - + ret_l=equal.lvalue.returned_type.name ret_r=equal.rvalue.returned_type.name diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index c5325d59..a9fb0c02 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -48,24 +48,6 @@ main: la $t0, Object_copy usw $t0, vt_Bool+8 la $t0, Object_abort - usw $t0, vt_A2I+0 - la $t0, Object_type_name - usw $t0, vt_A2I+4 - la $t0, Object_copy - usw $t0, vt_A2I+8 - la $t0, A2I_c2i - usw $t0, vt_A2I+40 - la $t0, A2I_i2c - usw $t0, vt_A2I+44 - la $t0, A2I_a2i - usw $t0, vt_A2I+48 - la $t0, A2I_a2i_aux - usw $t0, vt_A2I+52 - la $t0, A2I_i2a - usw $t0, vt_A2I+56 - la $t0, A2I_i2a_aux - usw $t0, vt_A2I+60 - la $t0, Object_abort usw $t0, vt_Main+0 la $t0, Object_type_name usw $t0, vt_Main+4 @@ -80,7 +62,31 @@ main: la $t0, IO_in_int usw $t0, vt_Main+24 la $t0, Main_main - usw $t0, vt_Main+64 + usw $t0, vt_Main+40 + la $t0, Object_abort + usw $t0, vt_Complex+0 + la $t0, Object_type_name + usw $t0, vt_Complex+4 + la $t0, Object_copy + usw $t0, vt_Complex+8 + la $t0, IO_out_string + usw $t0, vt_Complex+12 + la $t0, IO_out_int + usw $t0, vt_Complex+16 + la $t0, IO_in_string + usw $t0, vt_Complex+20 + la $t0, IO_in_int + usw $t0, vt_Complex+24 + la $t0, Complex_init + usw $t0, vt_Complex+44 + la $t0, Complex_print + usw $t0, vt_Complex+48 + la $t0, Complex_reflect_0 + usw $t0, vt_Complex+52 + la $t0, Complex_reflect_X + usw $t0, vt_Complex+56 + la $t0, Complex_reflect_Y + usw $t0, vt_Complex+60 # self = ALLOCATE Main ; li $a0, 12 li $v0, 9 @@ -104,16 +110,16 @@ main: sw $t0, 4($t1) # main_result = VCALL Main main ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) + sw $fp, 0($sp) + sw $ra, 4($sp) # ARG self ; lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) jal Main_main addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 sw $v0, -16($fp) # RETURN main_result ; @@ -342,1802 +348,571 @@ Bool_abort: Bool_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_23 = LOAD data_19 ; - la $t0, data_19 + # local_5 = LOAD data_7 ; + la $t0, data_7 sw $t0, -4($fp) - # RETURN local_23 ; + # RETURN local_5 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra Int_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_24 = LOAD data_20 ; - la $t0, data_20 + # local_6 = LOAD data_8 ; + la $t0, data_8 sw $t0, -4($fp) - # RETURN local_24 ; + # RETURN local_6 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra String_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_25 = LOAD data_21 ; - la $t0, data_21 + # local_7 = LOAD data_9 ; + la $t0, data_9 sw $t0, -4($fp) - # RETURN local_25 ; + # RETURN local_7 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra -A2I_c2i: +Main_main: move $fp, $sp - subu $sp, $sp, 168 - # local_0 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -4($fp) - # local_1 = char == local_0 ; - lw $t0, 0($fp) - lw $t1, -4($fp) - li $v0, 1 - sw $v0, -8($fp) - equal_loop_1: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_1 - beqz $t2, end_loop_1 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_1 - b end_loop_1 - not_equal_1: - - li $v0, 0 + subu $sp, $sp, 84 + # local_1 = ALLOCATE Complex ; + li $a0, 20 + li $v0, 9 + syscall sw $v0, -8($fp) - end_loop_1: - - # local_2 = local_1 ; - lw $t0, -8($fp) + la $t0, vt_Complex + sw $t0, 8($v0) + # local_2 = LOAD data_2 ; + la $t0, data_2 sw $t0, -12($fp) - # IF local_2 GOTO label_19 ; + # SETATTR local_1 @type local_2 ; lw $t0, -12($fp) - bnez $t0, label_19 - # local_3 = LOAD data_3 ; - la $t0, data_3 + lw $t1, -8($fp) + sw $t0, 0($t1) + # local_3 = 20 ; + li $t0, 20 sw $t0, -16($fp) - # local_4 = char == local_3 ; - lw $t0, 0($fp) - lw $t1, -16($fp) - li $v0, 1 - sw $v0, -20($fp) - equal_loop_2: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_2 - beqz $t2, end_loop_2 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_2 - b end_loop_2 - not_equal_2: - - li $v0, 0 + # SETATTR local_1 @size local_3 ; + lw $t0, -16($fp) + lw $t1, -8($fp) + sw $t0, 4($t1) + # local_0 = GETTYPEADDR local_1 ; + lw $t1, -8($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_4 = VCALL local_0 init ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 sw $v0, -20($fp) - end_loop_2: - - # local_5 = local_4 ; + # c = local_4 ; lw $t0, -20($fp) sw $t0, -24($fp) - # IF local_5 GOTO label_17 ; + # local_7 = GETTYPEADDR c ; + lw $t1, -24($fp) + lw $t0, 8($t1) + sw $t0, -32($fp) + # local_8 = VCALL local_7 reflect_X ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG c ; lw $t0, -24($fp) - bnez $t0, label_17 - # local_6 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -28($fp) - # local_7 = char == local_6 ; - lw $t0, 0($fp) - lw $t1, -28($fp) - li $v0, 1 - sw $v0, -32($fp) - equal_loop_3: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_3 - beqz $t2, end_loop_3 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_3 - b end_loop_3 - not_equal_3: - - li $v0, 0 - sw $v0, -32($fp) - end_loop_3: - - # local_8 = local_7 ; + subu $sp, $sp, 4 + sw $t0, ($sp) lw $t0, -32($fp) - sw $t0, -36($fp) - # IF local_8 GOTO label_15 ; + ulw $t1, 56($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_6 = GETTYPEADDR local_8 ; + lw $t1, -36($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_9 = VCALL local_6 reflect_Y ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG local_8 ; lw $t0, -36($fp) - bnez $t0, label_15 - # local_9 = LOAD data_5 ; - la $t0, data_5 - sw $t0, -40($fp) - # local_10 = char == local_9 ; - lw $t0, 0($fp) - lw $t1, -40($fp) - li $v0, 1 - sw $v0, -44($fp) - equal_loop_4: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_4 - beqz $t2, end_loop_4 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_4 - b end_loop_4 - not_equal_4: - - li $v0, 0 - sw $v0, -44($fp) - end_loop_4: - - # local_11 = local_10 ; + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 60($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 + sw $v0, -40($fp) + # local_10 = GETTYPEADDR c ; + lw $t1, -24($fp) + lw $t0, 8($t1) + sw $t0, -44($fp) + # local_11 = VCALL local_10 reflect_0 ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG c ; + lw $t0, -24($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) lw $t0, -44($fp) - sw $t0, -48($fp) - # IF local_11 GOTO label_13 ; - lw $t0, -48($fp) - bnez $t0, label_13 - # local_12 = LOAD data_6 ; - la $t0, data_6 + ulw $t1, 52($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = local_9 == local_11 ; + lw $t0, -40($fp) + lw $t1, -48($fp) + seq $t0, $t0, $t1 sw $t0, -52($fp) - # local_13 = char == local_12 ; - lw $t0, 0($fp) - lw $t1, -52($fp) - li $v0, 1 - sw $v0, -56($fp) - equal_loop_5: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_5 - beqz $t2, end_loop_5 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_5 - b end_loop_5 - not_equal_5: - - li $v0, 0 - sw $v0, -56($fp) - end_loop_5: - - # local_14 = local_13 ; + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # IF local_13 GOTO label_1 ; lw $t0, -56($fp) - sw $t0, -60($fp) - # IF local_14 GOTO label_11 ; - lw $t0, -60($fp) - bnez $t0, label_11 - # local_15 = LOAD data_7 ; - la $t0, data_7 - sw $t0, -64($fp) - # local_16 = char == local_15 ; - lw $t0, 0($fp) - lw $t1, -64($fp) - li $v0, 1 - sw $v0, -68($fp) - equal_loop_6: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_6 - beqz $t2, end_loop_6 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_6 - b end_loop_6 - not_equal_6: - - li $v0, 0 - sw $v0, -68($fp) - end_loop_6: - - # local_17 = local_16 ; - lw $t0, -68($fp) + bnez $t0, label_1 + # local_17 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) sw $t0, -72($fp) - # IF local_17 GOTO label_9 ; - lw $t0, -72($fp) - bnez $t0, label_9 - # local_18 = LOAD data_8 ; - la $t0, data_8 + # local_18 = LOAD data_4 ; + la $t0, data_4 sw $t0, -76($fp) - # local_19 = char == local_18 ; + # local_19 = VCALL local_17 out_string ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG self ; lw $t0, 0($fp) - lw $t1, -76($fp) - li $v0, 1 - sw $v0, -80($fp) - equal_loop_7: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_7 - beqz $t2, end_loop_7 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_7 - b end_loop_7 - not_equal_7: - - li $v0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_18 ; + lw $t0, -76($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -72($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 sw $v0, -80($fp) - end_loop_7: - # local_20 = local_19 ; lw $t0, -80($fp) sw $t0, -84($fp) - # IF local_20 GOTO label_7 ; - lw $t0, -84($fp) - bnez $t0, label_7 - # local_21 = LOAD data_9 ; - la $t0, data_9 - sw $t0, -88($fp) - # local_22 = char == local_21 ; - lw $t0, 0($fp) - lw $t1, -88($fp) - li $v0, 1 - sw $v0, -92($fp) - equal_loop_8: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_8 - beqz $t2, end_loop_8 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_8 - b end_loop_8 - not_equal_8: - - li $v0, 0 - sw $v0, -92($fp) - end_loop_8: - - # local_23 = local_22 ; - lw $t0, -92($fp) - sw $t0, -96($fp) - # IF local_23 GOTO label_5 ; - lw $t0, -96($fp) - bnez $t0, label_5 - # local_24 = LOAD data_10 ; - la $t0, data_10 - sw $t0, -100($fp) - # local_25 = char == local_24 ; - lw $t0, 0($fp) - lw $t1, -100($fp) - li $v0, 1 - sw $v0, -104($fp) - equal_loop_9: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_9 - beqz $t2, end_loop_9 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_9 - b end_loop_9 - not_equal_9: - - li $v0, 0 - sw $v0, -104($fp) - end_loop_9: - - # local_26 = local_25 ; - lw $t0, -104($fp) - sw $t0, -108($fp) - # IF local_26 GOTO label_3 ; - lw $t0, -108($fp) - bnez $t0, label_3 - # local_27 = LOAD data_11 ; - la $t0, data_11 - sw $t0, -112($fp) - # local_28 = char == local_27 ; - lw $t0, 0($fp) - lw $t1, -112($fp) - li $v0, 1 - sw $v0, -116($fp) - equal_loop_10: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_10 - beqz $t2, end_loop_10 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_10 - b end_loop_10 - not_equal_10: - - li $v0, 0 - sw $v0, -116($fp) - end_loop_10: + # GOTO label_2 ; + b label_2 + # LABEL label_1 ; + label_1: - # local_29 = local_28 ; - lw $t0, -116($fp) - sw $t0, -120($fp) - # IF local_29 GOTO label_1 ; - lw $t0, -120($fp) - bnez $t0, label_1 - # local_30 = GETTYPEADDR self ; - lw $t1, 4($fp) + # local_14 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -124($fp) - # local_31 = VCALL local_30 abort ; + sw $t0, -60($fp) + # local_15 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -64($fp) + # local_16 = VCALL local_14 out_string ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) + sw $fp, 0($sp) + sw $ra, 4($sp) # ARG self ; - lw $t0, 4($fp) + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_15 ; + lw $t0, -64($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -124($fp) - ulw $t1, 0($t0) + lw $t0, -60($fp) + ulw $t1, 12($t0) jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -128($fp) - # local_32 = 0 ; - li $t0, 0 - sw $t0, -132($fp) - # GOTO label_2 ; - b label_2 - # LABEL label_1 ; - label_1: - - # local_32 = 9 ; - li $t0, 9 - sw $t0, -132($fp) + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 + sw $v0, -68($fp) + # local_20 = local_16 ; + lw $t0, -68($fp) + sw $t0, -84($fp) # LABEL label_2 ; label_2: - # local_33 = local_32 ; - lw $t0, -132($fp) - sw $t0, -136($fp) - # GOTO label_4 ; - b label_4 - # LABEL label_3 ; - label_3: - - # local_33 = 8 ; - li $t0, 8 - sw $t0, -136($fp) - # LABEL label_4 ; - label_4: - - # local_34 = local_33 ; - lw $t0, -136($fp) - sw $t0, -140($fp) - # GOTO label_6 ; - b label_6 - # LABEL label_5 ; - label_5: - - # local_34 = 7 ; - li $t0, 7 - sw $t0, -140($fp) - # LABEL label_6 ; - label_6: - - # local_35 = local_34 ; - lw $t0, -140($fp) - sw $t0, -144($fp) - # GOTO label_8 ; - b label_8 - # LABEL label_7 ; - label_7: - - # local_35 = 6 ; - li $t0, 6 - sw $t0, -144($fp) - # LABEL label_8 ; - label_8: - - # local_36 = local_35 ; - lw $t0, -144($fp) - sw $t0, -148($fp) - # GOTO label_10 ; - b label_10 - # LABEL label_9 ; - label_9: - - # local_36 = 5 ; - li $t0, 5 - sw $t0, -148($fp) - # LABEL label_10 ; - label_10: - - # local_37 = local_36 ; - lw $t0, -148($fp) - sw $t0, -152($fp) - # GOTO label_12 ; - b label_12 - # LABEL label_11 ; - label_11: - - # local_37 = 4 ; - li $t0, 4 - sw $t0, -152($fp) - # LABEL label_12 ; - label_12: - - # local_38 = local_37 ; - lw $t0, -152($fp) - sw $t0, -156($fp) - # GOTO label_14 ; - b label_14 - # LABEL label_13 ; - label_13: - - # local_38 = 3 ; - li $t0, 3 - sw $t0, -156($fp) - # LABEL label_14 ; - label_14: - - # local_39 = local_38 ; - lw $t0, -156($fp) - sw $t0, -160($fp) - # GOTO label_16 ; - b label_16 - # LABEL label_15 ; - label_15: - - # local_39 = 2 ; - li $t0, 2 - sw $t0, -160($fp) - # LABEL label_16 ; - label_16: - - # local_40 = local_39 ; - lw $t0, -160($fp) - sw $t0, -164($fp) - # GOTO label_18 ; - b label_18 - # LABEL label_17 ; - label_17: - - # local_40 = 1 ; - li $t0, 1 - sw $t0, -164($fp) - # LABEL label_18 ; - label_18: - - # local_41 = local_40 ; - lw $t0, -164($fp) - sw $t0, -168($fp) - # GOTO label_20 ; - b label_20 - # LABEL label_19 ; - label_19: - - # local_41 = 0 ; - li $t0, 0 - sw $t0, -168($fp) - # LABEL label_20 ; - label_20: - - # RETURN local_41 ; - lw $v0, -168($fp) - addu $sp, $sp, 168 + # RETURN local_20 ; + lw $v0, -84($fp) + addu $sp, $sp, 84 jr $ra -A2I_i2c: +Complex_init: move $fp, $sp - subu $sp, $sp, 172 - # local_0 = i == 0 ; - lw $t0, 0($fp) - li $t1, 0 - seq $t0, $t0, $t1 - sw $t0, -4($fp) - # local_1 = local_0 ; - lw $t0, -4($fp) - sw $t0, -8($fp) - # IF local_1 GOTO label_39 ; - lw $t0, -8($fp) - bnez $t0, label_39 - # local_3 = i == 1 ; - lw $t0, 0($fp) - li $t1, 1 - seq $t0, $t0, $t1 - sw $t0, -16($fp) - # local_4 = local_3 ; - lw $t0, -16($fp) - sw $t0, -20($fp) - # IF local_4 GOTO label_37 ; - lw $t0, -20($fp) - bnez $t0, label_37 - # local_6 = i == 2 ; - lw $t0, 0($fp) - li $t1, 2 - seq $t0, $t0, $t1 - sw $t0, -28($fp) - # local_7 = local_6 ; - lw $t0, -28($fp) - sw $t0, -32($fp) - # IF local_7 GOTO label_35 ; - lw $t0, -32($fp) - bnez $t0, label_35 - # local_9 = i == 3 ; - lw $t0, 0($fp) - li $t1, 3 - seq $t0, $t0, $t1 - sw $t0, -40($fp) - # local_10 = local_9 ; - lw $t0, -40($fp) - sw $t0, -44($fp) - # IF local_10 GOTO label_33 ; - lw $t0, -44($fp) - bnez $t0, label_33 - # local_12 = i == 4 ; - lw $t0, 0($fp) - li $t1, 4 - seq $t0, $t0, $t1 - sw $t0, -52($fp) - # local_13 = local_12 ; - lw $t0, -52($fp) - sw $t0, -56($fp) - # IF local_13 GOTO label_31 ; - lw $t0, -56($fp) - bnez $t0, label_31 - # local_15 = i == 5 ; - lw $t0, 0($fp) - li $t1, 5 - seq $t0, $t0, $t1 - sw $t0, -64($fp) - # local_16 = local_15 ; - lw $t0, -64($fp) - sw $t0, -68($fp) - # IF local_16 GOTO label_29 ; - lw $t0, -68($fp) - bnez $t0, label_29 - # local_18 = i == 6 ; - lw $t0, 0($fp) - li $t1, 6 - seq $t0, $t0, $t1 - sw $t0, -76($fp) - # local_19 = local_18 ; - lw $t0, -76($fp) - sw $t0, -80($fp) - # IF local_19 GOTO label_27 ; - lw $t0, -80($fp) - bnez $t0, label_27 - # local_21 = i == 7 ; - lw $t0, 0($fp) - li $t1, 7 - seq $t0, $t0, $t1 - sw $t0, -88($fp) - # local_22 = local_21 ; - lw $t0, -88($fp) - sw $t0, -92($fp) - # IF local_22 GOTO label_25 ; - lw $t0, -92($fp) - bnez $t0, label_25 - # local_24 = i == 8 ; - lw $t0, 0($fp) - li $t1, 8 - seq $t0, $t0, $t1 - sw $t0, -100($fp) - # local_25 = local_24 ; - lw $t0, -100($fp) - sw $t0, -104($fp) - # IF local_25 GOTO label_23 ; - lw $t0, -104($fp) - bnez $t0, label_23 - # local_27 = i == 9 ; - lw $t0, 0($fp) - li $t1, 9 - seq $t0, $t0, $t1 - sw $t0, -112($fp) - # local_28 = local_27 ; - lw $t0, -112($fp) - sw $t0, -116($fp) - # IF local_28 GOTO label_21 ; - lw $t0, -116($fp) - bnez $t0, label_21 - # local_30 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -124($fp) - # local_31 = VCALL local_30 abort ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -124($fp) - ulw $t1, 0($t0) - jalr $t1 - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -128($fp) - # local_32 = LOAD data_12 ; - la $t0, data_12 - sw $t0, -132($fp) - # local_33 = local_32 ; - lw $t0, -132($fp) - sw $t0, -136($fp) - # GOTO label_22 ; - b label_22 - # LABEL label_21 ; - label_21: - - # local_29 = LOAD data_11 ; - la $t0, data_11 - sw $t0, -120($fp) - # local_33 = local_29 ; - lw $t0, -120($fp) - sw $t0, -136($fp) - # LABEL label_22 ; - label_22: - - # local_34 = local_33 ; - lw $t0, -136($fp) - sw $t0, -140($fp) - # GOTO label_24 ; - b label_24 - # LABEL label_23 ; - label_23: - - # local_26 = LOAD data_10 ; - la $t0, data_10 - sw $t0, -108($fp) - # local_34 = local_26 ; - lw $t0, -108($fp) - sw $t0, -140($fp) - # LABEL label_24 ; - label_24: - - # local_35 = local_34 ; - lw $t0, -140($fp) - sw $t0, -144($fp) - # GOTO label_26 ; - b label_26 - # LABEL label_25 ; - label_25: - - # local_23 = LOAD data_9 ; - la $t0, data_9 - sw $t0, -96($fp) - # local_35 = local_23 ; - lw $t0, -96($fp) - sw $t0, -144($fp) - # LABEL label_26 ; - label_26: - - # local_36 = local_35 ; - lw $t0, -144($fp) - sw $t0, -148($fp) - # GOTO label_28 ; - b label_28 - # LABEL label_27 ; - label_27: - - # local_20 = LOAD data_8 ; - la $t0, data_8 - sw $t0, -84($fp) - # local_36 = local_20 ; - lw $t0, -84($fp) - sw $t0, -148($fp) - # LABEL label_28 ; - label_28: - - # local_37 = local_36 ; - lw $t0, -148($fp) - sw $t0, -152($fp) - # GOTO label_30 ; - b label_30 - # LABEL label_29 ; - label_29: - - # local_17 = LOAD data_7 ; - la $t0, data_7 - sw $t0, -72($fp) - # local_37 = local_17 ; - lw $t0, -72($fp) - sw $t0, -152($fp) - # LABEL label_30 ; - label_30: - - # local_38 = local_37 ; - lw $t0, -152($fp) - sw $t0, -156($fp) - # GOTO label_32 ; - b label_32 - # LABEL label_31 ; - label_31: - - # local_14 = LOAD data_6 ; - la $t0, data_6 - sw $t0, -60($fp) - # local_38 = local_14 ; - lw $t0, -60($fp) - sw $t0, -156($fp) - # LABEL label_32 ; - label_32: - - # local_39 = local_38 ; - lw $t0, -156($fp) - sw $t0, -160($fp) - # GOTO label_34 ; - b label_34 - # LABEL label_33 ; - label_33: - - # local_11 = LOAD data_5 ; - la $t0, data_5 - sw $t0, -48($fp) - # local_39 = local_11 ; - lw $t0, -48($fp) - sw $t0, -160($fp) - # LABEL label_34 ; - label_34: - - # local_40 = local_39 ; - lw $t0, -160($fp) - sw $t0, -164($fp) - # GOTO label_36 ; - b label_36 - # LABEL label_35 ; - label_35: - - # local_8 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -36($fp) - # local_40 = local_8 ; - lw $t0, -36($fp) - sw $t0, -164($fp) - # LABEL label_36 ; - label_36: - - # local_41 = local_40 ; - lw $t0, -164($fp) - sw $t0, -168($fp) - # GOTO label_38 ; - b label_38 - # LABEL label_37 ; - label_37: - - # local_5 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -24($fp) - # local_41 = local_5 ; - lw $t0, -24($fp) - sw $t0, -168($fp) - # LABEL label_38 ; - label_38: - - # local_42 = local_41 ; - lw $t0, -168($fp) - sw $t0, -172($fp) - # GOTO label_40 ; - b label_40 - # LABEL label_39 ; - label_39: - - # local_2 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -12($fp) - # local_42 = local_2 ; - lw $t0, -12($fp) - sw $t0, -172($fp) - # LABEL label_40 ; - label_40: - - # RETURN local_42 ; - lw $v0, -172($fp) - addu $sp, $sp, 172 - jr $ra -A2I_a2i: - move $fp, $sp - subu $sp, $sp, 136 - # local_1 = VCALL String length ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_length - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -8($fp) - # local_2 = local_1 == 0 ; - lw $t0, -8($fp) - li $t1, 0 - seq $t0, $t0, $t1 - sw $t0, -12($fp) - # local_3 = local_2 ; - lw $t0, -12($fp) - sw $t0, -16($fp) - # IF local_3 GOTO label_45 ; - lw $t0, -16($fp) - bnez $t0, label_45 - # local_5 = VCALL String substr ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 0 ; - li $t0, 0 - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -24($fp) - # local_6 = LOAD data_13 ; - la $t0, data_13 - sw $t0, -28($fp) - # local_7 = local_5 == local_6 ; - lw $t0, -24($fp) - lw $t1, -28($fp) - li $v0, 1 - sw $v0, -32($fp) - equal_loop_11: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_11 - beqz $t2, end_loop_11 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_11 - b end_loop_11 - not_equal_11: - - li $v0, 0 - sw $v0, -32($fp) - end_loop_11: - - # local_8 = local_7 ; - lw $t0, -32($fp) - sw $t0, -36($fp) - # IF local_8 GOTO label_43 ; - lw $t0, -36($fp) - bnez $t0, label_43 - # local_18 = VCALL String substr ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 0 ; - li $t0, 0 - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -76($fp) - # local_19 = LOAD data_14 ; - la $t0, data_14 - sw $t0, -80($fp) - # local_20 = local_18 == local_19 ; - lw $t0, -76($fp) - lw $t1, -80($fp) - li $v0, 1 - sw $v0, -84($fp) - equal_loop_12: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_12 - beqz $t2, end_loop_12 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_12 - b end_loop_12 - not_equal_12: - - li $v0, 0 - sw $v0, -84($fp) - end_loop_12: - - # local_21 = local_20 ; - lw $t0, -84($fp) - sw $t0, -88($fp) - # IF local_21 GOTO label_41 ; - lw $t0, -88($fp) - bnez $t0, label_41 - # local_29 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -120($fp) - # local_30 = VCALL local_29 a2i_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -120($fp) - ulw $t1, 52($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -124($fp) - # local_31 = local_30 ; - lw $t0, -124($fp) - sw $t0, -128($fp) - # GOTO label_42 ; - b label_42 - # LABEL label_41 ; - label_41: - - # local_22 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -92($fp) - # local_25 = VCALL String length ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_length - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -104($fp) - # local_26 = local_25 - 1 ; - lw $t0, -104($fp) - li $t1, 1 - sub $t0, $t0, $t1 - sw $t0, -108($fp) - # local_27 = VCALL String substr ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_26 ; - lw $t0, -108($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -112($fp) - # local_28 = VCALL local_22 a2i_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_27 ; - lw $t0, -112($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -92($fp) - ulw $t1, 52($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -116($fp) - # local_31 = local_28 ; - lw $t0, -116($fp) - sw $t0, -128($fp) - # LABEL label_42 ; - label_42: - - # local_32 = local_31 ; - lw $t0, -128($fp) - sw $t0, -132($fp) - # GOTO label_44 ; - b label_44 - # LABEL label_43 ; - label_43: - - # local_9 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -40($fp) - # local_12 = VCALL String length ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_length - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -52($fp) - # local_13 = local_12 - 1 ; - lw $t0, -52($fp) - li $t1, 1 - sub $t0, $t0, $t1 - sw $t0, -56($fp) - # local_14 = VCALL String substr ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_13 ; - lw $t0, -56($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -60($fp) - # local_15 = VCALL local_9 a2i_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_14 ; - lw $t0, -60($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -40($fp) - ulw $t1, 52($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -64($fp) - # local_16 = ~ local_15 - not $t0, $t0 - sw $t0, -68($fp) - # local_32 = local_16 ; - lw $t0, -68($fp) - sw $t0, -132($fp) - # LABEL label_44 ; - label_44: - - # local_33 = local_32 ; - lw $t0, -132($fp) - sw $t0, -136($fp) - # GOTO label_46 ; - b label_46 - # LABEL label_45 ; - label_45: - - # local_33 = 0 ; - li $t0, 0 - sw $t0, -136($fp) - # LABEL label_46 ; - label_46: - - # RETURN local_33 ; - lw $v0, -136($fp) - addu $sp, $sp, 136 - jr $ra -A2I_a2i_aux: - move $fp, $sp - subu $sp, $sp, 56 - # int = 0 ; - li $t0, 0 - sw $t0, -4($fp) - # local_2 = VCALL String length ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_length - addu $sp, $sp, 4 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -12($fp) - # j = local_2 ; - lw $t0, -12($fp) - sw $t0, -16($fp) - # i = 0 ; - li $t0, 0 - sw $t0, -20($fp) - # LABEL label_47 ; - label_47: - - # local_5 = i < j ; - lw $t0, -20($fp) - lw $t1, -16($fp) - slt $t0, $t0, $t1 - sw $t0, -24($fp) - # IF local_5 GOTO label_48 ; - lw $t0, -24($fp) - bnez $t0, label_48 - # GOTO label_49 ; - b label_49 - # LABEL label_48 ; - label_48: - - # local_6 = int * 10 ; - lw $t0, -4($fp) - li $t1, 10 - mul $t0, $t0, $t1 - sw $t0, -28($fp) - # local_7 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -32($fp) - # local_9 = VCALL String substr ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, -20($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 12 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -40($fp) - # local_10 = VCALL local_7 c2i ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_9 ; - lw $t0, -40($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -32($fp) - ulw $t1, 40($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -44($fp) - # local_11 = local_6 + local_10 ; - lw $t0, -28($fp) - lw $t1, -44($fp) - add $t0, $t0, $t1 - sw $t0, -48($fp) - # int = local_11 ; - lw $t0, -48($fp) - sw $t0, -4($fp) - # local_12 = i + 1 ; - lw $t0, -20($fp) - li $t1, 1 - add $t0, $t0, $t1 - sw $t0, -52($fp) - # i = local_12 ; - lw $t0, -52($fp) - sw $t0, -20($fp) - # GOTO label_47 ; - b label_47 - # LABEL label_49 ; - label_49: - - # local_13 = 0 ; - li $t0, 0 - sw $t0, -56($fp) - # RETURN int ; - lw $v0, -4($fp) - addu $sp, $sp, 56 - jr $ra -A2I_i2a: - move $fp, $sp - subu $sp, $sp, 60 - # local_0 = i == 0 ; - lw $t0, 0($fp) - li $t1, 0 - seq $t0, $t0, $t1 - sw $t0, -4($fp) - # local_1 = local_0 ; - lw $t0, -4($fp) - sw $t0, -8($fp) - # IF local_1 GOTO label_52 ; - lw $t0, -8($fp) - bnez $t0, label_52 - # local_3 = 0 < i ; - li $t0, 0 - lw $t1, 0($fp) - slt $t0, $t0, $t1 - sw $t0, -16($fp) - # IF local_3 GOTO label_50 ; - lw $t0, -16($fp) - bnez $t0, label_50 - # local_7 = LOAD data_13 ; - la $t0, data_13 - sw $t0, -32($fp) - # local_8 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -36($fp) - # local_9 = ~ 1 - li $t0, 1 - not $t0, $t0 - sw $t0, -40($fp) - # local_10 = i * local_9 ; - lw $t0, 0($fp) - lw $t1, -40($fp) - mul $t0, $t0, $t1 - sw $t0, -44($fp) - # local_11 = VCALL local_8 i2a_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_10 ; - lw $t0, -44($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -36($fp) - ulw $t1, 60($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -48($fp) - # local_12 = VCALL String concat ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_7 ; - lw $t0, -32($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_11 ; - lw $t0, -48($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - jal String_concat - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -52($fp) - # local_13 = local_12 ; - lw $t0, -52($fp) - sw $t0, -56($fp) - # GOTO label_51 ; - b label_51 - # LABEL label_50 ; - label_50: - - # local_4 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -20($fp) - # local_5 = VCALL local_4 i2a_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG i ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -20($fp) - ulw $t1, 60($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -24($fp) - # local_13 = local_5 ; - lw $t0, -24($fp) - sw $t0, -56($fp) - # LABEL label_51 ; - label_51: - - # local_14 = local_13 ; - lw $t0, -56($fp) - sw $t0, -60($fp) - # GOTO label_53 ; - b label_53 - # LABEL label_52 ; - label_52: - - # local_2 = LOAD data_2 ; - la $t0, data_2 + subu $sp, $sp, 24 + # local_0 = GETATTR self x ; + lw $t0, 8($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # local_1 = local_0 == a ; + lw $t0, -4($fp) + lw $t1, 4($fp) + seq $t0, $t0, $t1 + sw $t0, -8($fp) + # local_2 = local_1 ; + lw $t0, -8($fp) sw $t0, -12($fp) - # local_14 = local_2 ; - lw $t0, -12($fp) - sw $t0, -60($fp) - # LABEL label_53 ; - label_53: - - # RETURN local_14 ; - lw $v0, -60($fp) - addu $sp, $sp, 60 + # local_3 = GETATTR self y ; + lw $t0, 8($fp) + lw $t1, 16($t0) + sw $t1, -16($fp) + # local_4 = local_3 == b ; + lw $t0, -16($fp) + lw $t1, 0($fp) + seq $t0, $t0, $t1 + sw $t0, -20($fp) + # local_5 = local_4 ; + lw $t0, -20($fp) + sw $t0, -24($fp) + # RETURN self ; + lw $v0, 8($fp) + addu $sp, $sp, 24 jr $ra -A2I_i2a_aux: +Complex_print: move $fp, $sp - subu $sp, $sp, 56 - # local_0 = i == 0 ; + subu $sp, $sp, 76 + # local_0 = GETATTR self y ; lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -4($fp) + # local_1 = local_0 == 0 ; + lw $t0, -4($fp) li $t1, 0 seq $t0, $t0, $t1 - sw $t0, -4($fp) - # local_1 = local_0 ; - lw $t0, -4($fp) sw $t0, -8($fp) - # IF local_1 GOTO label_54 ; + # local_2 = local_1 ; lw $t0, -8($fp) - bnez $t0, label_54 - # local_3 = i / 10 ; - lw $t0, 0($fp) - li $t1, 10 - div $t0, $t0, $t1 - sw $t0, -16($fp) - # next = local_3 ; - lw $t0, -16($fp) - sw $t0, -20($fp) - # local_6 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -28($fp) - # local_7 = VCALL local_6 i2a_aux ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 4($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG next ; - lw $t0, -20($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -28($fp) - ulw $t1, 60($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -32($fp) - # local_8 = GETTYPEADDR self ; - lw $t1, 4($fp) + sw $t0, -12($fp) + # IF local_2 GOTO label_3 ; + lw $t0, -12($fp) + bnez $t0, label_3 + # local_9 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -36($fp) - # local_9 = next * 10 ; - lw $t0, -20($fp) - li $t1, 10 - mul $t0, $t0, $t1 sw $t0, -40($fp) - # local_10 = i - local_9 ; + # local_10 = GETATTR self x ; lw $t0, 0($fp) - lw $t1, -40($fp) - sub $t0, $t0, $t1 - sw $t0, -44($fp) - # local_11 = VCALL local_8 i2c ; + lw $t1, 12($t0) + sw $t1, -44($fp) + # local_11 = VCALL local_9 out_int ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) + sw $fp, 0($sp) + sw $ra, 4($sp) # ARG self ; - lw $t0, 4($fp) + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) # ARG local_10 ; lw $t0, -44($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -36($fp) - ulw $t1, 44($t0) + lw $t0, -40($fp) + ulw $t1, 16($t0) jalr $t1 addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 sw $v0, -48($fp) - # local_12 = VCALL String concat ; + # local_8 = GETTYPEADDR local_11 ; + lw $t1, -48($fp) + lw $t0, 8($t1) + sw $t0, -36($fp) + # local_12 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -52($fp) + # local_13 = VCALL local_8 out_string ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_7 ; - lw $t0, -32($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) + sw $fp, 0($sp) + sw $ra, 4($sp) # ARG local_11 ; lw $t0, -48($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_concat - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -52($fp) - # local_13 = local_12 ; + # ARG local_12 ; lw $t0, -52($fp) - sw $t0, -56($fp) - # GOTO label_55 ; - b label_55 - # LABEL label_54 ; - label_54: - - # local_2 = LOAD data_12 ; - la $t0, data_12 - sw $t0, -12($fp) - # local_13 = local_2 ; - lw $t0, -12($fp) - sw $t0, -56($fp) - # LABEL label_55 ; - label_55: - - # RETURN local_13 ; - lw $v0, -56($fp) - addu $sp, $sp, 56 - jr $ra -Main_main: - move $fp, $sp - subu $sp, $sp, 92 - # local_1 = ALLOCATE A2I ; - li $a0, 12 - li $v0, 9 - syscall - sw $v0, -8($fp) - la $t0, vt_A2I - sw $t0, 8($v0) - # local_2 = LOAD data_15 ; - la $t0, data_15 - sw $t0, -12($fp) - # SETATTR local_1 @type local_2 ; - lw $t0, -12($fp) - lw $t1, -8($fp) - sw $t0, 0($t1) - # local_3 = 12 ; - li $t0, 12 - sw $t0, -16($fp) - # SETATTR local_1 @size local_3 ; - lw $t0, -16($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # local_0 = GETTYPEADDR local_1 ; - lw $t1, -8($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_4 = LOAD data_16 ; - la $t0, data_16 - sw $t0, -20($fp) - # local_5 = VCALL local_0 a2i ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_1 ; - lw $t0, -8($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 48($t0) + lw $t0, -36($fp) + ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -24($fp) - # a = local_5 ; - lw $t0, -24($fp) - sw $t0, -28($fp) - # local_8 = ALLOCATE A2I ; - li $a0, 12 - li $v0, 9 - syscall - sw $v0, -36($fp) - la $t0, vt_A2I - sw $t0, 8($v0) - # local_9 = LOAD data_15 ; - la $t0, data_15 - sw $t0, -40($fp) - # SETATTR local_8 @type local_9 ; - lw $t0, -40($fp) - lw $t1, -36($fp) - sw $t0, 0($t1) - # local_10 = 12 ; - li $t0, 12 - sw $t0, -44($fp) - # SETATTR local_8 @size local_10 ; - lw $t0, -44($fp) - lw $t1, -36($fp) - sw $t0, 4($t1) - # local_7 = GETTYPEADDR local_8 ; - lw $t1, -36($fp) + sw $v0, -56($fp) + # local_7 = GETTYPEADDR local_13 ; + lw $t1, -56($fp) lw $t0, 8($t1) sw $t0, -32($fp) - # local_11 = VCALL local_7 i2a ; + # local_14 = GETATTR self y ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -60($fp) + # local_15 = VCALL local_7 out_int ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG local_8 ; - lw $t0, -36($fp) + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG local_13 ; + lw $t0, -56($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 678987 ; - li $t0, 678987 + # ARG local_14 ; + lw $t0, -60($fp) subu $sp, $sp, 4 sw $t0, ($sp) lw $t0, -32($fp) - ulw $t1, 56($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -48($fp) - # b = local_11 ; - lw $t0, -48($fp) - sw $t0, -52($fp) - # local_13 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -56($fp) - # local_14 = VCALL local_13 out_int ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG a ; - lw $t0, -28($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -56($fp) ulw $t1, 16($t0) jalr $t1 addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -60($fp) - # local_15 = GETTYPEADDR self ; - lw $t1, 0($fp) + sw $v0, -64($fp) + # local_6 = GETTYPEADDR local_15 ; + lw $t1, -64($fp) lw $t0, 8($t1) - sw $t0, -64($fp) - # local_16 = LOAD data_17 ; - la $t0, data_17 + sw $t0, -28($fp) + # local_16 = LOAD data_6 ; + la $t0, data_6 sw $t0, -68($fp) - # local_17 = VCALL local_15 out_string ; + # local_17 = VCALL local_6 out_string ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 0($fp) + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG local_15 ; + lw $t0, -64($fp) subu $sp, $sp, 4 sw $t0, ($sp) # ARG local_16 ; lw $t0, -68($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -64($fp) + lw $t0, -28($fp) ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 sw $v0, -72($fp) - # local_18 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) + # local_18 = local_17 ; + lw $t0, -72($fp) sw $t0, -76($fp) - # local_19 = VCALL local_18 out_string ; - subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) - # ARG self ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG b ; - lw $t0, -52($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -76($fp) - ulw $t1, 12($t0) - jalr $t1 - addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) - addu $sp, $sp, 8 - sw $v0, -80($fp) - # local_20 = GETTYPEADDR self ; + # GOTO label_4 ; + b label_4 + # LABEL label_3 ; + label_3: + + # local_3 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -84($fp) - # local_21 = LOAD data_18 ; - la $t0, data_18 - sw $t0, -88($fp) - # local_22 = VCALL local_20 out_string ; + sw $t0, -16($fp) + # local_4 = GETATTR self x ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -20($fp) + # local_5 = VCALL local_3 out_int ; subu $sp, $sp, 8 - sw $ra, 0($sp) - sw $fp, 4($sp) + sw $fp, 0($sp) + sw $ra, 4($sp) # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_21 ; - lw $t0, -88($fp) + # ARG local_4 ; + lw $t0, -20($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -84($fp) - ulw $t1, 12($t0) + lw $t0, -16($fp) + ulw $t1, 16($t0) jalr $t1 addu $sp, $sp, 8 - lw $ra, 0($sp) - lw $fp, 4($sp) + lw $fp, 0($sp) + lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -92($fp) - # RETURN local_22 ; - lw $v0, -92($fp) - addu $sp, $sp, 92 + sw $v0, -24($fp) + # local_18 = local_5 ; + lw $t0, -24($fp) + sw $t0, -76($fp) + # LABEL label_4 ; + label_4: + + # RETURN local_18 ; + lw $v0, -76($fp) + addu $sp, $sp, 76 + jr $ra +Complex_reflect_0: + move $fp, $sp + subu $sp, $sp, 40 + # local_0 = GETATTR self x ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # local_1 = GETATTR self x ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -8($fp) + # local_2 = ~ local_1 + not $t0, $t0 + sw $t0, -12($fp) + # local_3 = local_0 == local_2 ; + lw $t0, -4($fp) + lw $t1, -12($fp) + seq $t0, $t0, $t1 + sw $t0, -16($fp) + # local_4 = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # local_5 = GETATTR self y ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -24($fp) + # local_6 = GETATTR self y ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -28($fp) + # local_7 = ~ local_6 + not $t0, $t0 + sw $t0, -32($fp) + # local_8 = local_5 == local_7 ; + lw $t0, -24($fp) + lw $t1, -32($fp) + seq $t0, $t0, $t1 + sw $t0, -36($fp) + # local_9 = local_8 ; + lw $t0, -36($fp) + sw $t0, -40($fp) + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 40 + jr $ra +Complex_reflect_X: + move $fp, $sp + subu $sp, $sp, 20 + # local_0 = GETATTR self y ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -4($fp) + # local_1 = GETATTR self y ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -8($fp) + # local_2 = ~ local_1 + not $t0, $t0 + sw $t0, -12($fp) + # local_3 = local_0 == local_2 ; + lw $t0, -4($fp) + lw $t1, -12($fp) + seq $t0, $t0, $t1 + sw $t0, -16($fp) + # local_4 = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 20 + jr $ra +Complex_reflect_Y: + move $fp, $sp + subu $sp, $sp, 20 + # local_0 = GETATTR self x ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # local_1 = GETATTR self x ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -8($fp) + # local_2 = ~ local_1 + not $t0, $t0 + sw $t0, -12($fp) + # local_3 = local_0 == local_2 ; + lw $t0, -4($fp) + lw $t1, -12($fp) + seq $t0, $t0, $t1 + sw $t0, -16($fp) + # local_4 = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # RETURN self ; + lw $v0, 0($fp) + addu $sp, $sp, 20 jr $ra .data data_1: .asciiz "Main" data_2: - .asciiz "0" + .asciiz "Complex" data_3: - .asciiz "1" + .asciiz "=)\n" data_4: - .asciiz "2" + .asciiz "=(\n" data_5: - .asciiz "3" + .asciiz "+" data_6: - .asciiz "4" + .asciiz "I" data_7: - .asciiz "5" - data_8: - .asciiz "6" - data_9: - .asciiz "7" - data_10: - .asciiz "8" - data_11: - .asciiz "9" - data_12: - .asciiz "" - data_13: - .asciiz "-" - data_14: - .asciiz "+" - data_15: - .asciiz "A2I" - data_16: - .asciiz "678987" - data_17: - .asciiz " == " - data_18: - .asciiz "\n" - data_19: .asciiz "Bool" - data_20: + data_8: .asciiz "Int" - data_21: + data_9: .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: .asciiz "\n" vt_Object: - .space 188 + .space 200 vt_IO: - .space 188 + .space 200 vt_Int: - .space 188 + .space 200 vt_String: - .space 188 + .space 200 vt_Bool: - .space 188 - vt_A2I: - .space 188 + .space 200 vt_Main: - .space 188 + .space 200 + vt_Complex: + .space 200 str: .space 1024 concat_result: diff --git a/src/semantic/semantic.py b/src/semantic/semantic.py index a932c006..12c46f02 100644 --- a/src/semantic/semantic.py +++ b/src/semantic/semantic.py @@ -543,6 +543,7 @@ def negation_visitor(negation: NegationNode, current_class: CT.CoolType, local_s add_semantic_error(negation.lineno, negation.colno, f'{ERR_TYPE}: Argument of \'~\' has type {value_type} instead of {CT.IntType}.') # 3) + negation.returned_type=CT.BoolType return CT.IntType @@ -564,6 +565,7 @@ def logic_negation_visitor(negation: LogicNegationNode, current_class: CT.CoolTy add_semantic_error(negation.lineno, negation.colno, f'{ERR_TYPE}: Argument of \'not\' has type {CT.IntType} instead of {value_type}.') # 3) + negation.returned_type=CT.BoolType return CT.BoolType From 7171ed6629e84ada3424e4278b615bc1d7af07b1 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 2 Dec 2020 08:56:59 -0500 Subject: [PATCH 416/435] removing nl from read --- src/code_generation/CIL/ast.py | 9 +- src/code_generation/CIL/cil.py | 33 +- src/code_generation/MIPS/mips.py | 36 +- src/code_generation/MIPS/test.asm | 754 +++++++++++++----------------- 4 files changed, 396 insertions(+), 436 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 407c2bac..5d22fffc 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -395,21 +395,23 @@ def __str__(self): class ConcatNode(InstructionNode): - def __init__(self, str_a, str_b, result): + def __init__(self, str_a, str_b, calls, result): self.result = result self.str_a = str_a self.str_b = str_b + self.calls=calls def __str__(self): return f'{self.result} = CONCAT {self.str_a} {self.str_b} ;' class SubStringNode(InstructionNode): - def __init__(self, str, i, len, result): + def __init__(self, str, i, len,calls, result): self.result = result self.i = i self.len = len self.str = str + self.calls=calls def __str__(self): return f'{self.result} = SUBSTRING {self.str} {self.i} {self.len};' @@ -428,8 +430,9 @@ def __str__(self): class ReadNode(InstructionNode): - def __init__(self, result): + def __init__(self, result, calls): super().__init__() + self.calls=calls self.result = result self.check_local(result) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 2d66d9a9..b24c88ce 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -71,6 +71,7 @@ def get_typeof(obj): def program_to_cil_visitor(program): + global __CONCAT_CALLS__, __SUBST_CALLS__ types = [] code = [] built_in_code = [] @@ -120,8 +121,10 @@ def program_to_cil_visitor(program): for data_value in __DATA__.keys()] data.append(CilAST.DataNode('data_abort', 'Abort called from class ')) - cil_program = CilAST.ProgramNode(types, data, code, built_in_code) + cil_program.concat_calls=__CONCAT_CALLS__ + cil_program.substr_calls=__SUBST_CALLS__ + cil_program.in_calls=__IN_CALLS__ # remove_unused_locals(cil_program) # aqui se esta perdiendo un vcall # optimization_locals(cil_program) @@ -141,8 +144,8 @@ def out_int_to_cil(): def in_string_to_cil(): - _str = CilAST.LocalNode('str') - return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self')], [_str], [CilAST.ReadNode(_str), CilAST.ReturnNode(_str)]) + _str = CilAST.LocalNode('read_result') + return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self'), CilAST.ParamNode('calls')], [_str], [CilAST.ReadNode(_str, 'calls'), CilAST.ReturnNode(_str)]) def in_int_to_cil(): @@ -199,12 +202,12 @@ def length_to_cil(): def concat_to_cil(): result = CilAST.LocalNode('concat_result') - return CilAST.FuncNode('String_concat', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_concat', [CilAST.ParamNode('self'), CilAST.ParamNode('x'), CilAST.ParamNode('calls')], [result], [CilAST.ConcatNode('self', 'x', 'calls', result), CilAST.ReturnNode(result)]) def substring_to_cil(): result = CilAST.LocalNode('substring_result') - return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l'), CilAST.ParamNode('calls')], [result], [CilAST.SubStringNode('self', 'i', 'l', 'calls', result), CilAST.ReturnNode(result)]) def abort_to_cil(): @@ -555,7 +558,12 @@ def block_to_cil_visitor(block): return CIL_block(body, value) +__SUBST_CALLS__=1 +__CONCAT_CALLS__=1 +__IN_CALLS__=1 + def func_call_to_cil_visitor(call): + global __SUBST_CALLS__, __CONCAT_CALLS__, __IN_CALLS__ body = [] t = add_local() returned=None @@ -585,10 +593,25 @@ def func_call_to_cil_visitor(call): body.append(CilAST.ArgNode(arg)) result = add_local() + + if call.id =='substr': + body.append(CilAST.ArgNode((__SUBST_CALLS__-1)*4)) + __SUBST_CALLS__+=1 + + if call.id=='in_string': + body.append(CilAST.ArgNode((__IN_CALLS__-1)*4)) + __IN_CALLS__+=1 + + if call.id =='concat': + body.append(CilAST.ArgNode((__CONCAT_CALLS__-1)*4)) + __CONCAT_CALLS__+=1 + + if not call.type: body.append(CilAST.VCAllNode(t, call.id, result)) else: body.append(CilAST.VCAllNode(call.type, call.id, result)) + return CIL_block(body, result) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 87938977..1f9e7ae1 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -36,6 +36,9 @@ def program_to_mips_visitor(program: cil.ProgramNode): __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(f'"{d.val}"')) for d in program.data] __DATA__.append(mips.MIPSDataItem('new_line', mips.AsciizInst(f'"\\n"'))) + __DATA__.append(mips.MIPSDataItem('concat_result', mips.SpaceInst(program.concat_calls*__BUFFSIZE__*2))) + __DATA__.append(mips.MIPSDataItem('substring_result', mips.SpaceInst(program.substr_calls*__BUFFSIZE__))) + __DATA__.append(mips.MIPSDataItem('read_result', mips.SpaceInst(program.in_calls*__BUFFSIZE__))) __DATA__.extend(vt_space_code) data_section = mips.MIPSDataSection(__DATA__) @@ -177,31 +180,42 @@ def read_to_mips_visitor(read: cil.ReadNode): """ offset = CURRENT_FUNCTION.offset[str(read.result)] - __DATA__.append(mips.MIPSDataItem( - read.result, mips.SpaceInst(__BUFFSIZE__))) - + calls_offset=CURRENT_FUNCTION.offset[str(read.calls)] return [ mips.LaInstruction('$a0', str(read.result)), + mips.LwInstruction('$t0', f'{calls_offset}($fp)'), + mips.AdduInstruction('$a0', '$a0','$t0'), mips.LiInstruction('$a1', __BUFFSIZE__), mips.LiInstruction('$v0', 8), mips.SyscallInstruction(), + mips.MIPSLabel('remove_nl_loop'), + mips.LbInstruction('$t0', '($a0)'), + mips.LaInstruction('$t1', 'new_line'), + mips.LbInstruction('$t2', '($t1)'), + mips.BeqInstruction('$t0', '$t2', 'end_loop'), + mips.AdduInstruction('$a0', '$a0', 1), + mips.BInstruction('remove_nl_loop'), + mips.MIPSLabel('end_loop'), + mips.SbInstruction('$zero', '($a0)'), + mips.LaInstruction('$a0', str(read.result)), + mips.LwInstruction('$t0', f'{calls_offset}($fp)'), + mips.AdduInstruction('$a0', '$a0','$t0'), mips.SwInstruction('$a0', f'{offset}($fp)') ] -# TODO: Check def substring_to_mips_visitor(ss: cil.SubStringNode): result_offset=CURRENT_FUNCTION.offset[str(ss.result)] str_offset = CURRENT_FUNCTION.offset[str(ss.str)] i_offset = CURRENT_FUNCTION.offset[str(ss.i)] len_offset = CURRENT_FUNCTION.offset[str(ss.len)] - __DATA__.append(mips.MIPSDataItem( - ss.result.id, mips.SpaceInst(__BUFFSIZE__))) - save_address(ss.result, ss.result.id) + calls_offset= CURRENT_FUNCTION.offset[str(ss.calls)] return [ mips.Comment(str(ss)), mips.LwInstruction('$t0', f'{str_offset}($fp)'), - mips.LaInstruction('$t1', ss.result.id), + mips.LaInstruction('$t5', str(ss.result)), + mips.LwInstruction('$t1', f'{calls_offset}($fp)'), + mips.AdduInstruction('$t1', '$t1', '$t5'), mips.LwInstruction('$t4', f'{i_offset}($fp)'), mips.LwInstruction('$t2', f'{len_offset}($fp)'), mips.AdduInstruction('$t0', '$t0', '$t4'), @@ -214,7 +228,9 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('substring_loop'), mips.MIPSLabel('end_substring_loop'), - mips.LaInstruction('$t1', ss.result.id), + mips.LaInstruction('$t5', str(ss.result)), + mips.LwInstruction('$t1', f'{calls_offset}($fp)'), + mips.AdduInstruction('$t1', '$t1', '$t5'), mips.SwInstruction('$t1', f'{result_offset}($fp)') ] @@ -252,8 +268,6 @@ def length_to_mips_visitor(length: cil.LengthNode): def concat_to_mips_visitor(concat: cil.ConcatNode): - __DATA__.append(mips.MIPSDataItem(str(concat.result), - mips.SpaceInst(2 * __BUFFSIZE__))) result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] b_offset = CURRENT_FUNCTION.offset[str(concat.str_b)] diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index a9fb0c02..6b70f99e 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -61,34 +61,12 @@ main: usw $t0, vt_Main+20 la $t0, IO_in_int usw $t0, vt_Main+24 - la $t0, Main_main + la $t0, Main_pal usw $t0, vt_Main+40 - la $t0, Object_abort - usw $t0, vt_Complex+0 - la $t0, Object_type_name - usw $t0, vt_Complex+4 - la $t0, Object_copy - usw $t0, vt_Complex+8 - la $t0, IO_out_string - usw $t0, vt_Complex+12 - la $t0, IO_out_int - usw $t0, vt_Complex+16 - la $t0, IO_in_string - usw $t0, vt_Complex+20 - la $t0, IO_in_int - usw $t0, vt_Complex+24 - la $t0, Complex_init - usw $t0, vt_Complex+44 - la $t0, Complex_print - usw $t0, vt_Complex+48 - la $t0, Complex_reflect_0 - usw $t0, vt_Complex+52 - la $t0, Complex_reflect_X - usw $t0, vt_Complex+56 - la $t0, Complex_reflect_Y - usw $t0, vt_Complex+60 + la $t0, Main_main + usw $t0, vt_Main+44 # self = ALLOCATE Main ; - li $a0, 12 + li $a0, 16 li $v0, 9 syscall sw $v0, -4($fp) @@ -101,8 +79,8 @@ main: lw $t0, -8($fp) lw $t1, -4($fp) sw $t0, 0($t1) - # local_2 = 12 ; - li $t0, 12 + # local_2 = 16 ; + li $t0, 16 sw $t0, -12($fp) # SETATTR self @size local_2 ; lw $t0, -12($fp) @@ -152,12 +130,28 @@ IO_out_string: IO_in_string: move $fp, $sp subu $sp, $sp, 4 - la $a0, str + la $a0, read_result + lw $t0, 0($fp) + addu $a0, $a0, $t0 li $a1, 1024 li $v0, 8 syscall + remove_nl_loop: + + lb $t0, ($a0) + la $t1, new_line + lb $t2, ($t1) + beq $t0, $t2, end_loop + addu $a0, $a0, 1 + b remove_nl_loop + end_loop: + + sb $zero, ($a0) + la $a0, read_result + lw $t0, 0($fp) + addu $a0, $a0, $t0 sw $a0, -4($fp) - # RETURN str ; + # RETURN read_result ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra @@ -233,8 +227,8 @@ String_concat: subu $sp, $sp, 4 # concat_result = CONCAT self x ; la $t0, concat_result - lw $t1, 4($fp) - lw $t2, 0($fp) + lw $t1, 8($fp) + lw $t2, 4($fp) concat_loop_a: lb $a0, ($t1) @@ -263,10 +257,12 @@ String_substr: move $fp, $sp subu $sp, $sp, 4 # substring_result = SUBSTRING self i l; - lw $t0, 8($fp) - la $t1, substring_result - lw $t4, 4($fp) - lw $t2, 0($fp) + lw $t0, 12($fp) + la $t5, substring_result + lw $t1, 0($fp) + addu $t1, $t1, $t5 + lw $t4, 8($fp) + lw $t2, 4($fp) addu $t0, $t0, $t4 substring_loop: @@ -279,7 +275,9 @@ String_substr: b substring_loop end_substring_loop: - la $t1, substring_result + la $t5, substring_result + lw $t1, 0($fp) + addu $t1, $t1, $t5 sw $t1, -4($fp) # RETURN substring_result ; lw $v0, -4($fp) @@ -348,289 +346,319 @@ Bool_abort: Bool_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_5 = LOAD data_7 ; - la $t0, data_7 + # local_15 = LOAD data_5 ; + la $t0, data_5 sw $t0, -4($fp) - # RETURN local_5 ; + # RETURN local_15 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra Int_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_6 = LOAD data_8 ; - la $t0, data_8 + # local_16 = LOAD data_6 ; + la $t0, data_6 sw $t0, -4($fp) - # RETURN local_6 ; + # RETURN local_16 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra String_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_7 = LOAD data_9 ; - la $t0, data_9 + # local_17 = LOAD data_7 ; + la $t0, data_7 sw $t0, -4($fp) - # RETURN local_7 ; + # RETURN local_17 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra -Main_main: +Main_pal: move $fp, $sp - subu $sp, $sp, 84 - # local_1 = ALLOCATE Complex ; - li $a0, 20 - li $v0, 9 - syscall + subu $sp, $sp, 108 + # local_1 = VCALL String length ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 sw $v0, -8($fp) - la $t0, vt_Complex - sw $t0, 8($v0) - # local_2 = LOAD data_2 ; - la $t0, data_2 + # local_2 = local_1 == 0 ; + lw $t0, -8($fp) + li $t1, 0 + seq $t0, $t0, $t1 sw $t0, -12($fp) - # SETATTR local_1 @type local_2 ; + # local_3 = local_2 ; lw $t0, -12($fp) - lw $t1, -8($fp) - sw $t0, 0($t1) - # local_3 = 20 ; - li $t0, 20 sw $t0, -16($fp) - # SETATTR local_1 @size local_3 ; + # IF local_3 GOTO label_5 ; lw $t0, -16($fp) - lw $t1, -8($fp) - sw $t0, 4($t1) - # local_0 = GETTYPEADDR local_1 ; - lw $t1, -8($fp) - lw $t0, 8($t1) - sw $t0, -4($fp) - # local_4 = VCALL local_0 init ; + bnez $t0, label_5 + # local_5 = VCALL String length ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG local_1 ; - lw $t0, -8($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + jal String_length + addu $sp, $sp, 4 + lw $fp, 0($sp) + lw $ra, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_6 = local_5 == 1 ; + lw $t0, -24($fp) + li $t1, 1 + seq $t0, $t0, $t1 + sw $t0, -28($fp) + # local_7 = local_6 ; + lw $t0, -28($fp) + sw $t0, -32($fp) + # IF local_7 GOTO label_3 ; + lw $t0, -32($fp) + bnez $t0, label_3 + # local_9 = VCALL String substr ; + subu $sp, $sp, 8 + sw $fp, 0($sp) + sw $ra, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 subu $sp, $sp, 4 sw $t0, ($sp) # ARG 1 ; li $t0, 1 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -4($fp) - ulw $t1, 44($t0) - jalr $t1 - addu $sp, $sp, 12 + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -20($fp) - # c = local_4 ; - lw $t0, -20($fp) - sw $t0, -24($fp) - # local_7 = GETTYPEADDR c ; - lw $t1, -24($fp) - lw $t0, 8($t1) - sw $t0, -32($fp) - # local_8 = VCALL local_7 reflect_X ; + sw $v0, -40($fp) + # local_12 = VCALL String length ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG c ; - lw $t0, -24($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -32($fp) - ulw $t1, 56($t0) - jalr $t1 + jal String_length addu $sp, $sp, 4 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -36($fp) - # local_6 = GETTYPEADDR local_8 ; - lw $t1, -36($fp) - lw $t0, 8($t1) - sw $t0, -28($fp) - # local_9 = VCALL local_6 reflect_Y ; + sw $v0, -52($fp) + # local_13 = local_12 - 1 ; + lw $t0, -52($fp) + li $t1, 1 + sub $t0, $t0, $t1 + sw $t0, -56($fp) + # local_14 = VCALL String substr ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG local_8 ; - lw $t0, -36($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -28($fp) - ulw $t1, 60($t0) - jalr $t1 - addu $sp, $sp, 4 + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 4 ; + li $t0, 4 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -40($fp) - # local_10 = GETTYPEADDR c ; - lw $t1, -24($fp) + sw $v0, -60($fp) + # local_15 = local_9 == local_14 ; + lw $t0, -40($fp) + lw $t1, -60($fp) + li $v0, 1 + sw $v0, -64($fp) + equal_loop_1: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_1 + beqz $t2, end_loop_1 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_1 + b end_loop_1 + not_equal_1: + + li $v0, 0 + sw $v0, -64($fp) + end_loop_1: + + # local_16 = local_15 ; + lw $t0, -64($fp) + sw $t0, -68($fp) + # IF local_16 GOTO label_1 ; + lw $t0, -68($fp) + bnez $t0, label_1 + # local_24 = 0 ; + li $t0, 0 + sw $t0, -100($fp) + # GOTO label_2 ; + b label_2 + # LABEL label_1 ; + label_1: + + # local_17 = GETTYPEADDR self ; + lw $t1, 4($fp) lw $t0, 8($t1) - sw $t0, -44($fp) - # local_11 = VCALL local_10 reflect_0 ; + sw $t0, -72($fp) + # local_20 = VCALL String length ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG c ; - lw $t0, -24($fp) + # ARG s ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -44($fp) - ulw $t1, 52($t0) - jalr $t1 + jal String_length addu $sp, $sp, 4 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -48($fp) - # local_12 = local_9 == local_11 ; - lw $t0, -40($fp) - lw $t1, -48($fp) - seq $t0, $t0, $t1 - sw $t0, -52($fp) - # local_13 = local_12 ; - lw $t0, -52($fp) - sw $t0, -56($fp) - # IF local_13 GOTO label_1 ; - lw $t0, -56($fp) - bnez $t0, label_1 - # local_17 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -72($fp) - # local_18 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -76($fp) - # local_19 = VCALL local_17 out_string ; + sw $v0, -84($fp) + # local_21 = local_20 - 2 ; + lw $t0, -84($fp) + li $t1, 2 + sub $t0, $t0, $t1 + sw $t0, -88($fp) + # local_22 = VCALL String substr ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG self ; + # ARG s ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_18 ; - lw $t0, -76($fp) + # ARG 1 ; + li $t0, 1 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -72($fp) - ulw $t1, 12($t0) - jalr $t1 - addu $sp, $sp, 8 + # ARG local_21 ; + lw $t0, -88($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 8 ; + li $t0, 8 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -80($fp) - # local_20 = local_19 ; - lw $t0, -80($fp) - sw $t0, -84($fp) - # GOTO label_2 ; - b label_2 - # LABEL label_1 ; - label_1: - - # local_14 = GETTYPEADDR self ; - lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -60($fp) - # local_15 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -64($fp) - # local_16 = VCALL local_14 out_string ; + sw $v0, -92($fp) + # local_23 = VCALL local_17 pal ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) # ARG self ; - lw $t0, 0($fp) + lw $t0, 4($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_15 ; - lw $t0, -64($fp) + # ARG local_22 ; + lw $t0, -92($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -60($fp) - ulw $t1, 12($t0) + lw $t0, -72($fp) + ulw $t1, 40($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -68($fp) - # local_20 = local_16 ; - lw $t0, -68($fp) - sw $t0, -84($fp) + sw $v0, -96($fp) + # local_24 = local_23 ; + lw $t0, -96($fp) + sw $t0, -100($fp) # LABEL label_2 ; label_2: - # RETURN local_20 ; - lw $v0, -84($fp) - addu $sp, $sp, 84 + # local_25 = local_24 ; + lw $t0, -100($fp) + sw $t0, -104($fp) + # GOTO label_4 ; + b label_4 + # LABEL label_3 ; + label_3: + + # local_25 = 1 ; + li $t0, 1 + sw $t0, -104($fp) + # LABEL label_4 ; + label_4: + + # local_26 = local_25 ; + lw $t0, -104($fp) + sw $t0, -108($fp) + # GOTO label_6 ; + b label_6 + # LABEL label_5 ; + label_5: + + # local_26 = 1 ; + li $t0, 1 + sw $t0, -108($fp) + # LABEL label_6 ; + label_6: + + # RETURN local_26 ; + lw $v0, -108($fp) + addu $sp, $sp, 108 jr $ra -Complex_init: +Main_main: move $fp, $sp - subu $sp, $sp, 24 - # local_0 = GETATTR self x ; - lw $t0, 8($fp) - lw $t1, 12($t0) - sw $t1, -4($fp) - # local_1 = local_0 == a ; + subu $sp, $sp, 60 + # local_0 = ~ 1 + li $t0, 1 + not $t0, $t0 + sw $t0, -4($fp) + # SETATTR self i local_0 ; lw $t0, -4($fp) - lw $t1, 4($fp) - seq $t0, $t0, $t1 - sw $t0, -8($fp) - # local_2 = local_1 ; - lw $t0, -8($fp) - sw $t0, -12($fp) - # local_3 = GETATTR self y ; - lw $t0, 8($fp) - lw $t1, 16($t0) - sw $t1, -16($fp) - # local_4 = local_3 == b ; - lw $t0, -16($fp) lw $t1, 0($fp) - seq $t0, $t0, $t1 - sw $t0, -20($fp) - # local_5 = local_4 ; - lw $t0, -20($fp) - sw $t0, -24($fp) - # RETURN self ; - lw $v0, 8($fp) - addu $sp, $sp, 24 - jr $ra -Complex_print: - move $fp, $sp - subu $sp, $sp, 76 - # local_0 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -4($fp) - # local_1 = local_0 == 0 ; - lw $t0, -4($fp) - li $t1, 0 - seq $t0, $t0, $t1 - sw $t0, -8($fp) - # local_2 = local_1 ; - lw $t0, -8($fp) - sw $t0, -12($fp) - # IF local_2 GOTO label_3 ; - lw $t0, -12($fp) - bnez $t0, label_3 - # local_9 = GETTYPEADDR self ; + sw $t0, 12($t1) + # local_1 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -40($fp) - # local_10 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -44($fp) - # local_11 = VCALL local_9 out_int ; + sw $t0, -8($fp) + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # local_3 = VCALL local_1 out_string ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) @@ -638,117 +666,112 @@ Complex_print: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_10 ; - lw $t0, -44($fp) + # ARG local_2 ; + lw $t0, -12($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -40($fp) - ulw $t1, 16($t0) + lw $t0, -8($fp) + ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -48($fp) - # local_8 = GETTYPEADDR local_11 ; - lw $t1, -48($fp) + sw $v0, -16($fp) + # local_4 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -36($fp) - # local_12 = LOAD data_5 ; - la $t0, data_5 - sw $t0, -52($fp) - # local_13 = VCALL local_8 out_string ; + sw $t0, -20($fp) + # local_5 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_6 = VCALL local_5 in_string ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG local_11 ; - lw $t0, -48($fp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_12 ; - lw $t0, -52($fp) + # ARG 0 ; + li $t0, 0 subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -36($fp) - ulw $t1, 12($t0) + lw $t0, -24($fp) + ulw $t1, 20($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -56($fp) - # local_7 = GETTYPEADDR local_13 ; - lw $t1, -56($fp) - lw $t0, 8($t1) - sw $t0, -32($fp) - # local_14 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -60($fp) - # local_15 = VCALL local_7 out_int ; + sw $v0, -28($fp) + # local_7 = VCALL local_4 pal ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG local_13 ; - lw $t0, -56($fp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_14 ; - lw $t0, -60($fp) + # ARG local_6 ; + lw $t0, -28($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -32($fp) - ulw $t1, 16($t0) + lw $t0, -20($fp) + ulw $t1, 40($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -64($fp) - # local_6 = GETTYPEADDR local_15 ; - lw $t1, -64($fp) + sw $v0, -32($fp) + # IF local_7 GOTO label_7 ; + lw $t0, -32($fp) + bnez $t0, label_7 + # local_11 = GETTYPEADDR self ; + lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -28($fp) - # local_16 = LOAD data_6 ; - la $t0, data_6 - sw $t0, -68($fp) - # local_17 = VCALL local_6 out_string ; + sw $t0, -48($fp) + # local_12 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -52($fp) + # local_13 = VCALL local_11 out_string ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) - # ARG local_15 ; - lw $t0, -64($fp) + # ARG self ; + lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_16 ; - lw $t0, -68($fp) + # ARG local_12 ; + lw $t0, -52($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -28($fp) + lw $t0, -48($fp) ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -72($fp) - # local_18 = local_17 ; - lw $t0, -72($fp) - sw $t0, -76($fp) - # GOTO label_4 ; - b label_4 - # LABEL label_3 ; - label_3: + sw $v0, -56($fp) + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # GOTO label_8 ; + b label_8 + # LABEL label_7 ; + label_7: - # local_3 = GETTYPEADDR self ; + # local_8 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -16($fp) - # local_4 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -20($fp) - # local_5 = VCALL local_3 out_int ; + sw $t0, -36($fp) + # local_9 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -40($fp) + # local_10 = VCALL local_8 out_string ; subu $sp, $sp, 8 sw $fp, 0($sp) sw $ra, 4($sp) @@ -756,169 +779,66 @@ Complex_print: lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_4 ; - lw $t0, -20($fp) + # ARG local_9 ; + lw $t0, -40($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -16($fp) - ulw $t1, 16($t0) + lw $t0, -36($fp) + ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 lw $fp, 0($sp) lw $ra, 4($sp) addu $sp, $sp, 8 - sw $v0, -24($fp) - # local_18 = local_5 ; - lw $t0, -24($fp) - sw $t0, -76($fp) - # LABEL label_4 ; - label_4: + sw $v0, -44($fp) + # local_14 = local_10 ; + lw $t0, -44($fp) + sw $t0, -60($fp) + # LABEL label_8 ; + label_8: - # RETURN local_18 ; - lw $v0, -76($fp) - addu $sp, $sp, 76 - jr $ra -Complex_reflect_0: - move $fp, $sp - subu $sp, $sp, 40 - # local_0 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -4($fp) - # local_1 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -8($fp) - # local_2 = ~ local_1 - not $t0, $t0 - sw $t0, -12($fp) - # local_3 = local_0 == local_2 ; - lw $t0, -4($fp) - lw $t1, -12($fp) - seq $t0, $t0, $t1 - sw $t0, -16($fp) - # local_4 = local_3 ; - lw $t0, -16($fp) - sw $t0, -20($fp) - # local_5 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -24($fp) - # local_6 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -28($fp) - # local_7 = ~ local_6 - not $t0, $t0 - sw $t0, -32($fp) - # local_8 = local_5 == local_7 ; - lw $t0, -24($fp) - lw $t1, -32($fp) - seq $t0, $t0, $t1 - sw $t0, -36($fp) - # local_9 = local_8 ; - lw $t0, -36($fp) - sw $t0, -40($fp) - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 40 - jr $ra -Complex_reflect_X: - move $fp, $sp - subu $sp, $sp, 20 - # local_0 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -4($fp) - # local_1 = GETATTR self y ; - lw $t0, 0($fp) - lw $t1, 16($t0) - sw $t1, -8($fp) - # local_2 = ~ local_1 - not $t0, $t0 - sw $t0, -12($fp) - # local_3 = local_0 == local_2 ; - lw $t0, -4($fp) - lw $t1, -12($fp) - seq $t0, $t0, $t1 - sw $t0, -16($fp) - # local_4 = local_3 ; - lw $t0, -16($fp) - sw $t0, -20($fp) - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 20 - jr $ra -Complex_reflect_Y: - move $fp, $sp - subu $sp, $sp, 20 - # local_0 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -4($fp) - # local_1 = GETATTR self x ; - lw $t0, 0($fp) - lw $t1, 12($t0) - sw $t1, -8($fp) - # local_2 = ~ local_1 - not $t0, $t0 - sw $t0, -12($fp) - # local_3 = local_0 == local_2 ; - lw $t0, -4($fp) - lw $t1, -12($fp) - seq $t0, $t0, $t1 - sw $t0, -16($fp) - # local_4 = local_3 ; - lw $t0, -16($fp) - sw $t0, -20($fp) - # RETURN self ; - lw $v0, 0($fp) - addu $sp, $sp, 20 + # RETURN local_14 ; + lw $v0, -60($fp) + addu $sp, $sp, 60 jr $ra .data data_1: .asciiz "Main" data_2: - .asciiz "Complex" + .asciiz "enter a string\n" data_3: - .asciiz "=)\n" + .asciiz "that was a palindrome\n" data_4: - .asciiz "=(\n" + .asciiz "that was not a palindrome\n" data_5: - .asciiz "+" - data_6: - .asciiz "I" - data_7: .asciiz "Bool" - data_8: + data_6: .asciiz "Int" - data_9: + data_7: .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: .asciiz "\n" + concat_result: + .space 2048 + substring_result: + .space 4096 + read_result: + .space 2048 vt_Object: - .space 200 + .space 152 vt_IO: - .space 200 + .space 152 vt_Int: - .space 200 + .space 152 vt_String: - .space 200 + .space 152 vt_Bool: - .space 200 + .space 152 vt_Main: - .space 200 - vt_Complex: - .space 200 - str: - .space 1024 - concat_result: - .space 2048 - substring_result: - .space 1024 + .space 152 abort_String: .asciiz "String" abort_Int: From 65099aa4e3bd83127de5ab49eed627801622b292 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 2 Dec 2020 12:56:28 -0500 Subject: [PATCH 417/435] fixing not nul terminated substring --- src/code_generation/CIL/cil.py | 20 +++++++++++++------- src/code_generation/MIPS/ast.py | 5 +++++ src/code_generation/MIPS/mips.py | 1 + src/code_generation/MIPS/test.asm | 15 ++++++++------- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index b24c88ce..038ca849 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -122,9 +122,9 @@ def program_to_cil_visitor(program): data.append(CilAST.DataNode('data_abort', 'Abort called from class ')) cil_program = CilAST.ProgramNode(types, data, code, built_in_code) - cil_program.concat_calls=__CONCAT_CALLS__ - cil_program.substr_calls=__SUBST_CALLS__ - cil_program.in_calls=__IN_CALLS__ + cil_program.concat_calls=__CONCAT_CALLS__-1 + cil_program.substr_calls=__SUBST_CALLS__-1 + cil_program.in_calls=__IN_CALLS__-1 # remove_unused_locals(cil_program) # aqui se esta perdiendo un vcall # optimization_locals(cil_program) @@ -297,7 +297,13 @@ def case_to_cil_visitor(case): for i, branch in enumerate(case.case_list): predicate = add_local() - body.append(CilAST.NotEqInstanceNode(t, branch.type, predicate)) + aux_predicate=add_local() + str_addr = add_str_data(branch.type) + str_id, need_load = add_data_local(str_addr) + if need_load: + body.append(CilAST.LoadNode(str_addr, str_id)) + body.append(CilAST.EqStringNode(t, str_id, aux_predicate)), + body.append(CilAST.EqNode(aux_predicate, 0, predicate)), body.append(CilAST.ConditionalGotoNode(predicate, labels[i])) val = add_local(branch.id) body.append(CilAST.AssignNode(val, expr_cil.value)) @@ -595,15 +601,15 @@ def func_call_to_cil_visitor(call): result = add_local() if call.id =='substr': - body.append(CilAST.ArgNode((__SUBST_CALLS__-1)*4)) + body.append(CilAST.ArgNode((__SUBST_CALLS__-1)*1024)) __SUBST_CALLS__+=1 if call.id=='in_string': - body.append(CilAST.ArgNode((__IN_CALLS__-1)*4)) + body.append(CilAST.ArgNode((__IN_CALLS__-1)*1024)) __IN_CALLS__+=1 if call.id =='concat': - body.append(CilAST.ArgNode((__CONCAT_CALLS__-1)*4)) + body.append(CilAST.ArgNode((__CONCAT_CALLS__-1)*1024)) __CONCAT_CALLS__+=1 diff --git a/src/code_generation/MIPS/ast.py b/src/code_generation/MIPS/ast.py index 2e54eb4c..ddcc609a 100644 --- a/src/code_generation/MIPS/ast.py +++ b/src/code_generation/MIPS/ast.py @@ -162,6 +162,11 @@ def __init__(self, *arguments): class UswInstruction(Instruction): def __init__(self, *arguments): super().__init__('usw', *arguments) + +class BreakInstruction(Instruction): + def __init__(self, *arguments): + super().__init__('break', *arguments) + diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 1f9e7ae1..50c79983 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -228,6 +228,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('substring_loop'), mips.MIPSLabel('end_substring_loop'), + mips.SbInstruction('$zero', '($t1)'), mips.LaInstruction('$t5', str(ss.result)), mips.LwInstruction('$t1', f'{calls_offset}($fp)'), mips.AdduInstruction('$t1', '$t1', '$t5'), diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 6b70f99e..4ab958b2 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -275,6 +275,7 @@ String_substr: b substring_loop end_substring_loop: + sb $zero, ($t1) la $t5, substring_result lw $t1, 0($fp) addu $t1, $t1, $t5 @@ -487,8 +488,8 @@ Main_pal: li $t0, 1 subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 4 ; - li $t0, 4 + # ARG 1024 ; + li $t0, 1024 subu $sp, $sp, 4 sw $t0, ($sp) jal String_substr @@ -572,8 +573,8 @@ Main_pal: lw $t0, -88($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 8 ; - li $t0, 8 + # ARG 2048 ; + li $t0, 2048 subu $sp, $sp, 4 sw $t0, ($sp) jal String_substr @@ -822,11 +823,11 @@ Main_main: new_line: .asciiz "\n" concat_result: - .space 2048 + .space 0 substring_result: - .space 4096 + .space 3072 read_result: - .space 2048 + .space 1024 vt_Object: .space 152 vt_IO: From f3caf08d5c94c2938e16ef53f42dc896421656e8 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 2 Dec 2020 13:38:37 -0500 Subject: [PATCH 418/435] Fix Not Equal to mips visitor *Remove parsetab from git --- .gitignore | 1 + src/code_generation/MIPS/mips.py | 9 ++-- src/lexer_parser/parsetab.py | 84 -------------------------------- 3 files changed, 5 insertions(+), 89 deletions(-) delete mode 100644 src/lexer_parser/parsetab.py diff --git a/.gitignore b/.gitignore index b63045ff..4726e6e2 100644 --- a/.gitignore +++ b/.gitignore @@ -412,3 +412,4 @@ dmypy.json .vscode *.cil *.mips +/src/lexer_parser/parsetab.py \ No newline at end of file diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 50c79983..e5c00330 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -112,7 +112,6 @@ def instruction_to_mips_visitor(inst): """ Resolves visitor for each type """ - return __visitors__[type(inst)](inst) try: return __visitors__[type(inst)](inst) except KeyError: @@ -594,12 +593,12 @@ def not_eq_to_mips_visitor(eq:cil.EqNode): ] def not_eq_instance_to_mips_visitor(noteq:cil.NotEqNode): - y_offset = CURRENT_FUNCTION.offset[str(eq.left)] - z_offset = CURRENT_FUNCTION.offset[str(eq.right)] - x_offset = CURRENT_FUNCTION.offset[str(eq.result)] + y_offset = CURRENT_FUNCTION.offset[str(noteq.left)] + z_offset = CURRENT_FUNCTION.offset[str(noteq.right)] + x_offset = CURRENT_FUNCTION.offset[str(noteq.result)] return [ - mips.Comment(str(eq)), + mips.Comment(str(noteq)), mips.LwInstruction('$t0', f'{y_offset}($fp)'), mips.LwInstruction('$t1', '($t0)'), mips.LwInstruction('$t0', f'{z_offset}($fp)'), diff --git a/src/lexer_parser/parsetab.py b/src/lexer_parser/parsetab.py deleted file mode 100644 index 9f87869e..00000000 --- a/src/lexer_parser/parsetab.py +++ /dev/null @@ -1,84 +0,0 @@ - -# parsetab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.8' - -_lr_method = 'LALR' - -_lr_signature = '48F1963BAC8E26D4136BDB65D37A6EF9' - -_lr_action_items = {'CLASS':([0,5,],[4,4,]),'$end':([1,2,5,7,],[0,-1,-4,-3,]),'SEMICOLON':([3,11,12,16,24,36,37,38,47,48,50,51,52,75,76,77,78,80,82,89,90,91,92,93,94,95,101,102,105,109,112,121,125,126,128,134,135,136,],[5,17,18,-5,-11,-6,-48,-10,-37,-47,-50,-51,-52,-33,-34,-35,-49,103,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,122,-19,-21,-12,-24,-20,-23,-42,]),'TYPE':([4,9,19,32,49,55,59,123,],[6,15,24,54,78,81,87,130,]),'OBRACKET':([6,15,31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,81,96,99,100,103,104,106,108,124,127,133,],[8,21,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,104,53,53,53,53,53,53,53,53,53,53,]),'INHERITS':([6,],[9,]),'ID':([8,17,18,20,21,31,34,39,40,41,42,43,44,45,46,53,57,58,60,61,62,63,64,65,66,67,96,97,98,99,100,103,104,106,107,108,122,124,127,133,],[14,14,14,25,14,37,25,70,37,37,37,37,37,37,37,37,37,37,88,37,37,37,37,37,37,37,37,70,113,37,37,37,37,37,119,37,113,37,37,37,]),'CBRACKET':([8,10,13,17,18,21,22,23,30,37,47,48,50,51,52,75,76,77,78,79,82,89,90,91,92,93,94,95,101,102,103,105,109,116,117,121,125,128,134,135,],[-2,16,-9,-2,-2,-2,-7,-8,36,-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,102,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-55,-25,-18,-54,126,-19,-21,-24,-20,-23,]),'COLON':([14,25,33,70,113,],[19,32,55,19,123,]),'OPAREN':([14,31,37,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,88,96,99,100,103,104,106,108,119,124,127,133,],[20,43,58,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,108,43,43,43,43,43,43,43,127,43,43,43,]),'CPAREN':([20,26,27,28,29,35,37,47,48,50,51,52,54,56,58,74,75,76,77,78,82,83,84,85,86,89,90,91,92,93,94,95,101,102,105,108,109,118,120,121,125,127,128,132,134,135,],[-2,33,-13,-14,-2,-16,-48,-37,-47,-50,-51,-52,-17,-15,-2,101,-33,-34,-35,-49,-22,105,-43,-44,-46,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-2,-18,-45,128,-19,-21,-2,-24,135,-20,-23,]),'ASSIGN':([24,37,],[31,57,]),'COMMA':([24,29,37,38,47,48,50,51,52,54,69,75,76,77,78,82,86,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-11,34,-48,-10,-37,-47,-50,-51,-52,-17,97,-33,-34,-35,-49,-22,106,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'IN':([24,37,38,47,48,50,51,52,68,69,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,110,121,125,128,134,135,],[-11,-48,-10,-37,-47,-50,-51,-52,96,-39,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-38,-19,-21,-24,-20,-23,]),'LET':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'CASE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'IF':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'WHILE':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,]),'NOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'ISVOID':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'LNOT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'INT':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'NEW':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'BOOL':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'STRING':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'AT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,59,-37,-47,-50,-51,-52,59,59,59,59,-33,-34,-35,-49,59,59,59,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,59,59,59,59,-19,-21,-24,59,-20,-23,59,]),'DOT':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,87,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,60,-37,-47,-50,-51,-52,60,60,60,60,60,60,60,-49,60,60,60,107,60,60,60,60,60,60,60,-36,-53,-25,60,60,60,60,-19,-21,-24,60,-20,-23,60,]),'PLUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,61,-37,-47,-50,-51,-52,61,61,61,61,61,61,61,-49,61,61,61,-26,-27,-28,-29,61,61,61,-36,-53,-25,61,61,61,61,-19,-21,-24,61,-20,-23,61,]),'MINUS':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,62,-37,-47,-50,-51,-52,62,62,62,62,62,62,62,-49,62,62,62,-26,-27,-28,-29,62,62,62,-36,-53,-25,62,62,62,62,-19,-21,-24,62,-20,-23,62,]),'STAR':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,63,-37,-47,-50,-51,-52,63,63,63,63,63,63,63,-49,63,63,63,63,63,-28,-29,63,63,63,-36,-53,-25,63,63,63,63,-19,-21,-24,63,-20,-23,63,]),'DIV':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,64,-37,-47,-50,-51,-52,64,64,64,64,64,64,64,-49,64,64,64,64,64,-28,-29,64,64,64,-36,-53,-25,64,64,64,64,-19,-21,-24,64,-20,-23,64,]),'LOWER':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,65,-37,-47,-50,-51,-52,65,65,65,65,65,65,65,-49,65,65,65,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,65,65,65,65,-19,-21,-24,65,-20,-23,65,]),'LOWEREQ':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,66,-37,-47,-50,-51,-52,66,66,66,66,66,66,66,-49,66,66,66,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,66,66,66,66,-19,-21,-24,66,-20,-23,66,]),'EQUAL':([37,38,47,48,50,51,52,71,72,73,74,75,76,77,78,80,82,86,89,90,91,92,93,94,95,101,102,105,109,114,115,117,121,125,128,131,134,135,136,],[-48,67,-37,-47,-50,-51,-52,67,67,67,67,67,67,67,-49,67,67,67,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,67,67,67,67,-19,-21,-24,67,-20,-23,67,]),'OF':([37,47,48,50,51,52,71,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,98,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'THEN':([37,47,48,50,51,52,72,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,99,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'LOOP':([37,47,48,50,51,52,73,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,100,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,-20,-23,]),'ELSE':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,114,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,124,-19,-21,-24,-20,-23,]),'POOL':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,115,121,125,128,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,125,-19,-21,-24,-20,-23,]),'FI':([37,47,48,50,51,52,75,76,77,78,82,89,90,91,92,93,94,95,101,102,105,109,121,125,128,131,134,135,],[-48,-37,-47,-50,-51,-52,-33,-34,-35,-49,-22,-26,-27,-28,-29,-30,-31,-32,-36,-53,-25,-18,-19,-21,-24,134,-20,-23,]),'ESAC':([111,122,129,],[121,-41,-40,]),'ARROW':([130,],[133,]),} - -_lr_action = {} -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = {} - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'program':([0,],[1,]),'class_list':([0,5,],[2,7,]),'def_class':([0,5,],[3,3,]),'feature_list':([8,17,18,21,],[10,22,23,30,]),'def_attr':([8,17,18,21,39,97,],[11,11,11,11,69,69,]),'def_func':([8,17,18,21,],[12,12,12,12,]),'empty':([8,17,18,20,21,29,58,108,127,],[13,13,13,28,13,35,85,85,85,]),'params':([20,],[26,]),'param_list':([20,34,],[27,56,]),'param':([20,34,],[29,29,]),'expr':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[38,71,72,73,74,75,76,77,80,82,86,89,90,91,92,93,94,95,109,114,115,80,117,86,86,131,86,136,]),'atom':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,]),'block':([31,40,41,42,43,44,45,46,53,57,58,61,62,63,64,65,66,67,96,99,100,103,104,106,108,124,127,133,],[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,]),'let_attrs':([39,97,],[68,110,]),'block_list':([53,103,],[79,116,]),'arg_list':([58,108,127,],[83,120,132,]),'arg_list_ne':([58,106,108,127,],[84,118,84,84,]),'case_list':([98,122,],[111,129,]),'case_elem':([98,122,],[112,112,]),} - -_lr_goto = {} -for _k, _v in _lr_goto_items.items(): - for _x, _y in zip(_v[0], _v[1]): - if not _x in _lr_goto: _lr_goto[_x] = {} - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> program","S'",1,None,None,None), - ('program -> class_list','program',1,'p_program','parser.py',26), - ('empty -> ','empty',0,'p_empty','parser.py',31), - ('class_list -> def_class SEMICOLON class_list','class_list',3,'p_class_list','parser.py',36), - ('class_list -> def_class SEMICOLON','class_list',2,'p_class_list','parser.py',37), - ('def_class -> CLASS TYPE OBRACKET feature_list CBRACKET','def_class',5,'p_def_class','parser.py',46), - ('def_class -> CLASS TYPE INHERITS TYPE OBRACKET feature_list CBRACKET','def_class',7,'p_def_class','parser.py',47), - ('feature_list -> def_attr SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',57), - ('feature_list -> def_func SEMICOLON feature_list','feature_list',3,'p_feature_list','parser.py',58), - ('feature_list -> empty','feature_list',1,'p_feature_list','parser.py',59), - ('def_attr -> ID COLON TYPE ASSIGN expr','def_attr',5,'p_def_attr_declaration','parser.py',67), - ('def_attr -> ID COLON TYPE','def_attr',3,'p_def_attr_declaration','parser.py',68), - ('def_func -> ID OPAREN params CPAREN COLON TYPE OBRACKET expr CBRACKET','def_func',9,'p_def_func','parser.py',78), - ('params -> param_list','params',1,'p_params_ne','parser.py',84), - ('params -> empty','params',1,'p_params_e','parser.py',89), - ('param_list -> param COMMA param_list','param_list',3,'p_param_list','parser.py',94), - ('param_list -> param empty','param_list',2,'p_param_list','parser.py',95), - ('param -> ID COLON TYPE','param',3,'p_param','parser.py',103), - ('expr -> LET let_attrs IN expr','expr',4,'p_expr_flow','parser.py',109), - ('expr -> CASE expr OF case_list ESAC','expr',5,'p_expr_flow','parser.py',110), - ('expr -> IF expr THEN expr ELSE expr FI','expr',7,'p_expr_flow','parser.py',111), - ('expr -> WHILE expr LOOP expr POOL','expr',5,'p_expr_flow','parser.py',112), - ('expr -> ID ASSIGN expr','expr',3,'p_expr_assign','parser.py',127), - ('expr -> expr AT TYPE DOT ID OPAREN arg_list CPAREN','expr',8,'p_expr_func_all','parser.py',133), - ('expr -> expr DOT ID OPAREN arg_list CPAREN','expr',6,'p_expr_func_all','parser.py',134), - ('expr -> ID OPAREN arg_list CPAREN','expr',4,'p_expr_func_all','parser.py',135), - ('expr -> expr PLUS expr','expr',3,'p_expr_operators_binary','parser.py',159), - ('expr -> expr MINUS expr','expr',3,'p_expr_operators_binary','parser.py',160), - ('expr -> expr STAR expr','expr',3,'p_expr_operators_binary','parser.py',161), - ('expr -> expr DIV expr','expr',3,'p_expr_operators_binary','parser.py',162), - ('expr -> expr LOWER expr','expr',3,'p_expr_operators_binary','parser.py',163), - ('expr -> expr LOWEREQ expr','expr',3,'p_expr_operators_binary','parser.py',164), - ('expr -> expr EQUAL expr','expr',3,'p_expr_operators_binary','parser.py',165), - ('expr -> NOT expr','expr',2,'p_expr_operators_unary','parser.py',185), - ('expr -> ISVOID expr','expr',2,'p_expr_operators_unary','parser.py',186), - ('expr -> LNOT expr','expr',2,'p_expr_operators_unary','parser.py',187), - ('expr -> OPAREN expr CPAREN','expr',3,'p_expr_group','parser.py',199), - ('expr -> atom','expr',1,'p_expr_atom','parser.py',204), - ('let_attrs -> def_attr COMMA let_attrs','let_attrs',3,'p_let_attrs','parser.py',209), - ('let_attrs -> def_attr','let_attrs',1,'p_let_attrs','parser.py',210), - ('case_list -> case_elem SEMICOLON case_list','case_list',3,'p_case_list','parser.py',218), - ('case_list -> case_elem SEMICOLON','case_list',2,'p_case_list','parser.py',219), - ('case_elem -> ID COLON TYPE ARROW expr','case_elem',5,'p_case_elem','parser.py',227), - ('arg_list -> arg_list_ne','arg_list',1,'p_arg_list','parser.py',233), - ('arg_list -> empty','arg_list',1,'p_arg_list','parser.py',234), - ('arg_list_ne -> expr COMMA arg_list_ne','arg_list_ne',3,'p_arg_list_ne','parser.py',239), - ('arg_list_ne -> expr','arg_list_ne',1,'p_arg_list_ne','parser.py',240), - ('atom -> INT','atom',1,'p_atom_int','parser.py',248), - ('atom -> ID','atom',1,'p_atom_id','parser.py',254), - ('atom -> NEW TYPE','atom',2,'p_atom_new','parser.py',260), - ('atom -> block','atom',1,'p_atom_block','parser.py',266), - ('atom -> BOOL','atom',1,'p_atom_bool','parser.py',271), - ('atom -> STRING','atom',1,'p_atom_atring','parser.py',277), - ('block -> OBRACKET block_list CBRACKET','block',3,'p_block','parser.py',283), - ('block_list -> expr SEMICOLON block_list','block_list',3,'p_block_list','parser.py',288), - ('block_list -> expr SEMICOLON','block_list',2,'p_block_list','parser.py',289), -] From 47afb43572236b9ce8f764403a6a0d005a9a0ee4 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Wed, 2 Dec 2020 18:36:05 -0500 Subject: [PATCH 419/435] fixinf concat nul terminated --- src/code_generation/MIPS/mips.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 50c79983..500732a1 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -293,6 +293,7 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t2', '$t2', 1), mips.BInstruction('concat_loop_b'), mips.MIPSLabel('end_concat'), + mips.SbInstruction('$zero', '($t0)'), mips.LaInstruction('$t0', str(concat.result)), mips.SwInstruction('$t0', f'{result_offset}($fp)') ] @@ -685,12 +686,12 @@ def not_to_mips_visitor(notn: cil.NotNode): instructions.append(mips.LiInstruction('$t0', notn.value)) else: y_offset = CURRENT_FUNCTION.offset[str(notn.value)] - mips.LwInstruction('$t0', f'{y_offset}($fp)') + instructions.append(mips.LwInstruction('$t0', f'{y_offset}($fp)')) x_offset = CURRENT_FUNCTION.offset[str(notn.result)] return instructions + [ - mips.NotInstruction('$t0', '$t0'), + mips.NegInstruction('$t0', '$t0'), mips.SwInstruction('$t0', f'{x_offset}($fp)') ] From f76d0aa4afa6694db7cfcd1ec767b4ee44244627 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Thu, 3 Dec 2020 09:07:18 -0500 Subject: [PATCH 420/435] adding init function to types --- src/code_generation/CIL/cil.py | 70 +- src/code_generation/MIPS/test.asm | 6993 +++++++++++++++++++++++++++-- 2 files changed, 6682 insertions(+), 381 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 038ca849..73b2d298 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -90,6 +90,9 @@ def program_to_cil_visitor(program): for met in value.get_all_self_methods(): _type.methods[met] = t + + if t not in ('SELF_TYPE', 'Object', 'IO', 'String', 'Bool', 'Int'): + _type.methods['__init__']=t types.append(_type) @@ -110,6 +113,7 @@ def program_to_cil_visitor(program): # completing .CODE and .DATA sections for c in program.classes: + code.append(init_instance(c.type, c.parent_type)) for f in c.feature_nodes: if type(f) == CoolAST.DefFuncNode: fun = func_to_cil_visitor(c.type, f) @@ -134,7 +138,6 @@ def program_to_cil_visitor(program): def built_in_to_cil(): return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil(), abort_string_to_cil(), abort_int_to_cil(), abort_bool_to_cil(), type_name_bool_to_cil(), type_name_int_to_cil(), type_name_string_to_cil()] - def out_string_to_cil(): return CilAST.FuncNode('IO_out_string', [CilAST.ParamNode('self'), CilAST.ParamNode('str')], [], [CilAST.PrintNode('str'), CilAST.ReturnNode('self')]) @@ -449,25 +452,23 @@ def id_to_cil_visitor(id): return CIL_block([], val) except: return CIL_block([], id.id) - - -def new_to_cil_visitor(new_node, value_id=None): - global __CURRENT_TYPE__ - if value_id: - value = add_local(value_id) - else: - value = add_local() - t = new_node.type + +def init_instance(t, parent=None): + global __CURRENT_TYPE__, __LOCALS__, __DATA_LOCALS__, __TYPEOF__ + + __LOCALS__ = {} + __DATA_LOCALS__ = {} + __TYPEOF__ = {} + __CURRENT_TYPE__ = t + value = add_local() body = [] - if t == 'SELF_TYPE': - t, need_typeof = get_typeof(__CURRENT_TYPE__) - if need_typeof: - body.append(CilAST.TypeOfNode(t, __CURRENT_TYPE__)) - - body.append(CilAST.AllocateNode(t, value)) init_attr = CT.TypesByName[t].get_all_attributes() + if parent and parent not in ('Object', 'IO'): + parent_init=add_local() + body.append(CilAST.ArgNode('self')) + body.append(CilAST.VCAllNode(parent, '__init__', parent_init)) # t_data = add_str_data(t) t_local = add_local() @@ -475,20 +476,43 @@ def new_to_cil_visitor(new_node, value_id=None): # body.append(CilAST.LoadNode(t_data, t_local)) - body.append(CilAST.SetAttrNode(value, '@type', t_local)) + body.append(CilAST.SetAttrNode('self', '@type', t_local)) body.append(CilAST.AssignNode(size_local, (len(init_attr)+3)*4)) - body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) - - old_current_type = __CURRENT_TYPE__ - __CURRENT_TYPE__ = new_node.type + body.append(CilAST.SetAttrNode('self', 'size', size_local, 1)) for index, attr in enumerate(init_attr, 3): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) body += attr_cil.body body.append(CilAST.SetAttrNode( - value, attr.id, attr_cil.value, index)) - __CURRENT_TYPE__ = old_current_type + 'self', attr.id, attr_cil.value, index)) + + body.append(CilAST.ReturnNode(value)) + + return CilAST.FuncNode(f'{t}___init__', [CilAST.ParamNode('self')], [__LOCALS__[k] for k in __LOCALS__.keys()], body) + + + + +def new_to_cil_visitor(new_node, val_id=None): + if val_id: + value=add_local(val_id) + else: + value=add_local() + t = new_node.type + + body = [] + if t == 'SELF_TYPE': + t, need_typeof = get_typeof(__CURRENT_TYPE__) + if need_typeof: + body.append(CilAST.TypeOfNode(t, __CURRENT_TYPE__)) + + + allocate_res=add_local() + body.append(CilAST.AllocateNode(t, value)) + body.append(CilAST.ArgNode(value)) + body.append(CilAST.VCAllNode(t, '__init__', allocate_res)) + return CIL_block(body, value) diff --git a/src/code_generation/MIPS/test.asm b/src/code_generation/MIPS/test.asm index 4ab958b2..a4f9c1c9 100644 --- a/src/code_generation/MIPS/test.asm +++ b/src/code_generation/MIPS/test.asm @@ -2,7 +2,7 @@ .text main: move $fp, $sp - subu $sp, $sp, 16 + subu $sp, $sp, 12 la $t0, Object_abort usw $t0, vt_Object+0 la $t0, Object_type_name @@ -48,6 +48,144 @@ main: la $t0, Object_copy usw $t0, vt_Bool+8 la $t0, Object_abort + usw $t0, vt_A+0 + la $t0, Object_type_name + usw $t0, vt_A+4 + la $t0, Object_copy + usw $t0, vt_A+8 + la $t0, A_value + usw $t0, vt_A+40 + la $t0, A_set_var + usw $t0, vt_A+44 + la $t0, A_method1 + usw $t0, vt_A+48 + la $t0, A_method2 + usw $t0, vt_A+52 + la $t0, A_method3 + usw $t0, vt_A+56 + la $t0, A_method4 + usw $t0, vt_A+60 + la $t0, A_method5 + usw $t0, vt_A+64 + la $t0, A___init__ + usw $t0, vt_A+68 + la $t0, Object_abort + usw $t0, vt_B+0 + la $t0, Object_type_name + usw $t0, vt_B+4 + la $t0, Object_copy + usw $t0, vt_B+8 + la $t0, A_value + usw $t0, vt_B+40 + la $t0, A_set_var + usw $t0, vt_B+44 + la $t0, A_method1 + usw $t0, vt_B+48 + la $t0, A_method2 + usw $t0, vt_B+52 + la $t0, A_method3 + usw $t0, vt_B+56 + la $t0, A_method4 + usw $t0, vt_B+60 + la $t0, B_method5 + usw $t0, vt_B+64 + la $t0, B___init__ + usw $t0, vt_B+68 + la $t0, Object_abort + usw $t0, vt_C+0 + la $t0, Object_type_name + usw $t0, vt_C+4 + la $t0, Object_copy + usw $t0, vt_C+8 + la $t0, A_value + usw $t0, vt_C+40 + la $t0, A_set_var + usw $t0, vt_C+44 + la $t0, A_method1 + usw $t0, vt_C+48 + la $t0, A_method2 + usw $t0, vt_C+52 + la $t0, A_method3 + usw $t0, vt_C+56 + la $t0, A_method4 + usw $t0, vt_C+60 + la $t0, C_method5 + usw $t0, vt_C+64 + la $t0, C_method6 + usw $t0, vt_C+72 + la $t0, C___init__ + usw $t0, vt_C+68 + la $t0, Object_abort + usw $t0, vt_D+0 + la $t0, Object_type_name + usw $t0, vt_D+4 + la $t0, Object_copy + usw $t0, vt_D+8 + la $t0, A_value + usw $t0, vt_D+40 + la $t0, A_set_var + usw $t0, vt_D+44 + la $t0, A_method1 + usw $t0, vt_D+48 + la $t0, A_method2 + usw $t0, vt_D+52 + la $t0, A_method3 + usw $t0, vt_D+56 + la $t0, A_method4 + usw $t0, vt_D+60 + la $t0, B_method5 + usw $t0, vt_D+64 + la $t0, D_method7 + usw $t0, vt_D+76 + la $t0, D___init__ + usw $t0, vt_D+68 + la $t0, Object_abort + usw $t0, vt_E+0 + la $t0, Object_type_name + usw $t0, vt_E+4 + la $t0, Object_copy + usw $t0, vt_E+8 + la $t0, A_value + usw $t0, vt_E+40 + la $t0, A_set_var + usw $t0, vt_E+44 + la $t0, A_method1 + usw $t0, vt_E+48 + la $t0, A_method2 + usw $t0, vt_E+52 + la $t0, A_method3 + usw $t0, vt_E+56 + la $t0, A_method4 + usw $t0, vt_E+60 + la $t0, B_method5 + usw $t0, vt_E+64 + la $t0, D_method7 + usw $t0, vt_E+76 + la $t0, E_method6 + usw $t0, vt_E+72 + la $t0, E___init__ + usw $t0, vt_E+68 + la $t0, Object_abort + usw $t0, vt_A2I+0 + la $t0, Object_type_name + usw $t0, vt_A2I+4 + la $t0, Object_copy + usw $t0, vt_A2I+8 + la $t0, A2I_c2i + usw $t0, vt_A2I+80 + la $t0, A2I_i2c + usw $t0, vt_A2I+84 + la $t0, A2I_a2i + usw $t0, vt_A2I+88 + la $t0, A2I_a2i_aux + usw $t0, vt_A2I+92 + la $t0, A2I_i2a + usw $t0, vt_A2I+96 + la $t0, A2I_i2a_aux + usw $t0, vt_A2I+100 + la $t0, A2I___init__ + usw $t0, vt_A2I+68 + la $t0, Object_abort usw $t0, vt_Main+0 la $t0, Object_type_name usw $t0, vt_Main+4 @@ -61,48 +199,60 @@ main: usw $t0, vt_Main+20 la $t0, IO_in_int usw $t0, vt_Main+24 - la $t0, Main_pal - usw $t0, vt_Main+40 + la $t0, Main_menu + usw $t0, vt_Main+104 + la $t0, Main_prompt + usw $t0, vt_Main+108 + la $t0, Main_get_int + usw $t0, vt_Main+112 + la $t0, Main_is_even + usw $t0, vt_Main+116 + la $t0, Main_class_type + usw $t0, vt_Main+120 + la $t0, Main_print + usw $t0, vt_Main+124 la $t0, Main_main - usw $t0, vt_Main+44 + usw $t0, vt_Main+128 + la $t0, Main___init__ + usw $t0, vt_Main+68 # self = ALLOCATE Main ; - li $a0, 16 + li $a0, 28 li $v0, 9 syscall sw $v0, -4($fp) la $t0, vt_Main sw $t0, 8($v0) - # local_1 = LOAD data_1 ; - la $t0, data_1 - sw $t0, -8($fp) - # SETATTR self @type local_1 ; - lw $t0, -8($fp) - lw $t1, -4($fp) - sw $t0, 0($t1) - # local_2 = 16 ; - li $t0, 16 - sw $t0, -12($fp) - # SETATTR self @size local_2 ; - lw $t0, -12($fp) - lw $t1, -4($fp) - sw $t0, 4($t1) + # local_1 = VCALL Main __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal Main___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) # main_result = VCALL Main main ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) + sw $ra, 0($sp) + sw $fp, 4($sp) # ARG self ; lw $t0, -4($fp) subu $sp, $sp, 4 sw $t0, ($sp) jal Main_main addu $sp, $sp, 4 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -16($fp) + sw $v0, -12($fp) # RETURN main_result ; - lw $v0, -16($fp) - addu $sp, $sp, 16 + lw $v0, -12($fp) + addu $sp, $sp, 12 li $v0, 10 syscall IO_out_int: @@ -247,6 +397,7 @@ String_concat: b concat_loop_b end_concat: + sb $zero, ($t0) la $t0, concat_result sw $t0, -4($fp) # RETURN concat_result ; @@ -347,499 +498,6625 @@ Bool_abort: Bool_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_15 = LOAD data_5 ; - la $t0, data_5 + # local_228 = LOAD data_66 ; + la $t0, data_66 sw $t0, -4($fp) - # RETURN local_15 ; + # RETURN local_228 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra Int_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_16 = LOAD data_6 ; - la $t0, data_6 + # local_229 = LOAD data_67 ; + la $t0, data_67 sw $t0, -4($fp) - # RETURN local_16 ; + # RETURN local_229 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra String_type_name: move $fp, $sp subu $sp, $sp, 4 - # local_17 = LOAD data_7 ; - la $t0, data_7 + # local_230 = LOAD data_68 ; + la $t0, data_68 sw $t0, -4($fp) - # RETURN local_17 ; + # RETURN local_230 ; lw $v0, -4($fp) addu $sp, $sp, 4 jr $ra -Main_pal: +A___init__: move $fp, $sp - subu $sp, $sp, 108 - # local_1 = VCALL String length ; - subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; + subu $sp, $sp, 12 + # local_1 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -8($fp) + # SETATTR self @type local_1 ; + lw $t0, -8($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_2 = 16 ; + li $t0, 16 + sw $t0, -12($fp) + # SETATTR self size local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self var 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 12($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +A_value: + move $fp, $sp + subu $sp, $sp, 4 + # local_0 = GETATTR self var ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -4($fp) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 4 + jr $ra +A_set_var: + move $fp, $sp + subu $sp, $sp, 0 + # SETATTR self var num ; lw $t0, 0($fp) + lw $t1, 4($fp) + sw $t0, 12($t1) + # RETURN self ; + lw $v0, 4($fp) + addu $sp, $sp, 0 + jr $ra +A_method1: + move $fp, $sp + subu $sp, $sp, 0 + # RETURN self ; + lw $v0, 4($fp) + addu $sp, $sp, 0 + jr $ra +A_method2: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = num1 + num2 ; + lw $t0, 4($fp) + lw $t1, 0($fp) + add $t0, $t0, $t1 + sw $t0, -4($fp) + # x = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # local_3 = ALLOCATE B ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_B + sw $t0, 8($v0) + # local_4 = VCALL B __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_length + jal B___init__ addu $sp, $sp, 4 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -8($fp) - # local_2 = local_1 == 0 ; - lw $t0, -8($fp) - li $t1, 0 - seq $t0, $t0, $t1 + sw $v0, -20($fp) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) sw $t0, -12($fp) - # local_3 = local_2 ; - lw $t0, -12($fp) - sw $t0, -16($fp) - # IF local_3 GOTO label_5 ; - lw $t0, -16($fp) - bnez $t0, label_5 - # local_5 = VCALL String length ; + # local_5 = VCALL local_2 set_var ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; - lw $t0, 0($fp) + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_length - addu $sp, $sp, 4 - lw $fp, 0($sp) - lw $ra, 4($sp) + # ARG x ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 sw $v0, -24($fp) - # local_6 = local_5 == 1 ; - lw $t0, -24($fp) - li $t1, 1 - seq $t0, $t0, $t1 - sw $t0, -28($fp) - # local_7 = local_6 ; - lw $t0, -28($fp) - sw $t0, -32($fp) - # IF local_7 GOTO label_3 ; - lw $t0, -32($fp) - bnez $t0, label_3 - # local_9 = VCALL String substr ; - subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +A_method3: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = ~ num lw $t0, 0($fp) + neg $t0, $t0 + sw $t0, -4($fp) + # x = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # local_3 = ALLOCATE C ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_C + sw $t0, 8($v0) + # local_4 = VCALL C __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 0 ; - li $t0, 0 - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + jal C___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_5 = VCALL local_2 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 0 ; - li $t0, 0 + # ARG x ; + lw $t0, -8($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 16 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $t0, -12($fp) + ulw $t1, 44($t0) + jalr $t1 addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +A_method4: + move $fp, $sp + subu $sp, $sp, 52 + # local_0 = num2 < num1 ; + lw $t0, 0($fp) + lw $t1, 4($fp) + slt $t0, $t0, $t1 + sw $t0, -4($fp) + # IF local_0 GOTO label_1 ; + lw $t0, -4($fp) + bnez $t0, label_1 + # local_7 = num2 - num1 ; + lw $t0, 0($fp) + lw $t1, 4($fp) + sub $t0, $t0, $t1 + sw $t0, -32($fp) + # x = local_7 ; + lw $t0, -32($fp) + sw $t0, -12($fp) + # local_9 = ALLOCATE D ; + li $a0, 16 + li $v0, 9 + syscall sw $v0, -40($fp) - # local_12 = VCALL String length ; + la $t0, vt_D + sw $t0, 8($v0) + # local_10 = VCALL D __init__ ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; - lw $t0, 0($fp) + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_9 ; + lw $t0, -40($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_length + jal D___init__ addu $sp, $sp, 4 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -52($fp) - # local_13 = local_12 - 1 ; - lw $t0, -52($fp) - li $t1, 1 - sub $t0, $t0, $t1 - sw $t0, -56($fp) - # local_14 = VCALL String substr ; + sw $v0, -44($fp) + # local_8 = GETTYPEADDR local_9 ; + lw $t1, -40($fp) + lw $t0, 8($t1) + sw $t0, -36($fp) + # local_11 = VCALL local_8 set_var ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; - lw $t0, 0($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG local_13 ; - lw $t0, -56($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_9 ; + lw $t0, -40($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 1024 ; - li $t0, 1024 + # ARG x ; + lw $t0, -12($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 16 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $t0, -36($fp) + ulw $t1, 44($t0) + jalr $t1 addu $sp, $sp, 8 - sw $v0, -60($fp) - # local_15 = local_9 == local_14 ; - lw $t0, -40($fp) - lw $t1, -60($fp) - li $v0, 1 - sw $v0, -64($fp) - equal_loop_1: - - lb $t2, ($t0) - lb $t3, ($t1) - seq $t4, $t2, $t3 - beqz $t4, not_equal_1 - beqz $t2, end_loop_1 - addu $t0, $t0, 1 - addu $t1, $t1, 1 - b equal_loop_1 - b end_loop_1 - not_equal_1: - - li $v0, 0 - sw $v0, -64($fp) - end_loop_1: - - # local_16 = local_15 ; - lw $t0, -64($fp) - sw $t0, -68($fp) - # IF local_16 GOTO label_1 ; - lw $t0, -68($fp) - bnez $t0, label_1 - # local_24 = 0 ; - li $t0, 0 - sw $t0, -100($fp) + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = local_11 ; + lw $t0, -48($fp) + sw $t0, -52($fp) # GOTO label_2 ; b label_2 # LABEL label_1 ; label_1: - # local_17 = GETTYPEADDR self ; - lw $t1, 4($fp) - lw $t0, 8($t1) - sw $t0, -72($fp) - # local_20 = VCALL String length ; - subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) + # local_1 = num1 - num2 ; + lw $t0, 4($fp) + lw $t1, 0($fp) + sub $t0, $t0, $t1 + sw $t0, -8($fp) + # x = local_1 ; + lw $t0, -8($fp) + sw $t0, -12($fp) + # local_4 = ALLOCATE D ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -20($fp) + la $t0, vt_D + sw $t0, 8($v0) + # local_5 = VCALL D __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal D___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_3 = GETTYPEADDR local_4 ; + lw $t1, -20($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_6 = VCALL local_3 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -28($fp) + # local_12 = local_6 ; + lw $t0, -28($fp) + sw $t0, -52($fp) + # LABEL label_2 ; + label_2: + + # RETURN local_12 ; + lw $v0, -52($fp) + addu $sp, $sp, 52 + jr $ra +A_method5: + move $fp, $sp + subu $sp, $sp, 40 + # x = 1 ; + li $t0, 1 + sw $t0, -4($fp) + # y = 1 ; + li $t0, 1 + sw $t0, -8($fp) + # LABEL label_3 ; + label_3: + + # local_2 = y <= num ; + lw $t0, -8($fp) + lw $t1, 0($fp) + sle $t0, $t0, $t1 + sw $t0, -12($fp) + # IF local_2 GOTO label_4 ; + lw $t0, -12($fp) + bnez $t0, label_4 + # GOTO label_5 ; + b label_5 + # LABEL label_4 ; + label_4: + + # local_3 = x * y ; + lw $t0, -4($fp) + lw $t1, -8($fp) + mul $t0, $t0, $t1 + sw $t0, -16($fp) + # x = local_3 ; + lw $t0, -16($fp) + sw $t0, -4($fp) + # local_4 = y + 1 ; + lw $t0, -8($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -20($fp) + # y = local_4 ; + lw $t0, -20($fp) + sw $t0, -8($fp) + # GOTO label_3 ; + b label_3 + # LABEL label_5 ; + label_5: + + # local_5 = 0 ; + li $t0, 0 + sw $t0, -24($fp) + # local_7 = ALLOCATE E ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -32($fp) + la $t0, vt_E + sw $t0, 8($v0) + # local_8 = VCALL E __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal E___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_6 = GETTYPEADDR local_7 ; + lw $t1, -32($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_9 = VCALL local_6 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -40($fp) + # RETURN local_9 ; + lw $v0, -40($fp) + addu $sp, $sp, 40 + jr $ra +B___init__: + move $fp, $sp + subu $sp, $sp, 16 + # local_1 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # local_2 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -12($fp) + # SETATTR self @type local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_3 = 16 ; + li $t0, 16 + sw $t0, -16($fp) + # SETATTR self size local_3 ; + lw $t0, -16($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self var 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 12($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +B_method5: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = num * num ; + lw $t0, 0($fp) + lw $t1, 0($fp) + mul $t0, $t0, $t1 + sw $t0, -4($fp) + # x = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # local_3 = ALLOCATE E ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_E + sw $t0, 8($v0) + # local_4 = VCALL E __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal E___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_5 = VCALL local_2 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +C___init__: + move $fp, $sp + subu $sp, $sp, 16 + # local_1 = VCALL B __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal B___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # local_2 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -12($fp) + # SETATTR self @type local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_3 = 16 ; + li $t0, 16 + sw $t0, -16($fp) + # SETATTR self size local_3 ; + lw $t0, -16($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self var 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 12($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +C_method6: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = ~ num + lw $t0, 0($fp) + neg $t0, $t0 + sw $t0, -4($fp) + # x = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # local_3 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_4 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_5 = VCALL local_2 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +C_method5: + move $fp, $sp + subu $sp, $sp, 28 + # local_0 = num * num ; + lw $t0, 0($fp) + lw $t1, 0($fp) + mul $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 * num ; + lw $t0, -4($fp) + lw $t1, 0($fp) + mul $t0, $t0, $t1 + sw $t0, -8($fp) + # x = local_1 ; + lw $t0, -8($fp) + sw $t0, -12($fp) + # local_4 = ALLOCATE E ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -20($fp) + la $t0, vt_E + sw $t0, 8($v0) + # local_5 = VCALL E __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal E___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_3 = GETTYPEADDR local_4 ; + lw $t1, -20($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_6 = VCALL local_3 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -28($fp) + # RETURN local_6 ; + lw $v0, -28($fp) + addu $sp, $sp, 28 + jr $ra +D___init__: + move $fp, $sp + subu $sp, $sp, 16 + # local_1 = VCALL B __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal B___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # local_2 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -12($fp) + # SETATTR self @type local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_3 = 16 ; + li $t0, 16 + sw $t0, -16($fp) + # SETATTR self size local_3 ; + lw $t0, -16($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self var 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 12($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +D_method7: + move $fp, $sp + subu $sp, $sp, 72 + # x = num ; + lw $t0, 0($fp) + sw $t0, -4($fp) + # local_1 = x < 0 ; + lw $t0, -4($fp) + li $t1, 0 + slt $t0, $t0, $t1 + sw $t0, -8($fp) + # IF local_1 GOTO label_12 ; + lw $t0, -8($fp) + bnez $t0, label_12 + # local_5 = 0 == x ; + li $t0, 0 + lw $t1, -4($fp) + seq $t0, $t0, $t1 + sw $t0, -24($fp) + # local_6 = local_5 ; + lw $t0, -24($fp) + sw $t0, -28($fp) + # IF local_6 GOTO label_10 ; + lw $t0, -28($fp) + bnez $t0, label_10 + # local_7 = 1 == x ; + li $t0, 1 + lw $t1, -4($fp) + seq $t0, $t0, $t1 + sw $t0, -32($fp) + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_8 ; + lw $t0, -36($fp) + bnez $t0, label_8 + # local_9 = 2 == x ; + li $t0, 2 + lw $t1, -4($fp) + seq $t0, $t0, $t1 + sw $t0, -40($fp) + # local_10 = local_9 ; + lw $t0, -40($fp) + sw $t0, -44($fp) + # IF local_10 GOTO label_6 ; + lw $t0, -44($fp) + bnez $t0, label_6 + # local_11 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -48($fp) + # local_12 = x - 3 ; + lw $t0, -4($fp) + li $t1, 3 + sub $t0, $t0, $t1 + sw $t0, -52($fp) + # local_13 = VCALL local_11 method7 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_12 ; + lw $t0, -52($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -48($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -56($fp) + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # GOTO label_7 ; + b label_7 + # LABEL label_6 ; + label_6: + + # local_14 = 0 ; + li $t0, 0 + sw $t0, -60($fp) + # LABEL label_7 ; + label_7: + + # local_15 = local_14 ; + lw $t0, -60($fp) + sw $t0, -64($fp) + # GOTO label_9 ; + b label_9 + # LABEL label_8 ; + label_8: + + # local_15 = 0 ; + li $t0, 0 + sw $t0, -64($fp) + # LABEL label_9 ; + label_9: + + # local_16 = local_15 ; + lw $t0, -64($fp) + sw $t0, -68($fp) + # GOTO label_11 ; + b label_11 + # LABEL label_10 ; + label_10: + + # local_16 = 1 ; + li $t0, 1 + sw $t0, -68($fp) + # LABEL label_11 ; + label_11: + + # local_17 = local_16 ; + lw $t0, -68($fp) + sw $t0, -72($fp) + # GOTO label_13 ; + b label_13 + # LABEL label_12 ; + label_12: + + # local_2 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_3 = ~ x + lw $t0, -4($fp) + neg $t0, $t0 + sw $t0, -16($fp) + # local_4 = VCALL local_2 method7 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_17 = local_4 ; + lw $t0, -20($fp) + sw $t0, -72($fp) + # LABEL label_13 ; + label_13: + + # RETURN local_17 ; + lw $v0, -72($fp) + addu $sp, $sp, 72 + jr $ra +E___init__: + move $fp, $sp + subu $sp, $sp, 16 + # local_1 = VCALL D __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal D___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # local_2 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -12($fp) + # SETATTR self @type local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_3 = 16 ; + li $t0, 16 + sw $t0, -16($fp) + # SETATTR self size local_3 ; + lw $t0, -16($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self var 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 12($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 16 + jr $ra +E_method6: + move $fp, $sp + subu $sp, $sp, 24 + # local_0 = num / 8 ; + lw $t0, 0($fp) + li $t1, 8 + div $t0, $t0, $t1 + sw $t0, -4($fp) + # x = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # local_3 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -16($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_4 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_2 = GETTYPEADDR local_3 ; + lw $t1, -16($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_5 = VCALL local_2 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # RETURN local_5 ; + lw $v0, -24($fp) + addu $sp, $sp, 24 + jr $ra +A2I___init__: + move $fp, $sp + subu $sp, $sp, 12 + # local_1 = LOAD data_6 ; + la $t0, data_6 + sw $t0, -8($fp) + # SETATTR self @type local_1 ; + lw $t0, -8($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_2 = 12 ; + li $t0, 12 + sw $t0, -12($fp) + # SETATTR self size local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +A2I_c2i: + move $fp, $sp + subu $sp, $sp, 168 + # local_0 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -4($fp) + # local_1 = char == local_0 ; + lw $t0, 0($fp) + lw $t1, -4($fp) + li $v0, 1 + sw $v0, -8($fp) + equal_loop_1: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_1 + beqz $t2, end_loop_1 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_1 + b end_loop_1 + not_equal_1: + + li $v0, 0 + sw $v0, -8($fp) + end_loop_1: + + # local_2 = local_1 ; + lw $t0, -8($fp) + sw $t0, -12($fp) + # IF local_2 GOTO label_32 ; + lw $t0, -12($fp) + bnez $t0, label_32 + # local_3 = LOAD data_8 ; + la $t0, data_8 + sw $t0, -16($fp) + # local_4 = char == local_3 ; + lw $t0, 0($fp) + lw $t1, -16($fp) + li $v0, 1 + sw $v0, -20($fp) + equal_loop_2: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_2 + beqz $t2, end_loop_2 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_2 + b end_loop_2 + not_equal_2: + + li $v0, 0 + sw $v0, -20($fp) + end_loop_2: + + # local_5 = local_4 ; + lw $t0, -20($fp) + sw $t0, -24($fp) + # IF local_5 GOTO label_30 ; + lw $t0, -24($fp) + bnez $t0, label_30 + # local_6 = LOAD data_9 ; + la $t0, data_9 + sw $t0, -28($fp) + # local_7 = char == local_6 ; + lw $t0, 0($fp) + lw $t1, -28($fp) + li $v0, 1 + sw $v0, -32($fp) + equal_loop_3: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_3 + beqz $t2, end_loop_3 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_3 + b end_loop_3 + not_equal_3: + + li $v0, 0 + sw $v0, -32($fp) + end_loop_3: + + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_28 ; + lw $t0, -36($fp) + bnez $t0, label_28 + # local_9 = LOAD data_10 ; + la $t0, data_10 + sw $t0, -40($fp) + # local_10 = char == local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + li $v0, 1 + sw $v0, -44($fp) + equal_loop_4: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_4 + beqz $t2, end_loop_4 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_4 + b end_loop_4 + not_equal_4: + + li $v0, 0 + sw $v0, -44($fp) + end_loop_4: + + # local_11 = local_10 ; + lw $t0, -44($fp) + sw $t0, -48($fp) + # IF local_11 GOTO label_26 ; + lw $t0, -48($fp) + bnez $t0, label_26 + # local_12 = LOAD data_11 ; + la $t0, data_11 + sw $t0, -52($fp) + # local_13 = char == local_12 ; + lw $t0, 0($fp) + lw $t1, -52($fp) + li $v0, 1 + sw $v0, -56($fp) + equal_loop_5: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_5 + beqz $t2, end_loop_5 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_5 + b end_loop_5 + not_equal_5: + + li $v0, 0 + sw $v0, -56($fp) + end_loop_5: + + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # IF local_14 GOTO label_24 ; + lw $t0, -60($fp) + bnez $t0, label_24 + # local_15 = LOAD data_12 ; + la $t0, data_12 + sw $t0, -64($fp) + # local_16 = char == local_15 ; + lw $t0, 0($fp) + lw $t1, -64($fp) + li $v0, 1 + sw $v0, -68($fp) + equal_loop_6: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_6 + beqz $t2, end_loop_6 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_6 + b end_loop_6 + not_equal_6: + + li $v0, 0 + sw $v0, -68($fp) + end_loop_6: + + # local_17 = local_16 ; + lw $t0, -68($fp) + sw $t0, -72($fp) + # IF local_17 GOTO label_22 ; + lw $t0, -72($fp) + bnez $t0, label_22 + # local_18 = LOAD data_13 ; + la $t0, data_13 + sw $t0, -76($fp) + # local_19 = char == local_18 ; + lw $t0, 0($fp) + lw $t1, -76($fp) + li $v0, 1 + sw $v0, -80($fp) + equal_loop_7: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_7 + beqz $t2, end_loop_7 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_7 + b end_loop_7 + not_equal_7: + + li $v0, 0 + sw $v0, -80($fp) + end_loop_7: + + # local_20 = local_19 ; + lw $t0, -80($fp) + sw $t0, -84($fp) + # IF local_20 GOTO label_20 ; + lw $t0, -84($fp) + bnez $t0, label_20 + # local_21 = LOAD data_14 ; + la $t0, data_14 + sw $t0, -88($fp) + # local_22 = char == local_21 ; + lw $t0, 0($fp) + lw $t1, -88($fp) + li $v0, 1 + sw $v0, -92($fp) + equal_loop_8: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_8 + beqz $t2, end_loop_8 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_8 + b end_loop_8 + not_equal_8: + + li $v0, 0 + sw $v0, -92($fp) + end_loop_8: + + # local_23 = local_22 ; + lw $t0, -92($fp) + sw $t0, -96($fp) + # IF local_23 GOTO label_18 ; + lw $t0, -96($fp) + bnez $t0, label_18 + # local_24 = LOAD data_15 ; + la $t0, data_15 + sw $t0, -100($fp) + # local_25 = char == local_24 ; + lw $t0, 0($fp) + lw $t1, -100($fp) + li $v0, 1 + sw $v0, -104($fp) + equal_loop_9: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_9 + beqz $t2, end_loop_9 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_9 + b end_loop_9 + not_equal_9: + + li $v0, 0 + sw $v0, -104($fp) + end_loop_9: + + # local_26 = local_25 ; + lw $t0, -104($fp) + sw $t0, -108($fp) + # IF local_26 GOTO label_16 ; + lw $t0, -108($fp) + bnez $t0, label_16 + # local_27 = LOAD data_16 ; + la $t0, data_16 + sw $t0, -112($fp) + # local_28 = char == local_27 ; + lw $t0, 0($fp) + lw $t1, -112($fp) + li $v0, 1 + sw $v0, -116($fp) + equal_loop_10: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_10 + beqz $t2, end_loop_10 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_10 + b end_loop_10 + not_equal_10: + + li $v0, 0 + sw $v0, -116($fp) + end_loop_10: + + # local_29 = local_28 ; + lw $t0, -116($fp) + sw $t0, -120($fp) + # IF local_29 GOTO label_14 ; + lw $t0, -120($fp) + bnez $t0, label_14 + # local_30 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_31 = VCALL local_30 abort ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -124($fp) + ulw $t1, 0($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -128($fp) + # local_32 = 0 ; + li $t0, 0 + sw $t0, -132($fp) + # GOTO label_15 ; + b label_15 + # LABEL label_14 ; + label_14: + + # local_32 = 9 ; + li $t0, 9 + sw $t0, -132($fp) + # LABEL label_15 ; + label_15: + + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_17 ; + b label_17 + # LABEL label_16 ; + label_16: + + # local_33 = 8 ; + li $t0, 8 + sw $t0, -136($fp) + # LABEL label_17 ; + label_17: + + # local_34 = local_33 ; + lw $t0, -136($fp) + sw $t0, -140($fp) + # GOTO label_19 ; + b label_19 + # LABEL label_18 ; + label_18: + + # local_34 = 7 ; + li $t0, 7 + sw $t0, -140($fp) + # LABEL label_19 ; + label_19: + + # local_35 = local_34 ; + lw $t0, -140($fp) + sw $t0, -144($fp) + # GOTO label_21 ; + b label_21 + # LABEL label_20 ; + label_20: + + # local_35 = 6 ; + li $t0, 6 + sw $t0, -144($fp) + # LABEL label_21 ; + label_21: + + # local_36 = local_35 ; + lw $t0, -144($fp) + sw $t0, -148($fp) + # GOTO label_23 ; + b label_23 + # LABEL label_22 ; + label_22: + + # local_36 = 5 ; + li $t0, 5 + sw $t0, -148($fp) + # LABEL label_23 ; + label_23: + + # local_37 = local_36 ; + lw $t0, -148($fp) + sw $t0, -152($fp) + # GOTO label_25 ; + b label_25 + # LABEL label_24 ; + label_24: + + # local_37 = 4 ; + li $t0, 4 + sw $t0, -152($fp) + # LABEL label_25 ; + label_25: + + # local_38 = local_37 ; + lw $t0, -152($fp) + sw $t0, -156($fp) + # GOTO label_27 ; + b label_27 + # LABEL label_26 ; + label_26: + + # local_38 = 3 ; + li $t0, 3 + sw $t0, -156($fp) + # LABEL label_27 ; + label_27: + + # local_39 = local_38 ; + lw $t0, -156($fp) + sw $t0, -160($fp) + # GOTO label_29 ; + b label_29 + # LABEL label_28 ; + label_28: + + # local_39 = 2 ; + li $t0, 2 + sw $t0, -160($fp) + # LABEL label_29 ; + label_29: + + # local_40 = local_39 ; + lw $t0, -160($fp) + sw $t0, -164($fp) + # GOTO label_31 ; + b label_31 + # LABEL label_30 ; + label_30: + + # local_40 = 1 ; + li $t0, 1 + sw $t0, -164($fp) + # LABEL label_31 ; + label_31: + + # local_41 = local_40 ; + lw $t0, -164($fp) + sw $t0, -168($fp) + # GOTO label_33 ; + b label_33 + # LABEL label_32 ; + label_32: + + # local_41 = 0 ; + li $t0, 0 + sw $t0, -168($fp) + # LABEL label_33 ; + label_33: + + # RETURN local_41 ; + lw $v0, -168($fp) + addu $sp, $sp, 168 + jr $ra +A2I_i2c: + move $fp, $sp + subu $sp, $sp, 172 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # IF local_1 GOTO label_52 ; + lw $t0, -8($fp) + bnez $t0, label_52 + # local_3 = i == 1 ; + lw $t0, 0($fp) + li $t1, 1 + seq $t0, $t0, $t1 + sw $t0, -16($fp) + # local_4 = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # IF local_4 GOTO label_50 ; + lw $t0, -20($fp) + bnez $t0, label_50 + # local_6 = i == 2 ; + lw $t0, 0($fp) + li $t1, 2 + seq $t0, $t0, $t1 + sw $t0, -28($fp) + # local_7 = local_6 ; + lw $t0, -28($fp) + sw $t0, -32($fp) + # IF local_7 GOTO label_48 ; + lw $t0, -32($fp) + bnez $t0, label_48 + # local_9 = i == 3 ; + lw $t0, 0($fp) + li $t1, 3 + seq $t0, $t0, $t1 + sw $t0, -40($fp) + # local_10 = local_9 ; + lw $t0, -40($fp) + sw $t0, -44($fp) + # IF local_10 GOTO label_46 ; + lw $t0, -44($fp) + bnez $t0, label_46 + # local_12 = i == 4 ; + lw $t0, 0($fp) + li $t1, 4 + seq $t0, $t0, $t1 + sw $t0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # IF local_13 GOTO label_44 ; + lw $t0, -56($fp) + bnez $t0, label_44 + # local_15 = i == 5 ; + lw $t0, 0($fp) + li $t1, 5 + seq $t0, $t0, $t1 + sw $t0, -64($fp) + # local_16 = local_15 ; + lw $t0, -64($fp) + sw $t0, -68($fp) + # IF local_16 GOTO label_42 ; + lw $t0, -68($fp) + bnez $t0, label_42 + # local_18 = i == 6 ; + lw $t0, 0($fp) + li $t1, 6 + seq $t0, $t0, $t1 + sw $t0, -76($fp) + # local_19 = local_18 ; + lw $t0, -76($fp) + sw $t0, -80($fp) + # IF local_19 GOTO label_40 ; + lw $t0, -80($fp) + bnez $t0, label_40 + # local_21 = i == 7 ; + lw $t0, 0($fp) + li $t1, 7 + seq $t0, $t0, $t1 + sw $t0, -88($fp) + # local_22 = local_21 ; + lw $t0, -88($fp) + sw $t0, -92($fp) + # IF local_22 GOTO label_38 ; + lw $t0, -92($fp) + bnez $t0, label_38 + # local_24 = i == 8 ; + lw $t0, 0($fp) + li $t1, 8 + seq $t0, $t0, $t1 + sw $t0, -100($fp) + # local_25 = local_24 ; + lw $t0, -100($fp) + sw $t0, -104($fp) + # IF local_25 GOTO label_36 ; + lw $t0, -104($fp) + bnez $t0, label_36 + # local_27 = i == 9 ; + lw $t0, 0($fp) + li $t1, 9 + seq $t0, $t0, $t1 + sw $t0, -112($fp) + # local_28 = local_27 ; + lw $t0, -112($fp) + sw $t0, -116($fp) + # IF local_28 GOTO label_34 ; + lw $t0, -116($fp) + bnez $t0, label_34 + # local_30 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_31 = VCALL local_30 abort ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -124($fp) + ulw $t1, 0($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -128($fp) + # local_32 = LOAD data_17 ; + la $t0, data_17 + sw $t0, -132($fp) + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_35 ; + b label_35 + # LABEL label_34 ; + label_34: + + # local_29 = LOAD data_16 ; + la $t0, data_16 + sw $t0, -120($fp) + # local_33 = local_29 ; + lw $t0, -120($fp) + sw $t0, -136($fp) + # LABEL label_35 ; + label_35: + + # local_34 = local_33 ; + lw $t0, -136($fp) + sw $t0, -140($fp) + # GOTO label_37 ; + b label_37 + # LABEL label_36 ; + label_36: + + # local_26 = LOAD data_15 ; + la $t0, data_15 + sw $t0, -108($fp) + # local_34 = local_26 ; + lw $t0, -108($fp) + sw $t0, -140($fp) + # LABEL label_37 ; + label_37: + + # local_35 = local_34 ; + lw $t0, -140($fp) + sw $t0, -144($fp) + # GOTO label_39 ; + b label_39 + # LABEL label_38 ; + label_38: + + # local_23 = LOAD data_14 ; + la $t0, data_14 + sw $t0, -96($fp) + # local_35 = local_23 ; + lw $t0, -96($fp) + sw $t0, -144($fp) + # LABEL label_39 ; + label_39: + + # local_36 = local_35 ; + lw $t0, -144($fp) + sw $t0, -148($fp) + # GOTO label_41 ; + b label_41 + # LABEL label_40 ; + label_40: + + # local_20 = LOAD data_13 ; + la $t0, data_13 + sw $t0, -84($fp) + # local_36 = local_20 ; + lw $t0, -84($fp) + sw $t0, -148($fp) + # LABEL label_41 ; + label_41: + + # local_37 = local_36 ; + lw $t0, -148($fp) + sw $t0, -152($fp) + # GOTO label_43 ; + b label_43 + # LABEL label_42 ; + label_42: + + # local_17 = LOAD data_12 ; + la $t0, data_12 + sw $t0, -72($fp) + # local_37 = local_17 ; + lw $t0, -72($fp) + sw $t0, -152($fp) + # LABEL label_43 ; + label_43: + + # local_38 = local_37 ; + lw $t0, -152($fp) + sw $t0, -156($fp) + # GOTO label_45 ; + b label_45 + # LABEL label_44 ; + label_44: + + # local_14 = LOAD data_11 ; + la $t0, data_11 + sw $t0, -60($fp) + # local_38 = local_14 ; + lw $t0, -60($fp) + sw $t0, -156($fp) + # LABEL label_45 ; + label_45: + + # local_39 = local_38 ; + lw $t0, -156($fp) + sw $t0, -160($fp) + # GOTO label_47 ; + b label_47 + # LABEL label_46 ; + label_46: + + # local_11 = LOAD data_10 ; + la $t0, data_10 + sw $t0, -48($fp) + # local_39 = local_11 ; + lw $t0, -48($fp) + sw $t0, -160($fp) + # LABEL label_47 ; + label_47: + + # local_40 = local_39 ; + lw $t0, -160($fp) + sw $t0, -164($fp) + # GOTO label_49 ; + b label_49 + # LABEL label_48 ; + label_48: + + # local_8 = LOAD data_9 ; + la $t0, data_9 + sw $t0, -36($fp) + # local_40 = local_8 ; + lw $t0, -36($fp) + sw $t0, -164($fp) + # LABEL label_49 ; + label_49: + + # local_41 = local_40 ; + lw $t0, -164($fp) + sw $t0, -168($fp) + # GOTO label_51 ; + b label_51 + # LABEL label_50 ; + label_50: + + # local_5 = LOAD data_8 ; + la $t0, data_8 + sw $t0, -24($fp) + # local_41 = local_5 ; + lw $t0, -24($fp) + sw $t0, -168($fp) + # LABEL label_51 ; + label_51: + + # local_42 = local_41 ; + lw $t0, -168($fp) + sw $t0, -172($fp) + # GOTO label_53 ; + b label_53 + # LABEL label_52 ; + label_52: + + # local_2 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -12($fp) + # local_42 = local_2 ; + lw $t0, -12($fp) + sw $t0, -172($fp) + # LABEL label_53 ; + label_53: + + # RETURN local_42 ; + lw $v0, -172($fp) + addu $sp, $sp, 172 + jr $ra +A2I_a2i: + move $fp, $sp + subu $sp, $sp, 136 + # local_1 = VCALL String length ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # local_2 = local_1 == 0 ; + lw $t0, -8($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -12($fp) + # local_3 = local_2 ; + lw $t0, -12($fp) + sw $t0, -16($fp) + # IF local_3 GOTO label_58 ; + lw $t0, -16($fp) + bnez $t0, label_58 + # local_5 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_6 = LOAD data_18 ; + la $t0, data_18 + sw $t0, -28($fp) + # local_7 = local_5 == local_6 ; + lw $t0, -24($fp) + lw $t1, -28($fp) + li $v0, 1 + sw $v0, -32($fp) + equal_loop_11: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_11 + beqz $t2, end_loop_11 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_11 + b end_loop_11 + not_equal_11: + + li $v0, 0 + sw $v0, -32($fp) + end_loop_11: + + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_56 ; + lw $t0, -36($fp) + bnez $t0, label_56 + # local_18 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 2048 ; + li $t0, 2048 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -76($fp) + # local_19 = LOAD data_19 ; + la $t0, data_19 + sw $t0, -80($fp) + # local_20 = local_18 == local_19 ; + lw $t0, -76($fp) + lw $t1, -80($fp) + li $v0, 1 + sw $v0, -84($fp) + equal_loop_12: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_12 + beqz $t2, end_loop_12 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_12 + b end_loop_12 + not_equal_12: + + li $v0, 0 + sw $v0, -84($fp) + end_loop_12: + + # local_21 = local_20 ; + lw $t0, -84($fp) + sw $t0, -88($fp) + # IF local_21 GOTO label_54 ; + lw $t0, -88($fp) + bnez $t0, label_54 + # local_29 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -120($fp) + # local_30 = VCALL local_29 a2i_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -120($fp) + ulw $t1, 92($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -124($fp) + # local_31 = local_30 ; + lw $t0, -124($fp) + sw $t0, -128($fp) + # GOTO label_55 ; + b label_55 + # LABEL label_54 ; + label_54: + + # local_22 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -92($fp) + # local_25 = VCALL String length ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -104($fp) + # local_26 = local_25 - 1 ; + lw $t0, -104($fp) + li $t1, 1 + sub $t0, $t0, $t1 + sw $t0, -108($fp) + # local_27 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_26 ; + lw $t0, -108($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 3072 ; + li $t0, 3072 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -112($fp) + # local_28 = VCALL local_22 a2i_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_27 ; + lw $t0, -112($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -92($fp) + ulw $t1, 92($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -116($fp) + # local_31 = local_28 ; + lw $t0, -116($fp) + sw $t0, -128($fp) + # LABEL label_55 ; + label_55: + + # local_32 = local_31 ; + lw $t0, -128($fp) + sw $t0, -132($fp) + # GOTO label_57 ; + b label_57 + # LABEL label_56 ; + label_56: + + # local_9 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -40($fp) + # local_12 = VCALL String length ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = local_12 - 1 ; + lw $t0, -52($fp) + li $t1, 1 + sub $t0, $t0, $t1 + sw $t0, -56($fp) + # local_14 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1024 ; + li $t0, 1024 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -60($fp) + # local_15 = VCALL local_9 a2i_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_14 ; + lw $t0, -60($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -40($fp) + ulw $t1, 92($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -64($fp) + # local_16 = ~ local_15 + lw $t0, -64($fp) + neg $t0, $t0 + sw $t0, -68($fp) + # local_32 = local_16 ; + lw $t0, -68($fp) + sw $t0, -132($fp) + # LABEL label_57 ; + label_57: + + # local_33 = local_32 ; + lw $t0, -132($fp) + sw $t0, -136($fp) + # GOTO label_59 ; + b label_59 + # LABEL label_58 ; + label_58: + + # local_33 = 0 ; + li $t0, 0 + sw $t0, -136($fp) + # LABEL label_59 ; + label_59: + + # RETURN local_33 ; + lw $v0, -136($fp) + addu $sp, $sp, 136 + jr $ra +A2I_a2i_aux: + move $fp, $sp + subu $sp, $sp, 56 + # int = 0 ; + li $t0, 0 + sw $t0, -4($fp) + # local_2 = VCALL String length ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_length + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # j = local_2 ; + lw $t0, -12($fp) + sw $t0, -16($fp) + # i = 0 ; + li $t0, 0 + sw $t0, -20($fp) + # LABEL label_60 ; + label_60: + + # local_5 = i < j ; + lw $t0, -20($fp) + lw $t1, -16($fp) + slt $t0, $t0, $t1 + sw $t0, -24($fp) + # IF local_5 GOTO label_61 ; + lw $t0, -24($fp) + bnez $t0, label_61 + # GOTO label_62 ; + b label_62 + # LABEL label_61 ; + label_61: + + # local_6 = int * 10 ; + lw $t0, -4($fp) + li $t1, 10 + mul $t0, $t0, $t1 + sw $t0, -28($fp) + # local_7 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -32($fp) + # local_9 = VCALL String substr ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG s ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1 ; + li $t0, 1 + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 4096 ; + li $t0, 4096 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_substr + addu $sp, $sp, 16 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -40($fp) + # local_10 = VCALL local_7 c2i ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_9 ; + lw $t0, -40($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -32($fp) + ulw $t1, 80($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -44($fp) + # local_11 = local_6 + local_10 ; + lw $t0, -28($fp) + lw $t1, -44($fp) + add $t0, $t0, $t1 + sw $t0, -48($fp) + # int = local_11 ; + lw $t0, -48($fp) + sw $t0, -4($fp) + # local_12 = i + 1 ; + lw $t0, -20($fp) + li $t1, 1 + add $t0, $t0, $t1 + sw $t0, -52($fp) + # i = local_12 ; + lw $t0, -52($fp) + sw $t0, -20($fp) + # GOTO label_60 ; + b label_60 + # LABEL label_62 ; + label_62: + + # local_13 = 0 ; + li $t0, 0 + sw $t0, -56($fp) + # RETURN int ; + lw $v0, -4($fp) + addu $sp, $sp, 56 + jr $ra +A2I_i2a: + move $fp, $sp + subu $sp, $sp, 60 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # IF local_1 GOTO label_65 ; + lw $t0, -8($fp) + bnez $t0, label_65 + # local_3 = 0 < i ; + li $t0, 0 + lw $t1, 0($fp) + slt $t0, $t0, $t1 + sw $t0, -16($fp) + # IF local_3 GOTO label_63 ; + lw $t0, -16($fp) + bnez $t0, label_63 + # local_7 = LOAD data_18 ; + la $t0, data_18 + sw $t0, -32($fp) + # local_8 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -36($fp) + # local_9 = ~ 1 + li $t0, 1 + neg $t0, $t0 + sw $t0, -40($fp) + # local_10 = i * local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + mul $t0, $t0, $t1 + sw $t0, -44($fp) + # local_11 = VCALL local_8 i2a_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -36($fp) + ulw $t1, 100($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = VCALL String concat ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_concat + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # GOTO label_64 ; + b label_64 + # LABEL label_63 ; + label_63: + + # local_4 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -20($fp) + # local_5 = VCALL local_4 i2a_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG i ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -20($fp) + ulw $t1, 100($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_13 = local_5 ; + lw $t0, -24($fp) + sw $t0, -56($fp) + # LABEL label_64 ; + label_64: + + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # GOTO label_66 ; + b label_66 + # LABEL label_65 ; + label_65: + + # local_2 = LOAD data_7 ; + la $t0, data_7 + sw $t0, -12($fp) + # local_14 = local_2 ; + lw $t0, -12($fp) + sw $t0, -60($fp) + # LABEL label_66 ; + label_66: + + # RETURN local_14 ; + lw $v0, -60($fp) + addu $sp, $sp, 60 + jr $ra +A2I_i2a_aux: + move $fp, $sp + subu $sp, $sp, 56 + # local_0 = i == 0 ; + lw $t0, 0($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -4($fp) + # local_1 = local_0 ; + lw $t0, -4($fp) + sw $t0, -8($fp) + # IF local_1 GOTO label_67 ; + lw $t0, -8($fp) + bnez $t0, label_67 + # local_3 = i / 10 ; + lw $t0, 0($fp) + li $t1, 10 + div $t0, $t0, $t1 + sw $t0, -16($fp) + # next = local_3 ; + lw $t0, -16($fp) + sw $t0, -20($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = VCALL local_6 i2a_aux ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG next ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 100($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # local_8 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -36($fp) + # local_9 = next * 10 ; + lw $t0, -20($fp) + li $t1, 10 + mul $t0, $t0, $t1 + sw $t0, -40($fp) + # local_10 = i - local_9 ; + lw $t0, 0($fp) + lw $t1, -40($fp) + sub $t0, $t0, $t1 + sw $t0, -44($fp) + # local_11 = VCALL local_8 i2c ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -36($fp) + ulw $t1, 84($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = VCALL String concat ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1024 ; + li $t0, 1024 + subu $sp, $sp, 4 + sw $t0, ($sp) + jal String_concat + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # GOTO label_68 ; + b label_68 + # LABEL label_67 ; + label_67: + + # local_2 = LOAD data_17 ; + la $t0, data_17 + sw $t0, -12($fp) + # local_13 = local_2 ; + lw $t0, -12($fp) + sw $t0, -56($fp) + # LABEL label_68 ; + label_68: + + # RETURN local_13 ; + lw $v0, -56($fp) + addu $sp, $sp, 56 + jr $ra +Main___init__: + move $fp, $sp + subu $sp, $sp, 12 + # local_1 = LOAD data_20 ; + la $t0, data_20 + sw $t0, -8($fp) + # SETATTR self @type local_1 ; + lw $t0, -8($fp) + lw $t1, 0($fp) + sw $t0, 0($t1) + # local_2 = 28 ; + li $t0, 28 + sw $t0, -12($fp) + # SETATTR self size local_2 ; + lw $t0, -12($fp) + lw $t1, 0($fp) + sw $t0, 4($t1) + # SETATTR self flag 1 ; + li $t0, 1 + lw $t1, 0($fp) + sw $t0, 24($t1) + # RETURN local_0 ; + lw $v0, -4($fp) + addu $sp, $sp, 12 + jr $ra +Main_menu: + move $fp, $sp + subu $sp, $sp, 320 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = LOAD data_21 ; + la $t0, data_21 + sw $t0, -8($fp) + # local_2 = VCALL local_0 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # local_3 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -20($fp) + # local_5 = VCALL local_3 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = LOAD data_22 ; + la $t0, data_22 + sw $t0, -32($fp) + # local_8 = VCALL local_6 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_9 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -40($fp) + # local_10 = LOAD data_23 ; + la $t0, data_23 + sw $t0, -44($fp) + # local_11 = VCALL local_9 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -40($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -52($fp) + # local_13 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -56($fp) + # local_14 = VCALL local_12 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -52($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -60($fp) + # local_15 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -64($fp) + # local_16 = LOAD data_24 ; + la $t0, data_24 + sw $t0, -68($fp) + # local_17 = VCALL local_15 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_16 ; + lw $t0, -68($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -64($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -72($fp) + # local_18 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -76($fp) + # local_19 = LOAD data_25 ; + la $t0, data_25 + sw $t0, -80($fp) + # local_20 = VCALL local_18 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_19 ; + lw $t0, -80($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -76($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -84($fp) + # local_21 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -88($fp) + # local_22 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -92($fp) + # local_23 = VCALL local_21 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_22 ; + lw $t0, -92($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -88($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -96($fp) + # local_24 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -100($fp) + # local_25 = LOAD data_26 ; + la $t0, data_26 + sw $t0, -104($fp) + # local_26 = VCALL local_24 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_25 ; + lw $t0, -104($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -100($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -108($fp) + # local_27 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -112($fp) + # local_28 = LOAD data_27 ; + la $t0, data_27 + sw $t0, -116($fp) + # local_29 = VCALL local_27 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_28 ; + lw $t0, -116($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -112($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -120($fp) + # local_30 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_31 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -128($fp) + # local_32 = VCALL local_30 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_31 ; + lw $t0, -128($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -124($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -132($fp) + # local_33 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -136($fp) + # local_34 = LOAD data_28 ; + la $t0, data_28 + sw $t0, -140($fp) + # local_35 = VCALL local_33 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_34 ; + lw $t0, -140($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -136($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -144($fp) + # local_36 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -148($fp) + # local_37 = LOAD data_29 ; + la $t0, data_29 + sw $t0, -152($fp) + # local_38 = VCALL local_36 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_37 ; + lw $t0, -152($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -148($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -156($fp) + # local_39 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -160($fp) + # local_40 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -164($fp) + # local_41 = VCALL local_39 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_40 ; + lw $t0, -164($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -160($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -168($fp) + # local_42 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -172($fp) + # local_43 = LOAD data_30 ; + la $t0, data_30 + sw $t0, -176($fp) + # local_44 = VCALL local_42 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_43 ; + lw $t0, -176($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -172($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -180($fp) + # local_45 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -184($fp) + # local_46 = LOAD data_31 ; + la $t0, data_31 + sw $t0, -188($fp) + # local_47 = VCALL local_45 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_46 ; + lw $t0, -188($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -184($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -192($fp) + # local_48 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -196($fp) + # local_49 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -200($fp) + # local_50 = VCALL local_48 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_49 ; + lw $t0, -200($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -196($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -204($fp) + # local_51 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -208($fp) + # local_52 = LOAD data_32 ; + la $t0, data_32 + sw $t0, -212($fp) + # local_53 = VCALL local_51 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_52 ; + lw $t0, -212($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -208($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -216($fp) + # local_54 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -220($fp) + # local_55 = LOAD data_33 ; + la $t0, data_33 + sw $t0, -224($fp) + # local_56 = VCALL local_54 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_55 ; + lw $t0, -224($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -220($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -228($fp) + # local_57 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -232($fp) + # local_58 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -236($fp) + # local_59 = VCALL local_57 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_58 ; + lw $t0, -236($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -232($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -240($fp) + # local_60 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -244($fp) + # local_61 = LOAD data_34 ; + la $t0, data_34 + sw $t0, -248($fp) + # local_62 = VCALL local_60 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_61 ; + lw $t0, -248($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -244($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -252($fp) + # local_63 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -256($fp) + # local_64 = LOAD data_35 ; + la $t0, data_35 + sw $t0, -260($fp) + # local_65 = VCALL local_63 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_64 ; + lw $t0, -260($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -256($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -264($fp) + # local_66 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -268($fp) + # local_67 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -272($fp) + # local_68 = VCALL local_66 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_67 ; + lw $t0, -272($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -268($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -276($fp) + # local_69 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -280($fp) + # local_70 = LOAD data_36 ; + la $t0, data_36 + sw $t0, -284($fp) + # local_71 = VCALL local_69 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_70 ; + lw $t0, -284($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -280($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -288($fp) + # local_72 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -292($fp) + # local_73 = LOAD data_37 ; + la $t0, data_37 + sw $t0, -296($fp) + # local_74 = VCALL local_72 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_73 ; + lw $t0, -296($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -292($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -300($fp) + # local_75 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -304($fp) + # local_76 = LOAD data_38 ; + la $t0, data_38 + sw $t0, -308($fp) + # local_77 = VCALL local_75 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_76 ; + lw $t0, -308($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -304($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -312($fp) + # local_78 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -316($fp) + # local_79 = VCALL local_78 in_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 0 ; + li $t0, 0 + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -316($fp) + ulw $t1, 20($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -320($fp) + # RETURN local_79 ; + lw $v0, -320($fp) + addu $sp, $sp, 320 + jr $ra +Main_prompt: + move $fp, $sp + subu $sp, $sp, 32 + # local_0 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -4($fp) + # local_1 = LOAD data_39 ; + la $t0, data_39 + sw $t0, -8($fp) + # local_2 = VCALL local_0 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_1 ; + lw $t0, -8($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -4($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -12($fp) + # local_3 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = LOAD data_40 ; + la $t0, data_40 + sw $t0, -20($fp) + # local_5 = VCALL local_3 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = VCALL local_6 in_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG 1024 ; + li $t0, 1024 + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 20($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # RETURN local_7 ; + lw $v0, -32($fp) + addu $sp, $sp, 32 + jr $ra +Main_get_int: + move $fp, $sp + subu $sp, $sp, 32 + # local_0 = ALLOCATE A2I ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -4($fp) + la $t0, vt_A2I + sw $t0, 8($v0) + # local_1 = VCALL A2I __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A2I___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # z = local_0 ; + lw $t0, -4($fp) + sw $t0, -12($fp) + # local_3 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = VCALL local_3 prompt ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 108($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # s = local_4 ; + lw $t0, -20($fp) + sw $t0, -24($fp) + # local_6 = GETTYPEADDR z ; + lw $t1, -12($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = VCALL local_6 a2i ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG z ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) # ARG s ; + lw $t0, -24($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 88($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # RETURN local_7 ; + lw $v0, -32($fp) + addu $sp, $sp, 32 + jr $ra +Main_is_even: + move $fp, $sp + subu $sp, $sp, 60 + # x = num ; + lw $t0, 0($fp) + sw $t0, -4($fp) + # local_1 = x < 0 ; + lw $t0, -4($fp) + li $t1, 0 + slt $t0, $t0, $t1 + sw $t0, -8($fp) + # IF local_1 GOTO label_73 ; + lw $t0, -8($fp) + bnez $t0, label_73 + # local_5 = 0 == x ; + li $t0, 0 + lw $t1, -4($fp) + seq $t0, $t0, $t1 + sw $t0, -24($fp) + # local_6 = local_5 ; + lw $t0, -24($fp) + sw $t0, -28($fp) + # IF local_6 GOTO label_71 ; + lw $t0, -28($fp) + bnez $t0, label_71 + # local_7 = 1 == x ; + li $t0, 1 + lw $t1, -4($fp) + seq $t0, $t0, $t1 + sw $t0, -32($fp) + # local_8 = local_7 ; + lw $t0, -32($fp) + sw $t0, -36($fp) + # IF local_8 GOTO label_69 ; + lw $t0, -36($fp) + bnez $t0, label_69 + # local_9 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -40($fp) + # local_10 = x - 2 ; + lw $t0, -4($fp) + li $t1, 2 + sub $t0, $t0, $t1 + sw $t0, -44($fp) + # local_11 = VCALL local_9 is_even ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -40($fp) + ulw $t1, 116($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # local_12 = local_11 ; + lw $t0, -48($fp) + sw $t0, -52($fp) + # GOTO label_70 ; + b label_70 + # LABEL label_69 ; + label_69: + + # local_12 = 0 ; + li $t0, 0 + sw $t0, -52($fp) + # LABEL label_70 ; + label_70: + + # local_13 = local_12 ; + lw $t0, -52($fp) + sw $t0, -56($fp) + # GOTO label_72 ; + b label_72 + # LABEL label_71 ; + label_71: + + # local_13 = 1 ; + li $t0, 1 + sw $t0, -56($fp) + # LABEL label_72 ; + label_72: + + # local_14 = local_13 ; + lw $t0, -56($fp) + sw $t0, -60($fp) + # GOTO label_74 ; + b label_74 + # LABEL label_73 ; + label_73: + + # local_2 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -12($fp) + # local_3 = ~ x + lw $t0, -4($fp) + neg $t0, $t0 + sw $t0, -16($fp) + # local_4 = VCALL local_2 is_even ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_3 ; + lw $t0, -16($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -12($fp) + ulw $t1, 116($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -20($fp) + # local_14 = local_4 ; + lw $t0, -20($fp) + sw $t0, -60($fp) + # LABEL label_74 ; + label_74: + + # RETURN local_14 ; + lw $v0, -60($fp) + addu $sp, $sp, 60 + jr $ra +Main_class_type: + move $fp, $sp + subu $sp, $sp, 172 + # local_0 = TYPEOF var ; + lw $t0, 0($fp) + lw $t1, ($t0) + sw $t1, -4($fp) + # local_3 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -16($fp) + # local_2 = local_0 == local_3 ; + lw $t0, -4($fp) + lw $t1, -16($fp) + li $v0, 1 + sw $v0, -12($fp) + equal_loop_13: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_13 + beqz $t2, end_loop_13 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_13 + b end_loop_13 + not_equal_13: + + li $v0, 0 + sw $v0, -12($fp) + end_loop_13: + + # local_1 = local_2 == 0 ; + lw $t0, -12($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -8($fp) + # IF local_1 GOTO label_75 ; + lw $t0, -8($fp) + bnez $t0, label_75 + # a = var ; + lw $t0, 0($fp) + sw $t0, -20($fp) + # local_5 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_6 = LOAD data_41 ; + la $t0, data_41 + sw $t0, -28($fp) + # local_7 = VCALL local_5 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_6 ; + lw $t0, -28($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -24($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # LABEL label_75 ; + label_75: + + # local_10 = LOAD data_2 ; + la $t0, data_2 + sw $t0, -44($fp) + # local_9 = local_0 == local_10 ; + lw $t0, -4($fp) + lw $t1, -44($fp) + li $v0, 1 + sw $v0, -40($fp) + equal_loop_14: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_14 + beqz $t2, end_loop_14 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_14 + b end_loop_14 + not_equal_14: + + li $v0, 0 + sw $v0, -40($fp) + end_loop_14: + + # local_8 = local_9 == 0 ; + lw $t0, -40($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -36($fp) + # IF local_8 GOTO label_76 ; + lw $t0, -36($fp) + bnez $t0, label_76 + # b = var ; + lw $t0, 0($fp) + sw $t0, -48($fp) + # local_12 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -52($fp) + # local_13 = LOAD data_42 ; + la $t0, data_42 + sw $t0, -56($fp) + # local_14 = VCALL local_12 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_13 ; + lw $t0, -56($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -52($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -60($fp) + # LABEL label_76 ; + label_76: + + # local_17 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -72($fp) + # local_16 = local_0 == local_17 ; + lw $t0, -4($fp) + lw $t1, -72($fp) + li $v0, 1 + sw $v0, -68($fp) + equal_loop_15: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_15 + beqz $t2, end_loop_15 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_15 + b end_loop_15 + not_equal_15: + + li $v0, 0 + sw $v0, -68($fp) + end_loop_15: + + # local_15 = local_16 == 0 ; + lw $t0, -68($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -64($fp) + # IF local_15 GOTO label_77 ; + lw $t0, -64($fp) + bnez $t0, label_77 + # c = var ; + lw $t0, 0($fp) + sw $t0, -76($fp) + # local_19 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -80($fp) + # local_20 = LOAD data_43 ; + la $t0, data_43 + sw $t0, -84($fp) + # local_21 = VCALL local_19 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_20 ; + lw $t0, -84($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -80($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -88($fp) + # LABEL label_77 ; + label_77: + + # local_24 = LOAD data_4 ; + la $t0, data_4 + sw $t0, -100($fp) + # local_23 = local_0 == local_24 ; + lw $t0, -4($fp) + lw $t1, -100($fp) + li $v0, 1 + sw $v0, -96($fp) + equal_loop_16: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_16 + beqz $t2, end_loop_16 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_16 + b end_loop_16 + not_equal_16: + + li $v0, 0 + sw $v0, -96($fp) + end_loop_16: + + # local_22 = local_23 == 0 ; + lw $t0, -96($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -92($fp) + # IF local_22 GOTO label_78 ; + lw $t0, -92($fp) + bnez $t0, label_78 + # d = var ; + lw $t0, 0($fp) + sw $t0, -104($fp) + # local_26 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -108($fp) + # local_27 = LOAD data_44 ; + la $t0, data_44 + sw $t0, -112($fp) + # local_28 = VCALL local_26 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_27 ; + lw $t0, -112($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -108($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -116($fp) + # LABEL label_78 ; + label_78: + + # local_31 = LOAD data_5 ; + la $t0, data_5 + sw $t0, -128($fp) + # local_30 = local_0 == local_31 ; + lw $t0, -4($fp) + lw $t1, -128($fp) + li $v0, 1 + sw $v0, -124($fp) + equal_loop_17: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_17 + beqz $t2, end_loop_17 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_17 + b end_loop_17 + not_equal_17: + + li $v0, 0 + sw $v0, -124($fp) + end_loop_17: + + # local_29 = local_30 == 0 ; + lw $t0, -124($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -120($fp) + # IF local_29 GOTO label_79 ; + lw $t0, -120($fp) + bnez $t0, label_79 + # e = var ; + lw $t0, 0($fp) + sw $t0, -132($fp) + # local_33 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -136($fp) + # local_34 = LOAD data_45 ; + la $t0, data_45 + sw $t0, -140($fp) + # local_35 = VCALL local_33 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_34 ; + lw $t0, -140($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -136($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -144($fp) + # LABEL label_79 ; + label_79: + + # local_38 = LOAD data_46 ; + la $t0, data_46 + sw $t0, -156($fp) + # local_37 = local_0 == local_38 ; + lw $t0, -4($fp) + lw $t1, -156($fp) + li $v0, 1 + sw $v0, -152($fp) + equal_loop_18: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_18 + beqz $t2, end_loop_18 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_18 + b end_loop_18 + not_equal_18: + + li $v0, 0 + sw $v0, -152($fp) + end_loop_18: + + # local_36 = local_37 == 0 ; + lw $t0, -152($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -148($fp) + # IF local_36 GOTO label_80 ; + lw $t0, -148($fp) + bnez $t0, label_80 + # o = var ; + lw $t0, 0($fp) + sw $t0, -160($fp) + # local_40 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -164($fp) + # local_41 = LOAD data_47 ; + la $t0, data_47 + sw $t0, -168($fp) + # local_42 = VCALL local_40 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_41 ; + lw $t0, -168($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -164($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -172($fp) + # LABEL label_80 ; + label_80: + + # RETURN local_42 ; + lw $v0, -172($fp) + addu $sp, $sp, 172 + jr $ra +Main_print: + move $fp, $sp + subu $sp, $sp, 48 + # local_0 = ALLOCATE A2I ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -4($fp) + la $t0, vt_A2I + sw $t0, 8($v0) + # local_1 = VCALL A2I __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A2I___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # z = local_0 ; + lw $t0, -4($fp) + sw $t0, -12($fp) + # local_3 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = GETTYPEADDR z ; + lw $t1, -12($fp) + lw $t0, 8($t1) + sw $t0, -20($fp) + # local_5 = GETTYPEADDR var ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -24($fp) + # local_6 = VCALL local_5 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG var ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -24($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -28($fp) + # local_7 = VCALL local_4 i2a ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG z ; + lw $t0, -12($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_6 ; + lw $t0, -28($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -20($fp) + ulw $t1, 96($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -32($fp) + # local_8 = VCALL local_3 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_9 = GETTYPEADDR self ; + lw $t1, 4($fp) + lw $t0, 8($t1) + sw $t0, -40($fp) + # local_10 = LOAD data_48 ; + la $t0, data_48 + sw $t0, -44($fp) + # local_11 = VCALL local_9 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_10 ; + lw $t0, -44($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -40($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -48($fp) + # RETURN local_11 ; + lw $v0, -48($fp) + addu $sp, $sp, 48 + jr $ra +Main_main: + move $fp, $sp + subu $sp, $sp, 912 + # local_0 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -4($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_1 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_0 ; + lw $t0, -4($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -8($fp) + # SETATTR self avar local_0 ; + lw $t0, -4($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # LABEL label_108 ; + label_108: + + # local_2 = GETATTR self flag ; + lw $t0, 0($fp) + lw $t1, 24($t0) + sw $t1, -12($fp) + # IF local_2 GOTO label_109 ; + lw $t0, -12($fp) + bnez $t0, label_109 + # GOTO label_110 ; + b label_110 + # LABEL label_109 ; + label_109: + + # local_3 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -16($fp) + # local_4 = LOAD data_49 ; + la $t0, data_49 + sw $t0, -20($fp) + # local_5 = VCALL local_3 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -16($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -24($fp) + # local_6 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -28($fp) + # local_7 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -32($fp) + # local_8 = VCALL local_6 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_7 ; + lw $t0, -32($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -28($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -36($fp) + # local_9 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -40($fp) + # local_11 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -48($fp) + # local_10 = GETTYPEADDR local_11 ; + lw $t1, -48($fp) + lw $t0, 8($t1) + sw $t0, -44($fp) + # local_12 = VCALL local_10 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_11 ; + lw $t0, -48($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -44($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -52($fp) + # local_13 = VCALL local_9 is_even ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_12 ; + lw $t0, -52($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -40($fp) + ulw $t1, 116($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -56($fp) + # IF local_13 GOTO label_81 ; + lw $t0, -56($fp) + bnez $t0, label_81 + # local_17 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -72($fp) + # local_18 = LOAD data_51 ; + la $t0, data_51 + sw $t0, -76($fp) + # local_19 = VCALL local_17 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_18 ; + lw $t0, -76($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -72($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -80($fp) + # local_20 = local_19 ; + lw $t0, -80($fp) + sw $t0, -84($fp) + # GOTO label_82 ; + b label_82 + # LABEL label_81 ; + label_81: + + # local_14 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -60($fp) + # local_15 = LOAD data_50 ; + la $t0, data_50 + sw $t0, -64($fp) + # local_16 = VCALL local_14 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_15 ; + lw $t0, -64($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -60($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -68($fp) + # local_20 = local_16 ; + lw $t0, -68($fp) + sw $t0, -84($fp) + # LABEL label_82 ; + label_82: + + # local_21 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -88($fp) + # local_22 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -92($fp) + # local_23 = VCALL local_21 class_type ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_22 ; + lw $t0, -92($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -88($fp) + ulw $t1, 120($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -96($fp) + # local_24 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -100($fp) + # local_25 = VCALL local_24 menu ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -100($fp) + ulw $t1, 104($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -104($fp) + # SETATTR self char local_25 ; + lw $t0, -104($fp) + lw $t1, 0($fp) + sw $t0, 12($t1) + # local_26 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -108($fp) + # local_27 = LOAD data_52 ; + la $t0, data_52 + sw $t0, -112($fp) + # local_28 = local_26 == local_27 ; + lw $t0, -108($fp) + lw $t1, -112($fp) + li $v0, 1 + sw $v0, -116($fp) + equal_loop_19: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_19 + beqz $t2, end_loop_19 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_19 + b end_loop_19 + not_equal_19: + + li $v0, 0 + sw $v0, -116($fp) + end_loop_19: + + # local_29 = local_28 ; + lw $t0, -116($fp) + sw $t0, -120($fp) + # IF local_29 GOTO label_106 ; + lw $t0, -120($fp) + bnez $t0, label_106 + # local_46 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -188($fp) + # local_47 = LOAD data_53 ; + la $t0, data_53 + sw $t0, -192($fp) + # local_48 = local_46 == local_47 ; + lw $t0, -188($fp) + lw $t1, -192($fp) + li $v0, 1 + sw $v0, -196($fp) + equal_loop_20: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_20 + beqz $t2, end_loop_20 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_20 + b end_loop_20 + not_equal_20: + + li $v0, 0 + sw $v0, -196($fp) + end_loop_20: + + # local_49 = local_48 ; + lw $t0, -196($fp) + sw $t0, -200($fp) + # IF local_49 GOTO label_104 ; + lw $t0, -200($fp) + bnez $t0, label_104 + # local_77 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -312($fp) + # local_78 = LOAD data_54 ; + la $t0, data_54 + sw $t0, -316($fp) + # local_79 = local_77 == local_78 ; + lw $t0, -312($fp) + lw $t1, -316($fp) + li $v0, 1 + sw $v0, -320($fp) + equal_loop_21: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_21 + beqz $t2, end_loop_21 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_21 + b end_loop_21 + not_equal_21: + + li $v0, 0 + sw $v0, -320($fp) + end_loop_21: + + # local_80 = local_79 ; + lw $t0, -320($fp) + sw $t0, -324($fp) + # IF local_80 GOTO label_102 ; + lw $t0, -324($fp) + bnez $t0, label_102 + # local_97 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -392($fp) + # local_98 = LOAD data_55 ; + la $t0, data_55 + sw $t0, -396($fp) + # local_99 = local_97 == local_98 ; + lw $t0, -392($fp) + lw $t1, -396($fp) + li $v0, 1 + sw $v0, -400($fp) + equal_loop_22: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_22 + beqz $t2, end_loop_22 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_22 + b end_loop_22 + not_equal_22: + + li $v0, 0 + sw $v0, -400($fp) + end_loop_22: + + # local_100 = local_99 ; + lw $t0, -400($fp) + sw $t0, -404($fp) + # IF local_100 GOTO label_100 ; + lw $t0, -404($fp) + bnez $t0, label_100 + # local_108 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -436($fp) + # local_109 = LOAD data_56 ; + la $t0, data_56 + sw $t0, -440($fp) + # local_110 = local_108 == local_109 ; + lw $t0, -436($fp) + lw $t1, -440($fp) + li $v0, 1 + sw $v0, -444($fp) + equal_loop_23: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_23 + beqz $t2, end_loop_23 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_23 + b end_loop_23 + not_equal_23: + + li $v0, 0 + sw $v0, -444($fp) + end_loop_23: + + # local_111 = local_110 ; + lw $t0, -444($fp) + sw $t0, -448($fp) + # IF local_111 GOTO label_98 ; + lw $t0, -448($fp) + bnez $t0, label_98 + # local_119 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -480($fp) + # local_120 = LOAD data_57 ; + la $t0, data_57 + sw $t0, -484($fp) + # local_121 = local_119 == local_120 ; + lw $t0, -480($fp) + lw $t1, -484($fp) + li $v0, 1 + sw $v0, -488($fp) + equal_loop_24: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_24 + beqz $t2, end_loop_24 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_24 + b end_loop_24 + not_equal_24: + + li $v0, 0 + sw $v0, -488($fp) + end_loop_24: + + # local_122 = local_121 ; + lw $t0, -488($fp) + sw $t0, -492($fp) + # IF local_122 GOTO label_96 ; + lw $t0, -492($fp) + bnez $t0, label_96 + # local_130 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -524($fp) + # local_131 = LOAD data_58 ; + la $t0, data_58 + sw $t0, -528($fp) + # local_132 = local_130 == local_131 ; + lw $t0, -524($fp) + lw $t1, -528($fp) + li $v0, 1 + sw $v0, -532($fp) + equal_loop_25: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_25 + beqz $t2, end_loop_25 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_25 + b end_loop_25 + not_equal_25: + + li $v0, 0 + sw $v0, -532($fp) + end_loop_25: + + # local_133 = local_132 ; + lw $t0, -532($fp) + sw $t0, -536($fp) + # IF local_133 GOTO label_94 ; + lw $t0, -536($fp) + bnez $t0, label_94 + # local_158 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -636($fp) + # local_159 = LOAD data_61 ; + la $t0, data_61 + sw $t0, -640($fp) + # local_160 = local_158 == local_159 ; + lw $t0, -636($fp) + lw $t1, -640($fp) + li $v0, 1 + sw $v0, -644($fp) + equal_loop_26: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_26 + beqz $t2, end_loop_26 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_26 + b end_loop_26 + not_equal_26: + + li $v0, 0 + sw $v0, -644($fp) + end_loop_26: + + # local_161 = local_160 ; + lw $t0, -644($fp) + sw $t0, -648($fp) + # IF local_161 GOTO label_92 ; + lw $t0, -648($fp) + bnez $t0, label_92 + # local_200 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -804($fp) + # local_201 = LOAD data_64 ; + la $t0, data_64 + sw $t0, -808($fp) + # local_202 = local_200 == local_201 ; + lw $t0, -804($fp) + lw $t1, -808($fp) + li $v0, 1 + sw $v0, -812($fp) + equal_loop_27: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_27 + beqz $t2, end_loop_27 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_27 + b end_loop_27 + not_equal_27: + + li $v0, 0 + sw $v0, -812($fp) + end_loop_27: + + # local_203 = local_202 ; + lw $t0, -812($fp) + sw $t0, -816($fp) + # IF local_203 GOTO label_90 ; + lw $t0, -816($fp) + bnez $t0, label_90 + # local_206 = GETATTR self char ; + lw $t0, 0($fp) + lw $t1, 12($t0) + sw $t1, -828($fp) + # local_207 = LOAD data_65 ; + la $t0, data_65 + sw $t0, -832($fp) + # local_208 = local_206 == local_207 ; + lw $t0, -828($fp) + lw $t1, -832($fp) + li $v0, 1 + sw $v0, -836($fp) + equal_loop_28: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_28 + beqz $t2, end_loop_28 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_28 + b end_loop_28 + not_equal_28: + + li $v0, 0 + sw $v0, -836($fp) + end_loop_28: + + # local_209 = local_208 ; + lw $t0, -836($fp) + sw $t0, -840($fp) + # IF local_209 GOTO label_88 ; + lw $t0, -840($fp) + bnez $t0, label_88 + # local_211 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -848($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_212 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_211 ; + lw $t0, -848($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -852($fp) + # local_210 = GETTYPEADDR local_211 ; + lw $t1, -848($fp) + lw $t0, 8($t1) + sw $t0, -844($fp) + # local_214 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -860($fp) + # local_213 = GETTYPEADDR local_214 ; + lw $t1, -860($fp) + lw $t0, 8($t1) + sw $t0, -856($fp) + # local_215 = VCALL local_213 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_214 ; + lw $t0, -860($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -856($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -864($fp) + # local_216 = VCALL local_210 method1 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_211 ; + lw $t0, -848($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_215 ; + lw $t0, -864($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -844($fp) + ulw $t1, 48($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -868($fp) + # SETATTR self avar local_216 ; + lw $t0, -868($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_217 = local_216 ; + lw $t0, -868($fp) + sw $t0, -872($fp) + # GOTO label_89 ; + b label_89 + # LABEL label_88 ; + label_88: + + # SETATTR self flag 0 ; + li $t0, 0 + lw $t1, 0($fp) + sw $t0, 24($t1) + # local_217 = 0 ; + li $t0, 0 + sw $t0, -872($fp) + # LABEL label_89 ; + label_89: + + # local_218 = local_217 ; + lw $t0, -872($fp) + sw $t0, -876($fp) + # GOTO label_91 ; + b label_91 + # LABEL label_90 ; + label_90: + + # local_204 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -820($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_205 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_204 ; + lw $t0, -820($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -824($fp) + # SETATTR self avar local_204 ; + lw $t0, -820($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_218 = local_204 ; + lw $t0, -820($fp) + sw $t0, -876($fp) + # LABEL label_91 ; + label_91: + + # local_219 = local_218 ; + lw $t0, -876($fp) + sw $t0, -880($fp) + # GOTO label_93 ; + b label_93 + # LABEL label_92 ; + label_92: + + # local_163 = ALLOCATE E ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -656($fp) + la $t0, vt_E + sw $t0, 8($v0) + # local_164 = VCALL E __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_163 ; + lw $t0, -656($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal E___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -660($fp) + # local_162 = GETTYPEADDR local_163 ; + lw $t1, -656($fp) + lw $t0, 8($t1) + sw $t0, -652($fp) + # local_166 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -668($fp) + # local_165 = GETTYPEADDR local_166 ; + lw $t1, -668($fp) + lw $t0, 8($t1) + sw $t0, -664($fp) + # local_167 = VCALL local_165 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_166 ; + lw $t0, -668($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -664($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -672($fp) + # local_168 = VCALL local_162 method6 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_163 ; + lw $t0, -656($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_167 ; + lw $t0, -672($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -652($fp) + ulw $t1, 72($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -676($fp) + # x = local_168 ; + lw $t0, -676($fp) + sw $t0, -680($fp) + # local_171 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -688($fp) + # local_170 = GETTYPEADDR local_171 ; + lw $t1, -688($fp) + lw $t0, 8($t1) + sw $t0, -684($fp) + # local_172 = VCALL local_170 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_171 ; + lw $t0, -688($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -684($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -692($fp) + # local_173 = GETTYPEADDR x ; + lw $t1, -680($fp) + lw $t0, 8($t1) + sw $t0, -696($fp) + # local_174 = VCALL local_173 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG x ; + lw $t0, -680($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -696($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -700($fp) + # local_175 = local_174 * 8 ; + lw $t0, -700($fp) + li $t1, 8 + mul $t0, $t0, $t1 + sw $t0, -704($fp) + # local_176 = local_172 - local_175 ; + lw $t0, -692($fp) + lw $t1, -704($fp) + sub $t0, $t0, $t1 + sw $t0, -708($fp) + # r = local_176 ; + lw $t0, -708($fp) + sw $t0, -712($fp) + # local_178 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -716($fp) + # local_179 = VCALL local_178 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -716($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -720($fp) + # local_180 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -724($fp) + # local_181 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -728($fp) + # local_182 = VCALL local_180 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_181 ; + lw $t0, -728($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -724($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -732($fp) + # local_183 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -736($fp) + # local_184 = LOAD data_62 ; + la $t0, data_62 + sw $t0, -740($fp) + # local_185 = VCALL local_183 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_184 ; + lw $t0, -740($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -736($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -744($fp) + # local_186 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -748($fp) + # local_187 = VCALL local_186 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG x ; + lw $t0, -680($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -748($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -752($fp) + # local_188 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -756($fp) + # local_189 = LOAD data_63 ; + la $t0, data_63 + sw $t0, -760($fp) + # local_190 = VCALL local_188 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_189 ; + lw $t0, -760($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -756($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -764($fp) + # local_191 = ALLOCATE A2I ; + li $a0, 12 + li $v0, 9 + syscall + sw $v0, -768($fp) + la $t0, vt_A2I + sw $t0, 8($v0) + # local_192 = VCALL A2I __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_191 ; + lw $t0, -768($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A2I___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -772($fp) + # a = local_191 ; + lw $t0, -768($fp) + sw $t0, -256($fp) + # local_193 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -776($fp) + # local_194 = GETTYPEADDR a ; + lw $t1, -256($fp) + lw $t0, 8($t1) + sw $t0, -780($fp) + # local_195 = VCALL local_194 i2a ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG a ; + lw $t0, -256($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG r ; + lw $t0, -712($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -780($fp) + ulw $t1, 96($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -784($fp) + # local_196 = VCALL local_193 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_195 ; + lw $t0, -784($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -776($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -788($fp) + # local_197 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -792($fp) + # local_198 = LOAD data_39 ; + la $t0, data_39 + sw $t0, -796($fp) + # local_199 = VCALL local_197 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_198 ; + lw $t0, -796($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -792($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -800($fp) + # SETATTR self avar x ; + lw $t0, -680($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_219 = x ; + lw $t0, -680($fp) + sw $t0, -880($fp) + # LABEL label_93 ; + label_93: + + # local_220 = local_219 ; + lw $t0, -880($fp) + sw $t0, -884($fp) + # GOTO label_95 ; + b label_95 + # LABEL label_94 ; + label_94: + + # local_135 = ALLOCATE D ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -544($fp) + la $t0, vt_D + sw $t0, 8($v0) + # local_136 = VCALL D __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_135 ; + lw $t0, -544($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal D___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -548($fp) + # local_134 = GETTYPEADDR local_135 ; + lw $t1, -544($fp) + lw $t0, 8($t1) + sw $t0, -540($fp) + # local_138 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -556($fp) + # local_137 = GETTYPEADDR local_138 ; + lw $t1, -556($fp) + lw $t0, 8($t1) + sw $t0, -552($fp) + # local_139 = VCALL local_137 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_138 ; + lw $t0, -556($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -552($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -560($fp) + # local_140 = VCALL local_134 method7 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_135 ; + lw $t0, -544($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_139 ; + lw $t0, -560($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -540($fp) + ulw $t1, 76($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -564($fp) + # IF local_140 GOTO label_86 ; + lw $t0, -564($fp) + bnez $t0, label_86 + # local_149 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -600($fp) + # local_150 = VCALL local_149 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -600($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -604($fp) + # local_151 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -608($fp) + # local_152 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -612($fp) + # local_153 = VCALL local_151 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_152 ; + lw $t0, -612($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -608($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -616($fp) + # local_154 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -620($fp) + # local_155 = LOAD data_60 ; + la $t0, data_60 + sw $t0, -624($fp) + # local_156 = VCALL local_154 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_155 ; + lw $t0, -624($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -620($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -628($fp) + # local_157 = local_156 ; + lw $t0, -628($fp) + sw $t0, -632($fp) + # GOTO label_87 ; + b label_87 + # LABEL label_86 ; + label_86: + + # local_141 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -568($fp) + # local_142 = VCALL local_141 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_4 ; + lw $t0, -20($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -568($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -572($fp) + # local_143 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -576($fp) + # local_144 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -580($fp) + # local_145 = VCALL local_143 print ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_144 ; + lw $t0, -580($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -576($fp) + ulw $t1, 124($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -584($fp) + # local_146 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -588($fp) + # local_147 = LOAD data_59 ; + la $t0, data_59 + sw $t0, -592($fp) + # local_148 = VCALL local_146 out_string ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; + lw $t0, 0($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_147 ; + lw $t0, -592($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -588($fp) + ulw $t1, 12($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -596($fp) + # local_157 = local_148 ; + lw $t0, -596($fp) + sw $t0, -632($fp) + # LABEL label_87 ; + label_87: + + # local_220 = local_157 ; + lw $t0, -632($fp) + sw $t0, -884($fp) + # LABEL label_95 ; + label_95: + + # local_221 = local_220 ; + lw $t0, -884($fp) + sw $t0, -888($fp) + # GOTO label_97 ; + b label_97 + # LABEL label_96 ; + label_96: + + # local_124 = ALLOCATE C ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -500($fp) + la $t0, vt_C + sw $t0, 8($v0) + # local_125 = VCALL C __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_124 ; + lw $t0, -500($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal C___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -504($fp) + # local_123 = GETTYPEADDR local_124 ; + lw $t1, -500($fp) + lw $t0, 8($t1) + sw $t0, -496($fp) + # local_127 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -512($fp) + # local_126 = GETTYPEADDR local_127 ; + lw $t1, -512($fp) + lw $t0, 8($t1) + sw $t0, -508($fp) + # local_128 = VCALL local_126 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_127 ; + lw $t0, -512($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -508($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -516($fp) + # local_129 = VCALL C method5 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_124 ; + lw $t0, -500($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_128 ; + lw $t0, -516($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal C_method5 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -520($fp) + # SETATTR self avar local_129 ; + lw $t0, -520($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_221 = local_129 ; + lw $t0, -520($fp) + sw $t0, -888($fp) + # LABEL label_97 ; + label_97: + + # local_222 = local_221 ; + lw $t0, -888($fp) + sw $t0, -892($fp) + # GOTO label_99 ; + b label_99 + # LABEL label_98 ; + label_98: + + # local_113 = ALLOCATE C ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -456($fp) + la $t0, vt_C + sw $t0, 8($v0) + # local_114 = VCALL C __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_113 ; + lw $t0, -456($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal C___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -460($fp) + # local_112 = GETTYPEADDR local_113 ; + lw $t1, -456($fp) + lw $t0, 8($t1) + sw $t0, -452($fp) + # local_116 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -468($fp) + # local_115 = GETTYPEADDR local_116 ; + lw $t1, -468($fp) + lw $t0, 8($t1) + sw $t0, -464($fp) + # local_117 = VCALL local_115 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_116 ; + lw $t0, -468($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -464($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -472($fp) + # local_118 = VCALL B method5 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_113 ; + lw $t0, -456($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_117 ; + lw $t0, -472($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal B_method5 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -476($fp) + # SETATTR self avar local_118 ; + lw $t0, -476($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_222 = local_118 ; + lw $t0, -476($fp) + sw $t0, -892($fp) + # LABEL label_99 ; + label_99: + + # local_223 = local_222 ; + lw $t0, -892($fp) + sw $t0, -896($fp) + # GOTO label_101 ; + b label_101 + # LABEL label_100 ; + label_100: + + # local_102 = ALLOCATE C ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -412($fp) + la $t0, vt_C + sw $t0, 8($v0) + # local_103 = VCALL C __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_102 ; + lw $t0, -412($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal C___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -416($fp) + # local_101 = GETTYPEADDR local_102 ; + lw $t1, -412($fp) + lw $t0, 8($t1) + sw $t0, -408($fp) + # local_105 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -424($fp) + # local_104 = GETTYPEADDR local_105 ; + lw $t1, -424($fp) + lw $t0, 8($t1) + sw $t0, -420($fp) + # local_106 = VCALL local_104 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_105 ; + lw $t0, -424($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -420($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -428($fp) + # local_107 = VCALL A method5 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_102 ; + lw $t0, -412($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_106 ; + lw $t0, -428($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A_method5 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -432($fp) + # SETATTR self avar local_107 ; + lw $t0, -432($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_223 = local_107 ; + lw $t0, -432($fp) + sw $t0, -896($fp) + # LABEL label_101 ; + label_101: + + # local_224 = local_223 ; + lw $t0, -896($fp) + sw $t0, -900($fp) + # GOTO label_103 ; + b label_103 + # LABEL label_102 ; + label_102: + + # local_82 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -332($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_83 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_82 ; + lw $t0, -332($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -336($fp) + # local_81 = GETTYPEADDR local_82 ; + lw $t1, -332($fp) + lw $t0, 8($t1) + sw $t0, -328($fp) + # local_84 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -340($fp) + # local_85 = VCALL local_84 get_int ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_length + lw $t0, -340($fp) + ulw $t1, 112($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -344($fp) + # local_86 = VCALL local_81 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_82 ; + lw $t0, -332($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_85 ; + lw $t0, -344($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -328($fp) + ulw $t1, 44($t0) + jalr $t1 + addu $sp, $sp, 8 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -348($fp) + # SETATTR self a_var local_86 ; + lw $t0, -348($fp) + lw $t1, 0($fp) + sw $t0, 20($t1) + # local_88 = ALLOCATE D ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -356($fp) + la $t0, vt_D + sw $t0, 8($v0) + # local_89 = VCALL D __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_88 ; + lw $t0, -356($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal D___init__ addu $sp, $sp, 4 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -84($fp) - # local_21 = local_20 - 2 ; - lw $t0, -84($fp) - li $t1, 2 - sub $t0, $t0, $t1 - sw $t0, -88($fp) - # local_22 = VCALL String substr ; + sw $v0, -360($fp) + # local_87 = GETTYPEADDR local_88 ; + lw $t1, -356($fp) + lw $t0, 8($t1) + sw $t0, -352($fp) + # local_91 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -368($fp) + # local_90 = GETTYPEADDR local_91 ; + lw $t1, -368($fp) + lw $t0, 8($t1) + sw $t0, -364($fp) + # local_92 = VCALL local_90 value ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG s ; + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_91 ; + lw $t0, -368($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -364($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -372($fp) + # local_94 = GETATTR self a_var ; lw $t0, 0($fp) + lw $t1, 20($t0) + sw $t1, -380($fp) + # local_93 = GETTYPEADDR local_94 ; + lw $t1, -380($fp) + lw $t0, 8($t1) + sw $t0, -376($fp) + # local_95 = VCALL local_93 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_94 ; + lw $t0, -380($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 1 ; - li $t0, 1 + lw $t0, -376($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -384($fp) + # local_96 = VCALL local_87 method4 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_88 ; + lw $t0, -356($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_21 ; - lw $t0, -88($fp) + # ARG local_92 ; + lw $t0, -372($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 2048 ; - li $t0, 2048 + # ARG local_95 ; + lw $t0, -384($fp) subu $sp, $sp, 4 sw $t0, ($sp) - jal String_substr - addu $sp, $sp, 16 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $t0, -352($fp) + ulw $t1, 60($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -92($fp) - # local_23 = VCALL local_17 pal ; + sw $v0, -388($fp) + # SETATTR self avar local_96 ; + lw $t0, -388($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_224 = local_96 ; + lw $t0, -388($fp) + sw $t0, -900($fp) + # LABEL label_103 ; + label_103: + + # local_225 = local_224 ; + lw $t0, -900($fp) + sw $t0, -904($fp) + # GOTO label_105 ; + b label_105 + # LABEL label_104 ; + label_104: + + # local_50 = GETATTR self avar ; + lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -204($fp) + # local_51 = TYPEOF local_50 ; + lw $t0, -204($fp) + lw $t1, ($t0) + sw $t1, -208($fp) + # local_54 = LOAD data_3 ; + la $t0, data_3 + sw $t0, -220($fp) + # local_53 = local_51 == local_54 ; + lw $t0, -208($fp) + lw $t1, -220($fp) + li $v0, 1 + sw $v0, -216($fp) + equal_loop_29: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_29 + beqz $t2, end_loop_29 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_29 + b end_loop_29 + not_equal_29: + + li $v0, 0 + sw $v0, -216($fp) + end_loop_29: + + # local_52 = local_53 == 0 ; + lw $t0, -216($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -212($fp) + # IF local_52 GOTO label_83 ; + lw $t0, -212($fp) + bnez $t0, label_83 + # c = local_50 ; + lw $t0, -204($fp) + sw $t0, -224($fp) + # local_56 = GETTYPEADDR c ; + lw $t1, -224($fp) + lw $t0, 8($t1) + sw $t0, -228($fp) + # local_57 = GETTYPEADDR c ; + lw $t1, -224($fp) + lw $t0, 8($t1) + sw $t0, -232($fp) + # local_58 = VCALL local_57 value ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG self ; - lw $t0, 4($fp) + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG c ; + lw $t0, -224($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_22 ; - lw $t0, -92($fp) + lw $t0, -232($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -236($fp) + # local_59 = VCALL local_56 method6 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG c ; + lw $t0, -224($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -72($fp) - ulw $t1, 40($t0) + # ARG local_58 ; + lw $t0, -236($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -228($fp) + ulw $t1, 72($t0) jalr $t1 addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -96($fp) - # local_24 = local_23 ; - lw $t0, -96($fp) - sw $t0, -100($fp) - # LABEL label_2 ; - label_2: - - # local_25 = local_24 ; - lw $t0, -100($fp) - sw $t0, -104($fp) - # GOTO label_4 ; - b label_4 - # LABEL label_3 ; - label_3: + sw $v0, -240($fp) + # SETATTR self avar local_59 ; + lw $t0, -240($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # LABEL label_83 ; + label_83: - # local_25 = 1 ; - li $t0, 1 - sw $t0, -104($fp) - # LABEL label_4 ; - label_4: + # local_62 = LOAD data_1 ; + la $t0, data_1 + sw $t0, -252($fp) + # local_61 = local_51 == local_62 ; + lw $t0, -208($fp) + lw $t1, -252($fp) + li $v0, 1 + sw $v0, -248($fp) + equal_loop_30: - # local_26 = local_25 ; - lw $t0, -104($fp) - sw $t0, -108($fp) - # GOTO label_6 ; - b label_6 - # LABEL label_5 ; - label_5: + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_30 + beqz $t2, end_loop_30 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_30 + b end_loop_30 + not_equal_30: - # local_26 = 1 ; - li $t0, 1 - sw $t0, -108($fp) - # LABEL label_6 ; - label_6: + li $v0, 0 + sw $v0, -248($fp) + end_loop_30: - # RETURN local_26 ; - lw $v0, -108($fp) - addu $sp, $sp, 108 - jr $ra -Main_main: - move $fp, $sp - subu $sp, $sp, 60 - # local_0 = ~ 1 - li $t0, 1 - not $t0, $t0 - sw $t0, -4($fp) - # SETATTR self i local_0 ; - lw $t0, -4($fp) - lw $t1, 0($fp) - sw $t0, 12($t1) - # local_1 = GETTYPEADDR self ; - lw $t1, 0($fp) + # local_60 = local_61 == 0 ; + lw $t0, -248($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -244($fp) + # IF local_60 GOTO label_84 ; + lw $t0, -244($fp) + bnez $t0, label_84 + # a = local_50 ; + lw $t0, -204($fp) + sw $t0, -256($fp) + # local_64 = GETTYPEADDR a ; + lw $t1, -256($fp) lw $t0, 8($t1) - sw $t0, -8($fp) - # local_2 = LOAD data_2 ; - la $t0, data_2 - sw $t0, -12($fp) - # local_3 = VCALL local_1 out_string ; + sw $t0, -260($fp) + # local_65 = GETTYPEADDR a ; + lw $t1, -256($fp) + lw $t0, 8($t1) + sw $t0, -264($fp) + # local_66 = VCALL local_65 value ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG self ; - lw $t0, 0($fp) + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG a ; + lw $t0, -256($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_2 ; - lw $t0, -12($fp) + lw $t0, -264($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -268($fp) + # local_67 = VCALL local_64 method3 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG a ; + lw $t0, -256($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -8($fp) - ulw $t1, 12($t0) + # ARG local_66 ; + lw $t0, -268($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -260($fp) + ulw $t1, 56($t0) jalr $t1 addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -16($fp) - # local_4 = GETTYPEADDR self ; + sw $v0, -272($fp) + # SETATTR self avar local_67 ; + lw $t0, -272($fp) lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -20($fp) - # local_5 = GETTYPEADDR self ; + sw $t0, 16($t1) + # LABEL label_84 ; + label_84: + + # local_70 = LOAD data_46 ; + la $t0, data_46 + sw $t0, -284($fp) + # local_69 = local_51 == local_70 ; + lw $t0, -208($fp) + lw $t1, -284($fp) + li $v0, 1 + sw $v0, -280($fp) + equal_loop_31: + + lb $t2, ($t0) + lb $t3, ($t1) + seq $t4, $t2, $t3 + beqz $t4, not_equal_31 + beqz $t2, end_loop_31 + addu $t0, $t0, 1 + addu $t1, $t1, 1 + b equal_loop_31 + b end_loop_31 + not_equal_31: + + li $v0, 0 + sw $v0, -280($fp) + end_loop_31: + + # local_68 = local_69 == 0 ; + lw $t0, -280($fp) + li $t1, 0 + seq $t0, $t0, $t1 + sw $t0, -276($fp) + # IF local_68 GOTO label_85 ; + lw $t0, -276($fp) + bnez $t0, label_85 + # o = local_50 ; + lw $t0, -204($fp) + sw $t0, -288($fp) + # local_72 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -24($fp) - # local_6 = VCALL local_5 in_string ; + sw $t0, -292($fp) + # local_73 = LOAD data_47 ; + la $t0, data_47 + sw $t0, -296($fp) + # local_74 = VCALL local_72 out_string ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) + sw $ra, 0($sp) + sw $fp, 4($sp) # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG 0 ; - li $t0, 0 + # ARG local_73 ; + lw $t0, -296($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -24($fp) - ulw $t1, 20($t0) + lw $t0, -292($fp) + ulw $t1, 12($t0) jalr $t1 addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -28($fp) - # local_7 = VCALL local_4 pal ; + sw $v0, -300($fp) + # local_75 = GETTYPEADDR self ; + lw $t1, 0($fp) + lw $t0, 8($t1) + sw $t0, -304($fp) + # local_76 = VCALL local_75 abort ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) + sw $ra, 0($sp) + sw $fp, 4($sp) # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_6 ; - lw $t0, -28($fp) - subu $sp, $sp, 4 - sw $t0, ($sp) - lw $t0, -20($fp) - ulw $t1, 40($t0) + lw $t0, -304($fp) + ulw $t1, 0($t0) jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + sw $v0, -308($fp) + # LABEL label_85 ; + label_85: + + # local_225 = 0 ; + li $t0, 0 + sw $t0, -904($fp) + # LABEL label_105 ; + label_105: + + # local_226 = local_225 ; + lw $t0, -904($fp) + sw $t0, -908($fp) + # GOTO label_107 ; + b label_107 + # LABEL label_106 ; + label_106: + + # local_31 = ALLOCATE A ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -128($fp) + la $t0, vt_A + sw $t0, 8($v0) + # local_32 = VCALL A __init__ ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_31 ; + lw $t0, -128($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal A___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -32($fp) - # IF local_7 GOTO label_7 ; - lw $t0, -32($fp) - bnez $t0, label_7 - # local_11 = GETTYPEADDR self ; + sw $v0, -132($fp) + # local_30 = GETTYPEADDR local_31 ; + lw $t1, -128($fp) + lw $t0, 8($t1) + sw $t0, -124($fp) + # local_33 = GETTYPEADDR self ; lw $t1, 0($fp) lw $t0, 8($t1) - sw $t0, -48($fp) - # local_12 = LOAD data_4 ; - la $t0, data_4 - sw $t0, -52($fp) - # local_13 = VCALL local_11 out_string ; + sw $t0, -136($fp) + # local_34 = VCALL local_33 get_int ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) + sw $ra, 0($sp) + sw $fp, 4($sp) # ARG self ; lw $t0, 0($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_12 ; - lw $t0, -52($fp) + lw $t0, -136($fp) + ulw $t1, 112($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -140($fp) + # local_35 = VCALL local_30 set_var ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_31 ; + lw $t0, -128($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -48($fp) - ulw $t1, 12($t0) + # ARG local_34 ; + lw $t0, -140($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -124($fp) + ulw $t1, 44($t0) jalr $t1 addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -56($fp) - # local_14 = local_13 ; - lw $t0, -56($fp) - sw $t0, -60($fp) - # GOTO label_8 ; - b label_8 - # LABEL label_7 ; - label_7: - - # local_8 = GETTYPEADDR self ; + sw $v0, -144($fp) + # SETATTR self a_var local_35 ; + lw $t0, -144($fp) lw $t1, 0($fp) - lw $t0, 8($t1) - sw $t0, -36($fp) - # local_9 = LOAD data_3 ; - la $t0, data_3 - sw $t0, -40($fp) - # local_10 = VCALL local_8 out_string ; + sw $t0, 20($t1) + # local_37 = ALLOCATE B ; + li $a0, 16 + li $v0, 9 + syscall + sw $v0, -152($fp) + la $t0, vt_B + sw $t0, 8($v0) + # local_38 = VCALL B __init__ ; subu $sp, $sp, 8 - sw $fp, 0($sp) - sw $ra, 4($sp) - # ARG self ; + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_37 ; + lw $t0, -152($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + jal B___init__ + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -156($fp) + # local_36 = GETTYPEADDR local_37 ; + lw $t1, -152($fp) + lw $t0, 8($t1) + sw $t0, -148($fp) + # local_40 = GETATTR self avar ; lw $t0, 0($fp) + lw $t1, 16($t0) + sw $t1, -164($fp) + # local_39 = GETTYPEADDR local_40 ; + lw $t1, -164($fp) + lw $t0, 8($t1) + sw $t0, -160($fp) + # local_41 = VCALL local_39 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_40 ; + lw $t0, -164($fp) subu $sp, $sp, 4 sw $t0, ($sp) - # ARG local_9 ; - lw $t0, -40($fp) + lw $t0, -160($fp) + ulw $t1, 40($t0) + jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) + addu $sp, $sp, 8 + sw $v0, -168($fp) + # local_43 = GETATTR self a_var ; + lw $t0, 0($fp) + lw $t1, 20($t0) + sw $t1, -176($fp) + # local_42 = GETTYPEADDR local_43 ; + lw $t1, -176($fp) + lw $t0, 8($t1) + sw $t0, -172($fp) + # local_44 = VCALL local_42 value ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_43 ; + lw $t0, -176($fp) subu $sp, $sp, 4 sw $t0, ($sp) - lw $t0, -36($fp) - ulw $t1, 12($t0) + lw $t0, -172($fp) + ulw $t1, 40($t0) jalr $t1 + addu $sp, $sp, 4 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - lw $fp, 0($sp) - lw $ra, 4($sp) + sw $v0, -180($fp) + # local_45 = VCALL local_36 method2 ; + subu $sp, $sp, 8 + sw $ra, 0($sp) + sw $fp, 4($sp) + # ARG local_37 ; + lw $t0, -152($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_41 ; + lw $t0, -168($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + # ARG local_44 ; + lw $t0, -180($fp) + subu $sp, $sp, 4 + sw $t0, ($sp) + lw $t0, -148($fp) + ulw $t1, 52($t0) + jalr $t1 + addu $sp, $sp, 12 + lw $ra, 0($sp) + lw $fp, 4($sp) addu $sp, $sp, 8 - sw $v0, -44($fp) - # local_14 = local_10 ; - lw $t0, -44($fp) - sw $t0, -60($fp) - # LABEL label_8 ; - label_8: + sw $v0, -184($fp) + # SETATTR self avar local_45 ; + lw $t0, -184($fp) + lw $t1, 0($fp) + sw $t0, 16($t1) + # local_226 = local_45 ; + lw $t0, -184($fp) + sw $t0, -908($fp) + # LABEL label_107 ; + label_107: - # RETURN local_14 ; - lw $v0, -60($fp) - addu $sp, $sp, 60 + # GOTO label_108 ; + b label_108 + # LABEL label_110 ; + label_110: + + # local_227 = 0 ; + li $t0, 0 + sw $t0, -912($fp) + # RETURN local_227 ; + lw $v0, -912($fp) + addu $sp, $sp, 912 jr $ra .data data_1: - .asciiz "Main" + .asciiz "A" data_2: - .asciiz "enter a string\n" + .asciiz "B" data_3: - .asciiz "that was a palindrome\n" + .asciiz "C" data_4: - .asciiz "that was not a palindrome\n" + .asciiz "D" data_5: - .asciiz "Bool" + .asciiz "E" data_6: - .asciiz "Int" + .asciiz "A2I" data_7: + .asciiz "0" + data_8: + .asciiz "1" + data_9: + .asciiz "2" + data_10: + .asciiz "3" + data_11: + .asciiz "4" + data_12: + .asciiz "5" + data_13: + .asciiz "6" + data_14: + .asciiz "7" + data_15: + .asciiz "8" + data_16: + .asciiz "9" + data_17: + .asciiz "" + data_18: + .asciiz "-" + data_19: + .asciiz "+" + data_20: + .asciiz "Main" + data_21: + .asciiz "\n\tTo add a number to " + data_22: + .asciiz "...enter a:\n" + data_23: + .asciiz "\tTo negate " + data_24: + .asciiz "...enter b:\n" + data_25: + .asciiz "\tTo find the difference between " + data_26: + .asciiz "and another number...enter c:\n" + data_27: + .asciiz "\tTo find the factorial of " + data_28: + .asciiz "...enter d:\n" + data_29: + .asciiz "\tTo square " + data_30: + .asciiz "...enter e:\n" + data_31: + .asciiz "\tTo cube " + data_32: + .asciiz "...enter f:\n" + data_33: + .asciiz "\tTo find out if " + data_34: + .asciiz "is a multiple of 3...enter g:\n" + data_35: + .asciiz "\tTo divide " + data_36: + .asciiz "by 8...enter h:\n" + data_37: + .asciiz "\tTo get a new number...enter j:\n" + data_38: + .asciiz "\tTo quit...enter q:\n\n" + data_39: + .asciiz "\n" + data_40: + .asciiz "Please enter a number... " + data_41: + .asciiz "Class type is now A\n" + data_42: + .asciiz "Class type is now B\n" + data_43: + .asciiz "Class type is now C\n" + data_44: + .asciiz "Class type is now D\n" + data_45: + .asciiz "Class type is now E\n" + data_46: + .asciiz "Object" + data_47: + .asciiz "Oooops\n" + data_48: + .asciiz " " + data_49: + .asciiz "number " + data_50: + .asciiz "is even!\n" + data_51: + .asciiz "is odd!\n" + data_52: + .asciiz "a" + data_53: + .asciiz "b" + data_54: + .asciiz "c" + data_55: + .asciiz "d" + data_56: + .asciiz "e" + data_57: + .asciiz "f" + data_58: + .asciiz "g" + data_59: + .asciiz "is divisible by 3.\n" + data_60: + .asciiz "is not divisible by 3.\n" + data_61: + .asciiz "h" + data_62: + .asciiz "is equal to " + data_63: + .asciiz "times 8 with a remainder of " + data_64: + .asciiz "j" + data_65: + .asciiz "q" + data_66: + .asciiz "Bool" + data_67: + .asciiz "Int" + data_68: .asciiz "String" data_abort: .asciiz "Abort called from class " new_line: .asciiz "\n" concat_result: - .space 0 + .space 4096 substring_result: - .space 3072 + .space 5120 read_result: - .space 1024 + .space 2048 vt_Object: - .space 152 + .space 476 vt_IO: - .space 152 + .space 476 vt_Int: - .space 152 + .space 476 vt_String: - .space 152 + .space 476 vt_Bool: - .space 152 + .space 476 + vt_A: + .space 476 + vt_B: + .space 476 + vt_C: + .space 476 + vt_D: + .space 476 + vt_E: + .space 476 + vt_A2I: + .space 476 vt_Main: - .space 152 + .space 476 abort_String: .asciiz "String" abort_Int: From 2fb23ef8ccf1ea0cd997acfd662d9dc301384c4b Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 4 Dec 2020 12:21:15 -0500 Subject: [PATCH 421/435] fixing case details --- src/code_generation/CIL/ast.py | 11 + src/code_generation/CIL/cil.py | 129 +- src/code_generation/MIPS/mips.py | 14 + src/code_generation/MIPS/test.asm | 7658 ++++--------------------- src/code_generation/MIPS/utilities.py | 2 +- src/cool_types/types.py | 31 +- 6 files changed, 1400 insertions(+), 6445 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 5d22fffc..4b455a93 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -293,6 +293,17 @@ def __init__(self, result, var): def __str__(self): return f'{self.result} = GETTYPEADDR {self.var} ;' +class GetTypeOrderNode(InstructionNode): + def __init__(self, result, var): + super().__init__() + self.result = result + self.var = var + self.check_local(result) + self.check_local(var) + + def __str__(self): + return f'{self.result} = GETTYPEORDER {self.var} ;' + class ArrayNode(InstructionNode): def __init__(self, len, result): diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 73b2d298..53ac2ccf 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -70,16 +70,20 @@ def get_typeof(obj): __CURRENT_TYPE__ = None + + def program_to_cil_visitor(program): global __CONCAT_CALLS__, __SUBST_CALLS__ types = [] code = [] built_in_code = [] + # completing .TYPE section for t in CT.TypesByName: _type = CilAST.TypeNode(t) value = CT.TypesByName[t] + __ATTR__[t] = [] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) @@ -274,6 +278,19 @@ def expression_to_cil_visitor(expression): raise Exception(f'There is no visitor for {type(expression)}') + + +def order_cases(case_list): + result=[] + while len(case_list): + m=case_list[0] + for branch in case_list[1:]: + if CT.TypesByName[branch.type].order Date: Fri, 4 Dec 2020 15:24:40 -0500 Subject: [PATCH 422/435] fixing allocate result for concat --- src/code_generation/CIL/ast.py | 9 ++-- src/code_generation/CIL/cil.py | 34 +++++---------- src/code_generation/MIPS/mips.py | 74 ++++++++++++++++++++------------ 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index 4b455a93..ca57a224 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -406,23 +406,21 @@ def __str__(self): class ConcatNode(InstructionNode): - def __init__(self, str_a, str_b, calls, result): + def __init__(self, str_a, str_b, result): self.result = result self.str_a = str_a self.str_b = str_b - self.calls=calls def __str__(self): return f'{self.result} = CONCAT {self.str_a} {self.str_b} ;' class SubStringNode(InstructionNode): - def __init__(self, str, i, len,calls, result): + def __init__(self, str, i, len, result): self.result = result self.i = i self.len = len self.str = str - self.calls=calls def __str__(self): return f'{self.result} = SUBSTRING {self.str} {self.i} {self.len};' @@ -441,9 +439,8 @@ def __str__(self): class ReadNode(InstructionNode): - def __init__(self, result, calls): + def __init__(self, result): super().__init__() - self.calls=calls self.result = result self.check_local(result) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 53ac2ccf..4790d315 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -73,7 +73,6 @@ def get_typeof(obj): def program_to_cil_visitor(program): - global __CONCAT_CALLS__, __SUBST_CALLS__ types = [] code = [] built_in_code = [] @@ -130,9 +129,6 @@ def program_to_cil_visitor(program): data.append(CilAST.DataNode('data_abort', 'Abort called from class ')) cil_program = CilAST.ProgramNode(types, data, code, built_in_code) - cil_program.concat_calls=__CONCAT_CALLS__-1 - cil_program.substr_calls=__SUBST_CALLS__-1 - cil_program.in_calls=__IN_CALLS__-1 # remove_unused_locals(cil_program) # aqui se esta perdiendo un vcall # optimization_locals(cil_program) @@ -152,7 +148,7 @@ def out_int_to_cil(): def in_string_to_cil(): _str = CilAST.LocalNode('read_result') - return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self'), CilAST.ParamNode('calls')], [_str], [CilAST.ReadNode(_str, 'calls'), CilAST.ReturnNode(_str)]) + return CilAST.FuncNode('IO_in_string', [CilAST.ParamNode('self')], [_str], [CilAST.ReadNode(_str), CilAST.ReturnNode(_str)]) def in_int_to_cil(): @@ -209,12 +205,12 @@ def length_to_cil(): def concat_to_cil(): result = CilAST.LocalNode('concat_result') - return CilAST.FuncNode('String_concat', [CilAST.ParamNode('self'), CilAST.ParamNode('x'), CilAST.ParamNode('calls')], [result], [CilAST.ConcatNode('self', 'x', 'calls', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_concat', [CilAST.ParamNode('self'), CilAST.ParamNode('x')], [result], [CilAST.ConcatNode('self', 'x', result), CilAST.ReturnNode(result)]) def substring_to_cil(): result = CilAST.LocalNode('substring_result') - return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l'), CilAST.ParamNode('calls')], [result], [CilAST.SubStringNode('self', 'i', 'l', 'calls', result), CilAST.ReturnNode(result)]) + return CilAST.FuncNode('String_substr', [CilAST.ParamNode('self'), CilAST.ParamNode('i'), CilAST.ParamNode('l')], [result], [CilAST.SubStringNode('self', 'i', 'l', result), CilAST.ReturnNode(result)]) def abort_to_cil(): @@ -582,6 +578,13 @@ def let_to_cil_visitor(let): body += attr_cil.body val = add_local(attr.id) body.append(CilAST.AssignNode(val, attr_cil.value)) + elif attr.type=='String': + str_addr = add_str_data('') + str_id, need_load = add_data_local(str_addr) + body.append(CilAST.LoadNode(str_addr, str_id)) + body.append(CilAST.AssignNode(attr.id, str_id)) + + expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body @@ -625,12 +628,8 @@ def block_to_cil_visitor(block): return CIL_block(body, value) -__SUBST_CALLS__=1 -__CONCAT_CALLS__=1 -__IN_CALLS__=1 def func_call_to_cil_visitor(call): - global __SUBST_CALLS__, __CONCAT_CALLS__, __IN_CALLS__ body = [] t = add_local() returned=None @@ -663,19 +662,6 @@ def func_call_to_cil_visitor(call): result = add_local() - if call.id =='substr': - body.append(CilAST.ArgNode((__SUBST_CALLS__-1)*1024)) - __SUBST_CALLS__+=1 - - if call.id=='in_string': - body.append(CilAST.ArgNode((__IN_CALLS__-1)*1024)) - __IN_CALLS__+=1 - - if call.id =='concat': - body.append(CilAST.ArgNode((__CONCAT_CALLS__-1)*1024)) - __CONCAT_CALLS__+=1 - - if not call.type: body.append(CilAST.VCAllNode(t, call.id, result)) else: diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 07a767ad..0963470d 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -36,9 +36,6 @@ def program_to_mips_visitor(program: cil.ProgramNode): __DATA__ = [mips.MIPSDataItem(d.id, mips.AsciizInst(f'"{d.val}"')) for d in program.data] __DATA__.append(mips.MIPSDataItem('new_line', mips.AsciizInst(f'"\\n"'))) - __DATA__.append(mips.MIPSDataItem('concat_result', mips.SpaceInst(program.concat_calls*__BUFFSIZE__*2))) - __DATA__.append(mips.MIPSDataItem('substring_result', mips.SpaceInst(program.substr_calls*__BUFFSIZE__))) - __DATA__.append(mips.MIPSDataItem('read_result', mips.SpaceInst(program.in_calls*__BUFFSIZE__))) __DATA__.extend(vt_space_code) data_section = mips.MIPSDataSection(__DATA__) @@ -180,11 +177,14 @@ def read_to_mips_visitor(read: cil.ReadNode): """ offset = CURRENT_FUNCTION.offset[str(read.result)] - calls_offset=CURRENT_FUNCTION.offset[str(read.calls)] return [ - mips.LaInstruction('$a0', str(read.result)), - mips.LwInstruction('$t0', f'{calls_offset}($fp)'), - mips.AdduInstruction('$a0', '$a0','$t0'), + + mips.LiInstruction('$a0', __BUFFSIZE__), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{offset}($fp)'), + mips.MoveInstruction('$a0', '$v0'), + mips.LiInstruction('$a1', __BUFFSIZE__), mips.LiInstruction('$v0', 8), mips.SyscallInstruction(), @@ -197,12 +197,8 @@ def read_to_mips_visitor(read: cil.ReadNode): mips.AdduInstruction('$a0', '$a0', 1), mips.BInstruction('remove_nl_loop'), mips.MIPSLabel('end_loop'), - mips.SbInstruction('$zero', '($a0)'), - mips.LaInstruction('$a0', str(read.result)), - mips.LwInstruction('$t0', f'{calls_offset}($fp)'), - mips.AdduInstruction('$a0', '$a0','$t0'), - mips.SwInstruction('$a0', f'{offset}($fp)') - ] + mips.SbInstruction('$zero', '($a0)') + ] def substring_to_mips_visitor(ss: cil.SubStringNode): @@ -210,13 +206,18 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): str_offset = CURRENT_FUNCTION.offset[str(ss.str)] i_offset = CURRENT_FUNCTION.offset[str(ss.i)] len_offset = CURRENT_FUNCTION.offset[str(ss.len)] - calls_offset= CURRENT_FUNCTION.offset[str(ss.calls)] return [ mips.Comment(str(ss)), mips.LwInstruction('$t0', f'{str_offset}($fp)'), - mips.LaInstruction('$t5', str(ss.result)), - mips.LwInstruction('$t1', f'{calls_offset}($fp)'), - mips.AdduInstruction('$t1', '$t1', '$t5'), + + + mips.LiInstruction('$a0', __BUFFSIZE__), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{result_offset}($fp)'), + mips.MoveInstruction('$t1', '$v0'), + + mips.LwInstruction('$t4', f'{i_offset}($fp)'), mips.LwInstruction('$t2', f'{len_offset}($fp)'), mips.AdduInstruction('$t0', '$t0', '$t4'), @@ -229,11 +230,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('substring_loop'), mips.MIPSLabel('end_substring_loop'), - mips.SbInstruction('$zero', '($t1)'), - mips.LaInstruction('$t5', str(ss.result)), - mips.LwInstruction('$t1', f'{calls_offset}($fp)'), - mips.AdduInstruction('$t1', '$t1', '$t5'), - mips.SwInstruction('$t1', f'{result_offset}($fp)') + mips.SbInstruction('$zero', '($t1)') ] @@ -248,7 +245,6 @@ def read_int_to_mips_visitor(read: cil.ReadIntNode): return code -# TODO: Check def length_to_mips_visitor(length: cil.LengthNode): val = CURRENT_FUNCTION.offset[str(length.str)] result_val = CURRENT_FUNCTION.offset[str(length.result)] @@ -269,6 +265,25 @@ def length_to_mips_visitor(length: cil.LengthNode): return code +def copy_string(string_var): + __DATA__.append(mips.MIPSDataItem(f'temporal_string_{string_var}', mips.SpaceInst(__BUFFSIZE__))) + offset=CURRENT_FUNCTION.offset[str(string_var)] + return [ + mips.LwInstruction('$t0',f'{offset}($fp)'), + mips.LaInstruction('$t1', f'temporal_string_{string_var}'), + mips.MIPSLabel(f'loop_{string_var}'), + mips.LbInstruction('$t2', '($t0)'), + mips.SbInstruction('$t2', '($t1)'), + mips.BeqzInstruction('$t2', f'end_loop_{string_var}'), + mips.AdduInstruction('$t0', '$t0', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction(f'loop_{string_var}'), + mips.MIPSLabel(f'end_loop_{string_var}'), + mips.LaInstruction('$t0', f'temporal_string_{string_var}'), + mips.SwInstruction('$t0', f'{offset}($fp)') + ] + + def concat_to_mips_visitor(concat: cil.ConcatNode): result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] @@ -276,7 +291,12 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): return [ mips.Comment(str(concat)), - mips.LaInstruction('$t0', str(concat.result)), + mips.LiInstruction('$a0', 2*__BUFFSIZE__), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{result_offset}($fp)'), + mips.MoveInstruction('$t0', '$v0'), + mips.LwInstruction('$t1', f'{a_offset}($fp)'), mips.LwInstruction('$t2', f'{b_offset}($fp)'), mips.MIPSLabel('concat_loop_a'), @@ -294,10 +314,8 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t2', '$t2', 1), mips.BInstruction('concat_loop_b'), mips.MIPSLabel('end_concat'), - mips.SbInstruction('$zero', '($t0)'), - mips.LaInstruction('$t0', str(concat.result)), - mips.SwInstruction('$t0', f'{result_offset}($fp)') - ] + mips.SbInstruction('$zero', '($t0)') + ] def load_to_mips_visitor(load: cil.LoadNode): From 21ea671682777e5e4ef80659c7a045dc7fc78a86 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 4 Dec 2020 15:35:15 -0500 Subject: [PATCH 423/435] fixing substring bug --- src/code_generation/MIPS/mips.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 0963470d..0adb38ac 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -264,26 +264,6 @@ def length_to_mips_visitor(length: cil.LengthNode): ] return code - -def copy_string(string_var): - __DATA__.append(mips.MIPSDataItem(f'temporal_string_{string_var}', mips.SpaceInst(__BUFFSIZE__))) - offset=CURRENT_FUNCTION.offset[str(string_var)] - return [ - mips.LwInstruction('$t0',f'{offset}($fp)'), - mips.LaInstruction('$t1', f'temporal_string_{string_var}'), - mips.MIPSLabel(f'loop_{string_var}'), - mips.LbInstruction('$t2', '($t0)'), - mips.SbInstruction('$t2', '($t1)'), - mips.BeqzInstruction('$t2', f'end_loop_{string_var}'), - mips.AdduInstruction('$t0', '$t0', 1), - mips.AdduInstruction('$t1', '$t1', 1), - mips.BInstruction(f'loop_{string_var}'), - mips.MIPSLabel(f'end_loop_{string_var}'), - mips.LaInstruction('$t0', f'temporal_string_{string_var}'), - mips.SwInstruction('$t0', f'{offset}($fp)') - ] - - def concat_to_mips_visitor(concat: cil.ConcatNode): result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] From 1bd46515bd9eddf75062c790f81afbf17bec1138 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Fri, 4 Dec 2020 16:19:13 -0500 Subject: [PATCH 424/435] fixing bugs --- src/code_generation/CIL/cil.py | 2 +- src/code_generation/MIPS/mips.py | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 4790d315..25c2d762 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -578,7 +578,7 @@ def let_to_cil_visitor(let): body += attr_cil.body val = add_local(attr.id) body.append(CilAST.AssignNode(val, attr_cil.value)) - elif attr.type=='String': + elif attr.type=='String': str_addr = add_str_data('') str_id, need_load = add_data_local(str_addr) body.append(CilAST.LoadNode(str_addr, str_id)) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 0adb38ac..31d451ad 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -182,8 +182,8 @@ def read_to_mips_visitor(read: cil.ReadNode): mips.LiInstruction('$a0', __BUFFSIZE__), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{offset}($fp)'), mips.MoveInstruction('$a0', '$v0'), + mips.MoveInstruction('$t3', '$v0'), mips.LiInstruction('$a1', __BUFFSIZE__), mips.LiInstruction('$v0', 8), @@ -197,7 +197,8 @@ def read_to_mips_visitor(read: cil.ReadNode): mips.AdduInstruction('$a0', '$a0', 1), mips.BInstruction('remove_nl_loop'), mips.MIPSLabel('end_loop'), - mips.SbInstruction('$zero', '($a0)') + mips.SbInstruction('$zero', '($a0)'), + mips.SwInstruction('$t3', f'{offset}($fp)') ] @@ -214,7 +215,6 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.LiInstruction('$a0', __BUFFSIZE__), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{result_offset}($fp)'), mips.MoveInstruction('$t1', '$v0'), @@ -230,7 +230,8 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.AdduInstruction('$t1', '$t1', 1), mips.BInstruction('substring_loop'), mips.MIPSLabel('end_substring_loop'), - mips.SbInstruction('$zero', '($t1)') + mips.SbInstruction('$zero', '($t1)'), + mips.SwInstruction('$v0', f'{result_offset}($fp)') ] @@ -274,7 +275,6 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.LiInstruction('$a0', 2*__BUFFSIZE__), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{result_offset}($fp)'), mips.MoveInstruction('$t0', '$v0'), mips.LwInstruction('$t1', f'{a_offset}($fp)'), @@ -294,7 +294,8 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): mips.AdduInstruction('$t2', '$t2', 1), mips.BInstruction('concat_loop_b'), mips.MIPSLabel('end_concat'), - mips.SbInstruction('$zero', '($t0)') + mips.SbInstruction('$zero', '($t0)'), + mips.SwInstruction('$v0', f'{result_offset}($fp)') ] From ee233bf8f1306409ff388a6d3e9ceb5962ea0f66 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 5 Dec 2020 16:32:08 +0100 Subject: [PATCH 425/435] Add type childs --- src/cool_types/types.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 4c867700..9555fd1b 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -14,8 +14,8 @@ def __init__(self, name, parent_type, inherit=True): self.attributes = {} self.methods = {} self.inherit = inherit - self.childs = [] - + self.childs = set() + # if parent_type: # self.order=self.parent.order-1 # else: @@ -162,7 +162,6 @@ def type_by_name(type_name): except KeyError: return None - def check_inherits(type_a: CoolType, type_b: CoolType): """ @@ -196,6 +195,7 @@ def check_type_hierarchy(node): parentType = TypesByName[c.parent_type] if parentType.inherit: cType.parent = parentType + parentType.childs.add(cType) type_x = parentType while type_x: if type_x: @@ -214,24 +214,24 @@ def check_type_hierarchy(node): return False else: cType.parent = ObjectType + ObjectType.childs.add(cType) set_types_order([TypesByName[c.type] for c in node.classes]) return True + def set_types_order(classes): - q=[c for c in classes] + q = [c for c in classes] while len(q): - c=q[0] - q=q[1:] + c = q[0] + q = q[1:] if c.parent: try: - c.order=c.parent.order-1 + c.order = c.parent.order-1 except: q.append(c) - else: - c.order=-1 - - - + else: + c.order = -1 + def __type_hierarchy__(type_x): h = [] @@ -240,6 +240,7 @@ def __type_hierarchy__(type_x): type_x = type_x.parent return h + def pronounced_join(type_a, type_b): h = __type_hierarchy__(type_b) while type_a is not None: @@ -251,15 +252,15 @@ def pronounced_join(type_a, type_b): SelfType = CoolType('SELF_TYPE', None, False) ObjectType = CoolType('Object', None) -ObjectType.order=0 +ObjectType.order = 0 IOType = CoolType('IO', ObjectType) -IOType.order=-1 +IOType.order = -1 IntType = CoolType('Int', ObjectType, False) -IntType.order=-2 +IntType.order = -2 StringType = CoolType('String', ObjectType, False) -StringType.order=-2 +StringType.order = -2 BoolType = CoolType('Bool', ObjectType, False) -BoolType.order=-2 +BoolType.order = -2 TypesByName = { 'SELF_TYPE': SelfType, @@ -270,7 +271,7 @@ def pronounced_join(type_a, type_b): 'Bool': BoolType } -ObjectType.childs = [IOType, IntType, StringType, BoolType] +ObjectType.childs = set([IOType, IntType, StringType, BoolType]) ObjectType.add_method('abort', [], 'Object') ObjectType.add_method('type_name', [], 'String') ObjectType.add_method('copy', [], 'SELF_TYPE') @@ -288,4 +289,4 @@ def pronounced_join(type_a, type_b): StringType.add_method('type_name', [], 'String') IntType.add_method('type_name', [], 'String') -BoolType.add_method('type_name', [], 'String') \ No newline at end of file +BoolType.add_method('type_name', [], 'String') From 3e514fa68c69483192676684b9e2feae1f59f9fd Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sat, 5 Dec 2020 10:44:30 +0100 Subject: [PATCH 426/435] Set order and min_order properties to CoolType --- src/cool_types/types.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/cool_types/types.py b/src/cool_types/types.py index 9555fd1b..3021e7aa 100644 --- a/src/cool_types/types.py +++ b/src/cool_types/types.py @@ -15,6 +15,8 @@ def __init__(self, name, parent_type, inherit=True): self.methods = {} self.inherit = inherit self.childs = set() + self.order = 0 + self.min_order = 0 # if parent_type: # self.order=self.parent.order-1 @@ -215,22 +217,16 @@ def check_type_hierarchy(node): else: cType.parent = ObjectType ObjectType.childs.add(cType) - set_types_order([TypesByName[c.type] for c in node.classes]) + set_types_order(ObjectType, 1) return True -def set_types_order(classes): - q = [c for c in classes] - while len(q): - c = q[0] - q = q[1:] - if c.parent: - try: - c.order = c.parent.order-1 - except: - q.append(c) - else: - c.order = -1 +def set_types_order(currnet_type: CoolType, current_order: int) -> int: + currnet_type.min_order = current_order + for t in currnet_type.childs: + current_order = set_types_order(t, current_order) + currnet_type.order = current_order + return current_order + 1 def __type_hierarchy__(type_x): From d3937e6e948e59de7f46a14ffd899385f35420ea Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 5 Dec 2020 10:44:29 -0500 Subject: [PATCH 427/435] fixing space allocation for concat and substring --- src/code_generation/CIL/cil.py | 33 +++++++++++++----- src/code_generation/MIPS/mips.py | 60 ++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 25c2d762..63f54447 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -502,6 +502,16 @@ def init_instance(t, parent=None): body += attr_cil.body body.append(CilAST.SetAttrNode( 'self', attr.id, attr_cil.value, index)) + elif attr.attrType.name =='String': + val=add_local() + body.append(CilAST.AllocateNode('String',val)) + body.append(CilAST.SetAttrNode('self', attr.id, val, index)) + elif attr.attrType.name not in ('Bool', 'Int'): + init=new_to_cil_visitor(None, default_type=attr.attrType.name) + body.extend(init.body) + body.append(CilAST.SetAttrNode('self', attr.id, init.value, index)) + else: + body.append(CilAST.SetAttrNode('self', attr.id, 0, index)) body.append(CilAST.ReturnNode('self')) @@ -510,12 +520,15 @@ def init_instance(t, parent=None): -def new_to_cil_visitor(new_node, val_id=None): +def new_to_cil_visitor(new_node, val_id=None, default_type=None): if val_id: value=add_local(val_id) else: value=add_local() - t = new_node.type + if default_type: + t=default_type + else: + t = new_node.type body = [] if t == 'SELF_TYPE': @@ -573,19 +586,21 @@ def string_to_cil_visitor(str): def let_to_cil_visitor(let): body = [] for attr in let.let_attrs: + val = add_local(attr.id) if attr.expr: attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body - val = add_local(attr.id) body.append(CilAST.AssignNode(val, attr_cil.value)) - elif attr.type=='String': - str_addr = add_str_data('') - str_id, need_load = add_data_local(str_addr) - body.append(CilAST.LoadNode(str_addr, str_id)) - body.append(CilAST.AssignNode(attr.id, str_id)) + elif attr.type=='String': + body.append(CilAST.AllocateNode('String', val)) + elif attr.type not in ('Bool', 'Int'): + init=new_to_cil_visitor(None, default_type=attr.type) + body.extend(init.body) + body.append(CilAST.AssignNode(val, init.value)) + else: + body.append(CilAST.AssignNode(val, 0)) - expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 31d451ad..97e6838a 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -212,7 +212,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.LwInstruction('$t0', f'{str_offset}($fp)'), - mips.LiInstruction('$a0', __BUFFSIZE__), + mips.LwInstruction('$a0', f'{len_offset}($fp)'), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t1', '$v0'), @@ -269,10 +269,33 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] b_offset = CURRENT_FUNCTION.offset[str(concat.str_b)] + + + return [ mips.Comment(str(concat)), - mips.LiInstruction('$a0', 2*__BUFFSIZE__), + + mips.LwInstruction('$t2', f'{a_offset}($fp)'), + mips.LiInstruction('$t1', 0), + mips.MIPSLabel('concat_a_length_loop'), + mips.LbInstruction('$t0', '($t2)'), + mips.BeqzInstruction('$t0', 'concat_a_end_length_loop'), + mips.AdduInstruction('$t2', '$t2', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('concat_a_length_loop'), + mips.MIPSLabel('concat_a_end_length_loop'), + + mips.LwInstruction('$t2', f'{b_offset}($fp)'), + mips.MIPSLabel('concat_b_length_loop'), + mips.LbInstruction('$t0', '($t2)'), + mips.BeqzInstruction('$t0', 'concat_b_end_length_loop'), + mips.AdduInstruction('$t2', '$t2', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('concat_b_length_loop'), + mips.MIPSLabel('concat_b_end_length_loop'), + + mips.AdduInstruction('$a0', '$t1', 1), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t0', '$v0'), @@ -336,19 +359,28 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): syscall sw $v0, [addr(x)] """ - size = get_type(allocate.type).size_mips address = CURRENT_FUNCTION.offset[str(allocate.result)] - - - code = [ - mips.Comment(str(allocate)), - mips.LiInstruction('$a0', size + 4), - mips.LiInstruction('$v0', 9), - mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{address}($fp)'), - mips.LaInstruction('$t0', f'vt_{allocate.type}'), - mips.SwInstruction('$t0', f'8($v0)') - ] + if allocate.type=='String': + size= __BUFFSIZE__ + code=[ + mips.Comment(str(allocate)), + mips.LiInstruction('$a0', size), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{address}($fp)') + ] + + else: + size = get_type(allocate.type).size_mips + 16 + code = [ + mips.Comment(str(allocate)), + mips.LiInstruction('$a0', size), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{address}($fp)'), + mips.LaInstruction('$t0', f'vt_{allocate.type}'), + mips.SwInstruction('$t0', f'8($v0)') + ] return code From 1e3621933b59dc00505fc38d8e2255bc1e2250b6 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 5 Dec 2020 10:56:15 -0500 Subject: [PATCH 428/435] adding one more byte to null termination --- src/code_generation/MIPS/mips.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 97e6838a..9a480eb7 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -213,6 +213,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.LwInstruction('$a0', f'{len_offset}($fp)'), + mips.AdduInstruction('$a0', '$a0', 1), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t1', '$v0'), From 84bbdabdfdd20dd880b26acdaa3a1343ea93edeb Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 5 Dec 2020 10:44:29 -0500 Subject: [PATCH 429/435] fixing space allocation for concat and substring --- src/code_generation/CIL/cil.py | 33 +++++++++++++----- src/code_generation/MIPS/mips.py | 60 ++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 25c2d762..63f54447 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -502,6 +502,16 @@ def init_instance(t, parent=None): body += attr_cil.body body.append(CilAST.SetAttrNode( 'self', attr.id, attr_cil.value, index)) + elif attr.attrType.name =='String': + val=add_local() + body.append(CilAST.AllocateNode('String',val)) + body.append(CilAST.SetAttrNode('self', attr.id, val, index)) + elif attr.attrType.name not in ('Bool', 'Int'): + init=new_to_cil_visitor(None, default_type=attr.attrType.name) + body.extend(init.body) + body.append(CilAST.SetAttrNode('self', attr.id, init.value, index)) + else: + body.append(CilAST.SetAttrNode('self', attr.id, 0, index)) body.append(CilAST.ReturnNode('self')) @@ -510,12 +520,15 @@ def init_instance(t, parent=None): -def new_to_cil_visitor(new_node, val_id=None): +def new_to_cil_visitor(new_node, val_id=None, default_type=None): if val_id: value=add_local(val_id) else: value=add_local() - t = new_node.type + if default_type: + t=default_type + else: + t = new_node.type body = [] if t == 'SELF_TYPE': @@ -573,19 +586,21 @@ def string_to_cil_visitor(str): def let_to_cil_visitor(let): body = [] for attr in let.let_attrs: + val = add_local(attr.id) if attr.expr: attr_cil = expression_to_cil_visitor(attr.expr) body += attr_cil.body - val = add_local(attr.id) body.append(CilAST.AssignNode(val, attr_cil.value)) - elif attr.type=='String': - str_addr = add_str_data('') - str_id, need_load = add_data_local(str_addr) - body.append(CilAST.LoadNode(str_addr, str_id)) - body.append(CilAST.AssignNode(attr.id, str_id)) + elif attr.type=='String': + body.append(CilAST.AllocateNode('String', val)) + elif attr.type not in ('Bool', 'Int'): + init=new_to_cil_visitor(None, default_type=attr.type) + body.extend(init.body) + body.append(CilAST.AssignNode(val, init.value)) + else: + body.append(CilAST.AssignNode(val, 0)) - expr_cil = expression_to_cil_visitor(let.expr) body += expr_cil.body diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 29437e98..833fdede 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -211,7 +211,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.LwInstruction('$t0', f'{str_offset}($fp)'), - mips.LiInstruction('$a0', __BUFFSIZE__), + mips.LwInstruction('$a0', f'{len_offset}($fp)'), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t1', '$v0'), @@ -268,10 +268,33 @@ def concat_to_mips_visitor(concat: cil.ConcatNode): result_offset = CURRENT_FUNCTION.offset[str(concat.result)] a_offset = CURRENT_FUNCTION.offset[str(concat.str_a)] b_offset = CURRENT_FUNCTION.offset[str(concat.str_b)] + + + return [ mips.Comment(str(concat)), - mips.LiInstruction('$a0', 2*__BUFFSIZE__), + + mips.LwInstruction('$t2', f'{a_offset}($fp)'), + mips.LiInstruction('$t1', 0), + mips.MIPSLabel('concat_a_length_loop'), + mips.LbInstruction('$t0', '($t2)'), + mips.BeqzInstruction('$t0', 'concat_a_end_length_loop'), + mips.AdduInstruction('$t2', '$t2', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('concat_a_length_loop'), + mips.MIPSLabel('concat_a_end_length_loop'), + + mips.LwInstruction('$t2', f'{b_offset}($fp)'), + mips.MIPSLabel('concat_b_length_loop'), + mips.LbInstruction('$t0', '($t2)'), + mips.BeqzInstruction('$t0', 'concat_b_end_length_loop'), + mips.AdduInstruction('$t2', '$t2', 1), + mips.AdduInstruction('$t1', '$t1', 1), + mips.BInstruction('concat_b_length_loop'), + mips.MIPSLabel('concat_b_end_length_loop'), + + mips.AdduInstruction('$a0', '$t1', 1), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t0', '$v0'), @@ -335,19 +358,28 @@ def allocate_to_mips_visitor(allocate: cil.AllocateNode): syscall sw $v0, [addr(x)] """ - size = get_type(allocate.type).size_mips address = CURRENT_FUNCTION.offset[str(allocate.result)] - - - code = [ - mips.Comment(str(allocate)), - mips.LiInstruction('$a0', size + 4), - mips.LiInstruction('$v0', 9), - mips.SyscallInstruction(), - mips.SwInstruction('$v0', f'{address}($fp)'), - mips.LaInstruction('$t0', f'vt_{allocate.type}'), - mips.SwInstruction('$t0', f'8($v0)') - ] + if allocate.type=='String': + size= __BUFFSIZE__ + code=[ + mips.Comment(str(allocate)), + mips.LiInstruction('$a0', size), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{address}($fp)') + ] + + else: + size = get_type(allocate.type).size_mips + 16 + code = [ + mips.Comment(str(allocate)), + mips.LiInstruction('$a0', size), + mips.LiInstruction('$v0', 9), + mips.SyscallInstruction(), + mips.SwInstruction('$v0', f'{address}($fp)'), + mips.LaInstruction('$t0', f'vt_{allocate.type}'), + mips.SwInstruction('$t0', f'8($v0)') + ] return code From 3efc9cbf2adddc83884fcc94dd4e5d9dda9e9d18 Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 5 Dec 2020 10:56:15 -0500 Subject: [PATCH 430/435] adding one more byte to null termination --- src/code_generation/MIPS/mips.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 833fdede..4f541359 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -212,6 +212,7 @@ def substring_to_mips_visitor(ss: cil.SubStringNode): mips.LwInstruction('$a0', f'{len_offset}($fp)'), + mips.AdduInstruction('$a0', '$a0', 1), mips.LiInstruction('$v0', 9), mips.SyscallInstruction(), mips.MoveInstruction('$t1', '$v0'), From 5afac0b2491ce28612b52fed39cfc27ffad0a56d Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 5 Dec 2020 11:15:10 -0500 Subject: [PATCH 431/435] fixing order in types --- src/code_generation/CIL/ast.py | 13 ++++++++++ src/code_generation/CIL/cil.py | 35 +++++++++++++++------------ src/code_generation/MIPS/mips.py | 12 +++++++++ src/code_generation/MIPS/utilities.py | 2 +- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/code_generation/CIL/ast.py b/src/code_generation/CIL/ast.py index ca57a224..e5f547a8 100644 --- a/src/code_generation/CIL/ast.py +++ b/src/code_generation/CIL/ast.py @@ -304,6 +304,19 @@ def __init__(self, result, var): def __str__(self): return f'{self.result} = GETTYPEORDER {self.var} ;' +class GetTypeMinOrderNode(InstructionNode): + def __init__(self, result, var): + super().__init__() + self.result = result + self.var = var + self.check_local(result) + self.check_local(var) + + def __str__(self): + return f'{self.result} = GETTYPEMINORDER {self.var} ;' + + + class ArrayNode(InstructionNode): def __init__(self, len, result): diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 63f54447..1e19cab0 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -301,6 +301,10 @@ def case_to_cil_visitor(case): body += expr_cil.body t = add_local() body.append(CilAST.GetTypeOrderNode(t, expr_cil.value)) + t_min=add_local() + + body.append(CilAST.GetTypeMinOrderNode(t_min, expr_cil.value)) + types = [] labels = [] for c in case.case_list: @@ -318,20 +322,15 @@ def case_to_cil_visitor(case): aux_predicate=add_local() order=CT.TypesByName[branch.type].order - comp_result=add_local() - body.append(CilAST.LessNode(order, t, comp_result)) - body.append(CilAST.ConditionalGotoNode(comp_result, labels[i])) - + min_order=CT.TypesByName[branch.type].min_order + first_comp_result=add_local() + body.append(CilAST.LessNode(order, t, first_comp_result)) + body.append(CilAST.ConditionalGotoNode(first_comp_result, labels[i])) - # str_addr = add_str_data(branch.type) - # str_id, need_load = add_data_local(str_addr) - # if need_load: - # body.append(CilAST.LoadNode(str_addr, str_id)) - # body.append(CilAST.EqStringNode(t, str_id, aux_predicate)), - # body.append(CilAST.EqNode(aux_predicate, 0, predicate)), - # body.append(CilAST.ConditionalGotoNode(predicate, labels[i])) - + second_comp_result=add_local() + body.append(CilAST.LessNode(t_min, min_order, second_comp_result)) + body.append(CilAST.ConditionalGotoNode(second_comp_result, labels[i])) val = add_local(branch.id) body.append(CilAST.AssignNode(val, expr_cil.value)) @@ -353,7 +352,7 @@ def assign_to_cil_visitor(assign): expr = expression_to_cil_visitor(assign.expr) if assign.id in __ATTR__[__CURRENT_TYPE__]: index = __ATTR__[__CURRENT_TYPE__].index(assign.id) - body = expr.body + [CilAST.SetAttrNode('self', assign.id, expr.value, index + 4)] + body = expr.body + [CilAST.SetAttrNode('self', assign.id, expr.value, index + 5)] return CIL_block(body, expr.value) else: val = add_local(assign.id) @@ -474,7 +473,7 @@ def id_to_cil_visitor(id): if id.id in __ATTR__[__CURRENT_TYPE__]: result = add_local() index = __ATTR__[__CURRENT_TYPE__].index(id.id) - return CIL_block([CilAST.GetAttrNode('self', id.id, result, index + 4)], result) + return CIL_block([CilAST.GetAttrNode('self', id.id, result, index + 5)], result) return CIL_block([], id.id) def init_instance(t, parent=None): @@ -495,7 +494,7 @@ def init_instance(t, parent=None): all_attr= CT.TypesByName[t].get_all_attributes() init_attr = CT.TypesByName[t].get_self_attributes() - for index, attr in enumerate(init_attr, len(all_attr)-len(init_attr)+4): + for index, attr in enumerate(init_attr, len(all_attr)-len(init_attr)+5): if attr.expression: attr_cil = expression_to_cil_visitor( attr.expression) @@ -541,17 +540,21 @@ def new_to_cil_visitor(new_node, val_id=None, default_type=None): t_local = add_local() size_local = add_local() order_local=add_local() + min_order_local=add_local() # init_attr = CT.TypesByName[t].get_all_attributes() body.append(CilAST.LoadNode(t_data, t_local)) body.append(CilAST.SetAttrNode(value, '@type', t_local)) - body.append(CilAST.AssignNode(size_local, (len(init_attr)+4)*4)) + body.append(CilAST.AssignNode(size_local, (len(init_attr)+5)*4)) body.append(CilAST.SetAttrNode(value, '@size', size_local, 1)) body.append(CilAST.AssignNode(order_local, CT.TypesByName[t].order)) body.append(CilAST.SetAttrNode(value, '@order', order_local, 3)) + body.append(CilAST.AssignNode(min_order_local, CT.TypesByName[t].min_order)) + body.append(CilAST.SetAttrNode(value, '@min_order', min_order_local, 4)) + if t not in ('IO', 'Object', 'Int', 'String', 'Bool'): body.append(CilAST.ArgNode(value)) allocate_res=add_local() diff --git a/src/code_generation/MIPS/mips.py b/src/code_generation/MIPS/mips.py index 4f541359..dd69cedf 100644 --- a/src/code_generation/MIPS/mips.py +++ b/src/code_generation/MIPS/mips.py @@ -805,6 +805,16 @@ def get_type_order_to_mips_visitor(get_order:cil.GetTypeOrderNode): mips.LwInstruction('$t0', f'12($t1)'), mips.SwInstruction('$t0', f'{t_addr}($fp)') ] + +def get_type_order_min_to_mips_visitor(get_order:cil.GetTypeMinOrderNode): + x_addr = CURRENT_FUNCTION.offset[str(get_order.var)] + t_addr = CURRENT_FUNCTION.offset[str(get_order.result)] + return [ + mips.Comment(str(get_order)), + mips.LwInstruction('$t1', f'{x_addr}($fp)'), + mips.LwInstruction('$t0', f'16($t1)'), + mips.SwInstruction('$t0', f'{t_addr}($fp)') + ] def assign_to_mips_visitor(assign: cil.AssignNode): """ @@ -933,6 +943,8 @@ def abort_to_mips_visitor(abort: cil.AbortNode): cil.AbortNode: abort_to_mips_visitor, cil.GetTypeAddrNode: get_type_addr_to_mips_visitor, cil.GetTypeOrderNode:get_type_order_to_mips_visitor, + + cil.GetTypeMinOrderNode:get_type_order_min_to_mips_visitor, cil.EqNode: eq_to_mips_visitor, cil.NotEqNode:not_eq_to_mips_visitor, cil.NotEqInstanceNode:not_eq_instance_to_mips_visitor, diff --git a/src/code_generation/MIPS/utilities.py b/src/code_generation/MIPS/utilities.py index 483e1a60..2e724c9f 100644 --- a/src/code_generation/MIPS/utilities.py +++ b/src/code_generation/MIPS/utilities.py @@ -15,7 +15,7 @@ def init_types(types): size_vt=0 for i, t in enumerate(types): t.code_mips = i - t.size_mips = (len(t.attributes) + 4) * 4 + t.size_mips = (len(t.attributes) + 5) * 4 size_vt +=(len(t.methods) + 1) * 4 t.attr_index_mips = {} for i, a in enumerate(t.attributes): From 087c0c51e2b0b40c85597ddebd68a1e5a8e687b3 Mon Sep 17 00:00:00 2001 From: stdevAdrianPaez Date: Sun, 6 Dec 2020 12:15:56 +0100 Subject: [PATCH 432/435] Final fix ;) --- src/code_generation/CIL/cil.py | 184 ++++++++++++++++----------------- 1 file changed, 87 insertions(+), 97 deletions(-) diff --git a/src/code_generation/CIL/cil.py b/src/code_generation/CIL/cil.py index 1e19cab0..d316b5f8 100644 --- a/src/code_generation/CIL/cil.py +++ b/src/code_generation/CIL/cil.py @@ -70,19 +70,16 @@ def get_typeof(obj): __CURRENT_TYPE__ = None - - def program_to_cil_visitor(program): types = [] code = [] built_in_code = [] - # completing .TYPE section for t in CT.TypesByName: _type = CilAST.TypeNode(t) value = CT.TypesByName[t] - + __ATTR__[t] = [] for attr in value.get_all_attributes(): _type.attributes.append(attr.id) @@ -93,9 +90,9 @@ def program_to_cil_visitor(program): for met in value.get_all_self_methods(): _type.methods[met] = t - + if t not in ('SELF_TYPE', 'Object', 'IO', 'String', 'Bool', 'Int'): - _type.methods['__init__']=t + _type.methods['__init__'] = t types.append(_type) @@ -122,7 +119,6 @@ def program_to_cil_visitor(program): fun = func_to_cil_visitor(c.type, f) code.append(fun) - built_in_code += built_in_to_cil() data = [CilAST.DataNode(__DATA__[data_value], data_value) for data_value in __DATA__.keys()] @@ -138,6 +134,7 @@ def program_to_cil_visitor(program): def built_in_to_cil(): return [out_int_to_cil(), out_string_to_cil(), in_string_to_cil(), in_int_to_cil(), type_name_to_cil(), copy_to_cil(), length_to_cil(), concat_to_cil(), substring_to_cil(), abort_to_cil(), abort_string_to_cil(), abort_int_to_cil(), abort_bool_to_cil(), type_name_bool_to_cil(), type_name_int_to_cil(), type_name_string_to_cil()] + def out_string_to_cil(): return CilAST.FuncNode('IO_out_string', [CilAST.ParamNode('self'), CilAST.ParamNode('str')], [], [CilAST.PrintNode('str'), CilAST.ReturnNode('self')]) @@ -157,18 +154,19 @@ def in_int_to_cil(): def type_name_string_to_cil(): - str_addr=add_str_data('String') + str_addr = add_str_data('String') t, need_load = add_data_local(str_addr) if need_load: body = [CilAST.LoadNode(str_addr, t)] else: body = [] - + return CilAST.FuncNode('String_type_name', [CilAST.ParamNode('self')], [t], body+[CilAST.ReturnNode(t)]) + def type_name_int_to_cil(): - str_addr=add_str_data('Int') + str_addr = add_str_data('Int') t, need_load = add_data_local(str_addr) if need_load: @@ -177,22 +175,23 @@ def type_name_int_to_cil(): body = [] return CilAST.FuncNode('Int_type_name', [CilAST.ParamNode('self')], [t], body+[CilAST.ReturnNode(t)]) + def type_name_bool_to_cil(): - str_addr=add_str_data('Bool') + str_addr = add_str_data('Bool') t, need_load = add_data_local(str_addr) if need_load: body = [CilAST.LoadNode(str_addr, t)] else: body = [] - return CilAST.FuncNode('Bool_type_name', [CilAST.ParamNode('self')], [t], body+[ CilAST.ReturnNode(t)]) + return CilAST.FuncNode('Bool_type_name', [CilAST.ParamNode('self')], [t], body+[CilAST.ReturnNode(t)]) + def type_name_to_cil(): t = CilAST.LocalNode('type') return CilAST.FuncNode('Object_type_name', [CilAST.ParamNode('self')], [t], [CilAST.TypeOfNode(t, 'self'), CilAST.ReturnNode(t)]) - def copy_to_cil(): copy = CilAST.LocalNode('copy') return CilAST.FuncNode('Object_copy', [CilAST.ParamNode('self')], [copy], [CilAST.CopyNode('self', copy), CilAST.ReturnNode(copy)]) @@ -220,15 +219,15 @@ def abort_to_cil(): def abort_string_to_cil(): return CilAST.FuncNode('String_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('String')]) + def abort_bool_to_cil(): return CilAST.FuncNode('Bool_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('Bool')]) + def abort_int_to_cil(): return CilAST.FuncNode('Int_abort', [CilAST.ParamNode('self')], [], [CilAST.AbortNode('Int')]) - - def func_to_cil_visitor(type_name, func): ''' Converts from FunctionNode in COOL AST to FuncionNode in CIL AST. \n @@ -274,19 +273,18 @@ def expression_to_cil_visitor(expression): raise Exception(f'There is no visitor for {type(expression)}') - - def order_cases(case_list): - result=[] + result = [] while len(case_list): - m=case_list[0] + m = case_list[0] for branch in case_list[1:]: - if CT.TypesByName[branch.type].order Date: Sun, 6 Dec 2020 16:27:48 -0500 Subject: [PATCH 433/435] Adding report --- Informe Compilador.pdf | Bin 0 -> 221799 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Informe Compilador.pdf diff --git a/Informe Compilador.pdf b/Informe Compilador.pdf new file mode 100644 index 0000000000000000000000000000000000000000..27cdc20d5c853d8a825e212daf0875c45ab87eae GIT binary patch literal 221799 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

    us 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%0DT#Me%}Z$?kwQX6k9L^BTQ4f+c@kh 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

    N`%QY1RPuOp-P5r6 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 CTs6}G literal 0 HcmV?d00001 From 5336367b667708338fbeacd56fb7689fd0eb1e9f Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 12 Dec 2020 12:00:26 -0500 Subject: [PATCH 434/435] Updating report --- Informe Compilador.pdf | Bin 221799 -> 336265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Informe Compilador.pdf b/Informe Compilador.pdf index 27cdc20d5c853d8a825e212daf0875c45ab87eae..b38e401879d92a96a6c5c48f7e6c8ade7d7d1a86 100644 GIT binary patch delta 284031 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:=<^4p}7q9RDJ7E+F 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 b#{+xDf6Lv<8aM(*0-I1$9v%fPMbiHPN986a From 46be8b77cd6615f0fa1afad783ca450a804fa51a Mon Sep 17 00:00:00 2001 From: Isabella Sierra Date: Sat, 12 Dec 2020 21:41:28 -0500 Subject: [PATCH 435/435] Fixing typos --- Informe Compilador.pdf | Bin 336265 -> 336992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Informe Compilador.pdf b/Informe Compilador.pdf index b38e401879d92a96a6c5c48f7e6c8ade7d7d1a86..43ca8431e971d6bb19927751a29aee4688b85e47 100644 GIT binary patch delta 45906 zcmaI71yq~ewk}L?clQ=|_u}rw-QC?KSaC{efIx98Qrz9$o#O6p#o^L#@BhE&?sL!0 z7|DF5tU1?u=1lUA@g`9{*c*e`mH6xc4v?W4Jy2jdd0EQ!{1H*e6cbBoJt*9jdtauS zXOY;cwna5_-p`%Y+zu8IeiGtf?*3Q}?6?9y?%eNb2!HcMV|C8sT&%ijnKJFo`}WWF zFQ+$JP+Z(K=UiHR7LV$VOKxv}G$n4-lK+a+D`}e@>OeL9A4R_!jnufWJT|yE4qau# zb3m`ct(fikmb-IcWSlKD=m^=xXMFP<8>=SIUp*IkXy+?t1L&DoC%?3+RSXIa)3*Cdlm6cfe^N8O>?G zIoyw*5JTiMNJ>OJm;6TSb+Nfb`!iz8-K*1`Gi5%TuGabR77-;dq!1)o&IG(PHtwcZ zJ5M>yuVSRRSA9b57*t!vts|oo9s07_mSvceEen!1@bQ9tpicE7L2Ise&|PRVq!$;= z!E2|}PL8XQxUM!HTHIpsyhJ0ozY-WIJUJ3P&727I8YgKfS;4t9V_0N2p3RbLHKse4 zdG!HEDDBMqEi?zH7?~=vbN~<4FY>=~q{0+66jmQKSOkpQ$n_4Xi;ykYfejIRd=IgpOZQi#Z^ zjyk}}Mm;WyxjmER=SS=J9iQ;m0{oBT-@i8#TU|1pG?#d}=tm#I7np!a(UO_t7S!32 zH~@U<32aFQg|pW{mpuNm*=o0>|@t+d5IMF zq!d-8W8dJ`cw3FZRn< z1CWTAZGUg$L@E;6+0mrHn3;ZsazwYW_u!`KE~eJYlp4sr_7uDYCPNy+^1u>hKi%(+ zqKX&+!rP0*V|MbI+C)RY2ojLE3ktwE2_A3k>zj$0ivMwj~BwgO2 zif}OH`$pWRx8T!ebPk8fW++zi3CD%RD4sPfN@^dJ%3Ea{_~~vJFWqUHn3F|}BEGa( zsRdUlM#}!C6YH}Dkci3hariQJ{4#N`K0@OG_K234SYhtRH;7o3jn>jG=HbU03gygN z16E&wEpmUT`sOwCj!x|Wkyr$4EdJj=h$M9VZHBa(e@!M7FjJ$Vj&aGEMg-facfAm! zkS8r1gpgvv<2mVk$F#Zs@=OiCUefhPnU5)SP^}P2>A2j43+T-i8f8o=Yg}mFuN3wg z`6GGNjdjE)lPQmcU9YS`@1*~we0&D30&$p-?pT{c+f@97bn)8{hS-RjJ5rflarBPU zrhVk?vYtRKrv-N<<%plbZi2(Odf~|-ZJ|nAdr!6x zZEd&Xbs`e})2eSGHQRWAY9_`^R2y}yr1D!runcH>A17zBa@_sG=BJ*o7;SBIF!vBS zXg?d~hdKvWu>gef<`tJJI7)k8yht$|gQvUXWgqm57an*WlB{#FaN0datIZTTS4yW2 z70|aAO3%S;$&4RYZ&C4Ca_fwtBT%Sm$|SK!wFk`PFqJRB9|z z2fsP^kqL-_-gfv@-zs>!;GC+sC2^EGg0jb-^V|NX_GANf7db`D&nny2Fud4upHJ#a znKv$$dg+G?&Aj?G1gx;$)vwAGo29j1U!`!b4@kI2&3wG((%{I(XU6~&&-EmxS+*Ew zLXM(A3^n?nY{Zz)t4croV0`*@VgZZEx?ET_RHn)h`6X|X7`8(X!g*zMC@>-G6q$aab)%L+v=T+<=egWbif@20-dKxy`MgKG^b zKPGRw3w~q77`l;9AUah*PI@zEf^pO-5SsXaCIigSCo6(dSDqtJ0 z7B#1(4g2F8mi&vC?O_BPjB8om2q8a+<~M-InXKIy`BdGfeZoqO%uHYA?LmTvDngG= z_8Xf#w(G6s6&g0#QMWQ6YnZTfZ$k3cKDYpcK1H;ITO%}0NfNa!+3CWw`%<0gO5zOE z4@x|j=S^Jl-QZaIaQ8%9ltMrC+Y(CL|AptmW}4AEio2FI_~7@kAD)nW{SOnL8xDuKm0V$?N@!AW+)vh z7@6YX2#SXzE6Oy^agK{@7pe3;Yl#oQS+?s8h0T1{*3{8dEDu<87{hWvZG0zDRD9GQ zPh{@49c_Xbf0suAmhJMN=7|!a5d=XB`ngi{TM`8mdHu^8w%WYkkB4&R$(IHossmST zi}Qrzdk?(5U>euHfHBWpjOg&@o6*CZ97wIG)0WZ3wJu)fR+NnkW_${^LHKJx>C+G; zL|A**(@-0o4HpbZwt1b+_Ja@($Y3dP*)5v956~}|V;=jD$`N*}u^a+l7jDkQtFaZ3 ztcp2LX^@^&X7qdsS0gSyy2l=pqV23yKFu&MwWzT|*v%6W6LHzrUi~oGRdc&Ru`2$o zO04w}zF8r(@T+H`EGwErY>e|W&>NBC61KVV7SF5|3F^cGOb3~TrHQrP@3#%=1q*qZ zVM{1Vwvb^CVt*;$b5kWk%6J(L+KXc4lBM$$ouES56`j~?&n*!$IKQ<*$o>)jOU#Dr z%Gh#lbbG)P$8bK3G0*3NT5z^jjKS|)Y}X$MUoTad78sZ&oty2?;~qI>kN&ohcdarn3}#_N^o#YE3Ce_zsh``*&^PJ-t+X z7Nq8yN^6;4-CT0ZA|JfneI)-OdB~G4MMo%4_XB5h%6O$ee_2CULWH;imroNnfs%tE zp+ShoS**R&h(d+kGvoly?H+2h+k)zhE;=QInvn#KPrV(aj%2C z#$V6dkfwMARFAJswqK|sj=?J5W+92WM7@0jb%cLA;%l|AY%Ng01$xWFu2q+!iaTa# zD-ZyIUxDz9;Te8tJCHGog%_!%M%FKDpKwnWYpN+U2U34fS6`f&R9ed%?mnn*TF4~c z^OK<22J$Gm+zL_tCJX;`R7Jcpa$J0+%CO#abj>jY8JPM5F-Pe(jM3NepvvG2m<@>tM2Vch$|6R%J86S%Jx^}PafV5bq9AkWzgWTpg#OSBv;(wP}17>p4W&nkhOrqhf= zeu8c_c4Tv+J@V(Iw_9@%8N%GkVwgc!CL|feqHMC`@*SD``zLgC$98Ke6o97rxqxhZ z=e1iXVZu?$b1c#nP4Y_gvZeb=tRWgmkd}$r| zJ~I|Jsj7uq936m=0xlWi-F03=Zf|!SY+Kqtq>HQ@SPS$z;0IcY>%4#FSEg9d3eC2E zhk5gFy~uzg4D;RN2(v7LIBwvKa8p|c`rpnl)angMLC6O?U_8Lay4b6>ERq<$ypRo9 zqJ;+0Xabv7pFuxK!*~3ui@C`RU*>>cI2rgQNLTSq z#{)M8kf%iM5s+)YbJn22?*l1+`|tN4VR&m@4FVl453~;EjAU_gB^zH9G*WD}>R&?~ z8p?(1ZkNoD9<>4^M@C`mdAU_TMJy(hD&0dnmJka%XMY`)Hu_w}a$ohSJh0igv+>~h zkOi+kaH|yJIii1|TIkUu40a};*`JsVoP`|Qmo2%z9_Z4NX%S5OSa=8OhnqCLU8SYd zLjqPe$aK9HXTH8L$!G$1$Ba9!;70Y%#JrMb5ub;EeQ{amF5@ElZ9ZweM`L z)u~d)8)w>O%vA@-cU)d>mY{XmGpY&PCgit&n^j|{yuFA+!rk2tuD=Q9{xq`T1(SG9 z;(R%%Tl)Q;*5cXs!~AIKdAxQUhZOBbIT8^4s~tt+btkl7x4APGd0qEdAGz z25PM-ZZ`6;)vpfiiucUWe(?@IB23`{Fus$5fv2WTV$PST%BO`H?d8<0oy95G;1J+G zUhd-s2_}s~wwWAf{X@-iIIBY&?kxSq{wY%VA8=GnOf#YQ)k%X35<3!lUpIp`v7ip$ z^Ht4-ZVX|A^`sP*T+>^WXmi#g%d6{6doLQf*Bx3G?6-zc9ew;-U`UiFmirf;eG=j0 z{^h&3@N2%7^^rnb#fK}V$ePmIJx#>1SAfK;@R^+Cw;D@vNC1dfk`fdvfe*glfJOz4 zNuz^aB;a7Vc{rKbSwR@gSm3BlXcUmX)L%OSG%GV3FX)m83zC-?q#{N1Hx`bAot2r7 zll{9C4=6yA02C)h1!|Eb1dU2jf*#%_qBJFlM~VQ{^)B6|2tlv!vie=}%TR(Y-lf;O zWR}JUIh&$@^xos_r12r&OK(aLgR-T`{=(1inRcb|K#lqsAR{Rp&_@|u(Cxpmp$y*N zkW2Bu(eR)&nE+4&8w%*+J=qDE03;-fO2$Uc#>+>}O0G)IBE`l^&c?_3Z-s;VU10~I znel=$4N+>^WWzDP~2U8LN@-pvg#el8e@VnDgapD zjR?M*VEh9?f=2IqHoHm^vC4ydNN~r5Qphsq;LE;bBeJ5 z$b}3Gv}a6!$@X2x6 zIoSRirR;p~l!}0hwxBV=8y*0%nrZhjGAxe&+&l*>__P#25Bdbg_?zuKksgbK>p%AM zZf8tl03THXkl_9~-n+pji2;-6zsLPd;{Tgw>tBL2`5#U99{~=ke6Q1){7)SW@H?5w z1fcsAWZ1v-ysyCkGh+UoqyI|nyIC2`2qH{E0?AS+fTqEcH2>eI@sP7~aQ;2@|2THI z;EXB&DhwMrJ3BA9vI@WsN=-3@Uh)7KpsGrXA+o3`nz-4Kvvcv)gcit80{9vxJOI7ikeqDbq*8z+ zSf(6+@m}IDw+!I$asc{Yg}w~%-${G7TfN(pEB+Oe|Bk_e|5i530Q6v=ihokQ&oma8 ztsH;{uK$+-tXB@8$Kv|WhQ8-Z`NzTWA6&jW=KgW~J@9`e`Q3q8@i*0f_Wj+VT=Bl; z|D4Zvd+cBPfA;^~K2!k^_QC;LAm zjW3G=R;mKe1U}IW&_*T0!YBBt$mCR zA+QcW3IOYL0+1RC>jAz1NNz50Of6s??9>Vf`Wu1-;0Awf0&oI&8hV-l-yi|J|Gz)| zUw*!Zg`<_bH9I*Q7Y{c# zI6(vw8-|UCm4h8*Y(@i&eX{tRemD<{xP2D3G1=Ji{t$?3X$jjnD;EuIf%Wq8YJd(A zh)5Omv;6ZEps}y6H8oN9tb35$VV^aWY zl^chPGY30l3IRdWtDW_EFA6%BYYivN;1pE;>1oiov-!tAsF_O1d$`PGKCe&k*_=6$ ztS&Atldp%U=+!X%IzR9i0Xwn!j6wBe1d6ft5cGejlSS|*-Vj8G>^8TyI>$OU&d!va z%#RhE&dtY_C6R#64enJCv``trN{%9Gon(oCE2;Xy zlMofvRu-C&QCN_{*Eu>33;!7%T;O%-oCAZunEGmBZ4TVFf7^80u{5_aGk-R@usW22 zaQQ$LGzHhwanF~=tHa;OJ0qaC^xT!O8P7`QfLp_XQ`Jxhv(&`f^P-YfRDddq)+Q8i@-=MKgo(SJ>KW8usLh#3uZ4W>jKW|^(fz}4XQkRw&yF7peY$u;3ADjv*E8E~Y)4s-$hzyMO!vl>?O|4*@{XgBmI;D3ATp0ZU%HhN@ zzLlIAVHBK*4u zo&bs=Eib3M8f7HLObvv?FQzU(uS&^VxyYks7v~nlMD+o~4>}4jFjo4fQH!k4?H>k^ z;6w&`2k(LIWCB*EFPEw=ue`s6H9F&y9@i61J*ofv1fGyy4>S?+@e%lR2N1u&nL>GU z1TYrUO>R#t!m>^-FShtMLI@2$K#rbdYye+*RXn*NLMO>`-^fuRLI;H-u{y~g(Y7F2 zBVXcpQy`Er-^g(xLT7~|Njk}&&>kb{?s&G$p;>8PLsJ0A!*AK~wDfP}nh>E!!Uq&T zAJ-#~DSl3^M;_*}Q-I+w&==t*VS8c6Vqmc_z1O|;OTxmY8QtmITwMIG z_^wN%i_n;vjt%L}@wX5%fc~q^El}DK4~b?&_(7;YrK@lC)d-brR{sq~xTxvnR~gwJ z>3iJer+3}r_-&sQ=m!;hKxyJZ{no4@XWI(AU*)_S?B zPc;)UqODh>q5>;dH~U@1-5fcO0DtXI{2E>2Sz6L$w<2~Inv={n)t{ublqmZkZ{Y3% z5#k?%&+WE9#K6f#%$=}bu&i4h=Fa81L&@(AUB%VlRYvCMA6%FeO)(38+jlzOn{+K) zLnzp`+3=sp(}`}aYe+Q%lH#>;)2pXuv{cDf)m2?|IZgFj4YqxWSIcJux5~%l)!!$( z@^+g=Xm$LdVH_+n!+N4KVk^{h4ov)b=7#}QZPXA6J#X?lTL$ksx! z)LgC>wW~IHFSqvXRJ79jB9+X>3iV>MZLmX?$}8J!@b-9;d#S&!8`%`3uzg7gOtx}E zl`nK)WA?B1=vRZ90j6mBvd?{@=}sd+7y02gcJ};WV61qEx5Rg>ob8%#&e^)A4;|1P z+R=3bohhQZA+%pX?D&LrX30goAT}l8K(g!}5N?v!-*hYfCONO3B9%rozZv#r0*<-5 zHE<`4kf00atXfKc&pMh_@GGu>9Do4ilhsnTQes&Y!g7;t2P8>~GAjHP5h82271Ysu znFb;=`cP-_j6=n;ozctTbKaMabd<^A?c88>u=_GT3^}`ROKf6ZV1sOFT)Ic-xv9Ta zyJD`12oHqtFff_6U`Zl2^Pa=X55o<0Q6g)K<2C6#O?hicfCFWR( z2h7$IEDlF(BwW=kRz9%P8lCLvLyCxN!%I4B=gw8`2bK;M*gbf zs7=Hy%~gOD&S@c|yK3%Qtyhy})aDb`F+`h0wScc$-|LU~EvTA{;s@W*r@AVS25&{w zPyX5dlEA1`9Oc+z2-$QLHk2nHzQ78;-zKGZ+f4Mg+j|vR#lJZ&4r=M;o@7S*PGKf+ zcCZUPlYTdcd-%#F7=<>*CwTJc`Yk$Cp5n(fiP_)sGXrNb*-Ddf4{Z~ww+|+vOQIyd zA=gU`?J}gReN>v8ifKO?)I1Lym~Jar!|=Z_%>mNVQD-Sxvb_2Zr8lGEOi9AZil_R6 zOh}BiBdD5h`#Rkx@xN?UbUDxvY7X!h8SIHMgXD#mJ z$%}Bnb*!Vyc$PV{Xvke*aftE0+pr zD3?v;w)V7o!BUe`_HsWjL%6wLMv$4bj1}La5)WbCR1m1k4Kvr*{xj#sUBu=-?=k27i__ft%~YtH zJ+*BjE;mxsb56B4GmBH)1!G<^&7X8o;Hu}*vFst9sYbw8Yg|P{D93MBB7>lz`48d- zZp7#;H8Pa-49l!uMon8Y$Ott|0sUneg9?5R9TCwFhR&@!=G{r7Ei#(wG z;)iOregoKM1dp!y+n-$5;SQtwUD7~pngbgZCNbW!6){&;{n|?>2RE6$y*i?hKLa9O z_i8shDmnaJb*J28{j>XWv5cCbI5KS*Q{v>&lF_y2l{;dO%z^qnbT3pb zrU#ce67j(wS@=n}u}C#M+dh7!jH3jWBs<*D@+6}X$|H9$p%sNfn|u#vdC$|so$gv3L7StEiSplaTEwoeOV*h5j0CY%%%(q)_f)w zIT7b|t=bBTFd_K1e6ey%|LQB#LXjP?$mo5a|17KW`}>46@wLmj>t%|wG~2GVuvoQZ-^*8R2CM4Gy3aAFx}&DjT@c7ctG|G%a4F& zi&CE2?@%w}er!2XHi6D9&yBJ=)7#$k&~@IAYe0jN@LP3FIJ2P~tMwkTo`(@r`K9YZ@ACC?0Qrc}m%7w=jj zB}PlVJqj)tKj3yj_2mwCgRCcX0~9P8qbbx8Uq$Ckf6H)P{+S7XS(MoTzAWGm(?g@E zS#cG^wIj6^Ho0T-W$_KhdaE768I+w5%j{xi0tUxQen9%9MO4jA0M^)bWDy^BDPlt>8DZwIL}`ZOQh9 z?@umNjlFK4W5keZ)(HJEs>L|>*M1_%K>2&tqROAT!W4}0OrGg!BT>6SnH zL&qL*2@JrYWzZILz8M!cbwWar!>xjelb<|B0^LXwB9VozozzpM4ym64^^ZQ@o54gQcZQ!*yUcq`dLaR62* zO%G^Is^5+D$AgB~!T5Zw!|NzuX7js}X0bkSKs!DELm>qNH}EBp`QrR)_~>?eP&$cN zB=+;mp-cBO;Sw6snI`6f|X>HoEt0@MC9v1Qu$wG{sQJIzgiY|#6O7_je3-`>nLW1Dk+>N_bh>xmbw)9)sLk`1S z1s4d+`Q31{!Tsx_epyfAZcGHt+~u`L_Osz$t9>+i+{h4@U?e4t31xZ}P{!3|&L&0e z2R;y2jp$={4_Jloy^~M_^HrA)l2K!-95nIGU)|R+!|o&P0sJo{2bVq#k60 zw_4QIi1Ke!u#;YEj&V$iPJ>3g=Q^-la}tOkqZ4gT5hx*up3`?(joH?0uMKZ>oc&Q` z-t>?I_u*g*Di_M_Z87Bz11$daoXsv7YR1QWsT^Z}gi~&2)XU3qUNNy?!%+=(+bB1X zUwtlqa<7!?fpMUM2y=%V8TCrE&3tg^p5apx33F6LWOngNwu(0DKp}i#7O7vr>MoF- z^)rD;t4YjHddPORX(DjJnGS}{c^~|h6fWthM1jsTzaiDYJrr+dbMM}vLLT|0>1bnc8?U#1EnqgLu?8m$IIU9$kd=voMwZmYe zqFRICxhRcy!E;8Vxez3Mx(^9m&50HrJ%K(*-*j*(Z*?%{iWK70TTDJDRzys{Uohra zCN{02eL4ghklFvd%7Ci)E|kDQlSyUaxAp8WX=BK|HOe?WD9QlJh-v*s0l~2-#3z~L zl|tO#9CZ;^J1zmaWVf!FIlTmojrt&2Wb?huyW<3JZ4~<66VlB6*21X6I_MV1EQ|!m z95sw+l;b@I4>jo&R^)X4KvQ?aghkaIZh&(F#B08};JbD%1;P)$Q z$?~r!wj7$f0(<9pY#cwz%C;j}&nTe>VTTPHS(moU)xQcXuLaTE2;}SGCn89IIF_9Di3Pn5eli4bun}(g(Facp~12PYkxu*Tt891->t*w zrJt!yDLPHu{#9}oq`LPRgS#zq=pd~;fy*7ssI6FHdIZ^jg6eJ)=#1=P^v%1^aNK|R z!>T4)R>H)&eqc>ihJ}~;d=ld2x>B629$e}HKMN%)7N=>>QN&0nT+%*o@?H^5SjxJ| z7OjAGqRmAv?snIbFL6ev7*{Qg8?^|T3NAU#Q|#elD8U~CH3|)-fP#LleEY2gXH&-I z*5k&}*mO^AFQ3aTpl_NMIOpw?ahYfhM4oDpU{~Og*8115u4PM+wUOLYi;u4c4o^+3 zC>Xmda-PFquC7}T#H7EH8qglRv~SfB;Pf>uBiZ$;`^2ZzHoxVgYJnXv(6oOysS$t2 z!dKzE@ZU-=>=Fn5(VA@b|Geb=C@a~D6Crg;Cu{j)4>?Qh4xFC0ei{6nR@n?)@K(Po z^mDvjJt`c%!g%D;klG04DMN(oF^Uh~7Mm{js7PXwKsS&)ueFA8`4n+*N4Ax5v(66M z0GakFw<&lT3qSoNCm=!FW5hT(3tJ-;86#%zT=tI4`hvV#?hej+?M~2!8PrMXyCMJ* zHQ-Od%+b%O1(G77)h@pF$HAtf<@RhrUY;ck`xs2kP4xORy74n7W1RO_<< zHWm5p@2(y|6-#YQ1>UOm1i1%tRttlN&@+RN zI6^dx2|!)NV7s)h**h*CKoqr!I4*9RoyNyhv*TNi{+d)c@1%N9q$HHo`4{UFT;xHB zkf4IXbKcFNIBuqXfpKsnm(yCd)r#sGO85>0PDH~OpD_N(klK6tGR135=fLvnr$YpY z;pUkz0u}VT1}fw`2LZ}%4bq)?^UkR3Nf5GqI55aZfhEkp)ojp)9-2Xhga%OqSZX^3 zeG-Hq!?Pr1^P^hsIC1m<`Yx60xZzm&n4Xoco#7K>E1g|oUR-NoF$4}*K;_V&wqFEM zVz?KFDYs~j%WyjIU+p1>|OD%kLRsEM`RTm?L29~n%m`Z*3ucvul#GNsMk?p z>3`PnzH`fJs0PwXIM;F%tVkG+Tq$(ewgYSMGFa7Ln3*tx(6irT?>3&G^Mwh*bmg zVzJ=m@VAaR*(g0kWG8jYAYZ zL6~gryTux{FC{))r!+<%Fs^1lTW$iMSi{$y>{qh{yTA-b^({A;0Tu)%#HU{Q;6PNs zw38-teU;7~&#YwF7pM{Q_)J0SlysC~`bs*FRO!3gJAt~x{rOEw=rbNq7bxXm-bEFZ zaz({-n#e)MWmGzr^rGCawNarNJ7`3M{EV*fJObmNUzlT%57gHEbk#AuzXk%SKJk2r zxiF?YjEbIbW_Jt{1&V9as{2lDUL$%FF{zFgCS$0$DO8R_$s#UMq&`wQo3H9Z#mi8^ zJw5H$KxeXxj(rQq{`jG)8h5}Vs$cKvk#TV4aLag1=U(!Wlp=1!{3YZly!Gf?CyJ%| z=2C@7p68(}nsSGx(us*yL_Z{utd|>5A47QJrAk7-ujQk*X8%3q=Nw=Kf}M z{>;OPaBgTYE*2a$1jh})ZYOMMHsazK0x46kIhqwinrp8U4XW0tS*l%+sf{$4yecsQk&H-f7|$$!!I5%$ zDi7w*X}8#3@I6xbz|uUF1Rds%azTH;1cA|Gdr*$d5RmOuy?mEAESZdou8|`l^3sSj z@!zEI>%chb;7JT5x$h!Fcy;EsM%$%9+ZK;(6N*Co0rzsLSfK18*?Mx0!&i({l-H{v9szv30m$&G#2yu2=$N_s zOa9JgX!cSWzzU~(L$-+X1sGEUWz_%|Ufntxl{((q!G|C=9c9NkvuoC;MfKx{)kgj2 zgN6c&i4lxT4OyKD>amq7Oc>!Et!%c}V98~9QSgMxdwBb!0 zpTK_8nw|fF#P{933L5M6{Mi|+VXyc(&g7!+^G>?%>yWkROz1ZpL=lz|!6q31dGlbG=r;vzjnIy`Tqz~VX=IcWfstE(n(Ia z`I*0b(_+*>6L5>t+q^q`tsrkevp3uGG zEe(hQI+E6ndR_axFVDJ45&qN5 zP8N%%nIP2XBj*N(YrW?F0xBz0I?;>;8;xOx(U7?nw)yzg*I0{cyr^EioOHD?mR)5m zy5HiDk4WVA!Us7}W9u?3Ihf5@%zG`7xn z_}*@n1%t}Zb!M8A5h|vuZo6(%ET3P49!|q{m%7F zxvYD(8ID!Sbt{?g`NasN$$LOzkw&49i&(YKFW+{90u&?|NXrBpPf{Zju%SDsRxYb5 zILv3U^+a=h__;Lw%pcWiGFFwplv%Q904t`)GPfztuuSOv_i-KEo4(hKLdoB!VO6^> zd8V^L#?AHGuo_Xk)gZ1uO(CEQaaDf-yut;Gx(g48OG3Ai{8ZzZC4?SwXx5)TSJn@e z5uo?c2V-T{VRWyY=7*@3^3ho!e^`kjntPh8KY!M!%Ao|LNecZF za)p0E_NFMKDEEF0R%Gs#-QTIXJl118T32!LzPXipv^8w+R>c)(`Sv|KgGHZgS99w= z$jR**D=tz50q+Z`^e=|tpVRK2&*l)nevg`UOI0!tIxSKSzyBtcW+!%UeoPm)R~liE zZG7{Eo_kY3Gt>T|-{ zqd9l)<*_x0HxKQNn1t$m1v@rZXqIZG@|wyYj|pynK#X4HOfe)xPYf0QD6A5fSwN)g z#PudoxdNyI_<_&B3cm5DP$ zG8p52sswNfPh*3wKue|)bs*Yg|Ay3vr4tZc;m=Y%!sUvPFw%|ja9{GPXA6xQKSOIO zs_==ngv#>*dzp>%*$F?SJRY<=ZJ?W!5}8Bu+Na;KU!C8K?KlZ*kzb;Fa|4RdX+OFM z1P`k(o|(QDeKQ;4y?~=Duo$qF5XO#B*SbQf+O$T4Z}}U zdyuqi9V`W-&?h3gLzN(xUlN8rQz~U%{QPBPxxb(-l8Iw8TOJGahuLA!l@U%LGUW^< zZv|R-k0aCzEbwef99u{A?g%0kP2bs*fElblF&t2H=(8u`0Zsc9R`lmV3+(M!K z&oaauF6jT+5&`)Hu2b{)r3lj@@_mRmT+5Ko$vj~>20=B{h@e!z!d=;}wz2xq_E4-RLpxeCi}U&~n^#zv2DQ24CXHJ*s4~^M1vnCt58$ zc=R+c+dO`iEX~}K*e1>^dG1x4157l=FyIw~k6hExGQZS+3VeEKv86J5Y6*Yp+#W%Q zJu5q_x1}8p9hGlYHVN|9=0$c@Q_z+3;ct(-+(&+YtKwa@IWtMD%v&_e%v2(;2d-ku z`-m=u?j`_Vd`pa?yNo586Tav@NOKw}KZenw;vh5lrI`t@NG-Q?!tFbZbcd;&PRvkt zWzZhOV3iY+wxBBiI?MO8i)rlZ5X_HOh@7S|GhXf;8^~YGio;8k5KAay;O<@77F=Pb zU&Ka`^-3yk^V)MCDvhoqt>UZAZqs8opE%Z+JSha$vT!)VqwSAhLO~60yoh#mc|4m9KH-*9UQy;_P7gIx1MJUge$~@fxos=2G;v2U(isx)iU{&@e zPQ?vymXO=Cy)beVM>@})E1YP~axma04<=L)!m?r-PVK`D#1Kh=A^qZ|+qC3WQ8D}Z zDCf~K>vDa7mcciB20z9dad8Ln#FF6Y8pp-r0OT==ij8A;;dI-|4ZS3H%zgw8oHM%0XSz6x z9YsxMW}Cc*L!O-If>xdqUU5OCH^Gvb!;4;ZVU6<9Dn|6Tz0V&<&(K8uYjKv8FOR#% zRz1n`A%7Dh-p5ZBptb@Br9PbK1iXa5#2Bz*%4#kkZW7ZTDr0}`A$rBUa4$?D?=FV{ zVrF~X_B~aatJlr_+$%vp`E|uP9Eqm`sWT9W;wW-M)6_^rH2O=x#c6yw!9!_}a1MIk z5OyupYmEz;p(6D!N2b82B46Aw!<$RARS6XLa z7V;4GGP<@{p|BxAK1ZX@-EAK1{SbHw*biVp7**W^Qn)=)@*{RJiH?rdB7<8{wZNSP51c|tt8B_y_9)Fnpv zLf;MYiP(M|NbH{Ts9OSc#>PJ@uHUFLGfXK?P%`EWu1Cxv1?umiH$b&Idh5!`3y1+1 zwF43b;=>9AQPp+{sTy=i5x!lzal~I-?j~*T_<~E(lX9FmoO+fh*zrjSfr?YriqAea zZ2_}sFr>e>W~+o2KZbIM#{T)(LjCfj8R7wYvZWW)68%7BWMTRnKsrb&@6-d?`J;!K z#Y}|@8dixe5V(@|1*#k(In@-0^+3;S3V@IOXw=U0BC5}b!`=grv zYx<8GJxI7 zoLnN7VAll@U{JIyxCfF}%7Vd9V)Y5tZyX(}z6zyVYo^`PtJENK>Mb)o3?%p@mT&cb_cw3Ggyf=L5?c*QZm6HaS`> zyDxM+?~u8ZVV9^3QWMX(mctybBxDen3<$f73?s4fRkIybrw`?Wf=wpu#S$2~rjof( z^7d0{=W*wBL&lcDyo+e?}8WlWS`zeVPt&P4ak4Sf6_#CabMzHPEo zB|Bf>yXbc}b&|0gn!RJD4AVgzd(L8!A4?qGwl%=>3A>Pj_`|kV`>kUZr!*+cyS#<(siG_GnSNdXwPpdN4;t)X^t@Ri=-1k6LD$ zx_~@uOX7us`nij9>xy=RYq(~F}PP46R!L_bN%6#@_-cNvv^e-~H zcUWVUH;i=sYJQY<{q;bP3L@<-f`AxLzlsuCDmS6;6)z|C#yt!d0kUpGlCZ(ua(^Aq znzLUJPtt6{>LQ*TT{3`w?)FiVjA>EMN8uC`B6CJb;kuu9+Ot8#C3R)V9`6QAY|PFs z&%;T4SFaj_ZrI^Yh2&^Bll6v^ty?kTbDAGi&c3RkKKkJ}8|nMuHF1%reFNe6`0SP1 z)bN!i#ZQ@?=8|8Q{qs2b<8!UX3elTJ&Mo=?b&=|JibdCmK>wtFz*E1O;|sew`Q%qw z4}B+a#t{v>u+V`veQ;j;anD_1c=`Ty2p>sa6?2HQfdNR8q#_|Een@oe=9nRYBDxr` z36)6iFiQjgnVnqgm9P;7QH=0g)mnIUwN`*Q=p_u-Seu3TUP}18jClX#g&PwQp3`U7 zDIV$h#>xl+Kv7YDCG~1N71FmzEp*XVlU@==G<;_7p-&Pzior`r~>JK2l@$Awbnq>ouC+9H{5EKB*Q?zRBGr)d-2zQo-h3Osl2lb(G85KS?53= z^M_3|D7H*D!@)QLpXi_M8wL0@8m`{7U4yqP73P`lb9%F3PSq(Z?!)GmiFuf24s`He z7~|)6FhS#xrz{iiTC` zQlB>!e24#kK}{PZTAwD8NFq*d^{EYevwK)?xI;?m)n93p4^CZ00*M2Q8Nh<9sNBFW zTxvuH#_;9~E;us-{6S>6{eZd~A!@q%c~b}dlrrY`mw4OR&$M^`MfeAr4KcDm;_3E7 zDq`cD2im|H5#vXce%wVY%Pi>1DVA>h5>;a34|vCalnuyF(&&+pxY2^BCYBk+_kadX zWb0M7r%hRb7xf#|Q>kV(iNF%L+?WBy?~>IE)fk1>q1QS^o<{v%S_|C@FIzKFb>ZuR zD331OBs#$Z=KeLJ`f}T&7_gwekhl+PVVU07cY)aqFM+&O+*`FHbcxnLHl!w#9_ zX1p3RJs3HAgOM}%J1o+@QrYbudX3ri0%dbg)JaQ9M837$Z=ZtgfPakqa-2%YU}&CAss)cw5QyvmUDA| zPHaygr0K;DG&bp{Qi5uEGf>zKJ7S;!wXfMsAc*uLVW3f(vEZ2J7>0f2U<;bj#~kPB zlVbf~7~UE+2&JFKXLeuZPLm#28zhp!@ZT%z*dB`Nvhp@_Bw!HM*{|K=+#Zn4zWvVe zPUMw}tKvR7RiP8BODb1W7%CMrxkTT8OB(qnXpzyteDNE)-LKJhM|<|+JCbhi`!%nh zV0Nvb^-Ip@dtnD>bHl1mlzPQ}wpb$tL4NsWG4JzQUf~!JyUa3BaT>jOqWnfn``GUq zp=x>S)fS7=;1!oy{XoEkc7zo|;)zqVeIQISM9|i*5>KsQH0Oo;N(&>n&z>uP3l{?4 z5^uC%sPTl~?WK0a8X}3kFL1y%CGNFdfqbK^nev0z5iO~z5X_{R&-s<+@cN?cNTVVN z*LQTCoM!qBj;~u<8x^ey5qL5Xgt4PK=~>I#E%E})FN>{QMlRs%eq%SrftiFI!W z-TDrAQpQ#t-hh*yRnpV~W>Ls5Fd==u6G&@85ftzF)^x_^F%m5K7sdSfS>gz&xKkr3 z?&l0n?=5dvoWs?@o`O|>E(W?DYk~WHLZ9k&C6H-n`jzvu+LShe(%<6ohHm$wh+JSG zKHdX3L%x@|0uzFL2fAqL#oO9%b4*|J+b$gikiK#Cd|qb%zIp%@m-%YmGW~82^=hQ= zz${UWc5SMlsyB&}I}6jHJvT03<%;ok6XPVGmZSvLQYyv8RcEAsS@gRvmg_PsH<=nN zQ5(hk7$X&qlH3#run}`(52+;y&DBBH6Y_gXP2iSOP0Fs^zonkuT#iF3+heFc86=B})x|l5;7p3|%Bm9U*GU--5t!-g7VI8c)>!Hulr6=Fuw{#Nf zx*mcMW3cfvemQ=PruSKFHnSVSXn3Co=`Ms9-Nm8^{SDQB@GX`hd1;;Zlgh*61D19w zc@|Y=T1fOYZ5vLK45_j66Zg^7)>x>?veGqc|M#PTiHXw$vC2j(ef1$)i+K<$xHIIw z)v-7U#1K14lG3CFNm(bg>K$^^8kD6R8BsTil5B8O8Z%e}jt-Lg{Y~p>Wii$yNon$} z`bx8(`1>jlYYcgmE!Tq%+m++r^Pdw?pAF`J;SHminnbZVxMVG*MGsHwoi2Ig zXPP0XG_Octz)CzOIEa_^=-a8m#*}Ft3w;khZ z3ti9>#q`3_a*GqClmh0J}n^ie_wVfc-5X31FHt&qP* zZmiA*-*fRWrQUflfz2v`&FQ!q>gCFfu!$poHnI9NLer$j|D!F-G3xwfpi3Bl|7=AkD!=*4Nh$kc-e;~)Y(lvHq!QX+I zm-OFVvC&+55P`0kC!=3Xw-V`Qj z#Q0u8Id}l&3w1t5388sOxZsNH3fM6lC6YMBV!@6jb@3P#R@rzp9Uc};wFQBTlJIFxSZlqNU9!6NdHN2=YCh)UJCtxuvDu; z?x4F!*>iC3t_4N&a-`Gy?0s&kg$XZ<*M9DS($wlf#Y*TN{|`Yyc#7-A-tAaqTQ0=7 z>&4$vkf;(@irzoTiZOjYjjWSo-cF2qfnR4Rqchf0S@5s)R84ho&(?;)`}OHF8VB+A z0x6!Icdi)o*eUhBSecYYZ=8F7sZu2UGe(_9qZo|WJqEfgv(JYA$iErxp)m_TPkma`))GL7++vl~pesZ;!(!M19yJ}5F3{z=>A zOA|a)gzV1TE>=`7lyr~Mv8Z5T{wPiab9rxTfQV-@t*k{VZA(axU{HmBYfnI#q{`dR zHSIIZ$j7t4T1=mID8^`Fmj&lA6zRk?Z)72WY;Ohyr?1a z(x^UZ-*~8&K`mJ_yG6f$mFyBybKcxYwAC8c1`qnUDz|$&@eSOg;~pukP`r_!)zA=; z%`jghT5+CerxYB&=M5HP`GF!o<;oF9lr2k8@s3d`lt+{)sQws_A-I0P`%J#~O)1Xg zd#3CvMQO_S1x3leD#(kVirJMA2f^{EYbMn)49^}tQqrG12)Ubo#?U|I+J8UBDH&g> zcAid`f7yt20x`1YjfkbOyYAo=Wh0G)>eExMtjjN9<@Af6Stw`+shm!Isep>rk&~d8# zpp%sVIkVwO>79g8n^1meNS7peE+P=azG$A=8BB0zvAN@a_Ewoe(fgGH;ry0l5P4a6 zRGsxXj`VBKhOQmK+ZRg97GX!h5nqY;<5Y|AOn^S=VWfaWUoku$1s*Hu_|dk)JgIQ@ zoUDjsSWbCa$#dq28U4uCkNkW+l*cvac)r5#Co!^%o5j^V`Kg+qI9zyrM$@cI!sD|F z&E*t~ljmuF6jHyjy9m#G`#g^5l0YBGf4LoqczR-1z?Wk-e!30(A};iXUGQ5FU0PN& z#0T}HTvc#Hvta6?zcp3VAT*3R^Te9KQ=BMJsSQ}-%%GQAK=b2OGczEHy39YP)n+&9 zjI*Bv!3`Ne-=6k|_NpK_jwdk8=|Ero6|MwWfvjMb} zug?QTGoG^}n-ip-xlK|%$ITU6I<~rv**M(oz{ovsoFv(~~>Q)QC zRagmt(fpc>uJ*;Nf*=$Mv9G+$Q)nW^OeS1(R!~-&p(S$q2sGO4YUszN>af_s?T7gRULL33US&rl10 zN-+n_xV7$lw93bxb2|!x#(n#J)b(lDMA9El!*e8@HpR(QO9te-F5wa*SVIeVV=Ul; zyt=0rYv5PLFDy0Jul~Xpa^Qf6EbN~@3gywQ1M;uqPbFYTkR^*|kFsrOv2NIQ8hD8L z>nz+cuAp+>$C7?Go;Jlm{Zba(ZJ%L(%Y)@9k9uZ$7_!=606EwHc^X-ykOOa#gR-?^ z7k3!a_I-5)e`kn0H6v=QuM^m9GJQ}%^5PV{{9}x=WMN}O43K9L&PU2YyQrY zS{gu9q$}IpIvid}$tTc!I+5d9^>~r5s@lWeKh)?kZACAu zSs{EfJPIMA#qp^Sp(Tc>L0D&yKu}AkVhZm@e=#Kmm!PQ5IaZvjo1& zc4t2_zkQHL0rRhxwE^Cxw7$w~F#mfHemK6ghn>rup(Ac8KX}gWft^-L1j>Fn0Vst_ zqyqiO1v*QD>k5#N7a|ZE=O2OF+e0+y(k3!SP;#nWII@JCVRBS|QidT5UCc76NTNPQ z-v<13*2(Yt*GM^=+kPj8PAVerl^?LhbhxSAF@DMg_8}f6-W11ZD-llzRrh!ZbLR=j zP2N%X9#3RQ7xu>wE#xbhsibf*vN9LBdTjpu;qiEi zMjh~s7)m!Hs>jkqWY?!HMF9sLPFiOgSh&QLm)F5~!m@qudj* zMs8QTARk5?HR6QIYJqUcc%>L>6~0CzvZKCzsMk3c7Qw5#F!+EIYV#&d$OK|{i8;Q7 z^?TXOsA@JLl2tQ`F|OrIO%Wk}Qv8$+1QJaO~5HW%2d*O9a3s1E3 zaf%f_TTj)WmrGkP`T6|c0D+A?O4}1JS!XrcIVUlaZU?N#GQRx=wP9GX+|?D~u-I-) z@}APb=i=^aI6py5QQ?;r)^zW%f3T{L3}bQu)~3zD$wVPR4TBNr&x9qz`gD(a03uyk z!Rdv6T!C3^4ixcEbP&!%X<-{L>R+C!eCkfa;lr+$KWnfL|?&2oiyV^$mYQ z7r1EKvi+c@!QbQLG>tB|GCoMxGbQ%ZrW;)h?5qj;DcaIgsM0(7moW|k6qmb!0xSzz zQBq4tS1UtJLRgmp@B$c@lnw%}mx0{`6qkKu0|}QdKmr<<$z%f*my&`4C%3Q<0+TP7 zu)qQ=mv27;>X-My0w=eCKmrvZm&xw}EtkS!0>qci@B%8guwnuVAD1Q(11*>5fdZ?S z`Vj*t5->M83NK7$ZfA68G9WQDGchrjkw5|z1u-=>HZ+r9V<&%&^#xEI+R_CIkVDw#T1fc|ShAXNd`*_&Ehas9(Z z$PNT_cs~;cI=p{-N?Th2BpodPjLZN=HZDeXE(Qhw69WV1e;lptxB$XHCsRX!G#xR5UG76rf~cYX2{bqP3BOGtdqMct5Z(H2_)JzsERQ8G`Hp@8toC5>fzJ8<5q% zoTdKdKm+*qbO4NWjQ>sd@94i0nOglF3^XvXwzL6SxtdxT1B^^9Kmb`$DLMxi2O0p- z%J45opoM?E^?N+f3215o)PHyQn>!F7Dj*L4zPI@A2JH>(Ol=(O>FiA{{%Vr`uQcy- z7O^rEvbMAYSvlAv{KZe$)DC3uK6qF9|J<*+m9?{#`+uR4sgFuDB{Q_PvT*(5{`W1@OUlWpt4mP-r|17#1qH2L0Pc(|09qzi z1^|B}13No_{r!vQ|K|Dc1pd?g-=}gw(|@!3M?wiJBWu8475?hteSH7v#OdG5LGf?t zPy+t9gpBq3PJ;jxe0y0^?zMeLH~b}wKT}k)Y0<)S|uES??Mr>0b{IfR>Sg;s4m)rDtIN{K$c zI{baNe__zO(*Bo%h?Rl0;a`$uVr2sW?d*WA2=Dvwj#%H<<6XOkAeX-v9zaiLW$l0P z9s+o8*Arl5ZHMsJEwix#=mq{d`WIpY&;QV9KZpZBFZ^G`&J3WJ_=Dc#r2e4y zIO#u#6F@KfU&O%xpqKlDm;m$&f6#kQ#XpDzK(F)%z4KK5FXDW!0Q@gve6IjBc)!Fy zT;F4X4u9O=sq6ni@9qYFg5NKJ-td1PkP$!+`UiYxX!Kvm`p(eE)aj3%^)IuvquoCO z-d&9U0pFRJ`~$wXVfqjFJ~y*}!1uPy{{i1=Tl@pQ^S1m0-?d6_^$+;Y+xowd<=yxF zSLz?;ccM0b%kH+8M68eAi!T8S9{!gFpM*H{2>yP<8!=C}aYn^}I!Nd;q zkHNgNb8xo)N5Fe;j(;H2yZs;OnBEh({sX?Vb^9Cs&$1gh+S$FU;qNEvT?zlefBzVP zKrSEygr#|F1MUE`nt;~(DuFM~w7cUx&}Yf_YD~1_`8se8eInDko3V-+>C4|rM3;IQ zMRm+NWCU&RGuIcc+;?gT>Rf+WZfOZb4~z-)qvzjl!Dr*#?{JCck(iitBTU4FmX9mPPP;rn)L^jc3H2n z$+NaBqx`qSwL+3)Qi;Ctv_BxkI#;4>3=9vhqW0o-h51T4`R$&Q1UY}8if|9&3bVjg zs;uUIe9kI#I!;A%*B3+QKQ`B~38u2YdFqKQCCo)7Pv1d3|-?C-m#(lnvpWG$7289H+m?K*RbNo*kH zU7tlN(cNxdDp{nBn=$I`?b%4 z+sjY;<5$7e)u9(<7bct=(CH<9vNpd6XT?mkeX~*2`4&@~>rF~T7bSjZk9#0zZ>%`F zKEr^A;!~E2+bU~o0N?Oq3Xi*@lHu9dJ@G<>1`w`nve>-lHavf`d$SYeIlus;@XL^@!!W>Ic8>n`VgxqS($6W3yUf=<{D0>eBU<LqhnQ~TL8*PkV%xf z*5Hnj*FysKw(8BUys;vYn3>pFe<{WJD$4n94_OnN7b#=5QBQ-lRqOA`n^_n^R>Dj$ zd&Qt8Qx<^`V)h{Qm}|4$T0D-2n=mns3$NESv5Tgb?w>5YW_ygy4dpCbiu4BR4&iC5 zj9KZ1xp#m1Gz{=&H!PinvuDc*Q+ta+>q4$Ww85l{YI&+MHB7M1@+%6ju0paR0s7KT zx?u*IhAA!%x#ed_#6fV}=^YrY@Ij><$ipc76Jhzu3xgtnl9%1_U^f&Zr8;dJ2Q^*l z-5&FuZ?V2HNgW5&`62dME3s>;1BnxB5|z>y(Vu@*)tVKW4+>i|skjx89Dsh%MWbUg zhpKuk`Wufszp$sCbzf&YFyvb9!Rhtt2R%*>(690DDx8v@!QNP!;6N?e9fF_a-E-{SMGgVugQHZVx(^xx>NO`YM@$Bv*k*%XDE}%;LZQdCh*w zZ|~VHGVlnN{OoQj*GrnEayG_Egkwsse_u&TsZjDOc!evjxMp3)PiZr=F@34fJ72pe zc>iB~!32pY%A~=4pGotc^kTxew;4ox0hWImFR>46smx2mF~u_Z~+)Z}F2el;Usa+!o#cer3`1`Wte@TC~ zQjde)as@vV#}Rj*q`2qilU~Qkv!KOZWHK(F3P^jCvNCK6Bf&PkEpN{y96Tz(96lFg zv-8wf8E+zcRNl(%vm?^3n2$h%&X-;qzSRrrc8qNssWxTL^lH`?!;B|d-5Xk{t?{<*^Vi2Zqy{R%q6SyW>@o7`vrqzrpO z(2hcM*Vy2XWVSr}PStdaRC@~(NHUPVY{U|MSJ*u>;e3!k3HOx!HJFV{wihqcLT z*#b;*ot2Oaq?ZwoQ{66X(0SDMLXISxHPXbOuBD>7)r37;U9bEwH>dgMTkwCw){P0m z+x$4@EWeqNWo_M4MA{L!gQ3Rz)CF_}8RSx*3!9VRVk$PL6$Z7X3wtN1iP4#EjTS2> z!Yr{L!7(F05T3sYl*m$->*eFoay}29p&=rhHd2@=K$lU`Ox(m^eI=*^ci_hv%Y-Fq zt@xO4k8e_B>V!B)k|f}b0JwiRSM`u-pznop>VxxqYr!Je^368t+7{IQq%1}Sz#~;O zF&54JR)gS()wqR=Hrf5QXTyJrAEQ1q{7XdN$X@!5c(wUb&sJK0? zw{GJeEPoG{Vu3?jZ1cijzxUot%BM(^`aVa&m2XZYjwP4pT*9jAq=xjlmQZ4W4To(3 ztJInPa@qpZ*bEB*jHXTxQ0DsB4aK5ceJdh#68zQ~!>xktF_8aYSn|_Ma4vDa#qgVE z$5*2d`9H|j9Shf0r*3~~^w^|e5m58wxX4SY%%H%fJJGdYD*24j-8N>-5|IkCrdu9< zK)y4PM%l>fIi;78AK0Qa{LG8*;h?N+r3RF6bahDT_mGG3ZTuDS#HWo)C{AWBTW&LI zaY?~1Gb>~4!0eNy$urgb6a?tS`0~r}QsN^zZ*A37gdOSdhSGn<%j@wqI^j?liP6F5 zu;> z%AM%09I1bAFA+WEVR``g=+wrDaxBP?M!saud1>!}eWthboxKmr(AK86L555Ipf_3f zv}%K(t%+4%V469wFTudSj*@K|O2tv;-!YKEt(Xi4V;K++=l39Z+>vkj5-OslW=J4C@ z!{_?or0YoKx<^7U-iw6JR(FfY-a$kQ1eG z+bMrPfE3?}0`v8>y3ZPeY9(kwnFAIS7q1qSqw>3ZJd}3F;X1r?hs_TZyVQ@(^nKC& zGsSqpI);Ecy*9`*Sf63^>kfxTIKF;DdbJ9|G7jk=YtkqcE(Y8mMO7oZe(}OH9g`*K zEfRxWN7_IYw_QbZN?_c`i}d+Mgh%$Q-IITRVLvk#iD4Xb$kN;+4Vf>JGyY<|JHOez z!|_W%O+v+LU}eTzYMb|rNuK5FumGlI8U#@xir zLPQ@#Atd1_CjKmXa7i)rqA9_nb|%U=5jvPo_$?vjQu4>esxqc>5qs;nV6nQ>Ph)>} z4>=QTzj#S>A;;>N-bc&->4$bj0l)-34t`}n(bvNGI~2nlvc9$AOSk;&mUshnzE-)w^cRE4Sg!EMdg`h+zrKW zY{+1MAX!<4SwSN=TG54{C3PHJp16N?(B8f6Ze!(hLe(wJVgxTlx8ck;puH@Tb4G|> zM=|TGI|!-Haj%DP#+v2hzUQ88t6zy6qBL@&CExHMi;nZ~n zX?lsX3_X|DCn4`li)JR6U;L78IVehojK)~Mma9hwDolXpIzJj+P~K&b5VC*p%poiN zXJjsK2T_T}3=-K+?$=)Gm5?-TC^0;GgtBjyIT}3CyYyJ1HGDE_} zley!Z#%b2D$_WeQ#(|c=K40rDRG5k{co>MULRL7D+xwNqXrTJuA;L2AmuZXOZgGdk zLb|>7S}}(L2_WfQDTpV;M|EPZ+7q$%r{fWB# zSkppCD96NMen8uMF(1>B7sfjoy8_eSKZ|Lx{F&&@rR@ zgj_m>Q1<>k8aNT`zWgX_kyYPS@61A7$&{33m0lhhaBs1|41OprSZlv)c8HRsbU#Yw%3`ypGFNSp~F)H|)dbrpG;Of!3^AM5sgn)`DHphO!skzMZRK}DQ*A~IjI(B7!BE!rn zu`c4lZ~cwP1EyE%6o$|rF&i>FaespytyF^vq8DN>q@hPaDK>xVP~}vaC@PAZ^p4Lq z4C~9y%r3$q^e4mk-MY;UzB_~c#vNM;jL1DfnGq2miv%#CaGpdqaH~cuhM~tG)FDJA z$tcvWzTP5H8c(0HT_pkA$=;=r7lF$;=*sn4`5g$>5HU6bZ9(+KyXX|Rf*!$!OnuHO z0@jNJySsX=njC*#`lp{#C1Y|=X>c_Uf-j^E(~6~I%C9CF9?^$76w@1qlDYI;kSlon z52oWkA7o}V*~I9%JDDK27v`8oRK!`1jTb}L47zzK9G4VGKv`&U!6iFfsqH>bH|5O! zc+tKMI8L7E=}(kl^tU#CtrOs#v;DBWP0qx|#`)LhK>4I8Fj*9_P z9>i-uHqC#fISzI}S(r33bRcZ}Ez?(It&6SFu}?<+Yd-8+$Lj$nfMJ}X#=<`0F^p1xeBZ^{NFt26+^;6UiW%i#irBrip%T ziGJ4vA-6USVk|V4Xuc|~MktygjKEX6em2@N+<1ReC*W$E%`m_FL_59@FI(cAm*lsv zR(0%deCm{wSnv`d*n3u*N2t3L?O+GfS(c;^ZepqERN6dxv%Wu@IpW}Q&Gx{c)YUQd zHO5mniQ=p2Hg6bZ4txyKfEbt3h_<48py+)y!n_MiHU1GBe_@d85oCW3j-h*f!G{W> zyrBf%ZlKh3kD=k{xmJf6e%lppUTU| zZlfI4#YD`_trc?gb*l*_25u6fUbTr{zrd%J>?aR~XQ>Ya;w9Z0D!Fi?Jf;qV)1A(4 z`za*@>SA1t#HU{tTg%nV;F~?+S%O4c7(ZPO<~q>6G=%66;b_Q@SA$KgsYkMFH9vo) zU=NoE%7{MYly;;h$_*a7I|jE0wzwO|AUh*v&<$Z&>jfD-+NAmH@%Fv8CDc#Db8#0vDnBIeczDfVslsm5~LnUTvy#W3Tv5uWOFQFJy1}X%6wq zMem6Sd}c%mI(03X>>G`gJmM63z?}%8<0z_IP%at_H3PePcIG~2-#3Ng+xmaTY)dy{ zWy4;zQ*N8_wA#~F*O$(>_;@5R!{a@2QW3hPV3I{pjI)c!5e>=E8g5oRtPVD*1K{dx3~w&yII?!aJf>LkS^IqHK_v& zZuqYdfmX@R64QoBw|?nQMO$UTd24X|J@MT-t5fo~wPrH;V%bAl@gByQT7}xgmyPoM z#$VzjwHu(XwNJ38Z^be$*b3@pw;$=gX5H+^Y=@CfRh<2r&IV^2V_knpm#`Tav3e#a z;X++UhtsztDC%m5>28||IXMb0c1E7`Lgd0LNbGM|h%+R<^0I*R7Ig^WY3a+w+_>wT zO}_K&n{sw;)-5+ppfU-#@6U}lpu8y7q8jK*5leY}X1L(jg&>HU^3sZ~?Pi?dHfNaU zHli@3%1(e!v&$%RTKj*AY$Xt2kk}J`W%xmnsi5wMRY!b#6K!fy6oWE9iJ+7zE&RFa zNJ>^A&T8U(b;7U0e1n{ys9lV@7_dvBE)ABI&}E|qO;Hq;=6RuHF>`iD;yyOCMD;Nx z_)7|30-%G-(74m%syTkB@ zYrCEvXDuEe`nIbqygFET|K(&hFDXLUse%n!RRy83q&o?|zS}9Y z=Qgtf&YMm<;i;1?U$}H~2EKy%9%1rDq5X?pz{dFv62;pU*Olr|;hC7z0|l?ZEJDmg z!MF+SD3bsyUd5ms)j%~WOZmY>^~KWatYUFtYPtJHqHljg^F&Bk9U18&Yzufh0bbZ? zsn6mt1UJGT4IOO0cwFNzyVrJ59>7V7#3|fkq+bOTjqh$vdTB`xHQtDykl@hct7vP! zrp7$*o=yW>$Q~%6B5;0`o7W254?Jh(xWqzbZ-q8{h~P>WWXGF8Ps{AUU1^yM4GeyX z`BpQM@D+b-XxMB;k9>b2s^!Pkra4~r&9@uXb8n{gQc4mXdnBX8{>j|E13D9aP&8po zY=cL2y7v@A<@X~A=}N~4Fxzkz29(EJY(7I0R8kR-SYm$e*KbXjCY^%a9?<^dHHhm? zJn;_4l1vK_mI405Yl~^M8d2mMzf6*13fNn1xmJHp4l+qBru*1eo1LPQ;A+D-Ifj|m zf`8vIGFO(pdJCf?w>|m^%jj&{v)0YW`e@F5aT;K>C*vr%g}^-RWRW9^%xW+SQSfR( zSZ%6Ll=y}~zPt?W=Nt&ELJDqNsQta{PFT8<>parvvv2UbYCa@N5zpuwUwgcxSQ=DRtCB=JSC9U#q+fp@@ZF>0NIC5&7>a0uCY)OidTyM7i}J+S zFb|IzwX~ciB*ls;^h8SE>z{>Ws0qjF8MSk@XZo6~dcG_y+YCnT(hSEebfi}i6!|79 z#p0%xpXzP;P_NBd(X2ngX}FgO_jD?W4Sw)Nt>Hwpr{43CPJ59Ftj6i`F&81zXHkD4 z9#eu}j?w}#al0q08^Jd0-buzHJEFvEocI$(b~jr`<)_fs{y1fad4<)u;V$&C9q z9m2zY4qE4 z4FiZ$_a}V=kIhTWax~f)HAM+I4!3`^$rumuhiB7FWTyLjQ%!wES~yJ)D^|$?2QkLo+`}}Y zH2Hc&x(3SJPlRK39di5*wa%$bJWoegO_My|nG-k0=v%p5efScOD>LLnrlo)7GfKro zjOcYAHN<2lOGV5dEPb?GCf)e%UpvetqzR-cnyAz6ZFPj3fYT}RO4oe{f&+BtB(cy= z@j-}VHD3ZzWdR2^+-9?+r;lj`SuOkq;2X>JgYtYOL4hd0)koF|TRX*uf-JtAX{*!t zq#t_c=H3!QlKkSk@Sv;D$2)(eN`|CySU}5=h38}j#wW$t=-&F#p~%KEe1eLcQ~jRx zV>#l2jZO$J*u(oW)2y0Em&bdvxNZ{A76W-8RF=#xK^dN%_ADSt$yeFa>79;C$Bk6o zYB;hyX}2w6-90S^<#aLq^pVjMTev>!EvF$QhfvZ0s;*|GO0bINHClh@5Jd&+wVhj_ z;o11p6Bw;;0P{9yVP_R(y(68ioWOVmC@efkTrWy!@HKp&PfzGpovWgJ${hwbp!i5t zG8JFe{ndntsswxU-Y6by52M;LcZG0U(;+!L?BGQJ;$jOe7KR+Uq5{f`=1~fs3(??MIiIOBeS#HSB zuX5nLCH(F2Ig_lT$rdCL{$wxclhl)f2(E$f@u{Dk+9A=;A?!swl8tpORLCC+4jw2*!C)Hk`&UuZa zm;!YteQF1}rNsnN4{p|@Gp%tN z?YG2_&@N(WL>wU%>RA}eyvin7G z&4G75jm}Q7Gb|EtKvF-V!AUamkrb^CSErDdpoVvHY0mp!+2glb)M%PsPbz-5aW*sv)Aru!#^ zv`Fa|Ax(Urg!oo4E2fVv*$3Co(Vat0&kjoLq)glbN2Wx0=Q7UKW_w?{;MRgEmgf1! zcrC#vah`~y!yh|VFrP6~YDK5p2x&Ibp*!+0+vbpvl@ee)0r03)9fBTiuHK$PN!0u) z3H5)+X5ZauaA$w_T6W3j1mVr1$QkkH>#@%kR$)00OD?xY zOF(8xkpRF?@BXfVf=so8Id2`{&E`F=vMOBgcdiO*bq(GA- z1lNuS&VHGE_j98CjvJgZZ>I@A+N-$6Z7_G-_hHv>eE4(O^SDhTsw`~1sT_DDnbIg( z^q~Q(->VDzFunm=zYP+RWf|gpYM4769h%GI+t7WX5Trx$IUZHPX+}g_p_%sZ!ES#a z^GkJ?&AXG?Ank~86dS@dgtAe5`zo&AZ+M1LB3Skq?s19_j?3eSqvz&6Zt*I3CAJeg zIxy87e%tHO?hrukVVb+{>;GA{kby{yFR9O;-tn50ie6na4G$f<(C{};pb9$s_jkv4q?d* zxOyl}%=HSBIpLX-(EGan4?I|V2Db|Wo6{(1RL#8YPlI|peLYF8AJA2mB+GjQlj;?h z?cG9O(&wxv1y6KZZ#3r^u5IJ1W=!CF7uA`xHu!w?>b^YPa?SlxyM^$reOZ4(4bIn_ zS>xlDH)0`ut~k4=Ofeas!FHnG>c^cRo64bloqmKxy$1c;$Xh8^X@mE-4ip zIP0S9S;Dt_Sf5|x)U;|!IFINq&{493Hr2oeXBJTlHHQTo<^<;~nU5y?rn*0*SqXEe2e`s=+xQF;)Zv~cRr=SQ|7kAkJC!0eQt=Y zV6I<)I<|9FXW8L`S42!hO0Vjgk}OzRqS)yHM>6pfnX)%WSXBodnHGP|5C^`K-kiCY zr;n?i6d=>oPNZ%~6Mv0XH3w5R@pc=>S?%D&L8k3Nrrj|4CPeLh}-l=LKWafBE3|vfb3gr!eUS6;D`Xe#rF6wedbjz|d(Z z;a7=UML4r7BaJYXk}-euSyUt+Ax|-eqW)*`a=fK&;Q@eSyv{fEryep_Y~LLHMRXf- z>Wy(ell@TSf*S|%QT8V|*;o33*xjx5-%aOy%;w`cUM)Gq1IllN2B_ra(xeY{E)6=p z+;=~}owoOd+*~@B!95tUsO zqCkk2DkavZBc|29$_jlZL%~NEaB}s;R@42HSQ)Gw|MI|$- zP{vf;lv#Jt}r?s z*lx1tNMmtJyUnU^O~TAkl|C+|s}JGaBuBO_eU731Q;_f>N$!-VYY#F5u8SOO3%)*i ziuS-8xtzAW-8b#X?h${nfIO}p2Xl!{JooW5rrs3UW~ZkwO_#CMT_HAP&kX46oOWw`n`XH7 z(;tI}+1?f(byZFsr5YZNd8DOy%278q?+@Qnd!py3r90ZT4u5-U>)%`?=A>4|-82;H znwk8oYlob}JxR6ce%T9=_jF$~I2!4jac&6*616t=$X0Mq*1fwBS+w8msqyEI_oS_F zCGL*AuX4=P)vsS&V)*LjO#EWlDO0G32u~P4%Z<5%qokETd-)p(aHM}h8iKk~8GiZG4I{WC< zsPckU@v_#u!)k{GOv|$4{F*y0Hx4MtcU7(xKF*xksoz}E9DK$peVcx_$gAYERrKLC zZOp_;ABbHgLJl&Ia>WaKXYP9(KBihL zP~N&TYHQc)9hseKB@tWSpRat+^uAdCC3^B}^7^$chbnImiLsXt<2LNCEq61yob5c5 zAz&F}lC4^`^!<|F0H;5}41vcbO4OVC_wTGr>4O${D9KNo5qIvo_*Vqem4)W*RapDmFIy3JJ)0!#jn%qt{s>RMS$%00^%Uipq zKIFK%o{}zb_yGkw1=7>5XjJ=6W-w2@NsS6Cz@6T?{#V|zB0G*ZZ==7&TCiDi@_s*D zwDG33&w<^{?|T#i*7udKF#i*)T+d~FD(rJjP~kD2R_~{eHGjS3S6^vU`eVY~wC?=z z>}T5|()}{-4RrEp7BAo1@jR@`<^zAyM)xC9n&bUemtF`x_I&T#UdYr+%E}M$Th3(a zKC@!hT=oe0r*4 zD)R5uAlv+JCVh$W0+Jfn&FrELpQUw0DJmLWni_?}AB4MnxEK)gsi(!Z`CF`cFZupi zTz4*C=G}OmO4+QQ(^{?`e5oNiwG%t{?q+VsSJY;j>S!Gme9bv<#%}m|XsGCQpHc0U z5BuU|D+?^MulYM_dj_PrPG2v2cEMOh=7=Iee6UIDNdV`ShUcnkRe1?(Uc7dXtvKG= zMjs{bbCdX{x31_rZfW=07^|`=;)*sQThYc{on=Fb*L&~zE>&!lB-vFBUwCSYul=R( z#C+MAQlsTSG6(-e&d**iN{P$+M!(pho)f#C#m3ojnbV}H*A#Nzb|s!SpgV&DU$IAnHpK0YrCU{xM556<+8)?}SpPlq#^ze*FW~Xz>De0uL zu6^%3)b=z;M2@LD-#)oUDNJ=>%ENG?2A8kL+|Sj1*S{IB;wB!O7JADgbiDppU-GGX zo)6ydPne&(cO&0LacNk#)9XK%k8Xb2x>t`Uo1<>b`}l?zyJ`k&R(NmuP!TP8)c8Pe z+q9j;`A>-xSJ{M$!?fR<5^_qqhxmslmV941&gpBe99-Z%Rj^&4%6vkS*`&(dyeWZ< zD7@!ldMLT6RZR?3ygY|D9_)^q-kEr?rhz1 zqe1bzT5-67`0%$fal?0U)k#i+VK>vSwM6u{)szYta>wlN&3Ex!^~x&q_UC3fd5`Tv zIa$|T9_ZyWj|3(0wBCd5-zaFf(bFbf#9FEf2*Ud$N0bsC z4BS>a3`)f-L&7Kd@WMJ`KU_biXKI?R4Z zSF~tfIhFZnDbt`q(DBfggo|DA^_~28g{Jp3271wlRi}m&IS89Kt#*xk;rGSu+d(ln zU#8;Nv+89E?Q0J9k1q{$6FtkhW>;<?s3 zm=0;A4ovJ_BLlsBxIC);cG-~P6CWv&p*Kf$8}kqCW85>uX~e{&VPl-84+!~SEB_P&h#th`~F^{inXpDCe z7z+$*tZp37;a0oRLVDM2O}N@1=IWSa1~oun%S@-pz|WexRezO075l(jeQ1K!remv8cYV ztqnYVk{6X|uLQQOPczqAOI`W?iTc-rKU%vBtfPviXGRBdws?FIKga$Hcev8|ZLOgiSm-mnR?xHHYRllJp z_V~Vd;g8)*&%F-H7xGMa>C9YdJ(IE_#e!74>1gKq0(n03OX8Q})oLWT0@NGZpF^~d z*70h-@hL?o#51(S?@NHc_Vo~VolezIzJH-`iC?JjP`l)TqJ3Laf~G&xJn_oxzjj`& zOwZvysU+XbNok6kF8Zc^{+P(By;IlOOA9xi+`Cy$!kj7OY1>cR{xijW7gJgKW$~*1 zLmf~0_Zj5})a@<0$xp{~IR>oS)o}Uue#GRe-qrCB!3~k$AQV-imS?=eI9cCAocDF@9HYc@QI#lP1=2q7i7<0)VAEe zi@ChI{I@rU;p1^*vYtO5?(`?r>oC1d zZJG!iu;~tK>*m&b9WOuC55H=ueZQ%tHNN$?+mokK36t*kCREhB-DFZvS@B)nBNudy zxBC4t)#Z^ZHrVc}T7Fgfv*(ZMJ07jJIFZMv=rutNw!_3{A$a13hYv;VeeQf{7xdfv zLQZ@%m#$lLBx$u)QT9|c(N84$T6pJ=e5O^_1;;I=zNQ5eyab+&Vr5Ti8=}4|fA0+b zB(eJH1~wJk-OS0?+J8Lwp#Yvckqw5~laJa|vez3OS9fn;v!ar}-;ZNckO=umK#UE-W8_ae>{Qb^n`;K zbGz^3Pr@OsZ!WjVyUC_VKNhEv0X=DhccXeQT}>c?BzyE*as35Zv(Wl~Jq{w~3YgK4-rt<_Eqe{>< z?pe!4$%+*5cQ;pkcejsuP{YtG6ZIX64Aqq%y8WZx<=U1ycY0jl@pByt%03zah+%Ul zf7P=~$2OH&Cl|gn_qY}t@=T@H_6mPrc4D9YR%#bh&wZ<7NL%x!?0YFmC*?RLb>IKt zDZLVZQTt>>;G1e64o;Dn$`g5yewGGNWK8wqJhw+bY_-S@QMqWw ze}Zz$X~3W9NNycHf%hnDYtwicWm%S9I90Y}b3EsnBPW6(r9n5-8!NXy+WX<%vGJ(5 zJ7S%6@$OfWijO;X_nnj%a2A%AlCk7ExEwA}v|9Tl#Ba~%*!p#`mxx(C=N{GO2Y3)= zGum?bH#|#}+n=A;`O8$@GMZfN4p`wWIwuyV@;nB3!aGMj~b5`+!9Ilm;>;Ro!mv@meAWC?Y$WktE=lQ#W}QWG@Xs^8}P4ZNC&A7XHlQVKl3JA zMY?RrZTtwHw>j@ODj<>aqj%!qJ=_w$%F~p1p%t&POC1{P-7JzEZj@!b;`R~OFW#7X zOfn}Z%wvh-7sSArnf>7Y2VTeJr@62C$GdSB<}4X|(-tLpqWtQx<4d>xscQD6MoTT6C%P(nD<{pqldX8V`D13J;W zjwM)lzirItHC0ZF{Am~Fdfi#b!{X#9=dUkcoWd>njv@TV>B~xdb~&2=uOQXxu57S{PnI?Zw$QR|JA5mQR?9S zb&@@h8jteD9jpEN3~j;le{YV;J=E}_7B~z0$!!p47)~^%c?eeDR+b+39tk(EOS5oE zh~;m_P0gg!c8z?~eb|xAQ`jTDeL(-pzNeu!4{~;jGL3(1cKla6W|yBGuC5mmoEs*giy65{f`9Oer8@#<#>4N-Rsv4 z#Ab~Y)%z!HR}|&vuM=4L#A}m$7GHx~SYXs4ZR6AFJ047IY3(X)8A;x2BI9|zC~h)R zW`ustF@jz!r!qSFt@CLTS>t}D(P`0M-WH|2Dlaea0Lg({Uo?NcIvKvfPULwkHRoh;v}pb{lgh9?$bAcE^`-4~YD0rM zn~fj5dD~en!X1;l^TYFWPT%-YrJ;}t_z8!I0Nq33>zb9fFZXVeh+~MoH$O%wOBnoI zpm+O+F#Dw|)7rYpFOnn2{kCt*6uVr#VkjqgN!ZmKb(L>R_t%NUn$Z+4Fh}pmC!N+*8CG zQ9l}z_x!7xDbLAmgv7@r*UWM!&d?X(GfG>lZXSL#$}R5S8SwDVAGec{kxxV(UyiCY zZfII>*L-Z*mWMSf6Ks<28Y_y4GEZfjH?294c}XwDbxmTq>>ldM2&sTe18zeVd?7F3 z19^iH^1}ApZTy`aqe|47iC$59U#fOL46>b4G%)I}#>Jl3>4>h_&(~y})TF7jlKyvl zE$5B8E|b)Na0~TaLOHQBAIoLrXx-Bp=G~9OR>@~=bb4yI<=~s&PgAYGd^t*F!bm`E znaiP&#AO2Y8pP`BoY$7MJr}Rn9u2eC?;Fax+Wc{XYdUHGQB*7LyN zNDC$7q$JnwSMl5OLgAg{~nAt@7~=Q>^Y)0GxTm3Z=qqe zf!mRdd$;nxN_{P?|4#lC^hI`HZ>W)3B3)kIyv#*1O8L3Q(am;>9~fTIy188YSBgoL z4htVCS#ohuUY@yBZ@20TnNA&b9ly6{k6UnQMY4UEe zw6`|}Pj?$`F+?Bl7DxU*VoydcJZ9Gr_0#g#^7lHZ6`&Qc+t1xyDuWm zt7N~afpi?jsUyDz**_q8;kcEhKZn>!3dn<-0Nk<^cO9v?g;Ob26vioTMuux}8l}Fj zI3G6T<4c@sDc&8|ER7_NfM>t?!f_c$CI7G9sv<+g*1^EWvCum)&>dV zU;+tw9F7w$J+=a(tFyxdBxwYg*S{I65d~uk1O;mzU0nrtA2(l@Jv=ahjC2mMisd&V$P)a-t9bf|tWEKYM979bCWVs$O8-w`f7>rt>1~xV-BHjiWa?CwJ zk2tkKQpoBKNEkWM21&BhU?jT@az!doM5Y}@$Ox?+az@NM0g}@WNiCxhF$zf(I&%9F zyC@>m3CSSb9grf@j8f}#KvL{f0%F$z^qI}BDUty&#OpI8f=U-aT00*2uDMpy|kGfc1Ak zLT7lgmLc^wanPKl&7UDzB&!=(%H0J?BF;U4meK`TA(S3~rE~%7X$0g>7w|__50I$R z4M~Ymv9>Zu3nm}Y4JjeEy>o^L^3!>=wt2Y)?Dkh6QAx<#Zs5nyy+F(1&yXM+0ZD5E z1_bm#Rv;u`WCEBYNF*-cp^=c09>^JukaO*jJUfYkl(j?BNK!Afg^h;v^g^oe$ zC>@5h=%m>wR8TbyaQD_E5?3jZNVDSpAtV%;U5M_Sp zM#p9y_m7%_B69}M>!1PzyqF1{!aPDlk=fArhtN@EksJn!(2$xDNDFcK4YUf3LNccG z1!733@i1c{f*Ma=D29X@PhMya2{oBaNBl>@&NUsM6U517vE zfW{rR6N@sn-dG;PML zX9)A_vp^9;6OBOPd}J*eK!XsxfrNhs0{_NkKCBiIpb!S&y4x-LY6yf~~?LqSYLgElgpY&$g zQmjncoJ<~eyZ{pU7g9q4|3X4%h46039X7lao~TLGgppw!UPPG4Vh=Jr2BwU%o{hlE z@&Fa6ZX%tI9QX?@<3>Nv#fl<3UUYUC4Nn4Lb{NbSp7lMVz>b$V+kuD9X5*LRP<3zE z@FD;ZMt(qezB&H@B|?Z88@?UQ(X(CvNE$m#L}YPz3*-?>_?I0o!w!=W1c$dm_TliW z*kKqEhw!S)6yW(B3X|p>0|Q^qh6xB@j-kCwTYo4>*ics`B7 zq`7E?Nps5#1B3F|@N)C63TMYFYtCj<3_CoRs^Ixxfah~C43p7ZzE*WM-~QtKL0%|N4qmYmd zoOn7!2I&ro;KW-%WFmozyqoDLQi17gQ2Re<2JVk$?G3dxLZahOAMzh^Q zsW2!up#5><##5z;;EM(_2xgo@g^{9v<7BXim~k?lfj~U-{Agarjssh5cz|*;g;hD) z`DM;C6X>ktpwuH{|Hjb*gAq<7!-x^@oN@vQtTSeuKxH7wym-0<%%FpXTRci)P^d^Z zFEEWjW*wvhHllSWLzMXeBMHsC7)A;S zoN>@Wn8G>;1J0-XsMP;41{jwK07f#6br7sD;wAtX(GCHlkqGL45juu$PRtkqR9#3A z2&K?j<^d`VSX6Y7iuM$XIYAbpA(?_eDuG2Kkxm2)Du}Q0WUzz^kwKS`SZoA?1Pf-A z{wI-Pv`@zfB(u~T5}8cHx*D`fXf4L@QW#jTf>Q;J)o41*V6reX2&~3{jfOR`ZFPt%vz@TC$LL`EuMN|-3L`Wc$Kt4psoOmTBV4`7@ z6N+JH53t!28%7~ZE&+55Z07)s01m|%3ouak(8Tb6%?=0CpxsR?mQo4Q!ACR=|wmWfIX%jRA=y zmK;GO!Yq3qV4#D<@`A9(Orm0f6krUrB+vT)UvdIr3!@G4;w7QbSq-Glo~9Pl zQR(P;XE8=w;OaR~1IK_x{*R71+vE~q3JJTl07hLvI7bJX8tm=>eG7>D{{+s_QK%I3 zP`1bz3TVc#bW|qjGgv?h0lni`#7rm9uw@vX2sUjKLDHsSUCn?&|Fl>hX#YX#02u23 zf9?k$1*@0@ZlcH-V*p0Ot|ur03~VfbhM9psz3^H%V{jcr$5u3O z8AL=6OpE9!3<7%Dg~3SJtVp7PCIib$BQXgq7Sdsug_#ah(aWKQN?-!$(6H&405&(q z)iBtJ|D*Y&p(njr|NnD8IGxTOP!}ly)exIz0TC73$N-FvjSq0j1!)gsH0UvC3zrl1 zKOlrzW(O|Au( zqk#m%g3(}1LIS*u`8I7~V+yJvc8y7NGJ5;8cuD9qY>fc70Ss1N1_9eMg4+VnV=t6v zhq@nZP!_8hphhkvoTa0%x*8OTMFMB(Ks$}}E8u0B;6=LDzPD` z`n*`;+1aKI)oyfrv?P!tQBZPfi06mT@4p$}m|nIC=0vjc%}=`jLMO;-azZzgAF5=n z2HL-zs{XEAa@c&Yd3$=>G!VCsarmI$i9t2Cjvl~rCr`;&aj#e9ZEzZs9dT@*HB9=I68WJRH1NqBz!{-ng;Dv0fMXS1)1)m4&L-BK9P z&o1voiaDJR*WN*TJ_j!WIvnVyg&l(DneYeMdeqqeaVEGQ!dSgxGM_XJ>llB~2M)!s z?t000>2CHaCQPf>YU%W2qz)Z)O{{i6B@VAbI_N+~{~^i8*#zsfHvw6iUzHP_w}TU4 z5oWD=wKlz?IZ4xIjtFO1LqX{ z`#0g&uV5G+IC*-0!acL1z>iXYd7#k&Yhy1{%db~WdsO#BEf_9DSjv42_1MIG0(gS&n?vrv&jQLx?rQ|ubDftd;4gLbjtsF!|6kRV=t_tZD1xgf48&)oR6CI%HQF+;M85h?YB#h(~Mdb32%0| zd>XDtho#XolNVd>WiL_eR6>00kh}6|o9Qnjzb zOf}2gprcfYPH?)|vaC}`ll)16lq~f=NrNj=Ehy_LtN^j&v5gr5X&Ca{Cg=wDxj^Qs z>!6yWXcFu;^pR>*tO_8@T?tF_T$}jaZ1qrf z!%#yA)T6&mIMfiaW#^M1e(3e`Di|;Il)$FyvRpV>B?kQUqge$OK%m?^c_V9RAp>7% zSe2b1@pyRi$CZBVW<0HCECxe29lWn|zBp|61n<#db2^n&W>?UAQd;O4(V~TEP`l90 zY3@l3^wQX5OQG?3LofwFgdk1ly*gXS=P^Ox6ju3^OGGYm>9Tt-gHZF!IoLG4P)_j0 zz7$UTHwb78bnyc70|G*{`ZU9{LpgsS*UEo|Nh&nVZvO4676y>$U}UH!#C9SvRAA0b zki3({;huncaX^q^*3gE1gB!$ZxgK1Y5@9yAJEt}V^VzWoHMh}U(|JEq*)c9 z0|ooLbcPbUb_)+Z?j^cPPcrQVi!^8>8w@0EldeX& zb{MtX(Uh(%DV4QequVp+5pNAXvsL2771 z2zIwToDGLGBpYZe@myI$Q8_de8tRM3$?C*edjYI-wwB=N%zVFU zdmoGdWZxuwf4V}lj!w-sY75QK{YBZ5<_YR>!a%lXr&}30U8iMZY@zg(5=;z|vIji? z8H!m-q$-DSZ<|JAyCbOG@PI~b*JbVC-oi9I`+R8L(wH4&SpyYQS4AbH(^Pg%=o?>a z^q+ZniRN`Nr_>m${#Lf{%4(=e1_qymWNIj!o~&CkkQ9vHr7cbMye43-sYlcOQXnZX z2oJGHa3VxpIZjzC0=6bCxcB!5_zrIYbC|_$j&HV}2<>oB{JJOdDqFj<);*h2xQy{f zzo)%?v!3)HQ#{q2rnzz7##ag0M34C%lS z66REMkfstvC}p>(?%74;HEjaVoCdVsP6&%aqKMg7*Wmjf4Jl>JtVcJPsn`}(z!oE{ zTsQYvEGzn2M>G_PAg2|l2{Ju3o$X^mMpR*1R1$7XdfdPd4*@9Xlq!N6Uy?}pihU;S zC$j)bneZ(vq9|<=C-k@xC-Qg~t|D+y+AN7MqgE1=33tUR&lcM{*+V<3j9jvn6)1qL z>y`SE-D#(DAf3xh6zjx`7>S7%*jBNJvr#%|lbmec^ZwJMM!kAHng+?Jnmp$xY>@!~ z0wj6=cJ7mks*z?U7artYsRui|u#lsN)uyK{0rjm^1}4$RiLF4Muo%vBnwuh8mAwG- zctU|S1f&1bg4Hs19#0t6b3!r~q5-9cAR+GP#R8EtdrvFee-7&IL1E|y7Qqy8Jf=^T7v^uX_&dg4M>PqhE3q;g4m!(W~e#H@jH)L0XPf;E@Vx&@M`(8<-gKr%H&+;Ht&fII{y_TGYret4UlK*I>ypUy zd>GJbwNk&|^nh(N=|j*_ikBqrG+8=ZD)1bts_~VUXGsFKtuW{p^8MSFj4)1UNp8R6 zH@S|r-}dXi1i5`+z!me@p1%sp37cGngMX0l-l6-crHb!0W{*xM1V9wL6 z%cknccO6U}^C87C6lIg_pB&VTiOan0OCG?IxJHQH_yq{r$}h6@&Ky4W-d%q}4>#-M z_O^JX<9cpPWAGEKGuNXLwyCkfq7ohz$K;GkL11o5nqB;M(D-T=n30|d?QhP= zJWyByMwSU0o26+oKm8?ULzvvY-t)w{C_rAgc&qpZ*oX?9v&1feD9NQo)A_R)0E!F8 z!*!I(z_cO7k(95(HP!HWeP3HUYMr!`Zi>DHb5F@-Ptaxjj5@nBrDh}dTm7+FiKZoG z(zgCKrb8-cT5#@%6=lkOJ-lgEFVyiPtc=RD+u1Y*=dNDg(8M)-Z{nK~^!FuU+P&f# zmm(djs>gVZmoW|5 z*E{h7vw>yh%-HP+fqB#e)+#hjTrYwowdcn3fQcP)_&$UmYk?z0P%e6j@430BMHF0} zb<^7%L01wclS(n@oKeojp;bJXO8Q(Ir%1J3ybtEjLEQYZ* z`Tn>woLe{vfHuxnDssPZ$oN4xdpT3Q-r;?v_&~EzL5`N(326j>!KOOpMiNjtB6kcL(D08uF&Vi5OOi z^%jXaV&f8iT*bYnF|d>RfkRAEPM*F7-Uy-FcD-%Kz;4u3( z&b8KzeUCQf@>=3rST#F-h7cMsw}2=l#HY#Wvz65x1`cyABqDPgNfj5W9(JvJ0S&V> zgkqSD%w3-!Q_=Xioc5dEl-fm?V7j}ejSA;O;+XcYLH-N4^G9o$icejp+N9C%cV|DZ zkmt4C_+-X@2c9xG*8(exfgi|U%GyqmNP6 zwEKT_Z;fp>7Em?!@E`G(Tfe0E0sH6P)He%Pl!n}o>7{+i+JF6=I^QNpWf=>jus@okM>8nchii7T;sFlhVO1ssJfEsHfmV5&XrQdILi9;G+c1%pz-yf#v z<}|tFi(9mV^%BxHu0_3J#PRQ)1Fz&QjDAIXW1GG~x>$LB?jc;E2bZ7`c-tB15ks;5 z9@tEkI?KsQ8hn-$(;f4u0_m+N?WkMlOXR0)+N$Arg{SjWzW!Jn(^2=dJ?ob#PE$?7!#q|NaRPI z^P`CMegig#{d8UoRT3jWk_!6B-lF?4Xt5okb2^;4p zNmZ@|;D9bo$U#w3NFW9TnEE(rAUc2r1i&T5W@Tpmr-f%yF?Vrrb2c@1A!TJ|2GP3; zfkvcIAy}DNK)y+|Ajoh3h3EBXF_<|%M|^rl%FhqaBu=XPPlKjU3*t9Hg!#W*LH|?t zZx{bV7p2elx$y9Rt`G+Qu#f>Q$Xgl-`oAag`J};m|901EK!?u!zh}5NpaXsAp?wP2 z4Cz4p`u~vQC-V9asx+hpeK+_w{P+_U{|8YU{aeTMKUd=v3{agBE@<~Zm0ltY(B&s1 zHT*Y%z?crC{~x4nObg2R4?;7+0F@f!ftC&bt@Do^7~_JljQ)$!1DHYn-!wo?smP$E zZ&aWh7DUi11p;W(gbkdPqaM?A3l*G|{l9!>{pZ^M>oY6cr_aKmaU;ZfPuFV_4Ay^V z`2RKRbL>C!-;L4!P1BY{i^0nCzaG`!qI;P%9Q^k zjZ^sk)&AXPZ3-Uxzs~p{+xb_zNWlY@B>m^kjHNI@45^=;Xp8`g{3Zv=PL-hgzm3R6 z%F4?9Im7>dQ&K{)d}>%hO47t2r8H;IXbMvOR9XN6fGrW144akhKcoMj&Sc~Kbc`L; z@e>xDjU#n+7m@lZp=D z`e!Ew`~U1JHm=mW3c&w%>od<<`I-NpK78gK{^i;Jhd-bBib}xe0_^|0aP(P7Evf*Z zeSR3FQdRv^{m;|>ESP>4Qb{WROO^MJ=>0eO^N*zeH^Hw4(4{U_0#N@=rumOxR{a-A zss`}=OV0dvM6LnwecItff|06U1EBqHm{|kB1ON2$vv*SwYd_6_O{0WhC1p+gLi%|S zm=LTS?9JA7fDmwS4vy5T1^^K_2WKj3Bj5;}gRA+a5kLh1=iqLpXa)p*0-k@B&D6^d zfPd;mBLD%woQlx~U_2$jRN+woZu8F(00%f0=YKx|@VacwtcJQlJ znGSL!E|aa;Jhg$W+3~fNWJ>FcLlLnNISB-$*5#{Flr8}r{^1yC&+e4^=q zB>z}p7@RzoEtD}ZF9@40!}&wwQ2?#Qe(Z4pR(x(S00}sq3q@YcZdg=(49hg& zGJzra zpY9o(x$ocX8SGgf>$&XTnwmud+YyZf3qlD6Ub(P4GdH_9|MXyQeh#AOCovXWrMEDp zH?grpYH)H6ek&AIc7e&8k=p!&_s**)OQ5SsF!e!>;X+^v60*YO1Fo@@tfsB;K@^F9 z)IFj0zEiM4@dB1{@$h(-c>u!RVAGQ$(c5v5wCCHzJv z7Uu;G{`CV7XeY@jSr|uB{4pha`D^^6d*y>-?BnF|V>5C9m|a=%KCk*dy!9dFU}R_i z_dRuRn4gc&_cS!?Y&dlJ)lk)K3y7_=yg2swar`q2QIJ!7WN7~Qf-{3JGP4~JgEf&I zJ@L*a{vi+&x23VqDGa46btA+`2u6fKvHLOOdzzK-cerTh(MbbX=1)R**G)5M8*Ll& zu`IA3=fdR(bYyl6d*gma8Gybtd)87h&0EW@M>5K5u628M1o*_?K&LJ9_Pje4oZ5mx z=L?B{h!BE7Cje2Y{Y7p`2B3^kUkIF-0k~h@Md-nxOM$3-{v!7zw`i*84g;gGMoNz` zED*R!?;<41NgpB=V9?3HX(_qJZnPySxu9;eIVp1>v?PhtecXGYb3br8Y~#>j;69(N zuJPIGar2$T*OK`i#_uO<)0-zXA<^WA`HcwfBh#aD>!{Er%B{mL3RN*sY%z{Fvvn;U z@R5BjcJB}tmxcWiNb*Ym0VO2U^o;YmW%`El+5(RIj`g%VYh3e2{SbCGTz|`SCspeH zQ6dDqUiG!jKkGhZ^JU-IHoPoU83y*Ep!@=6JS9wwP5>Si1LH)@9i1EBQu|?W4nAv) zj33tPVXbT3TT=WFz}`3$f%o7Kwp+>H$jBrpeYs1s!;-H!A5YI<0rtWa%gGYD6gk3C zBmrkA9HO38t}q}Umpz!{QZ?5cI%J~XiokFsX|;v)%_c%W1j?9O^6HBSlU$odY8*3O2+P|LuCCk15{w$Vnn(5mzaVIDMLEf z^fZy{JGx{0uu*shNT+dz@yh*VSIRx^u=GW{F=e-+*6>J>JB=GXmLAEfV3H382P% zDi5J70_v2$z50C7H>bXZK^tSuij{B;F{EcA$sYDP18U8~jRuSx0$EXtVc?Xo4vhu9 z@j%oy{cq!=d4?e_S8gVd%mE+(((0Kh=&QpN8m)&Pz{*?E^mggljCGt8{t zdfdJl+0`4jkX^#XAA$$woXux&9w6E(mjJ84;uN3)r_okPvS(vc9w_iD>f1@RtAlpH2H(1>vK|!LGE8WC#Nuf?Enkp_0WG>+l9mh zGNx=(C`{g(JQ@)H)z5g^$KzkQZoD)!3&-Wob^KP9Zy7I38KS|%iv#s2JyzdsY0Q&N z9oKTLG({M!Q`_s-8xchTTYe$L0!4#?-i_ps#jMJewJY*l@o-nd+1X~G>G`8hg<&|v z8aZjK8*AE`0jB>C5f?Bpf0}=mX(*j$@@Tyxz=J&nG7_iAXUMkLou6MaE&E=RWj_Ol zbD1$*_#L~U3`@WsRVu~yIjHn(5E4%2g&QvN3Nmyza9a4g3{D8^n*{bac!+EC@~RuC zHKt+GV!}9Vf^NrG66#JAo0dhya zuG8(HB0&Ca*j2DR5J~wQY4rK|A9HXJ_M3T^2 z!tl`=xZ@HbPZ`_vjzTmT-UD`SI`AhZ#lW48kU&zb%E%`B{v@}-60w{zWYutV*{RX$ zRei8e8YYwC?=`S1OO;&iEf2?cC82VIp?|Tfa0AWf(&$M~Pn;!tzyQ;8GOG?5Z$sie zB9!%r^Uti}2Tar9B0+zgam^Q5nfZjrL)>vSvvzB7>bK1{>ONmZvgLM!#?{1k!C!_m zw|=RygG=4U!a{|32_6(rN(C6zeKPIzJmlnFzmT0)nA(8E3J%`qf9qfhHRO2}sPaaj zihKE$zRupQ`0_myN}}aZNnHgM5*I;Hu1LF_;EApU^eja&NLRI_$NW4eaI@r4!RdWE zrg4zpGfT8`H6yaiJdKHfk~dj@va*y~!acmG&q|<2=Nj7ZW>dMmX0T-FRlmsI#Y!9m zTShZ2Ywo;St#0W+V|{pd+#%Fn(#I%=OZ`EMZzqTfA-* zw?l)oESQL#&TIX9UgkFfTYXC%3XkP6S7M)repZ76x&`v!{;@yQzo#@SUv<|A6M0(g zp7Y*jl+L&>76q-aSfq*o-)s(8c zc}~zYxZ3Dcl=Gr$-|-_={{oBcDt^r*qw%7CnLxnq*Bj z92B6The&$cOTwe=*dtPpIAYgw@dFczc=j9?Xl1|!M=VH_PY0WMvw5nRi)D~q-5OjL z!DNMyuD!Tg%&FnKD*1aam^2VlHmIeoAoLXf3oIzLPu-Pf-vsK$${WR0zpeRR3Vhj7 z1ufhn+aB*2vC>Se^Tt5FL?wfGok7T61^WNyS0}pcf!ViAXcKhIB2Vx(y{wtN-ToKU1 zHFu@$>)`JQs!mX-1`M;PgI(~Bla&xmKCgbgdgX47IOR2(#Djd(E`778Q8MWr6Y!PE2wdtP@lO_!jeAY{%EYmy_)Wj-6bEZDZl8zE4_M1ZbWoDihi#rp2Y$aR zAwr(6C9K*}3zGK+>uker+u64m`uK zpWxiP&9qOS5!R9e(N!Lm#8rsvGj2$5gf&KOD8%I9JGan=Ox>+)8nsD>o#;nOhwc2m z;wY|M%r<4>XC5t3KWxgRziO+hv(?$oN6!kj*SK>A825F`Zi9?)K7Zc3^q&J9UEUEchZA zi}y?NK##71#-G9T8U3GCcr#g&K0!E)$d8?Y`{&=M#u9cA=bhzuehB#ThN+h);~tlD zdQUsxEw8*h(p8RcdnsI^)&a@$itB6EIYVce^A+nV-|ksjBE*oTux;Dk^tQ~eWvtz1 zzeyz%3P+zA)^ZAsOnDSrPj?|x@u2WAJX2v*i3FR}B6CWeUaf*k_~2}A_TZBFeP+F$ z-rq2`6({6lPq-e=(90<;($Gos+)k%X zJmho*qUMN}B-z(GV_=ARtPE6=c64Vr)Cap-ew%oig_E@YI5 z;tDv7r4;b@7qE}>mQ@b3m+a< zF!2}?H7l0uqtJt0ln+@wRdYYDyaP8_WH{Iw6M%_PyVgw`ODjY6Vz(~qupQ&~lbmZ~ zaLZNqi8LfkEZJv05ynRm+dxa}V|KKzhd{F80j#uFkxxwp&e$}ZwcqmU+y-9CoGu@ zHE@TP5Xk3DZnqm}#Gt?xVSYiSC4UpZtFvD2m7KieB7DzZ^ZsQ1YshYbDXJY<+ge4d zVl=U;y(={yB;#A|)|xwM3Zh|lev2k&-kSv*=DR6CEpUKL*IP8FYC5EeCR8lxP~%>; z65UgKZ&223ZJ)S<3hUAEWV*;}$2dah@o6;y$mn9g6$%=(IKU+lSBhsvpIjFF!pmc` zFh!#fEfiIXjJ9iv68#;+Ziu&_HL`P)Urnt#tG+phzrv-Bd z=G{y|nO`ugIm2&L9=|{Fd0@shAe2K&DH(FDZD6UbhYYtknEW<$%s>;LV2F?e@bu0- zS$0_180;#TCadi7<@YxSt&BQLk&0Fvh7kf~$MDOuhs>~-f(8DC7rIfDp4Gc-IpWoM z1L23zvc@ypRmxj<7eF|gRwP%l;o?SuR39f7GLy{N+rl56yhjQ&xhlJhJ7F;A@AvPu z!9e=Nmy$8sVJ3sx#_~VS_AktCBni*2QYY2iTs~4g0zXWzsUO88-yg_x7#gb5imB?} za@#;gt*;G+Y)5bdxl0%b!gDSoA{dm(IYyh=8g=P?=A5*dP??)Rzd>A&qal9w5zW3zaS=aCx1l=5W{ zh)#ZWX}$o?ezXZLi~kjXF`)D%x0GR(9l9TQQmvkA&>Kk5{uvOYK}84iolF<(M;*}4 zIg<8)nI_2%;~mZ^I|8#|si~2_wFnMDEb?3bSJ`d973zuzxXU-l)vcvw-#>kTMa^h5 z_rO+hT7*C*iE?OMe?JIFecgwpuYcCBwc!~XDwAsX4h!?0uU{Dr43_?&3(5uzNMAN` zA@ssSG5L&drgc?p4sQMqBI+#VFn9r`m`Bn_&e=zwy88Iea(lHyJ(zf_XybS5HV`sf zhWJn@g8$u#&+VYPxr|siJA;GSZB97@C2#Jwd7$u>pY*~BhCu^x>6Jwk&`P_MB4!cf z=mY7U8!go{YiQpr7~3OrW~{#BN%^}|Qi{*2UiSno5_%NZZLZuy^5?%vb_4+}Sk_bp zH^;bDdX^>8h={^Hf`0A<=kQ&GDUce<9SMZ1&u?cppOJ8-$6ji)k8agZomz>eo-UZ%r=s5JwIcPw`S^r0{FhlW~7c?D23QA`fB_CW*9a2QZjUr;^W6%&duu_>j9Z4Vlg?6i?yMb>9s zCCN8cVsldDF15Z|mCPgO8rowjGAue2ev&bS!}qtjaTh%TUHBEZm2InhrlOF^=9 z_YWxlsQIdTA;K^e)Op9v8xT|AAbb8ToU`DIut;pg-;E$Fo#Ol)@?T9rm0boE-m7oy zEGg!zZhF?DB77B{9iDFWljW1s!1HE}>V!CDnjT^YKDU)-iu{MBqtur=E8lG4%l4)- zy^Y8;XM0MzCz&HJ1J`^3-7rSTTR+3?q2S}2)^P-zM>Vgww1$j}pV*qIZe%E0hpl4t z1rWGSn3p~~S-&>qJ?>e7M*4!JZv1CI$$tlmbsi?M7us_YJ0sINeQ&TgD^b^y51jQ_ z^C6M7F)Y*457(@D@?;9C4t;AD=2(rOftC4!7dTcTeuQV8BUIQ?NWb<6eq>KNi+(1? zgq|jt&Nv2c#c94>zLwjKQCA$MdM6@F)XJF0Kqw+v0`qnr=AhqPSVxjWS$FF(N9=G;5@>uq}t@n>gTFsk=pJt5JGr95YSoI0Bsak)6T5v|UM0fRdGZkrnxZ*8uPX7`=Z|zw<}TX4O0n~;1NQASxe{0~iV>vsdkx+n;vT4pGHm>T;26|%-)4#5aaoJ2f zy7CW$^IJO{TxOmUq}=5(w zRMM@V%t0@8B@m&-y3whlT(+kT8bL*6jz3pb6 zNa$XRq!u8Y%=Bk3SA`37)X;061EaH}7o?jy0j)Z#s11N7{bLmacwIA=xvpM+11h8t z_Zsw^O~o%8M2oa=8M`h`jnd$R5}jvX=Xw-qJf`!X)@+q%#sb)SQ6Nupkn&!WNURj_ z(}1KHD8gEgPlUU(x*%2uVgyA%Oc6oS<`-KMo$k}c)w>lUpVpmW_f&Ft z*+Ep&GxxvN1YvGKF?n&VtQhY&hgB9lsi&2~_y#CfmT@f^L zfDH2f!C*aP7rOCed>bY>TEwho?1{-;bJLx6eCym`Z$^Dhd4qr?e(z`-R5FrRGLS4l zw_+r)Q5G1)dF0IHk&CU6Wo+3V>cbSQ0ca}6&+=eppdHrqGToq`Jv=@-!&q=`^^*Dh z9kP#Itd?<*O?n>Un;G@90mePW`psa6p!)5V`C~reaS(sAz-DO{)4pu&vph25s$`R@ z@!0zAPt=0<2cJOJ?hxcO7p2U|dtkld79E;m6Be=fes=dLKN2)J`ZE&IPl$JgZzO0~RQW$XQa5+99RTwg^nI^K z9*0zx^?tITEE2Q!jaf)y+)ptHC7ca97FAi`O6#fTT>fA|Z9fbp8{3jUP4unwEG0@9 zhABGf-qve4uyoJZVpJknq42vJ(nY>LvJqd%|IQk(%)I;4jRl*sv`=B&YxkQ39Km6e z0zV{ZK#gZBJX-W-8~Le%zY92&{VUC|r>2W5zSO#Kp!hhuJi~HOPm&x#li2v{xk)7i zF|)hkz-?o`yE+QnG39q?t|LvsIrUPPOKM416f&!J-K1d?tHpuyhIz{hoi5a2JXC-r z4$i64dyJAb3c?6uJ_Yukc)*TBne_ZdXu99<_^s)ArjKizV=^nXBmkHIvIS7hYOX=7 zl%sl~Pepzq&fw_OT&X$DZE}Ciyf4e9AhfE0KiSFa5rtlO8mHd0&C5Q$!5d0MkviI* z)X*IUf-O?U8;M^V|H^NJf(i`m!YVJZxu_G)6ZW;YbdH)$O6?ul5Qg8ylS^-=A;X@H zoh0*oyBk|SoBkb7-wzZe;;gYY{6kq>{{5b}`>&d_cle0DnSK9GqK3NVFPO9p=BpCv z^{6%u^8@}RuNZ{%Z|s{LK7rQ?ay-7pJ|4RA<`MMvPw&a+?VFmAY@UCjL-SY2V39gn zYn}|Wog5E5Zg_c4=aT18&+~r-ommzZQoGO$+H8Zo?ZKsMzi2=X_A`OPgitGkKjOM@uJ( zTdOs>U~)X?IstF!KsA8XkEjb-%iGaydHfk)R&zFHAo9*lj5?sBP9~B7THa{~~_hrg647 zNz|jv#Qq=QUyt!vMxSpxQ^dL6_UVVS*TwQMp+D|;+BedHWNMO_d|hRvRYIb4nuNj) zncF0k$rP!?lg{6a?#$0j6{9gZBfRN*j$z>{rEj312wkQ{qr{H{W2{}D#x_rEd=Uz~ z2c|D=Y3%pJ*^HUx{lSgM&3(@hZDC#_y=^+^_j}6S(#8Gm)7OpYf?XmH zi(bEz<5_+KYI*>I^MZ)SHg982@mafc$=l6Z;>1Lb{iq2m`Mr;39s{NAV<epKePrzw zj3v^YSZBtiyI^m-7G@8E^gK)(cV`+g=7$}iiv7sp+s^n?oH`?gcfAYOvIO~EE7(9-zbSnM5t6LP0OFv`;@4mb+Fa}(U^BW+xuUC zp)Vo$WM<}iibJZjFz<28$cu1>6lXhEYd9w9{fr&=Bqy?!3SnK2q90R(=%bUBa$@%e z3f#iuiLDJ&>xYBlrbqMzBj;k31=C=EOobgQ+E-zzR8c1VSp+ za0w|&8SUsH<=N`7|566LWA0+g!a~kpJ3t&m{>>~YH8;%P0DY=7XE~iJHgRs%>j@^Z zsY%;U;7TCC7ye*qtTAg~kU*#>wMO`5gK5CUv6aNIVxWiXxz`0b&prM^MdCgWm|ROG z3R0w|5a+%aH9M`b<)Rq#P48AIY6;+kM%BPR3yEWi2&Ll-X}1NkO|7D(oIlmLBT_m zrnje1N+(~_A0WZ=p~pjbCoO6L+8QEdf^6qR157*sPE377Bn9`0PLGWFtt0IHXHskP zEd_=qsF!LQUy^ZoOPNA4O+BR5O%0ycM{Qr0JDbn5YpZw9uKR=0klZS?U4lIGTM}u4 zC_HPe4G4R?qP*q_-Dnv&NWOVXOgd3gHPS)ysajOGE3t$C;9qQ-57dl-{y+2mn{xTX zYd=nH$0&ZyM3j_a?~m&vq46d>{(3G~!g;Hs_JXienbU|v7HWnCEqAHLqK&e2(Xyi$ zj`Hq%J&*WvaYCVWrb=0BdPswUOW$NxEK=#Ib}J$jUzM$L(L`=Hzjpvo1& zV4^wE-SN{BO!9SF{3UQmWLzjd%b|DkH9a40K)vQV4|EW77WU%;1f)~9E9 z+W}l7+R<**nba-kOr52e-hm|rX?gx3lw5pll&)gpgw>-u?|6wiLg1lnuKVSV6%I)% z(HLf$qgOGWgno`;5b?1-5ES_OpcpZ-?G&bqq-QjYpnIuvVT(d(=z!L~d&d%0QV0@(M^>2UyP!y{V{8*n0%Rs1XBKsu9uRBM z98yr1v$C=a~AAewagmR9; z%*nTmKh!Lm<)Z(Tz2L}Fh^F^ijJbb0_x}q~zW7}SIoloF#mo24Y)*AX(FaLE5lFczttZ6+poO(2aV=-02{9WHb`?;Q_Wy7P=8q68c7FM z_3MG*^tGK}@O{jUgIshSiCt$}q#|Ak-UX8EDs(#jb3`@!vbPzSR6#Y3)o_pP-5;>G z=0%&`L1}jP?&)Rm?93mBvAQ$XP)%4=2BudsXKK+VM8GEhH2s%6gMcFWu)Fj4hi3mE zs42==xuF9_2h!nM+a${@y$7xqQh|9Bx2E&!udi>uPWwxg!X{nl zM>>k#=!{tMt|T%2=ZZ_S(T%=g$z)f*rMy`Invlo>n@v(3|x{Pnks>>E(V1+AYZV%o&RIohT_s^r;hO zv19D1pOw(HukRDW#h;DhN|fn=lX)_p%d&XcANWD__E#CyD{X%~D=u9B4E%s-&!Pc_ z1c$lqd+58^IaL=s`JoW+xhb1G>l!=WV@Nm=x+UT>=}GFYFShvY9Lr)q?9>X!cl`ja zDugU{a64sYFv|zHEvqa=I+QamX%U0l4-_p}Ny8GnaYyN!w^QJzBaIgzknO0A9WFA3 zW<-!(b9DMyfD?%Dv|TCeaGCPFxozp zSI!y)4}u!n6cT5LExUyE`8zr1G^&C#vv-$%*MAUP5zmt-PwF3IMI4-*_xk!YtOt2du&QYgapK)lyd5oPBZSI?E(HS;3> zxyYaUc=Ox)S=Jq3iRaqH#YFNqWBGFB;Ij~6mB{6YE&Hb@WGhawtSPLX zW2nMVJf2Q8xHLmg$bQC|DdlOhRyRy0hAr8?L&Z6sWA-2HT;ljirYTk;!MV#Kdu0Pe zymUc5Nj)zXpzL9hfV9hQ^<(Piye##z+6 zoNndaM|LbEq33c5t^?sBH@Q3o{71LuS;+80tJWq6z5WjXUO=J0p7?ex#B8VT)U9+h z*6@%ad|V-?^M3iFRG(~J$rLuEH**6c@>*NE)-cG_4#M#6^O9I;Bam4o557J|(&z#o zH4EqGayBCt;bOekXZFwK99p-89j z&SUrI>P?K3-{(~{OpCF^l1M=VeAG@&i~R|n%`e3llvk)ty9&XK{{Eg=#LmZDTZfYa z@Lyi}Ks_e?*c=%^3=w^)@!9r+QAk(%+7ug7&s&5;t0S9`uRB_q@Swmk zWn~ClF4EEkY6`$&PvJ;H`EY;G4(q(hPSn(?hs}8f8CdnCZ|?ZB(#+Iz{34LeA=gjj z09Vqe%+xzl=pE1?VpUUmJHUPkz(L8{5zG!a=+4(KwqtH`RNHL0@hS3}u0P_KkXITQ zAN(t&wYC7BwO#0uijfa?cyhm$9GPIJuMW)0djef)xqjV=HGMXWYd3%62S0eL#?Uz& zQR-nTrB8RTf5oX@S?FsUhznRsR|}<0xgkoRBZg^}+z{&FnAssDdrcRPd_{RV%|!Lt zB!33)h(@vgR*hPMg?LqNl4V~tQ^7Y{&6ntZsVA7M>+2?J5CgyR#BKsFD058{b}rDL zh6qNhe+(Is!OY`kf`R?O7g0}DPA(YHIQAf$CTVp2##1MT(GsW5lo>~u z&XLC}YFMSwSCAA(g;?lI@pm`E*~E-{czcQ7s~i^X%KRVaQsrx+Z#|(=HOfT{jPXd| zb;kFx+XTK)fgpl#uoH*ohLPG|E>;OLyM{wVw%ExC!k>RXyENlb(+75co6uH~`i8LV z(H0Klj86bjXmgYEDMqZI@iR2&U99kxu;&Ccff zecrkCUekXC_|j4)CowE14_E>I1fDr%yU^rFA|2mcGi7sQgUktADG91bgb(q)SYu9^Sjl8*dH80K}6MlPbVgB>#AY98IWsAW`e65BEZ4n>p5}BWACk} z*XMsugH4B~_kbo-l*VoY(eUHuv1da7v_FbZM!B(m7nn#?Q0&;7LZ;F}Ztn#ul{Vf;{rxr7LVcibLvRb-pi{{ccx*EYJH^ zh_6(giHX}L${Iw1r2I(5c!=6PkzhId;8cHbO)y0bB?GmeBrk7uQc3D$QuB1podkPm zUSfJkA*(>1Gp^}2Oa-kS87C6OS)YnCD5RsW#%@`zhqrJiHlZVS#3K|ONz>)>E_3oJ zYQLN+gmb{Q9dgT1!Q*or_2i6GAU}87g?X?cti>b?N-cc6ohM@xZ8;Y7lra}OC2W7q zjL-m4n^ny+l2ig7$akp8GkUkQp%xWy0L!$9z((}kcON^msn4Pv5E(9k$PbWf4X z81OY{&AnMDuU2X#RBV+(A+?|=KYpi7+`Fkw6f;R=R!lLvaNe*QD#{AjN?qzG0#~He?%!B8K&+=WfAG@~38n5z%g1fH-cKWME z-I@V|^Yz?2-L!RBR5f>vzw3374rWO9TZ#Sb4-(2rog!f)DJ&MDIZvpt_8g%$H!O#o zH8GK=o9o0r_k>KeR2k{_8|r`jGWq-rg9?%X9dr~rY|5~PS~E+uRtzF=s%Z`rZxlja zH&31Uj(lXOc|Hwan=nV=I&(7K05Jc`nQw8l?+7>*LV4`^Kiqm4=E)6%8}+TZ4ni@9 zN+h{FBT$_|5KiyowCEh=q9m#818@t621iRxlt2iJMZ%#aB<#L$u8e;XW~*Z+riOac z(}93M6j0t}38P!7U!WYO#zp1N}CO-KnuaMVg zePz5CvF7}pFDKwNf60HtUK2Y?G7HNRcJX`U$pL6X;|agRIeM5uu9<;-*vkbWRJD}I z5dv0(=KVyOxPkv&ud#Hu?5sA2et`Bk#Gn~%Rx&jCCSkC^yG6`A)@Kec<`-5knuzTl zjYRliD}G+7(2EuZW^yL-rnvak<|h*h3uwZ0#o3VraR#{Gt2loi$cz@ABbWv@q^r%< zQW>bXfjTUVKfO*XRQT9k7l@mcr?naqd;@MFiH<#0Ir(}wBQUtG5Tc?Z^>#K*zm;~C zEZ1}D?2>3l7B6uL*zu^A=20YvSK1nDm|2AdHuvs*CR%Ao&$!Ewu6!}_5=Bio`jQg! zIor0ZIGWfO!Tx_0P<$jMgQCT{lf{W{yli?Zti>Si`fU4@kju@4j1YgQ5gQ&(l-KIa*62;059!0PnK5m?Sbs7Y*mf<%%tH#R$$f6&m4c6CJDhkgWa!x8SIx5%@y*| z4hPuJuy8r$-4TfVWsVjd)q04*h`Dk2caP%?NR?;|_V=8Os0-k4(P!1OZwhXyVz@tt zGDPL@6?R2vDx8#Wo;r57$Jd4?!t$x|%72+fc*+AJITbp^Oq>sk6ap7-?JErjj9W7` zhLzGX<|Thr?|lysx|9gZOn&aIK|j+~6NOTpa#94T+UWI`5SkX0A;2A!1{9oU0?aWF z*~-zfo#h5rn_vPW*ILp)eGhNN;EK1y{_Xedtc->5g1qZWolu{zfCyF`w628JLb!N< zV6RmIuF?Bd?(+Bjj9Dm1!g)NtY;QDJErT;VeBOU?YbHWeXyvpSbc-6RDCXp6p=@es z22eif>acG~L$B@m_90__mjW-y3oJs7L<{QtsqRP{`iWyUECY-Y-g>a-pr?;|RAAS^ zkUAmBMd=8Vp!a^t!MgzWcMAiC*&n3|6n9dz0Ru(uAasgo?g`?vusNiUB;|4U;k`y> zpOJqzG>X_n_41y%SuiX}Hd3z#qD+>|IRu8B94~N)`nu(UzP$!*3tg_ZIL( z21DKvPMajBKQX*lguRf#RrSKom-!W3c;f|(KeglQ%fl50eN*X(96s|Hcj%R!Ob%Xb zVPT@vkt0{lKi&;8vD=GEv5KitMF;nJdRO0^7~Jd+$E zkvvY|l83*LT-+47=IxF{7n*?lGHF?dJS10nft;!;$ua$vHYp$?RwJ$M7;t5O4q+JM z1{*(GV(}~3BQAfOVSOZJ<-C$YS-G7ws;)IntutW<74D}aKlAtx_UzqO*XIPpLX&^& z#5u-q4*9&^zz)ZEze}PqhJ5I?XTsIINdrmUgU+i(w8acp_3N z?x%Nd6E}2X;iE0iRG9WC4SO(}&+C6o9D5d5rl#fZOcUW5a0o>6zvRt3^`IBseS&^9 z1o_XbalwvRGrdYqa9_-d?S?|QSuAd>VeZV@ z7KaK!QCa=XL{ry-zvJk_0n3evFMDUKG}HywR-P)}*cMaA&WS--M%jl=Jw170o#tQz zzo`OW>1Nc@u=W&D81&%;y7a04yn0EzNNL{c1hc1kxMgxHM|nt52mz{ANLgnhDRqqg zQjlI4P{-ViHe%}Y71U?rF~xsV62VS3n+WlwlnzJZwR;r<82_~u%jaTtA2B&F%}f-4 z{iL1+GW_$`(WQ-`XF$UY@RF(A+fm(>bT>aA!IqwYLh}2~Zr9n{ZqXvrPUQTZ{)NP; z2~O~A=HBK8IAL$*92tOlXtdqG5)^kDcKk;uFKM8+!s%8rfpWD<4r70U;&G5~eu+|S z+>K+b_r#$CBBx0SwCwS#0mxUWMEw}a-Pl+7o!;6$iF0zyb5rYP=HY3-!iDUerx_VJ1T}5xtR6`@C$x&;(^pwJx(G=`DTrK~;s>>o z&n(izapGs|zYnJy$6&&9z``k5i{T%%jY+AK8m4Ik0{eeD*jWbI5yjo)SVs|haiF&m z!TI@_3j(aW9^8N7i9x2f1mJQYaxDGA$U3{7254M}adoS^Rzh|h1B{h9MmfFmSFW7xw_i4{y4#v$&(Gx z7?-b$Xx`WEmYS=={w$;#w^M(D58{`rNk`IJ@=|Br$z*@t$*xFvaD&Z)!GoB-I)W6I z9oU0;hs56S?lXQ>L~95<13AbAJ6~OmQvPL+?Nl8d57pRR*#`7`u%scfz7r5K=J*~t z%0fZz)}VTfZ%r45pHSQ`_71wpy?N|ya5hmpF-YDpY4z}!kVbo^Q4STxfV@s`*hXm;a8U9@r%FzN0zQ`>8iyaa~(CPtj;$|%!<}$H~uVFx*|CK=GE<}0=)v`pv z+26dz2Q(&L8}=wDC0XKFccx2bH~f|4J(;v9{?+Cx}nnB9MD#crJ>zU8}jcFZ$LQHY#IVf&&+ zkXs!qF(Zd6gO{(AZDwP;Ze7nDv|L4Y$ySOg1Qhsa11KK2o%iDK9=Bi7bS6AQC=%>o zmItm}@UQWURWLivOiu1UeHSKR%YgA_C;Qen+`U5M_l4-pQQTjK+rxt%A?u@mBw zkPCkXnYN9h5yeA#+;d71C2ag88{8N5K4K)e+}tOL4L7V>^~iQd-!s6z>zg1%Q(Sy+ zd_yj&S@;`t@=Ewn%jFHk*n(yM=%IjCvT2ZvD@@t|q#!gUfgh;R{pD26vvcfD6vK0W zOj;*H!RI2$t1;0Y;ta_vcHJIc3TB~7bDe*7TIDgz9om^Ijy8#q_qzq?HZCnH(yvDE za7e9S1RQ5%vinXqcUo%da^aAexA!DxV1Fww zVTgLIi#Xa`z-+fA7AJ7J_m8zRPTSfO;-k9cDWvVTVb*l{}WzoSH^bLF+`zc z_zSZgE80UkaWN2y7CINa#q6I&Tuhy@bEyJJb8NLq3JgCZ(XlG#SBqZayCya@jk|W$9yznZNtP}X91n)1UbzapWXVHs>ZaPcfE7hzZWh4mw zt2hVQU6LNv{MyqkzxEd$p;tzV6(WL{_ZpIYiLE0(irk(uL7X{(opOIX!d{0leZ?L83F5Ky7l%S0Fehtb+nM|IJVz|XRK#=} z3+<{VJG6x0J5KH~jL@u+K(xJ}om%P1gc)UQkXSDEr-)vfm=YeRpK{n2gi%7@Bo)pBkw`p*lU@KJ!;+hpU_RrydWqMBXMLT{er zyFAtksBt(j?om`D75k8!-$oWugjol*;&`xR;cXks&;bw_f|bamKr>ZQBH8fI=bVf+ z4ll`KU>X9(OtTPxL(EcM`4IAQb+BA^h5kNP}YVe!Z6RsRo; z7)-X4;d2uKHb0XLTc!U8Op*<%94 z3O6($Fd$M2K0Y9qPR#)wx5Q)u4Ih_R5CSci{(}Omm!J^>ClfL;F*gb?Ol59obZ9al zF*GzdHkU9|1Qi4|H#Rbt!9oHkfAyFgCLU1LQ=d=^R}hX#gN=qrV(Mf0hn5Z}A{!keMaO z;LYJ*+(7_Q0R;f)P2zt9IvCoU**ZGVIha}gB@*~onzwxxu{IL2v9bbNJ31iz#ZTDG z9&Grw@ovEXp09ILer~a?zzpa9THm(2<24(;)BMUu%e}SHj4Z!yH;q||H{@#KA zs{hxjJjm=n?EaBZ!rIsd@K=SuRJ?89f0a1@r#UG8Gdh%j|1BYF^VZW~0L7mX(57dh zH+=iW@c(%b{uT27umAtb^8Y>p|Cf@elcnXq94P+d@&DrhvNE%D`;W_8Q#(1n4Ty}* z+n8AYUspBof4|3C25e;JWc7co5{{s^K@qSvvHW{4%^XC{T){^2W{!rY|L&y!9>rUF zOEYV*yp4m|Ul$L6mVuuB|JdF}&(PxSa&dS&uz#CC4sUbl_^-453xnS#?SCnVSR2|H z{WX$|EUW;Ky*{|g#g~=FJtWmXmd zP~fkneL2q%=f6!Z;%pb%70LuN1*y#a4`9Fve z095>g-f}AaLCgT4@*niZQ{`{O@m2x!H)43J05W_##6Mi$VnL37+~24h{6TN-hJS+J z4gqNNe+RxPF|v7kJscd&{^7#_0D}Jk-)I~E4O!l38=E=*v9tVTwsErmN5Gql$v@y5 zJ=1@{H*Nnc_C~?{AMj19#XsPi7R!IYH!)U!;M)KLt^Wbvc-#C9ncsZhp00nG--z1& zF~8NdeVbC7f9%HFdkD1q2Ye&`4_ORv#2x;~e||GMyj^gA%x?+*9Kzdu0CY692mfQA z-pD$-*!&~lO{&u$$oOXeM>@tgw(ft}zU_lM*#6(q|1%PXPWJY1GxM*D>}_8Di~sdx zfx)g|LxjaS8$+%@^XkCX`zirE7uwx%ZkY3wdv!+I@jP94$3Bs1z0G)~jPxa`64Aw8 ze+E%q^A1@-yZg+w`74i|8p2vP=381q(E}4ggV?#>w~#**Jnry`=a3sAvel9VKXVq^ z_d&=LM4)uO=QA?tQzAw7B(LsSNN^#;C=z9p3~H5a@2o0Hm&U~BP(9gFbZjyhRNiH| z#wO3&vWf}Vj?@lImQ5v=;%1v0#203U zt5jXd`S_ew=zN@t=3yX)&VOvwS3-ln>j|a+P^qq~4nA>e_wrE&iF`ZFy9TeP4A;Jk z15MLG1iODKeP^K17{5kEnuI0-EqO7#ZyF@3>AS!0mP*rzev`FW7GdPVUbO4Ne<>!h zfs~CE=+3FmOaVEJ*|7L7!n$7IJO@V>noFGCRG`|%?=a_Mg&7?PkMgdE{YVBhNU*-o zjNi*oo4;Ogb#>@X*@X%34sw3^I$4ufgu84m+P>K!>T-*z!}(iUL=WZb&>q)7_TE@= zY+Z&SH^rwcRreK^)v6`{YbU3wB=}|E1T?G>*Vli{E^ZrtbixrfMGfz2F+ZSmQ)=@9R)fJo2l+7%RU~6GU z*u7$KqZzY6*cY~7jks&`-5LV+hnom7_Dk>AG_lLZmhNU|Uh_SMf2R6!<}D?lp@w5* z+6qHfx>3%Z0S*0o^Bd;Q!k_0$iBo$E!D~WpL$o2J3+lOQvek@mE(*(vuWmweB7p`n z&Uz7sT1MYo9dpXhk-h}ObES7+w7w56Wk()H;h%`eOPL=O0hGM#j)%CT5G&W}*gC4~ zQSbIx>`2A?#U*zfe^BRzIbIfeuntX+z1b5R>4>O{Mj^{ zU6I^#t{40eLL!12`H|anLB*2*5G_a~IDU;LXpMpuGtEZhiKw0QD?w=DH+EG2 z`}wR8Y4)s&2G!vbBG3y3NVK+ z#8~aU3{=M($sSdkf&|vap7Kd;3L-6!^61m}_rt{S|PfyvteTMB+EbZ_D zN=`Cof7`By49X;l8ahWx3T$?xo!u<*VaBRR2lUStevR6n6WOnzGx~{YLSUQo9FUyh zAPC-3jE!E3XVtL0)GLc1D~dO^I7QyI2-2?zs|-p@tr?q`9BSdy_nb-i3H0OKDDkv0 zeJz`ZO{ujOa)tIb=60^#g$urj*`CjqWVJz>e;CxWQqr)VaA2+NRT$>tu)w*6JZ#;V zAiB*vszl;g;WbqS^l4!gLgt1R6yp_(h_(9eE zX{~h||6nOJM4A~MZK2Kk^V+@7UUD8qnsn$a1!tZGu{f4|u1g7vnzK3*P7RU7JS#5i zJXWa-@Yl2@rinQg02E7|9;m|kvHKmf-j7=mp_7o`opD^M*q#G<4@M=;=7O_He{(HH zQd%86#vk(X$u*n`*VLwNY4lm8;Sf-BW=*#| zNy3)ZuCpyBRX$Q)l`%{>F|c~<;&~wH9FBy1c~th zPQ-IfF{52{kkiwkOMmZuWh+6A6AWILVmKVt%nBGamR0}LO*j?OL+F5PpcMqXV0EdR zak(?yl@s;Z_9F39E~Y1dk4}AzINOr^Xap~F)>~%>0taaC_wznDLq`W_e~S#C@v+<)JmH0B&+FKoM&e;YO&o zKFJ04duI4I2C(YK*xxl@iXu;ib)1zcM5@uP`aYj zkTs>Zt-{NCwwgqVAkjZke>^lgwcM!in6HUgX zO{xprz$P0Glq3h=q-U&#`C)R{5wef@TLdSdT#MX3MhcG8e3U#ev{XRKE?ZRzEJ-wM zb`Z)hEf;Bp;e?_z6A(wdRD^4{4I|OZ!WW{&7W-xgxn1{3@aYt0e*z?U0wi9hj1fcH zGC*68q(lFW$lLgt+@FK?C3bT>;$?|#empa8^Q%voUKTwMIsYYCcW->ndfq5Aa7`*S zd^_Umhm33r_rWV3onAY2JaMl z_UDq)I=+@^3mPQg@IfdSYWQNU(^svZNWk1%(TLJ~NaO`|$*e)a;3 z{kOm6gD66YgYxvXyU!bfYb0pGnF8mP7Ov)1V)D9sJe7CH;X8bChAj@1x-^c>4gAmp zGR1fyI)*^Hy|&0RSU9i-wTD9^>^z^4Uaf<%Ou{w3bP0bxGX%1g-&||fXZ(Ga%DPO0e0APxq@P2te$yvVo1#OSi($E%9pJWN~qc zF?w~N8PVjDK5B3Pa=V^nzE-)uT?F}9epaHMfI6x+#SVe zY{+nce=tQwmPt`FCsxUopE-3LQsGPMpo2%--NrIbV%06pLKH7lx6zCg$UzRtB_m9~ zqnPE@1B_JbwAVv4W5fJ$-)qmV)xX+QQZEyo<6|Se#zl3-J6q>TV@EItExIX){?u(5 zX?l^P3_XX|H!=5In`S12U;G!{QgDnc8I6fSe+_4k?7Ij7n(Mq+bU_8zK_ckFbH}Xo z=I9*W4&oBc86?z^E2^i+>9jBKPCww_PxcNmlL;DZQ^uV_T4e<-=qftdU+Y47WQT-{ zCv(O*Oww%NR1)XQO@gdIeSS7wsIV1y1Q>{~Le{v^+xwL!XyCfuA)+#imubt8ZgIzk ze?q#w_8KwAHe^ZaplVhUp_?vQP(HsM@vf-s%1`Z-Q%zK2et+ zYdMSbx=oHR3R99=wjp7h-0j5W5r*puNvu-ul|lS&y!19|1A0uiudS(k2-8suK4wsu zkWZ%&`o4dU21yLJuQ19|WZiewJ2PKfG9_(QrJqX%+FK|ve?OEKqP<_ZoA%kJZ+7Y$;P439qyo!jpj=)Zfh2ps7ss-g6cchyJzVUOz$@bk;R|a%1-c=c%0d5FkzLP$j%pY1U3+*D?DDr?4qZ--!I6TiGRkzwwf zR2%i+zxJEh6Si0S6qYCe@jLYQf292lHndVrMyOt>y|DToMdkRIL)B9i;+PmN(mOu8 z2rRstnO%fKm`_GucWXB{`0fn%8+Pm@FrxPaWk*DOEfXPxBDs@TA*~y%>4zSJQHKzf zC1X&#`g)5*X}o;Pc9jL}CVLl0UIc#4!c?x+DC|J7go&{l>IkAQ+{J!#e=q0}tj{#y zs3K&!OtinN)2`0u1wJ)PmyF3jrNLJ}2)>ZkPb-yX-S0E8W1yVb8UBT=7liC9sZ&Rq=G6M$o1Jbk!4J#rQ)eaoj|f%pMepkJm8% zg8Q$#IwEw^C552V9E8$M0P@oF+Ri!84<6r(`2K}i5OpuQeY=i_e-msz83(%7{B?21 z2sh%jKdaW_EIS*ZEJ6kuCJ659Eh7)I_T^UT*eBzFRbMvku3+#S(a=7X=;bHvg0n)QKRxvOJ} zC(cVRnS#e`n>T_o`+XeJfEcIph>ns+km&snggIB(AD@p{fB6f8-HxF9vvG|)>Iyzo z5Fa;`Q9UE8wt#X@J-Y5%OH-A5$v$fwG%)n42+$~I1wXuC9+4}n8~SNtIH$kg2dr?b z^*|N&{jLF_ht-`OZqm5-qOyMhrPjm9JjhKc@dfN+7XGR+FzIVuFzJa3>p19n4&wVd z45<)XiNNrcf4ty2K4(!F4ihUcHAb( zRyJFem@dXITwK~=M?71NC~@$UP<3jJK!XC`R zyX~ix^r#C7)e@i9Ew`3_FhOqiL}m#RZ(%gM9?W*2f8o`K84TfSDvbYtm{`?_X47tZ z`i4DR9waOJlwI19nj}AX?BNvB9@OGt5{K-9ltDLyVWS^x{AiozyUPpZny{Dwo0CXl zemkQ|6qwwk03d~}AUqlG3c{h$U*oA=wwprEeaXNX9N_MtKzZnAAmF{jvt0k4sT~#G z3VNj=f3DSMzg9Q>0KI=dZt3hLv{^giQ5M&F|Dkm}Qy%oBc@SPg>B${Ak<>su_{WObs z<*NTg3^_BR43oN=LMBBct$;X%9(X50f8CYaiVI$wS@ zDD<1)B}nSj!(8i}U{BwQWn8ir)X8l>f70<}-R#G0N03fcoUc!Rhh!aNnNOFn9T>5G zCMV%UT|Y`Z+;FnES^Fb#Ut3z@ zy10_@XpAl#C<8{T1zgdTgbhb;e`Z@I)l6qIz$3*c<2!8Mzwo&3yAjuLjRV1-drMQAALPJUn4?VQGtWd9%=@XdNst&HLMRL^rO#g)`)Xl^TEA9r0ue6h-XpxpULP5JMHEiFd;nsrPIa zrjMj9ZRQ0WH=XvvQzu(~@ag3Ad@^5GSWp@=LvQK zy|L3$pT%JbZ-hS@IojfRUVmQlsOg|QfR`3YP`t-TzX~iG-`$$@)|MP`EtVe@5u^8NXkmi((t3xe-AQa5TBK8$Onlq9+iNXAM1lR0|_bf)~^ zSfaT2de0x}K2!9Sp+^!jl}=F*c9G2VD37<;d`2Xwq#~a2U--FRr5Z6!I|aKvVFJdh z5!V{Izd9aEGR{L;e+32%uP&t3XvUClteYms6|lA1aW0=6WRh4;_pz-sImaf$*FPWYoZT=mRhGT_2%{snJ^BmF>TWu))Xv5GYR%#~4=^~8u@~GzVV-s}%M(Xu)f2#lrp+P|7u zRcv{*YkdI}L`gvBLc|VS#ZuOXN)SvCY)7i*AYnne+YMr6pt}HZulyR&RB|J5RyvXS zt{vdz*hou)%&}xtZ#J_jdoBVVw}9Y=-%VOrv_`CKN8I>Y*0Bl%umYEnS@{N#?5lk` zVZp*R-%bnme~{I2P;9S*rnPcv3nDYG9s}G+c^*D{#3Yb%*i+CK(F9Mpv>f!@xPTTE zzF@;XJZ99;a+Hu1D}4hJD~HxS3&~Owjny&eD+xW0-of3EuXVT3z zOd}qa#Qu<18-0B$af7@__7iq6f9L);{rTiZf9B@iUcj`n)<=CzBDtcb;j~t%_mw^k zETyXGn8bo191v{APdGf*UySLw!x7D*-XpSdn%`W^uJ{F^ntRSX5jZ|R9jhfW#p4nn zQd!LZnxK*pIIu5S ze|EjGmsQM|D5_kTq!#Tt*x@Zc3WnppHW zkQ@&~9?q_>shM`SkyWlZQjmu?@N7nyP{l=T+frn6>#Cw33SvX$CB$nKr`XZme`e3c zE+xf{jj6E5-KSO^WqR~%_Qt8$0p7Wk6h^G3EioK^BP#ns;@#`;vnW}d4umCi6~iWb zpb^cq@+V{@SmHqsIlK?bc=34R&NJ8W1}0;t^^8>u3Ye0ig%-bPEPwaBp!BECLdy*W z71EP6goi3kIK_vj?Hmqoj-|l>e><^xj4-9ZrmYb}GjQGRrQenCD3DB)3!+Btf9hJL z|EMnseB9GV`d%)bxMnpyIZ1B2I1po>%kEOI`zxR6ys>?JlJfkJMR`Hanm719sRkOa z;hnL*Q?yS131fRu-}mU@Qm+UMbqw1FrUZQM#Zj`QYO9K)%q9Ste#8l0fA(F(c?U!f zlY2~GoxlP&HWkM=hXt)(1OFeEXHn4JGYb4F#a3}$gG)q<(l_@Cvm~_c<-k|TU_ybo zb`K5F3x{GlM4=B?T##{m*kprXpxZd3dftV3L{R{ic^%}&jr&2I3XP0M8Kkf84}%pN zCi)nE^@`GJu&?O;WX9(K#L06O(m^NmF1aX)4r)aBIkpbNDQ0d)t{&eS*9#4?z{O6M~?(7dxv@a%;S;<=OS({MD^# zr}K8#>-+861VG8ff6N_heB~wl4I|@QcT_alvB##RgR=zUR7I7x&+=&{|cY-6$e|~o&m9t=`AzX|I{K6md zDn;4po?OX3Q0ToG%4n($Nq?s->qO02^W3KFg8IHV{2rFY(=r9rvbGui@by6Fs|ZO2 z+0ux2!t2hKd1e|klu>g4tI$UwDTDh!(ChWSKwU+{I&gn_Bkqd2-07FjY=JW!WLCF+ z{UGY5q>n*re<3k;!VY-}ox}6|yZUD~2ykJ-$DLk!VzSFLQ@@1Z4r7Ds^dq-VU&*UN zjlX%)S%;rMdi`KVv|hS4}D}PFR?=4vux#N zf=<+x(P^HQBjkNc`4fMXd3~35r#aHSTD_3!mP2i`dUZun#^U?_gCm@~a% zS}HBYf14)ZHF40xf14FVf;bJhp62VQJ>ZJ zpXjI#!a8_V*v08XVd2kWzfFP4sC#DVBAb!nZ|C$uW!>sxjV+9iz?1d|&Az<1<8oSx zC^TZo-L?6h;UBEv!_NjP+Oop$1sp5;v0pOr37B6ffGn;&fIU;$a9^y21tDkzj4K__ zov#HoYpyq4goU{Qiq2wHTG4Kf_5*Q6e~3I5S&n}2Tx~hF_bnCJ?`a5Gn*z|p5skH# zkND&u9$1K{UtyheQks*2;!T<3aTkkyH89wXonO2L)mRJf=3z@cdBb40oDVB>!IKZM zW-kIekkW0x*6uzQZ9n1Ji^^Wor?InAEkm=9pTsP4~#Q{(>p|_1WEpN=d@jIu^O+ zQi^{{l~UR-q=!wrtMW#e5iUmL(b=%~e-~ z$mGJIU9L-LHbZjJ%VQS7B|DS$mZurC^pBBO!oFDp3)%H@c~B_f%VZj36#0eJe3vq} zalO%l)A+*jx5Uwm;G20Dh<-xK*RifCk<)G!rztYnn>-iQ;8C8(#i`=ykZrjk0R;{) z_7{SDELsZ}s%pQTN7RQSe;Li0^_7!mw+wN?$~XaH%6wA+>&vf>0)(*q^Q$V}k-2EO zQLL~Bc*d_-%c8gq6{VLxB&5Q6i0>Mn@X$6%WA`VkY2MRjO;J;Ryr$?kq3=F>L?)i* z?|24MIGX{@68l#@?p-PQ<+b<|bk%E%Y;5ZY383e{Na{HhGjjqlTwh zkWoJ&JWJ~C?Q^F+S_j5XQ4QZWg-8D^&q@NLbX?hBr@83VBf+Sr7Sv0pNmZnNSWx%K z`G^Ep*Av$dk-vo!sN>flw_WFXXNyVODcy=)gsrpvTTEi?;V7A}tR^|~* zgAAF9kf}jJ$&?`!GS;nxqEO-#l?Vx?nNUPXBuOeI^AJjAQu@xL-uLDDul2QBt9yTE z&u5>#_w%fEPZOV$KV6U8d}yD^7H^^H^0p)-C6s9S?Y8Zuv&Ka$o9~;gn&=qaDSL2i zXT*$8O!WD!81o&DEhLk}Q#Fq#X8b?E8Swlh(Ia=#}b0Pc3Izu+=L&SJzwiPbjcy zczrg=Zh0j-w`q4!yEmhMl9O}On0An0U6NA?rdYx%W#v0~yK0<>fW{uqtIiiWv>H_J zR?Cc>AAfnBDk938zc$P29@azZes&E{@qV4bb@=sX_iZ`6M^m@#L!D`;z})*$ZM)C$ zht0)(Qm?cBDCiN^wLhrCvc`W9@s7N%afQE471>6828bCviS0F3jBK3qhH+#@)WoyN z!$)E^v-&+Y=04kH)~nycBl;Yh9YP(AD%Rxi^>Ik$RIS zW8KOp#Q8&NY;^O^BZte)$Q!+fpA1OYMF`am#W1c&sy=XyA0rJ&Ta`5y!pnj0?D%?G z;QaQ^-Gej)AFoGZ}+dqviz$vxU|%_MUC!DwPDyyX*HG#3eCK8 zDN{2Qe3&R~YUZ8y%QNM-g7?#oI924J3iJPzHe1OdP}t`^+2m=Tzlw`WH8nj zlY6|M+f+NFu8-@{Bb$#_&%{%=rX1WT&Hh@cVqk>S&Kb6KbdZecn{IE?hzyX5bI@Iv z(-82mBYmsvp0pYs)56rZjOE%h4k3YJ_TMfsR6ZOL5BPZUlhuHtY33?;fq+%!a3ah4 ziCNw5FUp^KyJG9u$u-?vkMkr4jxUSfw2k;ia>@^*`tyyYiqvo0>hmP&j?bDEJMzjp zFWCiBR<>NaB$V~zRp~X8J{qf;cTvT)=@z=!hbBqOy+mP+mq$!LKOK0_aIAOIGJV_D z7QFWTo!w?*pCTKJPnn*s04*}wI5+oA(cBgKew&FG3J|e1Jy&#cQ!P5<+A@0S3W-7o zf}{LYM%3d|ADAU{SloV)TBO5i+jNp;Uw{6u8jVNWG`1+cU|ILATQjBnk%EaMH5n zy+yqh8|2BJI#hG4?^xM(#RRaTmfQ2@wb}U8OX?qFuKjfM8b6n?d8NHdsfv{U?eL3x zrTSw;Jzx8qy0A)VrZ0DQI#K8+xGPWBdPaLx|Au{%VS7mK58Ligw&e$%d>AjjXH=c( zAZ*-Szfn9n^riH~t3HspXUFu5>m|>OaI-rH#bo#CrfDjB=A1cl{^{Anxym~!&HFIN z`2uxr-%($=Tln!&hm&dW_N`R`amQ7Ud|AaMP;^5%44Jr6(UnvnZ^HH95MQBB{G{0y zn)yxXncTDX#p25gk^CVO62(P})QL?|yhHYU zr^Y;*T~>x9{=D0wy`Ce@a%S4$sZHiFo2clccXj73yfwL*SJ)Fg@g+F_ym6|#NXE^* z4O=eif3&(i`^f0m*W~{FB|8o79F+2~eQEXlXHB}7+i&a0lFq&{WA)P=g_s#<9!8Ty zNWFloccz_q_o>~UimH}d4{ooNeH#>Vr%BLOs^f$G%+{_wC$3j)6MeZ?VaVWkM@M&f zkC0N#l=Tw_)AbV{r|g}9%M(V+iQpugv} zzoN;bffM?S6D1Z-Kd#u_C3^V2T;7@z%#a#&GKi~*7q^YHq|IDO?-rh$eO4?W?U{|~ z=JvmTEido1e~#Fb`-s9wW17`6!OpxLrkB0-t<+DCOoqLal~i_WO!C`vz)GR8?85fv-^5y<6)*o8G+q)QWR)bi z-Y57vE+J=vYdaQmm2`7!)hD;=sBexc%Cz!dTBo1!nr*k0dwHVO>2V#|_#9I4bcdbd z^yhNM3*Y-{xK56n%g&bM25oXJH)049SEUV@#D9>f*Xx|Cy_j_=Krg>RGwr)mt$pko zrS-oq)O~5UX}(6vM=r&^wHbRJagWjdWt-mj;PUPHZxgZKe~usODK077K2@D{#4FWP z%=I^~Qcb>m$;G#=tEhtIu8DkOB7@kO9o>PS;$j)@$u#=4(4iM8x$ix~{m1sWT=hPF zr)yiRby65c`I~y6H_Phgj)HN=>8N`5yq*g16i`NJYp z*;2cA2mFF+E<8Q)r19#5vdJdNpBorQ<+b|KpO*AiW=E`%w`{_3*?-i2bV@VX%0>x|_dMPF06K>hF5J$>oh|&1>hDnGkLH>sxesXuE~psq^IQ9?Dbucn_?z zvnYBYJ^U=??Kh7VwGS{?9!G56=C!OZ;Cofzv0G;=o4dk0>Y`(t10y$ys3n;t>%W$q zP}!$I4muL;K)%DcXg76ljhlLQEM{fZ5Le}>qW=L0wcL`G7S1ytX2tT7Id3rT?{1q-bFDCb-oeo? zHG8hAI9s`+a%*0$wBz9Q=GbM^eGeFb7vr@IQ#Q`9PoHxF9cK>+wNO1G?;mdC9WP)Fx#?$nvqT=kqv>CSd z=U3L849@SYn0qC;p2)Z`<(W5~K4UBLY?c;48HjsBC#po9?uTkI^|q)$Nq@kZ+fE3uni(PTz{&lw0x(G*}bv#=nVq+>_Jfa#=mSFe;5+c-VH3k%TR^Aqr^E91V-v z8Lv_=#_QlM9_wJfmauMkQnEwb$W%l{X6n?mOYAAhK&KtyYFs-#)MT{9NJNLd_={v! zZ9cv86dj7B(r#mFCd=WjklP_i<+|rLM<*EZ*+0z^bh2>ly4Wd|^wwhRxtFzL%dcM5 z759BRbEa)|si)TX)G_uPDV)mI|M6IdeRm`VA2X%<8M6hW`250dvuCXaaqC0MJ~`Y! zP3d0g74v%=--@0s758^;R1}GEe!DYBK=|}jP>sP{%g%5P=b%j~llyBPJN6{*x+zu` zr}O;Gc>4W^2a2BVW;6*6K2YIjluDes^3`-F7~sW`^hum>-Nm3(d3 zIQx38MK=|@8u&j?lo_mWml-^7Vru?nRcfL>sh_LllQ0XssIP=J$CV!s zE*dwyUU#FQyu9O=0?%fJtZ4?m{*<}0iQG{2+`xFQ&%09vovPb89>vC2j)xg?g_VS04PdWyX3ctbprA%h?K_17w*)D{~|{+4QDv z)?T+9OSiE$J>&A^{x;!)r*{oh`pLaLjdKRGXV*kMk?wskq?PDy+d|%Z_%!3ARG!&` zyDq2Uy{wZ5*1bD^Bx|VM>Gft(edVC`u&-0JN#dDXRn#3-rWuD1T#FvG6rNtC9~>er z*4b$IFpOi4X6>YVG$19F#URP{X#R%AFMD{;YQ8bCaepz|I$n$<>^<|v&G}An&c&BS zoEBh(C40qts^M?D++~Jz;hB2tD~z>jZB`m`B7ti<*}Mvuwb3%ppEgcYERu-W7(HO& zcRoTc*h2VL!t0*~{vYgr3fYqctU?Eb!!Ly<^GT!@xN7O+YIC+kk2|D)Bn`dtJ>s}6 z-$)6*S(%Y#l+Es(#M}V!kMCjzr-7`a@ZZD`%&XL?sF)W~M|?%f{#yU2wRs<-c< zXsP`+`lh>U(%BTH-=`QRsQ5&ARscoLDeJ_*-tMQ`HLp^g zMdEtf2C{Fh!u#QD&B}Rv>+2(xZ=K)$Nxt%g>q+kE@aONo+CNhl+B-bUuA!969b3x9 zDSadOwVUMYIClD-n47PouK3^FF(zJf^<9MxWoDV1p{693x*;MwC7Iag*PA)W*sa~O zk7&W)_rUEVJ^cMZnNX?4B~S6BI{oM^-)t)$Hte`X^3O0D-T&gdUe?479`(Exo<`G( z*}cYJXS5w}OWS^68%?=o<*5|$ysoic;bi3%Q`cHsc?0_qEB|MK1_Lh?ruLcUWJ>kA z$(#tu&1D<9dth?o=)HRUH*TY_jXaHvFQ(u31)aa+{;iB;OXgljr+O;}Uau9OIdpOr zuJVxXW1Ie!-X&7So8D&uhbRL{s$cy^D=KZdj7}$?j4`c> zeZ42~g^i$hqg>0G7MUswrQ3#~xD#?G%v<6M)^EfpuJJfkO17UAw7%GRJNXefPJg@X zx*(F=uHaF>ejmT%@Kw$l>40h*xfJ#Yz<68uCGJ94xm136RzHiYltZ~jOHxx{j&ixy z)iu3O8$`$Nso#z*o?dm`G2MPo?g{l*hh;avOe=k?$(o!h$!=68r⁢*tg!|dtGb5 z@gbmQKa-;p7RDR0XQLHG#fzuWE*_YpP zKWY!AjA&S2pr-W4%$Tm6QEYDfs!8kGWFEt4&C7CJF;JkYJePn?PVrIln_1tyb=Rq{ zeoh-sbZtzV4?eiBE5)R@ZcIzC ziNL8=hyH2|f0S2%AvTc?inyGsn%W~feoY`P+@{&as!~~scQT`a`*1|&`T=%llY&=k z6BxnF65=~Rs0z*@l`CTy^T7k8m)aIk2r^sL+2M+ zZ$s_qr_aYbvub!65J8*QD|yQ-Yd2L@1d1`JJCr0Eibl`pUOzW&d@%j0!AD`fHfa?- z@>nYM-qr&dnT(SaX?sId^XVP&$7FdYg-*qc6&e>$c?23g-yV6jkcU5p-j{uJ^rvJ? zGv#5m+?3&=wE-m_zW&QT94ax9Y{}mM!aB#Id5V5s_{5Xu?e&;@#*Ir_ejtN3;udbp z&WJu*XXWO*mi^w$U(4)>;Q?We zBl3NlReb%=oULdI*B3~riCXLOPX44<8@F-}gR6?edr--KMj%7Q>RrCExe2G#duky3 z`EFV!S8P;AOxfmdt7j)>>a-fW1ne!paOcx=I)e|8R!v*Kh zgk0D7bUZpfP&7jn*OIrRWj5u)l#0;HRQdI3LFeN4Z{9wsUFsX^OX^BvKO$_;zv-!> zPP`;Tw0I-w>K8%F0~=!PLp63eO^kV+5={~wU$%VniQVjz&b_`D#FB!~88t<{nJl|l z&ilOenEy;cf?JzHq+se@MP!{NrRCb%BF=K@6pBjCU_!F9jPUbLn*IjaILdt$E?Ul8 zdc}=B3R>C+4HU;`BHlFTaQa9Dige`PH<(-%P2d93ZmUkr>HKtNDMf#{4tDCYs&a4H zYP-$ALRsHT-&!BU@w18ni*nZU9L_%eUM_xq?x3rjRgL8U;ICknU<*+XaXIJ%_Uf^c z3mhw0^Hjl2C-@_E`UvZLaK)KbsX$|t6(5NeUj&+z4u)-CB1}`!3tAWCCj7ritrUr~0huHUV%uO8leG{VwY88da zgsuXJbr4jxMqU7^mzcE$GFuTPJT!tjTtK!M&i|IbAgUEp(^?A_QjJ5Gxj9 zQYRt@_O~Nkz^We+1kvq?B`cK-TH7I6MIR!7A&?2^6#yat*MVq(k~YYBv;&b~C6ho( z2cp0H-+ckEdk`^T+KvdZP(VW)A`aenAp!~R2D~6w5#dDnrGZZ;A`d>bBLd)RCnCv4 zrlB_mB%~NfETH*~n&jO9Y1F$ANmeoym~`Opo?i_kS}4`K~&qL@byA_0=2cvc$iU(cjLbq}%9QRabRG)la$*K5(%Y;RdeVP)tEDVh*vK#gx zmY@$^_}Y%}@)F3L>O0(>{rCCF6UcN>*@x@}!M%`<){jU55%iODKcc@1k48eCK$yQn zL7qUQqTlV&%M@I^oqhIta1wEZg4%v$7-1n46n{ltvci8)eTN>i5WuxjM4yES`bH5w z8lEyQX|1up%YHRHUP+#SpO+>77a^d?eBA#*h$un_j$;TOaBPLn7>^@7j(8G;3AlyA z$SCs1(7(dqU10>mBJordp)cg3L4>$S4jo1CfM*<02b+@qC|qSsSinR;?IsczBBKi&{f+ezewN>STM z3j<0(Z6{HI*#x4)ilc(q2}FiQS{P0uYC36Q1c<2V794o;6A_1Q;eWuRG5Ql8$f~Ko6dW|v06d)lG=CxDl1nY5sln{T(@DS^u8aKL z#07TJ)$qXL7b40*SA*Mur_=suY5E1VWKJXU5T92-2eNaBm=tcQr*u>U0Y?TF^8|mh zVv!0ofnZV`pF=i+(=*W5);UB);jgj2j&3gVA_#w3=K(YeiFBay8_@&aKOjr^ZzPDF zi0%i4oQT1$f#-U|ETWibf#pg(jdcJ4ELi@;GAshjS+J|Y1P045@8aa|?&GaSL_J&U z7qA!o`xhgq!L0?Wej*A`00PV~SWXbZf^|m42m(u1tQ6>G#VTQNY6QTK!72igUx@HO zq=R7c7b5b{H*R2$U}M1ZIfMsq;_mDxzl(_b;~MdAw1~JraVO&bcu2(kDGfv%4XrNH zKo9;`N5K0x%=ZZds|)h5Se3-}SRUYs#TtORUoa8yY*=CJAEPB%pm9A|tPJX;BpV76 zloHA~guxRwEFVx|#qzB9YscTJNhJK$|2M)!c$dw*UNLs;3d#AZ1S_e$rY5I4Y>WPW z@kuLhrtqufSW|>Zr4fM~ zC)N~hFh4g|7#!uqYGNn^0x0FgnqkN!8sOuCA4sqr@8-hN#Ykjm+(O|*SRr8%$>+jS zByo5u8NYNLR!s2wpLOcebv%Uv%(?&YQ;18~anRaSZm66>U$RJ`)9_&UFEe$iaRfR% z3OYRV!fEqWbg}US8UY95{;tob3e!53M1gPpurzTJ4lVOcs}v#;sPjV8@VKRmWEe&U zFIGd8vUCkzIRsvzj8wF;GD#&;@Ia0aWn8+3UVY@l2N_}1moO4=I8cf%lJH9xagdXb zA4;YEk2T1+n;$ZgiAxsobUYE{ql`<#kEapH;P<>xn8b_Sz*C7NU@icKQix0Zz*At0 zOhp%|Fj1K~$rKV87C-~AWW(_!8r)DpY^57K15Aw2QgoPGWCpxz5)aGhB8-5e(U=9} z>2S7LLI*PfcnV<^b#Me&Wflv;B=moEYu-jNML_DEjjVP9d1%rce zQx?NIic#=P?!!Ywpu%ZN47-}~KRl!oVOd*b2y7!XCK*K7A(%G{%BA6%oIo)ubG5)z z>FD4G|1kb5ArPc9d4|K&a113o&>~VCz|op>&jgBE$H%fzsw5Cl)e8LfBiDFjLUEm5GkJ zBr-4+&{2FL9Ue!gGCRV+<8iQQEhfZ~;O%uwtX^9AP=Pe2utJQ+92tng9=TWtioqzL z=kLEU0vZFiiir?n%u#@Jc;?;&F#_{sfMQgpXhDof{MTW|pZNs^>CB$saU?QR6d)a$ z`MeY1G>$$^Ep!A&Coh>K@Q@k3I&dK!9>$-_d}blxk}(5fbmk+5hjoy)#5)3odH%uU z;Q-5IAc~ACc z0lwB?PF9GK79P*}{fCu@%xodVU`1MNHJq|(i`yq!sbN|(6&hI4VGNmhX|OypVPqPE ziauK{vYJezGw&UIqeo({W)Pz;F%Y(wCA>5ukvX@BXqlPcI_UpD;fElVxe^l5*??(F zhy?UVEH;`5L$h=|C*hgTJES9`?_&OS7>z#!|Hm^8iNf69AsvmxwD0gy5b`e&I4_U9 zr1nEP5_2Vl7?r`?^C1YwRAzw`cmS4QustooDCldQf4!SG29|(@9?xS`II+&t{Wt%? zhgkT=hnbnWr1e5N3UhKnjE=s-TdWw)giA5vVn<;7;lnX$=|0iO^d%nCmgWb62GeVa zVmkT)kI5L=Dw#1lp2k80r3zRX27y!E%E!lFp7`etBB#2sx2q5Q29p$CHLGrHAiql! zPdC)3;`OLBf*}spK{5@ePtxB=Ga%{HDTexncy0OrpTu5XTbt9*-|?V-&_NehPWa?c Pq7XS1v5JP~8#(_Eot;*<

  • {W}E9m^F-EUR-FK$dBROZS)bB+ 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�< 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 K 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