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

[API] Classy - Classes in Lua? [v1.1] - Inheritance!

Started by billysback, 18 November 2012 - 11:02 AM
billysback #1
Posted 18 November 2012 - 12:02 PM
Let's get the big question out of the way first;
This API/Program allows you to compact down projects/APIs into a file format I named ".cmp", this is compacted from a folder "project", the program then lets you import scripts from any of this .cmp files and either run them or initialize them as a new "class" and use their functions! (I kinda stole that bit from bios.lua, I hope no-one minds)

Firstly, there's the program which compacts down your project, this program is extremely simply, you just run it and follow the on-screen commands, but the project format is the most important thing:
SpoilerProjects don't have a "format" as such, you simply place any folders/files in to one folder then use this folder as you "project directory", the name of the folder without and / is required.

The output file cannot have any extension, you just put the name of the .cmp file.

NOTE INHERITANCE:
Spoilerin scripts which you are compiling you can add a line starting with "inherit" followed by a space and then the import the script is inheriting from, this basically puts all of the code from the import in to where the "inherit" line is when it compiles it.

in order to inherit a class inside the project the script is in you must first compile the project then add inherits in, it will not inherit classes from a non existent import.

I added an example inheritance in to the example further down

Updated this by the way, it now doesn't stack overflow and blank lines are ignored,
It also has a cool little percentage timer to show you how far through it is writing your file :D/>/>
(It took about 3-4 seconds to write 738 lines, but it was still a bit annoying not knowing what was happening)

Now there's the more advance bit, the "classy" bit :)/>/>
SpoilerThe classy API has only four functions:

init() - initializes the API, I recommend running this at the beginning and end of your code
import(import) - import is the import directory you are importing (will explain a bit further down)
runClass(class, vars, args) - runs the code as a script (vars and args are optional, look at os.run() to see what they do)
newClass(class) - creates a new instance of the class, returns it as if it were a table

Import explained:
Spoileran import is a string, but formatted in a certain way.
The import is split by a "." symbol,
the first part is the name of the .cmp file,
the last part is the name of the script
and everything in-between is the folders in the project.

So if I had a script in my "project" folder under "project/billy/general/main" and had compacted "project" to "org" then to import "main" my import would be:

classy.import("org.billy.general.main")

NOTE: imports also have a return table, the table is either nil (import failed) or it contains two values:
{chunk, temp_dir}
chunk is a table containing all the lines of the import, temp_dir is the temporary file of the script, by getting the chunk import can be used to also get the lines of files inside your .cmp file :D/>/>/>

the obvious downside to this is that your scripts/files cannot have an extension, however most scripts on CC don't use extensions anyway so it should be fine :D/>/>

then to run this I would do:

classy.runClass("main")

I can only have one instance of "main" imported at once, this means that I can have as many "mains" in my project as once by every time I wish to use a different one I must import the new one.

Downloads:
Spoilerclscmp (compiler):
http://pastebin.com/a1BQMMLi
classy (API):
http://pastebin.com/tKB4411n

Example:
SpoilerI have a folder called "example", this contains a file called "main" and a folder called "org"
In org there's a file called "helloworld" and a folder called "net"
In net there's a file called "test"
So the file tree would look like this:

example
  main
  org
	helloworld
	net
	  test

Main, Helloworld and Test contain these bits of code:
SpoilerMain:
Spoiler

function printTest2(name)
	print("PRINTING: "..name)
end

function printTest()
	print("Ran loaded API!")
end
Helloworld:
Spoiler

local line = "HELLO WORLD"
print(line)
Test:
Spoiler

inherit comp.org.helloworld

classy.import("comp.main")
local main = classy.newClass("main")

main.printTest()
main.printTest2("BILLY")

The resulting compile file looks like this:
Spoiler

++comp.main

function printTest2(name)
	print("PRINTING: "..name)
end

function printTest()
	print("Ran loaded API!")
end
--comp.main
++comp.org.helloworld

