www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - D to Javascript converter (a hacked up dmd)

reply "Adam D. Ruppe" <destructionator gmail.com> writes:
https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

Daniel Murphy's microd fork of dmd, meant to output C,
made me realize it'd be fairly easy to use that same method
for other languages too.

So, I spent some time these last two weekends making it work
to put out Javascript.


See below for a copy/paste of the readme on how to get started.

A live demo:
http://arsdnet.net/dtojs/test.html

D source code:
http://arsdnet.net/dtojs/microd.d



As you can see, a lot of things work: functions, main,
most the operators, loops, if, basic data types,
even structs, classes (including inheritance), and exceptions.


Take a look at the generated javascript
http://arsdnet.net/dtojs/microd.js

It looks messy, since it uses mangled names almost everywhere.
(if you replace the mangled names with shorter things, it cuts
the size down by like 60%. Or, you can gzip it for a 10x 
reduction.
  See tools/mangledown.d in the zip, but this is raw so you can see
what it makes.)



For classes, it creates a vtable and some run time type 
information
on the Javascript object. This allows dynamic casts and virtual
functions to work like you expect in D.

You can see _Dmain in the middle of the file, and at the bottom,
you can see it is called if present, so you can have one or not 
have
one at your preference.

As you scroll down, you'll see the methods. Since I forked a C
generator, they are made and usually called as free functions,
but extern(js) (see below) are made as object properties.


Not so obvious is the runtime that's mixed in there.

Here's the D source code:
http://arsdnet.net/dtojs/object.d


It's pretty simple code. extern(js) works to let you - and other
JS things - easily interact with the outside world, since it
turns off mangling while letting you define things like loose
variadics.

There is no handwritten Javascript except for the if(_Dmain) at
the end. The rest of the runtime and library is written in D.



Speaking of library, I started something there too.

http://arsdnet.net/dtojs/browser/

the browser package generates no Javascript code. It simply
binds to existing functionality so D can use it in a more
structured manner. (object.d generates ~14kb of code when
raw. If you run mangledown on it, it goes down to about 6.)

browser.document provides some access to the browser DOM.

http://arsdnet.net/dtojs/std/

The std package is a kind of Phobos library, meant to make
source-compatible code with regular D stuff. It generates some
javascript.


I don't want to use the real Phobos though because it is fairly
large, and won't take advantage of the browser's existing library
functions. It *might* work in here though; I haven't tried.



The browser package makes no attempt at cross browser 
compatibility,
but you can test for functions like you would in real JS:

if(&document.querySelector) { we have it }



If I start to use this thing seriously, I might provide a library
wrapper that does this kind of thing.






Anyway, it works pretty well in the trivial tests I've done
so far, but I haven't used it for anything more serious.



Kinda cool though, and hasn't been that hard. The dmd compiler
isn't so bad to hack up once you get to know it.

Combined with the stuff others and I have already done for
D on the server, we might just be coming up on web apps that
use the same D everywhere!

========
Here's how to use it:

First, copy in the backend folder from the dmd.zip you
get from Digital Mars.

(You need it to compile, but I don't have a license to
distribute it myself.)


Then, run make to build the hacked dmd.



When its done, change into the "test" directory and
start to play. The makefile there shows how to build
some javascript.

../dmd -md yourfile.d

