Advertisement
Guest User

Untitled

a guest
Jun 18th, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.26 KB | None | 0 0
  1. package br.ufpe.cin.if688.minijava.visitor;
  2.  
  3.  
  4. import br.ufpe.cin.if688.minijava.ast.And;
  5. import br.ufpe.cin.if688.minijava.ast.ArrayAssign;
  6. import br.ufpe.cin.if688.minijava.ast.ArrayLength;
  7. import br.ufpe.cin.if688.minijava.ast.ArrayLookup;
  8. import br.ufpe.cin.if688.minijava.ast.Assign;
  9. import br.ufpe.cin.if688.minijava.ast.Block;
  10. import br.ufpe.cin.if688.minijava.ast.BooleanType;
  11. import br.ufpe.cin.if688.minijava.ast.Call;
  12. import br.ufpe.cin.if688.minijava.ast.ClassDeclExtends;
  13. import br.ufpe.cin.if688.minijava.ast.ClassDeclSimple;
  14. import br.ufpe.cin.if688.minijava.ast.Exp;
  15. import br.ufpe.cin.if688.minijava.ast.False;
  16. import br.ufpe.cin.if688.minijava.ast.Formal;
  17. import br.ufpe.cin.if688.minijava.ast.Identifier;
  18. import br.ufpe.cin.if688.minijava.ast.IdentifierExp;
  19. import br.ufpe.cin.if688.minijava.ast.IdentifierType;
  20. import br.ufpe.cin.if688.minijava.ast.If;
  21. import br.ufpe.cin.if688.minijava.ast.IntArrayType;
  22. import br.ufpe.cin.if688.minijava.ast.IntegerLiteral;
  23. import br.ufpe.cin.if688.minijava.ast.IntegerType;
  24. import br.ufpe.cin.if688.minijava.ast.LessThan;
  25. import br.ufpe.cin.if688.minijava.ast.MainClass;
  26. import br.ufpe.cin.if688.minijava.ast.MethodDecl;
  27. import br.ufpe.cin.if688.minijava.ast.Minus;
  28. import br.ufpe.cin.if688.minijava.ast.NewArray;
  29. import br.ufpe.cin.if688.minijava.ast.NewObject;
  30. import br.ufpe.cin.if688.minijava.ast.Not;
  31. import br.ufpe.cin.if688.minijava.ast.Plus;
  32. import br.ufpe.cin.if688.minijava.ast.Print;
  33. import br.ufpe.cin.if688.minijava.ast.Program;
  34. import br.ufpe.cin.if688.minijava.ast.This;
  35. import br.ufpe.cin.if688.minijava.ast.Times;
  36. import br.ufpe.cin.if688.minijava.ast.True;
  37. import br.ufpe.cin.if688.minijava.ast.Type;
  38. import br.ufpe.cin.if688.minijava.ast.VarDecl;
  39. import br.ufpe.cin.if688.minijava.ast.While;
  40. import br.ufpe.cin.if688.minijava.symboltable.Class;
  41. import br.ufpe.cin.if688.minijava.symboltable.Method;
  42. import br.ufpe.cin.if688.minijava.symboltable.SymbolTable;
  43. import br.ufpe.cin.if688.minijava.symboltable.Variable;
  44.  
  45. public class TypeCheckVisitor implements IVisitor<Type> {
  46.  
  47.     private SymbolTable symbolTable;
  48.     private Class currClass;
  49.     private Method currMethod;
  50.     private errorMessage err;
  51.    
  52.     public TypeCheckVisitor(SymbolTable st) {
  53.         err = new errorMessage();
  54.         symbolTable = st;
  55.        
  56.     }
  57.  
  58.     /*Aqui temos que definir as regras que vamos checar:
  59.      * . Métodos retornam oque foi declarado  
  60.      * . If é um boolean
  61.      * . While é um boolean
  62.      * . O valor assignado para uma variável é do mesmo tipo que o declarado
  63.      * . Ao tentar acessar um index, o número usado é um inteiro
  64.      * . O valor assignado para um array é do mesmo tipo que o declarado
  65.      * . Numa chamada de função, os parâmetros devem ser do mesmo tipo e na mesma quantidade que declarados
  66.      */
  67.    
  68.     /* Outros detalhes de implementação:
  69.      *   Numa call, nós temos que mudar o currClass para a classe onde está presente o método sendo chamado, para que possamos checar as
  70.      *   variáveis usadas no escopo certo
  71.      *
  72.      *  Consequentemente num identifier temos que ver se a variável é de um método, classe, parâmetro ou outra coisa, para dar o Get na
  73.      *  SymbolTable
  74.      */
  75.    
  76.     public Type visit(Program n) {
  77.        
  78.         n.m.accept(this);
  79.         for (int i = 0; i < n.cl.size(); i++) {
  80.             n.cl.elementAt(i).accept(this);
  81.         }
  82.        
  83.         return null;
  84.     }
  85.  
  86.     public Type visit(MainClass n) {
  87.        
  88.         currClass = symbolTable.getClass(n.i1.s);
  89.         currMethod = symbolTable.getMethod("main", currClass.getId());
  90.        
  91.         n.i1.accept(this);
  92.         n.i2.accept(this);
  93.         n.s.accept(this);
  94.         currClass = null;
  95.         currMethod = null;
  96.         return null;
  97.     }
  98.  
  99.     public Type visit(ClassDeclSimple n) {
  100.        
  101.         currClass = symbolTable.getClass(n.i.s);
  102.        
  103.         n.i.accept(this);
  104.         for (int i = 0; i < n.vl.size(); i++) {
  105.             n.vl.elementAt(i).accept(this);
  106.         }
  107.         for (int i = 0; i < n.ml.size(); i++) {
  108.             n.ml.elementAt(i).accept(this);
  109.         }
  110.        
  111.         currClass = null;
  112.         return null;
  113.     }
  114.  
  115.    
  116.     public Type visit(ClassDeclExtends n) {
  117.        
  118.         currClass = symbolTable.getClass(n.i.s);
  119.         n.i.accept(this);
  120.         n.j.accept(this);
  121.         for (int i = 0; i < n.vl.size(); i++) {
  122.             n.vl.elementAt(i).accept(this);
  123.         }
  124.         for (int i = 0; i < n.ml.size(); i++) {
  125.             n.ml.elementAt(i).accept(this);
  126.         }
  127.        
  128.         currClass = null;
  129.         return null;
  130.     }
  131.  
  132.     public Type visit(VarDecl n) {
  133.        
  134.         n.i.accept(this);
  135.         return n.t.accept(this);
  136.     }
  137.  
  138.     public Type visit(MethodDecl n) {
  139.         //Temos que checar se o return é do mesmo tipo que declarado
  140.        
  141.         currMethod = symbolTable.getMethod(n.i.s, currClass.getId());
  142.        
  143.         Type declaredType = n.t.accept(this);
  144.        
  145.         n.i.accept(this);
  146.         for (int i = 0; i < n.fl.size(); i++) {
  147.             n.fl.elementAt(i).accept(this);
  148.         }
  149.         for (int i = 0; i < n.vl.size(); i++) {
  150.             n.vl.elementAt(i).accept(this);
  151.         }
  152.         for (int i = 0; i < n.sl.size(); i++) {
  153.             n.sl.elementAt(i).accept(this);
  154.         }
  155.         Type returnedType = n.e.accept(this);
  156.        
  157.         if(!assertTypesAreEqual(returnedType, declaredType)) {
  158.             System.out.println("In method: " + currMethod.getId());
  159.             err.cannotConvert(declaredType, returnedType);
  160.             System.exit(0);
  161.         }
  162.         currMethod = null;
  163.         return declaredType;
  164.     }
  165.  
  166.     public Type visit(Formal n) {
  167.         n.i.accept(this);
  168.         return n.t.accept(this);
  169.     }
  170.  
  171.     public Type visit(IntArrayType n) {
  172.         return n;
  173.     }
  174.  
  175.     public Type visit(BooleanType n) {
  176.         return n;
  177.     }
  178.  
  179.     public Type visit(IntegerType n) {
  180.         return n;
  181.     }
  182.  
  183.     // String s;
  184.     public Type visit(IdentifierType n) {
  185.         return n;
  186.     }
  187.  
  188.     // StatementList sl;
  189.     public Type visit(Block n) {
  190.         for (int i = 0; i < n.sl.size(); i++) {
  191.             n.sl.elementAt(i).accept(this);
  192.         }
  193.         return null;
  194.     }
  195.  
  196.     // Exp e;
  197.     // Statement s1,s2;
  198.     public Type visit(If n) {
  199.         //Assert inside the if we got a boolean
  200.         Type statement1Type = n.s1.accept(this);
  201.         Type statement2Type = n.s2.accept(this);
  202.         Type expressionType = n.e.accept(this);
  203.    
  204.         if(!this.symbolTable.compareTypes(expressionType, new BooleanType())) {
  205.             err.notABoolean(expressionType);
  206.             System.exit(0);
  207.             return null;
  208.         }
  209.    
  210.         return null;
  211.     }
  212.  
  213.     // Exp e;
  214.     // Statement s;
  215.     public Type visit(While n) {
  216.         //Assert inside the while we got a boolean     
  217.         Type expressionType = n.e.accept(this);
  218.        
  219.         if(!this.symbolTable.compareTypes(expressionType, new BooleanType())) {
  220.             err.notABoolean(expressionType);
  221.             System.exit(0);
  222.             return null;
  223.         }
  224.         n.s.accept(this);
  225.         return null;
  226.     }
  227.  
  228.     // Exp e;
  229.     public Type visit(Print n) {
  230.         n.e.accept(this);
  231.         return null;
  232.     }
  233.  
  234.     // Identifier i;
  235.     // Exp e;
  236.     public Type visit(Assign n) {
  237.         //makes sure the variable is assigned to the type defined
  238.         Type typeDeclared = symbolTable.getVarType(currMethod, currClass, n.i.s);
  239.        
  240.         Type typeUsed = n.e.accept(this);
  241.        
  242.         if(!(assertTypesAreEqual(typeDeclared, typeUsed))) {
  243.             System.out.println("In variable : " + n.i.s);
  244.             err.cannotConvert(typeDeclared, typeUsed);
  245.             System.exit(0);
  246.         }
  247.         n.i.accept(this);
  248.         return null;
  249.     }
  250.  
  251.     // Identifier i;
  252.     // Exp e1,e2;
  253.     public Type visit(ArrayAssign n) {
  254.         //assert e2 is a integer
  255.         Type indexAcessor = n.e2.accept(this);
  256.        
  257.         if(!(indexAcessor instanceof IntegerType )) {
  258.             err.indexAcessorNotInt(indexAcessor);
  259.             return null;
  260.         }
  261.        
  262.         //assert the array is being used in the same type it as declared
  263.         Type variableDeclaredType = symbolTable.getVarType(currMethod, currClass, n.i.s);
  264.         Type variableBeingUsedType = n.i.accept(this);
  265.        
  266.         if(!(assertTypesAreEqual(variableDeclaredType, variableBeingUsedType))) {
  267.             System.out.println("In array : " + n.i.s);
  268.             err.cannotConvert(variableDeclaredType, variableBeingUsedType);
  269.             return null;
  270.         }
  271.        
  272.         n.e1.accept(this);
  273.         n.e2.accept(this);
  274.         return null;
  275.     }
  276.  
  277.     // Exp e1,e2;
  278.     public Type visit(And n) {
  279.         Type typeLeft = n.e1.accept(this);
  280.         Type typeRight = n.e2.accept(this);
  281.         Type bool = new BooleanType();
  282.         String op = "AND";
  283.         if(!assertTypesAreEqual(typeLeft, bool) && assertTypesAreEqual(typeRight, bool)) {
  284.             err.badOperands(typeLeft, typeRight, op);
  285.         }
  286.         return new BooleanType();
  287.     }
  288.  
  289.     // Exp e1,e2;
  290.     public Type visit(LessThan n) {
  291.         Type typeLeft = n.e1.accept(this);
  292.         Type typeRight = n.e2.accept(this);
  293.         Type integer = new IntegerType();
  294.         String op = "Less than ( < )";
  295.         if(!assertTypesAreEqual(typeLeft, integer) && assertTypesAreEqual(typeRight, integer)) {
  296.             err.badOperands(typeLeft, typeRight, op);
  297.         }
  298.         return new BooleanType();
  299.     }
  300.  
  301.     // Exp e1,e2;
  302.     public Type visit(Plus n) {
  303.         Type typeLeft = n.e1.accept(this);
  304.         Type typeRight = n.e2.accept(this);
  305.         Type integer = new IntegerType();
  306.         String op = "Plus";
  307.         if(!assertTypesAreEqual(typeLeft, integer) && assertTypesAreEqual(typeRight, integer)) {
  308.             err.badOperands(typeLeft, typeRight, op);
  309.         }
  310.         return new IntegerType();
  311.     }
  312.  
  313.     // Exp e1,e2;
  314.     public Type visit(Minus n) {
  315.         Type typeLeft = n.e1.accept(this);
  316.         Type typeRight = n.e2.accept(this);
  317.         Type integer = new IntegerType();
  318.         String op = "Minus";
  319.         if(!assertTypesAreEqual(typeLeft, integer) && assertTypesAreEqual(typeRight, integer)) {
  320.             err.badOperands(typeLeft, typeRight, op);
  321.         }
  322.         return new IntegerType();
  323.     }
  324.  
  325.     // Exp e1,e2;
  326.     public Type visit(Times n) {
  327.         Type typeLeft = n.e1.accept(this);
  328.         Type typeRight = n.e2.accept(this);
  329.         Type integer = new IntegerType();
  330.         String op = "Times";
  331.         if(!assertTypesAreEqual(typeLeft, integer) && assertTypesAreEqual(typeRight, integer)) {
  332.             err.badOperands(typeLeft, typeRight, op);
  333.         }
  334.         return new IntegerType();
  335.     }
  336.  
  337.     // Exp e1,e2;
  338.     public Type visit(ArrayLookup n) {
  339.         Type type1 = n.e1.accept(this);
  340.         Type type2 = n.e2.accept(this);
  341.         if(!(assertTypesAreEqual(type1, new IntArrayType()))) {
  342.             err.cannotConvert(type1, new IntArrayType());
  343.             System.exit(0);
  344.         }
  345.         if(!(assertTypesAreEqual(type2, new IntegerType()))) {
  346.             err.cannotConvert(type2, new IntegerType());
  347.             System.exit(0);
  348.         }
  349.         return new IntegerType();
  350.     }
  351.  
  352.     // Exp e;
  353.     public Type visit(ArrayLength n) {
  354.         Type type = n.e.accept(this);
  355.         if(!(assertTypesAreEqual(type, new IntArrayType()))) {
  356.             err.cannotConvert(type, new IntArrayType());
  357.             System.exit(0);
  358.         }
  359.         return new IntegerType();
  360.     }
  361.  
  362.     // Exp e;
  363.     // Identifier i;
  364.     // ExpList el;
  365.     public Type visit(Call n) {
  366.         //this is a complicated matter, we have to return the method being called return type
  367.         Type returnType = null;
  368.        
  369.         Type check = n.e.accept(this);
  370.         //if it is a method from itself
  371.         if(n.e instanceof This) {
  372.             returnType = currClass.getMethod(n.i.s).type();
  373.         }
  374.         else if(check instanceof IdentifierType) {
  375.             Class calledClass = this.symbolTable.getClass(((IdentifierType) check).s);
  376.             Method calledMethod = this.symbolTable.getMethod(n.i.toString(), calledClass.getId());
  377.             //this is important for the identifier accept to work
  378.             Class currentClass = this.currClass;
  379.             this.currClass = calledClass;
  380.            
  381.            
  382.             int i;
  383.             for ( i = 0; i < n.el.size(); i++) {
  384.                 Type parametersTypes = n.el.elementAt(i).accept(this);
  385.            
  386.                 Variable parametersDeclared = calledMethod.getParamAt(i);
  387.                 //check if there are enough parameters
  388.                 if(parametersDeclared == null) {
  389.                     err.parametersDifferInLength(calledMethod);
  390.                     System.exit(0);
  391.                     return null;
  392.                 }
  393.                 Type parametersDeclaredTypes = calledMethod.getParamAt(i).type();
  394.                 //check if the types match
  395.                 if(!(assertTypesAreEqual(parametersTypes, parametersDeclaredTypes))) {
  396.                     err.cannotConvert(parametersDeclaredTypes, parametersTypes);
  397.                     System.exit(0);
  398.                     return null;
  399.                 }
  400.             }
  401.             //check if there are parameters left
  402.             if(calledMethod.getParamAt(i) != null) {
  403.                 err.parametersDifferInLength(calledMethod);
  404.                 System.exit(0);
  405.                 return null;
  406.             }
  407.             Type idType = n.i.accept(this);
  408.             currClass = currentClass;
  409.             return idType;
  410.         }
  411.  
  412.         //the parameters
  413.        
  414.         return returnType;
  415.     }
  416.  
  417.     // int i;
  418.     public Type visit(IntegerLiteral n) {
  419.         return new IntegerType();
  420.     }
  421.  
  422.     public Type visit(True n) {
  423.         return new BooleanType();
  424.     }
  425.  
  426.     public Type visit(False n) {
  427.         return new BooleanType();
  428.     }
  429.  
  430.     // String s;
  431.     public Type visit(IdentifierExp n) {
  432.         Type t = symbolTable.getVarType(this.currMethod, this.currClass, n.s);
  433.         return t;
  434.     }
  435.  
  436.     public Type visit(This n) {
  437.         return currClass.type();
  438.     }
  439.  
  440.     // Exp e;
  441.     public Type visit(NewArray n) {
  442.         Type indexType = n.e.accept(this);
  443.        
  444.         if(!(assertTypesAreEqual(indexType, new IntegerType()))) {
  445.             err.cannotConvert(indexType, new IntegerType());
  446.             System.exit(0);
  447.         }
  448.         return new IntArrayType();
  449.     }
  450.  
  451.     // Iid.dentifier i;
  452.     public Type visit(NewObject n) {
  453.         return n.i.accept(this);
  454.     }
  455.  
  456.     // Exp e;
  457.     public Type visit(Not n) {
  458.         n.e.accept(this);
  459.         return null;
  460.     }
  461.  
  462.     // String s;
  463.     public Type visit(Identifier n) {
  464.  
  465.         if(currClass.containsVar(n.s)) {
  466.             return symbolTable.getVarType(currMethod, currClass, n.s);
  467.         }
  468.         if(currClass.containsMethod(n.s)) {
  469.             return symbolTable.getMethodType(n.s, currClass.getId());
  470.         }
  471.         if(currMethod != null && currMethod.containsVar(n.s)) {
  472.             return currMethod.getVar(n.s).type();
  473.         }
  474.         if(currMethod != null && currMethod.containsParam(n.s)) {
  475.             return currMethod.getParam(n.s).type();
  476.         }
  477.         else {
  478.             Class c = this.symbolTable.getClass(n.s);
  479.             if(c == null) {
  480.                 err.cannotFindVariable(n);
  481.                 System.exit(0);
  482.             }
  483.             return c.type();
  484.         }
  485.  
  486.     }
  487.    
  488.     public boolean assertTypesAreEqual(Type t1, Type t2) {
  489.         return symbolTable.compareTypes(t1, t2);
  490.     }
  491. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement