See - Standard Execution Environment
#61
Posted 18 February 2014 - 10:25 PM
Things coming up: Doc gen by sci4me, and a networking library with routing I'm working on. Just wrote the peer discovery code tonight. Loads of fun so far!
Later, more weegui stuff. And bugfixes. Lots of those.
#62
Posted 20 February 2014 - 08:53 PM
To be clear, I'd want to be able to do things like this:
System.print(MyClass) --> Prints using toString method from see.rt.Class System.print(typeof(MyClass)) --> Prints see.rt.Class System.print(MyClass:getClass()) --> ^ ArgumentUtils.check(1, someClass, Class) --> True if someClass is a class.
Turns out there are tons of problems with having classes as first-class objects. You can't just set the metatable of the class to index Class, because then instances of the class will have access to Class methods. Additionally, Class is a class, so Class would have a metatable which indexes itself. (Yeah, I know that's confusing.)
The solution is to set a metatable for the class in which new indices are put in a helper table and index access is handled by a function which checks whether the table is a class or not and acts accordingly. If the table is a class, the system tries to get the field from Class and then Object. If the table is not a class, the system just loops upwards in the super class hierarchy until a matching field is found. With this system, we can call methods from normal objects and from classes, and the underlying system sorts out all the kinks for us!
There's still a small problem, though. Consider the following code which uses the current class model:
function MyClass:init(x)
MySuperClass.init(self, x, "hi")
end
function MyClass:doStuff(x, y)
MySuperClass.doStuff(self, x, y)
print("I told the super class to do some stuff.")
end
This is currently the way of calling super methods and super constructors. This is broken with the new class model, because indexing the class itself doesn't access the class, it accesses Class and then maybe Object. Luckily, I didn't like this syntax much anyways and I think the new syntax is a bit prettier.
function MyClass:init(x)
self:super(MySuperClass):init(x, "hi")
end
function MyClass:doStuff(x, y)
self:super(MySuperClass):doStuff(x, y)
print("I told the super class to do some stuff.")
end
Metatable magic is involved in this, and it can break and do weird stuff if you use it incorrectly, so I'm thinking of trying something else. For example, if you just call self:super without calling a method on it, self is just left there with a different metatable, which will index that super class you gave it the next time you try to use it.
But other than that, I think it looks nicer than the old way.
Here's some test code I was working with to see if this stuff was even possible (you can run it right inside the standard Lua interpreter if you want):
local Object = { name = "Object", __table = { } }
local Class = { name = "Class", __table = { }, __super = Object }
local MyClass = { name = "MyClass", __table = { }, __super = Object }
local MySubClass = { name = "MySubClass", __table = { }, __super = MyClass }
local classes = { [Object] = true, [Class] = true, [MyClass] = true, [MySubClass] = true }
local function newindex(t, k, v)
--print(k)
t.__table[k] = v
end
local function index(t, k)
-- Class access.
if classes[t] then
local v = rawget(Class, "__table")[k]
if v then
return v
end
v = rawget(Object, "__table")[k]
return v
end
-- Instance access.
local class = rawget(t, "__class")
repeat
local v = rawget(class, "__table")[k]
if v then
return v
end
class = rawget(class, "__super")
until not class
end
local mt = { __index = index, __newindex = newindex }
setmetatable(Object, mt)
setmetatable(Class, mt)
setmetatable(MyClass, mt)
setmetatable(MySubClass, mt)
function Object:toString()
return tostring(self):sub(8, -1)
end
function Object:super(class)
local mt = getmetatable(self)
return setmetatable(self, { __index = function(t, k, v)
local ret = rawget(class, "__table")[k]
setmetatable(t, mt)
return ret
end })
end
function Class:new(...)
local instance = setmetatable({ __class = self }, { __index = mt.__index })
instance:init(...)
return instance
end
function Class:toString()
return self.name
end
function MyClass:init()
print("hi")
self.x = 1337
end
function MyClass:myMethod()
return self.x + 1
end
function MyClass:toString()
return tostring(self.x)
end
function MySubClass:init()
self:super(MyClass):init()
self.x = self.x * 3
end
local myInstance = MyClass:new()
local myOtherInstance = MySubClass:new()
print(myInstance:myMethod())
print(myInstance:toString())
print(MyClass:toString())
print(myOtherInstance.x)
Note the Object:super method. It's a bit derp.
tl;dr: I get sidetracked really easily.
Edited by Yevano, 20 February 2014 - 09:10 PM.
#63
Posted 05 March 2014 - 05:00 PM
#64
Posted 05 March 2014 - 09:13 PM
LuaCrawler, on 05 March 2014 - 05:00 PM, said:
Right now the only documentation is that written in the code and the OP.
The standard library works pretty well as an example for proper usage, so I would look at that. I'm also on my TeamSpeak server and don't mind helping directly if you have specific questions.
Edited by Yevano, 05 March 2014 - 09:13 PM.
#65
Posted 10 March 2014 - 05:16 AM
LuaCrawler, on 05 March 2014 - 05:00 PM, said:
I am considering writing some tutorials. If I decide to write them, it will be some time this week probably.. I want to wait until we merge better-classes into master. Speaking of,
we have made a ton of progress on the better-classes stuff. Yevano did most of it, but I did fix some bugs.
I also plan to create some libraries for SEE (github, json, etc.)
Edited by sci4me, 10 March 2014 - 05:18 AM.
#66
Posted 10 March 2014 - 02:15 PM
Yevano, on 05 March 2014 - 09:13 PM, said:
LuaCrawler, on 05 March 2014 - 05:00 PM, said:
Right now the only documentation is that written in the code and the OP.
The standard library works pretty well as an example for proper usage, so I would look at that. I'm also on my TeamSpeak server and don't mind helping directly if you have specific questions.
#67
Posted 10 March 2014 - 08:31 PM
The command should look something like:
see -r program_folder MainClass
#68
Posted 15 March 2014 - 10:13 PM
http://www.computerc...524-see-basics/
Edited by sci4me, 16 March 2014 - 01:31 AM.
#69
Posted 16 March 2014 - 02:27 AM
#70
Posted 17 March 2014 - 02:27 AM
- Added the "abstract" annotation for "abstract" functions
- Fixed 2 issues (Added Timers, Changed Events.pull to use see.event.Event classes instead of strings)
- Added support for multiple classpaths (!!!!)
More testing and tweaking is needed before a merge, but I hope to merge some within the next week or so.
Once we merge I will update my tutorial.
EDIT:
I have now implemented ClassLoaders as well.
How SEE starts up:
- load see.base.Object and see.rt.Class with a dummy class loader function
- load a DefaultClassLoader to load other classes
- load a few other classes
- load a FileClassLoader and ArchiveClassLoader
[email protected] see.rt.HTTPClassLoader [email protected] see.net.URL function Test.main() local classLoader = HTTPClassLoader:new() local TestClass = classLoader:loadClass(URL:new("https://gist.githubusercontent.com/sci4me/9632239/raw/ce4cf1c93236258c8d8209f4f0db487e16171b49/gistfile1.txt"), "TestClass") local testClassInstance = TestClass:new() System.print(testClassInstance) TestClass.staticFunction() end
Not too shabby?
FYI we have merged these changes. Oh, I also forgot to say that you now pass a class into Events.pull not a string. KeyPressEvent instead of "key"
Edited by sci4me, 21 March 2014 - 07:24 PM.
#71
Posted 22 March 2014 - 10:03 AM
I've got one question. I can't seem to beable to loop through Peripheral.getNames (it does work when I make a non SEE file and use the regular 'peripheral.getNames'). I'm probably overlooking something here though.
This is the code:
And this is the output:
#72
Posted 22 March 2014 - 05:00 PM
Remi1115, on 22 March 2014 - 10:03 AM, said:
I've got one question. I can't seem to beable to loop through Peripheral.getNames (it does work when I make a non SEE file and use the regular 'peripheral.getNames'). I'm probably overlooking something here though.
This is the code:
And this is the output:
You are trying to use pairs. If you want to use pairs, you should [email protected] import it. HOWEVER, DO NOT DO THIS. Peripheral.getNames returns a see.base.Array
Use :iAll
[email protected] see.io.Peripheral function St00f.main() local names = Peripheral.getNames() for name in names:iAll() do System.print(name) end end
Also, name is a see.base.String not a lua string... just so you know. Check out the classes in the standard library: https://github.com/Y.../master/see/lib
See the see.io.peripheral package
No need for it, but if you have a reason to use pairs you would do this:
[email protected] pairs
Hope this helps!
EDIT:
The see.base.Iterators class contains a wrapper for pairs and ipairs. Use it instead of [email protected] pairs/ipairs.
Edited by sci4me, 22 March 2014 - 05:22 PM.
#73
Posted 23 March 2014 - 10:35 AM
sci4me, on 22 March 2014 - 05:00 PM, said:
Thanks for the help! It worked. I knew about the library on GitHub though, my bad that I didn't look what getNames returns.
Peripheral.getNames:iAll doesn't return them as a key->value pair, does it? When I iterate through it I for example get "back(linebreak)monitor". Not a problem though, but just something to keep in mind (for me).
By the way, is 'String:new("test")' the correct way to create/instantiate a new String?
#74
Posted 23 March 2014 - 07:13 PM
Remi1115, on 23 March 2014 - 10:35 AM, said:
sci4me, on 22 March 2014 - 05:00 PM, said:
Thanks for the help! It worked. I knew about the library on GitHub though, my bad that I didn't look what getNames returns.
Peripheral.getNames:iAll doesn't return them as a key->value pair, does it? When I iterate through it I for example get "back(linebreak)monitor". Not a problem though, but just something to keep in mind (for me).
By the way, is 'String:new("test")' the correct way to create/instantiate a new String?
Peripheral.getNames returns an array (number indexed) of the names. Should ... er.. maybe thats because of the native peripheral.getnames.. idk
Yes but a shortcut is STR("") or STR""
and just so you know :lstr() on a String will give a native lua string.
#75
Posted 25 March 2014 - 05:45 PM
sci4me, on 23 March 2014 - 07:13 PM, said:
Yes but a shortcut is STR("") or STR""
and just so you know :lstr() on a String will give a native lua string.
#76
Posted 25 March 2014 - 07:14 PM
Remi1115, on 25 March 2014 - 05:45 PM, said:
sci4me, on 23 March 2014 - 07:13 PM, said:
Yes but a shortcut is STR("") or STR""
and just so you know :lstr() on a String will give a native lua string.
No problem. Feel free to ask me or Yevano any more questions (although I guarantee it will take him longer to answer). Message me if you want too.
#77
Posted 20 April 2014 - 06:19 PM
Error:
see:190: see.event.Events:91: table index expected, got nil
It doesn't seem it's my problem, my code is:
function HelloWorld.main(args)
System.print("Hello World!")
end
Directory Structure:
hw
ardera
hw
HelloWorld
Edited by ardera, 20 April 2014 - 07:08 PM.
#78
Posted 21 April 2014 - 08:23 PM
Edit: Made a small script to generate the files to download for me. Both the pastebin script and file on github have been updated. Just download 4RgrdVgE again and run it.
Edited by Yevano, 21 April 2014 - 08:41 PM.
#79
Posted 05 May 2014 - 02:19 PM
Just one thing I found bug (or problem) I found when messing around with it: When you override the toString method, you have to return a String object, rather than the default Lua string. Otherwise you get an error. I think this is caused by see\bin\see (line 138): return value:toString():lstr(). I don't know if this is intentional but my 'fix' is:
local str = value:toString() if type(str) == "string" then return str end return str:lstr()
Otherwise this is such a great resource. Several things I would like to be seen in the future:
Proper event manager: This would be mainly for GUIs.Ignore me. I just read through your WeeGUI code and you already have that implimented but it would be nice to see this in the core SEE libary.- Sandboxing: I figure that if SEE has direct control over APIs then you could limit access to particular APIs. For instance ban access to websites or force a program to only run in one folder. This would be useful not only for untrusted code (not that there is much on CC) but also for debugging - you wouldn't be able to muck up the current file structure.
- Extensions to the current APIs: At the moment the SEE APIs (Rednet, Peripheral, etc...) simply replicate the built in APIs. It would be great if some new features could be added. This might include, for example, in the Rednet API one could make the side parameter for isOpen, open and close optional.
Edited by SquidDev, 05 May 2014 - 06:36 PM.
#80
Posted 07 May 2014 - 04:36 PM
I was playing around with the SEE Rednet API and I don't think it works. I am aware of the ModemInputStream and ModemOutputStream APIs but they are not as effective as the original Rednet API as they don't provide all functionality. I know I could just pull RendetMessageEvent (but you warn us against it) or ModemMessageEvent but this still does not give me the ability to use functions such as lookup.
I think the only bit of Rednet that does not work is receiving (so rednet.receive and rednet.lookup). I think what happens is that the "rednet_message" event is never found (as it is gobbled up by the /apis/see and queued internally instead). As a result neither of these two functions return.
This 'event gobbling' bug also affects other core functionality such as read (and System.read).
Short of re-creating the entire Rednet API I can't find a decent solution.
Sorry to sound so negative, everything else works perfectly.
Edited by SquidDev, 07 May 2014 - 04:36 PM.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users











