Example #1
0
        public static string GetSubrutineKey(this injectionParser.SubrutineContext context)
        {
            var parameterCount = context.parameters()?.parameterName()?.Length ?? 0;
            var name           = context.subrutineName().GetText();

            return($"{name}`{parameterCount}");
        }
Example #2
0
        public override bool VisitSubrutine([NotNull] injectionParser.SubrutineContext context)
        {
            ResetContext();
            StartValidContext();

            base.VisitSubrutine(context);

            EndContext();

            return(true);
        }
Example #3
0
        public override Metadata VisitSubrutine([NotNull] injectionParser.SubrutineContext context)
        {
            if (!string.IsNullOrEmpty(context.subrutineName()?.GetText()))
            {
                var generator = new Generator();
                generator.Visit(context);

                metadata.Add(new SubrutineDefinition(context.subrutineName().GetText(), context, generator.Instructions));
            }

            return(metadata);
        }
Example #4
0
        public override bool VisitSubrutine([NotNull] injectionParser.SubrutineContext context)
        {
            base.VisitSubrutine(context);

            foreach (var key in gotos.Keys)
            {
                if (labels.TryGetValue(key, out var labelIndex))
                {
                    foreach (var g in gotos[key])
                    {
                        g.TargetAddress = labelIndex;
                    }
                }
            }

            return(true);
        }
        public override bool VisitSubrutine([NotNull] injectionParser.SubrutineContext context)
        {
            varNames.Clear();
            declaredLabels.Clear();
            referencedLabels.Clear();

            var result = base.VisitSubrutine(context);

            foreach (var gotoContext in referencedLabels)
            {
                var labelName = gotoContext.SYMBOL().GetText();
                if (!declaredLabels.Contains(labelName))
                {
                    messages.Add(new Message(gotoContext.Start.Line, gotoContext.Start.Column, gotoContext.Stop.Line, gotoContext.Stop.Column,
                                             MessageSeverity.Warning, MessageCodes.UndefinedLabel,
                                             $"Label not found '{labelName}'."));
                }
            }

            return(result);
        }
Example #6
0
        public override bool VisitSubrutine([NotNull] injectionParser.SubrutineContext context)
        {
            subrutines.Add(context.GetSubrutineKey(), context);

            return(true);
        }
Example #7
0
        public InjectionValue CallSubrutine(injectionParser.SubrutineContext subrutine, InjectionValue[] argumentValues)
        {
            var forScopes     = new Stack <ForScope>();
            var repeatIndexes = new Stack <int>();

            semanticScope.Start();
            var parameters = subrutine.parameters()?.parameterName()?.Select(x => x.SYMBOL().GetText()).ToArray()
                             ?? Array.Empty <string>();

            for (int i = 0; i < parameters.Length; i++)
            {
                semanticScope.DefineVar(parameters[i], argumentValues[i]);
            }

            semanticScope.DefineGlobalVariables(metadata.GlobalVariables, globalVar => VisitExpression(globalVar.InitialValueExpression));

            var name = subrutine.subrutineName().GetText();
            var subrutineDefinition = metadata.GetSubrutine(name, parameters.Length);

            try
            {
                var instructionAddress = 0;
                while (instructionAddress < subrutineDefinition.Instructions.Length)
                {
                    var currentInstruction = subrutineDefinition.Instructions[instructionAddress];
                    var statement          = currentInstruction.Statement;

                    if (statement == null)
                    {
                        switch (currentInstruction)
                        {
                        case JumpInstruction jump:
                            instructionAddress = jump.TargetAddress;
                            break;
                        }

                        continue;
                    }

                    if (debugger != null)
                    {
                        var context = new StatementExecutionContext(instructionAddress, statement.Start.Line, currentFileName, statement, this);
                        debugger.BeforeStatement(context);
                    }

                    try
                    {
                        if (statement.returnStatement() != null)
                        {
                            return(Visit(statement.returnStatement()));
                        }
                        else if (statement.@if() != null)
                        {
                            var condition = Visit(statement.@if().expression());
                            if (condition == InjectionValue.False)
                            {
                                var ifInstruction = (IfInstruction)currentInstruction;
                                instructionAddress = ifInstruction.ElseAddress ?? ifInstruction.EndIfAddress;
                            }
                            else
                            {
                                instructionAddress++;
                            }
                        }
                        else if (statement.@for() != null)
                        {
                            instructionAddress++;
                            forScopes.Push(InterpretFor(instructionAddress, statement.@for(), semanticScope));
                        }
                        else if (statement.next() != null)
                        {
                            var forScope = forScopes.Peek();
                            if (!semanticScope.TryGetVar(forScope.VariableName, out var variable))
                            {
                                throw new ScriptFailedException($"Variable undefined - {forScope.VariableName}", subrutineDefinition.Instructions[instructionAddress].Statement.Start.Line);
                            }

                            if (variable < forScope.Range)
                            {
                                instructionAddress = forScope.StatementIndex;
                                variable           = variable + forScope.Step;
                                semanticScope.SetVar(forScope.VariableName, variable);
                            }
                            else
                            {
                                instructionAddress++;
                                forScopes.Pop();
                            }
                        }
                        else if (statement.repeat() != null)
                        {
                            instructionAddress++;
                            repeatIndexes.Push(instructionAddress);
                        }
                        else if (statement.until() != null)
                        {
                            var condition = Visit(statement.until().expression());
                            if (condition != InjectionValue.False)
                            {
                                instructionAddress++;
                                repeatIndexes.Pop();
                            }
                            else
                            {
                                instructionAddress = repeatIndexes.Peek();
                            }
                        }
                        else if (statement.@while() != null)
                        {
                            var whileInstruction = (WhileInstruction)currentInstruction;
                            var condition        = Visit(statement.@while().expression());

                            if (condition != InjectionValue.False)
                            {
                                instructionAddress++;
                            }
                            else
                            {
                                instructionAddress = whileInstruction.WendAddress;
                            }
                        }
                        else if (statement.@goto() != null)
                        {
                            var gotoInstruction = (GotoInstruction)currentInstruction;
                            instructionAddress = gotoInstruction.TargetAddress;
                        }
                        else
                        {
                            Visit(statement);
                            instructionAddress++;
                        }
                    }
                    catch (StatementFailedException ex)
                    {
                        throw new ScriptFailedException(ex.Message, statement.Start.Line, ex);
                    }
                    catch (ScriptFailedException)
                    {
                        throw;
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        throw new InternalInterpretationException(statement.Start.Line, ex);
                    }
                }

                if (debugger != null)
                {
                    debugger.BeforeStatement(
                        new StatementExecutionContext(instructionAddress, subrutine.END_SUB().Symbol.Line, currentFileName, null, this));
                }

                return(InjectionValue.Unit);
            }
            finally
            {
                semanticScope.End();
            }
        }
Example #8
0
 public InjectionValue CallSubrutine(injectionParser.SubrutineContext subrutine)
 => CallSubrutine(subrutine, Array.Empty <InjectionValue>());
Example #9
0
 internal SubrutineDefinition(string name, injectionParser.SubrutineContext subrutine, Instruction[] instructions)
 {
     Name         = name;
     Syntax       = subrutine;
     Instructions = instructions;
 }