This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Yevano's profile picture

See - Standard Execution Environment

Started by Yevano, 04 August 2013 - 08:18 PM
Yevano #1
Posted 04 August 2013 - 10:18 PM
SEE - An object oriented alternative to traditional CC programming.


Introduction

SEE is a convenient Lua runtime whose goal is to allow programmers to more easily write readable and reusable object-oriented code. The project is open source and has been in development since August, 2013.

Features
  • Automatic setup of classes and object instances.
    • All OOP code works the same, no obscure differences with peoples' code.
  • Standard library written to speed up development.
    • Custom string and array implementations.
    • Custom IO wrapper objects for binary and plaintext.
    • More convenient string matching with the Matcher class.
    • Use the standard library in most cases, or use native imports to get close to the metal!
  • Preprocessor.
    • Import classes and native functions before runtime.
    • Set class parameters, such as class inheritance.
  • Multi-file programming. 1 class per file.
    • Each class file has its own global scope.
    • Better organization of code. (No more 2000 line files for large programs.)
  • Managed threading system!
    • Spawn threads arbitrarily throughout your program and they'll just work.
    • Thread interruption.
  • Object-oriented event system.
    • Capture events and call on their methods or get their data.
    • Create your own event classes and register them.
  • Libraries are dead simple to make.
    • No difference between runnable code and a library.
    • Need to reuse your code in another project? Just add the classpath.
  • Exception handling.
    • Makes error handling much easier.
    • No parsing of error strings to figure out what happened.
    • No returning error codes or having to check if an error occurred in a return value.
    • Print error tracebacks.

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

Get SEE

Simply download the installer to your CC computer using pastebin get 4RgrdVgE installer.
or
Access the entire repo at https://github.com/Yevano/see.

If anyone wants to talk about the project, or anything else, I frequent the #computercraft channel and I'm usually connected to my TeamSpeak3 server at yevano.me.
Edited on 09 April 2014 - 09:20 PM
Parmacoy #2
Posted 05 August 2013 - 07:36 AM
I dont really have much idea what this is, why should we use this over the generic api's. Yes I did have a look at the links, and its still not making sense.
Yevano #3
Posted 05 August 2013 - 01:01 PM
I dont really have much idea what this is, why should we use this over the generic api's. Yes I did have a look at the links, and its still not making sense.

The reason to use SEE is not necessarily for the standard library, but for the automatic OOP (Object Oriented Programming), the non-polluted global namespace, and the multi-file importing system. I realize that most people here won't know what to do with an object oriented environment, but I'll be making a few simple tutorials once I get more of the standard library done.

The main goal of SEE is to be convenient for the programmer. Lua programs which may have been thousands of lines previously can be distributed to multiple classes for much better organization.
Yevano #4
Posted 05 August 2013 - 05:14 PM
Update https://github.com/Y...792d6d94bd4e893
  • Added exception handling. An example can be found here.
  • Fixed some problems with casting. I suspect there are still some bugs, but at least string conversion works fine now.
  • Added new global function STR. Just a more convenient way to convert a Lua string to a see.base.String. Example:
    • System.print(STR"A string!":length())
Now that some more of the low-level stuff is out of the way, expect to see more in the standard library. The library will hopefully wrap over most of the native Lua libraries by the next couple of updates. After that, I'll probably go and fill in documentation holes and add error throwing to the library functions.
Yevano #5
Posted 09 August 2013 - 06:52 PM
UpdateThere's still much work to be done, but here's some new updates. Still not too much progress on the library, mostly runtime stuff.
  • Added argument checking utility (see.util.ArgumentUtils).
  • Added Math class.
  • More casting fixes.
  • Changed class importing to happen after a class has been loaded.
    • Added __static invocation to support this behaviour.
  • Added an installer. Find it here.
  • Added standard library argument to SEE executor program.
  • Added tracebacks for exceptions and Lua errors, making program debugging much easier.
    • Planning to add Exception:printStackTrace in the next update. Tracebacks are currently only printed for uncaught exceptions.
  • Added see.rt.IndexOutOfBoundsException.
Yevano #6
Posted 11 August 2013 - 10:41 PM
UpdateI won't put these into word form, at least not now, so if anyone is really interested just look at the commit page.

So, most of the important API wrapping has been done. The runtime is fully functional, and at this point I'm confident people could write full-blown programs with this thing. For this reason, I'm going to make some simple usage tutorials. I'm pretty sure nobody is using this yet, so once I get the tutorials up, I'm hoping to see some feedback. I'll make an update here once I've written some tutorials.

EDIT: I decided to go ahead and write a setup tutorial. Should help people at least get started.
TorakTu #7
Posted 16 August 2013 - 05:31 PM
I dont really have much idea what this is, why should we use this over the generic api's. Yes I did have a look at the links, and its still not making sense.

It actually does make sense what he is "trying" to do, and its a nice attempt. Problem with all this is that most all of us will not use it. Microcrap does the same thing with their "DotNetFrameWork" and a lot of us programmers hate it. Plus, I personally won't convert to this for computercraft because that would mean that I would have to rely once again on someone else to update their code / runtimes. No thanks. This doesn't make it easier as the OP is trying to suggest. It only makes it that much harder since people would have to understand what this is in the first place, not to mention, install it. Which most people will not. If this was for regular LUA, this actually could be useful. But not for LuaCC do to the limits of CC. Not to mention it could potentially add to the lag in minecraft.
Yevano #8
Posted 16 August 2013 - 06:18 PM
It actually does make sense what he is "trying" to do, and its a nice attempt. Problem with all this is that most all of us will not use it. Microcrap does the same thing with their "DotNetFrameWork" and a lot of us programmers hate it. Plus, I personally won't convert to this for computercraft because that would mean that I would have to rely once again on someone else to update their code / runtimes. No thanks. This doesn't make it easier as the OP is trying to suggest. It only makes it that much harder since people would have to understand what this is in the first place, not to mention, install it. Which most people will not. If this was for regular LUA, this actually could be useful. But not for LuaCC do to the limits of CC. Not to mention it could potentially add to the lag in minecraft.

I just want to make a few points here since you've got so many negative things to say about this project.
  • Do not tell me that nobody will use this. This is first and foremost for MY usage. The reason I made this is because I got tired of the OOP boilerplate code I would have to write for every CC project I did. It just made any new project that much more daunting and less fun to write for me. So what you say is untrue. Even if nobody else in the world uses this thing, I will be using it. But rather than just keep it to myself, I've decided to share it and make it open source for anyone else to use.
  • .NET framework is the farthest thing you could think of from this. It is a closed source library and runtime produced by a huge company. It is of little relevance.
  • Nobody is forcing anyone to use this or "convert" to it.
  • If I were to stop working on this, which I'm sure will happen eventually, the code is still out there, and anyone is allowed to create their own branch.
  • Having to learn new concepts is a part of being a programmer.
  • The runtime can be easily ported to non-embedded Lua. Many classes in the standard library are already mostly compatible with non-embedded Lua.
  • Since class loading is done only at the beginning of runtime, there is very little overhead. OOP is handled by metatables, a standard part of Lua.
TorakTu #9
Posted 16 August 2013 - 07:30 PM
  • .NET framework is the farthest thing you could think of from this. It is a closed source library and runtime produced by a huge company. It is of little relevance.
Your making Runtime files that is Object Oriented in it's very design. This is EXACTLY like DotNetFrameWork.

  • Do not tell me that nobody will use this. This is first and foremost for MY usage.
  • If I were to stop working on this, which I'm sure will happen eventually, the code is still out there, and anyone is allowed to create their own branch.
And that is cool and all. But all I said is that very few, if any, would actually understand how to use this, much less install it. So your reply shows your taking this personally. If your not likeing the opinions of others, maybe you shouldn't have put this out there. Welcome to being a programmer.

  • Having to learn new concepts is a part of being a programmer.
I couldn't agree more. However this is not new. Do a search on this and other forums of others whom have spoke about OOP with LuaCC. You will see that this idea hasn't gotten too far with people. And based on what a lot of us know about CC and LuaCC and the comments on this and other forums, in many opinions, OOP in CC is not a good idea.

