1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-09-28 15:08:47 +00:00

Backport a couple of ROM commits

- Improve REPL's handling of expressions
   (655d5aeca8)

 - Some tiny optimisations to the window API
   (4accda6b8e)

 - Be lazy in reporting errors in the lexer
   (54ab98473f)

 - Update lua.lua require logic.
   (88f0c44152)
This commit is contained in:
Jonathan Coates 2023-07-06 23:15:55 +01:00
parent db2616d1c0
commit f7fdb6e729
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
8 changed files with 71 additions and 94 deletions

View File

@ -127,11 +127,7 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
local sEmptyTextColor = tEmptyColorLines[nTextColor] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, nHeight do for y = 1, nHeight do
tLines[y] = { tLines[y] = { sEmptyText, sEmptyTextColor, sEmptyBackgroundColor }
text = sEmptyText,
textColor = sEmptyTextColor,
backgroundColor = sEmptyBackgroundColor,
}
end end
for i = 0, 15 do for i = 0, 15 do
@ -161,7 +157,7 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
local function redrawLine(n) local function redrawLine(n)
local tLine = tLines[n] local tLine = tLines[n]
parent.setCursorPos(nX, nY + n - 1) parent.setCursorPos(nX, nY + n - 1)
parent.blit(tLine.text, tLine.textColor, tLine.backgroundColor) parent.blit(tLine[1], tLine[2], tLine[3])
end end
local function redraw() local function redraw()
@ -184,9 +180,9 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
-- Modify line -- Modify line
local tLine = tLines[nCursorY] local tLine = tLines[nCursorY]
if nStart == 1 and nEnd == nWidth then if nStart == 1 and nEnd == nWidth then
tLine.text = sText tLine[1] = sText
tLine.textColor = sTextColor tLine[2] = sTextColor
tLine.backgroundColor = sBackgroundColor tLine[3] = sBackgroundColor
else else
local sClippedText, sClippedTextColor, sClippedBackgroundColor local sClippedText, sClippedTextColor, sClippedBackgroundColor
if nStart < 1 then if nStart < 1 then
@ -206,9 +202,9 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
sClippedBackgroundColor = sBackgroundColor sClippedBackgroundColor = sBackgroundColor
end end
local sOldText = tLine.text local sOldText = tLine[1]
local sOldTextColor = tLine.textColor local sOldTextColor = tLine[2]
local sOldBackgroundColor = tLine.backgroundColor local sOldBackgroundColor = tLine[3]
local sNewText, sNewTextColor, sNewBackgroundColor local sNewText, sNewTextColor, sNewBackgroundColor
if nStart > 1 then if nStart > 1 then
local nOldEnd = nStart - 1 local nOldEnd = nStart - 1
@ -227,9 +223,9 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
sNewBackgroundColor = sNewBackgroundColor .. string_sub(sOldBackgroundColor, nOldStart, nWidth) sNewBackgroundColor = sNewBackgroundColor .. string_sub(sOldBackgroundColor, nOldStart, nWidth)
end end
tLine.text = sNewText tLine[1] = sNewText
tLine.textColor = sNewTextColor tLine[2] = sNewTextColor
tLine.backgroundColor = sNewBackgroundColor tLine[3] = sNewBackgroundColor
end end
-- Redraw line -- Redraw line
@ -276,11 +272,10 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
local sEmptyTextColor = tEmptyColorLines[nTextColor] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, nHeight do for y = 1, nHeight do
tLines[y] = { local line = tLines[y]
text = sEmptyText, line[1] = sEmptyText
textColor = sEmptyTextColor, line[2] = sEmptyTextColor
backgroundColor = sEmptyBackgroundColor, line[3] = sEmptyBackgroundColor
}
end end
if bVisible then if bVisible then
redraw() redraw()
@ -291,14 +286,10 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
function window.clearLine() function window.clearLine()
if nCursorY >= 1 and nCursorY <= nHeight then if nCursorY >= 1 and nCursorY <= nHeight then
local sEmptyText = sEmptySpaceLine local line = tLines[nCursorY]
local sEmptyTextColor = tEmptyColorLines[nTextColor] line[1] = sEmptySpaceLine
local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor] line[2] = tEmptyColorLines[nTextColor]
tLines[nCursorY] = { line[3] = tEmptyColorLines[nBackgroundColor]
text = sEmptyText,
textColor = sEmptyTextColor,
backgroundColor = sEmptyBackgroundColor,
}
if bVisible then if bVisible then
redrawLine(nCursorY) redrawLine(nCursorY)
updateCursorColor() updateCursorColor()
@ -427,11 +418,7 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
if y >= 1 and y <= nHeight then if y >= 1 and y <= nHeight then
tNewLines[newY] = tLines[y] tNewLines[newY] = tLines[y]
else else
tNewLines[newY] = { tNewLines[newY] = { sEmptyText, sEmptyTextColor, sEmptyBackgroundColor }
text = sEmptyText,
textColor = sEmptyTextColor,
backgroundColor = sEmptyBackgroundColor,
}
end end
end end
tLines = tNewLines tLines = tNewLines
@ -474,7 +461,8 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
error("Line is out of range.", 2) error("Line is out of range.", 2)
end end
return tLines[y].text, tLines[y].textColor, tLines[y].backgroundColor local line = tLines[y]
return line[1], line[2], line[3]
end end
-- Other functions -- Other functions
@ -570,26 +558,22 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, new_height do for y = 1, new_height do
if y > nHeight then if y > nHeight then
tNewLines[y] = { tNewLines[y] = { sEmptyText, sEmptyTextColor, sEmptyBackgroundColor }
text = sEmptyText,
textColor = sEmptyTextColor,
backgroundColor = sEmptyBackgroundColor,
}
else else
local tOldLine = tLines[y] local tOldLine = tLines[y]
if new_width == nWidth then if new_width == nWidth then
tNewLines[y] = tOldLine tNewLines[y] = tOldLine
elseif new_width < nWidth then elseif new_width < nWidth then
tNewLines[y] = { tNewLines[y] = {
text = string_sub(tOldLine.text, 1, new_width), string_sub(tOldLine[1], 1, new_width),
textColor = string_sub(tOldLine.textColor, 1, new_width), string_sub(tOldLine[2], 1, new_width),
backgroundColor = string_sub(tOldLine.backgroundColor, 1, new_width), string_sub(tOldLine[3], 1, new_width),
} }
else else
tNewLines[y] = { tNewLines[y] = {
text = tOldLine.text .. string_sub(sEmptyText, nWidth + 1, new_width), tOldLine[1] .. string_sub(sEmptyText, nWidth + 1, new_width),
textColor = tOldLine.textColor .. string_sub(sEmptyTextColor, nWidth + 1, new_width), tOldLine[2] .. string_sub(sEmptyTextColor, nWidth + 1, new_width),
backgroundColor = tOldLine.backgroundColor .. string_sub(sEmptyBackgroundColor, nWidth + 1, new_width), tOldLine[3] .. string_sub(sEmptyBackgroundColor, nWidth + 1, new_width),
} }
end end
end end