and optionally you can use my library in there from
test/browser and test/std.(add std/*.d to the dmd
command line to make sure its code is generated in.)

You can ignore most the messages it spams out; it
will do its best to generate the file anyway.

test/browser is the kind of core runtime to this,
in addition to object.d.

object.d - the stuff D expects and the basic JS language
constructs

browser/*.d - bindings to objects and functions the browser 
provides
such as the DOM.

Most global functions in the browser are found in 
browser/window.d.


std/*.d - just super minimal wrappers to browser functions laid 
out
more like Phobos.
Feb 26 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-27 04:51, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

 Daniel Murphy's microd fork of dmd, meant to output C,
 made me realize it'd be fairly easy to use that same method
 for other languages too.

 So, I spent some time these last two weekends making it work
 to put out Javascript.
Interesting, and cool. -- /Jacob Carlborg
Feb 27 2012
parent reply Andrea Fontana <advmail katamail.com> writes:
Cool!

Can you call custom (external, from 3rd party libs) JS functions from
there?
You should port jquery syntax sugar :)


Il giorno lun, 27/02/2012 alle 09.48 +0100, Jacob Carlborg ha scritto:

 On 2012-02-27 04:51, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

 Daniel Murphy's microd fork of dmd, meant to output C,
 made me realize it'd be fairly easy to use that same method
 for other languages too.

 So, I spent some time these last two weekends making it work
 to put out Javascript.
=20 Interesting, and cool. =20
Feb 27 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 27 February 2012 at 09:46:51 UTC, Andrea Fontana wrote:
 Can you call custom (external, from 3rd party libs)
 JS functions from there?
Yes, just make: extern(js) void function_name_here(...); and you can call it. For jQuery, you'd probably want to define an extern(js) class JQuery {} with all its method names. Since so many of them take strings, I think this would actually be somewhat easy.
Feb 27 2012
parent reply Andrea Fontana <advmail katamail.com> writes:
Il giorno lun, 27/02/2012 alle 16.09 +0100, Adam D. Ruppe ha scritto:

 On Monday, 27 February 2012 at 09:46:51 UTC, Andrea Fontana wrote:
 Can you call custom (external, from 3rd party libs)
 JS functions from there?
=20 Yes, just make: =20 extern(js) void function_name_here(...);
Good!
=20
 and you can call it. For jQuery, you'd probably want
 to define an extern(js) class JQuery {} with all its method
 names. Since so many of them take strings, I think this would
 actually be somewhat easy.
About jquery: i mean what about a d function similar to $() jquery function for better elements handling (instead of getElementById() )
Feb 27 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 27 February 2012 at 15:39:50 UTC, Andrea Fontana wrote:
 About jquery: i mean what about a d function similar to  $() 
 jquery
 function for better elements handling (instead of 
 getElementById() )
Have you seen my dom library? :P It's all server side but it is just awesome. Lots of convenience functions, getting elements is easy, and operating on them as a group is too, either through a wrapper struct or just using foreach yourself. I definitely want to port some of it to the javascript output. https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff the file is dom.d. It also depends on characterencodings.d. The most jquery-like interface is Document's opIndex: document[`#something .my-thing > p`].addClass("matched") .appendText("matched me!"); Though, I really think that querySelectorAll + foreach wipes out jquery's element selection advantage. querySelectorAll is in all browsers IE8 and up. Adding foreach to javascript can be done with text macro (see html.d in my github) or D->JS of course has foreach too! The zip of d->js actually breaks on foreach here, but it was an easy fix. I'll push up the changes this next weekend. Anyway, here's how it looks: foreach(element; document.querySelectorAll("#blah > p")) // do something to element
Feb 27 2012
parent Andrea Fontana <advmail katamail.com> writes:
Il giorno lun, 27/02/2012 alle 16.55 +0100, Adam D. Ruppe ha scritto:

 On Monday, 27 February 2012 at 15:39:50 UTC, Andrea Fontana wrote:
 About jquery: i mean what about a d function similar to  $()=20
 jquery
 function for better elements handling (instead of=20
 getElementById() )
=20 Have you seen my dom library? :P
Of course not!
 It's all server side but it is just awesome. Lots of
 convenience functions, getting elements is easy, and
 operating on them as a group is too, either through
 a wrapper struct or just using foreach yourself.
=20
 I definitely want to port some of it to the javascript
 output.
=20
 https://github.com/adamdruppe/misc-stuff-including-D-programming-language=
-web-stuff
 the file is dom.d. It also depends on characterencodings.d.
=20
 The most jquery-like interface is Document's opIndex:
=20
 document[`#something .my-thing > p`].addClass("matched")
    .appendText("matched me!");
=20
=20
 Though, I really think that querySelectorAll + foreach
 wipes out jquery's element selection advantage.
=20
 querySelectorAll is in all browsers IE8 and up. Adding
 foreach to javascript can be done with text macro
 (see html.d in my github) or D->JS of course has foreach
 too!
=20
=20
 The zip of d->js actually breaks on foreach here, but
 it was an easy fix. I'll push up the changes this next
 weekend.
=20
=20
 Anyway, here's how it looks:
=20
 foreach(element; document.querySelectorAll("#blah > p"))
      // do something to element
=20
Very interesting! :)
Feb 27 2012
prev sibling next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:yfmgvgprfpiquakiyjlk forum.dlang.org...
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

 Daniel Murphy's microd fork of dmd, meant to output C,
 made me realize it'd be fairly easy to use that same method
 for other languages too.

 So, I spent some time these last two weekends making it work
 to put out Javascript.
This is great - it might make javascript actually usable as a platform. =D How come you didn't do this as a proper fork/branch of dmd? It seems like doing it this way would make it harder to maintain, and it certainly makes it harder to see what's been changed. It's also not too hard to strip out the backend if you want to redistribute the binary. (stub out e2ir,s2ir,glue,toobj,iasm and remove the backend specific stuff from main)
Feb 27 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 27 February 2012 at 11:32:52 UTC, Daniel Murphy wrote:
 How come you didn't do this as a proper fork/branch of dmd?
At first, I downloaded a zip of your fork just to take a look at it - I had no intention of actually modifying it. But, then I started to play around and never cleaned stuff up. /home/me/d/toys/yebblies-dmd-7723455/src That's the name of the directory where it lives on my computer :) I pushed it up to github last night right before making the ng post as a last-minute decision, figuring github would make it easier for people to look at. Redoing it as a proper fork won't be that hard; most the changes are in the one microd.c file anyway. Maybe I will next weekend.
 It's also not too hard to strip out the backend if you want to 
 redistribute
 the binary.  (stub out e2ir,s2ir,glue,toobj,iasm and remove the 
 backend specific stuff from main)
Cool. I took a quick look at doing that but just horribly broke my build. Isn't parts of ctfe implemented in glue.c though? I don't see it obviously in there, but I thought I saw something about that once.
Feb 27 2012
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:cjalubgkkdpdacsigxic forum.dlang.org...
 On Monday, 27 February 2012 at 11:32:52 UTC, Daniel Murphy wrote:
 How come you didn't do this as a proper fork/branch of dmd?
At first, I downloaded a zip of your fork just to take a look at it - I had no intention of actually modifying it. But, then I started to play around and never cleaned stuff up. /home/me/d/toys/yebblies-dmd-7723455/src That's the name of the directory where it lives on my computer :) I pushed it up to github last night right before making the ng post as a last-minute decision, figuring github would make it easier for people to look at. Redoing it as a proper fork won't be that hard; most the changes are in the one microd.c file anyway. Maybe I will next weekend.
Cool, please do.
 It's also not too hard to strip out the backend if you want to 
 redistribute
 the binary.  (stub out e2ir,s2ir,glue,toobj,iasm and remove the backend 
 specific stuff from main)
Cool. I took a quick look at doing that but just horribly broke my build. Isn't parts of ctfe implemented in glue.c though? I don't see it obviously in there, but I thought I saw something about that once.
It really shouldn't be. The big things I'm aware of that are in the wrong place in the compiler are that overrides are verified when building the vtables in the glue layer, finding 'this' inside functions is done in the glue, and a couple of things are done too early (array ops, associative array re-writes). You can pretty much just delete, e2ir, s2ir, and a couple of others, then kill everything that calls them up until main. (warning - requires reading linker speak) The main reason I left the glue layer intact in my branch is because I was constantly referring to them for the more complex parts of microD. I had a branch somewhere where I did this, but I don't think it survived.
Feb 27 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 28 February 2012 at 03:06:12 UTC, Daniel Murphy wrote:
 Cool, please do.
I suck at using git, but I think it works now: https://github.com/adamdruppe/dmd/tree/dtojs The backend refused to die in the last 45 minutes, so I just left it there. I'm pretty sure it is up to date to real dmd now too... i hope. Anyway there it is.
Mar 03 2012
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:uhqgqgsyzzxrctbeftyf forum.dlang.org...
 On Tuesday, 28 February 2012 at 03:06:12 UTC, Daniel Murphy wrote:
 Cool, please do.
I suck at using git, but I think it works now: https://github.com/adamdruppe/dmd/tree/dtojs The backend refused to die in the last 45 minutes, so I just left it there. I'm pretty sure it is up to date to real dmd now too... i hope. Anyway there it is.
Lol, I think you revered a bunch of stuff when you rebased it. But so long as future changes are done with git it should be possible to fix the history later. I'll try and fix this for you sometime this week. Hopefully this makes some sense.
Mar 03 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 4 March 2012 at 06:50:48 UTC, Daniel Murphy wrote:
 Lol, I think you revered a bunch of stuff when you rebased it.
git and I don't quite understand each other yet. $ git eat flaming death git: 'eat' is not a git command. See 'git --help'. aaaarrrggggh
Mar 04 2012
parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:gsverzxcnkptoxxsucah forum.dlang.org...
 On Sunday, 4 March 2012 at 06:50:48 UTC, Daniel Murphy wrote:
 Lol, I think you revered a bunch of stuff when you rebased it.
git and I don't quite understand each other yet. $ git eat flaming death git: 'eat' is not a git command. See 'git --help'. aaaarrrggggh
https://www.semitwist.com/articles/article/view/stupid-git Normally, I just use TortoiseGit. Sooo much nicer. But it's not on Linux.
Mar 04 2012
prev sibling parent reply Don Clugston <dac nospam.com> writes:
On 27/02/12 16:16, Adam D. Ruppe wrote:
 On Monday, 27 February 2012 at 11:32:52 UTC, Daniel Murphy wrote:
 How come you didn't do this as a proper fork/branch of dmd?
At first, I downloaded a zip of your fork just to take a look at it - I had no intention of actually modifying it. But, then I started to play around and never cleaned stuff up. /home/me/d/toys/yebblies-dmd-7723455/src That's the name of the directory where it lives on my computer :) I pushed it up to github last night right before making the ng post as a last-minute decision, figuring github would make it easier for people to look at. Redoing it as a proper fork won't be that hard; most the changes are in the one microd.c file anyway. Maybe I will next weekend.
 It's also not too hard to strip out the backend if you want to
 redistribute
 the binary. (stub out e2ir,s2ir,glue,toobj,iasm and remove the backend
 specific stuff from main)
Cool. I took a quick look at doing that but just horribly broke my build. Isn't parts of ctfe implemented in glue.c though? I don't see it obviously in there, but I thought I saw something about that once.
CTFE is entirely implemented in interpret.c. Treatment of the runtime part of (__ctfe) is in the glue layer, that's probably what you saw.
Feb 28 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 28 February 2012 at 09:30:41 UTC, Don Clugston wrote:
 CTFE is entirely implemented in interpret.c. Treatment of the 
 runtime part of (__ctfe) is in the glue layer, that's probably 
 what you saw.
Outstanding! As a side note, I've been looking at dmdscript when I want a detailed reference on Javascript, and it is (as to be expected) written in a very similar style to dmd itself. It's very nice. I like the dmd code now that I'm getting to know it.
Feb 28 2012
prev sibling next sibling parent reply "node" <sp m.com> writes:
Does this mean I can do node.js in D? :)

On Monday, 27 February 2012 at 03:51:22 UTC, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

 Daniel Murphy's microd fork of dmd, meant to output C,
 made me realize it'd be fairly easy to use that same method
 for other languages too.

 So, I spent some time these last two weekends making it work
 to put out Javascript.


 See below for a copy/paste of the readme on how to get started.

 A live demo:
 http://arsdnet.net/dtojs/test.html

 D source code:
 http://arsdnet.net/dtojs/microd.d



 As you can see, a lot of things work: functions, main,
 most the operators, loops, if, basic data types,
 even structs, classes (including inheritance), and exceptions.


 Take a look at the generated javascript
 http://arsdnet.net/dtojs/microd.js

 It looks messy, since it uses mangled names almost everywhere.
 (if you replace the mangled names with shorter things, it cuts
 the size down by like 60%. Or, you can gzip it for a 10x 
 reduction.
  See tools/mangledown.d in the zip, but this is raw so you can 
 see
 what it makes.)



 For classes, it creates a vtable and some run time type 
 information
 on the Javascript object. This allows dynamic casts and virtual
 functions to work like you expect in D.

 You can see _Dmain in the middle of the file, and at the bottom,
 you can see it is called if present, so you can have one or not 
 have
 one at your preference.

 As you scroll down, you'll see the methods. Since I forked a C
 generator, they are made and usually called as free functions,
 but extern(js) (see below) are made as object properties.


 Not so obvious is the runtime that's mixed in there.

 Here's the D source code:
 http://arsdnet.net/dtojs/object.d


 It's pretty simple code. extern(js) works to let you - and other
 JS things - easily interact with the outside world, since it
 turns off mangling while letting you define things like loose
 variadics.

 There is no handwritten Javascript except for the if(_Dmain) at
 the end. The rest of the runtime and library is written in D.



 Speaking of library, I started something there too.

 http://arsdnet.net/dtojs/browser/

 the browser package generates no Javascript code. It simply
 binds to existing functionality so D can use it in a more
 structured manner. (object.d generates ~14kb of code when
 raw. If you run mangledown on it, it goes down to about 6.)

 browser.document provides some access to the browser DOM.

 http://arsdnet.net/dtojs/std/

 The std package is a kind of Phobos library, meant to make
 source-compatible code with regular D stuff. It generates some
 javascript.


 I don't want to use the real Phobos though because it is fairly
 large, and won't take advantage of the browser's existing 
 library
 functions. It *might* work in here though; I haven't tried.



 The browser package makes no attempt at cross browser 
 compatibility,
 but you can test for functions like you would in real JS:

 if(&document.querySelector) { we have it }



 If I start to use this thing seriously, I might provide a 
 library
 wrapper that does this kind of thing.






 Anyway, it works pretty well in the trivial tests I've done
 so far, but I haven't used it for anything more serious.



 Kinda cool though, and hasn't been that hard. The dmd compiler
 isn't so bad to hack up once you get to know it.

 Combined with the stuff others and I have already done for
 D on the server, we might just be coming up on web apps that
 use the same D everywhere!

 ========
 Here's how to use it:

 First, copy in the backend folder from the dmd.zip you
 get from Digital Mars.

 (You need it to compile, but I don't have a license to
 distribute it myself.)


 Then, run make to build the hacked dmd.



 When its done, change into the "test" directory and
 start to play. The makefile there shows how to build
 some javascript.

 ../dmd -md yourfile.d

 and optionally you can use my library in there from
 test/browser and test/std.(add std/*.d to the dmd
 command line to make sure its code is generated in.)

 You can ignore most the messages it spams out; it
 will do its best to generate the file anyway.

 test/browser is the kind of core runtime to this,
 in addition to object.d.

 object.d - the stuff D expects and the basic JS language
 constructs

 browser/*.d - bindings to objects and functions the browser 
 provides
 such as the DOM.

 Most global functions in the browser are found in 
 browser/window.d.


 std/*.d - just super minimal wrappers to browser functions laid 
 out
 more like Phobos.
Feb 27 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 27 February 2012 at 12:10:17 UTC, node wrote:
 Does this mean I can do node.js in D? :)
Probably. When I did my testing, I ran the code in dmdscript and later, firefox. The javascript it outputs is pretty basic so I imagine it will work in any engine. To access the library, you can define them as extern(js) functions or classes, and then some global objects. In my code, check out src/test/browser for examples - that package is just bindings to the browser's functions. Those are translated to javascript almost exactly as you write it in D, giving access to the outside world pretty naturally. Remember though two important facts: 1) there's no optimization here. The D compiler just spits out the code tree in the new language. So, don't expect speed bonuses. 2) Not all of D works. But, a decent chunk of it does and I think it's ready for some serious playing already.
Feb 27 2012
prev sibling next sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip

 Daniel Murphy's microd fork of dmd, meant to output C,
 made me realize it'd be fairly easy to use that same method
 for other languages too.

 So, I spent some time these last two weekends making it work
 to put out Javascript.
Cool! Can it compile a function to native code and JS simultaneously? I want to execute the same code on both client and server side.
Feb 28 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 28 February 2012 at 19:27:57 UTC, Piotr Szturmaj 
wrote:
 Can it compile a function to native code and JS simultaneously? 
 I want to execute the same code on both client and server side.
You'd have to run dmd twice because it exits before getting to the backend when doing js. But you can run the same code: You might need versions or something for library support, but that's just because I haven't ported much over yet. I just now tried: import std.algorithm; auto range = sort!"a < b"(["b", "a"]); window.alert(range.front); .. and it produced 44 KB of Javascript code that *almost* worked. Looks like I have to fix the dollar expression, but otherwise, almost usable.
Feb 28 2012
next sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Adam D. Ruppe wrote:
 On Tuesday, 28 February 2012 at 19:27:57 UTC, Piotr Szturmaj wrote:
 Can it compile a function to native code and JS simultaneously? I want
 to execute the same code on both client and server side.
You'd have to run dmd twice because it exits before getting to the backend when doing js. But you can run the same code:
I see.
 You might need versions or something for library support,
 but that's just because I haven't ported much over yet.
I realize that work on project has just begun :)
 I just now tried:

 import std.algorithm;
 auto range = sort!"a < b"(["b", "a"]);
 window.alert(range.front);

 .. and it produced 44 KB of Javascript
 code that *almost* worked.
44 KB - that's not bad!
 Looks like I have to fix the dollar expression,
 but otherwise, almost usable.
Some time ago, I was interested in translation to JS, but I rather thought about binary translation, like in http://bellard.org/jslinux/. There's similar "emscripten" project which translates LLVM bytecode to JS: https://github.com/kripken/emscripten. And there's also commercial Morfik: http://en.wikipedia.org/wiki/Morfik. Perhaps you might find these links useful, if you don't know them already.
Feb 28 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 02:42:38 UTC, Piotr Szturmaj 
wrote:
 44 KB - that's not bad!
It actually gets better: 9kb if you trim the mangled names down to size (I've written a mangle name trimmer and an unused function cutter; hello world is about 200 bytes.). The reason it didn't work before wasn't just dollar, but also ref params. This was a bit of a pain.. without pointers, how can I implement this? After thinking on it for almost an hour, I decided on passing lambdas instead: void a(ref b) { b = 10; } int c = 5; a(c); assert(c == 10); The JS looks like this: function a(b) { b(10); } var c = 5; a(function(set) { if(typeof set != "undefined") c = set; return c; }); c == 5 || _d_assert(); My implementation right now is a filthy hack... but std.algorithm is basically working. assumeSorted's constructor is missing for some reason, but the algorithm itself actually worked. (I spent time making class constructors work, but I think I neglected struct constructors, so probably easy fix.) But, I think the best thing to do though isn't to port phobos implementations, but instead port the interface as much as possible. sort can be a wrapper of Array.prototype.sort() from Javascript, thus letting us leave out the implementation. Odds are the native method will be faster anyway.
 Some time ago, I was interested in translation to JS, but I 
 rather thought about binary translation, like in 
 http://bellard.org/jslinux/. There's similar "emscripten" 
 project which translates LLVM bytecode to JS:
I've heard of these two, but they seem a lot bigger than I like. I want the generated JS to be as small as possible while still covering a good chunk of D features.
Feb 28 2012
next sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Adam D. Ruppe wrote:
 The reason it didn't work before wasn't just dollar, but also
 ref params. This was a bit of a pain.. without pointers, how
 can I implement this?

 After thinking on it for almost an hour, I decided on passing
 lambdas instead:

 void a(ref b) { b = 10; }

 int c = 5;
 a(c);
 assert(c == 10);


 The JS looks like this:

 function a(b) { b(10); }
 var c = 5;
 a(function(set) { if(typeof set != "undefined") c = set; return c; });
 c == 5 || _d_assert();
What about passing values within object? function a(b) { b.value = 10; } var c = 5; var wrapper = { value: c }; a(wrapper); c = wrapper.value;
Feb 28 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 03:24:17 UTC, Piotr Szturmaj 
wrote:
 What about passing values within object?
Yeah, that's one of the first things I thought of, but what about a more complex thing: d = a(c) + 4; where will the c=wrapper.value go? It can't go at the end of the function call now. Also, if the function call is in the middle of something, we'd have to assign the wrapper somewhere too. Suppose: d = (c = 2, a(c)); I think anything that isn't inline for the argument will be too easy to break.
Feb 28 2012
parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Adam D. Ruppe wrote:
 On Wednesday, 29 February 2012 at 03:24:17 UTC, Piotr Szturmaj wrote:
 What about passing values within object?
Yeah, that's one of the first things I thought of, but what about a more complex thing: d = a(c) + 4; where will the c=wrapper.value go? It can't go at the end of the function call now. Also, if the function call is in the middle of something, we'd have to assign the wrapper somewhere too. Suppose: d = (c = 2, a(c)); I think anything that isn't inline for the argument will be too easy to break.
Here's another try with objects: function Wrapper(value) { this.value = value; } Wrapper.prototype.valueOf = function() { return this.value; } Wrapper.prototype.toString = function() { return this.value.toString(); } function a(b) { b.value = 10 + b; } var c = new Wrapper(5); a(c); alert(c); // shows 15 but this implies that all value variables must be initialized with new Wrapper(x).
Feb 28 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 04:02:54 UTC, Piotr Szturmaj 
wrote:
 but this implies that all value variables must be initialized 
 with new Wrapper(x).
Yeah. I don't like that because it means you pay for something that you aren't necessarily going to use. Now, it could follow the variable and say, if it is going into a ref function, wrap it up like this, but that'd be a lot harder to work into the compiler. It's not a bad idea, though. If it can be arranged to only be used when needed, it would probably be better than the lambda.
Feb 28 2012
prev sibling next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 29/02/2012 03:11, Adam D. Ruppe wrote:
 On Wednesday, 29 February 2012 at 02:42:38 UTC, Piotr Szturmaj wrote:
 44 KB - that's not bad!
It actually gets better: 9kb if you trim the mangled names down to size (I've written a mangle name trimmer and an unused function cutter; hello world is about 200 bytes.).
You could probably still beat that if you ran it through Google's closure compiler (on advanced!): http://closure-compiler.appspot.com/home -- Robert http://octarineparrot.com/
Feb 29 2012
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 29/02/2012 09:18, Robert Clipsham wrote:
 On 29/02/2012 03:11, Adam D. Ruppe wrote:
 On Wednesday, 29 February 2012 at 02:42:38 UTC, Piotr Szturmaj wrote:
 44 KB - that's not bad!
It actually gets better: 9kb if you trim the mangled names down to size (I've written a mangle name trimmer and an unused function cutter; hello world is about 200 bytes.).
You could probably still beat that if you ran it through Google's closure compiler (on advanced!): http://closure-compiler.appspot.com/home
I actually just tried this with: http://arsdnet.net/dtojs/microd.js Original Size: 20.14KB (2.61KB gzipped) Compiled Size: 3.05KB (1015 bytes gzipped) Pretty impressive! It did spit out 86 warnings though... Mostly: * JSC_WRONG_ARGUMENT_COUNT * JSC_USED_GLOBAL_THIS * JSC_REDECLARED_VARIABLE * JSC_NOT_A_CONSTRUCTOR (iirc to get around that you have to drop in a /** constructor */ comment before anything you want to use as a constructor for that) Good work at getting std.algorithm (mostly) working! :D -- Robert http://octarineparrot.com/
Feb 29 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 09:27:53 UTC, Robert Clipsham 
wrote:
 Pretty impressive! It did spit out 86 warnings though...