And if your taking this as an attack on you personally, you shouldn't. I don't know you. People have opinions and we are all allowed to state what we think on a project.. as many of us do here. Heck even my own projects suck for some folks here. So you shouldn't take this personally.
lifewcody #10
Posted 16 August 2013 - 07:44 PM
So if i use SEE i have to go through your API, then CC's API to execute the code. No thanks :)/>. I see your idea and it has a lot of potential. If you made it an OS for CC it would be better.
theoriginalbit #11
Posted 16 August 2013 - 07:45 PM
I see your idea and it has a lot of potential.
haha I See what you did there! :P/> xD
lifewcody #12
Posted 16 August 2013 - 07:49 PM
I see your idea and it has a lot of potential.
haha I See what you did there! :P/> xD
It does. He is on the right track, but not the right type of program
TorakTu #13
Posted 16 August 2013 - 07:53 PM
I see your idea and it has a lot of potential.
haha I See what you did there! :P/> xD
It does. He is on the right track, but not the right type of program

I agree. It's a cool idea if it is integrated as part of an OS.
Yevano #14
Posted 16 August 2013 - 08:04 PM
This is EXACTLY like DotNetFrameWork.
You're comparing apples to oranges.

Also, I don't take your comment as an attack on me personally. I just wanted to correct the incorrect assumptions and false claims you made about what my goals are here.

I agree. It's a cool idea if it is integrated as part of an OS.

Because the runtime is implemented as an API, you can actually do just that for almost any environment. Have a look at https://github.com/Yevano/see/blob/master/see/apis/see.

Anyways, this a good time for me to mention that I haven't had much time to make tutorials, and school is coming soon. But I will get to it hopefully this weekend. :P/>
lifewcody #15
Posted 16 August 2013 - 08:14 PM
This is EXACTLY like DotNetFrameWork.
You're comparing apples to oranges.

Also, I don't take your comment as an attack on me personally. I just wanted to correct the incorrect assumptions and false claims you made about what my goals are here.

I agree. It's a cool idea if it is integrated as part of an OS.

Because the runtime is implemented as an API, you can actually do just that for almost any environment. Have a look at https://github.com/Y...er/see/apis/see.

Anyways, this a good time for me to mention that I haven't had much time to make tutorials, and school is coming soon. But I will get to it hopefully this weekend. :P/>

I mean instead of CraftOS with its code. Make your own. Then it wouldn't be as resource consuming.
Also what TorakTu is trying to say is that .NETFramework is an extension to windows to convert the whatever.NET to work. This is about the same. You would use SEE to convert FOR EXAMPLE see.redright to rs.setOutput("Right") just an extension. Good idea for new programmers for possible easier understanding, but as a viable programming structure. I do not think its going to get as many programs as CraftOS.
Yevano #16
Posted 16 August 2013 - 08:20 PM
I mean instead of CraftOS with its code. Make your own. Then it wouldn't be as resource consuming.

What do you mean by that? Even a custom OS uses the libraries and events provided by bios.lua. As far as function call overhead goes, I'm pretty sure it's negligible. If it really was a problem, you can still do native importing to talk directly to the CC libraries. But really, most of the time a CC program is waiting for new events, and not doing any processing.
theoriginalbit #17
Posted 16 August 2013 - 08:22 PM
What do you mean by that? Even a custom OS uses the libraries and events provided by bios.lua.
I would assume he means make a real OS, one that replaces the bios.lua
lifewcody #18
Posted 16 August 2013 - 08:51 PM
What do you mean by that? Even a custom OS uses the libraries and events provided by bios.lua.
I would assume he means make a real OS, one that replaces the bios.lua
yes
Yevano #19
Posted 16 August 2013 - 09:59 PM
Update (latest commit 17f3e6e4cdf3c0fc8f644e82ddc050d9071e958a)

Since last update, mostly small fixes. The important feature just added is runnable code archives. Archives can now be added to the class path in just the same way folders were. Archives can be created using see -p <src> <dest> and they can be unpacked using see -u <src> <dest>. This will make program distribution much easier, since you can just pack your programs and upload them to pastebin, or whatever other file host you choose.

In future updates, expect to see archive run configs, an installer generator which automatically packs class paths into one natively run file, and a hidden installation file which lists info about a computer's SEE installation.
lifewcody #20
Posted 17 August 2013 - 03:43 PM
A cool feature would be have a list of programs you can download. That would be cool
Yevano #21
Posted 17 August 2013 - 06:21 PM
A cool feature would be have a list of programs you can download. That would be cool

I'll start keeping a running list of SEE programs I or other people make in OP.
brett122798 #22
Posted 18 August 2013 - 05:00 PM
This project seems really great for people who know what OOP is! I'm going to take some serious look into this project, because it may just start a spark for me to come back to CC. After learning Java, Lua just seems so.. tough. OOP makes life so much easier in the long run.

And you people stop flaming this thread, I'm sure this guy hasn't worked his butt off to hear stuff like this from you all.
Yevano #23
Posted 18 August 2013 - 06:06 PM
This project seems really great for people who know what OOP is! I'm going to take some serious look into this project, because it may just start a spark for me to come back to CC. After learning Java, Lua just seems so.. tough. OOP makes life so much easier in the long run.

And you people stop flaming this thread, I'm sure this guy hasn't worked his butt off to hear stuff like this from you all.

Wow, thanks a lot. It makes my day to know someone is actually interested.

EDIT(8/19/13): Just want to leave a quick update without bumping the thread. I'm back at high school now so I probably won't be back working on this project until the weekend. I'll see what I can get done, but there will be less stuff being done. If anyone is interested in helping, you may may branch the repo and I will merge your commits on request after I've reviewed the changes. I'm a bit nit-picky about coding conventions and style, so try to keep whatever you write in the style of the current code. I'll make an update when I have time to work on things. Most likely it will be something easy like additions to the library.
Yevano #24
Posted 26 August 2013 - 06:25 PM
Update. (Latest commit 89d742febfb98d361038f253c60504a5e4145025) I added rgen, a program which generates a native runnable from a class archive. Using this now makes it much more convenient for end users to use programs which run with SEE. Here's an example:

#Pack code into a class archive.
see/programs/see -p someSeeProgram classArchive
#Generate a native runnable.
see/programs/rgen classArchive the.main.Class runnableFile
#Test it!
runnableFile

I haven't extensively tested this, but it does work for Omegle-CC. If anyone has issues please reply here.

