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)); }
public static void ThrowClassInheritanceCycleException(ClassNameTableItem classItem, FileInfo fileInfo) => throw new CompilerException($"Class {classItem.TypeIdent} is in inheritance cycle", fileInfo, classItem.Line, classItem.Column);
/// <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)); } } } } }