Пример #1
0
        /// <summary>
        /// Gets the translated code for the grammar structure.
        /// </summary>
        /// <returns>The translated code for the grammar structure.</returns>
        public IEnumerable <Block> Translate(TranslationContext context)
        {
            List <Block> output = new List <Block>();

            // Create scope of loop
            Scope innerScope = new Scope(context.CurrentScope);
            TranslationContext newContext = new TranslationContext(innerScope, context);

            // TODO: Inbuilt foreach block optimisation
            // TODO: Inline foreach

            // Create counter variable
            StackValue internalCounter = context.CurrentScope.CreateStackValue();

            output.AddRange(internalCounter.CreateDeclaration(1));

            // Create item variable
            StackValue itemVar = new StackValue(Variable, VarType, false);

            innerScope.StackValues.Add(itemVar);
            output.AddRange(itemVar.CreateDeclaration(VarType.GetDefault()));

            List <Block> loopContents = new List <Block>();

            GlobalListDeclaration globalList =
                context.CurrentSprite.GetList(SourceName) ?? context.Project.GetList(SourceName);
            StackValue arrayValue = null;

            if (globalList != null)
            {
                // Translate loop contents
                loopContents.Add(itemVar.CreateVariableAssignment(new Block(BlockSpecs.GetItemOfList,
                                                                            internalCounter.CreateVariableLookup(), SourceName)));
            }
            else
            {
                // Get stackvalue for array
                arrayValue = context.CurrentScope.Search(SourceName);

                if (arrayValue == null)
                {
                    context.ErrorList.Add(new CompilerError($"Array '{SourceName}' is not defined", ErrorType.NotDefined,
                                                            ErrorToken, FileName));
                    return(Enumerable.Empty <Block>());
                }

                loopContents.Add(itemVar.CreateVariableAssignment(arrayValue.CreateArrayLookup(internalCounter.CreateVariableLookup())));
            }

            // Increment counter
            loopContents.Add(internalCounter.CreateVariableIncrement(1));

            // Translate loop main body
            foreach (IEnumerable <Block> translated in Statements.Select(x => x.Translate(newContext)))
            {
                loopContents.AddRange(translated);
            }

            // Create loop Scratch block
            object repeats = globalList != null ? new Block(BlockSpecs.LengthOfList, SourceName) : (object)arrayValue.StackSpace;

            output.Add(new Block(BlockSpecs.Repeat, repeats, loopContents.ToArray()));

            // Clean up scope
            output.AddRange(internalCounter.CreateDestruction());
            output.AddRange(itemVar.CreateDestruction());

            return(output);
        }