EDIT: Tiny update on this (2285e220fb01992c7832a2b303a42dce451ae382 if you're interested)
Symmetryc #25
Posted 12 September 2013 - 10:17 PM
Seems like so much work and so little attention D:. Is there anyway to package this up with a program? Ex: When you download a LOVE2D program, you don't have to have to have LOVE2D yourself, there is a way to package it up with the program, is there anything similar for this? I think it would really increase interest.
Yevano #26
Posted 12 September 2013 - 10:35 PM
Seems like so much work and so little attention D:. Is there anyway to package this up with a program? Ex: When you download a LOVE2D program, you don't have to have to have LOVE2D yourself, there is a way to package it up with the program, is there anything similar for this? I think it would really increase interest.

Yes and no. I've made a utility for packaging SEE programs as singular, runnable programs. However, they won't run unless SEE is installed. Packaging the entire SEE library and runtime into a program would make for large filesizes and wasted resources. A better solution would be an automatic installer packaged onto the programs, but I just haven't gotten to it. Maybe I'll see if I have time to cook something up tomorrow/this weekend.
Kingdaro #27
Posted 12 September 2013 - 10:59 PM
To be fair, I don't think I've ever seen a LÖVE game that was even a fifth the size of the LÖVE executable itself (excluding binary files like audio, fonts or images), so in relative size, the code-to-runtime size ratio there is pretty damn small.
Yevano #28
Posted 12 September 2013 - 11:27 PM
The main problem is that packaging anything with my current system actually inflates it by a large amount because of the way I store the bytes in source code. For example, the Omegle-CC package http://pastebin.com/raw.php?i=ksZG8m62
Yevano #29
Posted 14 September 2013 - 11:07 AM
Update (latest commit c32c0b394edccc4c7c1d3b307f552388efb229f2)

The most important update here is the new program, igen. It can be used to generate an installer for SEE programs, where the generated installer will first check if SEE is installed, download the SEE updater if not, and then allow the user to pick a place to install their program. The generated installer size is by no means optimal, but at least it works, and can be distributed on pastebin (Because of the large file sizes, pastebin won't generally accept installers. I know of some ways I can shrink the file size, but I probably won't do it for at least another week unless someone is able to contribute a very trivial way of doing this.).

The usage for igen is igen <runnable> <name> <target>.
sci4me #30
Posted 22 September 2013 - 02:30 PM
ERMERGERD this is so awesome! Incredible what you could do with this… the possibilities. I find this to be under appreciated. Great work!!!
Yevano #31
Posted 06 October 2013 - 09:25 PM
Due to school, development has been slow as molasses recently. There are some parts that need cleaning up and I just wrote up a couple issues which I'll hopefully resolve this week (#1, #2). Again, anyone can branch the project and request a merge. There are many other things which need to be addressed, and I'll get those posted as well, but those two are the most important right now.
Symmetryc #32
Posted 06 October 2013 - 09:31 PM
The main problem is that packaging anything with my current system actually inflates it by a large amount because of the way I store the bytes in source code. For example, the Omegle-CC package http://pastebin.com/raw.php?i=ksZG8m62
I hope you know that long string of numbers and slashes can be compressed down so much it's not even funny.
Yevano #33
Posted 06 October 2013 - 10:07 PM
I hope you know that long string of numbers and slashes can be compressed down so much it's not even funny.

Quite aware. The problem, however, isn't compression. The problem is that I have to convert source code to a Lua string, and the way it's done right now is to just use character escape syntax. A better way is probably to go case by case and only escape problematic chars, but this isn't really a top priority right now. Definitely something I'll add to the repo issues, though!

Edit: Just realized you were proposing to compress the current string output. Since that's contained in the actual program, that's not really an option. Beforehand compression is definitely something that will be done at a later stage, though.
tesla1889 #34
Posted 07 October 2013 - 01:19 PM
for future reference, __gc is only called if the metatable describes a userdata value.
for example, FileInputStream will not call __gc when the object is garbagecollected.\
__gc is pretty much pointless in CC, unless you're writing a mod or dan200 is using a non-standard version of lua
Yevano #35
Posted 07 October 2013 - 03:50 PM
for future reference, __gc is only called if the metatable describes a userdata value.
for example, FileInputStream will not call __gc when the object is garbagecollected.\
__gc is pretty much pointless in CC, unless you're writing a mod or dan200 is using a non-standard version of lua

Thanks. After a quick search, it looks like finalizers for tables were added in 5.2. I'll remove the redundant code today.

Edit: Created a new branch for testing the new event system. https://github.com/Yevano/see/compare/better-events
Yevano #36
Posted 09 October 2013 - 07:30 PM
Lots of progress has been made! (relatively speaking) Not only is the event system fully functional, but the threading system has been completely overhauled (not that there was much work done on threads to begin with). I haven't merged all this with the master branch yet since I want to make sure everything works correctly and possibly add some changes here and there, but if you'd like to test it out just pull the better-events branch and mess around with it.

I'm not all that great at explaining things, so I'll let the example code explain itself.

see.dev.Test

--@import see.concurrent.Thread
--@import see.dev.TestEvent
--@import see.util.Math

function Test.main()
    Events.register("test", TestEvent)
    System.print("Hello World!")

    for i = 1, 4 do
        Thread.new(function()
            System.print("Hello from thread " .. i .. "!")

            local event = Events.pull("test")
            local message = event.message
            repeat
                System.print("T[" .. i .. "] " .. message)
                event = Events.pull("test")
                message = event.message
            until message == "stop"
        end):start()
    end

    for i = 1, 3 do
        Events.queue(TestEvent.new(Math.random()))
    end

    Events.queue(TestEvent.new("stop"))
end

see.dev.TestEvent

--@import see.event.Event

--@extends see.event.Event

function TestEvent:init(message)
    Event.init(self, "test")
    self.message = message
end

Output
Yevano #37
Posted 10 October 2013 - 06:44 PM
Commit #50 (Guess I can call this a milestone of sorts.) 42c33ec39c189b5153dd8a5484b4b0af1e0a271e

After running the new system against a good number of test cases, and also converting the Omegle-CC program over to the new system, I've finally merged the changes onto the repo. Yay! Not quite sure what I want to work on next right now, but there's definitely still quite a bit more to get done.

I think the best way forward is to just start writing a few practical programs for bug testing. I can do this by myself, but it will take a while for me to produce a good number of non-trivial programs and iron out possible bugs at the same time. If you think you want to help with bug testing, just shoot me a PM or tell me here. Even if you only code something simple, or you only find a couple bugs, the help is great no matter what. If you feel up for it, you can even pull the repo and fix something yourself.
distantcam #38
Posted 13 October 2013 - 07:50 PM
Holy creeper balls this is amazing!

As someone who's spent the last 10 years working with OOP languages and frameworks I appreciate SEE a lot.

I'm happy to help out with bug testing, it'll give me a chance to learn Lua and CC more.
Yevano #39
Posted 14 October 2013 - 09:52 PM
Holy creeper balls this is amazing!

As someone who's spent the last 10 years working with OOP languages and frameworks I appreciate SEE a lot.

I'm happy to help out with bug testing, it'll give me a chance to learn Lua and CC more.

Glad to hear it! If you need any help with setup, shoot me a PM. I should have mentioned this earlier, but I also have a teamspeak if anyone wants to talk via voice. I should really overhaul the OP…
distantcam #40
Posted 15 October 2013 - 02:52 AM
Alright, first bug report then. :D/>

The pastebin no longer installs correctly. The install script in the GitHub repo works fine, so I had to download that manually (btw why is there no simple wget program in the bios?!)

Once I got the proper install I got the simple hello world working no problems. Then I packaged it, and turned it into a self-contained program with rgen.
Yevano #41
Posted 15 October 2013 - 04:23 PM
The pastebin no longer installs correctly.

Yeah, I usually forget to update it. I should really just have it download the install program from the repo and run that, but for now I'll just edit in the newest installer into it. Today, I think I'll be cleaning up OP and working on making see.concurrent a bit more full fledged (tasks, future objects, thread joining, etc.).

Edit: Updated OP with relevant new feature set and my teamspeak. Later I'll add example code to the OP to show off the features a bit better.

Edit: Aaand this is awesome. :D/>

In addition to tasks, I also added a convenience function for running process-heavy code. When Thread.work is first called, it saves the time it was run inside the thread. Once it gets called 1/20 seconds after it was first called, it sleeps and resets the time. As a rule of thumb, you should use this function whenever your thread needs to do busy calculations.


--@import see.concurrent.Thread
--@import see.concurrent.Task

function Test.main()
    local piTask = Task.new(calculatePi, 1000000):setCallback(function(result)
        System.print(result)
    end)

    repeat
        System.print("Waiting...")
        Thread.sleep(1)
    until piTask:isFinished()
end

function calculatePi(iter)
    local pi = 4
    for i = 1, iter * 2, 2 do
        Thread.work()
        pi = pi - (4/(1 + i * 2))
        pi = pi + (4/(3 + i * 2))
    end
    return pi
end

Yevano #42
Posted 16 October 2013 - 08:23 PM
So apparently class inheritance hasn't been working. Surprised that I never realized it. Anyways, it's working now. I also added .__super to class tables. This weekend I want to work on fixing more issues and on my super special GUI library (I'll give it a repo once I have all basics in place and working).
Engineer #43
Posted 17 October 2013 - 05:51 PM
This really reminds me of Java. Of course just the way how you have your packages and your love for OOP made you do this.
I can see how this just combines 2 languages in one. At least, for the logic part. I mean, we can create easily objects with this, but we still can have our love for the scoping in Lua.

I really would use this if I wrrent the guy that never uses other API's and stuff. For example, my friend LBPHacker is explaining me how base64 works, he wrote an API for it but I still want it to be done my way. Not because his code is bad or anything, but just for the challenge. And that way I'm learning a lot of binary manipulation etc.

But to get back to SEE, I'm still that picky guy who would write his own framework to suit his needs. I mean, you're things are not bad at all, but I wouldn't use certain things or I want something to do extra stuff.

I really appreciate that you took chance to even publish it, and seeing this getting very underrated in the beginning I just want to say you did a good job on this. Even someone who just started programming deserves positive feedback, just to keep them motivated. I'm doing that with you, the only difference is that you didnt just start programming, but you just started writing this very promising framework.
Yevano #44
Posted 17 October 2013 - 08:41 PM
This really reminds me of Java. Of course just the way how you have your packages and your love for OOP made you do this.
I can see how this just combines 2 languages in one. At least, for the logic part. I mean, we can create easily objects with this, but we still can have our love for the scoping in Lua.

I used to do quite a bit of programming in Java. I really did enjoy the way they did their libraries and almost everything about how the pieces just fit together in general. Java has a huge impact on the project.

I really would use this if I wrrent the guy that never uses other API's and stuff. For example, my friend LBPHacker is explaining me how base64 works, he wrote an API for it but I still want it to be done my way. Not because his code is bad or anything, but just for the challenge. And that way I'm learning a lot of binary manipulation etc.

But to get back to SEE, I'm still that picky guy who would write his own framework to suit his needs. I mean, you're things are not bad at all, but I wouldn't use certain things or I want something to do extra stuff.

I get where you're coming from. There have been a few implementations of OOP on the forums which I thought were pretty cool, but never used because none of them were very feature-filled, or they were implemented in a way I felt I would do differently. I would like to note that at least with this project you can change those features to add in your own spice, since the project is open-source.

I really appreciate that you took chance to even publish it, and seeing this getting very underrated in the beginning I just want to say you did a good job on this. Even someone who just started programming deserves positive feedback, just to keep them motivated. I'm doing that with you, the only difference is that you didnt just start programming, but you just started writing this very promising framework.

Thanks, and the positive feedback definitely helps.
Yevano #45
Posted 20 October 2013 - 12:39 PM
My GUI library is coming along. Once it's done, I think it will be a great example of SEE's power.


--@import weegui.element.Panel
--@import weegui.element.Label

--@import see.concurrent.Thread
--@import see.util.Color

function WeeGuiDemo.main()
    local labelPanel = Panel.new(nil, 2, 2, 20, 10, Color.BLUE, Color.BLUE)
    local label1 = Label.new(labelPanel, 2, 2, "Hello!", Color.BLUE, Color.BLACK)
    local label2 = Label.new(labelPanel, 2, 3, "4", Color.BLUE, Color.BLACK)

    local pi = 4
    local i = 1
    while true do
        Thread.work()
        pi = pi - (4/(1 + i * 2))
        pi = pi + (4/(3 + i * 2))
        label2.text = STR(pi)
        i = i + 2
    end
end

Yevano #46
Posted 21 October 2013 - 09:34 PM
Just a few updates:

Threads were being run as soon as Thread:start was invoked. Now, they just get scheduled without being run. This is to prevent multiple threads from running on top of each other. I added a new event called SignalEvent. It's not all that useful now, but once I make events passable to specific threads, it will be useful for waking up threads or sending messages across threads. Something like Events.send(thread1, thread2, …) perhaps.

Also, I've been working hard on the gui lib (It's called WeeGui by the way). Since the last post I implemented element draw buffers, element event listening, and a window implementation.


--@import weegui.concurrent.GuiManager
--@import weegui.element.Button
--@import weegui.element.Element
--@import weegui.element.Label
--@import weegui.element.Window

--@import see.concurrent.Thread
--@import see.util.Color

function WeeGuiDemo.main()
    local testWindow = Window.new(nil, 2, 2, 30, 16, "Test")
    local contentPanel = testWindow.contentPanel
    local label1 = Label.new(contentPanel, 2, 2, "Hello!", Color.BLACK, Color.WHITE)
    local label2 = Label.new(contentPanel, 2, 3, "4", Color.BLACK, Color.WHITE)
    local button1 = Button.new(contentPanel, 2, 5, 10, 5, "STOP", Color.GRAY, Color.WHITE)

    local running = true
    button1:addListener(Element.CLICK, function(button, x, y)
        GuiManager.stop()
        running = false
    end)

    local pi = 4
    local i = 1
    while running do
        Thread.work()
        pi = pi - (4/(1 + i * 2))
        pi = pi + (4/(3 + i * 2))
        label2:setText(STR(pi))
        i = i + 2
    end
end

brett122798 #47
Posted 28 October 2013 - 08:14 PM
This is looking quite pleasing so far. Such a shame that there's hardly any people looking at this project. But, of course, all those Lua'ers(Is that a word?) don't know the wonders of Object-Oriented Programming over functional.

For the past inactive months on these forums(since May), I have dedicated myself to Java, and nothing else. I have made way bigger and more complex applications (and Bukkit plugins) than I would have sticking to Lua. The golden key was OOP. Java also has a nicer API and syntax as well.

Lua is still nice 'n all, it just doesn't cut it for me, though.
sci4me #48
Posted 24 December 2013 - 05:20 AM
Just a few updates:

Threads were being run as soon as Thread:start was invoked. Now, they just get scheduled without being run. This is to prevent multiple threads from running on top of each other. I added a new event called SignalEvent. It's not all that useful now, but once I make events passable to specific threads, it will be useful for waking up threads or sending messages across threads. Something like Events.send(thread1, thread2, …) perhaps.

Also, I've been working hard on the gui lib (It's called WeeGui by the way). Since the last post I implemented element draw buffers, element event listening, and a window implementation.


--@import weegui.concurrent.GuiManager
--@import weegui.element.Button
--@import weegui.element.Element
--@import weegui.element.Label
--@import weegui.element.Window

--@import see.concurrent.Thread
--@import see.util.Color

function WeeGuiDemo.main()
	local testWindow = Window.new(nil, 2, 2, 30, 16, "Test")
	local contentPanel = testWindow.contentPanel
	local label1 = Label.new(contentPanel, 2, 2, "Hello!", Color.BLACK, Color.WHITE)
	local label2 = Label.new(contentPanel, 2, 3, "4", Color.BLACK, Color.WHITE)
	local button1 = Button.new(contentPanel, 2, 5, 10, 5, "STOP", Color.GRAY, Color.WHITE)

	local running = true
	button1:addListener(Element.CLICK, function(button, x, y)
		GuiManager.stop()
		running = false
	end)

	local pi = 4
	local i = 1
	while running do
		Thread.work()
		pi = pi - (4/(1 + i * 2))
		pi = pi + (4/(3 + i * 2))
		label2:setText(STR(pi))
		i = i + 2
	end
end


man, that is reallly cool.
Yevano #49
Posted 10 February 2014 - 05:15 PM
Well, it's been months since I've last posted here. The project isn't dead. I just recently started working on this again, and I've fixed a couple things. Exception handling now works with the new threading system, and anonymous classes have been implemented. The anonymous classes are pretty neat, so I'll show an example of how they work here.


function AnonTest.main()
    local A = class("A", { },
    function()
        function A:init(x)
            self.x = x * 2
        end
    end)
    local B = class("B", {
        import = {
            "see.util.Math";
        };
        native = {
            "print";
        };
        extends = ExTest;
    }, function()
        function B:init(x)
            A.init(self, x)
        end

        function B:y(z)
            print(Math.pow(self.x, z))
        end
    end)
    B.new(3):y(4) --> prints 1296
end

Next up, Thread:interrupt(). This will make it possible to tell a thread to stop waiting on an event by throwing an exception.
surferpup #50
Posted 10 February 2014 - 11:25 PM
Very impressive. I just finished reading through all of your posts – you are in high school? Dude. This is amazing work. Kudos. I will have to dig into it and see if I can get it to do something.
Yevano #51
Posted 11 February 2014 - 10:01 AM
Very impressive. I just finished reading through all of your posts – you are in high school? Dude. This is amazing work. Kudos. I will have to dig into it and see if I can get it to do something.

Thanks for the kind words! Your best bet right now is to clone right from the repository and create the .see configuration file in the root directory of whatever CC computer you copy everything to. It should contain install_dir = "see install dir here". There's also an automatic installer but (Edit: Installer works just fine, simply use the one mentioned in the OP.) I'll need a moment to make sure it still works and add the new files to it (I really need to automate that part some day).

When you start writing applications, the standard library is a good reference for how to setup your code. If you want to do something more advanced, like plugging the SEE runtime into your own application, take a look here for reference.

Edit: Oh and Thread:interrupt() was committed. Yay. :)/>
Edit2: The application runner (see/programs/see) throws better errors now.
Edited on 11 February 2014 - 09:33 AM
sci4me #52
Posted 14 February 2014 - 03:34 PM
man… keep this up! this really is impressive! now to start coding with it! you should consider working on an eclipse plugin that (maybe could extend the lua plugins..) would add SEE projects and a build system… would be useful.

Edit:

I am using this to build my projects:

local tArgs = { ... }
if #tArgs ~= 3 then
error("Usage: build <src> <mainClass> <target>")
end

shell.run("see", "-p", tArgs[1], tArgs[1] .. "_p")
shell.run("rgen", tArgs[1] .. "_p", tArgs[2], tArgs[3])
fs.delete(tArgs[1] .. "_p")

Edit:

I keep getting this weird error trying to execute a program:


bios:339: [string "DB-r"]:4: escape sequence too large

I've had that multiple times.. and IDK how I fixed it the first few times… but, every time, the code has been correct… this is a bug in SEE :/

Edit:

Ok, currently the code causing that error is this:


if query[1] == "get" then

end

Actually, the specific piece that breaks it is this:


[1]

WTF did you do lol, fix ???

I put this:

