Major Javascript Syntax/oo Architechtural Overhaul

tliebeck's picture

Hi all,

I'm strongly considering changing the syntax / OO architecture used in the Echo3 client-side JavaScript. We're currently using the traditional approach:

Alpha = new function(x, y) {
    Beta.call(this, x);  // Call super constructor.
    this.y = y;
};

Alpha.prototype = EchoCore.derive(Beta);

Alpha.SOME_CONSTANT = 5;

Alpha.aClassMethod = fucntion() {
    alert("this is a class method");
};

Alpha.prototype.doSomething = function() {
    alert(this.x);
};

There's another approach in fairly common use today that I think looks simpler and might be easier to maintain. It's based around a tiny library called Inheritance.js by Alex Arnell:

http://twologic.com/projects/inheritance/

I added something based on this concept to Echo3's Core.js and so far like the result. For starters, the syntax is much cleaner:

Alpha = EchoCore.extend(Beta, {

    global: {
        SOME_CONSTANT: 5,

        aClassMethod: function() {
            alert("this is a class method");
        }
    },

    // this is the constructor
    initialize: function(x, y) {
        this.parent(x);
        this.y = y;
    },

    doSomething: function {
        alert(this.x);
    }
});

There are a few advantages to this approach beyond just the pretty syntax:

  • You can do ruby-style mixins (add fragments of code to multiple classes)...note that I don't have this ported to the Core.js version yet.
  • You can call this.parent() to invoke superconstructors/ancestor methods
  • It does away with the issue of 'dual purpose' object constructors...where the constructor needs to be able to create a prototype instance for a derived class as well as an actual instance. We currently 'solve' this using EchoCore.derive(), but I've always kind of hated that implementation, and it doesn't solve the problem completely, you still have to be a bit careful.
On the negative side, we have:
  • It doesn't seem to work with JSDoc yet. We might need to modify JSDoc to pull this off. Perhaps there's another tool or modified version already out there. Or perhaps someone here is a PERL programmer? :D
  • It's more architecture and you might not find a description of how it works in a JS book. We'll comment the hell out of it to fix the latter problem. Unlike prototype.js and other JS extension though, we DO NOT modify any built-in objects (Echo3 still modifies, in sum-total, ZERO JS objects that don't belong to it).
To see my implementation, check out the proposed Core.js in the wiki: http://wiki.nextapp.com/echowiki/Echo3Clie...eSourceProposed

Versus the old one: http://wiki.nextapp.com/echowiki/Echo3ClientScriptCoreSource

I've yet to test it for performance, but I think it should be good. Obviously a showstopper if its not. Once I finish porting Application.js and maybe WebCore.js I'll run some tests.

Oh and one more negative....changing code syntax like this is hell.

[/][/]
mjablonski's picture

Tod Liebeck wrote:

I'm strongly considering changing the syntax / OO architecture used in the Echo3 client-side JavaScript...

Looks just great to me. The syntax is so much easier to read and understand.

I've just dropped the new Core.js into JSEclipse (a very nice JavaScriptEditor for Eclipse) to see if it can handle it properly... and it works very well. The JavaScript-Outline is even better than with the old coding style. It's nearly perfect, so navigating JavaScript-code becomes fun...:)

Cheers, Maik

tliebeck's picture

mjablonski wrote:

Looks just great to me. The syntax is so much easier to read and understand.

I've just dropped the new Core.js into JSEclipse (a very nice JavaScriptEditor for Eclipse) to see if it can handle it properly... and it works very well. The JavaScript-Outline is even better than with the old coding style. It's nearly perfect, so navigating JavaScript-code becomes fun...:)

Cheers, Maik

I'll have to give that product another try. Right now I have the Java editor associated with JS files :lol: .... it's starting to have problems due to the new syntax given that huge blocks of code are now effectively one statement. I'm only using this because it seemed to be the only stable editor I could find with some syntax highlighting for JS.

tliebeck's picture

Well, this is a bit disturbing.... a certain web browser (and all versions of it) destroys toString() and valueOf() implementations declared in objects. For example:

var test = {

a: "foo",
b: function() { return 1337 },
toString: function() { return "Hello!" }
};

The toString method will immediately cease to exist.

Anyone want to guess what browser? Hint: it begins with an "i" and ends with an "e".

