X Tutup
Skip to content

Generator optimization #601

@ark120202

Description

@ark120202

Now we have two kinds of iterators - lua-like (functions) and js-like (objects with next method). The idea is to make generated js-like iterators contain data to make lua iteration faster. Additionally, all iterator functions are extracted to helpers to avoid extra allocations.

Input on Playground

local ____symbolMetatable = {__tostring = function(self)
  if self.description == nil then
    return "Symbol()"
  else
    return "Symbol(" .. tostring(self.description) .. ")"
  end
end}
function __TS__Symbol(self, description)
  return setmetatable({description = description}, ____symbolMetatable)
end
Symbol = {iterator = __TS__Symbol(_G, "Symbol.iterator")}

-- New helpers:

local __TS__IterableCoroutine = {}
local __TS__IterableArguments = {}

function __TS__IterateStep(self)
  local co = self[__TS__IterableCoroutine]
  local args = self[__TS__IterableArguments]
  local status, value
  if args then
    status, value = coroutine.resume(co, unpack(args))
    self[__TS__IterableArguments] = nil
  else
    status, value = coroutine.resume(co, self)
  end

  if coroutine.status(co) == "dead" then
    return
  end

  if not status then
    error(value)
  end

  -- Fix for #600
  return true, value
end

function __TS__Iterate(result)
  if not result[__TS__IterableCoroutine] then
    -- TODO: Fallback for manually constructed iterators
  end

  return __TS__IterateStep, result
end

function __TS__GeneratorNext(self, ...)
  local co = self[__TS__IterableCoroutine]
  local args = self[__TS__IterableArguments]
  local status, value
  if args then
    status, value = coroutine.resume(co, unpack(args))
    self[__TS__IterableArguments] = nil
  else
    status, value = coroutine.resume(co, ...)
  end

  return {
    done = coroutine.status(co) == "dead",
    value = value,
  }
end

function __TS__GeneratorIterator(self)
  return self
end

function __TS__Generator(fn)
  return function (...)
    local args = {...}
    return {
      [__TS__IterableCoroutine] = coroutine.create(fn),
      [__TS__IterableArguments] = args,
      next = __TS__GeneratorNext,
      [Symbol.iterator] = __TS__GeneratorIterator,
    }
  end
end

-------------------------------------------------------------------------------

local foo = __TS__Generator(function(self, argument)
  local ____ = coroutine.yield(1)
  local ____ = coroutine.yield(argument)

  return 3
end)

local it = foo(_G, 2)
local x1 = it:next()
print(x1.value, x1.done) -- 1 false
local x2 = it:next()
print(x2.value, x2.done) -- 2 false
local x3 = it:next()
print(x3.value, x3.done) -- 3 true

for ____, value in __TS__Iterate(foo(_G, 2)) do
  print(value) -- 1, 2
end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      X Tutup