View File

@ -17,6 +17,8 @@ local error_printer = require "cc.internal.error_printer"
local error_sentinel = {} local error_sentinel = {}
local function make_context(input) local function make_context(input)
expect(1, input, "string")
local context = {} local context = {}
local lines = { 1 } local lines = { 1 }
@ -69,8 +71,9 @@ local function parse(input, start_symbol)
expect(2, start_symbol, "number") expect(2, start_symbol, "number")
local context = make_context(input) local context = make_context(input)
function context.report(msg) function context.report(msg, ...)
expect(1, msg, "table") expect(1, msg, "table", "function")
if type(msg) == "function" then msg = msg(...) end
error_printer(context, msg) error_printer(context, msg)
error(error_sentinel) error(error_sentinel)
end end
@ -106,8 +109,9 @@ local function parse_repl(input)
local context = make_context(input) local context = make_context(input)
local last_error = nil local last_error = nil
function context.report(msg) function context.report(msg, ...)
expect(1, msg, "table") expect(1, msg, "table", "function")
if type(msg) == "function" then msg = msg(...) end
last_error = msg last_error = msg
error(error_sentinel) error(error_sentinel)
end end

View File

@ -92,7 +92,7 @@ local function lex_number(context, str, start)
local contents = sub(str, start, pos - 1) local contents = sub(str, start, pos - 1)
if not tonumber(contents) then if not tonumber(contents) then
-- TODO: Separate error for "2..3"? -- TODO: Separate error for "2..3"?
context.report(errors.malformed_number(start, pos - 1)) context.report(errors.malformed_number, start, pos - 1)
end end
return tokens.NUMBER, pos - 1 return tokens.NUMBER, pos - 1
@ -114,14 +114,14 @@ local function lex_string(context, str, start_pos, quote)
return tokens.STRING, pos return tokens.STRING, pos
elseif c == "\n" or c == "\r" or c == "" then elseif c == "\n" or c == "\r" or c == "" then
-- We don't call newline here, as that's done for the next token. -- We don't call newline here, as that's done for the next token.
context.report(errors.unfinished_string(start_pos, pos, quote)) context.report(errors.unfinished_string, start_pos, pos, quote)
return tokens.STRING, pos - 1 return tokens.STRING, pos - 1
elseif c == "\\" then elseif c == "\\" then
c = sub(str, pos + 1, pos + 1) c = sub(str, pos + 1, pos + 1)
if c == "\n" or c == "\r" then if c == "\n" or c == "\r" then
pos = newline(context, str, pos + 1, c) pos = newline(context, str, pos + 1, c)
elseif c == "" then elseif c == "" then
context.report(errors.unfinished_string_escape(start_pos, pos, quote)) context.report(errors.unfinished_string_escape, start_pos, pos, quote)
return tokens.STRING, pos return tokens.STRING, pos
elseif c == "z" then elseif c == "z" then
pos = pos + 2 pos = pos + 2
@ -129,7 +129,7 @@ local function lex_string(context, str, start_pos, quote)
local next_pos, _, c = find(str, "([%S\r\n])", pos) local next_pos, _, c = find(str, "([%S\r\n])", pos)
if not next_pos then if not next_pos then
context.report(errors.unfinished_string(start_pos, #str, quote)) context.report(errors.unfinished_string, start_pos, #str, quote)
return tokens.STRING, #str return tokens.STRING, #str
end end
@ -192,7 +192,7 @@ local function lex_long_str(context, str, start, len)
elseif c == "[" then elseif c == "[" then
local ok, boundary_pos = lex_long_str_boundary(str, pos + 1, "[") local ok, boundary_pos = lex_long_str_boundary(str, pos + 1, "[")
if ok and boundary_pos - pos == len and len == 1 then if ok and boundary_pos - pos == len and len == 1 then
context.report(errors.nested_long_str(pos, boundary_pos)) context.report(errors.nested_long_str, pos, boundary_pos)
end end
pos = boundary_pos pos = boundary_pos
@ -234,12 +234,12 @@ local function lex_token(context, str, pos)
local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - pos) local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - pos)
if end_pos then return tokens.STRING, end_pos end if end_pos then return tokens.STRING, end_pos end
context.report(errors.unfinished_long_string(pos, boundary_pos, boundary_pos - pos)) context.report(errors.unfinished_long_string, pos, boundary_pos, boundary_pos - pos)
return tokens.ERROR, #str return tokens.ERROR, #str
elseif pos + 1 == boundary_pos then -- Just a "[" elseif pos + 1 == boundary_pos then -- Just a "["
return tokens.OSQUARE, pos return tokens.OSQUARE, pos
else -- Malformed long string, for instance "[=" else -- Malformed long string, for instance "[="
context.report(errors.malformed_long_string(pos, boundary_pos, boundary_pos - pos)) context.report(errors.malformed_long_string, pos, boundary_pos, boundary_pos - pos)
return tokens.ERROR, boundary_pos return tokens.ERROR, boundary_pos
end end
@ -256,7 +256,7 @@ local function lex_token(context, str, pos)
local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - comment_pos) local end_pos = lex_long_str(context, str, boundary_pos + 1, boundary_pos - comment_pos)
if end_pos then return tokens.COMMENT, end_pos end if end_pos then return tokens.COMMENT, end_pos end
context.report(errors.unfinished_long_comment(pos, boundary_pos, boundary_pos - comment_pos)) context.report(errors.unfinished_long_comment, pos, boundary_pos, boundary_pos - comment_pos)
return tokens.ERROR, #str return tokens.ERROR, #str
end end
end end
@ -313,18 +313,18 @@ local function lex_token(context, str, pos)
if end_pos - pos <= 3 then if end_pos - pos <= 3 then
local contents = sub(str, pos, end_pos) local contents = sub(str, pos, end_pos)
if contents == "&&" then if contents == "&&" then
context.report(errors.wrong_and(pos, end_pos)) context.report(errors.wrong_and, pos, end_pos)
return tokens.AND, end_pos return tokens.AND, end_pos
elseif contents == "||" then elseif contents == "||" then
context.report(errors.wrong_or(pos, end_pos)) context.report(errors.wrong_or, pos, end_pos)
return tokens.OR, end_pos return tokens.OR, end_pos
elseif contents == "!=" or contents == "<>" then elseif contents == "!=" or contents == "<>" then
context.report(errors.wrong_ne(pos, end_pos)) context.report(errors.wrong_ne, pos, end_pos)
return tokens.NE, end_pos return tokens.NE, end_pos
end end
end end
context.report(errors.unexpected_character(pos)) context.report(errors.unexpected_character, pos)
return tokens.ERROR, end_pos return tokens.ERROR, end_pos
end end
end end

