POPL ’26 > Paper #779 > Artifact #16

Welterweight Go: Boxing, Structural Subtyping and Generics (Artifact)

Following the Documentation recommendations, this README has the following sections:


1. Purpose and claims

This artifact demonstrates a minimal prototype implementation of Welterweight Go (WG) as a command-line interpreter tool wgi.

WG captures a functional core subset of Go centering on interfaces, structs and methods with Go’s structural typing, along with a range of features that exercise Go’s type system and runtime mechanisms for type coercions, including anonymous types, underlying types, (dynamic) type assertions, (static) type conversions, generics, type sets, and generic type constraints. WG further extends Go with new features, including generic methods, method set intersections for constraints, and recursively bounded generics.

The wgi interpreter can be used to perform a few functions based on the formal model presented in the paper:

The main (and only) statement in the submitted paper regarding our implementation and aritfact is the below. While the paper does not discuss this implementation (it focusses on presenting our formal developments), we submit this artifact as an accompaniment.

l.84 We have developed a prototype based on our presented compilation approach. We plan to submit it for artifact evaluation.

This artifact supports the above statement by providing:

This artifact further provides:



2. Getting started: Download, installation, and sanity-testing instructions


2.1. Archive contents

The artifact archive paper779.zip contains:


2.2. Prerequisites

Prerequisites:

Notes on the Docker image:


2.3. Initial setup and sanity-test

Steps from scratch:

  1. Put the Docker image popl26-paper779-docker.tar.gz in some local directory; say, $MY_DIR.
  2. Load the image. In $MY_DIR, do:

    This only needs to be done once for all future sessions.
  3. Run a container with an interactive session. In $MY_DIR, do:

    Do this to start each session.
  4. Run a pre-written example. Inside the container, do:

    Expected output. The program should terminate successfully and you should see:

    …snip…

  5. Kick-the-tires: run all tests in one go. Inside the container, do:

    Expected output. A mix of examples and unit tests will be run. It may take around 1 or 2 minutes in total. You will see the file name of each example/test possibly followed by some output depending on the program. Overall you should see:

    …snip…


2.4. Main directories inside the artifact container

Directory Path inside container Env var Notes
Go path /home/paper779/artifact/go GO_PATH Workspace dir of Go installation
WG home $GO_PATH/src/github.com/rhu1/wg/ WG_HOME WG project base dir
Tests $WG_HOME/test WG project test dir
Examples $WG_HOME/examples WG examples
Go bin $GOPATH/bin/ Installation dir of wgi binary

The Go bin dir is included in $PATH.


2.5. Commands for compiling/running individual examples

Building and installing wgi inside the artifact.

Compiling/running individual WG examples.

The following commands should be run from $WG_HOME.

Some combinations are possible; e.g.

    wgi -v -eval=10 -compile -eval-lwg=10 examples/wg/hello/hello.wg

See 3. Evaluation instructions for more information on the examples.


2.6. Usage notes

Please note the following when using wgi.



3. Evaluation instructions


3.1. Running and checking the tests and examples from the paper and literature

For convenience, the below runs all the examples and tests in one go.

    cd $WG_HOME
    make test

We now explain how the examples and tests are organised.

The make test command simply enters the $WG_HOME/test directory and runs the go test commmand, which performs all of the tests coded inside these two files:

Regarding the source material of the examples:

Regarding the expected output for the unit tests and examples when running make test:

See 2.5 for explanation of the mentioned testing flags.

An example of output from make test for the latter case:

    -- ../examples/wg/oopsla20/fig4/functions.wg
    main.FF[]{}
    Bool[]@Bool[](FF[],map[Cond_D:FF.Cond_D Equal_D:FF.Equal_D Not_D:FF.Not_D],FF[]{})

See the paper for the full details of WG and LWG.

See Appendix A.1 for the output from a run of make test in full.



4. Additional artifact description


4.1. WG project structure

The WG code project under $WG_HOME has a typical Go structure:

See $WG_HOME/README.md for more notes on building and installing wgi.


4.2. Writing your own examples

