diff options
Diffstat (limited to 'tex/context/base/mkiv/syst-lua.lmt')
-rw-r--r-- | tex/context/base/mkiv/syst-lua.lmt | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/syst-lua.lmt b/tex/context/base/mkiv/syst-lua.lmt new file mode 100644 index 000000000..018231e30 --- /dev/null +++ b/tex/context/base/mkiv/syst-lua.lmt @@ -0,0 +1,315 @@ +if not modules then modules = { } end modules ['syst-lua'] = { + version = 1.001, + comment = "companion to syst-lua.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local load, type, tonumber = load, type, tonumber +local find = string.find +local concat = table.concat +local utfchar = utf.char +local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat + +local xmath = xmath or math +local xcomplex = xcomplex or { } + +local scan_next = token.scan_next or token.get_next +local scan_cmdchr = token.scan_cmdchr_expanded +local scan_token = token.scan_token + +local get_csname = token.get_csname +----- get_macro = token.get_macro +----- put_next = token.put_next + +local cmd = tokens.commands +local letter_code = cmd.letter +local other_char_code = cmd.other_char +local spacer_code = cmd.spacer +local other_char_code = cmd.other_char +local relax_code = cmd.relax +local register_int_code = cmd.register_int +local internal_int_code = cmd.internal_int +local register_dimen_code = cmd.register_dimen +local internal_dimen_code = cmd.internal_dimen +local register_glue_code = cmd.register_glue +local internal_glue_code = cmd.internal_glue +local register_toks_code = cmd.register_toks +local internal_toks_code = cmd.internal_toks +local char_given_code = cmd.char_given +local math_given_code = cmd.math_given +local xmath_given_code = cmd.xmath_given +local some_item_code = cmd.some_item +----- call_code = cmd.call +----- the_code = cmd.the +----- convert_code = cmd.convert +----- lua_expandable_call_code = cmd.lua_expandable_call + +local getdimen = tex.getdimen +local getglue = tex.getglue +local getcount = tex.getcount +local gettoks = tex.gettoks +local gettex = tex.get + +local context = context +commands = commands or { } +local commands = commands +local context = context +local implement = interfaces.implement +local dimenfactors = number.dimenfactors + +local ctx_protected_cs = context.protected.cs -- more efficient +local ctx_firstoftwoarguments = context.firstoftwoarguments +local ctx_secondoftwoarguments = context.secondoftwoarguments +local ctx_firstofoneargument = context.firstofoneargument +local ctx_gobbleoneargument = context.gobbleoneargument + +implement { -- will be overloaded later + name = "writestatus", + arguments = "2 strings", + actions = logs.status, +} + +function commands.doifelse(b) + if b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doifelsesomething(b) + if b and b ~= "" then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doif(b) + if b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifsomething(b) + if b and b ~= "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifnot(b) + if b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end +end + +function commands.doifnotthing(b) + if b and b ~= "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end +end + +commands.testcase = commands.doifelse -- obsolete + +function commands.boolcase(b) + context(b and 1 or 0) +end + +function commands.doifelsespaces(str) + if find(str,"^ +$") then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +local pattern = lpeg.patterns.validdimen + +function commands.doifelsedimenstring(str) + if lpegmatch(pattern,str) then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +local p_first = C((1-P(",")-P(-1))^0) + +implement { + name = "firstinset", + arguments = "string", + actions = function(str) context(lpegmatch(p_first,str or "")) end, + public = true, +} + +implement { + name = "ntimes", + arguments = { "string", "integer" }, + actions = { string.rep, context } +} + +implement { + name = "execute", + arguments = "string", + actions = os.execute -- wrapped in sandbox +} + +implement { + name = "doifelsesame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end + end +} + +implement { + name = "doifsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + end +} + +implement { + name = "doifnotsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + end +} + +-- This is a bit of a joke as I never really needed floating point expressions (okay, +-- maybe only with scaling because there one can get numbers that are too large for +-- dimensions to deal with). Of course one can write a parser in \TEX\ speak but then +-- one also needs to implement a bunch of functions. It doesn't pay of so we just +-- stick to the next gimmick. It looks inefficient but performance is actually quite +-- efficient. + +do + + local result = { "return " } + local word = { } + local r = 1 + local w = 0 + + local report = logs.reporter("system","expression") + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function expression() + local w = 0 + local r = 1 + while true do + local n, i = scan_cmdchr() + if n == letter_code then + w = w + 1 ; word[w] = utfchar(i) + else + if w > 0 then + -- we could use a metatable for all math, complex and factors + local s = concat(word,"",1,w) + local d = dimenfactors[s] + if d then + r = r + 1 ; result[r] = "*" + r = r + 1 ; result[r] = 1/d + else + if xmath[s] then + r = r + 1 ; result[r] = "xmath." + elseif xcomplex[s] then + r = r + 1 ; result[r] = "xcomplex." + end + r = r + 1 ; result[r] = s + end + w = 0 + end + if n == other_char_code then + r = r + 1 ; result[r] = utfchar(i) + elseif n == spacer_code then + -- r = r + 1 ; result[r] = " " + elseif n == relax_code then + break + elseif n == register_int_code or n == internal_int_code then + r = r + 1 ; result[r] = getcount(i) + elseif n == register_dimen_code or n == internal_dimen_code then + r = r + 1 ; result[r] = getdimen(i) + elseif n == register_glue_code or n == n == register_dimen_code_glue_code then + r = r + 1 ; result[r] = getglue(i) + elseif n == register_toks_code or n == n == register_dimen_code_toks_code then + r = r + 1 ; result[r] = gettoks(i) + elseif n == char_given_code or n == math_given_code or n == xmath_given_code then + r = r + 1 ; result[r] = i + elseif n == some_item_code then + local n = get_csname(t) + if n then + local s = gettex(n) + if s then + r = r + 1 ; result[r] = s + else + unexpected(c) + end + else + unexpected(c) + end + -- elseif n == call_code then + -- local n = get_csname(t) + -- if n then + -- local s = get_macro(n) + -- if s then + -- r = r + 1 ; result[r] = s + -- else + -- unexpected(c) + -- end + -- else + -- unexpected(c) + -- end + -- elseif n == the_code or n == convert_code or n == lua_expandable_call_code then + -- put_next(t) + -- scan_token() -- expands + else + unexpected(c) + end + end + end + local code = concat(result,"",1,r) + local func = load(code) + if type(func) == "function" then + context(func()) + else + report("invalid lua %a",code) + end + end + + implement { + public = true, + name = "expression", + actions = expression, + } + +end |