luat-usr.lua /size: 4945 b    last modification: 2020-07-01 14:35
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    arguments = "string"
97}
98
99interfaces.implement {
100    name      = "luathread",
101    actions   = runthread,
102    arguments = "2 strings",
103}
104
105local function registername(name,message)
106    if not name or name == "" then
107        report_instance("no valid name given")
108        return
109    end
110    if not message or message == "" then
111        message = name
112    end
113    local lnn = numbers[name]
114    if not lnn then
115        lnn = #messages + 1
116        messages[lnn] = message
117        numbers[name] = lnn
118    end
119    local report = reporter("lua instance",message)
120    local proxy = {
121        -- we can access all via:
122        global       = global, -- or maybe just a metatable
123        -- some protected data
124        moduledata   = setmetatableindex(moduledata),
125        thirddata    = setmetatableindex(thirddata),
126        -- less protected data
127        userdata     = userdata,
128        documentdata = documentdata,
129        -- always there fast
130        context      = context,
131        --
132        tostring     = tostring,
133        tonumber     = tonumber,
134        -- standard lua modules
135        string       = string,
136        table        = table,
137        lpeg         = lpeg,
138        math         = math,
139        io           = io,
140        os           = os,
141        lpeg         = lpeg,
142        --
143        print        = print,
144        report       = report,
145    }
146    return function(code)
147        local code, message = load(code,nil,nil,proxy)
148        if not code then
149            report_instance("error: %s",message or code)
150        elseif not xpcall(code,report) then
151            tex_errormessage("hit return to continue or quit this run")
152        end
153    end
154end
155
156lua.registername = registername
157
158implement {
159    name      = "registernamedlua",
160    arguments = "3 strings",
161    actions   = function(name,message,csname)
162        if csname and csname ~= "" then
163            implement {
164                name      = csname,
165                arguments = "string",
166                actions   = registername(name,message) or report,
167                scope     = "private",
168            }
169        else
170            report_instance("unvalid csname for %a",message or name or "?")
171        end
172    end
173}
174