private void CheckLevelAccessForRoutines(RoutineNameTableItem routine, ITerminalNode routineToken, string routineName) { foreach (var item in routine.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) { ThrowLevelAccessibilityForRoutineException(routineToken, ModuleData.File, customType.ToString(), routineName); } } } if (routine.ReturnType != null) { if (routine.ReturnType is SlangCustomType || routine.ReturnType is SlangPointerType) { var type = GetUserType(routine.ReturnType); var classItem = Table.Modules[type.ModuleName].Classes[type.Name]; if (classItem.AccessModifier == AccessModifier.Private) { ThrowLevelAccessibilityForRoutineException(routineToken, ModuleData.File, type.ToString(), routineName); } } } }
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 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 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); }
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); }
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; } }
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); }
private void WriteRoutineHeader(IndentedTextWriter writer, RoutineNameTableItem item) { writer.Write(GetStringFromType(item.ReturnType)); writer.Write($" {item.Name}"); WriteParameters(writer, item.Params); }
private void ValidateContext(SLangGrammarParser.ThisHeaderContext thisHeader, ITerminalNode id, SLangGrammarParser.ImportHeadContext importHead, ITerminalNode accessModifier, ITerminalNode abstractToken, ITerminalNode overrideToken, SLangGrammarParser.RoutineArgListContext routineArgList, SLangGrammarParser.TypeNameContext typeName, SLangGrammarParser.StatementSeqContext statementSeq) { var isMethod = thisHeader != null; var symbol = id.Symbol; string nameOfThis = string.Empty; if (isMethod) { nameOfThis = thisHeader.Id().GetText(); ThrowIfReservedWord(nameOfThis, ModuleData.File, thisHeader.Id().Symbol); if (importHead != null) { ThrowImportHeaderMethodsException(ModuleData.File, id); } } var name = id.GetText(); ThrowIfReservedWord(name, ModuleData.File, symbol); var args = Visit(routineArgList) as List <RoutineArgNameTableItem>; ImportHeader header = null; if (importHead != null) { header = Visit(importHead) as ImportHeader; } SlangType returnType = typeName != null?Visit(typeName) as SlangType : null; var modifier = GetModifierByName(accessModifier.GetText()); var isAbstract = abstractToken != null; var isOverride = overrideToken != null; if (!isMethod && (isAbstract || isOverride)) { ThrowRoutinesAbstractOverrideException(ModuleData.File, abstractToken ?? overrideToken); } if (header != null && statementSeq.statement().Length != 0) { ThrowImportHeaderException(ModuleData.File, id); } if (isMethod) { if (Visit(thisHeader) is SlangCustomType methodTypeIdent && methodTypeIdent.ModuleName != ModuleData.Name) { ThrowModuleFromOtherClassModuleException(id, ModuleData.File); } if (isAbstract) { ThrowIfAbstractMethodPrivate(modifier, ModuleData.File, id); } if ((args ?? throw new InvalidOperationException(nameof(args))).Any(a => a.Name == nameOfThis)) { ThrowConfictsThisException(thisHeader.Id(), ModuleData.File); } var classData = Visit(thisHeader) as SlangCustomType; var foundClass = Table.FindClass(classData); if (foundClass.Methods.ContainsKey(name)) { ThrowMethodSignatureExistsException(classData, id, ModuleData.File); } if (isAbstract && statementSeq.statement().Length != 0) { ThrowAbstractEmptyException(id, ModuleData.File); } var method = new MethodNameTableItem { AccessModifier = modifier, Column = symbol.Column, Header = header, IsAbstract = isAbstract, IsOverride = isOverride, Line = symbol.Line, Name = name, NameOfThis = nameOfThis, Params = args, ReturnType = returnType }; if (modifier == AccessModifier.Public) { CheckLevelAccessForMethods(method, id, classData); } foundClass.CheckRoutineConflicts(moduleItem.ModuleData, method); foundClass.Methods.Add(method.Name, method); } else { if (moduleItem.Routines.ContainsKey(name)) { ThrowRoutineExistsException(id, ModuleData.File); } var routine = new RoutineNameTableItem { AccessModifier = modifier, Column = symbol.Column, Line = symbol.Line, Header = header, Name = name, Params = args, ReturnType = returnType }; if (modifier == AccessModifier.Public) { CheckLevelAccessForRoutines(routine, id, name); } moduleItem.CheckCommonNamesConflicts(routine.Name, routine.Line, routine.Column); moduleItem.Routines.Add(routine.Name, routine); } }