local line = "HELLO WORLD"
print(line)
--comp.org.helloworld
++comp.org.net.test

local line = "HELLO WORLD"
print(line)

classy.import("comp.main")
local main = classy.newClass("main")

main.printTest()
main.printTest2("BILLY")
--comp.org.net.test
(Notice the inherited code in "comp.org.net.test")

Now, if we want to run the "test" program and "helloworld" we would do:

classy.init()
classy.import("comp.org.net.test")
classy.import("comp.org.helloworld")
classy.runClass("test")
classy.runClass("helloworld")
classy.init()

And that would be it, running those classes would output:

Hello world
Ran loaded API
PRINTING: BILLY
Hello world



NOTE:
this uses a folder in your computer called "temp", any files in temp will get deleted after you init(), this is because these files are temporary, for use by both runClass() and newClass()

Thanks!
tommyroyall #2
Posted 18 November 2012 - 01:49 PM
This is awesome man xD.
Sammich Lord #3
Posted 18 November 2012 - 01:57 PM
It is funny how I see this post after I just spent a hour in C# coding shit.
tommyroyall #4
Posted 18 November 2012 - 02:29 PM
Any example code? Also, inheritance?
billysback #5
Posted 18 November 2012 - 09:55 PM
Added an example, I might work on inheritance but I'm not sure how it would work…
something like in a script you write "inherit <import>" on it's own line then when it compiles the script it changes that in to the code that the import contains…

That would mean that inheriting only works on already-compiled projects however.
billysback #6
Posted 18 November 2012 - 10:43 PM
UPDATE: added inheritance, look under first tab about the compiler
Sebra #7
Posted 19 November 2012 - 03:45 AM
Too complicate and unneeded in my humble opinion.
Sorry. May be I'm just unable to understand.
billysback #8
Posted 19 November 2012 - 03:49 AM
It's pretty simple if I'm honest;
but if you don't want to use it then you don't want to use it, I'm not gonna ram it down your throat :)/>/>
Sebra #9
Posted 19 November 2012 - 04:06 AM
I did not understand why you need a compiler. Do you need many similar classes? Do you need it to copy some code from one class to another? Are you make anything complicate enough to use this?
billysback #10
Posted 19 November 2012 - 04:18 AM
The compiler is so when you wish to export your program others can use it by simply downloading file, but you can separate your code in to multiple files and folders, this means far cleaner code.

The inheritance is not necessary but was requested, other languages (which this is trying to imitate) use inheritance as well.
What do you mean by "Do you need many similar classes"?

For the me making anything complicated enough to use this, the response is no, not at the moment. However if I were writing CGE or Shipper right now I would have almost certainly used this, it adds little complication for the user and makes things much cleaner for the programmer, the only thing the user has to do is download the ".cmp" file, have classy installed then make a small program (which I may even supply) with the following lines of code:

classy.init()
classy.import("shipper.main")
classy.runClass("main")
classy.init()

done, the "main" script in the shipper.cmp would be the script which initializes and runs the program, the "main" script…
billysback #11
Posted 19 November 2012 - 11:08 AM
Updated the compiler,
It was overflowing for really big files, I also added a percentage done to show how far through it is writing the output file
(It took about 3-4 seconds to write 738 lines)

EDIT:
and, just so you know, I am working on something which can use this to it's full extent.
and so far, it has been very fun to code :)/>/>
It actually feels like I'm making and using classes, The way it compacts everything in to a single file also reminds me of .jar files and .love files, I created this basically for the fun of it, but I am actually seeing the practicalities of it.
(I'm making a mario-esq game, this has helped me make the game's engine, graphical and physical, very easy to code and sort out, I'll post the code once I've got the prototype working :D/>/>)
ETHANATOR360 #12
Posted 20 November 2012 - 03:02 PM
so this is like the class system in java?
billysback #13
Posted 20 November 2012 - 08:41 PM
A little bit, once my game's done you can take a look at what I did with it :(/>/>