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); }
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(); } }