Scripting Language Genesis

Started by
116 comments, last by cmp 19 years, 4 months ago
For a language that is (also) called voodoo. Voodoo is a very flexable concept at the moment. Even though I have done quite a bit of work on it, I am willing to drop the whole thing if someone has a better idea. In fact I am probably too willing, I have rewritten different versions of voodoo about 4 times in total - I always think of a better way to do it. So although I say "Is going to be" I really mean "the current idea is". Voodoo is going to be object oriented with a very flexible source file syntax. I basically have had a look at quite a few languages, and I want to take the best out of them, but still keep it simple. I like object oriented because it is possible to use design patterns, and they are cool. I also have had a look at groovy and if it didn't just run on the java virtual machine I would probably use it. The purpose of this language is to embed it into a game engine. It would have all the meta level programming, and all the actual algorithms would be implemented in C++. Voodoo would be good for abstract structures and objects, C++ is good for optimised code. This is a list of cool things I would like to use in Voodoo. Tabbed based structure (instead of { }, like (I think) python?) i.e. no semi-colons Closures Pure Object Oriented (no natives) Operator Overloading (just for data objects - vectors, other types of numbers) Native syntax for lists (maps and ranges also possible) I have written a Lexer and a Parser for a version of voodoo that had C like code syntax, and I have written tree manipulation code (using the visitor design pattern). The aim of the language is to have a strongly typed (think - compile time errors instead of runtime errors), object oriented, easy to write, easily embedded language. Any really cool things you would like to see in a language? Any Bad Programmer no Twinkie things I should look out for? The current ideas / examples. [Edited by - umbrae on November 1, 2004 9:16:50 AM]
Advertisement
Example code of the old format (C style code blocks) still not sure whether to use tabbed code blocks or c - style code blocks

The format for a class is

class <name of class> : <parent class> : <interfaces it uses> : <packages it can see>

The format for a interface is

interface <name of interface> : <interfaces it uses> : <packages it can see>

Objects can talk about classes and interfaces as long as they can see them. They can see them by being in the same package as them, 'importing' them in the <packages it can see> field, the objects being in any packages up the tree.

eg. an object in the root package will be seen by every single other object.

