Jump to content




See - Standard Execution Environment


  • You cannot reply to this topic
99 replies to this topic

#61 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 18 February 2014 - 10:25 PM

One day I'll have to take the time to see if SEE would realistically work as a compatibility layer for CC/OC.

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 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 20 February 2014 - 08:53 PM

So... I started working on the routing library some more, but I couldn't help but notice how Event.pull still uses strings as filters. We have an object-oriented system, so I figure it makes more sense to use classes as filters. When I was about to implement that, I realized the type checking for classes would be a bit weird, since they aren't really considered regular objects.

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 TechMasterGeneral

  • Members
  • 149 posts
  • LocationUnited States

Posted 05 March 2014 - 05:00 PM

i soooo want to try this out... but i can't figure out how to program with it... is there any documentation?

#64 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 05 March 2014 - 09:13 PM

View PostLuaCrawler, on 05 March 2014 - 05:00 PM, said:

i soooo want to try this out... but i can't figure out how to program with it... is there any documentation?

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 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 10 March 2014 - 05:16 AM

View PostLuaCrawler, on 05 March 2014 - 05:00 PM, said:

i soooo want to try this out... but i can't figure out how to program with it... is there any documentation?

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. :P Hopefully we will merge in the next week or so. For now, testing.

I also plan to create some libraries for SEE (github, json, etc.) :D

Edited by sci4me, 10 March 2014 - 05:18 AM.


#66 TechMasterGeneral

  • Members
  • 149 posts
  • LocationUnited States

Posted 10 March 2014 - 02:15 PM

View PostYevano, on 05 March 2014 - 09:13 PM, said:

View PostLuaCrawler, on 05 March 2014 - 05:00 PM, said:

i soooo want to try this out... but i can't figure out how to program with it... is there any documentation?

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.
I've spent some time looking at the libraries and it helped some... I can't figure out how to get it to install... or compile... i'm not sure... i guess i have to compile the programs after writing them using one of the programs that i install correct?

#67 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 10 March 2014 - 08:31 PM

You don't have to compile your programs. Try just running them with the see program in see-install-dir/bin/, and make sure to use the -r switch.

The command should look something like:
see -r program_folder MainClass


#68 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 15 March 2014 - 10:13 PM

We have merged the better-classes branch to master. I am going to start writing a tutorial now.

http://www.computerc...524-see-basics/

Edited by sci4me, 16 March 2014 - 01:31 AM.


#69 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 16 March 2014 - 02:27 AM

Added sci4me's tutorial to OP. It's not bad and actually covers a lot.

#70 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 17 March 2014 - 02:27 AM

Today I have
  • 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 (!!!!)
Multiple classpath support basically means that you can write a library and package it and then distribute the package. Then, if you are using a packaged library in your program, you simply add it to rgen when you build your executable and you have the library in your program! You no longer need to have the actual source files of a library in order to use it! Exciting!

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
It then uses the File and Archive class loaders to load things. I have also implemented an HTTPClassLoader:
[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 Remi

  • Members
  • 5 posts

Posted 22 March 2014 - 10:03 AM

I've worked with it for a day now and: This is so awesome! I've had issues with LUA after getting into Java, so this is going to be useful.

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:
Spoiler

And this is the output:
Spoiler
Can you see what I am doing wrong here?

#72 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 22 March 2014 - 05:00 PM

View PostRemi1115, on 22 March 2014 - 10:03 AM, said:

I've worked with it for a day now and: This is so awesome! I've had issues with LUA after getting into Java, so this is going to be useful.

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:
Spoiler

And this is the output:
Spoiler
Can you see what I am doing wrong here?

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 Remi

  • Members
  • 5 posts

Posted 23 March 2014 - 10:35 AM

View Postsci4me, on 22 March 2014 - 05:00 PM, said:

Spoiler

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 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 23 March 2014 - 07:13 PM

View PostRemi1115, on 23 March 2014 - 10:35 AM, said:

View Postsci4me, on 22 March 2014 - 05:00 PM, said:

Spoiler

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 Remi

  • Members
  • 5 posts

Posted 25 March 2014 - 05:45 PM

View Postsci4me, on 23 March 2014 - 07:13 PM, said:

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.
Ah thank you, I understand it now!

#76 sci4me

  • Members
  • 225 posts
  • LocationEarth

Posted 25 March 2014 - 07:14 PM

View PostRemi1115, on 25 March 2014 - 05:45 PM, said:

View Postsci4me, on 23 March 2014 - 07:13 PM, said:

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.
Ah thank you, I understand it now!

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 ardera

  • Members
  • 503 posts
  • LocationGermany

Posted 20 April 2014 - 06:19 PM

Getting an error when running using see -r ardera.hw.HelloWorld -cp hw
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 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 21 April 2014 - 08:23 PM

It's probably the installer hasn't been updated. Similar code works fine when I run straight from my local repository. Give me a sec and I'll fix it.

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 SquidDev

    Frickin' laser beams | Resident Necromancer

  • Members
  • 1,427 posts
  • LocationDoes anyone put something serious here?

Posted 05 May 2014 - 02:19 PM

I just downloaded this and I am amazed. This is by far and away one of the best things I've discovered that is made for CC.

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.
Thanks so much for creating this libary. If you want me to code anything I'm happy to help.

Edited by SquidDev, 05 May 2014 - 06:36 PM.


#80 SquidDev

    Frickin' laser beams | Resident Necromancer

  • Members
  • 1,427 posts
  • LocationDoes anyone put something serious here?

Posted 07 May 2014 - 04:36 PM

Issues with Rednet
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