Workaround at present is to allow "$" to precede function names and automatically lop them off when creating a class using EchoCore.Extend. Looked at prototype, who is using this same declaration strategy...no indication they're even aware of it.

Nadir's picture

Tod Liebeck wrote:

I'll have to give that product another try. Right now I have the Java editor associated with JS files :lol: .... it's starting to have problems due to the new syntax given that huge blocks of code are now effectively one statement. I'm only using this because it seemed to be the only stable editor I could find with some syntax highlighting for JS.

What's wrong with the javascript editor included with Eclipse's WST ?

Tristan

tliebeck's picture

The Echo3 core JS has now been migrated to this new architecture/style of declaration. I wound up pulling the clever closure around overridden methods that enabled you to invoke this.parent() however, due to performance considerations. IE appeared to slow down by 20% as a result. As such constructors are now invoked similar to the previous style, e.g.:

/**
 * @class Label component.
 */
EchoApp.Label = EchoCore.extend(EchoApp.Component, {

    globalInitialize: function() {
        EchoApp.ComponentFactory.registerType("Label", this);
    },

    componentType: "Label",

    /**
     * Creates a new Label.
     * 
     * @constructor
     * @base EchoApp.Component
     */
    initialize: function(properties) {
        EchoApp.Component.prototype.initialize.call(this, properties);
    }
});

I additionally added "global" and "globalInitialize" properties that are specially interpreted to allow for declarations of class variables and static initializers respectively.

I do want to add the "mixins" stuff in Alex Arnell's implementation, but have not done so yet. The initial commit is in Subversion v708.

Just a quick "devils advocate" question here.

<start>

Have you considered the alienating effect you are imposing on users/developers - who expect "industry standard" JS rather than some esoteric syntax that will be uncommon for 98% of the JS developers out there?

</start>

I havent coded JS in ages myself - but I do not immidiately recognize the syntax, and would much rather (as a casual JS developer/hardcode java developer) have industry standard OO code.

For me personally chances are, that I'll never will have to dig into your JS code. So not sure it matters. I can see the problem though

Thomas Lund wrote:

Just a quick "devils advocate" question here.

<start>

Have you considered the alienating effect you are imposing on users/developers - who expect "industry standard" JS rather than some esoteric syntax that will be uncommon for 98% of the JS developers out there?

</start>

I havent coded JS in ages myself - but I do not immidiately recognize the syntax, and would much rather (as a casual JS developer/hardcode java developer) have industry standard OO code.

For me personally chances are, that I'll never will have to dig into your JS code. So not sure it matters. I can see the problem though

I wouldn't use JavaScript and "industry standard code" together in one sentence. The fact is that JS is like most other scripting languages, it is possible to write code no one will understand (well, not as much as in PERL). :) I'm no JS expert, but I am reading the Rhino book currently and read up on some of the various APIs out there. As far as I know, there is no such thing as standard code practice in JS. If JS lets you do it, and you're creative, you can do it. That's the power and curse of JS. What Tod is doing here is JS used in a certain way by a certain API. I see no issue with it. If he did it another way, you'd have to learn that too.

Oro.

tliebeck's picture

Thomas Lund wrote:

Just a quick "devils advocate" question here.

<start>

Have you considered the alienating effect you are imposing on users/developers - who expect "industry standard" JS rather than some esoteric syntax that will be uncommon for 98% of the JS developers out there?

</start>

I havent coded JS in ages myself - but I do not immidiately recognize the syntax, and would much rather (as a casual JS developer/hardcode java developer) have industry standard OO code.

For me personally chances are, that I'll never will have to dig into your JS code. So not sure it matters. I can see the problem though

I am trying to keep it fairly simple and am concerned about this...don't want to go too far off the deep end with the JavaScript. It shouldn't take more than 5 minutes to get a hang of the coding style (I'll be putting a wiki page up).

The one critical item is the constructor design using 'initialize'...if we do things the "plain" way, a constructor has to serve two purposes (when a class will be derived) that can often create subtle bugs. Working around this issue manually in each case it can add a fair amount of cruft to code.

Additionally I believe a fair number of frameworks are using this same syntax/design to one extent or another. It's actually somewhat scaled back in Echo3 for performance reasons.

When possible though, I'm a big fan of sticking to the basics.

mjablonski's picture

Tod Liebeck wrote:

I am trying to keep it fairly simple and am concerned about this...don't want to go too far off the deep end with the JavaScript. It shouldn't take more than 5 minutes to get a hang of the coding style (I'll be putting a wiki page up).

I really appreciate the "new" coding style. It makes things easy to understand right from the start.

I've ported a simple custom component from Echo3-old-style to the new style yesterday and I'm very satisfied with the readability of the code. When I compare the new code to the coding needed for the same custom component in Echo2 I'm even more satisfied.

I'm feeling that Tod's ongoing quest for the most well designed code-base makes a huge step forward with the latest move.

Cheers, Maik

tliebeck's picture

mjablonski wrote:

I'm feeling that Tod's ongoing quest for the most well designed code-base makes a huge step forward with the latest move.

Thanks, makes my day to hear stuff like that.

One more thing I wanted to elaborate on though...the "dual purpose" constructor issue and the pitfalls you one can encounter with it. In normal JS, where we use an instance of an object as the prototype, objects referenced by the constructor are shared by all instances. For example:

<html>
<head>
<script>
TestObject = function() {
    this.instanceVariable = [];
};

DerivedObject = function() {

}

DerivedObject.prototype = new TestObject();

DerivedObject.prototype.toString = function() {
    return "instanceVariable: " + this.instanceVariable;
};

var d1 = new DerivedObject();
d1.instanceVariable.push("foo");

var d2 = new DerivedObject();
alert(d2);

</script>
</head>
<body>

</body>
</html>

(Included the HTML so you can cut/paste into a file and run in your browser if you like.)

The above code raises an alert that says "instanceVariable: foo", as the "instanceVariable" array is shared by all instances of DerivedObject. With the initialize method, we eliminate this issue.

It's worth noting that such issues are also eliminated by invoking the super-constructor...but accidentally omitting such a call can be tragic.

On another note, I'm considering getting rid of the term "initialize". It's easy to typo, has a "z" in it which will make the British angry, and sounds like a life cycle method. I'm thinking about "construct". "constructor" is of course reserved. The static initializer method, "globalInitialize" would become "globalConstruct".

tliebeck's picture

Well, I've gone and changed quite a number of things again:

EchoCore is now Core.
EchoWebCore is now WebCore.

Neither of these namespaces have any ties to "Echo", they're generic JavaScript stuff. May even make sense to move these into a separate project at some point in case people want to use them outside of Echo...perhaps with a more liberal license as well.

Additionally I've updated the naming conventions:

$construct - constructor (was initialize)
$static - static class variables (was global)
$load - static initializer/constructor (was staticInitialize)
$include - mixins (was include)
$abstract - abstract methods/flag indicating class is abstract (not concrete) (was briefly "virtual").
$toString - toString method, because IE eats it if you call it toString (unchanged from previous)
$valueOf - valueOf method, same reason as above (unchanged from previous).

I haven't previously mentioned $abstract here...its pretty simple and doesn't actually do anything at run-time, only at library-install-time. The Core.extend() method simply verifies that all abstract methods from parent classes are present, and throws an exception if they are not.

A class is deemed to be abstract if its '$abstract' property evaluates to true. Here's an example that provides abstract methods.

EchoRender.ComponentSync = Core.extend({ 

    /**
     * Creates a new copmonent synchronization peer.
     * @constructor
     */
    $construct: function() { },
        
    $abstract: {
        renderAdd: function(update, parentElement) { },
        
        renderDispose: function(update) { },
        
        /**
         * @return true if this invocation has re-rendered all child components, false otherwise
         */
        renderUpdate: function(update) { }
    }
});

And here's one that is just marked as abstract (because it extends an abstract class and does not provide implementations for all methods):

/**
 * Component rendering peer: TextComponent
 */
EchoAppRender.TextComponentSync = Core.extend(EchoRender.ComponentSync, {
    
    $abstract: true,
    
    $static: {
        _supportedPartialProperties: ["text"]
    },
    
    _renderStyle: function() {
        EchoAppRender.Border.render(this.component.getRenderProperty("border"), this._textComponentElement);
        EchoAppRender.Color.renderFB(this.component, this._textComponentElement);
        EchoAppRender.Font.renderComponentProperty(this.component, "font", null, this._textComponentElement);
        EchoAppRender.Insets.renderComponentProperty(this.component, "insets", null, this._textComponentElement, "padding");
:
:
:

mjablonski's picture

Hi Tod,

Tod Liebeck wrote:
Well, I've gone and changed quite a number of things again:

EchoCore is now Core.
EchoWebCore is now WebCore.

Neither of these namespaces have any ties to "Echo", they're generic JavaScript stuff. May even make sense to move these into a separate project at some point in case people want to use them outside of Echo...perhaps with a more liberal license as well.

I'm not sure about this...Core and WebCore are very generic names, so if you want to use Core / WebCore with other JavaScript-projects, there's a likely chance of a namespace clash. So the old naming was far better with the Echo-prefixing... IMHO it is a good practice to introduce only one namespace in JavaScript-library. Makes lots of things easier to glue together.

Tod Liebeck wrote:

Additionally I've updated the naming conventions: ...

These are very good renamings. I really like them...

Cheers, Maik

tliebeck's picture

mjablonski wrote:

I'm not sure about this...Core and WebCore are very generic names, so if you want to use Core / WebCore with other JavaScript-projects, there's a likely chance of a namespace clash. So the old naming was far better with the Echo-prefixing... IMHO it is a good practice to introduce only one namespace in JavaScript-library. Makes lots of things easier to glue together.

I totally hear you on this...if we name it EchoCore/EchoWebCore we're guaranteed good namespacing...but the code just looks so much cleaner without the leading "Echo" on those. I'm speaking mostly with regard to "Core" here, WebCore could go back to being EchoWebCore without too much complaint from me, but again I'm curious if it might be a good idea to tear all of this out of the Echo framework and make it a separate project that is simply used by Echo but not Echo-specific. If I were to do this, I was thinking of naming the project "Core".

Core contains only extensions to JavaScript itself, i.e., the derivation stuff, event/listener API, method references, the scheduler, etc. I think a fair number of frameworks (but maybe just the most popular one, prototype.js) just shove that stuff right into the Object object. I far prefer putting it a namespace, but that namespace needs a short/generic/applicable name, e.g., "Core".

Hi Tod,

It's been a while since I checked out the framework, we should really have a chat in the near future. I was wondering, have you yet established a schedule for (near) finalizing the API? I'll have to port all my custom peers and I don't want to invest heavily, only to see the next major evolution of the framework. I really like the changes so far, though, so keep up the good work :)

Tod Liebeck wrote:

Well, this is a bit disturbing.... a certain web browser (and all versions of it) destroys toString() and valueOf() implementations declared in objects. For example:

var test = {

a: "foo",
b: function() { return 1337 },
toString: function() { return "Hello!" }
};

The toString method will immediately cease to exist.

Anyone want to guess what browser? Hint: it begins with an "i" and ends with an "e".

Workaround at present is to allow "$" to precede function names and automatically lop them off when creating a class using EchoCore.Extend. Looked at prototype, who is using this same declaration strategy...no indication they're even aware of it.

Sorry, perhaps I didn't get it... This HTML works perfectly in my IE6 (shows "Hello!" box):

<script>
var test = {
    a: "foo",
    b: function() { return 1337 },
    toString: function() { return "Hello!" }
}

alert(test)
</script>

This is Windows XP Pro SP2 and IE is 6.0.2900.2180.xpsp_sp2_rtm.040803-2158.

Not sure, perhaps later you was confused by different thing - "toString" property is not enumerated when you do "for (propName in obj)" - not enumerated in IE6 but enumerated in other browsers.

tliebeck's picture

Durinda D'Bry wrote:

Sorry, perhaps I didn't get it... This HTML works perfectly in my IE6 (shows "Hello!" box):
<script>
var test = {
    a: "foo",
    b: function() { return 1337 },
    toString: function() { return "Hello!" }
}

alert(test)
</script>

This is Windows XP Pro SP2 and IE is 6.0.2900.2180.xpsp_sp2_rtm.040803-2158.

Not sure, perhaps later you was confused by different thing - "toString" property is not enumerated when you do "for (propName in obj)" - not enumerated in IE6 but enumerated in other browsers.

Awesome, thanks much for this info, as of SVN 729 $toString/$valueOf are gone and toString/valueOf are simply manually copied each time.

tliebeck's picture

Well after an exhausting several days of mucking about in text editors and roughing up my copy of the ECMAScript spec, I've gone and changed the internal architecture yet again. Nothing hugely breaking this time, but have moved away from Alex Arnell's inheritance system due to performance issues in IE6.

His implementation, while impressive, seems to have problems in IE6 when subjected to the vast number of objects created by Echo3 (components, peers, property objects, etc). I think IE6 sees a significant performance drop because each constructor becomes two method calls rather than one.

The new implementation turns out to be a bit simpler and better suited to our purposes.

A side effect is that invoking super-constructors is also cleaner, as one no longer needs to call .prototype.$construct but can simply call the parent constructor directly.

An old superconstructor call:
Foo.prototype.$construct.call(this, param1, param2);

The new style:
Foo.call(this, param1, param2);

A description of the new implementation, can be found here:
http://wiki.nextapp.com/echowiki/CoreJS.SharedPrototype

I've never seen this approach done before (but that probably just means only a few ten thousand people came up with it before I did, rather than the typical million). Or perhaps that just means it's crap. :D Anyway, I'd *greatly* appreciate any analysis of it...it seems to square with the spec and all tested browsers.

mjablonski's picture

Tod Liebeck wrote:

Awesome, thanks much for this info, as of SVN 729 $toString/$valueOf are gone and toString/valueOf are simply manually copied each time.

Hi Tod,

you've missed two $toString-conversions: Render.RemoteList and WebCore.

And if you're going to edit Render.RemoteList, maybe you can fix:

http://bugs.nextapp.com/mantis/view.php?id=78

Thanks, Maik

tliebeck's picture

mjablonski wrote:

Hi Tod,

you've missed two $toString-conversions: Render.RemoteList and WebCore.

And if you're going to edit Render.RemoteList, maybe you can fix:

http://bugs.nextapp.com/mantis/view.php?id=78

Thanks, Maik

Thanks, should all be fixed. Darn case-sensitive search checkbox :D

tliebeck's picture

:o :o Look out, it's another API change!!! :o :o

First let me just reiterate at this point that I honestly don't mean to keep adding crazy stuff to Core.extend(). Anything that goes in there needs to be for the purpose of making the Echo3 code more maintainable, cleaner, or higher performing.

And before I even mention what I've done, let me first present some of the rationale for it: JavaScript has no capability to create private instance variables or methods. (Academically, yes, it is possible, you can use closures to pull it off, but the performance stinks in such cases because you have to re-define any functions that access the private variables whenever you create an instance of the object...so that doesn't count :D)

The previous solution has been to identify private properties of objects by an underscore preceding the variable name, e.g., a property "_foo" would be private, where "bar" would be public. The API user then simply avoids accessing/modifying those variables. This will work just fine, but we do run into one technical issue: The API user must be very careful to not override any of those variables. If the base class has a quasi-private variable called "_count", a derivative class had better not create one with the same name. The lack of encapsulation here takes away freedom from the base class developer to modify his/her class' inner workings, can result in difficult-to-debug issues, and relies on the end-developer being careful.

The new solution, in SVN 734, is to require that any properties that are allowed to be overridden be placed in a block of code marked "virtual" (in much the same way abstract methods are current delineated). Any attempt to invoke Core.extend() and override a non-abstract or non-virtual property will result in an exception being thrown.

Requiring such designation of virtual properties (methods or variables) guarantees that our quasi-private variables cannot be wiped out by a derivative class. To make this work, all instance variables must be declared in Core.extend() as properties, NOT in the constructor. This is not a bad thing...as an additional bonus it provides a nice place to JSDoc each of them (assuming we can recruit a Perl enthusiast to modify JSDoc to work with the new craziness that is Core.extend() :D). Private variables should continue to be marked with the preceding underscore as well.

And of course, we also get the benefit of allowing the developer to specify how a class may be extended.

And here's an updated example code snippet:

var ExampleClass = Core.extend(BaseClass, {

    $static: {
        aClassVariable: 5;

        aClassMethod: function() {
            return this.aClassVariable; // this pointer is relative to static block.
        }
    },

    $load: function() {
         // a static initializer function.
    },

    // Declare internal variable z.
    _z: null,

    // Declare public variable q
    q: null,

    $constructor: function(x, y, z) {
        BaseClass.call(this, x, y);
        this._z = z;
    },

    // An abstract block...having one makes a class abstract.
    $abstract: {

        abstractMethod: function(q) { }
    },

    $virtual: {
        
        thisMethodCanBeOverridden: function(a, b) {
            return a + b;
        }
    },

    anInternalMethod: function() {
        alert("Only ExampleClass should call me.");
    },

    aPublicMethod: function() {
        alert("Feel free to call me!");
    },

    toString: function() {
        // Note that toString is always override-able.
        return "The value of z is: " + this._z;
    }
});


tliebeck's picture

And almost forgot....had one more odd idea for Core.extend()...but this one will take a lot of work to implement and probably isn't feasible for 3.0....

The JavaScript (ECMA 262v3) spec defines Function.toString() to return a function definition as a String, and this requirement is supported by all browsers. This can be used in combination with eval() to do some interesting stuff.

One of the more basic possibilities is to create copies of functions, and in fact Core.extend() is already using this as of the near-latest commit. In cases where a derivative object does not have a constructor, we copy the constructor of the base class rather than creating a new constructor that invokes "apply()" on its parent. This turns out to be a lot faster in IE6 when we start creating tons of objects (as Echo3 loves to do), and probably other browsers too.

So the probably-really-stupid-but-possibly-performance-enhancing idea I had was that if we wrote a JavaScript parser, we could perform optimizations to the JavaScript code on the client, e.g., inlining function calls, to produce better performance. You'd only do it at the time of declaration (which would be increased) but see a potential payoff at runtime. Doing this is on the server might be impractical due to the resultant increase in size of JS code (then again, it might not).

Again...I'm not thinking of actually doing this for 3.0, just figured I'd throw the idea out there.

its really great , Thanks

Tod Liebeck wrote:

Hi all,

I'm strongly considering changing the syntax / OO architecture used in the Echo3 client-side JavaScript. We're currently using the traditional approach:

Alpha = new function(x, y) {
    Beta.call(this, x);  // Call super constructor.
    this.y = y;
};

Alpha.prototype = EchoCore.derive(Beta);

Alpha.SOME_CONSTANT = 5;

Alpha.aClassMethod = fucntion() {
    alert("this is a class method");
};

Alpha.prototype.doSomething = function() {
    alert(this.x);
};

There's another approach in fairly common use today that I think looks simpler and might be easier to maintain. It's based around a tiny library called Inheritance.js by Alex Arnell:

http://twologic.com/projects/inheritance/

I added something based on this concept to Echo3's Core.js and so far like the result. For starters, the syntax is much cleaner:

Alpha = EchoCore.extend(Beta, {

    global: {
        SOME_CONSTANT: 5,

        aClassMethod: function() {
            alert("this is a class method");
        }
    },

    // this is the constructor
    initialize: function(x, y) {
        this.parent(x);
        this.y = y;
    },

    doSomething: function {
        alert(this.x);
    }
});

There are a few advantages to this approach beyond just the pretty syntax:

  • You can do ruby-style mixins (add fragments of code to multiple classes)...note that I don't have this ported to the Core.js version yet.
  • You can call this.parent() to invoke superconstructors/ancestor methods
  • It does away with the issue of 'dual purpose' object constructors...where the constructor needs to be able to create a prototype instance for a derived class as well as an actual instance. We currently 'solve' this using EchoCore.derive(), but I've always kind of hated that implementation, and it doesn't solve the problem completely, you still have to be a bit careful.
On the negative side, we have:
  • It doesn't seem to work with JSDoc yet. We might need to modify JSDoc to pull this off. Perhaps there's another tool or modified version already out there. Or perhaps someone here is a PERL programmer? :D
  • It's more architecture and you might not find a description of how it works in a JS book. We'll comment the hell out of it to fix the latter problem. Unlike prototype.js and other JS extension though, we DO NOT modify any built-in objects (Echo3 still modifies, in sum-total, ZERO JS objects that don't belong to it).
To see my implementation, check out the proposed Core.js in the wiki: http://wiki.nextapp.com/echowiki/Echo3Clie...eSourceProposed

Versus the old one: http://wiki.nextapp.com/echowiki/Echo3ClientScriptCoreSource

I've yet to test it for performance, but I think it should be good. Obviously a showstopper if its not. Once I finish porting Application.js and maybe WebCore.js I'll run some tests.

Oh and one more negative....changing code syntax like this is hell.

[/][/]