Commit f1cfa191 authored by Maxime Perrotin's avatar Maxime Perrotin

Working version of new iterator generator

parent 0441d625
......@@ -25,11 +25,11 @@ package ASN1_Iterators.Generic_SeqOf is
package Length_Pkg renames Length_ty.It;
type Cursor is private;
subtype MySeqOf is P.SeqOf (Max);
subtype Sequence_Of is P.SeqOf (Max);
type ASN1_Variable_SeqOf is new Controlled
with record
Length : Natural := Min;
Value : MySeqOf;
Value : Sequence_Of;
-- Iterate on the length
LenVal : Length_ty.Instance;
LenIt : Length_Pkg.Iterator;
......@@ -38,7 +38,7 @@ package ASN1_Iterators.Generic_SeqOf is
RestIt : access P.ASN1_SeqOf_It;
end record
with Default_Iterator => Iterate,
Iterator_Element => MySeqOf,
Iterator_Element => Sequence_Of,
Constant_Indexing => Element_Variable_SeqOf_Value;
-- Constructor (called automatically)
......@@ -70,7 +70,7 @@ package ASN1_Iterators.Generic_SeqOf is
function Element_Variable_SeqOf_Value (Self : ASN1_Variable_SeqOf;
Position : Cursor)
return MySeqOf is (Self.Value);
return Sequence_Of is (Self.Value);
subtype Instance is ASN1_Variable_SeqOf;
......
......@@ -27,8 +27,10 @@ import opengeode.ogParser as parser
LF = '\n'
def indent(nb: int, phrase: List[str], sep=""):
# offer indenting of multiple line strings when referenced inside f-strings
result = LF.join(phrase)
return (sep+LF+nb*" ").join(result.splitlines())
phase1 = LF.join(phrase)
phase2 = (sep+LF+nb*" ").join(phase1.splitlines())
# remove trailing spaces:
return LF.join(line.rstrip() for line in phase2.splitlines())
def adb_template(packages: List[str]) -> str:
''' Top-level template to generate the .adb file '''
......@@ -36,7 +38,7 @@ def adb_template(packages: List[str]) -> str:
with Ada.Strings,
Ada.Strings.Fixed,
Ada.Srings.Unbounded,
Ada.Strings.Unbounded,
Ada.Characters.Handling;
use Ada.Strings,
......@@ -86,7 +88,7 @@ def seq_of_adb_template (sort: str, inner: str, minR: int, maxR: int) -> str:
''' Template for iterating on an array '''
if minR == maxR:
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Inner.{sort};
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort}) is
begin
for Idx in 1 .. From.Length loop
......@@ -105,13 +107,13 @@ def seq_of_adb_template (sort: str, inner: str, minR: int, maxR: int) -> str:
Res := Res & ", " & Image (Elm.Data (Idx));
end loop;
end if;
return To_String ("{" & Res & "}");
return To_String ("{{" & Res & "}}");
end Image;
end {sort}_Pkg;'''
else:
# Variable-size sequence of
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Inner.{sort};
else:
# Variable-size sequence of
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort}) is
begin
for Idx in 1 .. From.Length loop
......@@ -121,17 +123,17 @@ end {sort}_Pkg;'''
end To_ASN1;
function Image (Elm : asn1Scc{sort}) return String is
function Image_Rec (Elm : ASN1_Type) return String is
function Image_Rec (Elm : asn1Scc{sort}) return String is
(if Elm.Length > 0 then
(Image (Elm.Data (1))
& (if Elm.Length > 1 then ", "
& Image_Rec (ASN1_Type'(Length => Elm.Length-1,
Data => Elm.Data(2 .. Elm.Length) &
Elm.Data(1 .. Elm.Data'Length - Elm.Length + 1)))
& Image_Rec (asn1Scc{sort}'(Length => Elm.Length - 1,
Data => Elm.Data (2 .. Elm.Length) &
Elm.Data (1 .. Elm.Data'Length - Elm.Length + 1)))
else ""))
else "");
begin
return "{ " & Image_Rec (Elm) & " }";
return "{{ " & Image_Rec (Elm) & " }}";
end Image;
end {sort}_Pkg;'''
......@@ -141,7 +143,6 @@ def enum_adb_template (sort: str) -> str:
return f'''package body {sort}_Pkg is
function Image (Elm : asn1Scc{sort}) return String is
(Delete (To_Lower (Elm'Img), From => 1, Through => 7)); -- remove "asn1scc" prefix
end Image;
end {sort}_Pkg;'''
......@@ -155,6 +156,69 @@ def fields_adb_init (fields : dict) -> List [str]:
return result
def fields_first_key (fields : dict) -> List [str]:
'''
Return the first field name.. The dict is ordered in python 3.7+
'''
try:
return next(iter(fields))
except StopIteration:
return ""
def fields_adb_first (fields : dict) -> List [str]:
'''
Generate SEQUENCE fields code for the "First" function
'''
result = []
for name in fields.keys():
result.append (f"unused_Cursor_{name} : P_{name}.Cursor := Item.Position.{name}_it.First;")
return result
def fields_adb_next (fields : dict) -> List [str]:
'''
Generate SEQUENCE fields code for the "Next" function (declarations)
'''
result = []
for name in fields.keys():
result.append (f"Cursor_{name} : P_{name}.Cursor := Position.{name}_it.Get_Cursor;")
return result
def fields_adb_iterate (fields : dict) -> List [str]:
'''
Generate SEQUENCE iteration code (for the "Next" function)
'''
# Exhaust the last field, then the previous one, and so on
def rec_it (names : List[str]) -> List [str]:
result = []
name = names[-1]
result.append(f"Cursor_{name} := Position.{name}_it.Next (Cursor_{name});")
if len(names) > 1: # not the last one -> go recursively
result.append(f"if not P_{name}.Has_Element (Cursor_{name}) then")
result.append(f" Cursor_{name} := Position.{name}_it.First;")
result.append(f" {indent(3, rec_it(names[0:-1]))}")
result.append(f"end if;")
return result
return rec_it (list(fields.keys()))
def fields_adb_image (fields : dict) -> List [str]:
'''
Generate GSER representation code for a list of SEQUENCE fields
'''
result = []
first = True
for name, sort in fields.items():
if not first:
result.append('& ", "')
result.append (f'& "{name} " & {sort}_Pkg.Image (Elm.{name})')
first = False
return result
def sequence_adb_template (sort: str, fields: dict) -> str:
''' Template for iterating on a record '''
return f'''package body {sort}_Pkg is
......@@ -165,12 +229,13 @@ def sequence_adb_template (sort: str, fields: dict) -> str:
end Initialize;
function Has_Element (Position : Cursor) return Boolean is
(P_{fields_first(fields)} (Position.{fields_first(fields)}_it.Get_Cursor));
(P_{fields_first_key(fields)}.Has_Element
(Position.{fields_first_key(fields)}_it.Get_Cursor));
function Iterate (Container : {sort}) return {sort}_It'Class is
begin
return I: {sort}_It do
I.Position := Self'Unrestricted_Access;
return I : {sort}_It do
I.Position := Container'Unrestricted_Access;
end return;
end Iterate;
......@@ -193,9 +258,9 @@ def sequence_adb_template (sort: str, fields: dict) -> str:
function Image (Elm : asn1Scc{sort}) return String is
begin
return "{"
{fields_adb_image(13, fields)}
& "}";
return "{{"
{indent(13, fields_adb_image(fields))}
& "}}";
end Image;
end {sort}_Pkg;'''
......@@ -259,7 +324,7 @@ def seq_of_ads_template (sort: str, inner: str, minR: int, maxR: int) -> str:
Max => {maxR},
Basic => {inner}_Pkg.It);
use {inner}_Pkg;
procedure To_ASN1 (From : Inner.{sort};
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort});
subtype Instance is Inner.Instance;
function Image (Elm : asn1Scc{sort}) return String;
......
with ASN1_Ada_Iterators.iterators; -- Generated by asn1scc using custom stg file
use ASN1_Ada_Iterators.iterators;
with ASN1_Ada_Iterators.Iterators;
use ASN1_Ada_Iterators.Iterators;
with TASTE_DataView;
use TASTE_DataView;
with TASTE_Dataview;
use TASTE_Dataview;
with ada.text_io;
use ada.text_io;
with Ada.Text_IO;
use Ada.Text_IO;
procedure test_generic is
-- THIS IS HOW TO DO IT MANUALLY:
-- THIS IS HOW TO DO IT MANUALLY:
-- -- create an Integer type with a range constraint
-- package MyInteger is new Generic_Integer (1, 4);
--
......@@ -23,53 +23,53 @@ procedure test_generic is
-- Max => 3,
-- Basic => MyInteger.It);
--
use MyInteger_Pkg;
use MySeqOf_Pkg;
use MyVarSeqOf_Pkg;
use MyEnum_Pkg;
use MySeqOfEnum_Pkg;
use MySeq_Pkg;
use MyInteger_Pkg;
use MySeqOf_Pkg;
use MyVarSeqOf_Pkg;
use MyEnum_Pkg;
use MySeqOfEnum_Pkg;
use MySeq_Pkg;
-- Test cases
MyIt : MyInteger_Pkg.Instance;
Fixed_SeqOf : MySeqOf_Pkg.Instance;
Var_SeqOf : MyVarSeqOf_Pkg.Instance;
Enum : MyEnum_Pkg.Instance;
SeqOfEnum : MySeqOfEnum_Pkg.Instance;
-- Test cases
MyIt : MyInteger_Pkg.Instance;
Fixed_SeqOf : MySeqOf_Pkg.Instance;
Var_SeqOf : MyVarSeqOf_Pkg.Instance;
Enum : MyEnum_Pkg.Instance;
SeqOfEnum : MySeqOfEnum_Pkg.Instance;
Seq : MySeq_Pkg.Instance;
Seq : MySeq_Pkg.Instance;
SeqOfItm : asn1SccMySeqOf;
VarSeqOfItm : asn1SccMyVarSeqOf;
SeqOfEnumItm : asn1SccMySeqOfEnum;
i : Natural := 1;
SeqOfItm : asn1SccMySeqOf;
VarSeqOfItm : asn1SccMyVarSeqOf;
SeqOfEnumItm : asn1SccMySeqOfEnum;
i : Natural := 1;
begin
-- test: compute all possible values of the integer type
-- (equivalent to "for each in 1..3 loop put_line(each'img); end loop;")
-- test: compute all possible values of the integer type
-- (equivalent to "for each in 1..3 loop put_line(each'img); end loop;")
for each of MyIt loop
--Put_Line(each'img);
Put_Line(Image(each));
-- Put_Line(each'img);
Put_Line (Image (each));
end loop;
-- test: compute all combinations of values for the fixed-size array
-- test: compute all combinations of values for the fixed-size array
Put_Line ("Variable-size array:");
for each of Var_SeqOf loop
To_ASN1 (From => each, To => VarSeqOfItm);
Put(Image(VarSeqOfItm));
Put (Image (VarSeqOfItm));
i := (if i mod 10 = 0 then 1 else i + 1);
if i = 1 then
New_Line;
end if;
end loop;
-- test: compute all combination of values for the variable-size array
-- test: compute all combination of values for the variable-size array
New_Line;
Put_Line ("Fixed-size array:");
i := 1;
for each of Fixed_SeqOf loop
To_ASN1 (From => each, To => SeqOfItm);
Put(Image(SeqOfItm));
Put (Image (SeqOfItm));
i := (if i mod 10 = 0 then 1 else i + 1);
if i = 1 then
New_Line;
......@@ -95,6 +95,4 @@ begin
Put (Image (Each) & " ");
end loop;
New_Line;
end;
end test_generic;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment