Skip to content
Permalink
Browse files
Added exception handling. Fixed some problems with casting. Added STR…
… global function for converting a Lua string to see.base.String.
  • Loading branch information
James King committed Aug 5, 2013
1 parent 87489ab commit 48372af
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 60 deletions.
@@ -1,4 +1,4 @@
see
===

An API, library, and runtime environment all in on for ComputerCraft.
An object oriented environment for ComputerCraft.
@@ -10,6 +10,7 @@ StandardGlobals = { }

--[[
Creates a new anonymous class.
@param SeeVM:vm The VM to run this function for.
@param function:def The function used to define this class.
@param table:super The super class for this class. If nil, this class extends see.lang.Object.
]]
@@ -19,6 +20,7 @@ end

--[[
Gets the type of a given value.
@param SeeVM:vm The VM to run this function for.
@param value:any The value to get the type of.
@return string|table The type identifier if value if primitive, or the class of value if value is an object.
]]
@@ -31,6 +33,7 @@ end

--[[
Casts a value to a particular class.
@param SeeVM:vm The VM to run this function for.
@param any:value The value to cast.
@param string|table:castType The type to cast to.
]]
@@ -45,26 +48,59 @@ function StandardGlobals.cast(vm, value, castType)
if type(value) ~= "table" or not value.__type then
return tostring(value)
elseif value.__type then
return value.__type.__cast(value)
return value:toString():lstr()
end
else
-- TODO
end
else
return castType.__cast(value)
-- Casting to Object.
-- TODO
end
end

--[[
Casts an object to a different class by setting its metatable.
@param SeeVM:vm The VM to run this function for.
@param see.base.Object value
]]
function StandardGlobals.reinterpret_cast(value, castType)
function StandardGlobals.reinterpret_cast(vm, value, castType)
if type(value) ~= "table" or not value.__type then error("Cannot use reinterpret_cast to cast a primitive type.") end
setmetatable(value, castType.__meta)
end

--[[
Throws an exception.
@param SeeVM:vm The VM to run this function for.
@param see.base.Exception The exception to throw.
]]
function StandardGlobals.throw(vm, exception)
vm.lastException = exception
error()
end

--[[
Tries to execute code until an error occurs. Calls catch code if an error occurs.
@param SeeVM:vm The VM to run this function for.
@param function:tryFunc Function to run and catch errors from.
@param function:catchFunc(see.base.Exception) Function to run on error.
]]
function StandardGlobals.try(vm, tryFunc, catchFunc)
local suc, err = pcall(tryFunc)
if suc then return end
if err then vm.lastException = vm:loadClassFromAny("see.rt.RuntimeException").new(err) end
catchFunc(vm.lastException)
end

--[[
Converts a Lua string to a see.base.String.
@param string:str
]]
function StandardGlobals.STR(vm, str)
return vm.base.String.new(str)
end

SeeVM = { }
SeeVM.__index = SeeVM

@@ -73,6 +109,8 @@ SeeVM.__index = SeeVM
]]
function SeeVM.new(natives)
local self = { }
setmetatable(self, SeeVM)

self.standardGlobals = { }
for k, v in pairs(StandardGlobals) do
self.standardGlobals[k] = function(...) return StandardGlobals[k](self, ...) end
@@ -82,8 +120,8 @@ function SeeVM.new(natives)
self.classes = { }
self.natives = natives
self.classPaths = { }
setmetatable(self, SeeVM)
self.base.Object = self:loadClassFromAny("see.base.Object")
self.base.Exception = self:loadClassFromAny("see.base.Exception")
self.base.System = self:loadClassFromAny("see.base.System")
self.base.Array = self:loadClassFromAny("see.base.Array")
self.base.String = self:loadClassFromAny("see.base.String")
@@ -101,7 +139,6 @@ function getByPackage(t, package, del)
if not del then del = "%." end
local f = package:find(del)
if f then
print(package .. " contains " .. del)
return getByPackage(t[package:sub(1, f - 1)], package:sub(f + 1), del)
else
return t[package]
@@ -265,6 +302,7 @@ function SeeVM:loadClass(def, annotations, name)
class.__name = name

function class.new(...)
if not class.init then error("Could not instantiate class " .. name .. ". No init method.") end
local self = { }
self.__type = class
setmetatable(self, class.__meta)
@@ -274,7 +312,7 @@ function SeeVM:loadClass(def, annotations, name)

