February 29, 2012 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe Attachments:
| 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | I love how this started as interesting and turned into awesome. Web programming... might actually become non-horrible? |
March 01, 2012 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bystroushaak | "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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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 Re: D to Javascript converter (a hacked up dmd) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Clipsham | 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.
|
Copyright © 1999-2021 by the D Language Foundation