Skip to content

Instantly share code, notes, and snippets.

@The0x539
Created April 8, 2018 16:56
Show Gist options
  • Save The0x539/8bf5fa9f206117a913c31640836c79ed to your computer and use it in GitHub Desktop.
Save The0x539/8bf5fa9f206117a913c31640836c79ed to your computer and use it in GitHub Desktop.
local memo_mt = {__mode = "k"}
-- Memoize a function with one argument.
local function memoize(func)
local t = {}
setmetatable(t, memo_mt)
return function(x)
if t[x] then
return table.unpack(t[x])
else
local ret = {func(x)}
t[x] = ret
return table.unpack(ret)
end
end
end
local rawload = load
local function load(str)
return rawload(str, str, "t")
end
load = memoize(load)
-- Check whether a string is syntactically valid Lua.
local function isValid(str)
return not not load(str)
end
isValid = memoize(isValid)
-- Check whether a string is a valid Lua expression.
local function isExpression(str)
return isValid("return " .. str)
end
isExpression = memoize(isExpression)
-- Check whether a string is valid as the left side of a Lua assignment.
local function isAssignable(str)
return isValid(str .. " = nil")
end
isAssignable = memoize(isAssignable)
-- Split a string at a given index. Excludes the char at that index.
local function split(str, idx)
local left = str:sub(1, idx - 1)
local right = str:sub(idx + 1)
return left, right
end
-- Check whether a string is a valid Lua assignment.
local function isAssignment(str)
local idx = str:find("[^=]=[^=]")
if idx then
local left, right = split(str, idx + 1)
return isAssignable(left) and isExpression(right)
else
return false
end
end
isAssignment = memoize(isAssignment)
-- Evaluate an expression
local function eval(str)
local chunk = load("return " .. str)
return select(2, pcall(chunk))
end
-- load()() but REPL-ier
local function exec(str)
if isExpression(str) then
print(eval(str))
elseif isAssignment(str) then
local left, right = split(str, str:find("[^=]=[^=]") + 1)
local rightVal = eval(right)
load(left .. "=" .. rightVal)()
print(rightVal)
elseif isValid(str) then
local chunk = load(str)
print(select(2, pcall(str)))
else
print(select(2, load(str)))
end
end
while true do
local line = io.read()
exec(line)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment