def test_named_aggregate_rflx_expr() -> None: assert ada.NamedAggregate( ("X", ada.Number(1)), (ada.ValueRange(ada.Number(2), ada.Number(3)), ada.Variable("Y")), ).rflx_expr() == expr.NamedAggregate( ("X", expr.Number(1)), (expr.ValueRange(expr.Number(2), expr.Number(3)), expr.Variable("Y")), )
def test_case_str() -> None: assert_equal( str( ada.Case( ada.Variable("X"), [ (ada.Variable("Y"), ada.Number(1)), (ada.Variable("Z"), ada.Number(1)), (ada.Variable("others"), ada.Number(2)), ], )), multilinestr("""(case X is when Y | Z => 1, when others => 2)"""), )
def test_call_statement_str() -> None: assert str(ada.CallStatement("A", [])) == "A;" assert str(ada.CallStatement( "A", [ada.Variable("B"), ada.Variable("C")])) == "A (B, C);" assert (str( ada.CallStatement("A", [], { ID("B"): ada.Number(1), ID("C"): ada.Number(2) })) == "A (B => 1, C => 2);") assert (str( ada.CallStatement( "A", [ada.Variable("B"), ada.Variable("C")], { ID("D"): ada.Number(1), ID("E"): ada.Number(2) }, )) == "A (B, C, D => 1, E => 2);")
def test_call_str() -> None: assert str(ada.Call("A", [])) == "A" assert str(ada.Call( "A", [ada.Variable("B"), ada.Variable("C")])) == "A (B, C)" assert (str( ada.Call("A", [], { ID("B"): ada.Number(1), ID("C"): ada.Number(2) })) == "A (B => 1, C => 2)") assert (str( ada.Call( "A", [ada.Variable("B"), ada.Variable("C")], { ID("D"): ada.Number(1), ID("E"): ada.Number(2) }, )) == "A (B, C, D => 1, E => 2)") assert str(-ada.Call("A", [])) == "(-A)"
def test_if_str() -> None: assert_equal( str( ada.If( [ (ada.Variable("X"), ada.Number(1)), (ada.Variable("Y"), ada.Number(2)), ], ada.Number(3), )), "(if X then 1 elsif Y then 2 else 3)", ) assert_equal( str( ada.If( [ ( ada.Variable("Some_Complex_Condition"), ada.Variable("Some_Complex_Expression"), ), ( ada.Variable("Another_Complex_Condition"), ada.Variable("Another_Complex_Expression"), ), ], ada.Variable("Some_Complex_Expression"), )), multilinestr("""(if Some_Complex_Condition then Some_Complex_Expression elsif Another_Complex_Condition then Another_Complex_Expression else Some_Complex_Expression)"""), )
def test_number_str_bin() -> None: assert str(ada.Number(454, 2)) == "2#111000110#"
def test_number_str_neg_oct() -> None: assert str(ada.Number(-45432, 8)) == "(-8#130570#)"
def test_number_str_oct() -> None: assert str(ada.Number(45432, 8)) == "8#130570#"
def test_attribute_expression_str() -> None: assert str(ada.Val("X", ada.Number(1))) == "X'Val (1)"
def test_number_str_long() -> None: assert str(ada.Number(539535)) == "539535"
def test_number_str() -> None: assert str(ada.Number(15)) == "15"
def test_aggregate_invalid() -> None: with pytest.raises(AssertionError): str(ada.Aggregate()) with pytest.raises(AssertionError): str(ada.Aggregate(ada.Number(1)))
def test_aggregate_rflx_expr() -> None: assert ada.Aggregate(ada.Number(1), ada.Number(2)).rflx_expr() == expr.Aggregate( expr.Number(1), expr.Number(2))
def test_aggregate_str() -> None: assert str(ada.Aggregate(ada.Number(1), ada.Number(2))) == "(1, 2)"
def test_number_rflx_expr() -> None: assert ada.Number(42).rflx_expr() == expr.Number(42)
def test_number_str_neg_long() -> None: assert str(ada.Number(-539535)) == "(-539535)"
def test_named_aggregate_str() -> None: assert (str( ada.NamedAggregate( ("X", ada.Number(1)), (ada.ValueRange(ada.Number(2), ada.Number(3)), ada.Variable("Y")), )) == "(X => 1, 2 .. 3 => Y)")
def test_number_str_hex() -> None: assert str(ada.Number(4096, 16)) == "16#1000#"
def test_expr_str() -> None: assert_equal( str( ada.If( [ ( ada.Or( ada.And(ada.Variable("X"), ada.Variable("Y")), ada.Variable("Z"), ), ada.Number(1), ), (ada.Variable("Y"), ada.Number(2)), ], ada.Div(ada.Mul(ada.Variable("A"), ada.Number(3)), ada.Number(8)), )), "(if (X and Y) or Z then 1 elsif Y then 2 else (A * 3) / 8)", ) assert_equal( str( ada.If( [ ( ada.Or( ada.And(ada.Variable("Variable_X"), ada.Variable("Variable_Y")), ada.Variable("Variable_Z"), ), ada.Number(1), ), (ada.Variable("Variable_Y"), ada.Number(2)), ], ada.Div(ada.Mul(ada.Variable("Variable_A"), ada.Number(3)), ada.Number(8)), )), multilinestr("""(if (Variable_X and Variable_Y) or Variable_Z then 1 elsif Variable_Y then 2 else (Variable_A * 3) / 8)"""), ) assert_equal( str( ada.And( ada.If( [ ( ada.Or( ada.And( ada.Variable("Variable_X"), ada.Variable("Variable_Y"), ), ada.Variable("Variable_Z"), ), ada.Number(1), ), (ada.Variable("Variable_Y"), ada.Number(2)), ], ada.Div( ada.Mul(ada.Variable("Variable_A"), ada.Number(3)), ada.Number(8), ), ), ada.Variable("A"), ada.Or(ada.Variable("B"), ada.Variable("C")), ada.Variable("D"), )), multilinestr("""(if (Variable_X and Variable_Y) or Variable_Z then 1 elsif Variable_Y then 2 else (Variable_A * 3) / 8) and A and (B or C) and D"""), ) assert_equal( str( ada.ForAllOf( "X", ada.Variable("Z"), ada.If( [ ( ada.Or( ada.And( ada.Variable("Variable_X"), ada.Variable("Variable_Y"), ), ada.Variable("Variable_Z"), ), ada.Number(1), ), (ada.Variable("Variable_Y"), ada.Number(2)), ], ada.Div( ada.Mul(ada.Variable("Variable_A"), ada.Number(3)), ada.Number(8), ), ), )), multilinestr("""(for all X of Z => (if (Variable_X and Variable_Y) or Variable_Z then 1 elsif Variable_Y then 2 else (Variable_A * 3) / 8))"""), ) assert str(ada.Equal(ada.String("S"), ada.Variable("X"))) == '"S" = X'
def test_number_str_neg_hex() -> None: assert str(ada.Number(-4096, 16)) == "(-16#1000#)"
def test_range_subtype() -> None: assert (str( ada.RangeSubtype("A", "B", ada.Number(1), ada.Number(2))) == "subtype A is B range 1 .. 2;")
def test_number_str_dec() -> None: assert str(ada.Number(4096, 10)) == "10#4096#"
def session_main( input_channels: dict[str, Sequence[tuple[int, ...]]] = None, output_channels: Sequence[str] = None, context: Sequence[ada.ContextItem] = None, subprograms: Sequence[ada.SubprogramBody] = None, session_package: StrID = "RFLX.Test.Session", ) -> Mapping[str, str]: input_channels = input_channels or {} output_channels = output_channels or [] context = context or [] subprograms = subprograms or [] session_package = ID(session_package) run_procedure_spec = ada.ProcedureSpecification("Run") run_procedure_decl = ada.SubprogramDeclaration(run_procedure_spec) run_procedure_body = ada.SubprogramBody( run_procedure_spec, [ ada.ObjectDeclaration(["Ctx"], "Session.Context"), ], [ ada.CallStatement(session_package * "Initialize", [ada.Variable("Ctx")]), ada.While( ada.Call(session_package * "Active", [ada.Variable("Ctx")]), [ ada.PragmaStatement( "Loop_Invariant", [ ada.Call(session_package * "Initialized", [ada.Variable("Ctx")]) ], ), *([ ada.ForIn( "C", ada.Range(session_package * "Channel"), [ ada.PragmaStatement( "Loop_Invariant", [ ada.Call( session_package * "Initialized", [ada.Variable("Ctx")], ) ], ), *([ ada.IfStatement([( ada.Call( session_package * "Has_Data", [ ada.Variable("Ctx"), ada.Variable("C"), ], ), [ ada.CallStatement( "Read", [ ada.Variable("Ctx"), ada.Variable("C"), ], ), ], )]) ] if output_channels else []), *([ ada.IfStatement([( ada.Call( session_package * "Needs_Data", [ ada.Variable("Ctx"), ada.Variable("C"), ], ), [ ada.CallStatement( "Write", [ ada.Variable("Ctx"), ada.Variable("C"), ], ), ], )]) ] if input_channels else []), ], ) ] if input_channels or output_channels else []), ada.CallStatement(session_package * "Run", [ada.Variable("Ctx")]), ], ), ada.PragmaStatement( "Warnings", [ada.Variable("Off"), ada.String("statement has no effect")], ), ada.PragmaStatement( "Warnings", [ ada.Variable("Off"), ada.String( '"Ctx" is set by "Finalize" but not used after the call' ), ], ), ada.CallStatement(session_package * "Finalize", [ada.Variable("Ctx")]), ada.PragmaStatement( "Warnings", [ada.Variable("On"), ada.String("statement has no effect")], ), ada.PragmaStatement( "Warnings", [ ada.Variable("On"), ada.String( '"Ctx" is set by "Finalize" but not used after the call' ), ], ), ], ) print_procedure = ada.SubprogramBody( ada.ProcedureSpecification( "Print", [ ada.Parameter(["Prefix"], "String"), ada.Parameter(["Chan"], session_package * "Channel"), ada.Parameter(["Buffer"], "RFLX" * const.TYPES_BYTES), ], ), [], [ ada.CallStatement( "Ada.Text_IO.Put", [ ada.Concatenation( ada.Variable("Prefix"), ada.String(" "), ada.Case( ada.Variable("Chan"), [( ada.Variable(session_package * f"C_{channel}"), ada.String(channel), ) for channel in sorted( {*input_channels.keys(), *output_channels})], ), ada.String(":"), ) ], ), ada.ForOf( "B", ada.Variable("Buffer"), [ ada.CallStatement("Ada.Text_IO.Put", [ada.Variable("B'Image")]), ], ), ada.CallStatement("Ada.Text_IO.New_Line"), ], aspects=[ ada.Precondition( ada.AndThen( ada.Equal(ada.First("Prefix"), ada.Number(1)), ada.LessEqual(ada.Length("Prefix"), ada.Number(1000)), )) ], ) read_procedure = ada.SubprogramBody( ada.ProcedureSpecification( "Read", [ ada.Parameter(["Ctx"], "Session.Context"), ada.Parameter(["Chan"], session_package * "Channel"), ], ), [ ada.UseTypeClause("RFLX" * const.TYPES_INDEX), ada.UseTypeClause("RFLX" * const.TYPES_LENGTH), ada.ObjectDeclaration( ["Buffer"], ada.Slice( ada.Variable("RFLX" * const.TYPES_BYTES), ada.First("RFLX" * const.TYPES_INDEX), ada.Add(ada.First("RFLX" * const.TYPES_INDEX), ada.Number(4095)), ), ada.NamedAggregate(("others", ada.Number(0))), ), ada.ObjectDeclaration( ["Size"], "RFLX" * const.TYPES_LENGTH, ada.Call( session_package * "Read_Buffer_Size", [ ada.Variable("Ctx"), ada.Variable("Chan"), ], ), constant=True, ), ], [ ada.IfStatement([ ( ada.Equal(ada.Variable("Size"), ada.Number(0)), [ ada.CallStatement( "Ada.Text_IO.Put_Line", [ ada.Concatenation( ada.String("Read "), ada.Image("Chan"), ada.String(": read buffer size is 0"), ) ], ), ada.ReturnStatement(), ], ), ]), ada.IfStatement([ ( ada.Less(ada.Length("Buffer"), ada.Variable("Size")), [ ada.CallStatement( "Ada.Text_IO.Put_Line", [ ada.Concatenation( ada.String("Read "), ada.Image("Chan"), ada.String(": read buffer size too small"), ) ], ), ada.ReturnStatement(), ], ), ], ), ada.CallStatement( session_package * "Read", [ ada.Variable("Ctx"), ada.Variable("Chan"), ada.Slice( ada.Variable("Buffer"), ada.First("Buffer"), ada.Add( ada.First("Buffer"), -ada.Number(2), ada.Call( "RFLX" * const.TYPES_INDEX, [ada.Add(ada.Variable("Size"), ada.Number(1))], ), ), ), ], ), ada.CallStatement( "Print", [ ada.String("Read"), ada.Variable("Chan"), ada.Slice( ada.Variable("Buffer"), ada.First("Buffer"), ada.Add( ada.First("Buffer"), -ada.Number(2), ada.Call( "RFLX" * const.TYPES_INDEX, [ada.Add(ada.Variable("Size"), ada.Number(1))], ), ), ), ], ), ], aspects=[ ada.Precondition( ada.AndThen( ada.Call(session_package * "Initialized", [ada.Variable("Ctx")]), ada.Call(session_package * "Has_Data", [ada.Variable("Ctx"), ada.Variable("Chan")]), ), ), ada.Postcondition( ada.Call(session_package * "Initialized", [ada.Variable("Ctx")])), ], ) write_procedure = ada.SubprogramBody( ada.ProcedureSpecification( "Write", [ ada.InOutParameter(["Ctx"], "Session.Context"), ada.Parameter(["Chan"], session_package * "Channel"), ], ), [ ada.UseTypeClause("RFLX" * const.TYPES_LENGTH), *([ada.UseTypeClause(session_package * "Channel")] if len(input_channels) > 1 else []), ada.ObjectDeclaration( ["None"], ada.Slice( ada.Variable("RFLX" * const.TYPES_BYTES), ada.Number(1), ada.Number(0), ), ada.NamedAggregate(("others", ada.Number(0))), constant=True, ), ada.ObjectDeclaration( ["Message"], "RFLX" * const.TYPES_BYTES, ada.If( [( ada.And( *([ ada.Equal( ada.Variable("Chan"), ada.Variable(session_package * f"C_{channel}"), ) ] if len(input_channels) > 1 else []), ada.Equal( ada.Call("Written_Messages", [ada.Variable("Chan")]), ada.Number(i), ), ), ada.Aggregate(*[ada.Number(b) for b in message]) if len(message) > 1 else ada.NamedAggregate(*[( ada.First("RFLX" * const.TYPES_INDEX), ada.Number(message[0]), )]), ) for channel, messages in input_channels.items() for i, message in enumerate(messages)], ada.Variable("None"), ), constant=True, ), ], [ ada.IfStatement([( ada.And( ada.Greater( ada.Length("Message"), ada.Number(0), ), ada.LessEqual( ada.Length("Message"), ada.Call( session_package * "Write_Buffer_Size", [ada.Variable("Ctx"), ada.Variable("Chan")], ), ), ), [ ada.CallStatement( "Print", [ ada.String("Write"), ada.Variable("Chan"), ada.Variable("Message"), ], ), ada.CallStatement( session_package * "Write", [ ada.Variable("Ctx"), ada.Variable("Chan"), ada.Variable("Message"), ], ), ada.IfStatement([( ada.Less( ada.Call("Written_Messages", [ada.Variable("Chan")]), ada.Last("Natural"), ), [ ada.Assignment( ada.Call("Written_Messages", [ada.Variable("Chan")]), ada.Add( ada.Call("Written_Messages", [ada.Variable("Chan")]), ada.Number(1), ), ) ], )]), ], )], ) ], aspects=[ ada.Precondition( ada.AndThen( ada.Call(session_package * "Initialized", [ada.Variable("Ctx")]), ada.Call(session_package * "Needs_Data", [ada.Variable("Ctx"), ada.Variable("Chan")]), ), ), ada.Postcondition( ada.Call(session_package * "Initialized", [ada.Variable("Ctx")])), ], ) lib_unit = ada.PackageUnit( [ *const.CONFIGURATION_PRAGMAS, *context, ], ada.PackageDeclaration( "Lib", [ run_procedure_decl, ], aspects=[ada.SparkMode()], ), [ *const.CONFIGURATION_PRAGMAS, *([ ada.WithClause("Ada.Text_IO"), ada.WithClause("RFLX" * const.TYPES), ] if input_channels or output_channels else []), ada.WithClause(session_package), ada.WithClause("Session"), ], ada.PackageBody( "Lib", [ *([print_procedure] if input_channels or output_channels else []), *([read_procedure] if output_channels else []), *([ ada.ArrayType("Number_Per_Channel", session_package * "Channel", "Natural"), ada.ObjectDeclaration( ["Written_Messages"], "Number_Per_Channel", ada.NamedAggregate(("others", ada.Number(0))), ), write_procedure, ] if input_channels else []), run_procedure_body, *[ ada.SubprogramBody(s.specification, s.declarations, s.statements) for s in subprograms ], ], aspects=[ada.SparkMode()], ), ) session_unit = ada.PackageUnit( [ *const.CONFIGURATION_PRAGMAS, ada.WithClause(session_package), ], ada.PackageDeclaration( "Session", [ ada.DerivedType("Context", session_package * "Context", []), ], aspects=[ ada.SparkMode(), ], ), [], ada.PackageBody("Session"), ) return { f"{session_unit.name}.ads": session_unit.ads, f"{lib_unit.name}.ads": lib_unit.ads, f"{lib_unit.name}.adb": lib_unit.adb, "main.adb": """with Lib; procedure Main with SPARK_Mode is begin Lib.Run; end Main; """, }
def test_add_str() -> None: assert str(ada.Add(ada.Number(1), ada.Call("Test", []))) == "1 + Test" assert str(ada.Add(ada.Number(1), -ada.Call("Test", []))) == "1 - Test"