token.expand is never useful, and is not fixed even 10 years passed, since every API from luatex is isolated from variables like cur_cmd.
But you can write you own expand
%!TEX program=lualatex
\documentclass{standalone}
\directlua{
local exp_after = token.create('expandafter')
local lbrace = token.create(string.byte('{'))
local rbrace = token.create(string.byte('}'))
function expand()
token.put_next(lbrace, exp_after, rbrace)
token.scan_toks(false, true)
end
}
\begin{document}
\def\mymacro{ABC}%
\directlua{
local t = token.create'mymacro'
token.put_next(t)
expand()
token.get_next()
}
\end{document}
If you need take care of the catcodes of braces and redefinition of \expandafter,
the code is much longer.
local lbrace = token.new(string.byte'{', 1)
local rbrace = token.new(string.byte'}', 2)
function expand()
local cur_exp_after = token.create('expandafter')
local cur_let = token.create('let')
local prefix = '^'..'^@'
while token.is_defined(prefix..'expandafter') or token.is_defined(prefix..'let') do
prefix = prefix..'^'..'^@'
end
local undefined = token.create(prefix..'expandafter')
tex.enableprimitives(prefix, {'expandafter', 'let'})
local exp_after, let = token.create(prefix..'expandafter'), token.create(prefix..'let')
token.put_next(lbrace, exp_after, rbrace)
token.scan_toks(false, true)
tex.runtoks(function()
token.put_next(let, exp_after, undefined, let, let, undefined)
end)
end
tex.runtoks. See expansion - Concurrently interleaving execution of Lua and TeX in LuaTeX - TeX - LaTeX Stack Exchange – user202729 Jul 02 '22 at 11:42