A lot of it is probably the same kind of thing my "linker" does. (I call it that, but it doesn't actually *link* anything.) I get down to 6 KB running it through that. Though, they still cut it in half and there's some code rewriting in there too. Not bad. Fun fact btw: dmd -inline works on this thing too. Though, inline makes a bunch of stuff in the form of (var a = 10, etc) which is illegal in JS (and D, actually). To hack that so it worked, I simply left the var out, so it uses an implicit global variable. The D mangled names are unique so I think it will work in practice, but still, blah. Regardless, inlining functions is pretty cool. Might make things bigger however, so idk if it is actually worth it.
  * JSC_WRONG_ARGUMENT_COUNT
  * JSC_REDECLARED_VARIABLE
I threw it a bone to silence some of these, but much of it isn't actually wrong so meh. But these:
  * JSC_USED_GLOBAL_THIS
  * JSC_NOT_A_CONSTRUCTOR
don't help at all. Even if I add the /** constructor*/, it just spits even more unhelpful warnings. http://arsdnet.net/dtojs/test2.js is where I put it. (the size there is tiny because I left a lot of dead code in there; I just put a return; before my other test code.) JSC_TYPE_MISMATCH: actual parameter 1 of __d_6Object.call does not match formal parameter found : __d_6microd6MyBase required: (__d_6Object|null|undefined) at line 2 character 17 in test2.js__d_6Object.call(this, null); ^ JSC_INEXISTENT_PROPERTY: Property __d_vtbl never defined on __d_6microd6MyBase at line 3 character 0 in test2.jsthis.__d_vtbl.length = 3; I call the Object initalizer (this isn't a constructor in D. The real D compiler would just blit the Object.init to get the memory started. The D constructor is passed as an argument to be called at the end.) to set up that vtable. So, I know its all right, but it is going to warn anyway.
 Good work at getting std.algorithm (mostly) working! :D
Thanks!
Feb 29 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
I found the std.algorithm problem. I skipped outputting
templated structs because it crashes my compiler.

For some reason.

microd.d(130): Error: variable t forward declaration
Segmentation fault.

Poo.

Function templates work fine, though.
Feb 29 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Feb 29 2012
parent Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Adam D. Ruppe wrote:
 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?
Take a look at WebGL's Typed Arrays. They allow explicit size integers and binary operators. The disadvantage is they're supported only on newest browsers.
Feb 29 2012
prev sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 29.02.2012, 04:11 Uhr, schrieb Adam D. Ruppe <destructionator gmail.com>:

 sort can be a wrapper of Array.prototype.sort() from Javascript,
 thus letting us leave out the implementation. Odds are the native
 method will be faster anyway.
That's right, although at least Google tries to implement the predefined functions in JS as well (that's what an engineer said in a video podcast)
Mar 02 2012
prev sibling parent sclytrack <sclytrack hotmail.com> writes:
On 02/28/2012 08:56 PM, Adam D. Ruppe wrote:
 On Tuesday, 28 February 2012 at 19:27:57 UTC, Piotr Szturmaj wrote:
 Can it compile a function to native code and JS simultaneously? I want
 to execute the same code on both client and server side.
You'd have to run dmd twice because it exits before getting to the backend when doing js. But you can run the same code: You might need versions or something for library support, but that's just because I haven't ported much over yet. I just now tried: import std.algorithm; auto range = sort!"a < b"(["b", "a"]); window.alert(range.front); .. and it produced 44 KB of Javascript code that *almost* worked. Looks like I have to fix the dollar expression, but otherwise, almost usable.
Do you already have a name for the compiler?
Feb 28 2012
prev sibling next sibling parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Fuck. Yes.

Combined with HTML5 <canvas> and such, this might be an awesome way to 
write web-based games.

Please do more!
Feb 28 2012
prev sibling next sibling parent reply Bystroushaak <bystrousak kitakitsune.org> writes:
 Daniel Murphy's microd fork of dmd, meant to output C
Link please.
Feb 29 2012
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 29/02/2012 16:56, Bystroushaak wrote:
 Daniel Murphy's microd fork of dmd, meant to output C
Link please.
https://github.com/yebblies/dmd/tree/microd -- Robert http://octarineparrot.com/
Feb 29 2012
parent reply Bystroushaak <bystrousak kitakitsune.org> writes:
Thx.

On 29.2.2012 18:03, Robert Clipsham wrote:
 On 29/02/2012 16:56, Bystroushaak wrote:
 Daniel Murphy's microd fork of dmd, meant to output C
Link please.
https://github.com/yebblies/dmd/tree/microd
Feb 29 2012
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Bystroushaak" <bystrousak kitakitsune.org> wrote in message 
news:mailman.239.1330541205.24984.digitalmars-d-announce puremagic.com...
 Thx.

 On 29.2.2012 18:03, Robert Clipsham wrote:
 On 29/02/2012 16:56, Bystroushaak wrote:
 Daniel Murphy's microd fork of dmd, meant to output C
Link please.
https://github.com/yebblies/dmd/tree/microd
Don't get your hopes up, it was more of an experiment than a serious fork, I have no intention of doing anything more with it (unless I get really bored again). It does work, but the effort is probably better spent on improving gdc's support of embedded platforms.
Mar 01 2012
parent reply Bystroushaak <bystrousak kitakitsune.org> writes:
I've played with gdc, but it's pretty complicated. I have few ADM 5120
routers with debwrt and it would be nice to be able compile D2 code
there, but so far, it was just fail.

C run pretty much everywhere and metacompiler D2C would be nice..

On 1.3.2012 09:05, Daniel Murphy wrote:
 "Bystroushaak" <bystrousak kitakitsune.org> wrote in message 
 news:mailman.239.1330541205.24984.digitalmars-d-announce puremagic.com...
 Thx.

 On 29.2.2012 18:03, Robert Clipsham wrote:
 On 29/02/2012 16:56, Bystroushaak wrote:
 Daniel Murphy's microd fork of dmd, meant to output C
Link please.
https://github.com/yebblies/dmd/tree/microd
Don't get your hopes up, it was more of an experiment than a serious fork, I have no intention of doing anything more with it (unless I get really bored again). It does work, but the effort is probably better spent on improving gdc's support of embedded platforms.
Mar 01 2012
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Bystroushaak" <bystrousak kitakitsune.org> wrote in message 
news:mailman.281.1330632834.24984.digitalmars-d-announce puremagic.com...
 I've played with gdc, but it's pretty complicated. I have few ADM 5120
 routers with debwrt and it would be nice to be able compile D2 code
 there, but so far, it was just fail.

 C run pretty much everywhere and metacompiler D2C would be nice..
I think once you get past the horror that is building gcc for your target platform, the big issue remaining is that druntime needs to be ported. You'll hit the same issue with a D->C translator, so it might be better just to work on the actual runtime. Doing a proper gdc-based compiler should get you some other nice things, like platform specific attributes/versions, inline asm, and a better debugging experience.
Mar 01 2012
parent Bystroushaak <bystrousak kitakitsune.org> writes:
 I think once you get past the horror that is building gcc for your target
 platform, the big issue remaining is that druntime needs to be ported.
There is actually gdc package in debwrt, but it is D1 :(
 You'll hit the same issue with a D->C translator, so it might be better just
 to work on the actual runtime.
Well, I don't consider myself as enough skilled programmer to work at gdc.
Mar 02 2012
prev sibling parent reply Johannes Pfau <nospam example.com> writes:
Am Thu, 01 Mar 2012 21:13:41 +0100
schrieb Bystroushaak <bystrousak kitakitsune.org>:

 I've played with gdc, but it's pretty complicated. I have few ADM 5120
 routers with debwrt and it would be nice to be able compile D2 code
 there, but so far, it was just fail.
 
ADM 5120 is MIPS, right? Are you trying to build a cross compiler or a compiler running on the MIPS itself? Making a cross-compiler is never easy. Assuming you already have a C cross-compiler, you have to patch the build process to include D at some point. You could also try https://bitbucket.org/goshawk/gdc/wiki/crosstool-ng but then you need a compatible 'sysroot' (a folder including the basic libraries & headers as on your target system, must include libc & some kernel headers, afaik) for your router. Another issue: druntime/phobos might not compile (as long as debwrt uses glibc it could work though), so configure with --disable-phobos to disable both druntime and phobos. You'll only get the compiler this way. And MIPS is probably also affected by GDC issue 120, so you have to configure like this: DFLAGS="-fno-section-anchors" ./configure [configure arguments here]
Mar 02 2012
parent Bystroushaak <bystrousak kitakitsune.org> writes:
 ADM 5120 is MIPS, right? Are you trying to build a cross compiler or a
 compiler running on the MIPS itself? 
Compiler running on the MIPS.
 And MIPS is probably also affected by GDC issue 120, so you have to
 configure like this:
 DFLAGS="-fno-section-anchors" ./configure [configure arguments here]
Thanks.
Mar 02 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Feb 29 2012
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind. -- - Alex
Feb 29 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Alex Rønne Petersen" <xtzgzorex gmail.com> wrote in message 
news:jilnie$1fsr$1 digitalmars.com...
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
Yea, creating JS without having to actually *write* JS is a huge use-case in and of itself. (I still can't believe the web has standardized on such an absolute shit langauge. Hell, two of them if you count PHP on the server.)
Feb 29 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-29 18:46, Nick Sabalausky wrote:
 "Alex Rønne Petersen"<xtzgzorex gmail.com>  wrote in message
 news:jilnie$1fsr$1 digitalmars.com...
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
Yea, creating JS without having to actually *write* JS is a huge use-case in and of itself. (I still can't believe the web has standardized on such an absolute shit langauge. Hell, two of them if you count PHP on the server.)
Five if you count HTML, CSS and SQL as well. -- /Jacob Carlborg
Mar 01 2012
parent reply "Nick Sabalausky" <a a.a> writes:
"Jacob Carlborg" <doob me.com> wrote in message 
news:jiptfu$qrg$1 digitalmars.com...
 On 2012-02-29 18:46, Nick Sabalausky wrote:
 "Alex Rønne Petersen"<xtzgzorex gmail.com>  wrote in message
 news:jilnie$1fsr$1 digitalmars.com...
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
Yea, creating JS without having to actually *write* JS is a huge use-case in and of itself. (I still can't believe the web has standardized on such an absolute shit langauge. Hell, two of them if you count PHP on the server.)
Five if you count HTML, CSS and SQL as well.
Very true, but a far as shittiness goes, JS and PHP are in a whole other league (IMO). Actually, HTML/CSS for what they are - *document* description formats - really aren't all that bad. The only real *major* problem with HTML/CSS is not the formats themselves, but the fact that people keep abusing them as application presentation layers, which they clearly aren't and were never intended to be. (And basing an entire application around the deliberately-stateless HTTP? Seriously? WTF?) Latex isn't bad (from what little I've seen), but if people started pretending it was a presentation layer for programs, then yea, it would completely blow for that. But that's exactly what people did with HTML/CSS. So HTML and CSS get a bad reputation when really the true blame lies with the people pushing for their misuse. (Not that HTML/CSS couldn't be improved even as pure document formats.)
Mar 02 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-02 19:13, Nick Sabalausky wrote:
 "Jacob Carlborg"<doob me.com>  wrote in message
 news:jiptfu$qrg$1 digitalmars.com...
 On 2012-02-29 18:46, Nick Sabalausky wrote:
 "Alex Rønne Petersen"<xtzgzorex gmail.com>   wrote in message
 news:jilnie$1fsr$1 digitalmars.com...
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
Yea, creating JS without having to actually *write* JS is a huge use-case in and of itself. (I still can't believe the web has standardized on such an absolute shit langauge. Hell, two of them if you count PHP on the server.)
Five if you count HTML, CSS and SQL as well.
Very true, but a far as shittiness goes, JS and PHP are in a whole other league (IMO).
Yeah, I agree. I'm just saying, thank god I don't have to use PHP in my job. I'm using CoffeeScript instead of JavaScript whenever I can which makes it a bit more bearable. Yes I know many people here don't like CS, specially the syntax, but it fixes several of the most annoying things about JS.
 Actually, HTML/CSS for what they are - *document* description formats -
 really aren't all that bad. The only real *major* problem with HTML/CSS is
 not the formats themselves, but the fact that people keep abusing them as
 application presentation layers, which they clearly aren't and were never
 intended to be. (And basing an entire application around the
 deliberately-stateless HTTP? Seriously? WTF?)

 Latex isn't bad (from what little I've seen), but if people started
 pretending it was a presentation layer for programs, then yea, it would
 completely blow for that. But that's exactly what people did with HTML/CSS.
 So HTML and CSS get a bad reputation when really the true blame lies with
 the people pushing for their misuse. (Not that HTML/CSS couldn't be improved
 even as pure document formats.)
Yes, I think both HTML and CSS could be improved a lot. One of the most annoying things is there's no good way to handle scoping. SASS (regardless of which syntax you choose to use) makes this problem less annoying and fixes several other issues with CSS. The fact that you most likely uses a server side language to output HTML fixes many of the problems with HTML. -- /Jacob Carlborg
Mar 03 2012
prev sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 2/29/12 2:34 PM, Alex Rønne Petersen wrote:
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
I think it's cool you can convert D to JS, but I don't see why anyone would want to do it. 1. JS is a superior language: variables are dynamic and are not bound to just one single type during their lifetime. JS objects can store any property. 2. JS funcions are much easier to write (no need to declare types) and also to pass around (no need to write "&"). If you'd like to annotate variables, you could use Closure: https://developers.google.com/closure/compiler/docs/js-for-compiler 3. With JS you don't have to compile and run your code (well, I guess you could make something smart in D for that). 4. If you write JS you can debug it in the browser. No need to track back to the original source code. 5. If you don't like JS syntax or verbosity, you can use CoffeeScript, which is just a syntax rewriter, not a language/paradigm shift: http://coffeescript.org/ 6. Javascript objects have some built-in properties that are different from D. So implementing those in D would make their performance worse (but you can always hard-code those functions into the compiler and translate them directly to their JS equivalent). The good thing about writing in D is that you could probably get some IDE for autocompletion and such. You might also like to type things instead of using dynamic types.
Mar 01 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/01/2012 07:04 PM, Ary Manzana wrote:
 I think it's cool you can convert D to JS, but I don't see why anyone
 would want to do it.

 1. JS is a superior language:
 [snip.]
Nope.
Mar 01 2012
prev sibling next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-03-2012 19:04, Ary Manzana wrote:
 On 2/29/12 2:34 PM, Alex Rønne Petersen wrote:
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
I think it's cool you can convert D to JS, but I don't see why anyone would want to do it. 1. JS is a superior language: variables are dynamic and are not bound to just one single type during their lifetime. JS objects can store any property.
You're arguing with a crowd gathered around a statically typed language. I think we can predict what this argument will lead to. :)
 2. JS funcions are much easier to write (no need to declare types) and
 also to pass around (no need to write "&"). If you'd like to annotate
 variables, you could use Closure:
 https://developers.google.com/closure/compiler/docs/js-for-compiler
See the above.
 3. With JS you don't have to compile and run your code (well, I guess
 you could make something smart in D for that).
? The D -> JS converter just translates it. It's no different from running e.g. the CoffeeScript compiler.
 4. If you write JS you can debug it in the browser. No need to track
 back to the original source code.
Valid argument. Maybe we can make the D -> JS converter help in some way here?
 5. If you don't like JS syntax or verbosity, you can use CoffeeScript,
 which is just a syntax rewriter, not a language/paradigm shift:
 http://coffeescript.org/
Don't even get me started on the horrible "features" in CoffeeScript. The guy who wrote the language literally had no clue what he was doing (he admitted to reading some "make your own language" book), and it isn't much better than JavaScript in terms of odd behavior and weird design decisions.
 6. Javascript objects have some built-in properties that are different
 from D. So implementing those in D would make their performance worse
 (but you can always hard-code those functions into the compiler and
 translate them directly to their JS equivalent).
Can you be a little more specific here?
 The good thing about writing in D is that you could probably get some
 IDE for autocompletion and such. You might also like to type things
 instead of using dynamic types.
To be fair, excellent JS IDEs exist already; Visual Studio has great JS auto-completion, and ReSharper enhances it a lot too. -- - Alex
Mar 01 2012
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 18:56:07 UTC, Alex Rønne Petersen 
wrote:
 Valid argument. Maybe we can make the D -> JS converter help in 
 some way here?
I don't know yet. assert() in your D code, while a far cry from a real debugger, does have the decency to give file and line number in your browser error log, like so: Error: uncaught exception: tests.d:9 [object.AssertError] Assertion failure in firefox, but it works in IE and I assume the others too. Debugging in javascript is sure to be painful due to two big facts though: 1) the line/file won't match up, and 2) the function and variable names are mangled, which gets RIDICULOUSLY long in places, and very difficult to read. For debugging, I might just put comments in the source code. /* file.d:30 */ var some_long_horrible_mangled_name = 20; so at least you'd have a hope of reading it, by matching it back up to your original source. This would be fairly easy to implement and is better than nothing. But, I don't know yet. For what I've done so far, a combination of asserts and manually picking the generated code apart has been what I use.
Mar 01 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-01 19:56, Alex Rønne Petersen wrote:
 On 01-03-2012 19:04, Ary Manzana wrote:
 3. With JS you don't have to compile and run your code (well, I guess
 you could make something smart in D for that).