Inside the container:

    apt-get install nano vim -y       // Just examples; pick your favourite editor
    cd $WG_HOME
    vim tmp/scratch.wg                // Or other editor

…edit and save the WG file…

    wgi -v -eval=-1 tmp/scratch.wg

See 2.6 for notes (warnings) on writing WG code. No syntactic sugar is supported, so empty brackets (e.g., empty generic parameter lists) and declaration separators (e.g., semicolons) all need to be written out in full.



Appendices

A.1. Expected output of make test in full

Below is the full output from a run of make test.

    cd test && go test
    
    -- ../examples/wg/oopsla20/fig4/functions.wg
    main.FF[]{}
    Bool[]@Bool[](FF[],map[Cond_D:FF.Cond_D Equal_D:FF.Equal_D Not_D:FF.Not_D],FF[]{})
    
    -- ../examples/wg/oopsla20/fig6/lists.wg
    main.Cons[main.Bool[]]{head:main.FF[]{}, tail:main.Cons[main.Bool[]]{head:main.TT[]{}, tail:main.Nil[main.Bool[]]{}}}
    List[Bool[]]@List[Bool[]](Cons[Bool[]],map[Map_D:Cons.Map_D],Cons[Bool[]]{Bool[]@Any[](FF[],map[],FF[]{}), List[Bool[]]@List[Bool[]](Cons[Bool[]],map[Map_D:Cons.Map_D],Cons[Bool[]]{Bool[]@Any[](TT[],map[],TT[]{}), List[Bool[]]@List[Bool[]](Nil[Bool[]],map[Map_D:Nil.Map_D],Nil[Bool[]]{})})})
    
    -- ../examples/wg/oopsla20/fig7/graph.wg
    main.A[]{}
    main.A[]{}
    
    -- ../examples/wg/oopsla20/fig10/nomono.wg
    main.Box[main.Box[main.Box[main.Box[main.D[]]]]]{value:main.Box[main.Box[main.Box[main.D[]]]]{value:main.Box[main.Box[main.D[]]]{value:main.Box[main.D[]]{value:main.D[]{}}}}}
    Any[]@Any[](Box[Box[Box[Box[D[]]]]],map[],Box[Box[Box[Box[D[]]]]]{Box[Box[Box[D[]]]]@Any[](Box[Box[Box[D[]]]],map[],Box[Box[Box[D[]]]]{Box[Box[D[]]]@Any[](Box[Box[D[]]],map[],Box[Box[D[]]]{Box[D[]]@Any[](Box[D[]],map[],Box[D[]]{D[]@Any[](D[],map[],D[]{})})})})})
    
    -- ../examples/wg/oopsla20/fig19/dispatcher.wg
    main.Int[]{}
    main.Int[]{}
    
    -- ../examples/wg/misc/irregular/irregular.wg
    main.Node[main.Nat[]]{label:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}, children:main.Node[main.Pair[main.Nat[]]]{label:main.Pair[main.Nat[]]{fst:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}, snd:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}}, children:main.Node[main.Pair[main.Pair[main.Nat[]]]]{label:main.Pair[main.Pair[main.Nat[]]]{fst:main.Pair[main.Nat[]]{fst:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}}, snd:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}}}}, snd:main.Pair[main.Nat[]]{fst:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}}}}, snd:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}}}}}}}, children:main.Leaf[main.Pair[main.Pair[main.Pair[main.Nat[]]]]]{}}}}
    Balanced[Nat[]]@Balanced[Nat[]](Node[Nat[]],map[BalancedMap_D:Node.BalancedMap_D],Node[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})}), Balanced[Pair[Nat[]]]@Balanced[Pair[Nat[]]](Node[Pair[Nat[]]],map[BalancedMap_D:Node.BalancedMap_D],Node[Pair[Nat[]]]{Pair[Nat[]]@Any[](Pair[Nat[]],map[],Pair[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})}), Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})})}), Balanced[Pair[Pair[Nat[]]]]@Balanced[Pair[Pair[Nat[]]]](Node[Pair[Pair[Nat[]]]],map[BalancedMap_D:Node.BalancedMap_D],Node[Pair[Pair[Nat[]]]]{Pair[Pair[Nat[]]]@Any[](Pair[Pair[Nat[]]],map[],Pair[Pair[Nat[]]]{Pair[Nat[]]@Any[](Pair[Nat[]],map[],Pair[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})})}), Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})})})})}), Pair[Nat[]]@Any[](Pair[Nat[]],map[],Pair[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})})})})}), Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})})})})})})})}), Balanced[Pair[Pair[Pair[Nat[]]]]]@Balanced[Pair[Pair[Pair[Nat[]]]]](Leaf[Pair[Pair[Pair[Nat[]]]]],map[BalancedMap_D:Leaf.BalancedMap_D],Leaf[Pair[Pair[Pair[Nat[]]]]]{})})})})
    
    -- ../examples/wg/misc/irregular/irregular2.wg
    Node[Nat[]]{Succ[]{Succ[]{Zero[]{}}}, Leaf[Pair[Nat[]]]{}}
    Balanced[Nat[]]@Balanced[Nat[]](Node[Nat[]],map[BalancedMap_D:Node.BalancedMap_D],Node[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})}), Balanced[Pair[Nat[]]]@Balanced[Pair[Nat[]]](Leaf[Pair[Nat[]]],map[BalancedMap_D:Leaf.BalancedMap_D],Leaf[Pair[Nat[]]]{})})
    
    -- ../examples/wg/misc/monomorph/monomorph.wg
    main.Pair[main.List[main.Bool[]], main.List[main.Nat[]]]{Fst:main.Cons[main.Bool[]]{head:main.FF[]{}, tail:main.Cons[main.Bool[]]{head:main.TT[]{}, tail:main.Nil[main.Bool[]]{}}}, Snd:main.Cons[main.Nat[]]{head:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}, tail:main.Cons[main.Nat[]]{head:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}, tail:main.Cons[main.Nat[]]{head:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Succ[]{pred:main.Zero[]{}}}}}, tail:main.Nil[main.Nat[]]{}}}}}
    main.Pair[main.List[main.Bool[]], main.List[main.Nat[]]]{Fst:List[Bool[]]@Any[](Cons[Bool[]],map[],Cons[Bool[]]{Bool[]@Any[](FF[],map[],FF[]{}), List[Bool[]]@List[Bool[]](Cons[Bool[]],map[Map_D:Cons.Map_D],Cons[Bool[]]{Bool[]@Any[](TT[],map[],TT[]{}), List[Bool[]]@List[Bool[]](Nil[Bool[]],map[Map_D:Nil.Map_D],Nil[Bool[]]{})})}), Snd:List[Nat[]]@Any[](Cons[Nat[]],map[],Cons[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})}), List[Nat[]]@List[Nat[]](Cons[Nat[]],map[Map_D:Cons.Map_D],Cons[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})}), List[Nat[]]@List[Nat[]](Cons[Nat[]],map[Map_D:Cons.Map_D],Cons[Nat[]]{Nat[]@Any[](Succ[],map[],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Succ[],map[Add_D:Succ.Add_D],Succ[]{Nat[]@Nat[](Zero[],map[Add_D:Zero.Add_D],Zero[]{})})})})}), List[Nat[]]@List[Nat[]](Nil[Nat[]],map[Map_D:Nil.Map_D],Nil[Nat[]]{})})})})}
    
    -- ../examples/wg/monom/mono-ko/box.wg
    
    -- ../examples/wg/monom/mono-ko/box2.wg
    
    -- ../examples/wg/monom/mono-ko/incompleteness-subtyping.wg
    S[]{}
    S[]{}
    
    -- ../examples/wg/monom/mono-ko/monom-imp.wg
    
    -- ../examples/wg/monom/mono-ko/mutual-poly-rec.wg
    
    -- ../examples/wg/monom/mono-ko/mutual-rec-iface.wg
    
    -- ../examples/wg/monom/mono-ko/nested-fix.wg
    
    -- ../examples/wg/monom/mono-ko/two-type-param.wg
    
    -- ../examples/wg/hello/hello.wg
    
    -- ../examples/wg/hello/fmtprintf/fmtprintf.wg
    
    -- ./wg/ok/Test01.wg
    A[]{}
    A[]{}
    
    -- ./wg/ok/Test02.wg
    S[]{}
    Any[]@Any[](S[],map[],S[]{})
    
    -- ./wg/ok/Test03.wg
    A[]{}
    A[]{}
    
    -- ./wg/ok/Test04.wg
    B[]{}
    B[]{}
    
    -- ./wg/ok/Test05.wg
    MyInt[](43)
    MyInt[](43)
    
    -- ./wg/ok/Test06.wg
    A[]{}
    A[]{}
    
    -- ./wg/ko/Test07.wg
    TypeDecl not OK:
    
    -- ./wg/ok/Test09.wg
    A[]{int(42)}
    A[]{int(42)}
    
    -- ./wg/ok/Test09.wg
    A[]{int(42)}
    A[]{int(42)}
    
    -- ./wg/ok/Test10.wg
    
    -- ./wg/ok/Test11.wg
    S[]{}
    S[]{}
    
    -- ./wg/ko/Test12.wg
    Arg expr type must be assignable to param type: arg=A3[], param=I2[]@I[I2[]]
    
    -- ./wg/ok/Test13.wg
    Cell[int]{int(42)}
    interface {}@interface {}(Cell[int],map[],Cell[int]{int@interface {}(int,map[],int(42))})
    
    -- ./wg/ko/Test14.wg
    Type actual must implement type formal: actual=Cell[int], param=I[]
    
    -- ./wg/ko/Test15.wg
    Arg expr type must be assignable to param type: arg=Cell[int], param=struct { f int@int }@I[]
    
    -- ./wg/ko/Test16.wg
    Type actual must implement type formal: actual=struct { x int@int }, param=I[]
    
    -- ./wg/ok/Test17.wg
    int(3)
    int(3)
    
    -- ./wg/ok/Test18.wg
    int(84)
    int(84)
    
    -- ./wg/ok/Test19.wg
    MyInt[](84)
    MyInt[](84)
    
    -- ./wg/ok/Test20.wg
    int(84)
    int(84)
    
    -- ./wg/ko/Test21.wg
    TypeDecl not OK:
    
    -- ./wg/ko/Test22.wg
    TypeDecl not OK:
    
    -- ./wg/ok/Test23.wg
    struct { f int@int }{int(42)}
    struct { f int@int }{int(42)}
    
    -- ./wg/ok/Test24.wg
    int(42)
    int(42)
    
    -- ./wg/ko/Test25.wg
    Type I[] not struct: I[]{int(42)}:
    
    -- ../examples/wg/popl26/fig1/join.wg
    int(42)
    int(42)
    
    -- ../examples/wg/popl26/fig1/joinOp.wg
    int(45)
    int(45)
    
    -- ../examples/wg/popl26/sec2_2/bar.wg
    int(42)
    int(42)
    
    -- ../examples/wg/popl26/fig2/extjoinConsMyInt.wg
    MyInt[](41)
    MyInt[](41)
    
    -- ../examples/wg/popl26/fig2/extjoinConsMyIntOp.wg
    MyInt[](44)
    MyInt[](44)
    
    -- ../examples/wg/popl26/fig2/extjoinMyIntCons.wg
    MyInt[](40)
    MyInt[](40)
    
    -- ../examples/wg/popl26/fig2/extjoinMyIntConsOp.wg
    MyInt[](43)
    MyInt[](43)
    
    -- ../examples/wg/popl26/sec3/ordered.wg
    int(1)
    int(1)
    
    -- ../examples/wg/popl26/sec3/ordered2.wg
    MyInt[](3)
    MyInt[](3)
    
    -- ../examples/wg/popl26/sec3/ordered3.wg
    struct {}{}
    struct {}{}
    
    -- ../examples/wg/popl26/sec3/ordered4.wg
    Type actual must implement type formal: actual=A[], param=Ordered[]
    
    -- ../examples/wg/popl26/sec3/ordered5.wg
    struct {}{}
    struct {}{}
    
    -- ../examples/wg/popl26/ex3_1/assign.wg
    Point[]{int(1), int(1)}
    Point[]{int(1), int(1)}
    
    -- ../examples/wg/popl26/ex3_1/assign2.wg
    Point[]{int(1), int(1)}
    Point[]{int(1), int(1)}
    
    -- ../examples/wg/popl26/ex3_1/assign3.wg
    Point[]{int(1), int(1)}
    Point[]{int(1), int(1)}
    
    -- ../examples/wg/popl26/ex3_1/assign4.wg
    struct { x int@int; y int@int }{int(1), int(1)}
    struct { x int@int; y int@int }{int(1), int(1)}
    
    -- ../examples/wg/popl26/ex3_1/assign5.wg
    struct { x int@int; y int@int }{int(1), int(1)}
    struct { x int@int; y int@int }{int(1), int(1)}
    
    -- ../examples/wg/popl26/ex3_2/constraint.wg
    MyStruct[]{int(43)}
    MyStruct[]{int(43)}
    
    -- ../examples/wg/popl26/ex3_2/constraint2.wg
    MyStruct[]{int(43)}
    MyStruct[]{int(43)}
    
    -- ../examples/wg/popl26/ex3_2/constraint3.wg
    int(2)
    int(2)
    
    -- ../examples/wg/popl26/ex3_2/constraint4.wg
    int(42)
    int(42)
    
    -- ../examples/wg/popl26/ex3_2/constraintOp.wg
    int(85)
    int(85)
    
    -- ../examples/wg/popl26/sec4/shape.wg
    Circle[]{Point[]{int(1), int(1)}, int(2)}
    Shape[]@Shape[](Circle[],map[draw_D:Circle.draw_D shape_D:Circle.shape_D],Circle[]{Point[]{int(1), int(1)}, int(2)})
    
    -- ../examples/wg/popl26/sec4/shape2.wg
    Circle[]{Point[]{int(1), int(1)}, int(2)}
    interface {}@interface {}(Circle[],map[],Circle[]{Point[]{int(1), int(1)}, int(2)})
    
    -- ../examples/wg/popl26/sec4/shape3.wg
    Circle[]{Point[]{int(1), int(1)}, int(2)}
    interface {}@interface {}(Circle[],map[],Circle[]{Point[]{int(1), int(1)}, int(2)})
    
    -- ../examples/wg/popl26/sec4/shape4.wg
    Circle[]{Point[]{int(1), int(1)}, int(2)}
    interface {}@interface {}(Circle[],map[],Circle[]{Point[]{int(1), int(1)}, int(2)})
    
    -- ../examples/wg/popl26/sec4/shape5.wg
    struct { p Point[]@Point[]; r int@int }{Point[]{int(1), int(1)}, int(2)}
    interface {}@interface {}(struct { p Point[]@Point[]; r int@int },map[],struct { p Point[]@Point[]; r int@int }{Point[]{int(1), int(1)}, int(2)})
    
    -- ../examples/wg/popl26/sec5/cell.wg
    Cell[int]{int(42)}
    Cell[int]{int@interface {}(int,map[],int(42))}
    
    -- ../examples/wg/popl26/sec5/cell2.wg
    StringerCell[]{MyInt[](42)}
    StringerCell[]{MyStringer[]@MyStringer[](MyInt[],map[String_D:MyInt.String_D],MyInt[](42))}
    
    -- ../examples/wg/popl26/ex5_1/process.wg
    int(42)
    int(42)
    
    -- ../examples/wg/popl26/ex5_1/process2.wg
    int(42)
    int(42)
    
    -- ../examples/wg/popl26/ex5_1/process3.wg
    int(43)
    int(43)
    
    -- ../examples/wg/popl26/ex5_1/process4.wg
    int(44)
    int(44)
    PASS
    ok      github.com/rhu1/wg/test 105.873s