public static BaseNameTableItem ByName(string name, Scope scope, RoutineNameTableItem currentRoutine, SlangCustomType currentType, ModuleNameTable moduleItem, SourceCodeTable table, Dictionary <string, bool> checkDefinitions) { var result = scope.FindVariable(name); // заходим во внешние блоки if (result == null) { // мы сейчас находимся в функции? if (currentRoutine != null && currentRoutine is { } routine) { // в методе? if (currentRoutine is MethodNameTableItem method) { // может это имя this метода? if (method.NameOfThis == name) { return(new VariableNameTableItem { IsConstant = false, Type = currentType, Name = name }); } } // неважно, в функции или методе -- проверяем его параметры foreach (var param in routine.Params) { if (param.Name == name) { return(new VariableNameTableItem { IsConstant = false, Type = param.TypeArg.Type, Name = name }); } } } if (moduleItem.Fields.ContainsKey(name) && (checkDefinitions != null ? checkDefinitions[name] : true)) { return(moduleItem.Fields[name]); } // либо это процедура-функция (взять все сигнатуры) ? if (moduleItem.Routines.ContainsKey(name) && (checkDefinitions != null ? checkDefinitions[name] : true)) { return(moduleItem.Routines[name]); } // ну либо это другой модуль? if (moduleItem.ImportedModules.Contains(name) || name == moduleItem.ModuleData.Name) { return(table.Modules[name]); } return(null); // иначе ничего не остается кроме как отдать пустоту } return(result); }
public override object VisitTypeDecl([NotNull] SLangGrammarParser.TypeDeclContext context) { checkDefinitions[context.Id().GetText()] = true; currentType = Table.FindClass(ModuleData.Name, context.Id().GetText()).TypeIdent; base.VisitTypeDecl(context); currentType = null; return(null); }
public override object VisitProcedureDecl([NotNull] SLangGrammarParser.ProcedureDeclContext context) { InitRoutines(context.thisHeader(), context.Id().GetText()); TranslateRoutines(context.statementSeq()); currentRoutine = null; currentType = null; return(null); }
public override object VisitModuleStatementsSeq([NotNull] SLangGrammarParser.ModuleStatementsSeqContext context) { // state -- work in module statements currentRoutine = null; inProgramBlock = true; currentType = null; //ToDo checks expressions in fields return(base.VisitModuleStatementsSeq(context)); }
public override object VisitProcedureDecl([NotNull] SLangGrammarParser.ProcedureDeclContext context) { var symbol = context.Id().Symbol; InitializeRoutineStates(context.thisHeader(), symbol); CheckParamsNameConflicts(context.thisHeader(), context.routineArgList()); // some work... need to call visit()? Visit(context.statementSeq()); currentType = null; currentRoutine = null; return(null); }
public override object VisitFunctionDecl([NotNull] SLangGrammarParser.FunctionDeclContext context) { // init states, check of abstract methods or imported functions // add entries in h & cpp // visit sequence InitRoutines(context.thisHeader(), context.Id().GetText()); TranslateRoutines(context.statementSeq()); currentRoutine = null; currentType = null; return(null); }
private void InitializeRoutineStates(SLangGrammarParser.ThisHeaderContext context, IToken symbol) { currentType = context != null?Visit(context.customType()) as SlangCustomType : null; if (currentType != null) { currentRoutine = Table.FindClass(currentType).Methods[symbol.Text]; } else { currentRoutine = moduleItem.Routines[symbol.Text]; checkDefinitions[symbol.Text] = true; } }
/// <summary> /// return custom type for pointer and custom types /// </summary> /// <param name="type">type</param> /// <returns>custom type (if exists), else null</returns> private SlangCustomType GetUserType(SlangType type) { SlangCustomType usedType = null; if (type is SlangCustomType t) { usedType = t; } else if (type is SlangPointerType pt) { usedType = pt.PtrType; } return(usedType); }
private void InitRoutines(SLangGrammarParser.ThisHeaderContext thisHeader, string routineName) { if (thisHeader != null) { currentType = GetCustomTypeContext(thisHeader.customType()); } if (currentType != null) { currentRoutine = source.FindClass(currentType).Methods[routineName]; } else { currentRoutine = currentModule.Routines[routineName]; } }
public override object VisitFunctionDecl([NotNull] SLangGrammarParser.FunctionDeclContext context) { var symbol = context.Id().Symbol; InitializeRoutineStates(context.thisHeader(), symbol); CheckParamsNameConflicts(context.thisHeader(), context.routineArgList()); var result = Visit(context.statementSeq()) as StatementResult; // функция, которая не импортируется извне и не является абстрактным методом? if (result != null && !result.Returning && currentRoutine.Header == null && !(currentRoutine is MethodNameTableItem method && method.IsAbstract)) { ThrowNotAllCodePathException(file, context.statementSeq().Start); } currentType = null; currentRoutine = null; return(null); }
public bool TryFoundClassItemsByName(string name, SlangCustomType classContext, SlangCustomType destType, out BaseNameTableItem item) { item = null; bool result = true; // находимся в контексте этого типа if (classContext != null && classContext.Equals(destType)) { var classItem = FindClass(destType); if (classItem.Methods.ContainsKey(name)) { item = classItem.Methods[name]; } else if (classItem.Fields.ContainsKey(name)) { item = classItem.Fields[name]; } else { result = false; } } else { var classItem = FindClass(destType); if (classItem.Methods.ContainsKey(name) && classItem.Methods[name].AccessModifier == AccessModifier.Public) { item = classItem.Methods[name]; } else if (classItem.Fields.ContainsKey(name) && classItem.Fields[name].AccessModifier == AccessModifier.Public) { item = classItem.Fields[name]; } else { result = false; } } return(result); }
public static void ThrowClassItemNotFoundException(string msg, SlangCustomType typeIdent, FileInfo file, int line, int column) => ThrowException($"Item with name {msg} was not found in class {typeIdent}", file, line, column);
private void CheckLevelAccessForMethods(MethodNameTableItem method, ITerminalNode routineToken, SlangCustomType classIdent) { foreach (var item in method.Params) { var typeArg = item.TypeArg.Type; if (typeArg is SlangCustomType || typeArg is SlangPointerType) { var customType = GetUserType(typeArg); var classItem = Table.Modules[customType.ModuleName].Classes[customType.Name]; if (classItem.AccessModifier == AccessModifier.Private && !customType.Equals(classIdent)) { ThrowLevelAccessibilityForRoutineException(routineToken, ModuleData.File, customType.ToString(), method.Name); } } } if (method.ReturnType != null) { if (method.ReturnType is SlangCustomType type) { var classItem = Table.Modules[type.ModuleName].Classes[type.Name]; if (classItem.AccessModifier == AccessModifier.Private) { ThrowLevelAccessibilityForRoutineException(routineToken, ModuleData.File, type.ToString(), method.Name); } } } }
private FileInfo GetFileOfClass(SlangCustomType typeId) { return(Table.Modules[typeId.ModuleName].ModuleData.File); }
public static void ThrowMethodSignatureExistsException(SlangCustomType classData, ITerminalNode name, FileInfo file) => ThrowException($"Method with same signature already exists in class {classData}", file, name.Symbol);
public static void ThrowInvalidUseIncompleteTypeException(SlangCustomType classItem, FileInfo file, IToken symbol) => ThrowException($"Invalid use of incomplete type {classItem}", file, symbol);
public static void ThrowClassNotMarkedAsBaseException(SlangCustomType classItem, FileInfo file, IToken symbol) => ThrowException($"Class {classItem} is not marked as base", file, symbol);
public SlangPointerType(SlangCustomType type) { PtrType = type; }
public static void ThrowClassFieldOverrideException(string fieldName, SlangCustomType baseClass, SlangCustomType derivedClass, FileInfo fileInfo, int line, int column) => throw new CompilerException($"Trying to override field {fieldName} from base class {baseClass} in derived class {derivedClass}", fileInfo, line, column);
public SlangPointerType() { PtrType = SlangCustomType.Object; }
public ClassNameTableItem FindClass(SlangCustomType type) { return(FindClass(type.ModuleName, type.Name)); }