Beispiel #1
0
        public bool VisitNode(VariableDeclaration node)
        {
            ASTNode nodeType;

            if (node.VarType.Type == ASTNodeType.Struct || node.VarType.Type == ASTNodeType.Enumeration)
            {
                // Check type, if its a struct or enum, visit that first.
                node.VarType.Outer = node.Outer;
                Success            = Success && node.VarType.AcceptVisitor(this);
                // Add the type to the list of types in the class.
                NodeUtils.GetContainingClass(node).TypeDeclarations.Add(node.VarType);
                nodeType = node.VarType;
            }
            else if (!Symbols.TryGetSymbol(node.VarType.Name, out nodeType, NodeUtils.GetOuterClassScope(node)))
            {
                return(Error("No type named '" + node.VarType.Name + "' exists in this scope!", node.VarType.StartPos, node.VarType.EndPos));
            }
            else if (!typeof(VariableType).IsAssignableFrom(nodeType.GetType()))
            {
                return(Error("Invalid variable type, must be a class/struct/enum/primitive.", node.VarType.StartPos, node.VarType.EndPos));
            }

            if (node.Outer.Type == ASTNodeType.Class)
            {
                int index = NodeUtils.GetContainingClass(node).VariableDeclarations.IndexOf(node);
                foreach (VariableIdentifier ident in node.Variables)
                {
                    if (Symbols.SymbolExistsInCurrentScope(ident.Name))
                    {
                        return(Error("A member named '" + ident.Name + "' already exists in this class!", ident.StartPos, ident.EndPos));
                    }
                    Variable variable = new Variable(node.Specifiers, ident, nodeType as VariableType, ident.StartPos, ident.EndPos);
                    variable.Outer = node.Outer;
                    Symbols.AddSymbol(variable.Name, variable);
                    NodeUtils.GetContainingClass(node).VariableDeclarations.Insert(index++, variable);
                }
                NodeUtils.GetContainingClass(node).VariableDeclarations.Remove(node);
            }
            else if (node.Outer.Type == ASTNodeType.Struct)
            {
                int index = (node.Outer as Struct).Members.IndexOf(node);
                foreach (VariableIdentifier ident in node.Variables)
                {
                    if (Symbols.SymbolExistsInCurrentScope(ident.Name))
                    {
                        return(Error("A member named '" + ident.Name + "' already exists in this struct!", ident.StartPos, ident.EndPos));
                    }
                    Variable variable = new Variable(node.Specifiers, ident, nodeType as VariableType, ident.StartPos, ident.EndPos);
                    variable.Outer = node.Outer;
                    Symbols.AddSymbol(variable.Name, variable);
                    (node.Outer as Struct).Members.Insert(index++, variable);
                }
                (node.Outer as Struct).Members.Remove(node);
            }

            return(Success);
        }
