/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Balasko, Jeno
 *   Kovacs, Ferenc
 *   Raduly, Csaba
 *   Szabados, Kristof
 *
 ******************************************************************************/
/* Some test cases are from TTCN3_SA_6_TD.script.  Those were negative tests
   before.  */
module TassignmentNotation
{
  modulepar integer tsp_param
  type integer int_array_1000[1000][1000][1000]
  type record rec0 { integer a }
  type integer int_array_3[3]
  type integer int_array_2[2]
  type record of integer intlist
  type record of float floatlist
  type record of floatlist floatlist2
  type set of integer intset
  type record of intlist intlist2
  type set of intset intset2
  type record rec1 { intlist a, intset b, int_array_2 c }
  type record of rec1 recs1
  type set of rec1 secs1
  template floatlist fl1 := { 1.0, 2.0, 3.0 }
  template floatlist fl2 modifies fl1 := { [10] := 1.0 }
  template floatlist2 fl3 := { { 1.0, 2.0 }, { 1.0, 2.9 } }
  template floatlist2 fl4 modifies fl3 := { [0] := { [99] := 100.0 } }
  template recs1 embed1 := { { { 1, 2 }, { 3, 4 }, { 11, 12 } }, { a := { 5, 6 }, b := { 7, 8 }, c := { 9, 10 } } }
  template secs1 embed2 := { { a := { 1, 2 }, b := { 3, 4 }, c := { 11, 12 } }, { { 5, 6 }, { 7, 8 }, { 9, 10 } } }
  template recs1 embed3 modifies embed1 := { [__LINE__] := { a := { 1, 2 } }, [1] := { b := { [tsp_param] := 1 } } }
  template secs1 embed4 modifies embed2 := { [valueof (embed1[0].a[1])] := { { embed1[0].a[tsp_param] }, { 2 }, { [valueof (embed3[2].c[0])] := 6 } } }
  template intlist2 i21 := { { 1, 2, 3 }, { 1, 2, 3 }  }
  template intlist2 i22 modifies i21 := { [tsp_param] := { [100] := 100 } }
  template intset2 i23 := { { 1, 2, 3 }, { 1, 2, 3 } }
  template intset2 i24 modifies i23 := { [tsp_param] := { [100] := 100 } }
  template recs1 i25 modifies embed3 := { -, - }
  template recs1 i26 modifies i25 := { [0] := { a := { } }, [tsp_param] := { a := { }, b := { } } }
  template secs1 i27 modifies embed4 := { -, - }
  template secs1 i28 modifies i27 := { [0] := { a := { } }, [tsp_param] := { a := { }, b := { } } }
  template int_array_3 i29 := { 1, 2, 3 }
  template int_array_3 i30 modifies i29 := { [tsp_param] := 1, [1] := 4 }
  template integer insp := valueof (sizeof (i30)) + valueof (embed4[valueof (embed3[tsp_param].a[0])].a[0])
  /* Parametrized templates for all supported types.  */
  template intlist part3 := { 1, 2, 3 }
  type port myportlist message { inout intlist } with { extension "internal" }
  type port myportset message { inout intset } with { extension "internal" }
  type port myportarr message { inout int_array_3 } with { extension "internal" }
  type port myintp message { inout integer } with { extension "internal" }
  type enumerated myenum { an (1), bn (2), cn (3) }
  /* "type integer myi (1..valueof (i30[0]))" is an error.  These two are the
     same.  Both boundaries must be constants.  */
  type integer myi (1..100)
  type integer myi2 (1, 2, 3)
  template integer intt := (1..valueof (i30[0]))
  template integer intt2 := (1..sizeof (i30))
  template integer intt3 := (sizeof(embed3[tsp_param].a)..valueof (embed3[tsp_param].a[100]))
  template integer intt4 := ((sizeof(embed3[tsp_param].a)..valueof (embed3[tsp_param].a[100])), tsp_param)
  type bitstring mbs length (valueof (sizeof (i26))) /* Old regression.  */
  type bitstring mbs2 length (valueof (sizeof(i26[0].a)))
  type record length (1..valueof (sizeof (i26))) of integer intlistr /* Index with sizeof (i26[1]).  */
  type record length (valueof (sizeof (i26))..valueof (sizeof (embed4[0].b))) of integer intsetr
  type record of intlistr intlistrr
  type record of intsetr intsetrr
  template intlistrr ilrr1 := { { 1, 2, 3 } }
  template intlistrr ilrr2 modifies ilrr1 := { [0] := { [tsp_param] := tsp_param }, [200] := { tsp_param } }
  template intsetrr ilrr3 := { { 1, 2, 3 } }
  template intsetrr ilrr4 modifies ilrr3 := { [0] := { [tsp_param] := tsp_param }, [200] := { 1 } }
  /* Record/set type cannot be indexed.  */
  template rec1 reccomp := { a := { complement (sizeof (i30), sizeof (embed4[4].a), 3) }, b := { }, c := { 1, 2 } }
  template rec0 reccomp2 := { a := complement (valueof (i30[0]), sizeof (i30), valueof (embed3[100].a[tsp_param])) }
  template intset subs := subset (valueof (i30[0]), sizeof (i30), valueof (embed3[100].a[tsp_param]))
  template intset subs2 modifies subs := { [tsp_param] := sizeof (i26), [0] := valueof (embed4[100].a[tsp_param]) }
  template intset sups := superset (valueof (i30[0]), sizeof (i30), valueof (embed3[100].a[tsp_param]))
  template intset sups2 modifies sups := { [tsp_param] := sizeof (i26), [0] := valueof (embed4[100].a[tsp_param]) }
  template intlist permu := { permutation (valueof (i30[0]), sizeof (i30), valueof (embed3[100].a[tsp_param])) }
  /* String types cannot be indexed.  No modified example for them.  */
  template charstring xstr := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]))
  template charstring xstr2 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param])..valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]) + tsp_param)
  template bitstring xstr3 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]))
  template bitstring xstr4 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param])..valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]) + tsp_param)
  template octetstring xstr5 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]))
  template octetstring xstr6 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param])..valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]) + tsp_param)
  template intlist xstr7 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]))
  template intlist xlist8 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param])..valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]) + tsp_param)
  template intlist xlist12 modifies xlist8 := { [tsp_param] := sizeof (i26), [0] := valueof (embed4[100].a[tsp_param]) }
  template intset xstr9 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]))
  template intset xlist10 := ? length (valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param])..valueof (i30[0]) + sizeof (i30) + valueof (embed3[100].a[tsp_param]) + tsp_param)
  template intset xlist11 modifies xlist10 := { [tsp_param] := sizeof (i26), [0] := valueof (embed4[100].a[tsp_param]) }
  type component compon
  {
    port myportlist myprec
    port myportset mypset
    port myportarr myparr
    port myportarr mypa[100]
    port myintp intp
  }
  template intlist part4 (integer p1, template integer p2) modifies part3 := { [valueof (p2) + p1] := p2, [100] := part3[1] }
  template intset part5 := { 1, 2, 3 }
  template intset part6 (integer p1, template integer p2) modifies part5 := { [valueof (p2) + p1] := p2, [__LINE__] := part5[1] }
  template int_array_3 part7 := { 1, 2, 3 }
  template int_array_3 part8 (integer p1, template integer p2) modifies part7 := { [sizeof (part7) - 1] := 100, [valueof (p2) - valueof (part7[p1])] := __LINE__, [1] := p1 }

  function f3 (inout intlist p1) return integer
  {
    var myi myii := valueof (part3[0]) + sizeof (embed2[0])
    var myi2 myii2 := valueof (part3[0]) + sizeof (embed4)
    p1[sizeof (p1)] := 1
    return 1
  }

  function f1 () return integer { return 100; }

  function f2 (in integer p1, in integer p2, out intlist p3, out intset p4,
    out int_array_2 p5, out integer p6)
  { /* Function parameters as array indices.  Test for record of/set of/array
       variables/constants only.  With parameter passing and indexing in
       various ways.  */
    var integer n := 0
    var integer mya1[2] := { p1, p2 }
    const integer cn := 0
    const integer mya2[2] := { [cn] := cn, [1] := 100 }
    var intlist myr1 := { [p1] := 1, [n + p1] := p2, [f1 ()] := 100 }
    var intset mys1 := { [p1] := 2, [p1 * p2] := p2, [f1 () * f1 ()] := 101 }
    n := mya2[1] + myr1[0] + mys1[0] * mya2[cn] - mys1[n] + mya2[f1 ()] +
      myr1[f1 ()] - mys1[f1 () - n] /* Old regression when indexing constant
      arrays.  */
    mya1[1] := 100
    p3 := myr1
    p4 := mys1
    p5 := mya2
    p6 := n
    var myenum mye := an
  }

  function array_fn ()
  {
    const int_array_3 f := { [0] := 0, [1] := 1, [2] := 2 }
    const intlist il1 := { [0] := 0, [1] := 1 }
    const intset is1 := { [0] := 0, [1] := 1 }
    var intlist p1
    var intset p2
    var int_array_2 p3
    var integer p4
    f2 (1, 2, p1, p2, p3, p4)
    f2 (sizeof (f) + f[tsp_param], valueof (embed4[__LINE__].a[tsp_param]), p1, p2, p3, p4)
    f2 (sizeof (f) + f[tsp_param], valueof (embed3[__LINE__].a[tsp_param]), p1, p2, p3, p4)
    p1[p4] := f[1]
    p2 := { [0] := f[0], [1] := p1[p4], [f[2]] := p4 }
    p3[p4] := p4
    p3 := { [p4] := p3[0 + f1 ()], [p3[0]] := 100 }
    p4 := p3[p3[p3[p4]]]
    var integer i := f[0]
    f2 (sizeof (p3) + p2[tsp_param], valueof (embed2[1].a[tsp_param]), p1, p2, p3, p4)
    var template intlist aaty := embed3[100].a
    var integer p5 := sizeof (embed3[100]) + sizeof (i26)
    var intset cis := { [sizeof (embed3[100].a)] := 4 }
    // Call some predefined functions for list-types.
    log(lengthof(p2))
    log(sizeof(p2))
    log(lengthof(f))
    log(sizeof(f))
    log(lengthof(il1))
    log(sizeof(il1))
    log(lengthof(is1))
    log(sizeof(is1))
  }

  testcase array_tc () runs on compon
  {
    // Legal indexing of arrays.
    var intlist p11
    var intset p22
    var int_array_2 p33
    var integer p44
    var integer i := 10
    template intlist a_base := { [0] := 0 } // It's now allowed.
    template intset b_base := { [i] := 0 }
    template int_array_3 c_base := { [0] := 0 }
    const int_array_3 v_f := { [0] := 1, [1] := 2, [2] := 3 }
    const int_array_3 v_g := { 1, 2, 3 }
    template int_array_3 t1 := { 0, 1, 2 }
    template int_array_3 t2 modifies t1 := { [f1 ()] := 2, [1] := 1, [2] := 0 }
    var template integer tv1 := t2[f1 () + 1]
    i := valueof (t2[valueof (tv1) + 1 - f1 ()])
    template int_array_3 part9 := part8 (1, 2)
    var template integer t3 := v_f[v_f[f1 ()]]
    var template intlist t4 := { v_g[i], v_f[f1 () + valueof (t2[i])] }
    var integer int1[v_g[2]..5] := { 1, valueof (t2[i]), v_f[i] }
    var integer int2[v_f[0]..5] := { [1] := 1, [i] := 4 }
    int2 := { [f1 () + sizeof (v_f)] := tsp_param }
    int1 := { [f1 ()] := tsp_param }
    f2 (sizeof (v_f) + valueof (t2[tsp_param]), valueof (embed3[__LINE__].a[tsp_param]), p11, p22, p33, p44)
    f2 (sizeof (int2) + valueof (int2[tsp_param]), valueof (embed3[__LINE__].a[tsp_param]), p11, p22, p33, p44)
    i := int2[v_f[i]]
    i := valueof (t1[valueof (t2[1])]) + int2[i]
    t4[valueof (t2[1])] := int1[v_f[i]]
    var integer a1[3] := { [tsp_param] := tsp_param, [0] := 100 }
    i := a1[tsp_param]
    /* Asssigning multi-dimensional arrays.  */
    var integer multi1[10][v_g[1]][1000] := { [tsp_param] := { [i + 100] := { [i] := 100 }, [i] := { [999] := 1 } } }
    i := multi1[5][1][5] + multi1[tsp_param][0][valueof (t2[1])]
    /* "var integer multi[a1[2]]" would be an error.  It's not a constant
       array.  '*/
    timer tim[1][v_f[1]] := { { [i] := 1.0, [tsp_param] := 2.0 } }
    timer tim2[2..5] := { [2] := 0.0, [3] := 1.0, [4] := 2.0, [5] := 3.0 }
    var float farr[2] := { [tsp_param] := 100.0, [0] := 22.0 }
    tim[0][0].start (valueof (fl2[100]))
    tim[a1[2]][i].start (valueof (fl4[100][tsp_param]))
    tim[a1[2]][i].start (valueof (farr[1]) + farr[tsp_param])
    timer tt := valueof (farr[1]) + farr[tsp_param]
    timer tt2 := valueof (fl4[100][tsp_param])
    myparr.receive (modifies t2 := { [0] := 1, [i] := i })
    mypa[i].receive (modifies t2 := { [0] := 1, [i] := i })
    mypa[sizeof (mypa) + v_f[tsp_param]].receive (modifies t2 := { [0] := 1, [i] := i })
    array_fn ()
  }

  altstep myalt (integer i) runs on compon {
    [sizeof (ilrr2) > valueof (embed3[i].a[tsp_param]) + sizeof (i30)] intp.receive (sizeof (ilrr2)) {
    }
  }

  function rec_set_fn () runs on compon
  {
    const intlist l1 := { [0] := 0, [1] := 1 }
    const intset l2 := { [0] := 0, [1] := 1 }
    var intlist p111
    var intset p222
    var int_array_3 p333
    var integer p444
    intp.receive ((valueof (embed3[__LINE__].a[tsp_param])..100))
    intp.receive ((sizeof (embed3[tsp_param].a)))
    intp.send (valueof (embed3[__LINE__].a[tsp_param]))
    intp.send ((sizeof (embed3[tsp_param].a)))
    intp.receive (valueof (embed3[__LINE__].a[tsp_param])) -> value p444
    myprec.receive (embed3[__LINE__].a) -> value p111
    mypset.receive (embed4[__LINE__].b) -> value p222
    myparr.receive (i30) -> value p333
    alt {
      [sizeof (ilrr2) > valueof (embed3[__LINE__].a[tsp_param]) + sizeof (i30)] intp.receive (sizeof (ilrr2)) {
      }
    }
    myalt (valueof (embed3[__LINE__].a[tsp_param]) + sizeof (i30) + sizeof (l2) + l2[1] + l2[tsp_param])
  }

  testcase rec_set_tc () runs on compon
  {
    /* Indexing with template parameters for local templates.  Code
       generation is not supported.  */
    template intlist part1 := { 1, 2, 3 }
    var integer inti := 100
    const intlist l1 := { [0] := 1, [1] := 2 }
    template intlist l2 := { 0, 1 }
    template intlist l2_modified modifies l2 := { [0] := 1, [100] := 0 }
    const intset s1 := { [0] := 1, [1] := 2 }
    template intset s2 := { 0, 1 }
    template intset s3_modified modifies s2 := { [0] := 1, [1] := 0 }
    template intset s4_modified modifies s3_modified := { [0] := 0 }
    var template intlist vt1 := part4 (1 - __LINE__, tsp_param)
    var integer i := valueof (vt1[1])
    var integer j := l1[0]
    var template intset vt2 := part6 (1 - __LINE__, tsp_param)
    var template intlist vt3 := part4 (valueof (vt2[i + valueof (part5[i + 1])]), tsp_param)
    i := valueof (vt2[i + valueof (part5[i + 1])]) - valueof (vt1[valueof (vt1[i])])
    var intlist a
    a[0] := f3 (a)
    const intlist clist1 := { [0] := 1, [1] := 3, [2] := 100 }
    const intset cset1 := { [0] := 1, [1] := 3, [2] := 100 }
    myprec.receive (modifies part3 := { [100] := 100, [0] := i, [tsp_param] := tsp_param })
    mypset.receive (modifies s4_modified := { [100] := 100, [0] := i, [tsp_param] := tsp_param })
    rec_set_fn ()
  }
  control
  {
    var integer i := 4
    execute (array_tc (), valueof (fl2[tsp_param + i]))
    execute (rec_set_tc (), valueof (fl4[100][tsp_param]))
  }
}
