luat-usr.lmt /size: 5033 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['luat-usr'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local global            = global
10
11local moduledata        = moduledata
12local thirddata         = thirddata
13local userdata          = userdata
14local documentdata      = documentdata
15
16local context           = context
17local tostring          = tostring
18local tonumber          = tonumber
19local print             = print
20
21local string            = string
22local table             = table
23local lpeg              = lpeg
24local math              = math
25local io                = io
26local os                = os
27local lpeg              = lpeg
28
29local setmetatableindex = table.setmetatableindex
30local load              = load
31local xpcall            = xpcall
32local instance_banner   = string.formatters["=[instance: %s]"] -- the = controls the lua error / see: lobject.c
33local tex_errormessage  = context.errmessage
34
35local implement         = interfaces.implement
36local reporter          = logs.reporter
37
38local report_instance   = reporter("lua instance")
39local report_script     = reporter("lua script")
40local report_thread     = reporter("lua thread")
41local newline           = logs.newline
42
43lua.numbers             = lua.numbers  or { }
44lua.messages            = lua.messages or { }
45
46local numbers           = lua.numbers
47local messages          = lua.messages
48
49storage.register("lua/numbers",  numbers,  "lua.numbers" )
50storage.register("lua/messages", messages, "lua.messages")
51
52-- First we implement a pure lua version of directlua and a persistent
53-- variant of it:
54
55local function runscript(code)
56    local done, message = loadstring(code)
57    if done then
58        done()
59    else
60        newline()
61        report_script("error : %s",message or "unknown")
62        report_script()
63        report_script("code  : %s",code)
64        newline()
65    end
66end
67
68local threads = setmetatableindex(function(t,k)
69    local v = setmetatableindex({},global)
70    t[k] = v
71    return v
72end)
73
74local function runthread(name,code)
75    if not code or code == "" then
76        threads[name] = nil
77    else
78        local thread = threads[name]
79        local done, message = loadstring(code,nil,nil,thread)
80        if done then
81            done()
82        else
83            newline()
84            report_thread("thread: %s",name)
85            report_thread("error : %s",message or "unknown")
86            report_thread()
87            report_thread("code  : %s",code)
88            newline()
89        end
90    end
91end
92
93interfaces.implement {
94    name      = "luascript",
95    actions   = runscript,
96    public    = true,
97    protected = true,
98    arguments = "string"
99}
100
101interfaces.implement {
102    name      = "luathread",
103    actions   = runthread,
104    public    = true,
105    protected = true,
106    arguments = "2 strings",
107}
108
109local function registername(name,message)
110    if not name or name == "" then
111        report_instance("no valid name given")
112        return
113    end
114    if not message or message == "" then
115        message = name
116    end
117    local lnn = numbers[name]
118    if not lnn then
119        lnn = #messages + 1
120        messages[lnn] = message
121        numbers[name] = lnn
122    end
123    local report = reporter("lua instance",message)
124    local proxy = {
125        -- we can access all via:
126        global       = global, -- or maybe just a metatable
127        -- some protected data
128        moduledata   = setmetatableindex(moduledata),
129        thirddata    = setmetatableindex(thirddata),
130        -- less protected data
131        userdata     = userdata,
132        documentdata = documentdata,
133        -- always there fast
134        context      = context,
135        --
136        tostring     = tostring,
137        tonumber     = tonumber,
138        -- standard lua modules
139        string       = string,
140        table        = table,
141        lpeg         = lpeg,
142        math         = math,
143        io           = io,
144        os           = os,
145        lpeg         = lpeg,
146        --
147        print        = print,
148        report       = report,
149    }
150    return function(code)
151        local code, message = load(code,nil,nil,proxy)
152        if not code then
153            report_instance("error: %s",message or code)
154        elseif not xpcall(code,report) then
155            tex_errormessage("hit return to continue or quit this run")
156        end
157    end
158end
159
160lua.registername = registername
161
162implement {
163    name      = "registernamedlua",
164    arguments = "3 strings",
165    actions   = function(name,message,csname)
166        if csname and csname ~= "" then
167            implement {
168                name      = csname,
169                arguments = "string",
170                actions   = registername(name,message) or report,
171                scope     = "private",
172            }
173        else
174            report_instance("unvalid csname for %a",message or name or "?")
175        end
176    end
177}
178