February 29, 2012
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
March 01, 2012
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!
March 01, 2012
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
March 01, 2012
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


March 01, 2012
I love how this started as interesting and turned into awesome.

Web programming... might actually become non-horrible?


March 01, 2012
"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.


March 01, 2012
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.
March 01, 2012
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. :)
March 01, 2012
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/
March 01, 2012
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.