%D \module
%D   [       file=luat-env,
%D        version=2005.05.26,
%D          title=\CONTEXT\ Lua Macros,
%D       subtitle=ConTeXt features,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright=PRAGMA]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D Originally we compiled the lua files externally and loaded
%D then at runtime, but when the amount grew, we realized that
%D we needed away to store them in the format, which is what
%D bytecode arrays do. And so the following is obsolete:
%D
%D \starttyping
%D \chardef\ctxluaembeddingmode \plusone
%D
%D 0 = external compilation and loading
%D 1 = runtime compilation and embedding
%D \stoptyping

% \writestatus{loading}{Lua Support Macros (environment)}

% print (lua.id)
% print (lua.version)
% print (lua.startupfile)

%D Allocation of \LUA\ engines.

\newcount\luadefcounter

\ifx\zerocount\undefined \chardef\zerocount=0 \fi
\ifx\plusone  \undefined \chardef\plusone  =1 \fi

\def\newlua#1%
  {\global\advance\luadefcounter\plusone
   \mathchardef#1\luadefcounter}

%D We use a dedicated instance for \CONTEXT\ core functionality. In
%D \CONTEXT we also use this as callback instance. Instance 0 is
%D the scratch instance.

\ifx\luastartup\undefined \newcount\luastartup \fi

\chardef\CTXlua\zerocount \luadefcounter\CTXlua \luastartup\CTXlua

\def\ctxdirectlua{\directlua\CTXlua}  \let\ctxlua\ctxdirectlua
\def\ctxlatelua  {\latelua  \CTXlua}

%D The simple \type {\lua} command is just a shortcut to the
%D zero instance. Beware, we don't use the 0--9 range for
%D scratch purposes as we do with other registers. First of all
%D we want to avoid the overhead, but mostly, users can just define
%D their own.

\newlua \luadefault

\def \lua       {\directlua\luadefault} % zero is the main one, and reserved for ctx
\edef\luaversion{\ctxlua{tex.print(_VERSION)}}

%D We want to define \LUA\ related things in the format but
%D need to reluad code because \LUA\ instances are not dumped
%D into the format.

\ifx\undefined\normaleveryjob \let\normaleveryjob\everyjob \newtoks\everyjob \fi

\newtoks\everyloadluacode
\newtoks\everyfinalizeluacode

\normaleveryjob{\the\everyloadluacode\the\everyfinalizeluacode\the\everyjob}

\newif\ifproductionrun

\long\def\startruntimeluacode#1\stopruntimeluacode % only simple code (load +init)
  {\ifproductionrun
     \global\let\startruntimeluacode\relax
     \global\let\stopruntimeluacode \relax
   \else
     \global\everyloadluacode\expandafter{\the\everyloadluacode#1}%
   \fi
   #1} % maybe no interference

\long\def\startruntimectxluacode#1\stopruntimectxluacode
  {\startruntimeluacode\ctxlua{#1}\stopruntimeluacode}

%D Next we load the initialization code.

\startruntimectxluacode
    environment = environment or { }
    environment.jobname    = "\jobname"                            % tex.jobname
    environment.initex     = \ifproductionrun false \else true \fi % tex.formatname == ""
    environment.version    = "\contextversion"
\stopruntimectxluacode

\chardef\ctxluaexecutionmode \zerocount % private

% we start at 500, below this, we store predefined data (dumps)

\newcount\luabytecodecounter \luabytecodecounter=500

\startruntimectxluacode
    if not lua.bytedata then lua.bytedata = { } end
\stopruntimectxluacode

%D Handy when we expand:

\let\stopruntimeluacode   \relax
\let\stopruntimectxluacode\relax

\ifx\normalprotected \undefined \let\normalprotected \protected  \fi
\ifx\normalunexpanded\undefined \let\normalunexpanded\unexpanded \fi
\ifx\normalexpanded  \undefined \let\normalexpanded  \expanded   \fi

\long\def\lastexpanded{} % todo: elsewhere we use \@@expanded

\long\def\expanded#1{\long\xdef\lastexpanded{\noexpand#1}\lastexpanded}

%D More code:

\def\ctxluabytecode#1% executes an already loaded chunk
  {\ctxlua {
    do
        local str = ''
        if lua.bytedata[#1] then
            str = " from file " .. lua.bytedata[#1][1] .. " version " .. lua.bytedata[#1][2]
        end
        if lua.bytecode[#1] then
            if environment.initex then
            %   logs.report("bytecode","executing blob " .. "#1" .. str)
                assert(lua.bytecode[#1])()
            else
                assert(lua.bytecode[#1])()
                lua.bytecode[#1] = nil
            end
        else
        %   logs.report("bytecode", "invalid blob " .. "#1" .. str)
        end
    end
  }}

\def\ctxluabyteload#1#2% registers and compiles chunk
  {\global\advance\luabytecodecounter \plusone
   \expanded{\startruntimectxluacode
     lua.bytedata[\the\luabytecodecounter] = { "#1", "#2" }
   \stopruntimectxluacode}%
   \ctxlua {
      lua.bytedata[\the\luabytecodecounter] = { "#1", "#2" }
      lua.bytecode[\the\luabytecodecounter] = environment.luafilechunk("#1")
    }}

\def\ctxloadluafile#1#2% load a (either not compiled) chunk at runtime
  {\doifelsenothing{#2}
     {\ctxlua{environment.loadluafile("#1")}}
     {\ctxlua{environment.loadluafile("#1",#2)}}}

\def\registerctxluafile#1#2% name version
  {\ifproductionrun \else
     \ctxluabyteload{#1}{#2}%
   \fi
   \global\everyloadluacode\expandafter\expandafter\expandafter{\expandafter\the\expandafter\everyloadluacode
      \expandafter\ctxluabytecode\expandafter{\the\luabytecodecounter}}%
   \ifcase\ctxluaexecutionmode\or\ctxluabytecode{\the\luabytecodecounter}\fi}

\registerctxluafile{luat-env}{1.001}

\chardef\ctxluaexecutionmode \plusone

\endinput