? The D -> JS converter just translates it. It's no different from running e.g. the CoffeeScript compiler.
It's quite a difference. The semantics of CoffeeScript and JavaScript is more alike than D and JavaScript. CoffeeScript was created to be compile to JavaScript, not something you could say about D.
 4. If you write JS you can debug it in the browser. No need to track
 back to the original source code.
Valid argument. Maybe we can make the D -> JS converter help in some way here?
Similar problem with CoffeeScript, not as bad as with D since it outputs readable JavaScript.
 5. If you don't like JS syntax or verbosity, you can use CoffeeScript,
 which is just a syntax rewriter, not a language/paradigm shift:
 http://coffeescript.org/
Don't even get me started on the horrible "features" in CoffeeScript. The guy who wrote the language literally had no clue what he was doing (he admitted to reading some "make your own language" book), and it isn't much better than JavaScript in terms of odd behavior and weird design decisions.
It's way way WAY more better than JavaScript. * Class based object model * Function binding, language support for binding the this reference If CoffeeScript had only these two features it would be so much more useful than JavaScript, but it has a lot more: * Extremely short function/lambda syntax * Built-in loop comprehension * == behaves as you would expect * Existential operator * Default arguments * Variadic arguments * Object syntax * foreach loop that actually makes sense * Almost everything is an expression * No need to declare variables * Implicit returns * No need for semicolons (yeah, I know JS have this as well but most don't seem to use this feature) * Ranges * Arrays slicing
 6. Javascript objects have some built-in properties that are different
 from D. So implementing those in D would make their performance worse
 (but you can always hard-code those functions into the compiler and
 translate them directly to their JS equivalent).
Can you be a little more specific here?
 The good thing about writing in D is that you could probably get some
 IDE for autocompletion and such. You might also like to type things
 instead of using dynamic types.
To be fair, excellent JS IDEs exist already; Visual Studio has great JS auto-completion, and ReSharper enhances it a lot too.
-- /Jacob Carlborg
Mar 01 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 18:04:35 UTC, Ary Manzana wrote:
 6. Javascript objects have some built-in properties that are 
 different from D. So implementing those in D would make their 
 performance worse (but you can always hard-code those functions 
 into the compiler and translate them directly to their JS 
 equivalent).
It's not so bad. In my zip, src/test/jslang provides bindings to these things, which generate no code to use. In src/test/std, I implement some Phobos interfaces this way. (Run with dmd -inline and they generate no extra code.) module std.string; import jslang.string; string replace(string a, string b, string c) { auto s = cast(JSString) a; // cast just to appease D return s.replace(b, c); // uses the built in method } ...come to think of it, I think that's wrong. replace() in JS only does the first occurrence iirc. D expects them all. But, we could do: import jslang.string; import jslang.regexp; string replace(string a, string b, string c) { auto s = cast(JSString) a; // cast just to appease D return s.replace(new RegExp(b, "g"), c); // uses the built in method } or something like that. But, none of this is hard coded in the compiler. You can call javascript functions just like anything else, given a prototype. Object eval(...); // don't bother typing the arguments if you don't want to
Mar 01 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-01 19:04, Ary Manzana wrote:
 On 2/29/12 2:34 PM, Alex Rønne Petersen wrote:
 On 29-02-2012 18:32, Andrei Alexandrescu wrote:
 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
Avoiding writing JS directly in web apps comes to mind.
I think it's cool you can convert D to JS, but I don't see why anyone would want to do it. 1. JS is a superior language: variables are dynamic and are not bound to just one single type during their lifetime. JS objects can store any property.
I really miss static typing sometimes in my day to day work (Ruby, JS, ...).
 2. JS funcions are much easier to write (no need to declare types) and
 also to pass around (no need to write "&"). If you'd like to annotate
 variables, you could use Closure:
 https://developers.google.com/closure/compiler/docs/js-for-compiler
D's new lambda syntax is way more superior than the one in JS. Most of the times I would like to be able to specify types in function declarations.
 3. With JS you don't have to compile and run your code (well, I guess
 you could make something smart in D for that).
True.
 4. If you write JS you can debug it in the browser. No need to track
 back to the original source code.
True. But if you're compiler is good enough that won't be a problem, i.e. CoffeeScript.
 5. If you don't like JS syntax or verbosity, you can use CoffeeScript,
 which is just a syntax rewriter, not a language/paradigm shift:
 http://coffeescript.org/
Already doing that. But if you're doing that you would most likley pre-compile it and have the same problems as 3. and 4.
 6. Javascript objects have some built-in properties that are different
 from D. So implementing those in D would make their performance worse
 (but you can always hard-code those functions into the compiler and
 translate them directly to their JS equivalent).

 The good thing about writing in D is that you could probably get some
 IDE for autocompletion and such. You might also like to type things
 instead of using dynamic types.
-- /Jacob Carlborg
Mar 01 2012
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Ary Manzana" <ary esperanto.org.ar> wrote in message 
news:jiodnj$ric$1 digitalmars.com...
 I think it's cool you can convert D to JS, but I don't see why anyone 
 would want to do it.

 1. JS is a superior language: variables are dynamic and are not bound to 
 just one single type during their lifetime. JS objects can store any 
 property.
 2. JS funcions are much easier to write (no need to declare types) and 
 also to pass around (no need to write "&").
Are you insane or just masochistic? ;)
 3. With JS you don't have to compile and run your code (well, I guess you 
 could make something smart in D for that).
Meh. I've done a lot of web work where "no compile" is common, and I've never seen it as really being that big of a deal (unless you're using something like C++ that takes ages to compile). It's an overrated selling point of such langauges, IMO, much like "Our langauge doesn't require semicolons!" Meh, so what? Trivialities.
 4. If you write JS you can debug it in the browser. No need to track back 
 to the original source code.
Not a bad point. Although Adam's suggestion does help mitigate it.
 5. If you don't like JS syntax or verbosity, you can use CoffeeScript, 
 which is just a syntax rewriter, not a language/paradigm shift: 
 http://coffeescript.org/
Bleh. I hate JS with a passion and I'd still much rather use straight JS than CoffeeScript. CoffeeScript has a few nice bits of sugar, but the basic syntax is just plain horrid. At least plain JS doesn't have that indent-syntax abomination that's so popular these days.
 6. Javascript objects have some built-in properties that are different 
 from D. So implementing those in D would make their performance worse (but 
 you can always hard-code those functions into the compiler and translate 
 them directly to their JS equivalent).
If you're doing any non-trivial JS, you can *expect* it to be slow, period. This is like saying "I drive a $100k sports car with 600 horsepower and yet I care about my gas mileage". Just kinda goofy.
Mar 01 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 17:32:42 UTC, Andrei 
Alexandrescu wrote:
So the idea is to make an entire subset of
 D convertible to Javascript?

 What use cases do you have in mind?


 Andrei
Feb 29 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
Sorry if I sent twice, it is so easy to hit the
wrong button on things.

On Wednesday, 29 February 2012 at 17:32:42 UTC, Andrei 
Alexandrescu wrote:
 So the idea is to make an entire subset of D convertible to 
 Javascript?
Yeah, and I'm pretty much there - I just built a little sort program with std.algorithm to it, which is pretty cool.
 What use cases do you have in mind?
A number of things: 1) The obvious one is writing the client side portions of a web app in D, as well as the server side portions. This gives all kinds of benefits: well, just think how much better D is than all other languages for both little and big things. I really like having static checking of names and types. D syntax is amazing. (Javascript really isn't bad here; add a foreach macro and it isn't bad at all. But D is still better.) Sane libraries. You could use something like an include macro in Javascript, or those insane client side add script tag include functions, but here, you can just use D's superior import system. You get namespacing, stripping what you don't use; all the advantages D brings to the table for any app. Well, I'm sure I don't have to sell the D language to you! 2) Using the same language for client and server means you can reuse code. Library functions, field validation, building parts of the site. No duplication of effort for the two locations. (Now this is already kinda small, since calling D functions from Javascript isn't hard thanks to ajax - my web.d makes it stupid easy by automatically wrapping functions. But, that does require a trip to the server, so it isn't always suitable.) 3) You don't need to write javascript at all! Imagine you want to write an iPad app. Apple wants you do fork over all kinds of dough and play ball by their rules. I expect we'll see a D compiler that can output code for that platform soon, but there's another option that avoids all this right now: a web app (which you can make full screen on the home page btw). But, writing web apps means javascript. Gross. No more! Just write the whole thing as D, then convert it to Javascript and offer that to the ipad users. I've started doing things like porting std.file to use browser local storage, so you can pretend to use files and have it save there too. 4) This is an insane idea, but one that came to mind. I'm testing this by piping the generated JS into dmdscript. dmd runs insanely fast when compiling this code. Phobos is kinda slow to compile, but you don't have to use it here. Write D1 style code and dmd is blink of an eye. dmdscript is reasonably fast too. Suppose you're writing an app and you want a scripting extension. Embed dmdscript, boom you can use javascript. (I really want to revive a dmdscript D2 port to make this even easier, but it isn't hard right now either.) What if you want to script in D? If you're GPL... embed dmd front end too. Make D output JS, which is interpreted by D, calling D apis.... Pretty insane, but you could script your app in D without doing shared libraries or anything like that! Compared to cases 1-3 though, this is silly. Just a thought that came to mind. The web app use case is strong though. I think I'll actually use this thing.
Feb 29 2012
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.02.2012 21:58, Adam D. Ruppe wrote:
[...]
 4) This is an insane idea, but one that came to mind.
 I'm testing this by piping the generated JS into
 dmdscript.

 dmd runs insanely fast when compiling this code. Phobos
 is kinda slow to compile, but you don't have to use it
 here. Write D1 style code and dmd is blink of an eye.

 dmdscript is reasonably fast too.
As someone that spent quite some time porting and fixing dmdscript I humbly suggest using Google's standalone version of v8. I mean I've done benchmarking, and it was like 20-200x times slower depending on the things you do. For one hashtables are the bottleneck, I though of reworking them but lost interest along the way. The other problem is FP speed since JS uses double for eveerything. dmd used FP stack for double back then, probably now it uses SSE(?).
 Suppose you're writing an app and you want a scripting
 extension. Embed dmdscript, boom you can use javascript.

 (I really want to revive a dmdscript D2 port to make this
 even easier, but it isn't hard right now either.)
You can try where I stopped it's still on D source, though I should probably upload that on github. If you are serious about dmd I would recommend it, as I've spent weeks to figure out proper try/catch/finally implementation and fix closures that were broken. Last thing I vaguely recall is building it with 2.055 or 2.056, and moving deprecated parts of phobos into it.
 What if you want to script in D? If you're GPL... embed
 dmd front end too.


 Make D output JS, which is interpreted by D, calling
 D apis....


 Pretty insane, but you could script your app in D without
 doing shared libraries or anything like that!
Indeed, but who knows ;)
 Compared to cases 1-3 though, this is silly. Just a thought
 that came to mind.



 The web app use case is strong though. I think I'll actually
 use this thing.
