1
0
Fork 0
mirror of https://github.com/Reuh/candran.git synced 2025-10-27 17:59:30 +00:00

Rename built-in macros to __*__, add flag to disable built-in macros

This commit is contained in:
Étienne Fildadut 2021-06-17 18:03:34 +02:00
parent b72aff807c
commit dd22f2de3d
3 changed files with 297 additions and 290 deletions

View file

@ -492,7 +492,8 @@ _assert(5 = 2, "failed") -- replaced with if 5 = 2 then error("failed") end
Candran provide some predefined macros by default: Candran provide some predefined macros by default:
* `__STR__(expr)`: returns a string litteral representing the expression (e.g., `__STR__(5 + 2)` expands to `"5 + 2"`) * `__STR__(expr)`: returns a string litteral representing the expression (e.g., `__STR__(5 + 2)` expands to `"5 + 2"`)
* `constexpr(expr)`: calculate the result of the expression in the preprocessor, and returns a representation of the returned value, i.e. precalculate an expression at compile time * `__CONSTEXPR__(expr)`: calculate the result of the expression in the preprocessor, and returns a representation of the returned value, i.e. precalculate an expression at compile time
You can disable these built-in macros using the `noBuiltInMacros` compiler option.
Compile targets Compile targets
--------------- ---------------
@ -669,6 +670,7 @@ variablePrefix = "__CAN_" -- Prefix used when Candran needs to set a local varia
mapLines = true -- if true, compiled files will contain comments at the end of each line indicating the associated line and source file. Needed for error rewriting. mapLines = true -- if true, compiled files will contain comments at the end of each line indicating the associated line and source file. Needed for error rewriting.
chunkname = "nil" -- the chunkname used when running code using the helper functions and writing the line origin comments. Candran will try to set it to the original filename if it knows it. chunkname = "nil" -- the chunkname used when running code using the helper functions and writing the line origin comments. Candran will try to set it to the original filename if it knows it.
rewriteErrors = true -- true to enable error rewriting when loading code using the helper functions. Will wrap the whole code in a xpcall(). rewriteErrors = true -- true to enable error rewriting when loading code using the helper functions. Will wrap the whole code in a xpcall().
noBuiltInMacros = false -- true to disable built-in macros __*__
``` ```
You can change the defaults used for these variables in the table `candran.default`. You can change the defaults used for these variables in the table `candran.default`.

View file

@ -28,7 +28,8 @@ candran.default = {
variablePrefix = "__CAN_", variablePrefix = "__CAN_",
mapLines = true, mapLines = true,
chunkname = "nil", chunkname = "nil",
rewriteErrors = true rewriteErrors = true,
noBuiltInMacros = false
} }
-- Autodetect version -- Autodetect version
@ -178,12 +179,13 @@ function candran.preprocess(input, options={})
end end
-- default macros -- default macros
-- TODO make it optional if not options.noBuiltInMacros then
env.define("__STR__(x)", function(x) return ("%q"):format(x) end) env.define("__STR__(x)", function(x) return ("%q"):format(x) end)
local s = require("candran.serpent") local s = require("candran.serpent")
env.define("constexpr(expr)", function(expr) env.define("__CONSTEXPR__(expr)", function(expr)
return s.block(assert(candran.load(expr))(), {fatal = true}) return s.block(assert(candran.load(expr))(), {fatal = true})
end) end)
end
-- compile & load preprocessor -- compile & load preprocessor
local preprocess, err = candran.compile(preprocessor, options) local preprocess, err = candran.compile(preprocessor, options)

View file