package a{    package b    {        class c : super_class : interface_uses another_interface : package.can.seeinto        {            // a method prototype            - public void "-=" method_name(int i, bool j);                        // a property            + private integer a_property;                        // knows that it is a decimal (can only have integer, decimal, boolean and string constants            ~ private a_constant = 1.0;        }    }    package b    {        class c        {            - public void method_name(int i, bool j)            {                integer i = 0;                do_something(i);                for (integer j = 1; j < 5; j++)                {                    print(i + " " + j);                }            }        }    }}


Could do this

package a    package b        class c : super_class : interface_uses another_interface : package.can.seeinto            // a method prototype            - public void "-=" method_name(int i, bool j)                        // a property            + private integer a_property                        // knows that it is a decimal (can only have integer, decimal, boolean and string constants            ~ private a_constant = 1.0    package b        class c            - public void method_name(int i, bool j)                integer i = 0                do_something(i)                // usage of range type                for integer j = 1..5                    print(i + " " + j)


It just means that the tabulation of the code is forced, some people won't like that, but don't most people tab anyway?

Could also use

a.b class : super_class : interface_uses another_interface : package.can.seeinto    // a method prototype    - public void "-=" method_name(int i, bool j)        // a property    + private integer a_property        // knows that it is a decimal (can only have integer, decimal, boolean and string constants    ~ private a_constant = 1.0


So as not use so many tabs

Any ideas?

[Edited by - umbrae on November 1, 2004 9:25:14 AM]
By the way...

a "-" in front of a property or method means that the method or property belongs to the instance object, a "+" means that the method or property belongs to the super object, a "~" means that the object is a constant and doesn't need a type (the type is guessed from the value). There is only one super object per class, it could be though of as the actual class itself. You ask it to create instances for you. eg.

integer i = integer.alloc().init(5)


Although for the basic objects (and not so basic?) there is built in syntax for their creation.

integer i = integer.alloc().init(5)integer i = 5string s = string.alloc().init("Hello")string s = "Hello"integer[] a = integer[].alloc().init(3, 4, 5)integer[] a = [3, 4, 5]range r = range.alloc().init(1, 5)range r = 1..5


The super objects allow you to include library like methods that don't necessarily act on an object to still be included in the object oriented paradigm.

A Singleton design pattern can easily be implemented by just having a super class, all methods are super methods, no instances can be made.
Sorry about the multiple posts, just lots of ideas.

Just an example of a possible setup of objects, dynamics and renderers

The 3d package knows nothing about rendering and dynamics, all it knows is that it can ask a renderer to render itself when asked. The rendering package knows about the 3d package (duh) but doesn't know about the dynamics package.

The simulators don't even know about the 3d models, only the new dynamic objects.

Also you can leave out the ":" if there is nothing past the last identifier (eg class a : b : : can be written as class a : b)

package 3d    interface renderable        - void renderer_visit (3d_renderer r)        interface 3d_renderer        - void render_cube (cube c)        - void render_sphere (sphere s)    class 3d_object :: renderable        - vector_3d position        - quaternion rotation    class cube : 3d_object        - vector_3d dimensions        - void renderer_visit (3d_renderer r)            r.render_cube (self)        class sphere :: 3d_object        - decimal radius        - void renderer_visit (3d_renderer r)            r.render_sphere (self)package renderer    class open_gl_renderer :: 3d_renderer : 3d        - void render_cube (cube c)            // cube drawing code here                - void render_sphere (sphere s)            // sphere drawing here        class dx_renderer :: 3d_renderer : 3d        - void render_cube (cube c)            // cube drawing code here                - void render_sphere (sphere s)            // sphere drawing herepackage dynamics    interface dynamic_object        - void simulator_visit (simulator s)        class dynamic_cube : cube : dynamic_object : 3d        - void simulator_visit (simulator s)            s.simulate_cube(self)        class dynamic_sphere : sphere : dynamic_object : 3d        - void simulator_visit (simulator s)            s.simulate_sphere(self)        interface simulator        - void simulate_cube (dynamic_cube c)        - void simulate_sphere (dynamic_sphere c)        class ode_simulator :: simulator        - void simulate_cube (dynamic_cube c)            // crazy equation here                    - void simulate_sphere (dynamic_sphere c)            // crazy equation here        class havok_simulator :: simulator        - void simulate_cube (dynamic_cube c)            // crazy equation here                    - void simulate_sphere (dynamic_sphere c)            // crazy equation here
hi,
i have a very similar project, but instead on just concentrate on scripting i plan to make it compileable nativly. each sourcefile should be processed into a xml file, wich itself is than transformed into the target language.
at this point i have written some xslt stylesheets wich transform the xml code into c++ code. but due to the easy parsing of xml it shouldn't be such a problem to use the xml code directly.
currently i have to implement the kernel library. sth. similar to c++'s stl, but some features have to be cut out, so it can be compiled for all target languages.
the language itself should have the following features:
* classes and namespaces (pure oop, so no functions and vars outside of a class)
* genericity (templates)
* lamda functions (i think these are the same as closures)
* garbage collection (at this point simple refernce counting)

there are some othere features planned, but at this point i don't know if i ever will implement them - feature like automatic remote code execution (like corba), automatic wrapping of scripting languages, easy threading (the eifel way, just via one keyword).

the structure should resemble c++ without semicola (like i said not implemented at this point).

if you are interested we could conside merging both projects.

and btw. there's an edit button ;) and i think you're language isn't a functional one, since it looks very declarative to me.
Quote:hi,
i have a very similar project, but instead on just concentrate on scripting i plan to make it compileable nativly. each sourcefile should be processed into a xml file, wich itself is than transformed into the target language.


Very cool idea! In fact that would be so damn cool that I would use it all the time.

I really want the scripting language part, but we could use the same language. That way you could choose either to convert the code to the target language or generate bytecode. Scripting languages are cool because you can load code from any source, any platform - which is not possible to do with C++ and other compiled languages.

Quote:at this point i have written some xslt stylesheets wich transform the xml code into c++ code. but due to the easy parsing of xml it shouldn't be such a problem to use the xml code directly.


I still think that idea is great, so this basically means that I can program in a cool language, and have it converted to any supported language?

Quote:currently i have to implement the kernel library. sth. similar to c++'s stl, but some features have to be cut out, so it can be compiled for all target languages.


I also have to implement a few things, but they are mostly tied to the virtual machine (lists / maps / ranges).

Quote:the language itself should have the following features:
* classes and namespaces (pure oop, so no functions and vars outside of a class)


Hooray!

Packages, Namespaces - same things different names.

Quote:* genericity (templates)


Not as sure if this is needed, it is really good in C++ only because it is not a pure oop language, it is needed to make class based data structures not casting from void *. It is really only needed for data structures - I was thinking about having an extra "type" of object that would only be used to store data, and it could be generic. Even java has this problem, you have to cast from object to whatever type of object you put in the collection.

Going to at least have built in lists - they are generic. Can have other generics.

Quote:* lamda functions (i think these are the same as closures)


I think they are similar, it depends if they can exist past the scope of the method. I'm not sure if I would like the 'mini functions' to exist beyond the scope of a function bacause there would be two types of closures, ones that can reference external variables, and ones that cannot.

The Groovy Wiki goes into more depth.

Quote:* garbage collection (at this point simple refernce counting)


I really like Objective-C's garbage collection, which is basically reference counting.

An object is created with a reference count of 1. The object that created it 'references' it. Another object can get the object and say that it also references it by
object.retain()
. When an object is finished with another object it releases it
object.release()
. This way, if you temporally want an object but don't want to keep it then you don't retain it.

Objects returned from methods are "autoreleased" which means if an object is returned like this:

return object.autorelease()


At the end of the method it is returning to, the object will be checked if it was retained during that method, if it wasn't then it is deleted.

It is also possible to just autorelease an object during the method, at the end it will be deleted if nothing has retained it.

Quote:there are some othere features planned, but at this point i don't know if i ever will implement them - feature like automatic remote code execution (like corba), automatic wrapping of scripting languages, easy threading (the eifel way, just via one keyword).


It is hard to know what to build into the language, and what to implement with objects. I think simplicity matters, I personally don't like to be inundated with different keywords that clutter up a language, most of the keywords don't get used very often (volitile etc).

Quote:the structure should resemble c++ without semicola (like i said not implemented at this point).


Groovy is quite cool in this respect, it doesn't care if you use semicolons or not.

Quote:if you are interested we could conside merging both projects.


We would have to sort some things out, but it sounds like a good idea. As I think I have said, I've done a bit of work on the parsing side of things, and it sounds like you have done a bit of work on the other side of things (xslt is greek to me) so we could work together.

Quote:and btw. there's an edit button ;)


Yeah, I normally edit my posts a lot - these posts seemed to be individual points so I posted them separately.

Quote:and i think you're language isn't a functional one, since it looks very declarative to me.


I was meaning functional as "Designed for or adapted to a particular function or use" but you are right it's not functional as such, I probably should have used a different word.

[Edited by - umbrae on November 2, 2004 11:12:50 PM]
This is sort of like my language...

Source code (Agamemnon)
Button = Form:Button Event: Button.Onclick Fire="call somesub"Sub somesub    Static:Integer Subcalled    Subcalled = Subcalled + 1 'I know, i need to do the i++'s    Eventsend:Msgbox "This is my box"end subsum


Compiled source

Soruce (asm)
EXT MEMRESIZE, 13 MSET 0, 0MSET 1,  104 MSET 2, 105 MSET 3, 115 MSET 4, 32 MSET 5, 105 MSET 6, 115 MSET 7, 32 MSET 8, 109 MSET 9, 121 MSET 10, 32 MSET 11, 98 MSET 12, 111 MSET 13, 120 EXT ADDFORM, 0EXT ADDBUTTON, 0REGSET Ax, 22REGSET Bx, 100REGSET Cx, 55EXT BUTTONSET, 0INT BUTTON, 0, 22REGSET ax, 00MEMGET 00, axADD ax, 1MSMSET ax, 00EXT MSGBOX, 01


A very simple language.
vm has registers, and a resizable amount of memory (up to a point)
Nice little (very flexible), parser. All very nice...

Your idea of an oop language would be nice...

You should consider making this a compiled language for a vm (or actual computer), it makes it easier to make, port (hay, you've got less to rewrite!), and just easier to build.

Edit:
Been thinking, you should really have macros in your language, there easy to make (for you), and really handy (your language is very verbose).

Ok, heres an idea for you...

You make the functions, variables, ect. seperate from the objects.

Egsample:

Function1 {}

Function2 {}

Function3 {}

Var1 = 0
Var2 = 9
Var3 = 21
//Above not corect syntax for egsample, below is.
Object Obj::
Functions import::Function1, Function2, Function 3
Variables import::Var1, Var2, Var3
Object O2::
Function import::Function1
Variables import::Var1
Obj
Var1 = 21
Var2 = 42
var3 = 32
function1
O2
Var1 = 42
var2 = 9
var3 = 425

// Please note that O2.var1 != Obj.var1, and O2.function1 != Obj.function1 (different instances)

HTH.
From,
Nice coder

[Edited by - Nice Coder on November 3, 2004 12:52:10 AM]
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Thanks for the feedback.

Nice language.
Looks similar to Visual Basic in syntax.
I like your scope syntax. (Static:)


The whole idea is to make a virtual machine and incorporate it into a game engine. At the moment I just want to get the language sorted.

A virtual machine because:

Cross platform bytecode
Higher level programming (meta)
Can optimise bits by implementing in C++
Dynamic inclusion of code (code imbedded into a character file to control walking / actions etc.)
Can extend a game without re-compilation

Thanks again
Quote:Nice Coder
Been thinking, you should really have macros in your language, there easy to make (for you), and really handy (your language is very verbose).


This is similar to the closure idea - little methods that can be defined on the fly

I already want to have a "real" object orientated structure.

type    - method        - method(integer.add(integer i))        - etc.    - class        - super(integer)        - super(decimal)        - super(boolean)        - super(string)    - object        - integer        - decimal        - boolean        - string



This means that it is possible to have a reference to a method, and call it using some sort of syntax that I haven't worked out yet.

It will also be able to have a reference to a class, and ask it to make a new instance of that type - even though you don't know what type it is (has to subclass from an object right?). I was also thinking about the possibly to have a reference to an object's super (integer.alloc()) but would have to use some different syntax to mean that the object container we are defining is for the object's super - not the instance.

integer i = integer.alloc().init()


super(integer) c = integer


not

integer c = integer


I can see that it wouldn't be that hard to make the functions and properties separately, would this happen at compile time or run time?

If runtime then this would put a lot of strain on what I was envisaging, if the size of a class (number of methods and properties) can change at runtime then I am screwed. It would be possible, but how I was going to deal with function calls (direct offsets) in the linked virtual machine would not work, and each function call would have to be looked up - which would use up a lot more cycles than just following an offset.

If compile-time then cool.
Quote:Original post by umbrae
Quote:Nice Coder
Been thinking, you should really have macros in your language, there easy to make (for you), and really handy (your language is very verbose).


This is similar to the closure idea - little methods that can be defined on the fly

I already want to have a "real" object orientated structure.

type    - method        - method(integer.add(integer i))        - etc.    - class        - super(integer)        - super(decimal)        - super(boolean)        - super(string)    - object        - integer        - decimal        - boolean        - string



This means that it is possible to have a reference to a method, and call it using some sort of syntax that I haven't worked out yet.

It will also be able to have a reference to a class, and ask it to make a new instance of that type - even though you don't know what type it is (has to subclass from an object right?). I was also thinking about the possibly to have a reference to an object's super (integer.alloc()) but would have to use some different syntax to mean that the object container we are defining is for the object's super - not the instance.

integer i = integer.alloc().init()


super(integer) c = integer


not

integer c = integer


I can see that it wouldn't be that hard to make the functions and properties separately, would this happen at compile time or run time?

If runtime then this would put a lot of strain on what I was envisaging, if the size of a class (number of methods and properties) can change at runtime then I am screwed. It would be possible, but how I was going to deal with function calls (direct offsets) in the linked virtual machine would not work, and each function call would have to be looked up - which would use up a lot more cycles than just following an offset.

If compile-time then cool.


1. macros have many, many uses.
Look at this.

Macro EQ ==Macro NEQ !=Macro Set =Macro isint(X) (cint(x) eq x)Macro issquare(x) isint((z set sqr(y)))Macro msgbox(x) eventsend:Msgbox(cstring(x))Dox = x + 1if issquare(x)    Msgbox xend ifloop

Now look how simple that is!


Also try to make a simple vm first, its less then an hours work to make a real good one, and it'll help you later. (when your trying to code for something which doesn't exist, it is Not Nice.)


Most of it would happen at compile time.
Sometimes it would happen at run-time (but rarely would you need to). Doing so is quite easy,
Get code for function,
Allocate new memory (for each var in function)
Copy function to new spot on the object array
Change vars in function.

All in all quite a fast job.

Also, What i try and do, is keep a smallish array (or vector, in c++), which contains the jump points. These are points where your code should go to.

Something like
jmp GUID_OF_FUNCTION, GUID_OF_OBJECT, Line number

-1 (or NULL) should be used to signify My. (current object).

If your not using guids, then shame on you!

With lists,
Make it a data type, and make the list, a list of type datatype.
That would allow you to have lists of lists of lists of lists, ect.

maybe have a few methods in list, like concatinate, sort, split-at, ect. to make things easier.

Have namespaces, and allow them to be changed at runtime (which would make things a lot easier).

Function pointers! (you do not know how good these are, until your using a language which doesn't support them!)

Also, it would be nice to have a flexable grammer and/or reprogrammable grammer. (currently my parser, (with a bit of extra taggery) will accept C style for loops, basic style for loops, and with a bit of persuading, probably a few more types too!)

Maybe something like a grammer define tag?

GRAMMER ; NEWLINE

All in all, Great language!

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.

This topic is closed to new replies.

Advertisement