//[https://en.wikipedia.org/wiki/C3_linearization]:
//class O
//class A extends O
//class B extends O
//class C extends O
//class D extends O
//class E extends O
//class K1 extends A, B, C
//class K2 extends D, B, E
//class K3 extends D, A
//class Z extends K1, K2, K3


general {
    funcon-term: 
      initialise-giving initialise-generating initialise-binding finalise-failing 
      scope(collateral(
        {"O" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"O",map()),
           map())}
        ,
        {"A" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"A",map(),
                 object(fresh-atom,"O",map())),
           map(), "O")}
        ,
        {"B" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"B",map(),
                 object(fresh-atom,"O",map())),
           map(), "O")}
        ,
        {"C" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"C",map(),
                 object(fresh-atom,"O",map())),
           map(), "O")}
        ,
        {"D" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"D",map(),
                 object(fresh-atom,"O",map())),
           map(), "O")}
        ,
        {"E" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"E",map(),
                 object(fresh-atom,"O",map())),
           map(), "O")}
        ,
        {"K1" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"K1",map(),
                 object(fresh-atom,"A",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"B",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"C",map(),object(fresh-atom,"O",map()))),
           map(), "A", "B", "C")}
        ,
        {"K2" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"K2",map(),
                 object(fresh-atom,"D",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"B",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"E",map(),object(fresh-atom,"O",map()))),
           map(), "D", "B", "E")}
        ,
        {"K3" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"K3",map(),
                 object(fresh-atom,"D",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"A",map(),object(fresh-atom,"O",map()))),
           map(), "D", "A")}
        ,
        {"Z" |-> 
         class(
           thunk abstraction reference 
               object(fresh-atom,"Z",map(),
               object(fresh-atom,"K1",map(),
                 object(fresh-atom,"A",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"B",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"C",map(),object(fresh-atom,"O",map()))),
               object(fresh-atom,"K2",map(),
                 object(fresh-atom,"D",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"B",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"E",map(),object(fresh-atom,"O",map()))),
               object(fresh-atom,"K3",map(),
                 object(fresh-atom,"D",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"A",map(),object(fresh-atom,"O",map())))),
           map(), "K1", "K2", "K3")}
        ),
        sequential(
        print class-instantiator bound-value "O",
        print class-instantiator bound-value "A",
        print class-instantiator bound-value "K1"
        )
      )
        ;
}

tests {
    result-term: null-value;
    standard-out: [
    thunk abstraction reference 
               object(fresh-atom,"O",map())
    ,
    thunk abstraction reference 
               object(fresh-atom,"A",map(),
                 object(fresh-atom,"O",map()))
    ,
    thunk abstraction reference 
               object(fresh-atom,"K1",map(),
                 object(fresh-atom,"A",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"B",map(),object(fresh-atom,"O",map())),
                 object(fresh-atom,"C",map(),object(fresh-atom,"O",map())))
    ];
}
