public override bool CanInline(Context context, Scope scope, IStatement statement)
        {
            if (!(statement is VariableDefinitionStatement varDefStt))
            {
                throw new InvalidOperationException();
            }

            if (varDefStt.DefaultValue is EvaluationStatement defaultValue)
            {
                return(EvaluationStatementTranspilerBase.CanInlineEvaluation(context, scope, defaultValue));
            }

            return(true);
        }
Esempio n. 2
0
        private bool CalculatePreProcessorCondition(Token token, IPeekingEnumerator <Token> enumerator,
                                                    ParserContext context, bool parseCondition)
        {
            if (!enumerator.MoveNext())
            {
                throw EndOfFile(token, context);
            }

            token = enumerator.Current;
            if (token.Type != TokenType.OpenParenthesis)
            {
                throw UnexpectedToken(token, context, true);
            }

            if (!enumerator.MoveNext()) //read the first eval token
            {
                throw EndOfFile(token, context);
            }

            token = enumerator.Current;

            var evalStatement = Parser.ReadEvaluationStatement(token, enumerator, context);

            if (!enumerator.MoveNext()) //read the close parenthesis
            {
                throw EndOfFile(token, context);
            }

            token = enumerator.Current;
            if (token.Type != TokenType.CloseParenthesis)
            {
                throw UnexpectedToken(token, context);
            }

            if (parseCondition)
            {
                try
                {
                    var stt = EvaluationStatementTranspilerBase.ProcessEvaluation(Context, Context.GeneralScope,
                                                                                  evalStatement);

                    if (stt is ConstantValueStatement constantValueStatement)
                    {
                        if (StatementHelpers.TryParseBooleanFromString(constantValueStatement.Value, out var boolVal))
                        {
                            return(boolVal);
                        }

                        throw UnexpectedToken(token, context);
                    }
                }
                catch (IdentifierNotFoundCompilerException)
                {
                    return(false);
                }

                throw UnexpectedToken(token, context);
            }

            return(false);
        }
        public override void WriteBlock(Context context, Scope scope, TextWriter writer,
                                        TextWriter metaWriter,
                                        IStatement statement)
        {
            if (!(statement is VariableDefinitionStatement varDefStt))
            {
                throw new InvalidOperationException();
            }

            if (varDefStt.IsConstant)
            {
                if (!varDefStt.HasDefaultValue)
                {
                    throw new InvalidOperationException();
                }

                var result =
                    EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, varDefStt.DefaultValue);

                if (!(result is ConstantValueStatement constantValueStatement))
                {
                    throw new InvalidOperationException(ErrorMessages.ConstantValueRequired);
                }

                if (!StatementHelpers.IsAssignableFrom(context, scope, varDefStt.TypeDescriptor,
                                                       constantValueStatement.TypeDescriptor))
                {
                    throw new TypeMismatchCompilerException(constantValueStatement.TypeDescriptor,
                                                            varDefStt.TypeDescriptor, varDefStt.Info);
                }

                scope.ReserveNewConstant(varDefStt.TypeDescriptor, varDefStt.Name, constantValueStatement.Value);
            }
            else
            {
                var skipDefinition = false;
                if (varDefStt.HasDefaultValue)
                {
                    var def        = varDefStt.DefaultValue;
                    var transpiler = context.GetEvaluationTranspilerForStatement(def);
                    if (transpiler == null)
                    {
                        throw new InvalidOperationException();
                    }

                    //it pins non-inlinable values to a helper variable:
                    //int x = 34 * myFunc();
                    //becomes:
                    //myFuncResult=myFunc()
                    //x=$((34 * myFuncResult))
                    if (varDefStt.TypeDescriptor.IsArray())
                    {
                        var p = new ExpressionBuilderParams(context, scope, metaWriter, writer,
                                                            new BlockStatement(null, varDefStt.Info));

                        scope.ReserveNewVariable(varDefStt.TypeDescriptor, varDefStt.Name);
                        skipDefinition = true;

                        var targetVar = new VariableAccessStatement(varDefStt.Name, varDefStt.Info);

                        var call = transpiler.CallApiFunction <ApiArray.Copy>(p, new[] { targetVar, def }, varDefStt,
                                                                              varDefStt.Info);

                        if (!call.IsEmptyResult)
                        {
                            WriteVariableDefinition(context, scope, writer, varDefStt.Name, call.Expression);
                        }
                    }
                    else
                    {
                        var result = transpiler.GetExpression(context, scope, metaWriter, writer, null, def);

                        WriteVariableDefinition(context, scope, writer, varDefStt.Name, result.Expression);
                    }
                }
                else
                {
                    WriteVariableDefinition(context, scope, writer, varDefStt.Name,
                                            context.Platform.GetDefaultValue(varDefStt.TypeDescriptor.DataType));
                }

                if (!skipDefinition)
                {
                    scope.ReserveNewVariable(varDefStt.TypeDescriptor, varDefStt.Name);
                }

                scope.IncrementStatements();
            }
        }
        public static void WriteIf(Context context, Scope scope, TextWriter writer, TextWriter nonInlinePartWriter,
                                   TextWriter metaWriter, IfElseStatement ifElseStatement)
        {
            var ifEscaped = false;
            var skipElse  = false;

            var condition =
                EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, ifElseStatement.MainIf.Condition);

            if (StatementHelpers.IsAbsoluteBooleanValue(condition, out var isTrue))
            {
                if (isTrue)
                {
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.MainIf.Statement, ScopeType.Block, true);

                    return;
                }

                ifEscaped = true;
            }
            else
            {
                writer.Write("if ");
                WriteCondition(context, scope, writer, metaWriter, nonInlinePartWriter, ifElseStatement, condition);
                writer.WriteLine();
                writer.WriteLine("then");
                BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                 ifElseStatement.MainIf.Statement, ScopeType.IfMainBlock, true);
            }

            if (ifElseStatement.ElseIfs != null)
            {
                foreach (var elseIf in ifElseStatement.ElseIfs)
                {
                    condition = EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, elseIf.Condition);

                    if (StatementHelpers.IsAbsoluteBooleanValue(condition, out isTrue))
                    {
                        if (isTrue)
                        {
                            if (!ifEscaped)
                            {
                                writer.WriteLine("else");
                            }

                            BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                             elseIf.Statement, ScopeType.IfElseBlock, true);

                            skipElse = true;
                            break;
                        }
                    }
                    else
                    {
                        if (ifEscaped)
                        {
                            writer.Write("if ");
                            ifEscaped = false;
                        }
                        else
                        {
                            writer.Write("elif ");
                        }

                        WriteCondition(context, scope, writer, metaWriter, nonInlinePartWriter, ifElseStatement,
                                       condition);
                        writer.WriteLine();
                        writer.WriteLine("then");
                        BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                         elseIf.Statement, ScopeType.IfIfElseBlock, true);
                    }
                }
            }

            if (!skipElse && ifElseStatement.Else != null)
            {
                if (ifEscaped)
                {
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.Else, ScopeType.IfMainBlock, true);
                }
                else
                {
                    writer.WriteLine("else");
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.Else, ScopeType.IfElseBlock, true);
                }
            }

            if (!ifEscaped)
            {
                writer.WriteLine("fi");

                scope.IncrementStatements();
            }
        }