protected void VarDefinitionNode(SymbolResolverVisitor visitor, VariableDefinitionNode vardecl)
        {
            foreach (var definition in vardecl.Definitions)
            {
                // Get the identifier name
                var variableName = definition.Left.Value;
                var storage      = SymbolHelper.GetStorage(vardecl.Information.Mutability);

                // Check if the symbol is already defined
                if (visitor.SymbolTable.HasVariableSymbol(variableName))
                {
                    throw new SymbolException($"Symbol {variableName} is already defined.");
                }

                // If it is a variable definition, visit the right-hand side expression
                var rhsSymbol = definition.Right?.Visit(visitor);

                IVariable lhsSymbol = null;

                if (rhsSymbol == null)
                {
                    // Create the new symbol for the variable
                    var typeInfo = SymbolHelper.GetTypeSymbol(visitor.SymbolTable, visitor.Inferrer, vardecl.Information.Type);
                    lhsSymbol = visitor.SymbolTable.AddNewVariableSymbol(variableName, typeInfo, Access.Public, storage);
                }
                else
                {
                    visitor.SymbolTable.AddNewVariableSymbol(variableName, rhsSymbol.GetTypeSymbol(), Access.Public, storage);
                }
            }
        }
        private void CreateParameterSymbol(SymbolResolverVisitor visitor, Function functionSymbol, ParameterNode parameter)
        {
            // If the parameter's type is present use it, if not use an anonymous type
            var paramTypeSymbol = parameter.SymbolInfo.Type == null
                        ? visitor.Inferrer.NewAnonymousType()
                        : SymbolHelper.GetTypeSymbol(visitor.SymbolTable, visitor.Inferrer, parameter.SymbolInfo.Type);

            // Check if the parameter has storage modifiers
            var storage = SymbolHelper.GetStorage(parameter.SymbolInfo.Mutability);

            // Create the parameter symbol in the function's scope
            var boundSymbol = functionSymbol.CreateParameter(parameter.Name.Value, paramTypeSymbol, storage);

            if (paramTypeSymbol is Anonymous asym)
            {
                visitor.Inferrer.TrackSymbol(asym, boundSymbol);
            }
        }
        public ISymbol Visit(SymbolResolverVisitor visitor, ObjectPropertyNode node)
        {
            var storage = SymbolHelper.GetStorage(node.Information.Mutability);

            // Visit the property's value node
            var rhsSymbol = visitor.Visit(node.Value);

            if (rhsSymbol != null)
            {
                visitor.SymbolTable.AddNewVariableSymbol(node.Name.Value, rhsSymbol.GetTypeSymbol(), Access.Public, storage);
                return(rhsSymbol);
            }

            var typeSymbol = SymbolHelper.GetTypeSymbol(visitor.SymbolTable, visitor.Inferrer, node.Information.Type);

            // Create the symbol for the object's property
            visitor.SymbolTable.AddNewVariableSymbol(node.Name.Value, typeSymbol, Access.Public, storage);

            return(typeSymbol);
        }
        protected void VarDestructuringNode(SymbolResolverVisitor visitor, VariableDestructuringNode destrnode)
        {
            var types = destrnode.Right.Visit(visitor);

            foreach (var declaration in destrnode.Left)
            {
                if (declaration == null)
                {
                    continue;
                }

                // Get the identifier name
                var variableName = declaration.Value;

                // Check if the symbol is already defined
                if (visitor.SymbolTable.HasVariableSymbol(variableName))
                {
                    throw new SymbolException($"Symbol {variableName} is already defined.");
                }

                // If the type anotation is not specific (uses 'var'), we need to create an anonymous type
                // for every variable. If not, we just get the type information from the token
                var varType = destrnode.Information.Type.Type == Syntax.TokenType.Variable
                    ? visitor.Inferrer.NewAnonymousType()
                    : SymbolHelper.GetTypeSymbol(visitor.SymbolTable, visitor.Inferrer, destrnode.Information.Type);

                // Create the new symbol for the variable
                var boundSymbol = visitor.SymbolTable.AddNewVariableSymbol(variableName, varType, Access.Public, SymbolHelper.GetStorage(destrnode.Information.Mutability));

                if (varType is Anonymous asym)
                {
                    visitor.Inferrer.TrackSymbol(asym, boundSymbol);
                }
            }
        }