Ejemplo n.º 1
0
 /// <summary>
 /// This method type checks the ElseStatementNode node in the AST.
 /// </summary>
 /// <param name="elseStatement">The node to check.</param>
 /// <returns>Returns null</returns>
 public override object Visit(ElseStatementNode elseStatement)
 {
     CurrentScope = GlobalScope.FindChild($"ELSESTMNT_{elseStatement.Line}");
     elseStatement.Statements.ForEach(stmnt => stmnt.Accept(this));
     CurrentScope = CurrentScope?.Parent ?? GlobalScope;
     return(null);
 }
Ejemplo n.º 2
0
 /// <summary>
 /// This method type checks the FuncNode node in the AST.
 /// </summary>
 /// <param name="funcNode">The node to check.</param>
 /// <returns>Returns null</returns>
 public override object Visit(FuncNode funcNode)
 {
     CurrentScope = GlobalScope.FindChild($"func_{funcNode.Name.Id}_{funcNode.Line}");
     funcNode.Statements.ForEach(stmnt =>
     {
         if (stmnt is CallNode)
         {
             if (((CallNode)stmnt).Id.Id == funcNode.Name.Id)
             {
                 new InvalidOperationException($"Illegal recursion at {stmnt.Line}:{stmnt.Offset}");
             }
         }
         stmnt.Accept(this);
     });
     if (funcNode.Statements.Any() && funcNode.Statements.Last().Type == TokenType.RETURN)
     {
         {
             funcNode.SymbolType = (TypeContext)funcNode.Statements.Last().Accept(this);
             CurrentScope        = CurrentScope.Parent ?? GlobalScope;
             return(funcNode.SymbolType);
         }
     }
     CurrentScope = CurrentScope.Parent ?? GlobalScope;
     return(null);
 }
Ejemplo n.º 3
0
        /// <summary>
        /// This method type checks the ForNode node in the AST.
        /// </summary>
        /// <param name="forNode">The node to check.</param>
        /// <returns>Returns null</returns>
        public override object Visit(ForNode forNode)
        {
            CurrentScope = GlobalScope.FindChild($"LOOPF_{forNode.Line}");
            TypeContext fromType = (TypeContext)forNode.From.Accept(this);
            TypeContext toType   = (TypeContext)forNode.To.Accept(this);

            if (null == CurrentScope.FindSymbol(forNode.CountingVariable))
            {
                CurrentScope.Symbols.Add(new Symbol(forNode.CountingVariable.Id, NUMERIC, false, forNode.CountingVariable));
            }
            else
            {
                CurrentScope.UpdateTypedef(forNode.CountingVariable, new TypeContext(TokenType.NUMERIC)
                {
                    IsFloat = false
                }, CurrentScope.Name, true);
            }
            if (fromType.Type != toType.Type)
            {
                new InvalidTypeException($"Mismatch in range types at {forNode.Line}:{forNode.Offset}");
            }
            forNode.Statements.ForEach(stmnt => stmnt.Accept(this));
            CurrentScope = CurrentScope.Parent ?? GlobalScope;
            return(null);
        }
Ejemplo n.º 4
0
 /// <summary>
 /// This method type checks the ElseIfStatementNode node in the AST.
 /// </summary>
 /// <param name="elseifStatementNode">The node to check.</param>
 /// <returns>Returns null</returns>
 public override object Visit(ElseifStatementNode elseifStatementNode)
 {
     CurrentScope = GlobalScope.FindChild($"{elseifStatementNode.Type}_{elseifStatementNode.Line}");
     if (((TypeContext)elseifStatementNode.Expression.Accept(this)).Type == BOOL)
     {
         elseifStatementNode.Statements.ForEach(stmnt => stmnt.Accept(this));
     }
     else
     {
         new InvalidTypeException($"Else if statement expected a boolean expression at {elseifStatementNode.Line}:{elseifStatementNode.Offset}");
     }
     CurrentScope = CurrentScope.Parent ?? GlobalScope;
     return(null);
 }
