nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.39k stars 1.47k forks source link

Maybe a tiny ARC bug #17712

Closed StefanSalewski closed 3 years ago

StefanSalewski commented 3 years ago

Unfortunately I can not create a tiny example that shows the bug -- my tiny example works fine.

I have this proc, which is a bit ugly still as it is converted from my ugly Ruby code:

proc nubly(r: Router; collapse = false) =
  var replaced = true
  var rep_c = 0
  while replaced:
    replaced = false
    rep_c += 1
    for cv in r.vertices:
      var stepPos = cv.attached_nets.len
      while stepPos > 0:
        dec(stepPos)
        var step = cv.attached_nets[stepPos]
      #for step in cv.attached_nets.reversed:
        let (prev_step, nxt_step) = (step.pstep, step.nstep)
        let (pv, nv) = (step.prev, step.next)
        var d = (hypot(cv.x - pv.x, cv.y - pv.y) - (prev_step.radius - step.radius).abs.float * 1.02).float
        if d < 0:
          if step.radius < prev_step.radius:
            step.radius -= d
            replaced = true
          continue
        d = (hypot(cv.x - nv.x, cv.y - nv.y) - (nxt_step.radius - step.radius).abs.float * 1.02).float
        if d < 0:
          if step.radius < nxt_step.radius:
            step.radius -= d
            replaced = true
          continue
        var (hx, hy) = convex_kkk(prev_step, step, nxt_step, r)
        step.xt = hx != NilFloat
        if collapse and step.xt:
          let (pv, nv) = (step.prev, step.next)
          var hv0 = XVertex()
          initialize(hv0, hx, hy)
          assert hv0.x != NaN
          replaced = true
          let pvx = pv.x
          let pvy = pv.y
          let nvx = nv.x
          let nvy = nv.y
          var pp = prev_step.pstep
          if (pp != nil):
            (hx, hy) = convex_kkk(pp, prev_step, step)
          var ppv: XVertex
          if pp != nil and hx != NilFloat:
            ppv = XVertex()
            initialize(ppv, hx, hy)
          else:
            ppv = pv
          if ppv.x == 0:
            echo ppv; assert false
          let nn = nxt_step.nstep
          if nn != nil:
            (hx, hy) = convex_kkk(step, nxt_step, nn)
          var nnv: XVertex
          if nn != nil and hx != NilFloat:
            nnv = XVertex()
            initialize(nnv, hx, hy)
          else:
            nnv = nv
          hx = nvx - pvx
          hy = nvy - pvy
          var vec_x, vec_y: float
          if step.rgt:
            (vec_x, vec_y) = (hy, -hx)
          else:
            (vec_x, vec_y) = (-hy, hx)
          let hv3 = XVertex(x: pvx + hx / 2 + vec_x, y: pvy + hy / 2 + vec_y)
          initialize(hv3, pvx + hx / 2 + vec_x, pvy + hy / 2 + vec_y)
          hx *= 2
          hy *= 2
          vec_x *= 2
          vec_y *= 2
          let hv4 = XVertex(x: pvx - hx + vec_x, y: pvy - hy + vec_y, tradius: 100)
          initialize(hv4, pvx - hx + vec_x, pvy - hy + vec_y)
          let hv5 = XVertex(x: nvx + hx + vec_x, y: nvy + hy + vec_y, tradius: 100)
          initialize(hv5, nvx + hx + vec_x, nvy + hy + vec_y)
          var rep = vertices_in_polygon(@[ppv, hv0, nnv, hv3], r.vertices) - [pv, nv, ppv, cv, nnv, hv3]
          #discard hv0 == nil
          #discard hv3 == nil
          for el in [ppv, hv0, nnv, hv3]:
            echo "-----"
            #echo el.xid, " ", el.x, " ", el.y, " ", el.x == NaN
            r.pic.arc(el.x, el.y, 0.3* Pin_Radius, 0, 2*math.PI)
            if el.trgt:
              r.pic.setSource(0,0,1)
            else:
              r.pic.setSource(0,0,1)
            r.pic.fill
            r.pic.stroke
          let hhh = rep
          if rep.len > 0:
            let net = step.net_desc
            for v in rep:
              v.trgt = not step.rgt
              v.tradius = v.radius + [net.trace_clearance, v.separation].max + net.trace_width / 2
            pv.trgt = step.pstep.rgt
            pv.tradius = step.pstep.radius
            nv.trgt = step.nstep.rgt
            nv.tradius = step.nstep.radius
            rep = new_convex_vertices(rep, pv, nv, hv4, hv5)
            for el in rep:
              if true: break
              r.pic.arc(el.x, el.y, 0.3* Pin_Radius, 0, 2*math.PI)
              if el.trgt:
                r.pic.setSource(1,0,0)
              else:
                r.pic.setSource(0,1,0)
              r.pic.fill
              r.pic.stroke
          smart_replace(step, rep)

In this form the program compiled with arc crash:

Traceback (most recent call last)
/home/salewski/Router/router.nim(2536) router
/home/salewski/Router/router.nim(2507) main
/home/salewski/Router/router.nim(2379) nubly
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Segmentation fault (core dumped)

Uncomenting the two

          #discard hv0 == nil
          #discard hv3 == nil

