Skip to content
Permalink
Browse files
Added tracebacks for exceptions and Lua errors. Added more methods to…
… see.base.String. Added see.rt.IndexOutOfBoundsException.
  • Loading branch information
James King committed Aug 9, 2013
1 parent e724673 commit 37f4a5e
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 1,473 deletions.
@@ -1,3 +1,61 @@
function traceback(err, level, b)
local errors = { }
local ok, err
local j = level or 2
while j < 256 do
j = j + 1
ok, err = pcall(_G.error, '', j)
local name = err:match("^[^:]+")
if not b and name == "bios" or name == "see" then break end
table.insert(errors, err)
end

return errors
end

function formatTraceback(err, errors, level)
if not err then err = "" end
local f = "Error: " .. err
local j = 1
for _, err in pairs(errors) do
if j == level then
f = f .. "\n... and " .. (#errors - level) .. " more."
break
end

local ls = err:find(":")
if ls then ls = ls + 1 end
local le = err:find(":", ls)
if le then le = le - 1 end
local line = ls and le and err:sub(ls, le)
local location = ls and err:sub(1, ls - 2) or err
f = f .. "\n@ line " .. (le and line or "?") .. " in " .. location
j = j + 1
end
return f
end

local function error(err, level)
if term.isColor() then
term.setTextColor(colors.red)
end
print(formatTraceback(err, traceback(err, level, b), 10))
if term.isColor() then
term.setTextColor(colors.white)
end
_G.error()
end

function errorHandler(err)
if term.isColor() then
term.setTextColor(colors.red)
end
print(see.formatTraceback(err, see.traceback(err, 3, true), 10))
if term.isColor() then
term.setTextColor(colors.white)
end
end

local function copy(t)
local r = { }
for k, v in pairs(t) do
@@ -85,7 +143,7 @@ function StandardGlobals.throw(vm, exception)
else
vm.lastException = vm:loadClassFromAny("see.rt.RuntimeException").new("Invalid argument to throw.")
end
error()
error("Uncaught exception " .. exception.__type.__name .. ': "' .. exception.message:lstr() .. '"', 4, true)
end

--[[
@@ -129,6 +187,7 @@ function SeeVM.new(natives, seePath)
self.rt = { }
self.classes = { }
self.natives = natives
self.natives.error = error
self.classPaths = { }
self.base.Object = self:loadClassFromAny("see.base.Object")
self.rt = self:loadClassFromAny("see.rt.Class")
@@ -210,15 +269,20 @@ function SeeVM:loadClassFromAny(name)
-- Load from the standard library.
local p = name:gsub("%.", "/")
class, err = self:loadClassFromFile(fs.combine(fs.combine(self.seePath, "/lib/"), p) .. ".lua", name)
local lerr = err

if class then return class end

-- Load from custom class paths
for _, classPath in pairs(self.classPaths) do
class = self:loadClassFromFile(fs.combine(classPath, name:gsub("%.", "/") .. ".lua"), name)
class, err = self:loadClassFromFile(fs.combine(classPath, name:gsub("%.", "/") .. ".lua"), name)
if class then return class end
end

if not lerr:find("Could not read file.") then
err = lerr
end

if not class then
error("Could not load class " .. name .. ". " .. err)
end
@@ -1,8 +1,12 @@
--@native table.remove
--@native table.insert
--@native rawget
--@native rawset
--@native tostring

--@import see.rt.IndexOutOfBoundsException
--@import see.base.System

--[[
A table-backed, infinite array.
]]
@@ -47,9 +51,10 @@ function Array:get(index)
if index < 0 then
index = self.length + index + 1
end
if index <= self.length + 1 and index > 0 then
if index <= self.length and index > 0 then
return self.luaArray[index]
end
throw(IndexOutOfBoundsException.new(index))
end

--[[
@@ -67,7 +72,9 @@ function Array:set(index, value)
self.length = self.length + 1
end
self.luaArray[index] = value
return
end
throw(IndexOutOfBoundsException.new(index))
end

--[[
@@ -85,10 +92,26 @@ end
@return any The value at the removed index.
]]
function Array:remove(index)
if index < 0 then
index = self.length + index + 1
end
if index <= self.length and index > 0 then
return table.remove(self.luaArray, index)
end
throw(IndexOutOfBoundsException.new(index))
end

--[[
Inserts a value into this Array at the given index, sliding elements forward if needed.
@param number:index The index to insert at.
@param any:value The value to insert.
]]
function Array:insert(index, value)
if index < 0 then
index = self.length + index + 1
end
if index <= self.length + 1 and index > 0 then
return table.remove(self.luaArray, index)
end
throw(IndexOutOfBoundsException.new(index))
end
@@ -14,6 +14,7 @@
--[[
Casts a value to a String.
@param any:value The value to be casted.
@return see.base.String The casted value.
]]
function String.__cast(value)
local type = typeof(value)
@@ -31,6 +32,15 @@ function String.__cast(value)
return ret
end

--[[
Converts a byte to a single-char String.
@param number:byte The byte to convert.
@return see.base.String A string representation of the given byte.
]]
function String.char(byte)
return String.new(string.char(byte))
end

--[[
Constructs a new String which copies the given string.
@param strings:str... The strings to be copied.
@@ -48,7 +58,7 @@ function String:init(...)
end
elseif typeof(str) == String then
for i = 1, str:length() do
self.charArray:add(str.charArray[i])
self.charArray:add(str[i])
end
end
end
@@ -81,7 +91,7 @@ end
function String:lstr()
local str = ""
for i = 1, self.charArray.length do
str = str .. string.char(self.charArray[i])
str = str .. string.char(self[i])
end
return str
end
@@ -100,7 +110,7 @@ function String.concat(a, b)
local ret = String.new(a)
local len = a:length()
for i = 1, b:length() do
ret.charArray[i + len] = b.charArray[i]
ret[i + len] = b[i]
end
return ret
end
@@ -117,8 +127,68 @@ end
]]
function String:sub(a, b)
if not b then b = self:length() end
ArgumentUtils.check(1, a, "number")
ArgumentUtils.check(2, b, "number")

if a > b then
local c = b
b = a
a = c
end

local substring = String.new()
for i = a, b do
substring[i - a + 1] = self[i]
end
return substring
end

--[[
Finds a given substring in this string.
@param see.base.String:str The string to search for.
@param number:init The index to start searching from. Defaults to 1.
@return number The index that the substring occurs.
]]
function String:find(str, init)
local t = typeof(str)
str = cast(str, String)
if not init then init = 1 end
ArgumentUtils.check(2, init, "number")

local j = 1
for i = init, self:length() do
if self[i] == str[j] then
if j == str:length() then
return i - j + 1
end
j = j + 1
else
j = 1
end
end
end

-- TODO: Reimplement as non-native solution.
--[[
Formats this String using the native string.format.
@param native:values... The values to pass to string.format.
@return see.base.String The formatted string.
]]
function String:format(...)
return String.new(self:lstr():format(...))
end

--[[
Replaces all instances of str with rep.
@param see.base.String:str The string to be replaced.
@param see.base.String:rep The string to replace with.
]]
function String:replace(str, rep)
local found = self:find(str)
while found do

found = self:find(str)
end
end

function String:toString()
@@ -0,0 +1,7 @@
--@import see.rt.RuntimeException
--@import see.base.String
--@extends see.rt.RuntimeException

function IndexOutOfBoundsException:init(index)
RuntimeException.init(self, String.new("Index: " .. index))
end
@@ -4,7 +4,7 @@

function InvalidArgumentException:init(n, expected, got)
if not isprimitive(expected) then
expected = exepected:getName()
expected = expected.__name
end
if not isprimitive(got) then
got = got:getName()
@@ -21,6 +21,7 @@ local DL_PATHS = {
"lib/see/base/System.lua",
"lib/see/concurrent/Thread.lua",
"lib/see/rt/Class.lua",
"lib/see/rt/IndexOutOfBoundsException.lua",
"lib/see/rt/InvalidArgumentException.lua",
"lib/see/rt/RuntimeException.lua",
"lib/see/util/ArgumentUtils.lua",
@@ -17,10 +17,10 @@ local _, err = pcall(function(...)
local MainClass = vm:loadClassFromAny(mainClassName)
if not MainClass then error("Main class not found! ") end
if not MainClass.main then error("Main method not found!") end
MainClass.main(args)
xpcall(function() MainClass.main(args) end, see.errorHandler)
end

local USAGE = "Usage: see <-r <seePath> <classPath> <mainClass> <args>>|<-p <dir>>|<-u <archive>>|<-help>"
local USAGE = "Usage: see <-r <seePath> <classPath> <mainClass> <args>>|<-help>"
local args = {...}
local op = args[1]

@@ -44,12 +44,6 @@ local _, err = pcall(function(...)
else
-- TODO: Add archive reading.
end
elseif op == "-p" then
-- Pack option.
-- TODO
elseif op == "-u" then
-- Unpack option.
-- TODO
elseif op == "-help" then
-- Help option.
print(USAGE)

This file was deleted.

0 comments on commit 37f4a5e

Please sign in to comment.