Ejemplo n.º 5
0
 /// <summary>
 /// This method type checks the CallNode node in the AST.
 /// </summary>
 /// <param name="callNode">The node to check.</param>
 /// <returns>Type context of the function called</returns>
 public override object Visit(CallNode callNode)
 {
     try
     {
         if (SymbolTableObject.FunctionDefinitions.Any(func => func.Name.Id == callNode.Id.Id && func.FunctionParameters.Count == callNode.Parameters.Count))
         {
             FuncNode    n = SymbolTableObject.FunctionDefinitions.First(node => node.Name.Id == callNode.Id.Id && node.FunctionParameters.Count == callNode.Parameters.Count);
             TypeContext ctx;
             if (n.Statements.Any())
             {
                 if (n.Statements.Last().IsType(typeof(ReturnNode)))
                 {
                     _temp        = CurrentScope;
                     CurrentScope = GlobalScope.FindChild($"func_{n.Name.Id}_{n.Line}");
                     ctx          = (TypeContext)n.Statements.Last().Accept(this);
                     CurrentScope = _temp;
                 }
                 else
                 {
                     ctx = new TypeContext(TokenType.FUNC);
                 }
             }
             else
             {
                 ctx = new TypeContext(TokenType.FUNC);
             }
             return(ctx);
         }
         else if (SymbolTableObject.PredefinedFunctions.Any(func => func.Name.Id == callNode.Id.Id && func.FunctionParameters.Count == callNode.Parameters.Count))
         {
             TypeContext ctx = SymbolTableObject.PredefinedFunctions.First(node => node.Name.Id == callNode.Id.Id && node.FunctionParameters.Count == callNode.Parameters.Count).SymbolType;
             return(ctx);
         }
         else
         {
             new NotDefinedException($"A function '{callNode.Id.Id}' with {callNode.Parameters.Count} parameters has not been defined. Error at {callNode.Line}:{callNode.Offset} ");
             return(null);
         }
     }
     catch
     {
         new NotDefinedException($"Undefined function call at {callNode.Line}:{callNode.Offset}");
         return(null);
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// This method type checks the ProgramNode node in the AST.
        /// This is the entry point for the type checker
        /// </summary>
        /// <param name="programNode">The node to check.</param>
        /// <returns>Returns null</returns>
        public override object Visit(ProgramNode programNode)
        {
            programNode.Statements.ForEach(stmnt => stmnt.Accept(this));
            programNode.FunctionDefinitons.ForEach(func =>
            {
                if (!(SymbolTableObject.FunctionDefinitions.Where(fn => fn.Name.Id == func.Name.Id && func.FunctionParameters.Count == fn.FunctionParameters.Count).Count() > 1))
                {
                    if (SymbolTableObject.FunctionCalls.Any(cn => cn.Id.Id == func.Name.Id && cn.Parameters.Count == func.FunctionParameters.Count))
                    {
                        CallNode cn             = SymbolTableObject.FunctionCalls.First(cn => cn.Id.Id == func.Name.Id && cn.Parameters.Count == func.FunctionParameters.Count);
                        FuncNode declaredFunc   = SymbolTableObject.FunctionDefinitions.First(fn => fn.Name.Id == func.Name.Id);
                        SymbolTableObject scope = GlobalScope.FindChild($"func_{declaredFunc.Name.Id}_{declaredFunc.Line}");
                        for (int i = 0; i < cn.Parameters.Count; i++)
                        {
                            if (cn.Parameters[i].SymbolType.Type == VAR)
                            {
                                continue;
                            }
                            scope.UpdateTypedef(declaredFunc.FunctionParameters[i], cn.Parameters[i].SymbolType, scope.Name, true);
                        }
                    }
                    func.Accept(this);
                }
                else
                {
                    new MultipleDefinedException($"A function '{func.Name.Id}' with {func.FunctionParameters.Count} parameters has already been defined. Error at {func.Line}:{func.Offset}");
                }
            });

            if (programNode.LoopFunction == null)
            {
                new NotDefinedException("Loop function was not defined.");
                return(null);
            }
            programNode.LoopFunction.Accept(this);
            return(null);
        }