-- Dmitry Olshansky
Feb 29 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 February 2012 at 19:10:27 UTC, Dmitry Olshansky 
wrote:
 If you are serious about dmd I would recommend it, as I've 
 spent weeks to figure out proper try/catch/finally 
 implementation and fix closures that were broken.
Indeed, I still have a copy of your zip from before. I tried to do it too, but I never got a lot of things working quite right; it'd sometimes crash, I replaced the AAs with a linear lookup since I didn't get that working right either. Your version worked well, as I recall. But on dmdscript vs v8, v8 is faster, but I'm not too concerned about speed. A couple big advantages dmdscript has are: a) I expect it will be easier to integrate in D apps b) I already know its source code, so if I want to hack new things on to the language, it won't be a big todo. c) license is a little more permissive. The big one though is familiarity with the source.
Feb 29 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.02.2012 23:40, Adam D. Ruppe wrote:
 On Wednesday, 29 February 2012 at 19:10:27 UTC, Dmitry Olshansky wrote:
 If you are serious about dmd I would recommend it, as I've spent weeks
 to figure out proper try/catch/finally implementation and fix closures
 that were broken.
Indeed, I still have a copy of your zip from before. I tried to do it too, but I never got a lot of things working quite right; it'd sometimes crash, I replaced the AAs with a linear lookup since I didn't get that working right either.
I ended up using hacked RandAA by David Simcha, it works quite well. It's a somewhat slow on reads comapred to d's native one, but sure it's more stable ;)
 Your version worked well, as I recall.


 But on dmdscript vs v8, v8 is faster, but I'm not too
 concerned about speed.

 A couple big advantages dmdscript has are:

 a) I expect it will be easier to integrate in D apps

 b) I already know its source code, so if I want to hack new
 things on to the language, it won't be a big todo.

 c) license is a little more permissive.



 The big one though is familiarity with the source.
Agreed, it's very clean and lean for full interpreter (not to mention built-ins). -- Dmitry Olshansky
Feb 29 2012
prev sibling next sibling parent Mikael Lindsten <mikael lindsten.net> writes:
2012/2/29 Adam D. Ruppe <destructionator gmail.com>

 4) This is an insane idea, but one that came to mind.
 I'm testing this by piping the generated JS into
 dmdscript.

 dmd runs insanely fast when compiling this code. Phobos
 is kinda slow to compile, but you don't have to use it
 here. Write D1 style code and dmd is blink of an eye.

 dmdscript is reasonably fast too.



 Suppose you're writing an app and you want a scripting
 extension. Embed dmdscript, boom you can use javascript.

 (I really want to revive a dmdscript D2 port to make this
 even easier, but it isn't hard right now either.)


 What if you want to script in D? If you're GPL... embed
 dmd front end too.


 Make D output JS, which is interpreted by D, calling
 D apis....


 Pretty insane, but you could script your app in D without
 doing shared libraries or anything like that!
Being mainly a web developer, I think this project of yours is really exciting! Also, being a fan of embedding JS into Java applications using their ScriptingEngine API, I absolutely don't think number 4 is an insane idea. I think it's a great idea! I wish I had more time (and D knowledge!) to contribute.. for now I'm just cheering! / Mikael
Feb 29 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/29/12 11:58 AM, Adam D. Ruppe wrote:
 Sorry if I sent twice, it is so easy to hit the
 wrong button on things.

 On Wednesday, 29 February 2012 at 17:32:42 UTC, Andrei Alexandrescu wrote:
 So the idea is to make an entire subset of D convertible to Javascript?
Yeah, and I'm pretty much there - I just built a little sort program with std.algorithm to it, which is pretty cool.
Saw that - pretty amazing. The motivation sounds great. I think one area of focus going forward might be defining precisely the subset of D supported (e.g. I suppose pointer semantics would be difficult). I presume most of Safe D would be supported, but there's no formal definition of that either :o). Si this area is ripe for development. Andrei
Mar 01 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 17:35:02 UTC, Andrei Alexandrescu 
wrote:
 The motivation sounds great. I think one area of focus going 
 forward might be defining precisely the subset of D supported 
 (e.g. I suppose pointer semantics would be difficult).
Right. I'm not sure exactly what is and is not safe myself, but I think *most* of it is realistic. goto and pointers are the questionable ones right now. They are solvable, but are they solvable in a way that I'm willing to do? I don't want a while() { switch() { } } thing; the code should look like javascript, not assembly. Some integer semantics might be hard too. ubyte is ok, but byte is different because 127+1 isn't as simple as x & 0xff I'll have to think about that. Again, it surely *can* be done, but I'd rather than an error than it generating horribly inefficient javascript for simple operations. But, everything else I've considered either already works or is solvable with a little more time. It helps a lot that dmd lowers a lot of the fancier things into simple C-like constructs for me. I just got scope guards working a few minutes ago, so destructors can't be far behind.... then some bugs on struct, and int math, goto, and pointer are the only big rough spots left. At least that I've thought of so far!
Mar 01 2012
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Thu, Mar 1, 2012 at 11:13 AM, Adam D. Ruppe <destructionator gmail.com>wrote:
 Some integer semantics might be hard too. ubyte is ok, but byte
 is different because 127+1 isn't as simple as x & 0xff

 I'll have to think about that. Again, it surely *can*
 be done, but I'd rather than an error than it generating
 horribly inefficient javascript for simple operations.
Might TypedArrays help you implement some number type semantics? http://www.khronos.org/registry/typedarray/specs/latest/ --bb
Mar 01 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 19:49:46 UTC, Bill Baxter wrote:
 Might TypedArrays help you implement some number type semantics?
Yeah, I think so. I do have compatibility concerns though; it'd be a pity of something taking a ubyte means it doesn't work in IE8 anymore. I'll have to play with it though.
Mar 01 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:uvagboafiyjrhvywpiyd forum.dlang.org...
 but I'd rather than an error than it generating
 horribly inefficient javascript for simple operations.
You make it sound as if there's another kind of JS.
Mar 01 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 2 March 2012 at 05:58:03 UTC, Nick Sabalausky wrote:
 You make it sound as if there's another kind of JS.
Horribly inefficient relative to the environment :P I just don't want 100 kb of crap to download just to write a hello world. A lot of people prefer to use gzipped sizes, but I don't because the browser still has to parse the whole thing, and that takes time after the download, even if you don't actually run any of it. (On some browsers, it parses it again on every page load!) This generated D code gzips very, very well, but I still want to keep it small in general for general speed. The fastest code is no code at all. Less to parse, less to run.
Mar 02 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:arowwzayimwhzmqahxic forum.dlang.org...
 On Friday, 2 March 2012 at 05:58:03 UTC, Nick Sabalausky wrote:
 You make it sound as if there's another kind of JS.
Horribly inefficient relative to the environment :P I just don't want 100 kb of crap to download just to write a hello world.
Heh, yea. That's why, even though I use Haxe, I don't use it for generating JS (unless I wanted to do a Flash-style HTML5/canvas thing).
 A lot of people prefer to use gzipped sizes, but I don't
 because the browser still has to parse the whole thing,
 and that takes time after the download, even if you don't
 actually run any of it.

 (On some browsers, it parses it again on every page load!)


 This generated D code gzips very, very well, but I still
 want to keep it small in general for general speed.

 The fastest code is no code at all. Less to parse, less
 to run.
Suggestion: Allow all D features even if it requires...inefficient-er...boilerplate, BUT then have a system similar to safe/ trusted/ system (or maybe just a "pragma(SimpleJS)") so a developer can selectively turn on "Disallow any D features that would result in extra-inefficient JS output" at the module-level (and/or whatever other granularity safe works on).
Mar 02 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 2 March 2012 at 18:28:15 UTC, Nick Sabalausky wrote:
 Suggestion: Allow all D features even if it
 requires...inefficient-er...boilerplate, BUT then have a system 
 [...]
Eh. A problem there is those pragmas or whatever would be unrecognized by the real dmd. A command line switch, maybe, though. But on pragmas, I have extern(js) and pragma(no_js_output), but I want to keep them hidden inside the library modules. Even if you version() something out, if dmd's lexer doesn't understand it, it won't compile under the normal thing. This breaks the benefit of same code on both sides. But, version(generating_js) import something; always works. That's about as fine-grained as I think it should be. But, on this stuff, if it is there, I think it is ok to use it. The key though is to not pay for what you don't use. The gcfunctions helper app (in src/test/tools) acts like a static linker here, cutting out unreferenced functions and variables. The library now can define a whole mess of functions, and if you don't use them, they get stripped out of the final file. The key is then: a) not referencing stuff in a hidden fashion; make sure typical D code is still small and b) minimizing interdependencies, so pulling in one function doesn't pull in a whole package. This is something that's generally desirable in regular D, too (for the same reason, even) so it is I think a good path.
Mar 02 2012
parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:sazpaicrjwzchqcfwlql forum.dlang.org...
 On Friday, 2 March 2012 at 18:28:15 UTC, Nick Sabalausky wrote:
 Suggestion: Allow all D features even if it
 requires...inefficient-er...boilerplate, BUT then have a system [...]
Eh. A problem there is those pragmas or whatever would be unrecognized by the real dmd. A command line switch, maybe, though.
I thought unrecognized pragmas were supposed to just be ignored? (Or maybe I have it backwards?)
Mar 02 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-03 06:56, Nick Sabalausky wrote:
 "Adam D. Ruppe"<destructionator gmail.com>  wrote in message
 news:sazpaicrjwzchqcfwlql forum.dlang.org...
 On Friday, 2 March 2012 at 18:28:15 UTC, Nick Sabalausky wrote:
 Suggestion: Allow all D features even if it
 requires...inefficient-er...boilerplate, BUT then have a system [...]
Eh. A problem there is those pragmas or whatever would be unrecognized by the real dmd. A command line switch, maybe, though.
I thought unrecognized pragmas were supposed to just be ignored? (Or maybe I have it backwards?)
No, they're not: "Compilers must diagnose an error for unrecognized Pragmas, even if they are vendor specific ones. This implies that vendor specific pragmas should be wrapped in version statements". http://dlang.org/pragma.html -- /Jacob Carlborg
Mar 03 2012
parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Jacob Carlborg" <doob me.com> wrote in message 
news:jit2r7$rlu$2 digitalmars.com...
 I thought unrecognized pragmas were supposed to just be ignored? (Or 
 maybe I
 have it backwards?)
No, they're not: "Compilers must diagnose an error for unrecognized Pragmas, even if they are vendor specific ones. This implies that vendor specific pragmas should be wrapped in version statements". http://dlang.org/pragma.html -- /Jacob Carlborg
There's a switch to ignore them.
Mar 03 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-02 15:38, Adam D. Ruppe wrote:
 On Friday, 2 March 2012 at 05:58:03 UTC, Nick Sabalausky wrote:
 You make it sound as if there's another kind of JS.
Horribly inefficient relative to the environment :P I just don't want 100 kb of crap to download just to write a hello world. A lot of people prefer to use gzipped sizes, but I don't because the browser still has to parse the whole thing, and that takes time after the download, even if you don't actually run any of it. (On some browsers, it parses it again on every page load!) This generated D code gzips very, very well, but I still want to keep it small in general for general speed. The fastest code is no code at all. Less to parse, less to run.
No, we don't want to do it like Dart: https://gist.github.com/1277224 17260 lines of code for Hello World. -- /Jacob Carlborg
Mar 03 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 3 March 2012 at 12:10:47 UTC, Jacob Carlborg wrote:
 No, we don't want to do it like Dart:
 17260 lines of code for Hello World.
Wow. I thought I was a bit on the bloated side with ~100 lines of boilerplate (before running the unused function stripper). $ ../dmd -md object.d DMD v2.058 DEBUG $ wc object.js 108 472 11843 object.js Then again, when giant things like jQuery is considered a "necessity" when I get by just fine with my 10 KB (source, not minified, not gzipped) custom library, if even that, it shows there's a big disconnect between me and most other web people nowadays.
Mar 03 2012
next sibling parent reply James Miller <james aatch.net> writes:
On 4 March 2012 05:40, Adam D. Ruppe <destructionator gmail.com> wrote:
 On Saturday, 3 March 2012 at 12:10:47 UTC, Jacob Carlborg wrote:
 No, we don't want to do it like Dart:
 17260 lines of code for Hello World.
Wow. I thought I was a bit on the bloated side with ~100 lines of boilerplate (before running the unused function stripper). $ ../dmd -md object.d DMD v2.058 DEBUG $ wc object.js =C2=A0108 =C2=A0 472 11843 object.js Then again, when giant things like jQuery is considered a "necessity" when I get by just fine with my 10 KB (source, not minified, not gzipped) custom library, if even that, it shows there's a big disconnect between me and most other web people nowadays.
Hmm, does your DOM library compile with this? Also, is it smaller than jQuery? And how easy would it be to make it work with the browser dom? This is mostly because I pretty much use jQuery for AJAX and Dom manipulation, everything is just extras. -- James Miller
Mar 03 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 4 March 2012 at 00:05:19 UTC, James Miller wrote:
 Hmm, does your DOM library compile with this?
