D to Javascript converter (a hacked up dmd)

Adam D. Ruppe destructionator at gmail.com
Wed Feb 29 09:21:28 PST 2012


On Wednesday, 29 February 2012 at 15:46:40 UTC, Adam D. Ruppe 
wrote:
> microd.d(130): Error: variable t forward declaration
> Segmentation fault.

And that's fixed... and handling if(__ctfe)... and

boom! It worked. Generated 70 KB of javascript though,
a lot of it is obvious garbage - global variable declarations
and pieces of D code.

Looks like leftover stuff from CTFE and mixins. Probably
shouldn't be outputted at all, but it can be garbage collected
pretty well; my simple string search one brought it down to
40 KB.

Then, if I run my tools/mangledown, which replaces the D mangled
names with $number$, the size goes down to 6 KB.



6 KB isn't half bad! And got the right result from a complex
chunk of D code. (it just runs std.algorithm.sort on an array,
but that does a LOT of fancy stuff - string lambdas, treating
an array as a range, ctfe, and more.)

import std.algorithm;
void main() {
         auto range = sort!"a < b"(["hello", "adam"]);
         println(range.front); // "adam"
}



The Google thing can probably strip it more by shortening the
names more than my program does. (My name shortener doesn't
understand scoping - it is just a regex string replacer - so I'm
conservative in what it does.)



still hehehe, not bad at all.


BTW, I've written basic bindings to almost everything in the core
browser experience.

import jslang.name = the Javascript builtins, RegExp, Array, etc.
These generate no code, it is just like calling C from D.

import browser.name = Browser objects like JSON, document, window,
history, location, canvas, etc.

Again, generates no code, but gives access and static checks.




Now, I also wrote up a hack so you can do third party extensions,
with minimal generated code (especially if you use dmd -inline,
but even without it, it does well).


import browser.document;

final class MyElement {
    extern(js) JSElement __js_this; // JSElement is the native 
binding
    // __js_ words have special meaning - they give direct access 
to
    // javascript keywords. use with care, it might not do what 
you think.

    // here, since object.this is nonsense in JS, the compiler 
uses that
    // to output object instead - giving direct access.
    alias __js_this this; // alias this translates as A.member = 
thing.
    // but since member here is this, which is noop, it is just 
plain A.

    void addClass(string a) { className ~= " " ~ a; }
}


auto a = cast(MyElement) document.getElementById("something");

a.style.color = "green";
a.addClass("cool");


Generates (basically):

// it knows it is cast from final class to final class, which
// is a no-op in Javascript

var a = document.getElementById("something");
a.style.color = "green"; // directly output

addClass("cool", a); // the extension class is a free function

function addClass(a, d_this) {
    d_this.className = d_this.className.concat(" ".concat(a));
}



alias this is cool. You can also do a real class, but don't
reinterpret cast to it - the vtbl will be missing. Instead,
just new it and let the compiler do its work.




This is getting pretty cool. Next challenge is the in operator.
In Javascript, in returns a boolean. D expects a pointer. How
can I do it efficiently?

The lambda trick will work for the pointer, but I don't want to
make that if we don't need it. Perhaps if the in expression
is immediately cast to bool, I'll skip it.



Another semanitc issue is:

ubyte a = 255;
a++; // we expect 0, but js will give 256.



I solved division:

int a = 1/2; // becomes var a = Math.floor(1/2);


And since D does a really good job at keeping int and float
math distinct, this is generally easy to work with.

float a = 1;
int b = a/2; // D requires an explicit cast here, so there's out
               // Math.floor opportunity!

float b = a/2; // becomes just a/2.



But, wrapping might be fun. I could probably do & 0xff
if and only if D otherwise forces it to be a ubyte. But,
what about the bit pattern of negative numbers?

I could probably just ignore it, but I'd like to match as
much as is reasonable.


More information about the Digitalmars-d-announce mailing list