local one = 1
query[one]

And that fixed it (lol)….

Edit:

OK this one is by far the most confusing so far:


function Modem:broadcast(msg)
    if msg == nil then
         error("nil")
    end
    self:send(CHANNEL_BROADCAST, msg)
end

I call it like this:


modem.broadcast("getDNSID")

and get this:


Error: nil

WTF? WTF????? WHAT?!?
Edited on 14 February 2014 - 06:36 PM
Yevano #53
Posted 14 February 2014 - 09:03 PM
I'm not sure about the escape sequence error. Since it's a bios error that doesn't really tell me very much. I think that error may be produced by the generated runnable itself and not the code within it. It's definitely weird.

Edit: According to http://www.lua.org/s...5.1/llex.c.html, there seems to be a hard limit on escape sequences, UCHAR_MAX (255). It'd be good if you could send me a runnable file which reproduces the problem. I believe it can be fixed if I have the runnable concatenate multiple strings at runtime so that the lexer won't complain Ok, new idea. After rereading the code, it looks like it just sets a limit on the escape number where in the escape \xxx, xxx cannot be greater than 255. This would explain why the error only occurs when you add the number back in. In the runnable, the escaped archive string must have an escape code in it right before the 1, causing it to produce something like \xxx1. The 1 contributes to the escape code, and the error gets thrown because the number is perhaps in the thousands. I'm not sure why the character in front of the 1 would be escaped though. I'll look into it.

More Edit: Alright, so starting at line 68 of rgen Cameron wrote some code to deal with unprintable characters more elegantly than before, reducing archive and runnable sizes. However, it still has a few holes in it. The reason your code broke was because of the number right after the left-bracket. Currently the converter escapes brackets for some reason, most likely because they are used in commenting, but this isn't actually necessary since they are inside of a string anyways. Taking out the unnecessary things will fix the problem, but I'll need a special case for the situation where there are escaped chars right before numbers.

Until the above is fixed, (Hopefully tomorrow if the power comes back) you can test your programs using the -r switch to run programs from directories without any building necessary.

To your second problem, you need to call instance methods like this:

modem:broadcast("getDNSID")

Otherwise, the method won't get the object value for self. (Basically you're giving it "getDNSID" for self and nil for msg.)

I don't recall ever making a Modem class, so I'm guessing it's your own wrapper. If you post the code I can help you further.
Edited on 14 February 2014 - 08:40 PM
sci4me #54
Posted 15 February 2014 - 11:20 AM
Okay, thank you! :D/> As for the modem, wow I feel dumb. :P/> Its just a little wrapper for rednet: https://github.com/sci4me/CC

Awwww, symlinks dont work with CC? :'(
Edited on 15 February 2014 - 10:23 AM
Yevano #55
Posted 15 February 2014 - 11:38 PM
With the help of sci4me, (you were a great tester :P/>) rgen is fully working. After I fixed the character escape problem, we realized there was something else wrong. Trivial hello world programs would work, but I was unable to generate a working runnable for Omegle-CC. The problem was that rgen was still running the main code as the main coroutine, which was the way things were before I wrote the new threading system. The inner event loop and thread manager was not being started, causing all sorts of weird things to happen when trying to pull events. Anyways, now that it works, I'm going to fix up igen (which works, it creates an installer) and write a ton of error handling code.

After that, maybe I'll finish up weegui and make an IDE.
sci4me #56
Posted 16 February 2014 - 09:40 PM
I have submitted a pull requestFixes SEE support for OpenPeripherals
- Native Events - events that are handled like normal (not using the SEE event system)
Edited on 16 February 2014 - 09:43 PM
Yevano #57
Posted 16 February 2014 - 10:52 PM
I have submitted a pull requestFixes SEE support for OpenPeripherals
- Native Events - events that are handled like normal (not using the SEE event system)

To expand:

There was a problem where peripheral.call would always fail on OpenPeripheral methods. After taking a look at the OpenPeripheral code, we found that the methods would yield to pull an event, which it was doing in a way incompatible with SEE's event system. The easy solution was to register events which are allowed to be caught up into the system as native events. You can do this with any event by the way, so this could be used for other custom peripherals as well.
TechMasterGeneral #58
Posted 17 February 2014 - 04:56 PM
Awesome!!
Symmetryc #59
Posted 17 February 2014 - 09:30 PM
Wait…so this supports both CC and OC?
sci4me #60
Posted 17 February 2014 - 09:33 PM
Wait…so this supports both CC and OC?

It could be adapted to work with OC but at the moment the standard library and (i think, maybe..) some of the actual see api is CC dependent.. but, it would be fairly easy to make it work with OC. Whether we will make an OC version or not.. idk. It would be a lot of work to maintain both branches of it.
Yevano #61
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.
Yevano #62
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 on 20 February 2014 - 08:10 PM
TechMasterGeneral #63
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?
Yevano #64
Posted 05 March 2014 - 09:13 PM
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 on 05 March 2014 - 08:13 PM
sci4me #65
Posted 10 March 2014 - 05:16 AM
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 on 10 March 2014 - 04:18 AM
TechMasterGeneral #66
Posted 10 March 2014 - 02:15 PM
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?
Yevano #67
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
sci4me #68
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.computercraft.info/forums2/index.php?/topic/17524-see-basics/
Edited on 16 March 2014 - 12:31 AM
Yevano #69
Posted 16 March 2014 - 02:27 AM
Added sci4me's tutorial to OP. It's not bad and actually covers a lot.
sci4me #70
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:
  1. load see.base.Object and see.rt.Class with a dummy class loader function
  2. load a DefaultClassLoader to load other classes
  3. load a few other classes
  4. load a FileClassLoader and ArchiveClassLoader
It then uses the File and Archive class loaders to load things. I have also implemented an HTTPClassLoader:

--@import see.rt.HTTPClassLoader
--@import 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 on 21 March 2014 - 06:24 PM
Remi #71
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

--@import see.io.Peripheral

function St00f.main()
  System.print(Peripheral.getNames())
  for _,name in pairs(Peripheral.getNames()) do
	System.print(name)
  end
end

And this is the output:
Spoiler

see.base.Array ('data')
St00f:5: attempt to call nil
@ line 5 in St00f
Can you see what I am doing wrong here?
sci4me #72
Posted 22 March 2014 - 05:00 PM
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

--@import see.io.Peripheral

function St00f.main()
  System.print(Peripheral.getNames())
  for _,name in pairs(Peripheral.getNames()) do
	System.print(name)
  end
end

And this is the output:
Spoiler

see.base.Array ('data')
St00f:5: attempt to call nil
@ line 5 in St00f
Can you see what I am doing wrong here?

You are trying to use pairs. If you want to use pairs, you should –@native import it. HOWEVER, DO NOT DO THIS. Peripheral.getNames returns a see.base.Array
Use :iAll


--@import 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.&#46;&#46;/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:


--@native pairs

Hope this helps!

EDIT:

The see.base.Iterators class contains a wrapper for pairs and ipairs. Use it instead of –@native pairs/ipairs.
Edited on 22 March 2014 - 04:22 PM
Remi #73
Posted 23 March 2014 - 10:35 AM
Spoiler
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

--@import see.io.Peripheral

function St00f.main()
  System.print(Peripheral.getNames())
  for _,name in pairs(Peripheral.getNames()) do
	System.print(name)
  end
end

And this is the output:
Spoiler

see.base.Array ('data')
St00f:5: attempt to call nil
@ line 5 in St00f
Can you see what I am doing wrong here?

You are trying to use pairs. If you want to use pairs, you should –@native import it. HOWEVER, DO NOT DO THIS. Peripheral.getNames returns a see.base.Array
Use :iAll


--@import 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.&#46;&#46;/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:


--@native pairs

Hope this helps!

EDIT:

The see.base.Iterators class contains a wrapper for pairs and ipairs. Use it instead of –@native pairs/ipairs.

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?
sci4me #74
Posted 23 March 2014 - 07:13 PM
Spoiler
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

--@import see.io.Peripheral

function St00f.main()
  System.print(Peripheral.getNames())
  for _,name in pairs(Peripheral.getNames()) do
	System.print(name)
  end
end

And this is the output:
Spoiler

see.base.Array ('data')
St00f:5: attempt to call nil
@ line 5 in St00f
Can you see what I am doing wrong here?

You are trying to use pairs. If you want to use pairs, you should –@native import it. HOWEVER, DO NOT DO THIS. Peripheral.getNames returns a see.base.Array
Use :iAll


--@import 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.&#46;&#46;/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:


--@native pairs