-- Extend Object by default.
if abool then
setmetatable(class, self.base.Object.__meta)
setmetatable(class, self.base.Object)
end

-- Import base classes.
@@ -0,0 +1,10 @@
--@import see.base.String

--[[
Constructs a new Exception.
@param string:message The error message.
]]
function Exception:init(message)
message = cast(message, String)
self.message = message
end
@@ -2,6 +2,7 @@
--@native pairs
--@native setmetatable
--@native getmetatable
--@import see.base.String

--[[
The super class for all classes loaded in the See Runtime.
@@ -29,5 +30,10 @@ function Object:getClass()
end

function Object:toString()
return tostring(self) .. ":" .. self:getClass().__name
return String.new(tostring(self) .. ":" .. self:getClass().__name)
end

-- TODO: Fix me.
function Object.__concat(l, r)
return cast(l, String):concat(cast(r, String))
end
@@ -1,4 +1,7 @@
--@native string
--@native tostring
--@import see.base.Array
--@import see.base.System

--[[
A mutable, Array-backed string. Faster and more memory efficient than native strings.
@@ -17,14 +20,20 @@ function String.__cast(value)
end

--[[
Constructs a new String which copies the given luaString.
@param string:luaString The string to be copied.
Constructs a new String which copies the given string.
@param string:str The string to be copied.
]]
function String:init(luaString)
function String:init(str)
self.charArray = Array.new()
if not luaString then return end
for i = 1, #luaString do
self.charArray[i] = luaString:sub(i, i):byte()
if not str then return end
if typeof(str) == "string" then
for i = 1, #str do
self.charArray[i] = str:sub(i, i):byte()
end
elseif typeof(str) == String then
for i = 1, str:length() do
self.charArray[i] = str.charArray[i]
end
end
end

@@ -48,12 +57,31 @@ function String:length()
return self.charArray.length
end

function String:concat(str)
local ret = String.new(self)
local len = self:length()
for i = 1, str:length() do
ret.charArray[i + len] = str.charArray[i]
end
return ret
end

function String.__meta.__concat(a, b)
return a:concat(b)
end

--[[
Gets a substring of this String.
@param number:a Start index.
@param number:b End index. Defaults to the length of this String.
@return see.base.String A substring of this String.
]]
function String:sub(a, b)

if not b then b = self:length() end

-- TODO
end

function String:toString()
return self
end
@@ -1,5 +1,6 @@
--@native print
--@native read
--@native unpack

--[[
A utility class for useful system operations.
@@ -20,11 +21,12 @@ end
function System.print(...)
local args = {...}
for i = 1, #args do
args[i] = cast(str, "string")
args[i] = cast(args[i], "string")
end
print(...)
print(unpack(args))
end

-- TODO: Prevent from trashing global namespace.
function System.loadNativeAPI(path)
os.loadAPI()
end
@@ -0,0 +1,10 @@
--@extends see.base.Exception

--[[
Constructs a new RuntimeException.
@param string:message The error message.
]]
function RuntimeException:init(message)
message = cast(message, String)
Exception.init(self, message)
end
@@ -0,0 +1,11 @@
function Math.sin(x)
-- body
end

function Math.cos(x)
-- body
end

function Math.tan( ... )
-- body
end
@@ -13,24 +13,6 @@ local _, err = pcall(function(...)

os.loadAPI("/see/apis/see")

local function loadClassesFromPath(path)
for _, name in pairs(fs.list(path)) do
local subPath = fs.combine(path, name)
if fs.isDir(subPath) then
loadClassesFromPath(subPath)
else
if name:sub(-4, -1) == ".lua" then
local relativePath = subPath:sub(#classPath + 2)
local class, err = vm:loadClassFromFile(subPath, relativePath:gsub("/", "."):sub(1, -5))

if not class then
print("Error loading class '" .. name .. "': " .. tostring(err))
end
end
end
end
end

local function runFromPath(classPath, mainClassName, args)
local MainClass = vm:loadClassFromAny(mainClassName)
if not MainClass then error("Main class not found! ") end
@@ -0,0 +1,8 @@
function Test.main(args)
try (function()
System.print("Running some error-prone code...")
notarealfunction()
end, function(e)
System.print(STR"There was an exception! " .. e.message)
end)
end

0 comments on commit 48372af

Please sign in to comment.