makes it work fine. Initially I used echo instead of discard, with echo enabled it works fine too. Guess was that scope based destructors release the local references hv0 and hv3 too early. And indeed, when we look at the C sources

                                        nimln_(2370, "/home/salewski/Router/router.nim");
                                        blitTmp = hv0;
                                        hv0 = 0;
                                        colontmpD__10.p->data[1] = blitTmp;
                                        colontmpD__8 = 0;
                                        nimln_(995, "/home/salewski/Nim/lib/system.nim");
                                        eqcopy__router_302(&colontmpD__8, nnv);
                                        if (NIM_UNLIKELY(*nimErr_)) goto LA41_;
                                        colontmpD__10.p->data[2] = colontmpD__8;
                                        nimln_(2370, "/home/salewski/Router/router.nim");
                                        colontmpD__9 = 0;
                                        nimln_(995, "/home/salewski/Nim/lib/system.nim");
                                        eqcopy__router_302(&colontmpD__9, hv3);
                                        if (NIM_UNLIKELY(*nimErr_)) goto LA41_;
                                        colontmpD__10.p->data[3] = colontmpD__9;
                                        nimln_(2370, "/home/salewski/Router/router.nim");
                                        colontmpD__11 = vertices_in_polygon_router_14986(colontmpD__10, (*r).vertices);
                                        if (NIM_UNLIKELY(*nimErr_)) goto LA41_;
                                        nimZeroMem((void*)T94_, sizeof(tyArray__fnBoDLr3bv7Bhq1iCxEZfw));
                                        T94_[0] = pv_2;
                                        T94_[1] = nv_2;
                                        T94_[2] = ppv;
                                        T94_[3] = (*cv);
                                        T94_[4] = nnv;
                                        T94_[5] = hv3;
                                        rep = minus__router_29582(colontmpD__11.p->data, colontmpD__11.len, T94_, 6);
                                        if (NIM_UNLIKELY(*nimErr_)) goto LA41_;
                                        {
                                            tyObject_XVertexcolonObjectType___aIpZROovGVS9cYHRNL1CHaQ* el;
                                            NI i_2;
                                            el = (tyObject_XVertexcolonObjectType___aIpZROovGVS9cYHRNL1CHaQ*)0;
                                            nimln_(2376, "/home/salewski/Router/router.nim");
                                            el = 0;
                                            nimln_(33, "/home/salewski/Nim/lib/system/iterators.nim");
                                            i_2 = ((NI) 0);
                                            {
                                                nimln_(34, "/home/salewski/Nim/lib/system/iterators.nim");
                                                while (1) {
                                                    tyArray__zvo3ify9aboCono8rdTKO5w T99_;
                                                    NI TM__tNvW9c8Ok7k9bk1L3sBh38ZA_655;
                                                    nimln_(995, "/home/salewski/Nim/lib/system.nim");
                                                    nimZeroMem((void*)T99_, sizeof(tyArray__zvo3ify9aboCono8rdTKO5w));
                                                    T99_[0] = ppv;
                                                    T99_[1] = hv0;
                                                    T99_[2] = nnv;
                                                    T99_[3] = hv3;
                                                    eqcopy__router_302(&el, T99_[(i_2)- 0]);
                                                    if (NIM_UNLIKELY(*nimErr_)) goto LA96_;

may confirm this impression? First hv0 = 0; and later T99_[1] = hv0;

Will close this issue tomorrow, maybe I can reopen in some months when I have more information or a self contained tiny example.

StefanSalewski commented 3 years ago

Maybe valgrind output may help:

nim --version
Nim Compiler Version 1.5.1 [Linux: amd64]
Compiled at 2021-04-13
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: 8e6b87a917a5d09a70d1e29f0b06915c29fcac6b
active boot switches: -d:release

nim c --gc:arc -d:useMalloc router.nim

$ valgrind ./router 2
==319647== Memcheck, a memory error detector
==319647== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==319647== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==319647== Command: ./router 2
==319647== 
reached destination
reached destination
reached destination
:::51661.0 71596.0 0.0 false 35458.0 68046.0 3400.0 true 
:::35458.0 68046.0 3400.0 true 32513.0 54422.0 3400.0 true 
drawing lines
:::51661.0 71596.0 35426.55620422228 71445.85459802432 
:::32134.75507425575 68764.36144350535 29189.75507425575 55140.36144350535 
==>32708.96074671409 1.167396893401115 -0.1949764592388275
:::35458.0 68046.0 3400.0 true 32513.0 54422.0 3400.0 true 
:::32513.0 54422.0 3400.0 true 25244.0 52603.0 3400.0 false 
drawing lines
:::32134.75507425575 68764.36144350535 29189.75507425575 55140.36144350535 
:::29173.10186893891 55058.45932637883 28583.89813106109 51966.54067362117 
==>29180.92510879 1.00299829048073 -0.01327764803269028
:::32513.0 54422.0 3400.0 true 25244.0 52603.0 3400.0 false 
:::25244.0 52603.0 3400.0 false 31506.0 52465.0 0.0 false 
drawing lines
:::29173.10186893891 55058.45932637883 28583.89813106109 51966.54067362117 
:::27152.07222776584 55417.11804543248 31506.0 52465.0 
==>29002.37460854105 0.2897592961863815 0.4249731455296395
:::51661.0 71596.0 0.0 false 35458.0 68046.0 3400.0 true 
:::35458.0 68046.0 3400.0 true 32513.0 54422.0 3400.0 true 
drawing lines
:::51661.0 71596.0 35426.55620422228 71445.85459802432 
:::32134.75507425575 68764.36144350535 29189.75507425575 55140.36144350535 
==>32708.96074671409 1.167396893401115 -0.1949764592388275
:::35458.0 68046.0 3400.0 true 32513.0 54422.0 3400.0 true 
:::32513.0 54422.0 3400.0 true 25244.0 52603.0 3400.0 false 
drawing lines
:::32134.75507425575 68764.36144350535 29189.75507425575 55140.36144350535 
:::29173.10186893891 55058.45932637883 28583.89813106109 51966.54067362117 
==>29180.92510879 1.00299829048073 -0.01327764803269028
:::32513.0 54422.0 3400.0 true 25244.0 52603.0 3400.0 false 
:::25244.0 52603.0 3400.0 false 31506.0 52465.0 0.0 false 
drawing lines
:::29173.10186893891 55058.45932637883 28583.89813106109 51966.54067362117 
:::27152.07222776584 55417.11804543248 31506.0 52465.0 
==>29002.37460854105 0.2897592961863815 0.4249731455296395
:::35458.0 68046.0 3400.0 true 32513.0 54422.0 3400.0 true 
:::32513.0 54422.0 3400.0 true 25244.0 52603.0 3400.0 false 
==>29180.92510879 1.00299829048073 -0.01327764803269028
-----
-----
==319647== Invalid read of size 8
==319647==    at 0x192704: nubly_router_29473 (in /home/salewski/Router/router)
==319647==    by 0x1976D7: main_router_29835 (in /home/salewski/Router/router)
==319647==    by 0x197ABB: NimMainModule (in /home/salewski/Router/router)
==319647==    by 0x1979C0: NimMainInner (in /home/salewski/Router/router)
==319647==    by 0x1979FC: NimMain (in /home/salewski/Router/router)
==319647==    by 0x197A4A: main (in /home/salewski/Router/router)
==319647==  Address 0xe0 is not stack'd, malloc'd or (recently) free'd
==319647== 
Traceback (most recent call last)
/home/salewski/Router/router.nim(2536) router
/home/salewski/Router/router.nim(2507) main
/home/salewski/Router/router.nim(2379) nubly
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
==319647== 
==319647== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==319647==    at 0x49E56EF: raise (raise.c:45)
==319647==    by 0x112551: signalHandler (in /home/salewski/Router/router)
==319647==    by 0x49E578F: ??? (in /lib64/libc-2.33.so)
==319647==    by 0x192703: nubly_router_29473 (in /home/salewski/Router/router)
==319647==    by 0x1976D7: main_router_29835 (in /home/salewski/Router/router)
==319647==    by 0x197ABB: NimMainModule (in /home/salewski/Router/router)
==319647==    by 0x1979C0: NimMainInner (in /home/salewski/Router/router)
==319647==    by 0x1979FC: NimMain (in /home/salewski/Router/router)
==319647==    by 0x197A4A: main (in /home/salewski/Router/router)
==319647== 
==319647== HEAP SUMMARY:
==319647==     in use at exit: 2,792,366 bytes in 1,866 blocks
==319647==   total heap usage: 6,271 allocs, 4,405 frees, 5,822,082 bytes allocated
==319647== 
==319647== LEAK SUMMARY:
==319647==    definitely lost: 11 bytes in 1 blocks
==319647==    indirectly lost: 0 bytes in 0 blocks
==319647==      possibly lost: 2,692,750 bytes in 1,384 blocks
==319647==    still reachable: 99,605 bytes in 481 blocks
==319647==                       of which reachable via heuristic:
==319647==                         length64           : 840 bytes in 3 blocks
==319647==                         newarray           : 41,784 bytes in 901 blocks
==319647==         suppressed: 0 bytes in 0 blocks
==319647== Rerun with --leak-check=full to see details of leaked memory
==319647== 
==319647== For lists of detected and suppressed errors, rerun with: -s
==319647== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

I can not test with refc GC because of

https://github.com/nim-lang/Nim/issues/17602

currently.

ghost commented 3 years ago

By the way, you can use --expandArc:procName so that Nim compiler shows the Nim source code after frontend processing (including destructors injection)

StefanSalewski commented 3 years ago
$ nim c --gc:arc -d:useMalloc --expandArc:nubly router.nim
Hint: used config file '/home/salewski/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/salewski/Nim/config/config.nims' [Conf]
................................................
/home/salewski/quickhulldisk/point2d.nim(111, 31) Hint: conversion from Point2D to itself is pointless [ConvFromXtoItselfNotNeeded]
.....
/home/salewski/quickhulldisk/geometricfunction2d.nim(134, 58) Hint: conversion from Circle2D to itself is pointless [ConvFromXtoItselfNotNeeded]
/home/salewski/quickhulldisk/geometricfunction2d.nim(134, 77) Hint: conversion from Circle2D to itself is pointless [ConvFromXtoItselfNotNeeded]
/home/salewski/quickhulldisk/convexhullofdisks.nim(17, 6) Hint: 'get_hull_disks' is declared but not used [XDeclaredButNotUsed]
/home/salewski/quickhulldisk/convexhullofdisks.nim(14, 6) Hint: 'get_input_disks' is declared but not used [XDeclaredButNotUsed]
/home/salewski/quickhulldisk/quickhulldisk.nim(154, 9) Hint: 'currTriangleApex' is declared but not used [XDeclaredButNotUsed]
/home/salewski/quickhulldisk/quickhulldisk.nim(336, 7) Hint: 'stacknr' is declared but not used [XDeclaredButNotUsed]
/home/salewski/quickhulldisk/quickhulldisk.nim(1, 56) Warning: imported and not used: 'geometricfunction2d' [UnusedImport]
/home/salewski/Router/router.nim(1011, 42) Warning: Number of spaces around '*' is not consistent [Spacing]
/home/salewski/Router/router.nim(1076, 7) Hint: 'pcb_start_angle' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1541, 13) Hint: 'only_outer' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1397, 7) Hint: 'h' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1442, 7) Hint: 'old_distance' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1738, 7) Hint: 'v1x' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1740, 7) Hint: 'v2x' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1741, 7) Hint: 'v2y' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1739, 7) Hint: 'v1y' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1790, 3) Warning: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
/home/salewski/Router/router.nim(1795, 9) Hint: 'bx' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1794, 9) Hint: 'ay' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1796, 9) Hint: 'by' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1791, 14) Hint: 'bb' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1793, 9) Hint: 'ax' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1791, 18) Hint: 'nn' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1791, 10) Hint: 'aa' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1790, 8) Hint: 'new_bor_list' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(2379, 38) Warning: Number of spaces around '*' is not consistent [Spacing]
/home/salewski/Router/router.nim(2399, 40) Warning: Number of spaces around '*' is not consistent [Spacing]
/home/salewski/Router/router.nim(2386, 15) Hint: 'hhh' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(2428, 11) Hint: 'sep' is declared but not used [XDeclaredButNotUsed]
/home/salewski/.nimble/pkgs/cdt-0.1.0/cdt/edges.nim(15, 15) Warning: 'q.e[0].next = q.e[0]' creates an uncollectable ref cycle; annotate 'next' with .cursor [CycleCreated]
/home/salewski/.nimble/pkgs/cdt-0.1.0/cdt/edges.nim(17, 15) Warning: 'q.e[2].next = q.e[2]' creates an uncollectable ref cycle; annotate 'next' with .cursor [CycleCreated]
/home/salewski/Router/router.nim(973, 42) Hint: passing 'v1.name' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(973, 60) Hint: passing 'v2.name' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Nim/lib/pure/collections/sequtils.nim(199, 18) Hint: passing 'prev' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Nim/lib/pure/collections/sequtils.nim(203, 22) Hint: passing 'prev' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1857, 28) Hint: passing 'net_desc.t1_name' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1857, 46) Hint: passing 'net_desc.t2_name' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1436, 25) Hint: passing 'parents[u]' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1436, 25) Hint: passing 'parents[u]' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1470, 26) Hint: passing 'uu.vertex.neighbors' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1509, 27) Hint: passing 'uu.vertex.neighbors' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1563, 29) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1632, 32) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1677, 33) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1563, 29) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1632, 32) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(1677, 33) Hint: passing 'min' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it [Performance]
/home/salewski/Router/router.nim(572, 20) Warning: 'el.ref = el' creates an uncollectable ref cycle; annotate 'ref' with .cursor [CycleCreated]
--expandArc: nubly

