Who here actually uses D?

Adam D. Ruppe destructionator at gmail.com
Sat Jan 1 22:00:19 PST 2011


I wrote:
> (It'll be cool
> to say "yeah we can basically write full javascript from inside
> D" some day, but I doubt I'd actually put it to serious use.)

Oh my god, I almost did it. It took all bleeding day, but this
thing compiles and runs:

// skipping some boring stuff...
	auto js = new ClientSideScript(document);

	js.innerCode = {
		js.funclol = "10";    // parens are (currently) required when setting
		js.funclol = 10;      // works with a variety of basic types
		js.funclol = 10.4;
		js.funclol = js.rofl; // can also set to another js variable
		js.setVariable("name", [10, 20]); // try setVariable for complex types
		js.setVariable("name", 100); // it can also set with strings for names
		js.alert(js.funclol, dInt); // call functions with js and D arguments
		js.funclol().call;       // to call without arguments, use the call method. This
is a needed compromise to also support getters
		js.funclol(10);        // calling with arguments looks normal
		js.funclol(10, "20");  // including multiple, varied arguments
		js.myelement = ele;    // works with DOM references too
		js.a = js.b + js.c;    // some operators work too
	};

      write(js.toString);




That D, when run, outputs this:
<script>
        funclol = "10";
        funclol = 10;
        funclol = 10.4;
        funclol = rofl;
        name = [10,20];
        name = 100;
        alert(funclol, 50);
        funclol();
        funclol(10);
        funclol(10, "20");
        myelement = document.getElementById("javascript-referenced-element-1");
        a = b+c;
</script>


It's just what the D did. But that D was so close to the javascript
itself that it was able to output the code without needing special
functions.

Naturally, reading a JS variable is impossible (perhaps unless
it is already set here - that's what the repository is for). They
have type of either Variable or Source though, so if you
accidentially tried to use one, you wouldn't get far.

Anyway:

The way it works is innerCode takes a delegate. It then sets the
js object to record mode and runs the delegate, then returns
to normal mode.

When in record mode, the js methods write their arguments to
strings and append them to a variable in a stack (so nested
innerCodes should, in theory, work).


That was the easy part. The hard thing was getting rid of the
vars helper object from the call site. I got an acceptable
compromise by doing opDispatch(string name, T...)(T t) if (T.length != 0) for the
function calls, and opDispatch(string name)(...) for
the assignment.

So the variadic template put together an argument list. A traditional
variadic function passes its argument on to an opAssign template
on the Variable object.


The Variable's opBinary simply takes the string op and puts it
between its "names", creating a temporary with a name of the
operation.


D datatypes are passed in and converted to JSON for the assignment.
So Javascript sees a D variable in there as a literal value. My
existing toJsonValue template handled structs and arrays too,
so quite a few D variables could be passed in.


I special cased my DOM.Element class as well. Since client
JS can't actually make use of a D reference, it finds some
common ground - the Element's id attribute. If one is set, it
uses it directly. If not, it generates one and passes that to
the JS.



Conditionals and looping can't be easily translated like this.
If they can't be done server side, the all useful escape hatch
of js.appendSource("code here") will be necessary.





All in all, this is really just a toy, but that technique to
get opDispatch and properties working might be useful elsewhere.
I think it might work to go wild with a Javascript like object
system from inside native D.



Anyway I'm up super late. If you want to see my code, it is
available here:

http://arsdnet.net/dcode/html.d

It depends on this: http://arsdnet.net/dcode/dom.d


(Forgive the ugly code. I originally started this module as
just a collection of useful html transformation functions I wrote
elsewhere and wanted in one place. As you can see, I never actually
did that and went off on this script nonsense instead.

The worst part is having those validation functions in there is
legitimately useful. I'll probably never use this script thing
beyond this toying - simply using plain strings or json is easy
enough and does a decent job already... oh well)


More information about the Digitalmars-d mailing list