Hope this helps!

EDIT:

The see.base.Iterators class contains a wrapper for pairs and ipairs. Use it instead of –@native pairs/ipairs.

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.
Remi #75
Posted 25 March 2014 - 05:45 PM
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!
sci4me #76
Posted 25 March 2014 - 07:14 PM
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. :)/>
ardera #77
Posted 20 April 2014 - 07: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 on 20 April 2014 - 06:08 PM
Yevano #78
Posted 21 April 2014 - 09: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 on 21 April 2014 - 07:41 PM
SquidDev #79
Posted 05 May 2014 - 03: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 on 05 May 2014 - 05:36 PM
SquidDev #80
Posted 07 May 2014 - 05: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 on 07 May 2014 - 03:36 PM
Yevano #81
Posted 07 May 2014 - 10:10 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.


Glad you like it SquidDev! :D/> I don't work on this project much these days, though I do check the repo regularly for pull requests and such. If you want to work on some of those things you listed, you're definitely welcome to make some commits and send them my way!

toString should always return a see.base.String rather than a normal Lua string. It needs to do that because both user code and runtime code may call it. Since it can get called by user code directly, we don't want the user to have to worry about casting those strings. They should always be expecting a see.base.String. The line you're referencing is in see/apis/see, and it actually is for casting objects to normal strings.

About event handling, I'd like to keep the core event system pretty much the way it currently is. The main problem with listener style handling is that eventually you can get into callback hell with listeners inside listeners inside listeners (etc). That was actually the way I originally did the events system, using hooks (You can probably find them in some commits waaay back). The current events system works much better with the threading system, which by the way, you should totally play with that. :P/> One of the most fun parts of the code I think.

Of course, listener style event handling works pretty well for GUI systems because they're so object-oriented. That's why it has its own custom event system.

Now, sandboxing. I was thinking about doing that when someone was making that new browser that was supposed to be pretty awesome, but he ended up being our biggest critic so I didn't think too much more about it. Still though, SEE applets would be pretty damn cool for the new Firewolf I think. All you'd need to do is call the SEE API functions from Firewolf to load the runtime in. At that point, natives would have to be disabled and file APIs would need to be restricted. There could be something similar to Java like a SecurityManager or something to do the sandboxing. Maybe you get an instance of the SecurityManager and it tracks the level of the object. Code with access to higher level security managers would be able to sandbox potentially unsafe code by writing settings to the object. The same code would still be able to do as it pleases by temporarily disabling the manager when it needs to do some protected operations. Hmm, this might actually be a really neat idea. :D/>

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.

I may ask sci4me about some of those things because he added in the rednet stuff for the update to CC1.6. It's quite possible he ended up just wrapping the functions directly instead of pulling the correct event. This a problem I had with sleep a while back, and then realized that I'd just need to queue and pull timer events manually in the code rather than calling the native sleep since the events system works differently.

Edit: Yep, he's directly calling rednet.receive and rednet.lookup. Those functions will end up pulling events the native way and just break stuff.
Edited on 07 May 2014 - 08:19 PM
sci4me #82
Posted 07 May 2014 - 11:48 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.


Glad you like it SquidDev! :D/> I don't work on this project much these days, though I do check the repo regularly for pull requests and such. If you want to work on some of those things you listed, you're definitely welcome to make some commits and send them my way!

toString should always return a see.base.String rather than a normal Lua string. It needs to do that because both user code and runtime code may call it. Since it can get called by user code directly, we don't want the user to have to worry about casting those strings. They should always be expecting a see.base.String. The line you're referencing is in see/apis/see, and it actually is for casting objects to normal strings.

About event handling, I'd like to keep the core event system pretty much the way it currently is. The main problem with listener style handling is that eventually you can get into callback hell with listeners inside listeners inside listeners (etc). That was actually the way I originally did the events system, using hooks (You can probably find them in some commits waaay back). The current events system works much better with the threading system, which by the way, you should totally play with that. :P/> One of the most fun parts of the code I think.

Of course, listener style event handling works pretty well for GUI systems because they're so object-oriented. That's why it has its own custom event system.

Now, sandboxing. I was thinking about doing that when someone was making that new browser that was supposed to be pretty awesome, but he ended up being our biggest critic so I didn't think too much more about it. Still though, SEE applets would be pretty damn cool for the new Firewolf I think. All you'd need to do is call the SEE API functions from Firewolf to load the runtime in. At that point, natives would have to be disabled and file APIs would need to be restricted. There could be something similar to Java like a SecurityManager or something to do the sandboxing. Maybe you get an instance of the SecurityManager and it tracks the level of the object. Code with access to higher level security managers would be able to sandbox potentially unsafe code by writing settings to the object. The same code would still be able to do as it pleases by temporarily disabling the manager when it needs to do some protected operations. Hmm, this might actually be a really neat idea. :D/>

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.

I may ask sci4me about some of those things because he added in the rednet stuff for the update to CC1.6. It's quite possible he ended up just wrapping the functions directly instead of pulling the correct event. This a problem I had with sleep a while back, and then realized that I'd just need to queue and pull timer events manually in the code rather than calling the native sleep since the events system works differently.

Edit: Yep, he's directly calling rednet.receive and rednet.lookup. Those functions will end up pulling events the native way and just break stuff.

Yes, I admit it. I did some silly things. :D/> We are now working on all the things now. I will go and fix the broken API's soon. We are currently working on a Security Manager system……. :D/> It sounds like it will be very interesting… :D/>
SquidDev #83
Posted 09 May 2014 - 08:42 PM
toString should always return a see.base.String rather than a normal Lua string. It needs to do that because both user code and runtime code may call it. Since it can get called by user code directly, we don't want the user to have to worry about casting those strings. They should always be expecting a see.base.String. The line you're referencing is in see/apis/see, and it actually is for casting objects to normal strings.

About event handling, I'd like to keep the core event system pretty much the way it currently is. The main problem with listener style handling is that eventually you can get into callback hell with listeners inside listeners inside listeners (etc). That was actually the way I originally did the events system, using hooks (You can probably find them in some commits waaay back). The current events system works much better with the threading system, which by the way, you should totally play with that. :P/> One of the most fun parts of the code I think.

Of course, listener style event handling works pretty well for GUI systems because they're so object-oriented. That's why it has its own custom event system.
All of that makes sense. I realised after posting that event listeners were only useful about 1 in 100 times as most of the time I have several 'event loops', making listeners less useful as you have to assign and unassign listeners to events.

Read
Why port over the entire function? You should just cast the parameters and pass them to the native function.
(from GitHub)
I felt I should explain more: read uses os.pullEvent (bios.lua:257) to work. It checks if it is a character, key, paste and performs an action based on that (such as entering a character). As SEE 'gobbles' up events from the os queue all read does is display a blinking cursor as it receives no events.

Rednet
I pushed a rednet fix to GitHub. Receive and lookup work.
I added a RednetConnection class. This allows you to send and receive rednet messages between two computers - a one-to-one connection. An array of these are returned on lookup. I chose to do this as lookup also gives you the ability to get the hostname, as well as filter by it so RednetConnection can store the hostname. Returning an array of these seemed better than returning an array of ids. I can always switch it back though if you think this isn't a great idea or there is a better way.

Rednet.receive returns the appropriate RednetMessageEvent. I wasn't sure about this but otherwise I would just end up creating another object that duplicates all data from RednetMessageEvent. There probably is a neater/better way, if so do tell me.

However the main issue I have is that rednet.host uses rednet.lookup (rednet:141). As host then sets tHostnames (which is a variable local to the rednet API), one cannot re-implement the functionality of it without porting the entire rednet loop which does not seem a not very good idea.

A side note: Why are we warned not to use RednetMessageEvent?
Yevano #84
Posted 09 May 2014 - 09:38 PM
Ah nice. Ok, I'll take a look at all this and probably merge it.
Yevano #85
Posted 09 May 2014 - 09:58 PM
I felt I should explain more: read uses os.pullEvent (bios.lua:257) to work. It checks if it is a character, key, paste and performs an action based on that (such as entering a character). As SEE 'gobbles' up events from the os queue all read does is display a blinking cursor as it receives no events.


Gotcha. Merged.

However the main issue I have is that rednet.host uses rednet.lookup (rednet:141). As host then sets tHostnames (which is a variable local to the rednet API), one cannot re-implement the functionality of it without porting the entire rednet loop which does not seem a not very good idea.