No. I want do a port of some of the functions to it, though. (Even if I fix it to not use goto, so it compiles to JS, I don't actually need a parser in the browser - it should use native methods when possible. So, my strategy will be to port convenience functions instead of the whole thing.) For Javascript dom stuff, I'm generally happy enough with the browser's api alone, but my little js file ports some of my convenience functions: addChild insertAfter prependChild hasClass toggleClass removeClass addClass getParent appendText replaceText removeFromTree All as free functions in Javascript. Together with what the browser already has, that covers everything I want, well, except for dataset which is beautiful on the server, but meh on the client since you have to use getAttribute for compatibility. But, that's not a big deal. I didn't port most of my form functions in dom.d because I just don't do that kind of stuff client side anyway. (Other stuff in my js lib are some functional programming helpers and an event compatibility set.) But, for the D->JS DOM additions, these functions are pretty much what I want. My strategy I'm considering is to make a separate document module, that replaces the browser.document. Using alias this magic, I'll make extension classes that are compatible with the real thing, without any runtime wrapping. It'll be like a homemade UFCS: final class BetterElement { JSElement __js_this; alias __js_this this; BetterElement addClass(string c) { className ~= " " ~ c; } } /* do the same for document */ auto be = document.querySelector("#foo > p"); be.addClass("test"); When this is compiled, it comes out as: function addClass(c, d_this) { d_this.className += " " + c; } var be = document.querySelector("#foo > p"); addClass("test", be); Which is about as minimal as you can get in JS (it's about the same as I wrote by hand), while keeping the beautiful syntax in D. Anyway, bottom line is my goal is indeed to have a compatible version of my dom library for D->JS too, but it will have almost a completely separate implementation to be more efficient in the browser environment.
Mar 03 2012
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:mxstsriydkbxxrjlfxqn forum.dlang.org...
 Then again, when giant things like jQuery is considered
 a "necessity" when I get by just fine with my 10 KB
 (source, not minified, not gzipped) custom library,
 if even that, it shows there's a big disconnect between
 me and most other web people nowadays.
Yea, a disconnect of about 50 IQ points (in your favor). Things like that are why I hate "typical" web developers and webdev "conventional wisdom" (hah!) with a burning passion. We're talking "thermonuclear power of a thousand suns" here.
Mar 06 2012
parent reply James Miller <james aatch.net> writes:
On 7 March 2012 16:19, Nick Sabalausky <a a.a> wrote:
 "Adam D. Ruppe" <destructionator gmail.com> wrote in message
 news:mxstsriydkbxxrjlfxqn forum.dlang.org...
 Then again, when giant things like jQuery is considered
 a "necessity" when I get by just fine with my 10 KB
 (source, not minified, not gzipped) custom library,
 if even that, it shows there's a big disconnect between
 me and most other web people nowadays.
Yea, a disconnect of about 50 IQ points (in your favor). Things like that are why I hate "typical" web developers and webdev "conventional wisdom" (hah!) with a burning passion. We're talking "thermonuclear power of a thousand suns" here.
I don't know what webdev "conventional wisdom" is, but it would be nice to use site that don't eat my CPU because of a billion different javascript, erm, scripts all trying to do things. There's something to be said for rolling your own libraries. However, I would like jQuery's CSS selector engine as a standalone library, sooo much easier than complex DOM lookups, especially when you want something fairly specific. -- James Miller
Mar 06 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 7 March 2012 at 03:46:45 UTC, James Miller wrote:
 However, I would like jQuery's CSS selector engine as a 
 standalone library, sooo much easier than complex DOM lookups
CSS selector is built into all the browsers since IE8/FF3.5. The functions are element.querySelector and element.querySelectorAll. http://msdn.microsoft.com/en-us/library/cc304119%28v=VS.85%29.aspx https://developer.mozilla.org/En/DOM/Document.querySelector If you need to support older browsers, I think jquery's engine is called Sizzle stand alone, but I just let it throw the method not found exception, and carry on without the javascript. It's not worth the size.
Mar 06 2012
parent James Miller <james aatch.net> writes:
On 7 March 2012 16:51, Adam D. Ruppe <destructionator gmail.com> wrote:
 On Wednesday, 7 March 2012 at 03:46:45 UTC, James Miller wrote:
 However, I would like jQuery's CSS selector engine as a standalone
 library, sooo much easier than complex DOM lookups
CSS selector is built into all the browsers since IE8/FF3.5. The functions are element.querySelector and element.querySelectorAll. http://msdn.microsoft.com/en-us/library/cc304119%28v=VS.85%29.aspx https://developer.mozilla.org/En/DOM/Document.querySelector If you need to support older browsers, I think jquery's engine is called Sizzle stand alone, but I just let it throw the method not found exception, and carry on without the javascript. It's not worth the size.
Oh right, I didn't know that, IE8 and FF3.5 are old enough that you can use it without too much worry, older browsers can just have some graceful fallback. -- James Miller
Mar 06 2012
prev sibling parent reply "Brad Anderson" <eco gnuk.net> writes:
On Saturday, 3 March 2012 at 12:10:47 UTC, Jacob Carlborg wrote:
 On 2012-03-02 15:38, Adam D. Ruppe wrote:
 On Friday, 2 March 2012 at 05:58:03 UTC, Nick Sabalausky wrote:
 You make it sound as if there's another kind of JS.
Horribly inefficient relative to the environment :P I just don't want 100 kb of crap to download just to write a hello world. A lot of people prefer to use gzipped sizes, but I don't because the browser still has to parse the whole thing, and that takes time after the download, even if you don't actually run any of it. (On some browsers, it parses it again on every page load!) This generated D code gzips very, very well, but I still want to keep it small in general for general speed. The fastest code is no code at all. Less to parse, less to run.
No, we don't want to do it like Dart: https://gist.github.com/1277224 17260 lines of code for Hello World.
To be fair to Dart, that was from the initial preview release of it. They managed to get it quite a bit smaller a couple months ago. https://gist.github.com/1385015 Regards, Brad Anderson
Mar 04 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-04 23:29, Brad Anderson wrote:
 On Saturday, 3 March 2012 at 12:10:47 UTC, Jacob Carlborg wrote:
 On 2012-03-02 15:38, Adam D. Ruppe wrote:
 On Friday, 2 March 2012 at 05:58:03 UTC, Nick Sabalausky wrote:
 You make it sound as if there's another kind of JS.
Horribly inefficient relative to the environment :P I just don't want 100 kb of crap to download just to write a hello world. A lot of people prefer to use gzipped sizes, but I don't because the browser still has to parse the whole thing, and that takes time after the download, even if you don't actually run any of it. (On some browsers, it parses it again on every page load!) This generated D code gzips very, very well, but I still want to keep it small in general for general speed. The fastest code is no code at all. Less to parse, less to run.
No, we don't want to do it like Dart: https://gist.github.com/1277224 17260 lines of code for Hello World.
To be fair to Dart, that was from the initial preview release of it. They managed to get it quite a bit smaller a couple months ago. https://gist.github.com/1385015 Regards, Brad Anderson
Seems they found a way to not include the complete runtime every time. -- /Jacob Carlborg
Mar 04 2012
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
Here's one of the nicer things to do:

http://arsdnet.net/dtojs/game.d
http://arsdnet.net/dtojs/game.html

we can do little browser games in D.

If you look at game.js:
http://arsdnet.net/dtojs/game.js

you can see it is similar in size to the original
D file (this is after running tools/gcfunctions and
tools/mangledown on it; before them, it was 21 KB).

I just quickly whipped this together, so it isn't
much of a game - you just move your thing around.
Use keys a,d, and w to control it.


Not much to it, and writing this in Javascript would
have been easy enough, but even for this trivial thing,
a few D nicieties came through:

1) I typo'd one of the method names. D caught it instantly.

2) The degrees thing is supposed to be a user defined literal..
    but it didn't actually work like that (it outputted functions
    that returned the literals!) I consider this a bug in the 
converter.

3) The click event handler is a little more succicent than the
    same in Javascript would be.

4) The switch. Two nice features of D here that JS lacks:

    a) "case 'A':" comes out as "case 65:". The key code is a
       number, which is not equal to 'A' in Javascript!

       A lot of sites have tables for this, but it is just ascii,
       so 'A' works well. In D.

    b) the comma on case is a bit shorter than the same in JS.
       D is better at this short, dynamic stuff than JS itself
       if you ask me - just look at the beauty of my server side
       dom.d compared to JS.




But, it also shows that D->JS isn't a magic bullet.


1) This won't work on IE8, since it doesn't have the canvas thing
    nor addEventListener. (The latter could be emulated in a 
library,
    though, with exactly the same syntax too.)

2) It runs smoothly on IE9, but sucks my butt on Firefox 9 on the
    same computer (my little laptop).

    It is still javascript when it runs, so speed boosts are 
limited
    by that; if the browser is slow, using D won't help much.

3) Obviously, it won't magically turn on people's javascript 
either.
    But, same language client+server means it is that much less
    work to make nice fallbacks (e.g. proper validation).

BTW speaking of validation, I'm pondering if scope(failure)
could make elegant code for that...



But, hey, I'm calling it a win. The suckage of browsers
is a reality regardless of the language.
Mar 02 2012
parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:wplwmjdlvvqcokxykskm forum.dlang.org...
 Here's one of the nicer things to do:

 http://arsdnet.net/dtojs/game.d
 http://arsdnet.net/dtojs/game.html

 we can do little browser games in D.

 If you look at game.js:
 http://arsdnet.net/dtojs/game.js

 you can see it is similar in size to the original
 D file (this is after running tools/gcfunctions and
 tools/mangledown on it; before them, it was 21 KB).

 I just quickly whipped this together, so it isn't
 much of a game - you just move your thing around.
 Use keys a,d, and w to control it.


 Not much to it, and writing this in Javascript would
 have been easy enough, but even for this trivial thing,
 a few D nicieties came through:

 1) I typo'd one of the method names. D caught it instantly.

 2) The degrees thing is supposed to be a user defined literal..
    but it didn't actually work like that (it outputted functions
    that returned the literals!) I consider this a bug in the converter.

 3) The click event handler is a little more succicent than the
    same in Javascript would be.

 4) The switch. Two nice features of D here that JS lacks:

    a) "case 'A':" comes out as "case 65:". The key code is a
       number, which is not equal to 'A' in Javascript!

       A lot of sites have tables for this, but it is just ascii,
       so 'A' works well. In D.

    b) the comma on case is a bit shorter than the same in JS.
       D is better at this short, dynamic stuff than JS itself
       if you ask me - just look at the beauty of my server side
       dom.d compared to JS.




 But, it also shows that D->JS isn't a magic bullet.


 1) This won't work on IE8, since it doesn't have the canvas thing
    nor addEventListener. (The latter could be emulated in a library,
    though, with exactly the same syntax too.)

 2) It runs smoothly on IE9, but sucks my butt on Firefox 9 on the
    same computer (my little laptop).

    It is still javascript when it runs, so speed boosts are limited
    by that; if the browser is slow, using D won't help much.

 3) Obviously, it won't magically turn on people's javascript either.
    But, same language client+server means it is that much less
    work to make nice fallbacks (e.g. proper validation).

 BTW speaking of validation, I'm pondering if scope(failure)
 could make elegant code for that...



 But, hey, I'm calling it a win. The suckage of browsers
 is a reality regardless of the language.
Yea, that's pretty cool. The *one* nice thing about modern JS is that is can kill off Flash. Of course, it's still not a partucularly good approach, but at least it's an improvement over Flash. Your demo there reminds me of an awesome demoscene website around ten years ago...umm "matt"-something-or-other. Shit, I can't remember, but it was like a demoscene entry, but with the browser as the platform. Included one or two DHTML games, and this was years before anyone had even heard of "canvas" or "HTML5". Unfortunately, I don't think it's around anymore :(
Mar 02 2012
prev sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 29.02.2012, 18:32 Uhr, schrieb Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org>:

 On 2/26/12 9:51 PM, Adam D. Ruppe wrote:
 https://github.com/downloads/adamdruppe/dtojs/dtojs.zip
[snip] That's interesting. So the idea is to make an entire subset of D convertible to Javascript? What use cases do you have in mind? Andrei
The visualizer I wrote for aichallenge.org had 3 versions: - HTML 5 / JavaScript - Java applet - Java application The source code was in JavaScript and executed in the Rhino JS engine for the Java versions. The applet was actually there to support Internet Explorer versions which suffered from a massive NIH syndrome when it came to HTML 5. So with those becoming a minority the remaining targets are the standalone application and the browser visualizer. With D-to-JS I would have had the option to write the application in D using GtkD or similar GUI library with access to drawing functions that are similar to the HTML 5 Canvas, and then export the whole thing to JS. The obvious benefits are to me: - Native efficiency (JS in Rhino in JVM used masses of memory and was slow as molasses) - Type checking and compiler errors The downside is that I would have missed the perfect JavaScript debugging support in the major browsers when working with D code. :)
Mar 01 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
I probably should have been working today.... but instead
spent a good amount of time on this again.

New zip:

https://github.com/downloads/adamdruppe/dtojs/dtojs-0.3.zip