View File

@ -240,7 +240,7 @@ local function handle_error(context, stack, stack_n, token, token_start, token_e
end end
end end
context.report(errors.unexpected_token(token, token_start, token_end)) context.report(errors.unexpected_token, token, token_start, token_end)
return false return false
end end

View File

@ -107,7 +107,9 @@ local function set_status(text, ok)
status_text = text status_text = text
end end
if not bReadOnly and fs.getFreeSpace(sPath) < 1024 then if bReadOnly then
set_status("File is read only", false)
elseif fs.getFreeSpace(sPath) < 1024 then
set_status("Disk is low on space", false) set_status("Disk is low on space", false)
else else
local message local message

View File

@ -27,7 +27,7 @@ local function pcm_decoder(chunk)
end end
local function report_invalid_format(format) local function report_invalid_format(format)
printError(("The speaker cannot play %s files."):format(format)) printError(("speaker cannot play %s files."):format(format))
local pp = require "cc.pretty" local pp = require "cc.pretty"
pp.print("Run '" .. pp.text("help speaker", colours.lightGrey) .. "' for information on supported formats.") pp.print("Run '" .. pp.text("help speaker", colours.lightGrey) .. "' for information on supported formats.")
end end
@ -103,6 +103,7 @@ elseif cmd == "play" then
elseif start == "OggS" then return report_invalid_format("Ogg") elseif start == "OggS" then return report_invalid_format("Ogg")
elseif start == "fLaC" then return report_invalid_format("FLAC") elseif start == "fLaC" then return report_invalid_format("FLAC")
elseif start:sub(1, 3) == "ID3" then return report_invalid_format("MP3") elseif start:sub(1, 3) == "ID3" then return report_invalid_format("MP3")
elseif start == "<!DO" --[[<!DOCTYPE]] then return report_invalid_format("HTML")
end end
print("Playing " .. file) print("Playing " .. file)

View File

@ -21,21 +21,13 @@ local tEnv = {
} }
setmetatable(tEnv, { __index = _ENV }) setmetatable(tEnv, { __index = _ENV })
-- Replace our package.path, so that it loads from the current directory, rather -- Replace our require with new instance that loads from the current directory
-- than from /rom/programs. This makes it a little more friendly to use and -- rather than from /rom/programs. This makes it more friendly to use and closer
-- closer to what you'd expect. -- to what you'd expect.
do do
local make_package = require "cc.require".make
local dir = shell.dir() local dir = shell.dir()
if dir:sub(1, 1) ~= "/" then dir = "/" .. dir end _ENV.require, _ENV.package = make_package(_ENV, dir)
if dir:sub(-1) ~= "/" then dir = dir .. "/" end
local strip_path = "?;?.lua;?/init.lua;"
local path = package.path
if path:sub(1, #strip_path) == strip_path then
path = path:sub(#strip_path + 1)
end
package.path = dir .. "?;" .. dir .. "?.lua;" .. dir .. "?/init.lua;" .. path
end end
if term.isColour() then if term.isColour() then
@ -78,18 +70,13 @@ while running do
local name, offset = "=lua[" .. chunk_idx .. "]", 0 local name, offset = "=lua[" .. chunk_idx .. "]", 0
local force_print = 0
local func, err = load(input, name, "t", tEnv) local func, err = load(input, name, "t", tEnv)
if load("return " .. input) then
local expr_func = load("return _echo(" .. input .. ");", name, "t", tEnv) -- We wrap the expression with a call to _echo(...), which prevents tail
if not func then -- calls (and thus confusing errors). Note we check this is a valid
if expr_func then -- expression separately, to avoid accepting inputs like `)--` (which are
func = expr_func -- parsed as `_echo()--)`.
offset = 13 func = load("return _echo(" .. input .. "\n)", name, "t", tEnv)
force_print = 1
end
elseif expr_func then
func = expr_func
offset = 13 offset = 13
end end
@ -99,9 +86,8 @@ while running do
local results = table.pack(exception.try(func)) local results = table.pack(exception.try(func))
if results[1] then if results[1] then
local n = 1 for i = 2, results.n do
while n < results.n or n <= force_print do local value = results[i]
local value = results[n + 1]
local ok, serialised = pcall(pretty.pretty, value, { local ok, serialised = pcall(pretty.pretty, value, {
function_args = settings.get("lua.function_args"), function_args = settings.get("lua.function_args"),
function_source = settings.get("lua.function_source"), function_source = settings.get("lua.function_source"),
@ -111,7 +97,6 @@ while running do
else else
print(tostring(value)) print(tostring(value))
end end
n = n + 1
end end
else else
printError(results[2]) printError(results[2])

View File

@ -45,8 +45,9 @@ local function capture_parser(input, print_tokens, start)
end end
local context = make_context(input) local context = make_context(input)
function context.report(message) function context.report(message, ...)
expect(3, message, "table") expect(3, message, "table", "function")
if type(message) == "function" then message = message(...) end
for _, msg in ipairs(message) do for _, msg in ipairs(message) do
if type(msg) == "table" and msg.tag == "annotate" then if type(msg) == "table" and msg.tag == "annotate" then