@ -7078,307 +7078,310 @@ candran["default"] = { -- candran.can:24
["variablePrefix"] = "__CAN_", -- candran.can:28 ["variablePrefix"] = "__CAN_", -- candran.can:28
["mapLines"] = true, -- candran.can:29 ["mapLines"] = true, -- candran.can:29
["chunkname"] = "nil", -- candran.can:30 ["chunkname"] = "nil", -- candran.can:30
["rewriteErrors"] = true -- candran.can:31 ["rewriteErrors"] = true, -- candran.can:31
} -- candran.can:31 ["noBuiltInMacros"] = false -- candran.can:32
if _VERSION == "Lua 5.1" then -- candran.can:35 } -- candran.can:32
if package["loaded"]["jit"] then -- candran.can:36 if _VERSION == "Lua 5.1" then -- candran.can:36
candran["default"]["target"] = "luajit" -- candran.can:37 if package["loaded"]["jit"] then -- candran.can:37
else -- candran.can:37 candran["default"]["target"] = "luajit" -- candran.can:38
candran["default"]["target"] = "lua51" -- candran.can:39 else -- candran.can:38
end -- candran.can:39 candran["default"]["target"] = "lua51" -- candran.can:40
elseif _VERSION == "Lua 5.2" then -- candran.can:41 end -- candran.can:40
candran["default"]["target"] = "lua52" -- candran.can:42 elseif _VERSION == "Lua 5.2" then -- candran.can:42
elseif _VERSION == "Lua 5.3" then -- candran.can:43 candran["default"]["target"] = "lua52" -- candran.can:43
candran["default"]["target"] = "lua53" -- candran.can:44 elseif _VERSION == "Lua 5.3" then -- candran.can:44
end -- candran.can:44 candran["default"]["target"] = "lua53" -- candran.can:45
candran["preprocess"] = function(input, options) -- candran.can:54 end -- candran.can:45
if options == nil then options = {} end -- candran.can:54 candran["preprocess"] = function(input, options) -- candran.can:55
options = util["merge"](candran["default"], options) -- candran.can:55 if options == nil then options = {} end -- candran.can:55
local macros = { -- candran.can:56 options = util["merge"](candran["default"], options) -- candran.can:56
["functions"] = {}, -- candran.can:57 local macros = { -- candran.can:57
["variables"] = {} -- candran.can:58 ["functions"] = {}, -- candran.can:58
} -- candran.can:58 ["variables"] = {} -- candran.can:59
local preprocessor = "" -- candran.can:62 } -- candran.can:59
local i = 0 -- candran.can:63 local preprocessor = "" -- candran.can:63
local inLongString = false -- candran.can:64 local i = 0 -- candran.can:64
local inComment = false -- candran.can:65 local inLongString = false -- candran.can:65
local inComment = false -- candran.can:66
for line in (input .. "\ for line in (input .. "\
"):gmatch("(.-\ "):gmatch("(.-\
)") do -- candran.can:66 )") do -- candran.can:67
i = i + (1) -- candran.can:67 i = i + (1) -- candran.can:68
if inComment then -- candran.can:69 if inComment then -- candran.can:70
inComment = not line:match("%]%]") -- candran.can:70 inComment = not line:match("%]%]") -- candran.can:71
elseif inLongString then -- candran.can:71 elseif inLongString then -- candran.can:72
inLongString = not line:match("%]%]") -- candran.can:72 inLongString = not line:match("%]%]") -- candran.can:73
else -- candran.can:72 else -- candran.can:73
if line:match("[^%-]%[%[") then -- candran.can:74 if line:match("[^%-]%[%[") then -- candran.can:75
inLongString = true -- candran.can:75 inLongString = true -- candran.can:76
elseif line:match("%-%-%[%[") then -- candran.can:76 elseif line:match("%-%-%[%[") then -- candran.can:77
inComment = true -- candran.can:77 inComment = true -- candran.can:78
end -- candran.can:77 end -- candran.can:78
end -- candran.can:77 end -- candran.can:78
if not inComment and not inLongString and line:match("^%s*#") and not line:match("^#!") then -- candran.can:80 if not inComment and not inLongString and line:match("^%s*#") and not line:match("^#!") then -- candran.can:81
preprocessor = preprocessor .. (line:gsub("^%s*#", "")) -- candran.can:81 preprocessor = preprocessor .. (line:gsub("^%s*#", "")) -- candran.can:82
else -- candran.can:81 else -- candran.can:82
local l = line:sub(1, - 2) -- candran.can:83 local l = line:sub(1, - 2) -- candran.can:84
if not inLongString and options["mapLines"] and not l:match("%-%- (.-)%:(%d+)$") then -- candran.can:84 if not inLongString and options["mapLines"] and not l:match("%-%- (.-)%:(%d+)$") then -- candran.can:85
preprocessor = preprocessor .. (("write(%q)"):format(l .. " -- " .. options["chunkname"] .. ":" .. i) .. "\ preprocessor = preprocessor .. (("write(%q)"):format(l .. " -- " .. options["chunkname"] .. ":" .. i) .. "\
") -- candran.can:85 ") -- candran.can:86
else -- candran.can:85 else -- candran.can:86
preprocessor = preprocessor .. (("write(%q)"):format(line:sub(1, - 2)) .. "\ preprocessor = preprocessor .. (("write(%q)"):format(line:sub(1, - 2)) .. "\
") -- candran.can:87 ") -- candran.can:88
end -- candran.can:87 end -- candran.can:88
end -- candran.can:87 end -- candran.can:88
end -- candran.can:87 end -- candran.can:88
preprocessor = preprocessor .. ("return output") -- candran.can:91 preprocessor = preprocessor .. ("return output") -- candran.can:92
local env = util["merge"](_G, options) -- candran.can:94 local env = util["merge"](_G, options) -- candran.can:95
env["candran"] = candran -- candran.can:96 env["candran"] = candran -- candran.can:97
env["output"] = "" -- candran.can:98 env["output"] = "" -- candran.can:99
env["import"] = function(modpath, margs) -- candran.can:105 env["import"] = function(modpath, margs) -- candran.can:106
if margs == nil then margs = {} end -- candran.can:105 if margs == nil then margs = {} end -- candran.can:106
local filepath = assert(util["search"](modpath, { -- candran.can:106 local filepath = assert(util["search"](modpath, { -- candran.can:107
"can", -- candran.can:106 "can", -- candran.can:107
"lua" -- candran.can:106 "lua" -- candran.can:107
}), "No module named \"" .. modpath .. "\"") -- candran.can:106 }), "No module named \"" .. modpath .. "\"") -- candran.can:107
local f = io["open"](filepath) -- candran.can:109 local f = io["open"](filepath) -- candran.can:110
if not f then -- candran.can:110 if not f then -- candran.can:111
error("can't open the module file to import") -- candran.can:110 error("can't open the module file to import") -- candran.can:111
end -- candran.can:110 end -- candran.can:111
margs = util["merge"](options, { -- candran.can:112 margs = util["merge"](options, { -- candran.can:113
["chunkname"] = filepath, -- candran.can:112 ["chunkname"] = filepath, -- candran.can:113
["loadLocal"] = true, -- candran.can:112 ["loadLocal"] = true, -- candran.can:113
["loadPackage"] = true -- candran.can:112 ["loadPackage"] = true -- candran.can:113
}, margs) -- candran.can:112 }, margs) -- candran.can:113
local modcontent, modmacros = assert(candran["preprocess"](f:read("*a"), margs)) -- candran.can:113 local modcontent, modmacros = assert(candran["preprocess"](f:read("*a"), margs)) -- candran.can:114
macros = util["recmerge"](macros, modmacros) -- candran.can:114 macros = util["recmerge"](macros, modmacros) -- candran.can:115
f:close() -- candran.can:115 f:close() -- candran.can:116
local modname = modpath:match("[^%.]+$") -- candran.can:118 local modname = modpath:match("[^%.]+$") -- candran.can:119
env["write"]("-- MODULE " .. modpath .. " --\ env["write"]("-- MODULE " .. modpath .. " --\
" .. "local function _()\ " .. "local function _()\
" .. modcontent .. "\ " .. modcontent .. "\
" .. "end\ " .. "end\
" .. (margs["loadLocal"] and ("local %s = _() or %s\ " .. (margs["loadLocal"] and ("local %s = _() or %s\
"):format(modname, modname) or "") .. (margs["loadPackage"] and ("package.loaded[%q] = %s or true\ "):format(modname, modname) or "") .. (margs["loadPackage"] and ("package.loaded[%q] = %s or true\
"):format(modpath, margs["loadLocal"] and modname or "_()") or "") .. "-- END OF MODULE " .. modpath .. " --") -- candran.can:127 "):format(modpath, margs["loadLocal"] and modname or "_()") or "") .. "-- END OF MODULE " .. modpath .. " --") -- candran.can:128
end -- candran.can:127 end -- candran.can:128
env["include"] = function(file) -- candran.can:132 env["include"] = function(file) -- candran.can:133
local f = io["open"](file) -- candran.can:133 local f = io["open"](file) -- candran.can:134
if not f then -- candran.can:134 if not f then -- candran.can:135
error("can't open the file " .. file .. " to include") -- candran.can:134 error("can't open the file " .. file .. " to include") -- candran.can:135
end -- candran.can:134 end -- candran.can:135
env["write"](f:read("*a")) -- candran.can:135 env["write"](f:read("*a")) -- candran.can:136
f:close() -- candran.can:136 f:close() -- candran.can:137
end -- candran.can:136 end -- candran.can:137
env["write"] = function(...) -- candran.can:140 env["write"] = function(...) -- candran.can:141
env["output"] = env["output"] .. (table["concat"]({ ... }, "\9") .. "\ env["output"] = env["output"] .. (table["concat"]({ ... }, "\9") .. "\
") -- candran.can:141 ") -- candran.can:142
end -- candran.can:141 end -- candran.can:142
env["placeholder"] = function(name) -- candran.can:145 env["placeholder"] = function(name) -- candran.can:146
if env[name] then -- candran.can:146 if env[name] then -- candran.can:147
env["write"](env[name]) -- candran.can:147 env["write"](env[name]) -- candran.can:148
end -- candran.can:147 end -- candran.can:148
end -- candran.can:147 end -- candran.can:148
env["define"] = function(identifier, replacement) -- candran.can:150 env["define"] = function(identifier, replacement) -- candran.can:151
local iast, ierr = parser["parsemacroidentifier"](identifier, options["chunkname"]) -- candran.can:152 local iast, ierr = parser["parsemacroidentifier"](identifier, options["chunkname"]) -- candran.can:153
if not iast then -- candran.can:153 if not iast then -- candran.can:154
return error(("in macro identifier: %s"):format(tostring(ierr))) -- candran.can:154 return error(("in macro identifier: %s"):format(tostring(ierr))) -- candran.can:155
end -- candran.can:154 end -- candran.can:155
if type(replacement) == "string" then -- candran.can:157 if type(replacement) == "string" then -- candran.can:158
local rast, rerr = parser["parse"](replacement, options["chunkname"]) -- candran.can:158 local rast, rerr = parser["parse"](replacement, options["chunkname"]) -- candran.can:159
if not rast then -- candran.can:159 if not rast then -- candran.can:160
return error(("in macro replacement: %s"):format(tostring(rerr))) -- candran.can:160 return error(("in macro replacement: %s"):format(tostring(rerr))) -- candran.can:161
end -- candran.can:160 end -- candran.can:161
if # rast == 1 and rast[1]["tag"] == "Push" and rast[1]["implicit"] then -- candran.can:163 if # rast == 1 and rast[1]["tag"] == "Push" and rast[1]["implicit"] then -- candran.can:164
rast = rast[1][1] -- candran.can:164 rast = rast[1][1] -- candran.can:165
end -- candran.can:164 end -- candran.can:165
replacement = rast -- candran.can:166 replacement = rast -- candran.can:167
elseif type(replacement) ~= "function" then -- candran.can:167 elseif type(replacement) ~= "function" then -- candran.can:168
error("bad argument #2 to 'define' (string or function expected)") -- candran.can:168 error("bad argument #2 to 'define' (string or function expected)") -- candran.can:169
end -- candran.can:168 end -- candran.can:169
if iast["tag"] == "MacroFunction" then -- candran.can:171 if iast["tag"] == "MacroFunction" then -- candran.can:172
macros["functions"][iast[1][1]] = { -- candran.can:172 macros["functions"][iast[1][1]] = { -- candran.can:173
["args"] = iast[2], -- candran.can:172 ["args"] = iast[2], -- candran.can:173
["replacement"] = replacement -- candran.can:172 ["replacement"] = replacement -- candran.can:173
} -- candran.can:172 } -- candran.can:173
elseif iast["tag"] == "Id" then -- candran.can:173 elseif iast["tag"] == "Id" then -- candran.can:174
macros["variables"][iast[1]] = replacement -- candran.can:174 macros["variables"][iast[1]] = replacement -- candran.can:175
else -- candran.can:174 else -- candran.can:175
error(("invalid macro type %s"):format(tostring(iast["tag"]))) -- candran.can:176 error(("invalid macro type %s"):format(tostring(iast["tag"]))) -- candran.can:177
end -- candran.can:176 end -- candran.can:177
end -- candran.can:176 end -- candran.can:177
env["define"]("__STR__(x)", function(x) -- candran.can:182 if not options["noBuiltInMacros"] then -- candran.can:182
return ("%q"):format(x) -- candran.can:182 env["define"]("__STR__(x)", function(x) -- candran.can:183
end) -- candran.can:182 return ("%q"):format(x) -- candran.can:183
local s = require("candran.serpent") -- candran.can:183 end) -- candran.can:183
env["define"]("constexpr(expr)", function(expr) -- candran.can:184 local s = require("candran.serpent") -- candran.can:184
return s["block"](assert(candran["load"](expr))(), { ["fatal"] = true }) -- candran.can:185 env["define"]("__CONSTEXPR__(expr)", function(expr) -- candran.can:185
end) -- candran.can:185 return s["block"](assert(candran["load"](expr))(), { ["fatal"] = true }) -- candran.can:186
local preprocess, err = candran["compile"](preprocessor, options) -- candran.can:189 end) -- candran.can:186
if not preprocess then -- candran.can:190 end -- candran.can:186
return nil, "in preprocessor: " .. err -- candran.can:191 local preprocess, err = candran["compile"](preprocessor, options) -- candran.can:191
end -- candran.can:191 if not preprocess then -- candran.can:192
preprocess, err = util["load"](preprocessor, "candran preprocessor", env) -- candran.can:194 return nil, "in preprocessor: " .. err -- candran.can:193
if not preprocess then -- candran.can:195 end -- candran.can:193
return nil, "in preprocessor: " .. err -- candran.can:196 preprocess, err = util["load"](preprocessor, "candran preprocessor", env) -- candran.can:196
end -- candran.can:196 if not preprocess then -- candran.can:197
local success, output = pcall(preprocess) -- candran.can:200 return nil, "in preprocessor: " .. err -- candran.can:198
if not success then -- candran.can:201 end -- candran.can:198
return nil, "in preprocessor: " .. output -- candran.can:202 local success, output = pcall(preprocess) -- candran.can:202
end -- candran.can:202 if not success then -- candran.can:203
return output, macros -- candran.can:205 return nil, "in preprocessor: " .. output -- candran.can:204
end -- candran.can:205 end -- candran.can:204
candran["compile"] = function(input, options, macros) -- candran.can:215 return output, macros -- candran.can:207
if options == nil then options = {} end -- candran.can:215 end -- candran.can:207
options = util["merge"](candran["default"], options) -- candran.can:216 candran["compile"] = function(input, options, macros) -- candran.can:217
local ast, errmsg = parser["parse"](input, options["chunkname"]) -- candran.can:218 if options == nil then options = {} end -- candran.can:217
if not ast then -- candran.can:220 options = util["merge"](candran["default"], options) -- candran.can:218
return nil, errmsg -- candran.can:221 local ast, errmsg = parser["parse"](input, options["chunkname"]) -- candran.can:220
end -- candran.can:221 if not ast then -- candran.can:222
return require("compiler." .. options["target"])(input, ast, options, macros) -- candran.can:224 return nil, errmsg -- candran.can:223
end -- candran.can:224 end -- candran.can:223
candran["make"] = function(code, options) -- candran.can:233 return require("compiler." .. options["target"])(input, ast, options, macros) -- candran.can:226
local r, err = candran["preprocess"](code, options) -- candran.can:234 end -- candran.can:226
if r then -- candran.can:235 candran["make"] = function(code, options) -- candran.can:235
r, err = candran["compile"](r, options, err) -- candran.can:236 local r, err = candran["preprocess"](code, options) -- candran.can:236
if r then -- candran.can:237 if r then -- candran.can:237
return r -- candran.can:238 r, err = candran["compile"](r, options, err) -- candran.can:238
end -- candran.can:238 if r then -- candran.can:239
end -- candran.can:238 return r -- candran.can:240
return r, err -- candran.can:241 end -- candran.can:240
end -- candran.can:241 end -- candran.can:240
local errorRewritingActive = false -- candran.can:244 return r, err -- candran.can:243
local codeCache = {} -- candran.can:245 end -- candran.can:243
candran["loadfile"] = function(filepath, env, options) -- candran.can:248 local errorRewritingActive = false -- candran.can:246
local f, err = io["open"](filepath) -- candran.can:249 local codeCache = {} -- candran.can:247
if not f then -- candran.can:250 candran["loadfile"] = function(filepath, env, options) -- candran.can:250
return nil, ("cannot open %s"):format(tostring(err)) -- candran.can:251 local f, err = io["open"](filepath) -- candran.can:251
end -- candran.can:251 if not f then -- candran.can:252
local content = f:read("*a") -- candran.can:253 return nil, ("cannot open %s"):format(tostring(err)) -- candran.can:253
f:close() -- candran.can:254 end -- candran.can:253
return candran["load"](content, filepath, env, options) -- candran.can:256 local content = f:read("*a") -- candran.can:255
end -- candran.can:256 f:close() -- candran.can:256
candran["load"] = function(chunk, chunkname, env, options) -- candran.can:261 return candran["load"](content, filepath, env, options) -- candran.can:258
if options == nil then options = {} end -- candran.can:261 end -- candran.can:258
options = util["merge"]({ ["chunkname"] = tostring(chunkname or chunk) }, options) -- candran.can:262 candran["load"] = function(chunk, chunkname, env, options) -- candran.can:263
local code, err = candran["make"](chunk, options) -- candran.can:264 if options == nil then options = {} end -- candran.can:263
if not code then -- candran.can:265 options = util["merge"]({ ["chunkname"] = tostring(chunkname or chunk) }, options) -- candran.can:264
return code, err -- candran.can:266 local code, err = candran["make"](chunk, options) -- candran.can:266
end -- candran.can:266 if not code then -- candran.can:267
codeCache[options["chunkname"]] = code -- candran.can:269 return code, err -- candran.can:268
local f -- candran.can:270 end -- candran.can:268
f, err = util["load"](code, ("=%s(%s)"):format(options["chunkname"], "compiled candran"), env) -- candran.can:271 codeCache[options["chunkname"]] = code -- candran.can:271
if f == nil then -- candran.can:276 local f -- candran.can:272
return f, "candran unexpectedly generated invalid code: " .. err -- candran.can:277 f, err = util["load"](code, ("=%s(%s)"):format(options["chunkname"], "compiled candran"), env) -- candran.can:273
end -- candran.can:277 if f == nil then -- candran.can:278
if options["rewriteErrors"] == false then -- candran.can:280 return f, "candran unexpectedly generated invalid code: " .. err -- candran.can:279
return f -- candran.can:281 end -- candran.can:279
else -- candran.can:281 if options["rewriteErrors"] == false then -- candran.can:282
return function(...) -- candran.can:283 return f -- candran.can:283
if not errorRewritingActive then -- candran.can:284 else -- candran.can:283
errorRewritingActive = true -- candran.can:285 return function(...) -- candran.can:285
local t = { xpcall(f, candran["messageHandler"], ...) } -- candran.can:286 if not errorRewritingActive then -- candran.can:286
errorRewritingActive = false -- candran.can:287 errorRewritingActive = true -- candran.can:287
if t[1] == false then -- candran.can:288 local t = { xpcall(f, candran["messageHandler"], ...) } -- candran.can:288
error(t[2], 0) -- candran.can:289 errorRewritingActive = false -- candran.can:289
end -- candran.can:289 if t[1] == false then -- candran.can:290
return unpack(t, 2) -- candran.can:291 error(t[2], 0) -- candran.can:291
else -- candran.can:291 end -- candran.can:291
return f(...) -- candran.can:293 return unpack(t, 2) -- candran.can:293
end -- candran.can:293 else -- candran.can:293
end -- candran.can:293 return f(...) -- candran.can:295
end -- candran.can:293 end -- candran.can:295
end -- candran.can:293 end -- candran.can:295
candran["dofile"] = function(filename, options) -- candran.can:301 end -- candran.can:295
local f, err = candran["loadfile"](filename, nil, options) -- candran.can:302 end -- candran.can:295
if f == nil then -- candran.can:304 candran["dofile"] = function(filename, options) -- candran.can:303
error(err) -- candran.can:305 local f, err = candran["loadfile"](filename, nil, options) -- candran.can:304
else -- candran.can:305 if f == nil then -- candran.can:306
return f() -- candran.can:307 error(err) -- candran.can:307
end -- candran.can:307 else -- candran.can:307
end -- candran.can:307 return f() -- candran.can:309
candran["messageHandler"] = function(message, noTraceback) -- candran.can:313 end -- candran.can:309
end -- candran.can:309
candran["messageHandler"] = function(message, noTraceback) -- candran.can:315
if not noTraceback and not message:match("\ if not noTraceback and not message:match("\
stack traceback:\ stack traceback:\
") then -- candran.can:314 ") then -- candran.can:316
message = debug["traceback"](message, 2) -- candran.can:315 message = debug["traceback"](message, 2) -- candran.can:317
end -- candran.can:315 end -- candran.can:317
return message:gsub("(\ return message:gsub("(\
?%s*)([^\ ?%s*)([^\
]-)%:(%d+)%:", function(indentation, source, line) -- candran.can:317 ]-)%:(%d+)%:", function(indentation, source, line) -- candran.can:319
line = tonumber(line) -- candran.can:318 line = tonumber(line) -- candran.can:320
local originalFile -- candran.can:320 local originalFile -- candran.can:322
local strName = source:match("^(.-)%(compiled candran%)$") -- candran.can:321 local strName = source:match("^(.-)%(compiled candran%)$") -- candran.can:323
if strName then -- candran.can:322 if strName then -- candran.can:324
if codeCache[strName] then -- candran.can:323 if codeCache[strName] then -- candran.can:325
originalFile = codeCache[strName] -- candran.can:324 originalFile = codeCache[strName] -- candran.can:326
source = strName -- candran.can:325 source = strName -- candran.can:327
end -- candran.can:325 end -- candran.can:327
else -- candran.can:325 else -- candran.can:327
do -- candran.can:328 do -- candran.can:330
local fi -- candran.can:328 local fi -- candran.can:330
fi = io["open"](source, "r") -- candran.can:328 fi = io["open"](source, "r") -- candran.can:330
if fi then -- candran.can:328 if fi then -- candran.can:330
originalFile = fi:read("*a") -- candran.can:329 originalFile = fi:read("*a") -- candran.can:331
fi:close() -- candran.can:330 fi:close() -- candran.can:332
end -- candran.can:330 end -- candran.can:332
end -- candran.can:330 end -- candran.can:332
end -- candran.can:330 end -- candran.can:332
if originalFile then -- candran.can:334 if originalFile then -- candran.can:336
local i = 0 -- candran.can:335 local i = 0 -- candran.can:337
for l in (originalFile .. "\ for l in (originalFile .. "\
"):gmatch("([^\ "):gmatch("([^\
]*)\ ]*)\
") do -- candran.can:336 ") do -- candran.can:338
i = i + 1 -- candran.can:337 i = i + 1 -- candran.can:339
if i == line then -- candran.can:338 if i == line then -- candran.can:340
local extSource, lineMap = l:match(".*%-%- (.-)%:(%d+)$") -- candran.can:339 local extSource, lineMap = l:match(".*%-%- (.-)%:(%d+)$") -- candran.can:341
if lineMap then -- candran.can:340 if lineMap then -- candran.can:342
if extSource ~= source then -- candran.can:341 if extSource ~= source then -- candran.can:343
return indentation .. extSource .. ":" .. lineMap .. "(" .. extSource .. ":" .. line .. "):" -- candran.can:342 return indentation .. extSource .. ":" .. lineMap .. "(" .. extSource .. ":" .. line .. "):" -- candran.can:344
else -- candran.can:342 else -- candran.can:344
return indentation .. extSource .. ":" .. lineMap .. "(" .. line .. "):" -- candran.can:344 return indentation .. extSource .. ":" .. lineMap .. "(" .. line .. "):" -- candran.can:346
end -- candran.can:344 end -- candran.can:346
end -- candran.can:344 end -- candran.can:346
break -- candran.can:347 break -- candran.can:349
end -- candran.can:347 end -- candran.can:349
end -- candran.can:347 end -- candran.can:349
end -- candran.can:347 end -- candran.can:349
end) -- candran.can:347 end) -- candran.can:349
end -- candran.can:347 end -- candran.can:349
candran["searcher"] = function(modpath) -- candran.can:355 candran["searcher"] = function(modpath) -- candran.can:357
local filepath = util["search"](modpath, { "can" }) -- candran.can:356 local filepath = util["search"](modpath, { "can" }) -- candran.can:358
if not filepath then -- candran.can:357 if not filepath then -- candran.can:359
if _VERSION == "Lua 5.4" then -- candran.can:358 if _VERSION == "Lua 5.4" then -- candran.can:360
return "no candran file in package.path" -- candran.can:359 return "no candran file in package.path" -- candran.can:361
else -- candran.can:359 else -- candran.can:361
return "\ return "\
\9no candran file in package.path" -- candran.can:361 \9no candran file in package.path" -- candran.can:363
end -- candran.can:361 end -- candran.can:363
end -- candran.can:361 end -- candran.can:363
return function(modpath) -- candran.can:364 return function(modpath) -- candran.can:366
local r, s = candran["loadfile"](filepath) -- candran.can:365 local r, s = candran["loadfile"](filepath) -- candran.can:367
if r then -- candran.can:366 if r then -- candran.can:368
return r(modpath, filepath) -- candran.can:367 return r(modpath, filepath) -- candran.can:369
else -- candran.can:367 else -- candran.can:369
error(("error loading candran module '%s' from file '%s':\ error(("error loading candran module '%s' from file '%s':\
\9%s"):format(modpath, filepath, tostring(s)), 0) -- candran.can:369 \9%s"):format(modpath, filepath, tostring(s)), 0) -- candran.can:371
end -- candran.can:369
end, filepath -- candran.can:371
end -- candran.can:371 end -- candran.can:371
candran["setup"] = function() -- candran.can:375 end, filepath -- candran.can:373
local searchers = (function() -- candran.can:376 end -- candran.can:373
if _VERSION == "Lua 5.1" then -- candran.can:376 candran["setup"] = function() -- candran.can:377
return package["loaders"] -- candran.can:377 local searchers = (function() -- candran.can:378
else -- candran.can:377 if _VERSION == "Lua 5.1" then -- candran.can:378
return package["searchers"] -- candran.can:379 return package["loaders"] -- candran.can:379
end -- candran.can:379 else -- candran.can:379
end)() -- candran.can:379 return package["searchers"] -- candran.can:381
for _, s in ipairs(searchers) do -- candran.can:382 end -- candran.can:381
if s == candran["searcher"] then -- candran.can:383 end)() -- candran.can:381
return candran -- candran.can:384 for _, s in ipairs(searchers) do -- candran.can:384
end -- candran.can:384 if s == candran["searcher"] then -- candran.can:385
end -- candran.can:384 return candran -- candran.can:386
table["insert"](searchers, 1, candran["searcher"]) -- candran.can:388 end -- candran.can:386
return candran -- candran.can:389 end -- candran.can:386
end -- candran.can:389 table["insert"](searchers, 1, candran["searcher"]) -- candran.can:390
return candran -- candran.can:392 return candran -- candran.can:391
end -- candran.can:391
return candran -- candran.can:394