github.com/xmx/lua@v0.0.0-20230324063450-8a298e091302/_glua-tests/goto.lua (about)

     1  local function errmsg (code, m)
     2    local st, msg = loadstring(code)
     3    assert(not st and string.find(msg, m))
     4  end
     5  
     6  -- cannot see label inside block
     7  errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
     8  errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
     9  
    10  -- repeated label
    11  errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
    12  
    13  
    14  -- undefined label
    15  errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
    16  
    17  -- jumping over variable definition
    18  errmsg([[
    19  do local bb, cc; goto l1; end
    20  local aa
    21  ::l1:: print(3)
    22  ]], "local 'aa'")
    23  
    24  -- jumping into a block
    25  errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
    26  errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
    27  
    28  -- cannot continue a repeat-until with variables
    29  errmsg([[
    30    repeat
    31      if x then goto cont end
    32      local xuxu = 10
    33      ::cont::
    34    until xuxu < x
    35  ]], "local 'xuxu'")
    36  
    37  -- simple gotos
    38  local x
    39  do
    40    local y = 12
    41    goto l1
    42    ::l2:: x = x + 1; goto l3
    43    ::l1:: x = y; goto l2
    44  end
    45  ::l3:: ::l3_1:: assert(x == 13)
    46  
    47  
    48  -- long labels
    49  do
    50    local prog = [[
    51    do
    52      local a = 1
    53      goto l%sa; a = a + 1
    54     ::l%sa:: a = a + 10
    55      goto l%sb; a = a + 2
    56     ::l%sb:: a = a + 20
    57      return a
    58    end
    59    ]]
    60    local label = string.rep("0123456789", 40)
    61    prog = string.format(prog, label, label, label, label)
    62    assert(assert(loadstring(prog))() == 31)
    63  end
    64  
    65  -- goto to correct label when nested
    66  do goto l3; ::l3:: end   -- does not loop jumping to previous label 'l3'
    67  
    68  -- ok to jump over local dec. to end of block
    69  do
    70    goto l1
    71    local a = 23
    72    x = a
    73    ::l1::;
    74  end
    75  
    76  while true do
    77    goto l4
    78    goto l1  -- ok to jump over local dec. to end of block
    79    goto l1  -- multiple uses of same label
    80    local x = 45
    81    ::l1:: ;;;
    82  end
    83  ::l4:: assert(x == 13)
    84  
    85  if print then
    86    goto l1   -- ok to jump over local dec. to end of block
    87    error("should not be here")
    88    goto l2   -- ok to jump over local dec. to end of block
    89    local x
    90    ::l1:: ; ::l2:: ;;
    91  else end
    92  
    93  -- to repeat a label in a different function is OK
    94  local function foo ()
    95    local a = {}
    96    goto l3
    97    ::l1:: a[#a + 1] = 1; goto l2;
    98    ::l2:: a[#a + 1] = 2; goto l5;
    99    ::l3::
   100    ::l3a:: a[#a + 1] = 3; goto l1;
   101    ::l4:: a[#a + 1] = 4; goto l6;
   102    ::l5:: a[#a + 1] = 5; goto l4;
   103    ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
   104                a[4] == 5 and a[5] == 4)
   105    if not a[6] then a[6] = true; goto l3a end   -- do it twice
   106  end
   107  
   108  ::l6:: foo()
   109  
   110  
   111  
   112  --------------------------------------------------------------------------------
   113  -- testing closing of upvalues
   114  
   115  local function foo ()
   116    local a = {}
   117    do
   118    local i = 1
   119    local k = 0
   120    a[0] = function (y) k = y end
   121    ::l1:: do
   122      local x
   123      if i > 2 then goto l2 end
   124      a[i] = function (y) if y then x = y else return x + k end end
   125      i = i + 1
   126      goto l1
   127    end
   128    end
   129    ::l2:: return a
   130  end
   131  
   132  local a = foo()
   133  a[1](10); a[2](20)
   134  assert(a[1]() == 10 and a[2]() == 20 and a[3] == nil)
   135  a[0](13)
   136  assert(a[1]() == 23 and a[2]() == 33)
   137  
   138  --------------------------------------------------------------------------------
   139  -- testing if x goto optimizations
   140  
   141  local function testG (a)
   142    if a == 1 then
   143      goto l1
   144      error("should never be here!")
   145    elseif a == 2 then goto l2
   146    elseif a == 3 then goto l3
   147    elseif a == 4 then
   148      goto l1  -- go to inside the block
   149      error("should never be here!")
   150      ::l1:: a = a + 1   -- must go to 'if' end
   151    else
   152      goto l4
   153      ::l4a:: a = a * 2; goto l4b
   154      error("should never be here!")
   155      ::l4:: goto l4a
   156      error("should never be here!")
   157      ::l4b::
   158    end
   159    do return a end
   160    ::l2:: do return "2" end
   161    ::l3:: do return "3" end
   162    ::l1:: return "1"
   163  end
   164  
   165  assert(testG(1) == "1")
   166  assert(testG(2) == "2")
   167  assert(testG(3) == "3")
   168  assert(testG(4) == 5)
   169  assert(testG(5) == 10)
   170  --------------------------------------------------------------------------------
   171  
   172  
   173  print'OK'