public override object VisitTypeDotExpression([NotNull] DoshikParser.TypeDotExpressionContext context) { SetWholeExpression(context); VisitChildren(context); _compilationContext.SetParsingAntlrContext(context); var node = new TypeDotExpressionNode(context); var foundType = GetTypeNameVisitor.Apply(_compilationContext, context.left); foundType.ThrowIfNotFound(_compilationContext); node.LeftType = foundType.DataType; if (context.rightIdentifier != null) { node.RightIdentifier = context.rightIdentifier.Text; } else { node.RightMethodCallData = new MethodCallExpressionNodeData(); GetMethodCallData(context.rightMethodCall, node.RightMethodCallData); } Sequence.Sequence.Add(node); return(null); }
// возвращает MethodDeclarationParameter public override object VisitFormalParameter([NotNull] DoshikParser.FormalParameterContext context) { _compilationContext.SetParsingAntlrContext(context); var parameter = new MethodDeclarationParameter(_currentMethodDeclaration.Parameters); var scope = parameter.Parent.Scope; parameter.IsOutput = context.OUT() != null; var foundType = GetTypeNameVisitor.Apply(_compilationContext, context.typeType()); foundType.ThrowIfNotFound(_compilationContext); var variable = new Variable(parameter) { Type = foundType.DataType, Name = context.parameterName.Text }; if (scope.FindVariableByName(variable.Name, true) != null) { throw _compilationContext.ThrowCompilationError($"parameter { variable.Name } is already defined"); } scope.Variables[variable.Name] = variable; parameter.Variable = variable; return(parameter); }
private IEnumerable <DataType> GetTypeArguments(DoshikParser.TypeArgumentsContext typeArgumentsCtx) { if (typeArgumentsCtx == null) { yield break; } foreach (var typeArgumentCtx in typeArgumentsCtx.typeArgument()) { var foundType = GetTypeNameVisitor.Apply(_compilationContext, typeArgumentCtx.typeType()); foundType.ThrowIfNotFound(_compilationContext); yield return(foundType.DataType); } }
public override object VisitTypeOfExpression([NotNull] DoshikParser.TypeOfExpressionContext context) { SetWholeExpression(context); VisitChildren(context); _compilationContext.SetParsingAntlrContext(context); var node = new TypeOfExpressionNode(context); var foundType = GetTypeNameVisitor.Apply(_compilationContext, context.typeOf().typeType()); foundType.ThrowIfNotFound(_compilationContext); node.Type = foundType.DataType; Sequence.Sequence.Add(node); return(null); }
// возвращает LocalVariableDeclarationStatement public override object VisitLocalVariableDeclaration([NotNull] DoshikParser.LocalVariableDeclarationContext context) { _compilationContext.SetParsingAntlrContext(context); var statement = new LocalVariableDeclarationStatement(_currentNode); statement.Variable = new Variable(statement); var foundType = GetTypeNameVisitor.Apply(_compilationContext, context.typeType()); foundType.ThrowIfNotFound(_compilationContext); statement.Variable.Type = foundType.DataType; _declaringVariable = statement.Variable; _currentExpressionParent = statement; // Он инициализирует _declaringVariable Visit(context.variableDeclarator()); // Добавляем переменную ПОСЛЕ выполнения инициализации, таким образом при выполнении выражения инициализации эта переменная еще будет недоступна для референеса // то есть нельзя будет сделать так int a = a + 1; // этим отличается инициализация переменной от обычного присваивания, где референсить присваемую переменную можно _currentScope.Variables.Add(statement.Variable.Name, statement.Variable); statement.Initializer = _declaringVariableInitializerExpression; if (statement.Initializer == null && IsInsideOfLoop()) { // Если инициализатор не задан (то есть переменная объявлена без инициализирующего выражения) // и при этом мы находимся в теле цикла // то создаем неявное инициализирующее выражение = default(T), где T = statement.Variable.Type statement.Initializer = ExpressionBuilder.BuildDefaultOfType(_compilationContext, _currentExpressionParent, statement.Variable.Type); // это нужно, чтобы при объявлении локальной переменной в теле цикла при любой итерации цикла она имела дефолтное значение, если // ей не был указан инициализатор, иначе получится что ее значение будет переиспользоватья с предыдущей итерации // впринципе можно в любом случае делать этот искусственный инициализатор (даже если не в цикле), но вроде как если переменная // не находится в цикле то ее значение всегда будет дефолтным, если не было инициализатора // возможно это изменится при реализации рекурсивных юзерских функций } return(statement); }
private void HandleEventDeclaration( DoshikParser.TypeTypeOrVoidContext eventReturnTypeCtx, string eventCodeName, DoshikParser.FormalParametersContext eventParametersCtx, DoshikParser.BlockContext eventBodyCtx ) { var eventDeclaration = new EventDeclaration(_compilationContext.CompilationUnit); eventDeclaration.Parameters = new MethodDeclarationParameters(eventDeclaration, _compilationContext.CompilationUnit.Scope); _currentMethodDeclaration = eventDeclaration; eventDeclaration.Name = eventCodeName; var foundType = GetTypeNameVisitor.Apply(_compilationContext, eventReturnTypeCtx); foundType.ThrowIfNotFound(_compilationContext); eventDeclaration.ReturnTypeOrVoid = foundType.DataType; eventDeclaration.ExternalEvent = _compilationContext.FindExternalApiEventByCodeName(eventDeclaration.Name); if (_compilationContext.CompilationUnit.Events.ContainsKey(eventDeclaration.Name)) { throw _compilationContext.ThrowCompilationError($"event handler { eventDeclaration.Name } is already defined"); } eventDeclaration.Parameters.Parameters.AddRange((List <MethodDeclarationParameter>)Visit(eventParametersCtx)); eventDeclaration.AntlrBody = eventBodyCtx; if (eventDeclaration.IsCustom) { ValidateCustomEvent(eventDeclaration); } else { ValidateBuiltInEvent(eventDeclaration); } _compilationContext.CompilationUnit.Events[eventDeclaration.Name] = eventDeclaration; }
public override object VisitNewCallExpression([NotNull] DoshikParser.NewCallExpressionContext context) { SetWholeExpression(context); VisitChildren(context); _compilationContext.SetParsingAntlrContext(context); var node = new NewCallExpressionNode(context); var newCallCtx = context.newCall(); var foundType = GetTypeNameVisitor.Apply(_compilationContext, newCallCtx.typeType()); foundType.ThrowIfNotFound(_compilationContext); node.Type = foundType.DataType; node.Parameters.AddRange(GetMethodCallParameters(newCallCtx.methodCallParams())); Sequence.Sequence.Add(node); return(null); }
public override object VisitFieldDeclaration([NotNull] DoshikParser.FieldDeclarationContext context) { _compilationContext.SetParsingAntlrContext(context); var scope = _compilationContext.CompilationUnit.Scope; var variable = new CompilationUnitVariable(_compilationContext.CompilationUnit); variable.IsPublic = context.PUBLIC() != null; var foundType = GetTypeNameVisitor.Apply(_compilationContext, context.typeType()); foundType.ThrowIfNotFound(_compilationContext); variable.Type = foundType.DataType; (var variableName, var variableInitializer) = ((string, DoshikParser.VariableInitializerContext))Visit(context.variableDeclarator()); variable.Name = variableName; if (variableInitializer != null) { // ToDo: потом можно сделать инициализаторы полей. Прикол тут в том что их нельзя инициализировать также // как локальные переменные в statement-ах, потому что тут нет порядка выполнения операций, а значит // в инициализирующем выражении первой переменной может быть зареференшена вторвая переменная а в инициализации второй переменной референс на первую // таким образом будет circular reference. И такие вещи нужно определять, для этого нужно сортировать эти определения переменных и инициализировать их // в порядке начиная от меньшего количества референсов на другие переменные в инициализаторе до больших + трекать как то circular референсы. // Из-за того что тут такой гимор, я решил пока не делать инициализаторы (инициализировать переменные все равно можно будет вручную на событии Start или как там его) throw _compilationContext.ThrowCompilationError($"field initializer is not supported yet"); } if (scope.FindVariableByName(variable.Name, true) != null) { throw _compilationContext.ThrowCompilationError($"variable { variable.Name } is already defined"); } scope.Variables[variable.Name] = variable; return(null); }