var replaced = true
var rep_c = 0
block :tmp:
  while replaced:
    replaced = false
    rep_c += 1
    block :tmp_1:
      var cv
      var i = 0
      let L = len(r.vertices)
      block :tmp_2:
        while i < L:
          cv = r.vertices[i]
          var stepPos = len(cv.attached_nets)
          block :tmp_3:
            while (
              0 < stepPos):
              block :tmp_4:
                var
                  step
                  :tmp_5
                  :tmpD
                  :tmpD_1
                  prev_step
                  nxt_step
                  :tmp_6
                  :tmpD_2
                  :tmpD_3
                  pv
                  nv
                try:
                  dec(stepPos, 1)
                  `=copy`(step, cv.attached_nets[stepPos])
                  :tmp_5 = default()
                  :tmp_5 = (
                    wasMoved(:tmpD)
                    `=copy`(:tmpD, step.pstep)
                    :tmpD,
                    wasMoved(:tmpD_1)
                    `=copy`(:tmpD_1, step.nstep)
                    :tmpD_1)
                  prev_step = :tmp_5[0]
                  nxt_step = :tmp_5[1]
                  :tmp_6 = default()
                  :tmp_6 = (
                    wasMoved(:tmpD_2)
                    `=copy_1`(:tmpD_2, step.prev)
                    :tmpD_2,
                    wasMoved(:tmpD_3)
                    `=copy_1`(:tmpD_3, step.next)
                    :tmpD_3)
                  pv = :tmp_6[0]
                  nv = :tmp_6[1]
                  var d = float(hypot(cv.x - pv.x, cv.y - pv.y) -
                      float(abs(prev_step.radius - step.radius)) * 1.02)
                  if d < 0.0:
                    if step.radius < prev_step.radius:
                      step.radius -= d
                      replaced = true
                    break :tmp_4
                  d = float(hypot(cv.x - nv.x, cv.y - nv.y) -
                      float(abs(nxt_step.radius - step.radius)) * 1.02)
                  if d < 0.0:
                    if step.radius < nxt_step.radius:
                      step.radius -= d
                      replaced = true
                    break :tmp_4
                  var (hx, hy) = convex_kkk(prev_step, step, nxt_step, r)
                  step.xt =
                    not (hx == 1e+300)
                  if collapse and step.xt:
                    var
                      :tmp_7
                      :tmpD_4
                      :tmpD_5
                      pv_1
                      nv_1
                      hv0
                      pp
                      ppv
                      nn
                      nnv
                      hv3
                      hv4
                      hv5
                      rep
                      :tmpD_6
                      :tmpD_7
                      :tmpD_8
                      :tmpD_9
                      :tmpD_10
                      hhh
                    try:
                      :tmp_7 = default()
                      :tmp_7 = (
                        wasMoved(:tmpD_4)
                        `=copy_1`(:tmpD_4, step.prev)
                        :tmpD_4,
                        wasMoved(:tmpD_5)
                        `=copy_1`(:tmpD_5, step.next)
                        :tmpD_5)
                      pv_1 = :tmp_7[0]
                      nv_1 = :tmp_7[1]
                      hv0 = XVertex()
                      initialize(hv0, hx, hy, 2000.0, 800.0)
                      const
                        loc`gensym451 = (
                          filename: "/home/salewski/Router/router.nim",
                          line: 2327, column: 17)
                        ploc`gensym451 = "/home/salewski/Router/router.nim(2327, 18)"
                      bind instantiationInfo
                      mixin failedAssertImpl
                      {.line: (filename: "/home/salewski/Router/router.nim",
                               line: 2327, column: 17).}:
                        if not
                          not (hv0.x == 0x7FF7FFFFFFFFFFFF'f64):
                          failedAssertImpl("/home/salewski/Router/router.nim(2327, 18) `hv0.x != NaN` ")
                      replaced = true
                      let pvx = pv_1.x
                      let pvy = pv_1.y
                      let nvx = nv_1.x
                      let nvy = nv_1.y
                      `=copy`(pp, prev_step.pstep)
                      if (
                        not (pp == nil)):
                        let _ = convex_kkk(pp, prev_step, step, nil)
                        hx = _[0]
                        hy = _[1]
                      ppv = default()
                      if
                        not (pp == nil) and
                        not (hx == 1e+300):
                        `=sink`(ppv, XVertex())
                        initialize(ppv, hx, hy, 2000.0, 800.0)
                      else:
                        `=copy_1`(ppv, pv_1)
                      if ppv.x == 0.0:
                        var :tmpD_11
                        try:
                          echo [
                            :tmpD_11 = `$`(Vertex(ppv))
                            :tmpD_11]
                          const
                            loc`gensym456 = (
                              filename: "/home/salewski/Router/router.nim",
                              line: 2343, column: 29)
                            ploc`gensym456 = "/home/salewski/Router/router.nim(2343, 30)"
                          bind instantiationInfo
                          mixin failedAssertImpl
                          {.line: (filename: "/home/salewski/Router/router.nim",
                                   line: 2343, column: 29).}:
                            if true:
                              failedAssertImpl("/home/salewski/Router/router.nim(2343, 30) `false` ")
                        finally:
                          `=destroy`(:tmpD_11)
                      `=copy`(nn, nxt_step.nstep)
                      if (
                        not (nn == nil)):
                        let __1 = convex_kkk(step, nxt_step, nn, nil)
                        hx = __1[0]
                        hy = __1[1]
                      nnv = default()
                      if
                        not (nn == nil) and
                        not (hx == 1e+300):
                        `=sink`(nnv, XVertex())
                        initialize(nnv, hx, hy, 2000.0, 800.0)
                      else:
                        `=copy_1`(nnv, nv_1)
                      hx = nvx - pvx
                      hy = nvy - pvy
                      var vec_x: float
                      var vec_y: float
                      if step.rgt:
                        let __2 = (hy, -hx)
                        vec_x = __2[0]
                        vec_y = __2[1]
                      else:
                        let __3 = (-hy, hx)
                        vec_x = __3[0]
                        vec_y = __3[1]
                      hv3 = XVertex(x: pvx + hx / 2.0 + vec_x,
                                    y: pvy + hy / 2.0 + vec_y)
                      initialize(hv3, pvx + hx / 2.0 + vec_x,
                                 pvy + hy / 2.0 + vec_y, 2000.0, 800.0)
                      hx *= 2.0
                      hy *= 2.0
                      vec_x *= 2.0
                      vec_y *= 2.0
                      hv4 = XVertex(x: pvx - hx + vec_x, y: pvy - hy + vec_y,
                                    tradius: 100.0)
                      initialize(hv4, pvx - hx + vec_x, pvy - hy + vec_y,
                                 2000.0, 800.0)
                      hv5 = XVertex(x: nvx + hx + vec_x, y: nvy + hy + vec_y,
                                    tradius: 100.0)
                      initialize(hv5, nvx + hx + vec_x, nvy + hy + vec_y,
                                 2000.0, 800.0)
                      rep =
                        :tmpD_10 = vertices_in_polygon(
                          :tmpD_9 = @[
                            wasMoved(:tmpD_6)
                            `=copy_1`(:tmpD_6, ppv)
                            :tmpD_6,
                            let blitTmp = hv0
                            wasMoved(hv0)
                            blitTmp,
                            wasMoved(:tmpD_7)
                            `=copy_1`(:tmpD_7, nnv)
                            :tmpD_7,
                            wasMoved(:tmpD_8)
                            `=copy_1`(:tmpD_8, hv3)
                            :tmpD_8]
                          :tmpD_9, r.vertices)
                        :tmpD_10 -_2
                          [pv_1, nv_1, ppv, cv, nnv, hv3]
                      block :tmp_8:
                        var el
                        try:
                          el = default()
                          var i_1 = 0
                          block :tmp_9:
                            while true:
                              `=copy_1`(el, [ppv, hv0, nnv, hv3][i_1])
                              echo ["-----"]
                              arc(r.pic, el.x, el.y, 600.0, 0.0,
                                  6.283185307179586)
                              if el.trgt:
                                setSource(r.pic, 0.0, 0.0, 1.0)
                              else:
                                setSource(r.pic, 0.0, 0.0, 1.0)
                              fill(r.pic)
                              stroke(r.pic)
                              if (
                                3 <= i_1):
                                break :tmp_9
                              inc(i_1, 1)
                        finally:
                          `=destroy_1`(el)
                      `=copy_2`(hhh, rep)
                      if (
                        0 < len(rep)):
                        var net
                        try:
                          `=copy_3`(net, step.net_desc)
                          block :tmp_10:
                            var v
                            var i_2 = 0
                            let L_1 = len(rep)
                            block :tmp_11:
                              while i_2 < L_1:
                                v = rep[i_2]
                                v.trgt = not step.rgt
                                v.tradius = v.radius_1 +
                                    max([net.trace_clearance, v.separation]) +
                                    net.trace_width / 2.0
                                inc(i_2, 1)
                                const
                                  loc`gensym162 = (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10)
                                  ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
                                bind instantiationInfo
                                mixin failedAssertImpl
                                {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10).}:
                                  if not (len(rep) == L_1):
                                    failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
                          pv_1.trgt = step.pstep.rgt
                          pv_1.tradius = step.pstep.radius
                          nv_1.trgt = step.nstep.rgt
                          nv_1.tradius = step.nstep.radius
                          `=sink_1`(rep,
                                    new_convex_vertices(rep, pv_1, nv_1, hv4,
                              hv5))
                          block :tmp_12:
                            var el_1
                            var i_3 = 0
                            let L_2 = len(rep)
                            block :tmp_13:
                              while i_3 < L_2:
                                el_1 = rep[i_3]
                                if true:
                                  break :tmp_12
                                arc(r.pic, el_1.x, el_1.y, 600.0, 0.0,
                                    6.283185307179586)
                                if el_1.trgt:
                                  setSource(r.pic, 1.0, 0.0, 0.0)
                                else:
                                  setSource(r.pic, 0.0, 1.0, 0.0)
                                fill(r.pic)
                                stroke(r.pic)
                                inc(i_3, 1)
                                const
                                  loc`gensym162 = (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10)
                                  ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
                                bind instantiationInfo
                                mixin failedAssertImpl
                                {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10).}:
                                  if not (len(rep) == L_2):
                                    failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
                        finally:
                          `=destroy_2`(net)
                      smart_replace(step, rep)
                    finally:
                      `=destroy_3`(hhh)
                      `=destroy_3`(:tmpD_10)
                      `=destroy_3`(:tmpD_9)
                      `=destroy_3`(rep)
                      `=destroy_1`(hv5)
                      `=destroy_1`(hv4)
                      `=destroy_1`(hv3)
                      `=destroy_1`(nnv)
                      `=destroy_4`(nn)
                      `=destroy_1`(ppv)
                      `=destroy_4`(pp)
                      `=destroy_1`(hv0)
                      `=destroy_1`(nv_1)
                      `=destroy_1`(pv_1)
                finally:
                  `=destroy_1`(nv)
                  `=destroy_1`(pv)
                  `=destroy_4`(nxt_step)
                  `=destroy_4`(prev_step)
                  `=destroy_4`(step)
          inc(i, 1)
          const
            loc`gensym162 = (
              filename: "/home/salewski/Nim/lib/system/iterators.nim",
              line: 240, column: 10)
            ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
          bind instantiationInfo
          mixin failedAssertImpl
          {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                   line: 240, column: 10).}:
            if not (len(r.vertices) == L):
              failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
-- end of expandArc ------------------------
/home/salewski/Router/router.nim(2149, 23) Warning: 'pstep.nstep.pstep = pstep' creates an uncollectable ref cycle; annotate 'nstep' with .cursor [CycleCreated]
/home/salewski/Router/router.nim(460, 6) Hint: 'resetVertexClass' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1231, 6) Hint: 'unused_convex_hull' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(845, 6) Hint: 'insert_pcb_vertex' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(121, 6) Hint: 'minmax' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1780, 6) Hint: 'atan2_tangents' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(456, 6) Hint: 'initialize' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1733, 6) Hint: 'split_neighbor_list' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(468, 6) Hint: 'add_to_current_cluster' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(464, 6) Hint: 'begin_new_cluster' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(917, 6) Hint: 'generate_netlist' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(118, 6) Hint: 'isOdd' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(390, 6) Hint: 'booleanReallySmartCrossProduct2dWithOffset' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(80, 3) Hint: 'glob' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1125, 6) Hint: 'distance_line_point' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(691, 6) Hint: 'distance_to' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1202, 6) Hint: 'unused_vertices_in_triangle' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(937, 6) Hint: 'sort_netlist' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(805, 6) Hint: 'insert_pcb_border' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1130, 6) Hint: 'distance_line_point_squared' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(1698, 6) Hint: 'dijkstra_use_path' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(102, 3) Hint: 'MinCutSize' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(438, 6) Hint: 'booleanReallySmartCrossProduct2d' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/router.nim(67, 11) Warning: imported and not used: 'vertices' [UnusedImport]
/home/salewski/Router/router.nim(66, 8) Warning: imported and not used: 'salewski' [UnusedImport]
/home/salewski/Router/router.nim(67, 11) Warning: imported and not used: 'edges' [UnusedImport]
Hint:  [Link]
Hint: 75080 lines; 4.950s; 214.301MiB peakmem; Debug build; proj: /home/salewski/Router/router.nim; out: /home/salewski/Router/router [SuccessX]
salewski@nuc ~/Router $ 
ghost commented 3 years ago
--expandArc: nubly

var replaced = true
var rep_c = 0
block :tmp:
  while replaced:
    replaced = false
    rep_c += 1
    block :tmp_1:
      var cv
      var i = 0
      let L = len(r.vertices)
      block :tmp_2:
        while i < L:
          cv = r.vertices[i]
          var stepPos = len(cv.attached_nets)
          block :tmp_3:
            while (
              0 < stepPos):
              block :tmp_4:
                var
                  step
                  :tmp_5
                  :tmpD
                  :tmpD_1
                  prev_step
                  nxt_step
                  :tmp_6
                  :tmpD_2
                  :tmpD_3
                  pv
                  nv
                try:
                  dec(stepPos, 1)
                  `=copy`(step, cv.attached_nets[stepPos])
                  :tmp_5 = default()
                  :tmp_5 = (
                    wasMoved(:tmpD)
                    `=copy`(:tmpD, step.pstep)
                    :tmpD,
                    wasMoved(:tmpD_1)
                    `=copy`(:tmpD_1, step.nstep)
                    :tmpD_1)
                  prev_step = :tmp_5[0]
                  nxt_step = :tmp_5[1]
                  :tmp_6 = default()
                  :tmp_6 = (
                    wasMoved(:tmpD_2)
                    `=copy_1`(:tmpD_2, step.prev)
                    :tmpD_2,
                    wasMoved(:tmpD_3)
                    `=copy_1`(:tmpD_3, step.next)
                    :tmpD_3)
                  pv = :tmp_6[0]
                  nv = :tmp_6[1]
                  var d = float(hypot(cv.x - pv.x, cv.y - pv.y) -
                      float(abs(prev_step.radius - step.radius)) * 1.02)
                  if d < 0.0:
                    if step.radius < prev_step.radius:
                      step.radius -= d
                      replaced = true
                    break :tmp_4
                  d = float(hypot(cv.x - nv.x, cv.y - nv.y) -
                      float(abs(nxt_step.radius - step.radius)) * 1.02)
                  if d < 0.0:
                    if step.radius < nxt_step.radius:
                      step.radius -= d
                      replaced = true
                    break :tmp_4
                  var (hx, hy) = convex_kkk(prev_step, step, nxt_step, r)
                  step.xt =
                    not (hx == 1e+300)
                  if collapse and step.xt:
                    var
                      :tmp_7
                      :tmpD_4
                      :tmpD_5
                      pv_1
                      nv_1
                      hv0
                      pp
                      ppv
                      nn
                      nnv
                      hv3
                      hv4
                      hv5
                      rep
                      :tmpD_6
                      :tmpD_7
                      :tmpD_8
                      :tmpD_9
                      :tmpD_10
                      hhh
                    try:
                      :tmp_7 = default()
                      :tmp_7 = (
                        wasMoved(:tmpD_4)
                        `=copy_1`(:tmpD_4, step.prev)
                        :tmpD_4,
                        wasMoved(:tmpD_5)
                        `=copy_1`(:tmpD_5, step.next)
                        :tmpD_5)
                      pv_1 = :tmp_7[0]
                      nv_1 = :tmp_7[1]
                      hv0 = XVertex()
                      initialize(hv0, hx, hy, 2000.0, 800.0)
                      const
                        loc`gensym451 = (
                          filename: "/home/salewski/Router/router.nim",
                          line: 2327, column: 17)
                        ploc`gensym451 = "/home/salewski/Router/router.nim(2327, 18)"
                      bind instantiationInfo
                      mixin failedAssertImpl
                      {.line: (filename: "/home/salewski/Router/router.nim",
                               line: 2327, column: 17).}:
                        if not
                          not (hv0.x == 0x7FF7FFFFFFFFFFFF'f64):
                          failedAssertImpl("/home/salewski/Router/router.nim(2327, 18) `hv0.x != NaN` ")
                      replaced = true
                      let pvx = pv_1.x
                      let pvy = pv_1.y
                      let nvx = nv_1.x
                      let nvy = nv_1.y
                      `=copy`(pp, prev_step.pstep)
                      if (
                        not (pp == nil)):
                        let _ = convex_kkk(pp, prev_step, step, nil)
                        hx = _[0]
                        hy = _[1]
                      ppv = default()
                      if
                        not (pp == nil) and
                        not (hx == 1e+300):
                        `=sink`(ppv, XVertex())
                        initialize(ppv, hx, hy, 2000.0, 800.0)
                      else:
                        `=copy_1`(ppv, pv_1)
                      if ppv.x == 0.0:
                        var :tmpD_11
                        try:
                          echo [
                            :tmpD_11 = `$`(Vertex(ppv))
                            :tmpD_11]
                          const
                            loc`gensym456 = (
                              filename: "/home/salewski/Router/router.nim",
                              line: 2343, column: 29)
                            ploc`gensym456 = "/home/salewski/Router/router.nim(2343, 30)"
                          bind instantiationInfo
                          mixin failedAssertImpl
                          {.line: (filename: "/home/salewski/Router/router.nim",
                                   line: 2343, column: 29).}:
                            if true:
                              failedAssertImpl("/home/salewski/Router/router.nim(2343, 30) `false` ")
                        finally:
                          `=destroy`(:tmpD_11)
                      `=copy`(nn, nxt_step.nstep)
                      if (
                        not (nn == nil)):
                        let __1 = convex_kkk(step, nxt_step, nn, nil)
                        hx = __1[0]
                        hy = __1[1]
                      nnv = default()
                      if
                        not (nn == nil) and
                        not (hx == 1e+300):
                        `=sink`(nnv, XVertex())
                        initialize(nnv, hx, hy, 2000.0, 800.0)
                      else:
                        `=copy_1`(nnv, nv_1)
                      hx = nvx - pvx
                      hy = nvy - pvy
                      var vec_x: float
                      var vec_y: float
                      if step.rgt:
                        let __2 = (hy, -hx)
                        vec_x = __2[0]
                        vec_y = __2[1]
                      else:
                        let __3 = (-hy, hx)
                        vec_x = __3[0]
                        vec_y = __3[1]
                      hv3 = XVertex(x: pvx + hx / 2.0 + vec_x,
                                    y: pvy + hy / 2.0 + vec_y)
                      initialize(hv3, pvx + hx / 2.0 + vec_x,
                                 pvy + hy / 2.0 + vec_y, 2000.0, 800.0)
                      hx *= 2.0
                      hy *= 2.0
                      vec_x *= 2.0
                      vec_y *= 2.0
                      hv4 = XVertex(x: pvx - hx + vec_x, y: pvy - hy + vec_y,
                                    tradius: 100.0)
                      initialize(hv4, pvx - hx + vec_x, pvy - hy + vec_y,
                                 2000.0, 800.0)
                      hv5 = XVertex(x: nvx + hx + vec_x, y: nvy + hy + vec_y,
                                    tradius: 100.0)
                      initialize(hv5, nvx + hx + vec_x, nvy + hy + vec_y,
                                 2000.0, 800.0)
                      rep =
                        :tmpD_10 = vertices_in_polygon(
                          :tmpD_9 = @[
                            wasMoved(:tmpD_6)
                            `=copy_1`(:tmpD_6, ppv)
                            :tmpD_6,
                            let blitTmp = hv0
                            wasMoved(hv0)
                            blitTmp,
                            wasMoved(:tmpD_7)
                            `=copy_1`(:tmpD_7, nnv)
                            :tmpD_7,
                            wasMoved(:tmpD_8)
                            `=copy_1`(:tmpD_8, hv3)
                            :tmpD_8]
                          :tmpD_9, r.vertices)
                        :tmpD_10 -_2
                          [pv_1, nv_1, ppv, cv, nnv, hv3]
                      block :tmp_8:
                        var el
                        try:
                          el = default()
                          var i_1 = 0
                          block :tmp_9:
                            while true:
                              `=copy_1`(el, [ppv, hv0, nnv, hv3][i_1])
                              echo ["-----"]
                              arc(r.pic, el.x, el.y, 600.0, 0.0,
                                  6.283185307179586)
                              if el.trgt:
                                setSource(r.pic, 0.0, 0.0, 1.0)
                              else:
                                setSource(r.pic, 0.0, 0.0, 1.0)
                              fill(r.pic)
                              stroke(r.pic)
                              if (
                                3 <= i_1):
                                break :tmp_9
                              inc(i_1, 1)
                        finally:
                          `=destroy_1`(el)
                      `=copy_2`(hhh, rep)
                      if (
                        0 < len(rep)):
                        var net
                        try:
                          `=copy_3`(net, step.net_desc)
                          block :tmp_10:
                            var v
                            var i_2 = 0
                            let L_1 = len(rep)
                            block :tmp_11:
                              while i_2 < L_1:
                                v = rep[i_2]
                                v.trgt = not step.rgt
                                v.tradius = v.radius_1 +
                                    max([net.trace_clearance, v.separation]) +
                                    net.trace_width / 2.0
                                inc(i_2, 1)
                                const
                                  loc`gensym162 = (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10)
                                  ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
                                bind instantiationInfo
                                mixin failedAssertImpl
                                {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10).}:
                                  if not (len(rep) == L_1):
                                    failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
                          pv_1.trgt = step.pstep.rgt
                          pv_1.tradius = step.pstep.radius
                          nv_1.trgt = step.nstep.rgt
                          nv_1.tradius = step.nstep.radius
                          `=sink_1`(rep,
                                    new_convex_vertices(rep, pv_1, nv_1, hv4,
                              hv5))
                          block :tmp_12:
                            var el_1
                            var i_3 = 0
                            let L_2 = len(rep)
                            block :tmp_13:
                              while i_3 < L_2:
                                el_1 = rep[i_3]
                                if true:
                                  break :tmp_12
                                arc(r.pic, el_1.x, el_1.y, 600.0, 0.0,
                                    6.283185307179586)
                                if el_1.trgt:
                                  setSource(r.pic, 1.0, 0.0, 0.0)
                                else:
                                  setSource(r.pic, 0.0, 1.0, 0.0)
                                fill(r.pic)
                                stroke(r.pic)
                                inc(i_3, 1)
                                const
                                  loc`gensym162 = (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10)
                                  ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
                                bind instantiationInfo
                                mixin failedAssertImpl
                                {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                                    line: 240, column: 10).}:
                                  if not (len(rep) == L_2):
                                    failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
                        finally:
                          `=destroy_2`(net)
                      smart_replace(step, rep)
                    finally:
                      `=destroy_3`(hhh)
                      `=destroy_3`(:tmpD_10)
                      `=destroy_3`(:tmpD_9)
                      `=destroy_3`(rep)
                      `=destroy_1`(hv5)
                      `=destroy_1`(hv4)
                      `=destroy_1`(hv3)
                      `=destroy_1`(nnv)
                      `=destroy_4`(nn)
                      `=destroy_1`(ppv)
                      `=destroy_4`(pp)
                      `=destroy_1`(hv0)
                      `=destroy_1`(nv_1)
                      `=destroy_1`(pv_1)
                finally:
                  `=destroy_1`(nv)
                  `=destroy_1`(pv)
                  `=destroy_4`(nxt_step)
                  `=destroy_4`(prev_step)
                  `=destroy_4`(step)
          inc(i, 1)
          const
            loc`gensym162 = (
              filename: "/home/salewski/Nim/lib/system/iterators.nim",
              line: 240, column: 10)
            ploc`gensym162 = "/home/salewski/Nim/lib/system/iterators.nim(240, 11)"
          bind instantiationInfo
          mixin failedAssertImpl
          {.line: (filename: "/home/salewski/Nim/lib/system/iterators.nim",
                   line: 240, column: 10).}:
            if not (len(r.vertices) == L):
              failedAssertImpl("/home/salewski/Nim/lib/system/iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it")
-- end of expandArc ------------------------

fore more comfortable viewing :)

StefanSalewski commented 3 years ago

Yes, seems to be really a wired ARC bug:

I can add

         #discard hv0 == nil
          #discard hv3 == nil
          for el in [ppv, hv0, nnv, hv3]:
            echo "-----"
            echo "el? ", el == nil

and get

==>29180.92510879 1.00299829048073 -0.01327764803269028
-----
el? false
-----
el? true
Traceback (most recent call last)
Clyybber commented 3 years ago

Can you try with --cursorInference: off ?

StefanSalewski commented 3 years ago

OK, I hope this test is OK for you:

from math import hypot

const
  NilFloat = 1e300
  PinRadius = 100.0

type
  Router = ref object of RootRef
    pic: int # cairo.Context
    vertices: seq[XVertex]

  Vertex = ref object of RootRef
    x, y: float

  XVertex = ref object of Vertex
    attached_nets: seq[Step]
    tradius: float
    radius: float
    separation: float
    trgt: bool

  Step = ref object of RootRef
    net_desc: Net
    x, y: float
    radius: float
    prev, next: XVertex
    pstep, nstep: Step
    xt: bool
    rgt: bool

  Net = ref object of RootRef
    trace_clearance: float
    trace_width: float

proc initialize(v: XVertex; x, y: float) =
  v.x = x
  v.y = y

proc smart_replace(step: Step;  rep: seq[XVertex]) =
  discard

proc vertices_in_polygon(a, b: seq[XVertex]): seq[XVertex] =
  result = a
  if b.len > 0:
    result.add(b[0])

proc nubly(r: Router; collapse = false) =
  var replaced = true
  var rep_c = 0
  while replaced:
    replaced = false
    rep_c += 1
    for cv in r.vertices:
      var stepPos = cv.attached_nets.len
      while stepPos > 0:
        dec(stepPos)
        var step = cv.attached_nets[stepPos]
      #for step in cv.attached_nets.reversed:
        let (prev_step, nxt_step) = (step.pstep, step.nstep)
        let (pv, nv) = (step.prev, step.next)
        var d = 0.0 # (hypot(cv.x - pv.x, cv.y - pv.y) - (prev_step.radius - step.radius).abs.float * 1.02).float
        if d < 0:
          if step.radius < prev_step.radius:
            step.radius -= d
            replaced = true
          continue
        d = 0.0 # (hypot(cv.x - nv.x, cv.y - nv.y) - (nxt_step.radius - step.radius).abs.float * 1.02).float
        if d < 0:
          if step.radius < nxt_step.radius:
            step.radius -= d
            replaced = true
          continue
        var (hx, hy) = (0.0, 0.0) # convex_kkk(prev_step, step, nxt_step, r)
        step.xt = hx != NilFloat
        if true: # collapse and step.xt:
          let (pv, nv) = (step.prev, step.next)
          var hv0 = XVertex()
          initialize(hv0, hx, hy)
          assert hv0.x != NaN
          replaced = true
          let pvx = pv.x
          let pvy = pv.y
          let nvx = nv.x
          let nvy = nv.y
          var pp: Step = nil # prev_step.pstep
          if (pp != nil):
            (hx, hy) = (0.0, 0.0) # convex_kkk(pp, prev_step, step)
          var ppv: XVertex
          if pp != nil and hx != NilFloat:
            ppv = XVertex()
            initialize(ppv, hx, hy)
          else:
            ppv = pv
          if ppv.x == 0:
            echo ppv.x# ; assert false
          let nn: Step = nil #  = nxt_step.nstep
          if nn != nil:
            (hx, hy) = (0.0, 0.0) # convex_kkk(step, nxt_step, nn)
          var nnv: XVertex
          if nn != nil and hx != NilFloat:
            nnv = XVertex()
            initialize(nnv, hx, hy)
          else:
            nnv = nv
          hx = nvx - pvx
          hy = nvy - pvy
          var vec_x, vec_y: float
          if step.rgt:
            (vec_x, vec_y) = (hy, -hx)
          else:
            (vec_x, vec_y) = (-hy, hx)
          let hv3 = XVertex(x: pvx + hx / 2 + vec_x, y: pvy + hy / 2 + vec_y)
          initialize(hv3, pvx + hx / 2 + vec_x, pvy + hy / 2 + vec_y)
          hx *= 2
          hy *= 2
          vec_x *= 2
          vec_y *= 2
          let hv4 = XVertex(x: pvx - hx + vec_x, y: pvy - hy + vec_y, tradius: 100)
          initialize(hv4, pvx - hx + vec_x, pvy - hy + vec_y)
          let hv5 = XVertex(x: nvx + hx + vec_x, y: nvy + hy + vec_y, tradius: 100)
          initialize(hv5, nvx + hx + vec_x, nvy + hy + vec_y)
          var rep: seq[XVertex] = vertices_in_polygon(@[ppv, hv0, nnv, hv3], r.vertices)#  - [pv, nv, ppv, cv, nnv, hv3]
          #discard hv0 == nil
          #discard hv3 == nil
          # [
          for el in [ppv, hv0, nnv, hv3]:
            echo "-----"
            echo el.x
          let hhh = rep
          if rep.len > 100:
            let net = step.net_desc
            for v in rep:
              v.trgt = not step.rgt
              v.tradius = v.radius + [net.trace_clearance, v.separation].max + net.trace_width / 2
            pv.trgt = step.pstep.rgt
            pv.tradius = step.pstep.radius
            nv.trgt = step.nstep.rgt
            nv.tradius = step.nstep.radius
            rep = @[] # new_convex_vertices(rep, pv, nv, hv4, hv5)
            for el in rep:
              if true: break
          smart_replace(step, rep)

proc main =
  var r = Router()
  var v = XVertex()
  var s = Step()
  s.next = XVertex()
  s.prev = XVertex()
  v.attached_nets.add(s)
  initialize(v, 0, 0)
  r.vertices.add(v)
  nubly(r)

main()

Runs without terminating with refc, but with ARC

$ nim c --gc:arc nubly.nim 
Hint: used config file '/home/salewski/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/salewski/Nim/config/config.nims' [Conf]
........
/home/salewski/Router/nubly.nim(129, 15) Hint: 'hhh' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/nubly.nim(60, 14) Hint: 'pv' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/nubly.nim(60, 18) Hint: 'nv' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/nubly.nim(5, 3) Hint: 'PinRadius' is declared but not used [XDeclaredButNotUsed]
/home/salewski/Router/nubly.nim(1, 6) Warning: imported and not used: 'math' [UnusedImport]
CC: stdlib_assertions.nim
CC: stdlib_formatfloat.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: nubly.nim
Hint:  [Link]
Hint: 25339 lines; 0.662s; 31.793MiB peakmem; Debug build; proj: /home/salewski/Router/nubly.nim; out: /home/salewski/Router/nubly [SuccessX]
salewski@nuc ~/Router $ ./nubly 
0.0
-----
Traceback (most recent call last)
/home/salewski/Router/nubly.nim(155) nubly
/home/salewski/Router/nubly.nim(153) main
/home/salewski/Router/nubly.nim(128) nubly
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Segmentation fault (core dumped)

I think the core issue is vertices_in_polygon(), the refs are moved to that proc, but used later in the constructed array.

StefanSalewski commented 3 years ago

--cursorInference: off

does not help.