The simplest solution may be to call getfenv on rednet.host and detour its os.pullEvent so that it makes the correct calls. However, I'm not sure if a custom rednet event dispatcher would be a totally horrible thing. On the one side, we're of course basically duplicating old code and events and possibly making SEE's inner event loop have even more special cases, but on the other side, this would allow us to add our own custom parts to the rednet API, since it's not like rednet is doing anything magical anyways. I guess what I'm getting at is that we don't necessarily need to keep rednet as a standard, unless everyone thinks not keeping rednet as a standard is a really bad idea. A while ago I had started coding my own networking library using SEE which would do neat things like build route tables and do network discovery. It would also have been able to send out binary messages instead of just plaintext, using the current io system as the standard for doing such things. We'd be able to expand upon such a thing with connection-based sockets of course.

A side note: Why are we warned not to use RednetMessageEvent?


I believe that warning has been there since before 1.6, when I basically deemed rednet as a small direct wrapper over modems. Now that rednet is more of a networking toolset, it makes more sense to use it, unless we were to make our own library for a similar purpose.
Edited on 09 May 2014 - 08:00 PM
SquidDev #86
Posted 10 May 2014 - 09:40 AM
The simplest solution may be to call getfenv on rednet.host and detour its os.pullEvent so that it makes the correct calls. However, I'm not sure if a custom rednet event dispatcher would be a totally horrible thing. On the one side, we're of course basically duplicating old code and events and possibly making SEE's inner event loop have even more special cases, but on the other side, this would allow us to add our own custom parts to the rednet API, since it's not like rednet is doing anything magical anyways. I guess what I'm getting at is that we don't necessarily need to keep rednet as a standard, unless everyone thinks not keeping rednet as a standard is a really bad idea. A while ago I had started coding my own networking library using SEE which would do neat things like build route tables and do network discovery. It would also have been able to send out binary messages instead of just plaintext, using the current io system as the standard for doing such things. We'd be able to expand upon such a thing with connection-based sockets of course.

Sorry. You lost me there. So I think what you are suggesting is that either we can recreate the rednet loop or use getfenv to redirect function calls. I quickly implemented the latter. I don't know if this is what you meant but it seemed simplest.


local hostEnv = getfenv(rednet.host)
hostEnv.lookup = Rednet.lookup

local status, err = pcall(rednet.host, protocol, name)

hostEnv.lookup = rednet.lookup

if not status then
    throw(Exception:new(err))
end

It simply redirects the rednet.lookup function to the SEE Rednet.looup, then returns it again. I have to use pcall to prevent rednet.host breaking and never getting its lookup back. Maybe this isn't the best solution?
sci4me #87
Posted 10 May 2014 - 10:16 AM
The simplest solution may be to call getfenv on rednet.host and detour its os.pullEvent so that it makes the correct calls. However, I'm not sure if a custom rednet event dispatcher would be a totally horrible thing. On the one side, we're of course basically duplicating old code and events and possibly making SEE's inner event loop have even more special cases, but on the other side, this would allow us to add our own custom parts to the rednet API, since it's not like rednet is doing anything magical anyways. I guess what I'm getting at is that we don't necessarily need to keep rednet as a standard, unless everyone thinks not keeping rednet as a standard is a really bad idea. A while ago I had started coding my own networking library using SEE which would do neat things like build route tables and do network discovery. It would also have been able to send out binary messages instead of just plaintext, using the current io system as the standard for doing such things. We'd be able to expand upon such a thing with connection-based sockets of course.

Sorry. You lost me there. So I think what you are suggesting is that either we can recreate the rednet loop or use getfenv to redirect function calls. I quickly implemented the latter. I don't know if this is what you meant but it seemed simplest.


local hostEnv = getfenv(rednet.host)
hostEnv.lookup = Rednet.lookup

local status, err = pcall(rednet.host, protocol, name)

hostEnv.lookup = rednet.lookup

if not status then
	throw(Exception:new(err))
end

It simply redirects the rednet.lookup function to the SEE Rednet.looup, then returns it again. I have to use pcall to prevent rednet.host breaking and never getting its lookup back. Maybe this isn't the best solution?

Talking to yevano, I think we're going to re-write rednet in the see library.
SquidDev #88
Posted 10 May 2014 - 11:51 AM
Talking to yevano, I think we're going to re-write rednet in the see library.
I'm happy to code this. You guys seem to be making good progress with the Security manager. Just wondering how rednet will work though. I'm presuming Rednet.__static will spawn in a thread running an equivalent to rednet.run. Do we want compatibility with redet though?

Installer
I created an installer for SEE that pulls all files that aren't on a blacklist. I saw the GitHub issue and wrote a quick implementation. You'll probably want to change large portions of it though - it was more of a proof of concept.
Edited on 10 May 2014 - 10:34 AM
Yevano #89
Posted 10 May 2014 - 03:33 PM
Talking to yevano, I think we're going to re-write rednet in the see library.
I'm happy to code this. You guys seem to be making good progress with the Security manager. Just wondering how rednet will work though. I'm presuming Rednet.__static will spawn in a thread running an equivalent to rednet.run. Do we want compatibility with redet though?

I still have some old code that I can send you to give you an idea of how it was supposed to work. I'll make a new branch later today and you can pull it if you want. And yes, we should keep a separate library for keeping compatibility with rednet. If that code you wrote for lookup and receive works, then that should be all we need on that front I think.

Installer
I created an installer for SEE that pulls all files that aren't on a blacklist. I saw the GitHub issue and wrote a quick implementation. You'll probably want to change large portions of it though - it was more of a proof of concept.

Awesome! That's something we've needed for a while. The only problem might be the calls to the github API. Apparently a non-authenticated user can only make 60 calls/hour. I'm thinking that should be enough for someone just installing every once in a while, but I could be mistaken on how many calls are actually made.

https://developer.gi.&#46;&#46;/#rate-limiting

EDIT: Here's the new branch for the net code I had worked on a while ago. https://github.com/Yevano/see/tree/linknet
Please note it was being written a few months ago before we even had the new class system, but I did go ahead and fix any easily noticeable weirdness. Just take a look at it and see what you can gather of how it works. I'll explain more in depth soon when I get some time to myself.
Edited on 10 May 2014 - 01:48 PM
SquidDev #90
Posted 10 May 2014 - 03:58 PM
I still have some old code that I can send you to give you an idea of how it was supposed to work. I'll make a new branch later today and you can pull it if you want. And yes, we should keep a separate library for keeping compatibility with rednet. If that code you wrote for lookup and receive works, then that should be all we need on that front I think.
Great. I'll have a look. Thanks.

Awesome! That's something we've needed for a while. The only problem might be the calls to the github API. Apparently a non-authenticated user can only make 60 calls/hour. I'm thinking that should be enough for someone just installing every once in a while, but I could be mistaken on how many calls are actually made.

https://developer.gi.&#46;&#46;/#rate-limiting
The code only makes two requests - one for the sha hash, the other for the tree. Everything else is done through raw.github.com. I don't think the API call limit will apply as the calls are coming from different IPs. I might be wrong though.
Edited on 10 May 2014 - 01:59 PM
sci4me #91
Posted 10 May 2014 - 09:28 PM
I still have some old code that I can send you to give you an idea of how it was supposed to work. I'll make a new branch later today and you can pull it if you want. And yes, we should keep a separate library for keeping compatibility with rednet. If that code you wrote for lookup and receive works, then that should be all we need on that front I think.
Great. I'll have a look. Thanks.

Awesome! That's something we've needed for a while. The only problem might be the calls to the github API. Apparently a non-authenticated user can only make 60 calls/hour. I'm thinking that should be enough for someone just installing every once in a while, but I could be mistaken on how many calls are actually made.

https://developer.gi.&#46;&#46;/#rate-limiting
The code only makes two requests - one for the sha hash, the other for the tree. Everything else is done through raw.github.com. I don't think the API call limit will apply as the calls are coming from different IPs. I might be wrong though.

Nice work on the installer, I was working on that a while ago but the request limiting pissed me off too much to finish it lol.
SquidDev #92
Posted 10 May 2014 - 10:32 PM
Linknet
I'm slightly confused about this. I understand all the code it is just that I don't understand why. Why as in "Why does it do that?"; Some bits I can see as being really useful (Network discoverer) others I feel are just duplicating previous Rednet functionality.
sci4me #93
Posted 11 May 2014 - 01:01 AM
Linknet
I'm slightly confused about this. I understand all the code it is just that I don't understand why. Why as in "Why does it do that?"; Some bits I can see as being really useful (Network discoverer) others I feel are just duplicating previous Rednet functionality.

