%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. Older version sof this module show the way it evolved.

boolean context_luas ; context_luas := true ;

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 ;

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) = % we could use mlib_luas_s instead of c
    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 ;

% Color:

% We do a low level runscript:
%
% lua.mp.namedcolor(s)       % conflicts with macro namedcolor
% lua.mp.mf_named_color(s)   % okay but, can also be
% lua.mp("mf_named_color",s) % which gives expansion mess

def resolvedcolor primary s = % no vardef
    if string s :
        runscript("mp.mf_named_color('" & s & "')") % faster anyway
    else :
        s
    fi
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 ;

def setglobalmacro(expr k,v) = lua.mp._set_global_macro_(k,v) enddef ;
def setglobaldimen(expr k,v) = lua.mp._set_global_dimen_(k,v) enddef ;
def setglobalcount(expr k,v) = lua.mp._set_global_count_(k,v) enddef ;
def setglobaltoks (expr k,v) = lua.mp._set_global_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:

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 ;

vardef pointof primary i = runscript("mp.mf_path_point(" & decimal i & ")") enddef ;
vardef leftof  primary i = runscript("mp.mf_path_left("  & decimal i & ")") enddef ;
vardef rightof primary i = runscript("mp.mf_path_right(" & decimal i & ")") enddef ;

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

vardef utflen(expr s)     = lua.mp.utflen(s)     enddef ;
vardef utfsub(expr s,f,t) = lua.mp.utfsub(s,f,t) enddef ;