Пример #1
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);
        }
Пример #2
0
        /// <summary>
        /// This method type checks the AssignmentNode node in the AST.
        /// </summary>
        /// <param name="assignmentNode">The node to check.</param>
        /// <returns>Returns null</returns>
        public override object Visit(AssignmentNode assignmentNode)
        {
            TypeContext lhs = (TypeContext)assignmentNode.LeftHand.Accept(this);
            TypeContext rhs;

            if (assignmentNode.RightHand.IsType(typeof(ArrayNode)))
            {
                ArrayNode arr = (ArrayNode)assignmentNode.RightHand;
                if (arr.HasBeenAccessed)
                {
                    if (lhs.Type == VAR)
                    {
                        arr.SymbolType = lhs = rhs = (TypeContext)arr.FirstAccess.RightHand.Accept(this);
                        assignmentNode.LeftHand.SymbolType = rhs;
                        assignmentNode.LeftHand.Type       = rhs.Type;
                    }
                    else
                    {
                        rhs = (TypeContext)arr.FirstAccess.RightHand.Accept(this);
                    }
                }
                else
                {
                    new InvalidTypeException($"Array type never set. Error at {arr.Line}:{arr.Offset}");
                    return(null);
                }
            }
            else
            {
                rhs = (TypeContext)assignmentNode.RightHand.Accept(this);
            }
            if (assignmentNode.RightHand.IsType(typeof(ArrayAccessNode)))
            {
                if (CurrentScope.FindArray((assignmentNode.LeftHand as ArrayAccessNode).Actual.ActualId.Id).Type == ARR)
                {
                    ArrayAccessNode node = (assignmentNode.LeftHand as ArrayAccessNode);
                    ArrayNode       arr  = CurrentScope.FindArray(node.Actual.ActualId.Id);
                    if (!(arr.Dimensions.Count >= node.Accesses.Count))
                    {
                        new OutOfRangeException($"Illegal access to {arr.Dimensions.Count} dimensional array. Error at {node.Line}:{node.Offset}");
                        return(null);
                    }
                    if (arr.Dimensions.Count > node.Accesses.Count && node.Accesses.Count > 1)
                    {
                        AssignmentNode declaringStatement = new AssignmentNode(node.Line, node.Offset);
                        declaringStatement.LeftHand =
                            new VarNode($"protected_declaration_{arr.ActualId.Id}_{node.Accesses.Count - 1}", new ScannerToken(node.Type, $"protected_declaration_{arr.ActualId.Id}_{node.Accesses.Count - 1}", node.Line, node.Offset))
                        {
                            IsArray = true, SymbolType = new TypeContext(node.Type)
                        };
                        ArrayNode declaringArray = new ArrayNode(node.Line, node.Offset);
                        for (int i = 0; i < node.Accesses.Count; i++)
                        {
                            declaringArray.Dimensions.Add(arr.Dimensions[i]);
                        }
                        ((IScope)assignmentNode.Parent).Statements.Insert(((IScope)assignmentNode.Parent).Statements.IndexOf(assignmentNode), declaringStatement);
                    }
                    node.Actual.FirstAccess.LeftHand.SymbolType = rhs;
                    node.Actual.FirstAccess.LeftHand.Type       = rhs.Type;
                    arr.SymbolType = rhs;
                    arr.Type       = rhs.Type;
                    lhs            = rhs;
                }
            }
            if (lhs.Type == VAR)
            {
                if (!CurrentScope.HasDeclaredVar(assignmentNode.LeftHand as AstNode))
                {
                    (assignmentNode.LeftHand as VarNode).Declaration = true;
                    CurrentScope.DeclaredVars.Add((assignmentNode.LeftHand as VarNode).Id);
                }

                if (assignmentNode.LeftHand.IsType(typeof(VarNode)))
                {
                    if (CurrentScope.FindSymbol(assignmentNode.LeftHand as VarNode).Type == VAR)
                    {
                        CurrentScope.UpdateTypedef(assignmentNode.LeftHand as VarNode, rhs, CurrentScope.Name, true);
                    }
                    lhs = CurrentScope.FindSymbol(assignmentNode.LeftHand as VarNode);
                }
                else if (assignmentNode.LeftHand.IsType(typeof(ArrayAccessNode)))
                {
                }
            }
            if (lhs.Type != rhs.Type)
            {
                if ((lhs.Type != DPIN && lhs.Type != APIN) || (rhs.Type != NUMERIC && rhs.Type != BOOL))
                {
                    new InvalidTypeException($"Type {rhs.Type} is not assignable toType {lhs.Type} at {assignmentNode.Line}:{assignmentNode.Offset}");
                }
            }


            return(null);
        }