Beispiel #2
0
        public SymbolReference TryParseBasicRef(Expression compositeOuter = null)
        {
            Func <ASTNode> refParser = () =>
            {
                var token = Tokens.ConsumeToken(TokenType.Word);
                if (token == null)
                {
                    return(null);
                }

                ASTNode         symbol = null;
                FunctionCall    func   = compositeOuter as FunctionCall;
                SymbolReference outer  = compositeOuter as SymbolReference;

                if (func != null)
                {
                    var containingClass = NodeUtils.GetContainingClass(func.ResolveType().Declaration);
                    if (!Symbols.TryGetSymbolFromSpecificScope(token.Value, out symbol, containingClass.GetInheritanceString() + "." + func.Function.Name))
                    {
                        return(Error("Left side has no member named '" + func.Function.Name + "'!", token.StartPosition, token.EndPosition));
                    }
                }
                else if (outer != null)
                {
                    var containingClass = NodeUtils.GetContainingClass(outer.ResolveType().Declaration);
                    if (!Symbols.TryGetSymbolFromSpecificScope(token.Value, out symbol, containingClass.GetInheritanceString() + "." + outer.ResolveType().Name))
                    {
                        return(Error("Left side has no member named '" + outer.Name + "'!", token.StartPosition, token.EndPosition));
                    }
                }
                else
                {
                    if (!Symbols.TryGetSymbol(token.Value, out symbol, NodeUtils.GetOuterClassScope(Node)))
                    {
                        return(Error("No symbol named '" + token.Value + "' exists in the current scope!", token.StartPosition, token.EndPosition));
                    }
                }

                return(new SymbolReference(symbol, token.StartPosition, token.EndPosition, token.Value));
            };

            return((SymbolReference)Tokens.TryGetTree(refParser));
        }
        public bool VisitNode(Function node)
        {
            if (Pass == ValidationPass.TypesAndFunctionNamesAndStateNames)
            {
                if (Symbols.SymbolExistsInCurrentScope(node.Name))
                {
                    return(Error($"The name '{node.Name}' is already in use in this class!", node.StartPos, node.EndPos));
                }

                Symbols.AddSymbol(node.Name, node);
                return(Success);
            }

            if (Pass == ValidationPass.ClassAndStructMembersAndFunctionParams)
            {
                if (node.ReturnType != null && !Symbols.TryResolveType(ref node.ReturnType))
                {
                    return(Error($"No type named '{node.ReturnType.Name}' exists!", node.ReturnType.StartPos, node.ReturnType.EndPos));
                }

                Symbols.PushScope(node.Name);
                foreach (FunctionParameter param in node.Parameters)
                {
                    param.Outer = node;
                    Success     = Success && param.AcceptVisitor(this);
                }
                Symbols.PopScope();

                if (Success == false)
                {
                    return(Error("Error in function parameters.", node.StartPos, node.EndPos));
                }

                string parentScope     = null;
                Class  containingClass = NodeUtils.GetContainingClass(node);
                if (node.Outer.Type == ASTNodeType.State)
                {
                    parentScope = containingClass.Name;
                }
                else if (containingClass.Parent != null)
                {
                    parentScope = containingClass.Parent.Name;
                }

                if (parentScope != null && Symbols.TryGetSymbolInScopeStack(node.Name, out ASTNode func, parentScope) && // override functions in parent classes only (or current class if its a state)
                    func.Type == ASTNodeType.Function)
                {   // If there is a function with this name that we should override, validate the new functions declaration
                    Function original = (Function)func;
                    if (original.Flags.Has(FunctionFlags.Final))
                    {
                        return(Error($"{node.Name} overrides a function in a parent class, but the parent function is marked as final!", node.StartPos, node.EndPos));
                    }
                    if (!Equals(node.ReturnType, original.ReturnType))
                    {
                        return(Error($"{node.Name} overrides a function in a parent class, but the functions do not have the same return types!", node.StartPos, node.EndPos));
                    }
                    if (node.Parameters.Count != original.Parameters.Count)
                    {
                        return(Error($"{node.Name} overrides a function in a parent class, but the functions do not have the same number of parameters!", node.StartPos, node.EndPos));
                    }
                    for (int n = 0; n < node.Parameters.Count; n++)
                    {
                        if (node.Parameters[n].Type != original.Parameters[n].Type)
                        {
                            return(Error($"{node.Name} overrides a function in a parent class, but the functions do not have the same parameter types!", node.StartPos, node.EndPos));
                        }
                    }
                }

                return(Success);
            }
            return(Success);
        }
        public bool VisitNode(Struct node)
        {
            if (Pass == ValidationPass.TypesAndFunctionNamesAndStateNames)
            {
                if (!Symbols.TryAddType(node))
                {
                    //Structs do not have to be globally unique, but they do have to be unique within a scope
                    if (((IObjectType)node.Outer).TypeDeclarations.Any(decl => decl != node && decl.Name.CaseInsensitiveEquals(node.Name)))
                    {
                        return(Error($"A type named '{node.Name}' already exists in this {node.Outer.GetType().Name.ToLower()}!", node.StartPos, node.EndPos));
                    }
                }

                Symbols.PushScope(node.Name);

                //register types of inner structs
                foreach (VariableType typeDeclaration in node.TypeDeclarations)
                {
                    typeDeclaration.Outer = node;
                    Success &= typeDeclaration.AcceptVisitor(this);
                }

                Symbols.PopScope();

                return(Success);
            }

            if (Pass == ValidationPass.ClassAndStructMembersAndFunctionParams)
            {
                string parentScope = null;
                if (node.Parent != null)
                {
                    node.Parent.Outer = node;
                    if (!Symbols.TryResolveType(ref node.Parent))
                    {
                        return(Error($"No parent struct named '{node.Parent.Name}' found!", node.Parent.StartPos, node.Parent.EndPos));
                    }

                    if (node.Parent.Type != ASTNodeType.Struct)
                    {
                        return(Error($"Parent named '{node.Parent.Name}' is not a struct!", node.Parent.StartPos, node.Parent.EndPos));
                    }

                    parentScope = $"{NodeUtils.GetContainingClass(node.Parent).GetInheritanceString()}.{node.Parent.Name}";
                }

                Symbols.PushScope(node.Name, parentScope);

                //second pass for inner struct members
                foreach (VariableType typeDeclaration in node.TypeDeclarations)
                {
                    Success &= typeDeclaration.AcceptVisitor(this);
                }

                // TODO: can all types of variable declarations be supported in a struct?
                // what does the parser let through?
                foreach (VariableDeclaration decl in node.VariableDeclarations)
                {
                    decl.Outer = node;
                    Success    = Success && decl.AcceptVisitor(this);
                }

                Symbols.PopScope();

                node.Declaration = node;

                return(Success);
            }

            if (Pass == ValidationPass.BodyPass)
            {
                if (node.Parent != null && ((Struct)node.Parent).SameOrSubStruct(node.Name))
                {
                    return(Error($"Extending from '{node.Parent.Name}' causes circular extension!", node.Parent.StartPos, node.Parent.EndPos));
                }
                //TODO
                return(Success);
            }
            return(Success);
        }