Пример #1
0
 private void TranslateClassData(ClassNameTableItem typeData, AccessModifier modifier)
 {
     foreach (var item in typeData.GetItems(modifier))
     {
         if (item is MethodNameTableItem method)
         {
             TranslateMethodDecl(method);
         }
         else if (item is VariableNameTableItem field)
         {
             TranslateClassFieldDecl(field);
         }
     }
 }
        public override object VisitEmptyTypeDecl([NotNull] SLangGrammarParser.EmptyTypeDeclContext context)
        {
            var classItem = new ClassNameTableItem
            {
                TypeIdent      = new SlangCustomType(ModuleData.Name, context.Id().GetText()),
                AccessModifier = GetModifierByName(context.AccessModifier().GetText()),
                Base           = null,
                CanBeBase      = false,
                Column         = context.Id().Symbol.Column,
                Line           = context.Id().Symbol.Line,
                Header         = Visit(context.importHead()) as ImportHeader
            };

            moduleTable.CheckCommonNamesConflicts(classItem.Name, classItem.Line, classItem.Column);
            moduleTable.Classes[classItem.Name] = classItem;
            return(base.VisitEmptyTypeDecl(context));
        }
        public override object VisitTypeDecl([NotNull] SLangGrammarParser.TypeDeclContext context)
        {
            var className = context.Id().GetText();

            ThrowIfReservedWord(className, ModuleData.File, context.Id().Symbol);

            if (moduleTable.Classes.ContainsKey(className))
            {
                ThrowClassRedefinitionException(className, ModuleData.File, context.Id().Symbol);
            }

            var isBase   = context.Base() != null;
            var modifier = GetModifierByName(context.AccessModifier().GetText());

            var classItem = new ClassNameTableItem {
                TypeIdent = new SlangCustomType(ModuleData.Name, className), CanBeBase = isBase, Column = context.Id().Symbol.Column, Line = context.Id().Symbol.Line, AccessModifier = modifier
            };

            moduleTable.CheckCommonNamesConflicts(classItem.TypeIdent.Name, classItem.Line, classItem.Column);
            moduleTable.Classes[className] = classItem;
            return(base.VisitTypeDecl(context));
        }
        public override object VisitTypeDecl([NotNull] SLangGrammarParser.TypeDeclContext context)
        {
            var classItem = moduleItem.Classes[context.Id().GetText()];

            if (context.typeInherit() != null)
            {
                // Есть наследник
                classItem.Base = Visit(context.typeInherit().customType()) as SlangCustomType;
            }
            else
            {
                // Нету наследника, берем Object из System
                classItem.Base = Table.Modules[CompilerConstants.SystemModuleName].Classes[CompilerConstants.ObjectClassName].TypeIdent;
                CheckClassExists(CompilerConstants.SystemModuleName, CompilerConstants.ObjectClassName, context.Id().Symbol);
            }

            var errToken = context.Id().Symbol;

            if (classItem.Base != null && !Table.Modules[classItem.Base.ModuleName].Classes[classItem.Base.Name].CanBeBase)
            {
                ThrowClassNotMarkedAsBaseException(classItem.Base, ModuleData.File, errToken);
            }

            // store fields
            foreach (var fieldContext in context.typeFieldDecl())
            {
                var item   = Visit(fieldContext) as FieldNameTableItem;
                var expCtx = fieldContext.variableDecl().simpleDecl()?.exp() ?? fieldContext.variableDecl().ptrDecl()?.exp();
                if (expCtx != null)
                {
                    ThrowClassFieldExprException(ModuleData.File, expCtx.Start);
                }

                if (item != null)
                {
                    ThrowIfReservedWord(item.Name, ModuleData.File, fieldContext.variableDecl().Start);
                    if (classItem.Fields.ContainsKey(item.Name))
                    {
                        ThrowClassFieldAlreadyDefinedException(item.Name, context.Id().GetText(), ModuleData.File,
                                                               fieldContext.variableDecl().Start);
                    }

                    // check level of access
                    if (item.Type is SlangCustomType || item.Type is SlangPointerType)
                    {
                        ClassNameTableItem usedType = null;
                        if (item.Type is SlangCustomType t)
                        {
                            usedType = Table.FindClass(t);
                        }
                        else if (item.Type is SlangPointerType pt)
                        {
                            usedType = Table.FindClass(pt.PtrType);
                        }

                        // если поле класса публично, а тип поля приватный, но при этом тип поля не тип класса
                        if (usedType != null && item.AccessModifier == AccessModifier.Public && usedType.AccessModifier == AccessModifier.Private && (!usedType.TypeIdent.Equals(classItem.TypeIdent)))
                        {
                            ThrowLevelAccessibilityForFieldsException(fieldContext.variableDecl().Start,
                                                                      ModuleData.File, usedType.TypeIdent.ToString(), item.Name);
                        }
                    }

                    classItem.CheckFieldConflicts(ModuleData, item);
                    classItem.Fields.Add(item.Name, item);
                }
            }

            return(base.VisitTypeDecl(context));
        }