(I haven't cleaned up the github fork yet)

To give you an idea of what is working, check out
my tests.d file:

http://arsdnet.net/dtojs/tests.d

This compiles (raw) into this:
http://arsdnet.net/dtojs/tests.js

BTW, when compiling, be sure to put test/object.d
on your command line too, or the runtime functions
won't be present in your .js file!

23 KB (down to 11 KB if you run the included mangledown tool
on it. gcfunctions can often make a big difference, but not here,
since it removes what you don't use. A test that doesn't use
something is an incomplete test!)


I think I broke std.algorithm again :(, but fixed a lot of
other stuff. (it is the lambda generator in std.algorithm that
is breaking. The JS has the function, but it is nested too deep
and inaccessible to the actual algorithm.)



But, a lot of stuff works now, and the generated code isn't
half bad. I've started using more static type info to slightly
optimize it too, but only some basics.


One of the messiest things was try/catch. JS doesn't do
types like D, so I implemented it with a series of
if(dynamic_cast()), and ultimately rethrow if none matched.

A bit ugly, but it seems to pass the tests!

(The messiest compiler implementation so far is [0..$]. That
pesky dollar sign. In microd.c, you can see a couple global
variables there to hack things up. Poo. But, again, it works.)


Library wise, check out src/test/jslang and src/test/browser.
I tried for completeness there, but not full accuracy yet.

This gives free (no generated wrappers) access to regexps,
the array object, string functions, etc. as part of the
core language, and browser has things for the DOM, window,
history, location, canvas, style, json, ajax, etc. - all
just bindings to the native functions.



I'm to the point where I think I'm ready to write a program
with this thing!
Feb 29 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-01 06:20, Adam D. Ruppe wrote:
 I probably should have been working today.... but instead
 spent a good amount of time on this again.
BTW, how do you fit D's class based object model in JavaScript's prototype based object model? -- /Jacob Carlborg
Feb 29 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 07:14:02 UTC, Jacob Carlborg wrote:
 BTW, how do you fit D's class based object model in 
 JavaScript's prototype based object model?
Short answer is each D object in JS has a virtual function array and implements array as properties attached to the object. The JS constructor for the object populates these arrays. Virtual calls thus look like: obj._virtual_table[call_num](); instead of obj.function(); It is similar in principle to how you'd implement it in C. Long answer: A D class is written out like this: function _d_class_NAME(requested_constructor) { _d_class_object.call(this, null); // repeat for all base classes through to Object _d_class_baseclass.call(this, null); this.virtual_function_table[index] = member_function; // repeat for all virtual functions /* BTW, I'm probably going to change this implementation but it will have the same result */ this.implements = ["Object", "Interface_Name", "Base_Class", "This_Class"]; // (these names are actually mangled in the real thing) if(requested_constructor) requested_constructor(this, arguments); } function member_function(arguments..., d_this) { // implementation of the member function } Usage: in D: MyClass a = new MyClass(); a.final_function(); a.virtual_function(); in Javascript: var a = new _d_class_MyClass(default_constructor); // most functions are free functions, like they would be implemented // in C. You pass this as a final parameter: MyClass_final_function(a); // but virtual functions have to use the table: a.virtual_function_table[0](); The index into the virtual table is known by dmd ahead of time, so plain integers are outputted. If you override, what happens is the base class initializer is called first, which creates its virtual functions. Then, your class initializer simply overwrites that entry in the table. (Plain Javascript properties probably could have done this too, with the base class being the prototype, but dmd already has the infrastructure to do it C style, and getting the Js names right in the presence of things like overloading would have been harder to keep straight than a simple integer index.) Whether you access it through a base class, interface, or whatever, the vtable is attached to the object, so it works. The other thing you expect in classes is dynamic casting. That's where the this.implements comes in. If you write cast(Class) object; in D, it outputs var n = __d_dynamic_cast(object, "Class"); The dynamic cast function is implemented in test/object.d as a simple loop: // given an object, should we allow the runtime cast to succeed? // if no, return null. Object __d_dynamic_cast(Object from, string to) { if(from.__d_implements) { foreach(s; from.__d_implements) if(s == to) return from; return null; // it is a D object, but not of this class } // if in doubt, let it pass since we don't want to tie hands // where the programmer knows what he is doing. I might // change this since it isn't actually that good of an idea. // (there's always reinterpret_cast if you know you want it) return from; } But yeah, if the class name is in the implements list, go ahead and return the object; the cast succeeds. If not, do null. This is used in exception handling. In D, if you write: try { throw new Exception("not an error"); } catch(Error e) { assert(0); } you expect the exception to keep flying, since Exception is not an Error. Javascript, though, doesn't have the same concept of types. I implemented this like so: try { throw new _d_Exception(exception_string_constructor, "not an error"); } catch(e) { var was_exception_caught = false; var e_as_error = _d_dynamic_cast(e, "Error"); if(e_as_error) { was_exception_caught = true; 0 || _d_assert(...); } // repeat for other catch blocks, if present if(!was_exception_caught); throw e; // keep it going up the call stack } The dynamic cast lets the program know if we have the right catch block, so it works like you expect it would in D. (Javascript can do something similar with if(e instance of y), but... I'm not 100% sure; I don't do this kind of JS often, but I'm pretty sure instanceof only looks at the constructor - there's no inheritance chain to look at. If we catch(Throwable), we want Error, Exception, and all their subclasses in D.) That initializer that sets up the vtbl also does things like default value initialization, so int a; is == 0 like you expect in D. This got a little fun for the magical "null" word. int[] a = null; a ~= 3; if we translated that as var a = null; a = a.concat(3); // fails, a is null it is no good. JS null isn't the right type. But, D's null knows what type it is! So, NullExp looks like this: if(type->ty == Taarray) // ass array sink("{}"); // use an object literal as this null else if(string) sink("\"\"") else if(array) sink("[]"); else sink("null"); Now, the JS variables are the right type when initialized to D's null. The trick will now be getting is null right... but meh that confuses people in D itself due to implementation details, so I think I'll just make (array is null) mean (array === []) or something along those lines and call it good enough.
Mar 01 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-01 16:07, Adam D. Ruppe wrote:
 On Thursday, 1 March 2012 at 07:14:02 UTC, Jacob Carlborg wrote:
 BTW, how do you fit D's class based object model in JavaScript's
 prototype based object model?
Short answer is each D object in JS has a virtual function array and implements array as properties attached to the object. The JS constructor for the object populates these arrays. Virtual calls thus look like: obj._virtual_table[call_num](); instead of obj.function(); It is similar in principle to how you'd implement it in C. Long answer:
Ok, I see. Thanks for the detailed explanation. -- /Jacob Carlborg
Mar 01 2012
prev sibling next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
I love how this started as interesting and turned into awesome.

Web programming... might actually become non-horrible? 
Mar 01 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 08:01:07 UTC, Daniel Murphy wrote:
 Web programming... might actually become non-horrible?
hehe. I already found it ok though; I've been using D on the server for... will be two years in a couple weeks. Javascript isn't bad if you use it sparingly, and in the last year, my web.d server side thing has just enough javascript to let me write less of it. I just call server side functions in most the JS. I went a little nuts on partial application to make it nice looking; you pass arguments to the callback when you make it. But, it is nice to have this other stuff too. If I have to do a browser game, definitely doing D now, from top to bottom. Work wants ipad apps too... I'll probably do them as downloadable browser things, now in D! Anyway, a few more hours on d to js today. I spent the time working on struct semantics. It is amazing how complicated structs are! Compared to this, classes are just plain easy. My tests file (which I need to run in real D to confirm my thought here, but I think all my asserts are sane) now passes including tests of struct. http://arsdnet.net/dtojs/tests.d I implement structs as Javascript Object()'s, but this doesn't quite match what D expects. 1) JS Object are references, whereas D struct are value. 2) JS variables have indeterminate lifetimes 3) The JS language doesn't have block scoping like D. (1) was a big mess, and I'm sure I don't have it right yet (I know it is a lot less efficient than it could be). My solution was to make all assignments do shallow copies, including function call. void t(MyStruct a) {} t(a); becomes t(__d_struct_copy(a)) Worked for the basics. But, D structs are incredibly complex monsters. opAssign, postblit, copy constructors, blit initializers, expression initializers, TOKconstruct - something I'm not even sure what it actually is. Well, I think I got it. Lots of filthy dirty code, but it passed the test file. I haven't tested struct constructors yet, but they are relatively easy, just like class constructor, so I'm confident it will work. (2) and (3) go together: variable lifetime. D structs die when they go out of scope, both on function returns and exceptions. dmd implemented this as a Scope followed by a Finally. I ended up making it put try {} around the scope, and then write out the finally {}. dmd really did all the work already! And... finally works in Javascript. Amazing, we have struct destructors working like you expect. Moreover, dmd implements scope(exit) the exact same way. Boom, we have scope guards too. To my surprise, scope(failure) and scope(success) Just Worked: dmd set up a flag variable and automatically added it to the appropriate places. As far as I can tell, we have variable lifetime! (JS's garbage collector is still a question, and some of the variables are global - dmd loves the (var a, b) syntax, which is invalid so I made var a in global scope. It is not set to null when done.) Pretty cool. The majority of the language works correctly, though there's a few hacks in there to make it happen. I probably won't upload another zip until the weekend though.
Mar 01 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-02 03:28, Adam D. Ruppe wrote:
 On Thursday, 1 March 2012 at 08:01:07 UTC, Daniel Murphy wrote:
 Web programming... might actually become non-horrible?
As far as I can tell, we have variable lifetime! (JS's garbage collector is still a question, and some of the variables are global - dmd loves the (var a, b) syntax, which is invalid so I made var a in global scope. It is not set to null when done.)
What do you mean with "dmd loves the (var a, b) syntax, which is invalid so"? -- /Jacob Carlborg
Mar 02 2012
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Jacob Carlborg" <doob me.com> wrote in message 
news:jipus9$v81$1 digitalmars.com...
 On 2012-03-02 03:28, Adam D. Ruppe wrote:
 On Thursday, 1 March 2012 at 08:01:07 UTC, Daniel Murphy wrote:
 Web programming... might actually become non-horrible?
As far as I can tell, we have variable lifetime! (JS's garbage collector is still a question, and some of the variables are global - dmd loves the (var a, b) syntax, which is invalid so I made var a in global scope. It is not set to null when done.)
What do you mean with "dmd loves the (var a, b) syntax, which is invalid so"?
CommaExp's containing Declarations
Mar 02 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-02 10:57, Daniel Murphy wrote:
 "Jacob Carlborg"<doob me.com>  wrote in message
 news:jipus9$v81$1 digitalmars.com...
 On 2012-03-02 03:28, Adam D. Ruppe wrote:
 On Thursday, 1 March 2012 at 08:01:07 UTC, Daniel Murphy wrote:
 Web programming... might actually become non-horrible?
As far as I can tell, we have variable lifetime! (JS's garbage collector is still a question, and some of the variables are global - dmd loves the (var a, b) syntax, which is invalid so I made var a in global scope. It is not set to null when done.)
What do you mean with "dmd loves the (var a, b) syntax, which is invalid so"?
CommaExp's containing Declarations
Is he saying "var a, b, c;" is invalid JavaScript code? -- /Jacob Carlborg
Mar 02 2012
parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Jacob Carlborg" <doob me.com> wrote in message 
news:jiq8kb$1ht0$1 digitalmars.com...
 CommaExp's containing Declarations
Is he saying "var a, b, c;" is invalid JavaScript code? -- /Jacob Carlborg
It's invalid if it's a comma expression. eg. auto x = (auto a = 3, a); Which dmd creates _everywhere_.
Mar 02 2012
prev sibling parent reply Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 02/03/2012 02:28, Adam D. Ruppe wrote:

 3) The JS language doesn't have block scoping like D.
Have you considered faking scopes in JS using anonymous functions? ---- var foo; (function(a, b){ var foo; // not the same as the foo outside the func! // do stuff }(x, y)); // invoke immediately with needed arguments from outer scope ---- by passing all the parameters to the anon func you get a speed increase in the lookup on most JS platforms. I don't think they are very pretty, but it is sometimes a useful technique. A...
Mar 02 2012
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 2 March 2012 at 09:33:44 UTC, Alix Pexton wrote:
 Have you considered faking scopes in JS using anonymous 
 functions?
Yeah, though right now I'm trusting the D compiler to keep it straight, and it is doing a pretty good job while being really simple to code. What happens is all the local variables are mangled with respect to their full scope too (which leads to ridiculously long, but unique names). The D scope simply outputs its own code: D: { // create a scope int a = 10; } int a = 20; // the old a is out of scope, so we can do this Javascript: var _D_inner_a = 10; // not a real var name, just demo var _D_outer_a = 20; // new var The inner variable is still in scope, so I doubt Javascript garbage collects it, but thanks to the rules of D, it is never used again. But, if you use a struct with a destructor (or scope(exit)), it generates this: D: { MyStruct a; } MyStruct a; Javascript: try { var _D_inner_A = new MyStruct(); } finally { MyStruct_destructor(_D_inner_A); } try { var _D_outer_A = new MyStruct(); } finally { MyStruct_destructor(_D_outer_A); } And, in this case, Javascript's bizarre scoping actually simplifies things. In Javascript, when you write "var x = y;" in the middle of a function, the way it really works is it adds a "var x;" to the top of the function, and leaves "x = y;" in hte middle. You write: function test() { if(something_here()) { var a = 10; } a++; } Javascript acts as if you wrote: function test() { var a; if(something_here()) { a = 10; } a++; } With our try/finally (that dmd generates, mostly; I didn't have to do much to make this work), the var declartion in the try being hoisted up top means we can be sure it works correctly in the finally, too. But, with regard to the D scoping, dmd mangles the names to make sure you don't reference anything that's out of scope accidentally by giving them unique names. This hoisting behavior is the proper solution to the CommaExp declarations mentioned previously, where dmd likes to write: foo( (var a = 10, a) ) and the sort. Currently, I put the var a; in global scope, leaving just (a=10,a) in the expression. This is legal Javascript, and should be ok due to unique names, but it pollutes the globals. If I add a way to instead put those var declarations in function scope, it is cleaner - no globals - and the same thing Javascript itself would do anyway! I'll have to redo the string buffering to make that though, so it will take some code to do it. Dumping it in the global was simple to implement with what was already there.
 I don't think they are very pretty, but it is sometimes a 
 useful technique.
heh, same with mangled names :)
Mar 02 2012
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:omhitgvibquioulpcxxq forum.dlang.org...
 If I add a way to instead put those var declarations in
 function scope, it is cleaner - no globals - and the same
 thing Javascript itself would do anyway!


 I'll have to redo the string buffering to make that though,
 so it will take some code to do it. Dumping it in the global
 was simple to implement with what was already there.
Btw, in VarDeclaration::toMicroD you're using microd_decl23 as the sink, which results in all var declarations getting doubled. The problem with globals not getting default initialized is here too, it's only using explicit initializers. Something like this should work: // set sink to be one of the normal buffers, not a tee sink(" = "); if (init) init->toMicroD(sink); else type->defaultInit(0)->toMicroD(sink); sink(";\n");
Mar 02 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 3 March 2012 at 00:56:48 UTC, Daniel Murphy wrote:
 Something like this should work:
Awesome, it does! Thanks.
Mar 02 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-02 15:57, Adam D. Ruppe wrote:
 On Friday, 2 March 2012 at 09:33:44 UTC, Alix Pexton wrote:
 Have you considered faking scopes in JS using anonymous functions?
Yeah, though right now I'm trusting the D compiler to keep it straight, and it is doing a pretty good job while being really simple to code. What happens is all the local variables are mangled with respect to their full scope too (which leads to ridiculously long, but unique names).
Wouldn't you save a lot of characters by properly scoping the variables instead of using unique names? The compile JavaScript code would also be more readable. -- /Jacob Carlborg
Mar 03 2012
next sibling parent Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 03/03/2012 12:12, Jacob Carlborg wrote:
 On 2012-03-02 15:57, Adam D. Ruppe wrote:
 On Friday, 2 March 2012 at 09:33:44 UTC, Alix Pexton wrote:
 Have you considered faking scopes in JS using anonymous functions?
Yeah, though right now I'm trusting the D compiler to keep it straight, and it is doing a pretty good job while being really simple to code. What happens is all the local variables are mangled with respect to their full scope too (which leads to ridiculously long, but unique names).
Wouldn't you save a lot of characters by properly scoping the variables instead of using unique names? The compile JavaScript code would also be more readable.
and potentially faster! A...
Mar 03 2012
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 3 March 2012 at 12:12:53 UTC, Jacob Carlborg wrote:
 Wouldn't you save a lot of characters by properly scoping the 
 variables instead of using unique names?
There's no such thing as proper scoping in Javascript. The next best thing is the nested functions, but that's really just trading one poison for another. D mangled names do a lot more than scoping, too, anyway. Mangled names overload properly: void a(int, int); void a(int, string); a(1, "one"); // which one gets called? With dmd's name mangling, it Just Works. Now, there might be something to gain by using prettier local variable names, but it is a lot of extra work and IMO the benefit is still very small. Note that local variables are still local variables 95% of the time (and the other 5% is a bug that I'm hoping to fix today), so its already scoped almost as well as it can be on the function level. The biggest benefit is readability and size. Size is handled by running it through a string replacer (tools/mangledown.d). Readability is a nice gain, but not an essential one I think; it is readable right now if you want to.
Mar 03 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 3 March 2012 at 16:29:25 UTC, Adam D. Ruppe wrote:
 There's no such thing as proper scoping in Javascript.
Let me expand a bit. consider this D: if(1) { int a = 3; } In JS, right now, that'd output: if(1) { var mangled_a = 3; } which, to the interpreter, is: var mangled_a; if(1) { mangled_a = 3; } thanks to declaration hoisting. If you want it to be scoped literally like D, it'd look more like this: if(1) { function() { var a = 3; }(); } I really doubt that'd help performance. Another option is to reuse declarations: if(1) { int a = 0; } string a = ""; could become: var a; if(1) { a = 0; } a = ""; // we know the old a is out of scope, so we'll reuse it but I don't see a big benefit there either. Now, the JS compiler will definitely see a as a dynamically typed var, and may not be able to do the same optimizations it could if it had a consistent type. When you consider the bug-pronedness of me doing this instead of relying on dmd's well debugged mangling process to do it all for me, I really think it is a net loss, despite the slightly more readable names. Oh another thing: global variables in D are module scoped. The mangledness again handles that for me. Just another bug opportunity. Perhaps a smarter helper tool could make pretty names, but I don't want to put it in the compiler.
Mar 03 2012
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/3/12, Adam D. Ruppe <destructionator gmail.com> wrote:
 Oh another thing: global variables in D are module scoped.
Could export help?
Mar 03 2012
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 4 March 2012 at 00:09:11 UTC, Andrej Mitrovic wrote:
 Could export help?
Not for the global (that's handled adequately by dmd's name mangling anyway), but I did just add export checking as comments. export void foo() {} becomes function /*export*/ mangled_foo() {} the idea is then tools like gcfunctions will know not to strip that function out, since it may be referenced in another module. It also occurs to me that .di generation may be useful here for things like server communication. So that might be cool.
Mar 04 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-03 17:29, Adam D. Ruppe wrote:
 On Saturday, 3 March 2012 at 12:12:53 UTC, Jacob Carlborg wrote:
 Wouldn't you save a lot of characters by properly scoping the
 variables instead of using unique names?
There's no such thing as proper scoping in Javascript. The next best thing is the nested functions, but that's really just trading one poison for another.
Ok, I see.
 D mangled names do a lot more than scoping, too, anyway.
 Mangled names overload properly:

 void a(int, int);
 void a(int, string);

 a(1, "one"); // which one gets called?


 With dmd's name mangling, it Just Works.
Well, functions are different.
 Now, there might be something to gain by using prettier
 local variable names, but it is a lot of extra work and
 IMO the benefit is still very small.


 Note that local variables are still local variables
 95% of the time (and the other 5% is a bug that I'm
 hoping to fix today), so its already scoped almost
 as well as it can be on the function level.



 The biggest benefit is readability and size. Size is handled
 by running it through a string replacer (tools/mangledown.d).

 Readability is a nice gain, but not an essential one I think;
 it is readable right now if you want to.
-- /Jacob Carlborg
Mar 03 2012
prev sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 01/03/2012 05:20, Adam D. Ruppe wrote:
 I probably should have been working today.... but instead
 spent a good amount of time on this again.

 New zip:

 https://github.com/downloads/adamdruppe/dtojs/dtojs-0.3.zip

 (I haven't cleaned up the github fork yet)

 To give you an idea of what is working, check out
 my tests.d file:

 http://arsdnet.net/dtojs/tests.d

 This compiles (raw) into this:
 http://arsdnet.net/dtojs/tests.js

 BTW, when compiling, be sure to put test/object.d
 on your command line too, or the runtime functions
 won't be present in your .js file!

 23 KB (down to 11 KB if you run the included mangledown tool
 on it. gcfunctions can often make a big difference, but not here,
 since it removes what you don't use. A test that doesn't use
 something is an incomplete test!)


 I think I broke std.algorithm again :(, but fixed a lot of
 other stuff. (it is the lambda generator in std.algorithm that
 is breaking. The JS has the function, but it is nested too deep
 and inaccessible to the actual algorithm.)



 But, a lot of stuff works now, and the generated code isn't
 half bad. I've started using more static type info to slightly
 optimize it too, but only some basics.


 One of the messiest things was try/catch. JS doesn't do
 types like D, so I implemented it with a series of
 if(dynamic_cast()), and ultimately rethrow if none matched.

 A bit ugly, but it seems to pass the tests!
This is really cool! It would be quite interesting to run the dmd testsuite through it and see how much passes. Same goes for phobos unittests (obviously both of these would fail for system stuff like inline asm...) I'd also be interested in some benchmarks (eg std.algorithm.sort vs Array.sort), but that seems a bit pointless really. Might be interesting to throw in some optimisations when translating though (though you're doing some of these already!) Interesting idea: version(JavaScript) asm { /* Well... it's not really asm, but it's as close as you could get with a javascript backend :p */ document.write("Oh look, inline javascript D-:"); } Perhaps it would be better to have a dedicated function for that though. -- Robert http://octarineparrot.com/
Mar 01 2012
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 March 2012 at 16:29:10 UTC, Robert Clipsham wrote:
 Perhaps it would be better to have a dedicated function for 
 that though.
eval() :) I considered doing asm {} for javascript, but that'd be a pretty invasive change to the compiler, so I decided against it; I want to keep most the changes as simple as possible. One possibility would be a special function, let's call it static_eval, that takes a string but instead of being a function call, simple pastes the string itself into the js file. But, I haven't really wanted it yet! All the functions I want have been implementable in relatively plain D (with the addition of the __js_keywords in some places), except foreach on associative arrays. I had to hardcode that function, since there's no way to represent for(i in obj) on the low level. For phobos btw, I haven't decided how to run with that yet. My first thought was to implement my own version - test/std shows this - that emulates the interface using native JS functions where possible. That will be hard to keep up to date, and causes conflicts if you want to borrow a little from the real Phobos. So eh, I don't know yet.
Mar 01 2012
prev sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 01.03.2012, 17:29 Uhr, schrieb Robert Clipsham <robert octarineparrot.com>:

 Interesting idea:

 version(JavaScript) asm
 {
      /* Well... it's not really asm, but it's
         as close as you could get with a javascript backend :p */
      document.write("Oh look, inline javascript D-:");
 }

 Perhaps it would be better to have a dedicated function for that though.
How about: pragma(js) { document.write("Oh look, inline javascript D-:"); }
Mar 08 2012
prev sibling next sibling parent "Jean-Bernard Pellerin" <jeanbern ualberta.ca> writes:
This will go nicely with the web framework I'm building in D. I'm 
borrowing heavily from silverlight. Here's a teaser (sorry, 
neglected to comment the code...)

Here's a sample code file (CGI script for apache, I'm new to 
these web technologies):
http://pastebin.com/SpfmfpmS

and here's what the resulting site looks like, sorry for the 
image quality

before pressing the button:
http://i.imgur.com/JGvMC.png
after:
http://i.imgur.com/9ZiQp.png
Notice how I clicked a different tab (woot)

It's my first time using HTML, CSS, or JS, so it's a bit rough. 
But I learn it as I go along, to perform the code generation.

A whole lot of really neat CTFE and mixins went into having the 
Control classes and Factory working as smoothly as they do. I'll 
publish it on my blog once it's built (I want to showcase 
darklight with a blog written in darklight) :D

But I just noticed you have a whole suite of D web code, I'll 
have to look into it.

Thanks for all the hard work you've put into D, it's quite a feat.
Mar 01 2012
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
This is still alive:

https://github.com/adamdruppe/dmd/tree/dtojs

Merging in DMD changes as they happen has been fairly
easy, so we have things like UFCS in there.

I'm pretty happy with the core setup, though it still
isn't finished. Enough of the D language works like
you expect that you can do a lot of things with it
naturally.

Thus, I've moved on to libraries. I previously
talked about the jslang and browser packages. These
provide zero-overhead, direct access to javascript
built-ins.

You can also use a good chunk of the real Phobos in
here if you want.


But now, I'm adding minimal overhead nicer libraries,
including a port of my dom.d, adopted to try to
cover some browser incompatibilities. (The browser
package, being zero overhead, makes no attempt at
this. It just provides the tools to DIY.)


The trick is though, doing it with as lean code as
possible. Here's my domtest.d:

import arsd.dom;
import browser.window;

void main() {
	Element e = document.getElementById("cool");
	e.addClass("sweet");
	e.style = "font-weight: bold;";
	e.style.fontSize = "30px";
	e.innerText = e.style;
	window.alert(e.parentNode.tagName);
	e.removeFromTree();
}


It generates about 2 kb of javascript, libraries
included, after you strip unused functions and
reduce the variable name length. (NOT gzipped!)

Let's talk about one line at a time:

	Element e = document.getElementById("cool");

In browser.document, there are JSElement and JSDocument
classes defined. Here, though, I'm using a custom
type: Element.

The implementation for this uses zero overhead forwarding
to native methods, unless I override them, in which case
it is implemented as a free function.

Many functions are now mixin templates in browser.document
so I don't have to repeat them, even if changing types.

Using alias this, these are compatible with the native
types as well.


	e.addClass("sweet");

Is a new function in class Element. It manipulates the
native className property and in the resulting .js file
is a free function.

	e.style = "font-weight: bold;";

The style object is defined in browser.document and has
a  long list of properties. It maps directly to native
code, but with one addition:

    alias cssText this;


style.cssText in Javascript is the attribute as a string.
In my dom.d, Element.style can be treated as a string or
a struct, and I wanted that here too.

alias this accomplishes that goal with zero overhead.
e.style = ""; translates simply to e.style.cssText = "";

	e.style.fontSize = "30px";

The property is a native one, nothing special here.

	e.innerText = e.style;

innerText, while a property on some browsers, isn't present
on all of them.

Thus, class Element defines it itself. This generates a free
function (with a mangled D name, so no conflict) that is
called using D property syntax.

The generated code looks like this:
     _D_mangled_innerText(e.style.cssText, e);



This is the general pattern I'll do for browser compatibility.
Use the real name in D, but let it implement as free functions
with mangled names.

	window.alert(e.parentNode.tagName);


The browser.window module defines some things that are global
in JS, including alert(). e.parentNode returns an Element,
thanks to a mixin that can specialize on types with zero overhead.


tagName, while a native property, is actually a function here.
The reason is dom.d uses lowercase tag names, but Javascript
uses uppercase.

Thus, this is implemented:

 property string tagName() { return 
__js_this.tagName.toLowerCase(); }


and the above line calls a D function. Some overhead, but very
little.

	e.removeFromTree();


Finally, this is just a regular function. I'm thinking about
changing it to UFCS though so it can check for null on e too.

(It does:

  if(parentNode) parentNode.removeChild(this);

the idea being to just ensure it isn't in the tree without
needing an external null check.

If this is null, it is also not in the tree, so its contract
is satisified anyway, so it might as well succeed. Currently,
though, it will not work since the Element invariant will
segfault it.)




But, there's a rundown of what I'm doing with libraries.
Beautiful D code, compatible implementations, minimal
overhead.


I'll be posting the library soon, and then this will
be sharable.
Mar 17 2012
parent reply Jonathan I Levi <catanscout gmail.com> writes:
Did this thing ever get to a release/usable point?
Apr 19 2018
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 19 April 2018 at 16:20:22 UTC, Jonathan I Levi wrote:
 Did this thing ever get to a release/usable point?
Not really. I didn't find it worth the trouble after using it in a few experimental projects and basically let it go like six years ago. The compiler has significantly changed since then, so it'd have to be rewritten. You might use the ldc fork with emscripten instead (of you don't mind code bloat. that is something that bothers me...)
Apr 19 2018