I dont think its finished yet, but i'm sure Yevano will have better explanations. I think the idea is that it is intended to be a bit higher level than rednet…
SquidDev #94
Posted 11 May 2014 - 07:52 PM
For some strange reason I chose to write some serialization code. textutils.serialize works but textutils.unserialize just gives you a standard table. It works in the same way but for two major changes:
  • The class name is stored in the __class property. This is used to find the required class.
  • You can define custom serialization and deserialization functions. These should store a table or properties required to recreate the Object. For instance String returns {['lstr']='Your string']} instead of an array. The idea is that you can save space by not dumping everything.
This was more an experiment than useful or decent code some some bits may not be perfect.
Yevano #95
Posted 11 May 2014 - 09:24 PM
Linknet
I'm slightly confused about this. I understand all the code it is just that I don't understand why. Why as in "Why does it do that?"; Some bits I can see as being really useful (Network discoverer) others I feel are just duplicating previous Rednet functionality.

Linknet is supposed to be a lower level yet more flexible version of Rednet. It's really supposed to model a bit closer to real life networking; a much simplified version of IP perhaps. Rednet is more high level with lots of abstractions, like its way of doing hostnames using broadcasting. With Linknet, messages aren't just broadcast around everywhere. The network discoverer need only broadcast itself every so often to its peers, and then when you need to send something to a remote computer, a check is done as to whether the address is mapped to a route yet. If not, the network discoverer hasn't found it yet. If yes, then the message is passed on to the next computer in the route. This continues until the message gets to the target computer. This is nice because it means that for large stable networks, all the computers aren't getting pinged every time a message is sent. Linknet might also have ports, that way we can do port blocking and such.

For some strange reason I chose to write some serialization code. textutils.serialize works but textutils.unserialize just gives you a standard table. It works in the same way but for two major changes:
  • The class name is stored in the __class property. This is used to find the required class.
  • You can define custom serialization and deserialization functions. These should store a table or properties required to recreate the Object. For instance String returns {['lstr']='Your string']} instead of an array. The idea is that you can save space by not dumping everything.
This was more an experiment than useful or decent code some some bits may not be perfect.

Hmm, we should probably be doing binary serialization, though. Maybe have a class called Serializable with methods read(InputStream) and write(OutputStream). In the end, we could still do automatic serialization I think, too.
Edited on 11 May 2014 - 07:24 PM
SquidDev #96
Posted 12 May 2014 - 07:03 PM
Linknet is supposed to be a lower level yet more flexible version of Rednet. It's really supposed to model a bit closer to real life networking; a much simplified version of IP perhaps. Rednet is more high level with lots of abstractions, like its way of doing hostnames using broadcasting. With Linknet, messages aren't just broadcast around everywhere. The network discoverer need only broadcast itself every so often to its peers, and then when you need to send something to a remote computer, a check is done as to whether the address is mapped to a route yet. If not, the network discoverer hasn't found it yet. If yes, then the message is passed on to the next computer in the route. This continues until the message gets to the target computer. This is nice because it means that for large stable networks, all the computers aren't getting pinged every time a message is sent. Linknet might also have ports, that way we can do port blocking and such.
Ah. That makes far more sense. It sounds like it could be pretty cool once it all works.

Hmm, we should probably be doing binary serialization, though. Maybe have a class called Serializable with methods read(InputStream) and write(OutputStream). In the end, we could still do automatic serialization I think, too.
I wrote it like that simply to keep backwards compatibility with textutils.serialize and also if I wanted to implement other serialization (JSON, XML, etc…) it would be simple. Binary serialization would be interesting. You could use string.dump to even serialize functions! The Lua Wiki has some interesting ways to achieve this,
Yevano #97
Posted 13 May 2014 - 09:49 PM
I wrote it like that simply to keep backwards compatibility with textutils.serialize and also if I wanted to implement other serialization (JSON, XML, etc…) it would be simple. Binary serialization would be interesting. You could use string.dump to even serialize functions! The Lua Wiki has some interesting ways to achieve this,

I have a pure Lua serializer and deserializer that I wrote a few months ago which supports all Lua types except for threads and other userdata. It supports functions and is also able to serialize self-referencing tables. On top of all that, the serialization is all binary. Maybe it will be of some use as a reference to you. https://gist.github.com/Yevano/e4a2f35cda144a9f9667
SquidDev #98
Posted 16 May 2014 - 08:57 PM
I have a pure Lua serializer and deserializer that I wrote a few months ago which supports all Lua types except for threads and other userdata. It supports functions and is also able to serialize self-referencing tables. On top of all that, the serialization is all binary. Maybe it will be of some use as a reference to you. https://gist.github....35cda144a9f9667

Thanks! I added a 'Binary' (de)serializer to my serialize branch.

Little feature request: Could @native statements have an optional as <asName> parameter. This would act a bit like Python's import statement does: –@native string.char as strchar would set strchr = string.char instead of importing it directly to string.char.
Yevano #99
Posted 17 May 2014 - 04:16 PM
I have a pure Lua serializer and deserializer that I wrote a few months ago which supports all Lua types except for threads and other userdata. It supports functions and is also able to serialize self-referencing tables. On top of all that, the serialization is all binary. Maybe it will be of some use as a reference to you. https://gist.github....35cda144a9f9667

Thanks! I added a 'Binary' (de)serializer to my serialize branch.

Little feature request: Could @native statements have an optional as <asName> parameter. This would act a bit like Python's import statement does: –@native string.char as strchar would set strchr = string.char instead of importing it directly to string.char.

Sure. We should do that for imports as well. That would actually be a solution to the same-named imports problem.

Edit: https://github.com/Y...o/see/issues/47

Looked at your serialization/deserialization stuff. Could you give a quick run-down of how it all works? Btw, I noticed your abstract classes in see.io.serialization are explicitly throwing exceptions instead of using –@abstract.
Edited on 17 May 2014 - 02:26 PM
SquidDev #100
Posted 18 May 2014 - 12:52 PM
Btw, I noticed your abstract classes in see.io.serialization are explicitly throwing exceptions instead of using –@abstract.
Fixed. Sorry, I got confused by the use of the abstract 'keyword' and so didn't use it.

Looked at your serialization/deserialization stuff. Could you give a quick run-down of how it all works?
I'll have a go. Most of this is based on the .Net way of (de)serializing data. A good description of how that works can be found here.

Serialization
A simple serializer should look like:


--@extends see.io.serialization.AbstractSerializer

function SimpleSerializer.serializeObject(object)
  if isprimitive(object) then
	-- Serialize simple objects: string, number, boolean, table and nil
  else
	-- Serialize objects: get the 'objct'
	local toSerialize = object:serialize()

	-- Give it a 'class' property (should copy the table to avoid overwriting but this is just an example)
	toSerialize['__class'] = object:getClass():getName():lstr()

	-- Serialize it as a table
	return SimpleSerializer.serializeObject(toSerialize)
  end
end
This is a simple serializer. To serialize an object it simply calls the object:serialize() function. This is defined in the Object class:

function Object:serialize()
  return self
end
However it can be overridden by other classes. This is mostly done if the class stores data which could be stored more simply. The String class stores its serialized data as a string rather than an Array:

function String:serialize()
  return {['lstr'] = self:lstr()}
end
This should always return a table. We set this table with a __class property with the class name in order to store what class this is.

Deserialization
A simple deserializer would work like:

--@extends see.io.serialization.AbstractDeserializer
function SimpleDeserializer.deserializeObject(string)
  --Deserialize data, stepping through it. If we find a table:
  if objectType == "table"
	--Get class of object
	local class = object['__class']
	-- If this is an object then clear class variable
	if class then
	  object['__class'] = nil
	  -- Get the class from the string and deserialize it
	  object = __rt:loadClassFromAny(class):deserialize(object)
	end
  end
end
In actual fact, it should 'parse inside' the object before creating the object. The Class:deserialize method is slightly more complex then serialization:

function Class:deserialize(data)
  --If over-ride function exists then call it
  local override = __rt.classTables[self]["deserialize"]
  if override ~= nil then
	return override(data)
  end
  --Else create new class
  local instance = setmetatable({ __class = self }, __rt.classMT)
  for k,v in pairs(data) do
	instance[k] = v
  end
  return instance
end
What this does is check if the class contains a 'deserialize' method. If so, then it will call that instead. Otherwise we just create a new class and copy each piece of data into the created object. Custom deserialization would look something like:

function String.deserialize(data)
  return String:new(data['lstr'])
end
Simply creating a new string class with the lua string from the serialized data.

I hope that all made sense.
Edited on 18 May 2014 - 01:44 PM