%D \module
%D   [       file=mp-luas.mpiv,
%D        version=2014.04.14,
%D          title=\CONTEXT\ \METAPOST\ graphics,
%D       subtitle=\LUA,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

if known context_luas : endinput ; fi ;

% When I prototyped the runscript primitive I was just thinking of a usage like
% the original \directlua primitive in luatex: genererate something and pipe
% that back to metapost, and have access to some internals. Instead of compiling
% the code a the metapost end here we delegate that to the lua end. Only strings
% get passed. Of course in the end the real usage got a bit beyong the intended
% usage. So, in addition to some definitions here there are and will be use in
% other metafun modules too. Of course in retrospect I should have done this five
% years earlier.

boolean context_luas ; context_luas := true ;

% First variant:
%
% let lua = runscript ;
%
% Second variant:
%
% vardef lua (text t) =
%     runscript(for s = t : s & endfor "")
% enddef;
%
% Third variant:
%
% vardef lua (text t) =
%     runscript("" for s = t :
%         if string s :
%             & s
%         elseif numeric s :
%             & decimal s
%         elseif boolean s :
%             & if s : "true" else "false" fi
%         fi endfor)
% enddef;
%
% Fourth variant:

string mfun_lua_bs ; mfun_lua_bs := "[===[" ;
string mfun_lua_es ; mfun_lua_es := "]===]" ;

vardef mlib_luas_luacall(text t) =
    runscript("" for s = t :
        if string s :
            & s
          % & mfun_lua_bs & s & mfun_lua_es
        elseif numeric s :
            & decimal s
        elseif boolean s :
            & if s : "true" else : "false" fi
        elseif pair s :
            & mfun_pair_to_table(s)
        elseif path s :
            & mfun_path_to_table(s)
        elseif rgbcolor s :
            & mfun_rgb_to_table(s)
        elseif cmykcolor s :
            & mfun_cmyk_to_table(s)
        else :
            & ditto & tostring(s) & ditto
        fi endfor
    )
enddef ;

% vardef mlib_luas_lualist(expr c)(text t) =
%     save b ; boolean b ; b := false ;
%     runscript(c & "(" for s = t :
%         if b :
%             & ","
%         else :
%             hide(b := true)
%         fi
%         if string s :
%           % & ditto & s & ditto
%             & mfun_lua_bs & s & mfun_lua_es
%         elseif numeric s :
%             & decimal s
%         elseif boolean s :
%             & if s : "true" else : "false" fi
%         elseif pair s :
%             & mfun_pair_to_table(s)
%         elseif path s :
%             & mfun_path_to_table(s)
%         elseif rgbcolor s :
%             & mfun_rgb_to_table(s)
%         elseif cmykcolor s :
%             & mfun_cmyk_to_table(s)
%         else :
%             & ditto & tostring(s) & ditto
%         fi endfor & ")"
%     )
% enddef ;

newinternal mfun_luas_b ;

def mlib_luas_luadone =
    exitif numeric begingroup mfun_luas_b := 1 ; endgroup ;
enddef ;

vardef mlib_luas_lualist(expr c)(text t) =
    interim mfun_luas_b := 0 ;
    runscript(c & for s = t :
        if mfun_luas_b = 0 :
            "("
          % hide(mfun_luas_b := 1)
            mlib_luas_luadone
        else :
            ","
        fi
        &
        if string s :
            mfun_lua_bs & s & mfun_lua_es
        elseif numeric s :
            decimal s
        elseif boolean s :
            if s : "true" else : "false" fi
        elseif pair s :
            mfun_pair_to_table(s)
        elseif path s :
            mfun_path_to_table(s)
        elseif rgbcolor s :
            mfun_rgb_to_table(s)
        elseif cmykcolor s :
            mfun_cmyk_to_table(s)
        else :
            ditto & tostring(s) & ditto
        fi & endfor if mfun_luas_b = 0 : "()" else : ")" fi
    )
enddef ;

def luacall = mlib_luas_luacall enddef ; % why no let

vardef lualist@#(text t) = mlib_luas_lualist(str @#)(t) enddef ;

string mlib_luas_s ; % saves save/restore

vardef lua@#(text t) =
    mlib_luas_s := str @# ;
    if length(mlib_luas_s) > 0 :
        mlib_luas_lualist(mlib_luas_s,t)
    else :
        mlib_luas_luacall(t)
    fi
enddef ;

vardef MP@#(text t) =
    mlib_luas_lualist("MP." & str @#,t)
enddef ;

def message expr t =
    lua.mp.report(tostring(t)) ;
enddef ;

% Modes:

vardef texmode   (expr s) = lua.mp("mode",      s) enddef ;
vardef systemmode(expr s) = lua.mp("systemmode",s) enddef ;

% A few helpers

vardef isarray   suffix a = lua.mp.isarray  (str a) enddef ;
vardef prefix    suffix a = lua.mp.prefix   (str a) enddef ;
vardef dimension suffix a = lua.mp.dimension(str a) enddef ;

% More access

vardef getmacro(expr k)   = lua.mp._get_macro_(k)   enddef ;
vardef getdimen(expr k)   = lua.mp._get_dimen_(k)   enddef ;
vardef getcount(expr k)   = lua.mp._get_count_(k)   enddef ;
vardef gettoks (expr k)   = lua.mp._get_toks_ (k)   enddef ;

def setmacro(expr k,v) = lua.mp._set_macro_(k,v) enddef ;
def setdimen(expr k,v) = lua.mp._set_dimen_(k,v) enddef ;
def setcount(expr k,v) = lua.mp._set_count_(k,v) enddef ;
def settoks (expr k,v) = lua.mp._set_toks_ (k,v) enddef ;

vardef positionpath  (expr name) = lua.mp.positionpath  (name) enddef ;
vardef positioncurve (expr name) = lua.mp.positioncurve (name) enddef ;
vardef positionxy    (expr name) = lua.mp.positionxy    (name) enddef ;
vardef positionpxy   (expr name) = lua.mp.positionpxy   (name) enddef ;
vardef positionwhd   (expr name) = lua.mp.positionwhd   (name) enddef ;
vardef positionpage  (expr name) = lua.mp.positionpage  (name) enddef ;
vardef positionregion(expr name) = lua.mp.positionregion(name) enddef ;
vardef positionbox   (expr name) = lua.mp.positionbox   (name) enddef ;
vardef positionanchor            = lua.mp.positionanchor()     enddef ;

let wdpart = redpart ;
let htpart = greenpart ;
let dppart = bluepart ;

vardef positioninregion =
    currentpicture := currentpicture shifted - positionxy(positionanchor) ;
enddef ;

vardef positionatanchor(expr name) =
    currentpicture := currentpicture shifted - positionxy(name) ;
enddef ;

vardef texvar(expr name) = lua.mp.texvar(name) enddef ;
vardef texstr(expr name) = lua.mp.texstr(name) enddef ;

%D New experimental feature for Alan-The-Number-Cruncher:

% \startMPcode{doublefun}
%     path p ; p := (
%         for i=1 upto 20000 :
%             origin randomized 10000 ..
%         endfor cycle
%     ) xysized (TextWidth,TextHeight) ;
%     draw for i inpath p:
%         pointof i .. controls (leftof i) and (rightof i) ..
%     endfor cycle ;
% \stopMPcode

% def inpath suffix p =
%     = 1 step 1 until lua.mp.mf_path_length(str p)
% enddef ;

% def inpath suffix p =
%  %  = 1 step 1 until lua.mp.mf_path_length(str p)
%     = 1 step 1 until (begingroup save n ; n := lua.mp.mf_path_length(str p) ; if n = 0 : 1 else : n fi endgroup)
% enddef ;

def inpath suffix p = % permits p[0]
    = 1 step 1 until
    begingroup
    save mfun_inpath_r,mfun_inpath_n ; path mfun_inpath_r ;
    mfun_inpath_r = p ;
    mfun_inpath_n := lua.mp.mf_path_length(str mfun_inpath_r) ;
    if mfun_inpath_n = 0 : 1 else : mfun_inpath_n fi
    endgroup
enddef ;

vardef pointof primary i = lua.mp.mf_path_point(i) enddef ;
vardef leftof  primary i = lua.mp.mf_path_left (i) enddef ;
vardef rightof primary i = lua.mp.mf_path_right(i) enddef ;

extra_endfig := extra_endfig & " lua.mp.mf_path_reset() ; " ;