Пример #5
0
 public static void ThrowClassInheritanceCycleException(ClassNameTableItem classItem, FileInfo fileInfo) => throw new CompilerException($"Class {classItem.TypeIdent} is in inheritance cycle", fileInfo, classItem.Line, classItem.Column);
Пример #6
0
        /// <summary>
        /// Base checks for base and derived classes
        /// 1) Check abstract and override methods
        /// 2) Checks fields overriding
        /// 3) Add notes about methods from base classes
        /// </summary>
        /// <param name="baseClass">Item for base class</param>
        /// <param name="derivedClass">Item for derived class</param>
        private void CheckClass(ClassNameTableItem baseClass, ClassNameTableItem derivedClass)
        {
            // check fields
            foreach (var item in baseClass.Fields)
            {
                if (item.Value.AccessModifier == AccessModifier.Public)
                {
                    if (derivedClass.Fields.ContainsKey(item.Key))
                    {
                        var field = derivedClass.Fields[item.Key];
                        ThrowClassFieldOverrideException(item.Key, baseClass.TypeIdent, derivedClass.TypeIdent, GetFileOfClass(derivedClass.TypeIdent), field.Line, field.Column);
                    }

                    if (item.Value.Clone() is FieldNameTableItem cloneField)
                    {
                        cloneField.IsDerived = true;
                        derivedClass.Fields.Add(item.Key, cloneField);
                    }
                }
            }
            // check methods
            // method marked override but does not override
            foreach (var item in derivedClass.Methods.Values)
            {
                if (item.IsOverride)
                {
                    if (!baseClass.Methods.Values.Any(i => i.Name == item.Name && i.Params.SequenceEqual(item.Params)))
                    {
                        ThrowClassMethodDoesNotOverrideException(item, GetFileOfClass(derivedClass.TypeIdent));
                        return;
                    }
                }
            }

            foreach (var item in baseClass.Methods.Values)
            {
                // для каждого публичного метода из базового класса проверяем, есть ли перегрузка
                // если есть -- то базовый метод нет смысла добавлять
                if (item.AccessModifier == AccessModifier.Public)
                {
                    if (!derivedClass.Methods.Values.Any(i => i.Name == item.Name && i.Params.SequenceEqual(item.Params)))
                    {
                        if (item.Clone() is MethodNameTableItem copy)
                        {
                            copy.IsDerived = true;

                            if (!derivedClass.Methods.ContainsKey(copy.Name))
                            {
                                derivedClass.Methods.Add(copy.Name, copy);
                            }
                            else
                            {
                                ThrowConflictMethodException(GetFileOfClass(derivedClass.TypeIdent),
                                                             derivedClass.TypeIdent.ToString(), derivedClass.Line, derivedClass.Column);
                            }
                        }
                    }
                    else
                    {
                        var methodOverriden = derivedClass.Methods.Values.First(i => i.Name == item.Name && i.Params.SequenceEqual(item.Params));
                        if (!methodOverriden.IsOverride)
                        {
                            ThrowClassMethodNotMarkedOverrideException(methodOverriden, GetFileOfClass(derivedClass.TypeIdent));
                        }
                    }
                }
            }
        }