www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Interactive D?

reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
I got the idea to investigate the possibility of an interactive D 
interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
and what follows is a short demo.

Could there be any interest in pursuing this?

(# --- are just comments)

$ ./interactiveD
Interactive D version 0.0.1
Type "help" for more information.

# --- Basic expressions

 1+1



ans = 2 (int)
 x = 2



x = 2 (int) # --- Dynamic types
 x = x * 5.0



x = 10 (double)
 x++



ans = 10 (double) # --- Variables
 who



Variables: x = 11 (double) ans = 10 (double) # --- Error recovery
 foo(5)



input:1: Error: undefined identifier foo input:1: Error: function expected before (), not foo of type int Failed to evaluate # --- Dynamic module imports (and on the fly compilation)
 import test



 foo(5)



ans = 26 (int) # --- Automatic dependency checking and dynamic recompilation
 foo(5)



test.d changed on disk. Recompiling. ans = 25 (int) # --- Standard library access
 import std.math



 cos(1.0)



ans = 0.540302 (real)
 import std.stdio



 writefln("Hello World")



Hello World # --- UDTs
 a = Vec(1,5)



a = [1,5] (test.Vec)
 b = Vec(3,2)



b = [3,2] (test.Vec)
 a+b



ans = [4,7] (test.Vec)
 import



Imports: test std.math
 import std.string



# --- Bugs :)
 "a b c d e".split()



ans = [l,e,.,,s] (char[][])
 "a b c d e".dup.split()



ans = [a,b,c,d,e] (char[][]) # --- Templates
 import multiarray



 x = ArraySlice!(int,2)(3,4)



x = (3x4) 0 0 0 0 0 0 0 0 0 0 0 0 (multiarray.ArraySlice!(int,2))
 x.diag[] = 1



ans = (3) 1 1 1 (multiarray.ArraySlice!(int,1))
 x



ans = (3x4) 1 0 0 0 1 0 0 0 1 0 0 0 (multiarray.ArraySlice!(int,2))
 x.transpose()



 x



ans = (4x3) 1 0 0 0 0 1 0 0 0 0 1 0 (multiarray.ArraySlice!(int,2))
 x[range(0,$), 1] = 2



ans = (4) 2 2 2 2 (multiarray.ArraySlice!(int,1))
 x



ans = (4x3) 1 0 0 0 2 2 2 2 0 0 1 0 (multiarray.ArraySlice!(int,2)) -- Oskar
Feb 22 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 Could there be any interest in pursuing this?

A interactive shell interpreter is very useful to learn the language, and to try little snippets of code before copying them into the code. Python and Scheme programmers do it all the time, and it's one of the advantages of those languages. So I think this may become quite useful. How does it work? Do you use the run-time compiler lib recently announced? Bye, bearophile
Feb 22 2008
next sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
bearophile wrote:
 Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 Could there be any interest in pursuing this?

A interactive shell interpreter is very useful to learn the language, and to try little snippets of code before copying them into the code. Python and Scheme programmers do it all the time, and it's one of the advantages of those languages. So I think this may become quite useful. How does it work? Do you use the run-time compiler lib recently announced?

I don't use exe-lib. What Burton Radons has done is seriously impressive and is a much bigger project than my small hack. I have constrained myself to using the system built-in dynamic linking tools (dlopen,dlclose et. al. or LoadLibrary/FreeLibrary on win32). What the code does is basically creating some run-time d-code wrapping the expression together with some helpers to feed data and type information back and forth. It then compiles the generated code into object code and transforms it into a dynamic library loadable with dlopen. The generated library is then loaded, executed and unloaded within the interpreters memory space. The "import" statement compiles the corresponding .d source file and its dependencies into one dynamic library per module, and then loads them into the interpreter. If, at any time, a .d source file is changed the corresponding module (and modules depending on that module) are unloaded, recompiled and reloaded. Burton's approach seems very interesting though. Not primarily speed wise, since interactive speeds are enough for an interactive application and a 50 ms delay compared to Burton's 1 ms is not very noticeable. Instead, the major advantage of exe-lib is that it allows a much finer control over library loading than the blunt dlopen/LoadLibrary. For example, the possibility of having a callback resolving missing symbols would be extremely useful. -- Oskar
Feb 23 2008
parent oliver <oliver.ruebenkoenigREM web.de> writes:
Oskar Linde Wrote:

 bearophile wrote:
 Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 Could there be any interest in pursuing this?



This sounds both interesting and helpful! I often find that a repl reduces development time. [...snip....]
 
 What the code does is basically creating some run-time d-code wrapping 
 the expression together with some helpers to feed data and type 
 information back and forth. It then compiles the generated code into 
 object code and transforms it into a dynamic library loadable with 
 dlopen. The generated library is then loaded, executed and unloaded 
 within the interpreters memory space.
 
 The "import" statement compiles the corresponding .d source file and its 
 dependencies into one dynamic library per module, and then loads them 
 into the interpreter. If, at any time, a .d source file is changed the 
 corresponding module (and modules depending on that module) are 
 unloaded, recompiled and reloaded.

I am curious on how you did that. Did you put the code somewhere (dsource) to look at? Is it possible to write some text file with a couple of commands, read that into the interpreter and, once i like the output, compile it? [ ...snip...] Oliver
Feb 24 2008
prev sibling parent reply renoX <renosky free.fr> writes:
bearophile a écrit :
 Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of
 concept, and what follows is a short demo. Could there be any
 interest in pursuing this?

A interactive shell interpreter is very useful to learn the language, and to try little snippets of code before copying them into the code.

Well D being statically typed and this 'interactive D' being dynamically typed, I'm not sure that the interpreter is usable for this purpose. That said, I'm quite impressed with the work.. Only one afternoon of work? Wow! renoX
 Python and Scheme programmers do it all the time, and it's one of the
 advantages of those languages. So I think this may become quite
 useful. How does it work? Do you use the run-time compiler lib
 recently announced?
 
 Bye, bearophile

Feb 24 2008
parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
renoX wrote:
 bearophile a écrit :
 Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of
 concept, and what follows is a short demo. Could there be any
 interest in pursuing this?

A interactive shell interpreter is very useful to learn the language, and to try little snippets of code before copying them into the code.

Well D being statically typed and this 'interactive D' being dynamically typed, I'm not sure that the interpreter is usable for this purpose.

The only part where the dynamical typing takes place is during assignment to the interactive variables. One could quite easily remove that dynamic typing. It was just easier doing it this way. :)
 That said, I'm quite impressed with the work..
 Only one afternoon of work? Wow!

I'll put the code online in a few days so you can see that it is much less impressive than it might seem. :P -- Oskar
Feb 26 2008
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Oskar Linde" <oskar.lindeREM OVEgmail.com> wrote in message 
news:fpmpa6$2muq$1 digitalmars.com...
I got the idea to investigate the possibility of an interactive D 
interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
and what follows is a short demo.

 Could there be any interest in pursuing this?

[snip a ton of amazingness]
 -- 
 Oskar

:O I think you get a cookie for this. Nay, an entire _cake_.
Feb 22 2008
prev sibling next sibling parent torhu <no spam.invalid> writes:
Oskar Linde wrote:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 
 Could there be any interest in pursuing this?

This is definitely interesting. I remember wanting something like this a while ago. If it's properly done, it could move D one step closer to Python. Interactive testing of algorithms is very handy.
Feb 22 2008
prev sibling next sibling parent Alexander Panek <alexander.panek brainsware.org> writes:
Oskar Linde wrote:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 
 Could there be any interest in pursuing this?

Awesome! How are you doing this? Wrapping your constructs into int main () {} and returning/outputting the result of the operation, catching the pipe and pretty-printing it? Anyways, impressive!
Feb 22 2008
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
I would love to see that as a Descent view. It looks really awesome!

Oskar Linde escribió:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.
 
 Could there be any interest in pursuing this?

Feb 22 2008
prev sibling next sibling parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
On Fri, 22 Feb 2008, Oskar Linde wrote:

 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, and 
 what follows is a short demo.

 Could there be any interest in pursuing this?

I've been waiting for a repl for years. Great work. Some further ideas: catching exceptions, displaying the values and types of structs/classes and their members recursively (if the default uses toString) -- hopefully this will encourage Walter to fix some of the unspecified behavior with .stringof, exporting the current state to a file, locating symbol definitions.
Feb 22 2008
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Jari-Matti Mäkelä wrote:
 
 
 On Fri, 22 Feb 2008, Oskar Linde wrote:
 
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of 
 concept, and what follows is a short demo.

 Could there be any interest in pursuing this?

I've been waiting for a repl for years. Great work. Some further ideas: catching exceptions, displaying the values and types of structs/classes and their members recursively (if the default uses toString) -- hopefully this will encourage Walter to fix some of the unspecified behavior with .stringof, exporting the current state to a file, locating symbol definitions.

Catching exceptions actually already work:
 a = [1,2,3][]



a = [1,2,3] (int[])
 a[3] = 4



ArrayBoundsError input(1)
 a ~= 4



ans = [1,2,3,4] (int[]) Regarding stringof. The following is irritating, given: template A(T) { struct A {} } template B(T) { struct A {} struct B {} } A!(int) a; B!(int).B b; How do I reliably get the string representation of the type of a and b? There are two ways that I know of: 1. typeid(typeof(x)).toString 2. typeof(x).stringof The problem is that the results are: 1A: test.A!(int).A WRONG 1B: test.B!(int).B CORRECT 2A: A!(int) CORRECT (although not fully qualified) 2B: B WRONG So neither way works for both cases... Your other points are interesting and useful, but some of them are quite hard. I can't do much more than the D compiler can do at compile + runtime together. -- Oskar
Feb 26 2008
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Oskar Linde" <oskar.lindeREM OVEgmail.com> wrote in message 
news:fq126m$enh$1 digitalmars.com...

 Regarding stringof. The following is irritating, given:

 template A(T) { struct A {} }
 template B(T) { struct A {} struct B {} }

 A!(int) a;
 B!(int).B b;

 How do I reliably get the string representation of the type of a and b?

 There are two ways that I know of:

 1. typeid(typeof(x)).toString
 2. typeof(x).stringof

 The problem is that the results are:

 1A: test.A!(int).A WRONG

This one is correct, as far as I can see. A!(int) a; is just sugar for A!(int).A a;.
Feb 26 2008
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Jarrett Billingsley wrote:
 "Oskar Linde" <oskar.lindeREM OVEgmail.com> wrote in message 
 news:fq126m$enh$1 digitalmars.com...
 
 Regarding stringof. The following is irritating, given:

 template A(T) { struct A {} }
 template B(T) { struct A {} struct B {} }

 A!(int) a;
 B!(int).B b;

 How do I reliably get the string representation of the type of a and b?

 There are two ways that I know of:

 1. typeid(typeof(x)).toString
 2. typeof(x).stringof

 The problem is that the results are:

 1A: test.A!(int).A WRONG

This one is correct, as far as I can see. A!(int) a; is just sugar for A!(int).A a;.

Nope, if implicit template properties is in action, A!(int) is the only valid way to refer to the template instance. If that weren't the case, consider: template A(T) { struct A { int A; }} what is A!(int).A ? And that reminds me that this ( http://d.puremagic.com/issues/show_bug.cgi?id=242 ) ancient bug is still unresolved: template A() { template A() { alias int A; }} A!()!() x; // found '!' when expecting ';' following 'statement' -- Oskar
Feb 26 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Oskar Linde" <oskar.lindeREM OVEgmail.com> wrote in message 
news:fq18lf$120r$1 digitalmars.com...

 1A: test.A!(int).A WRONG

This one is correct, as far as I can see. A!(int) a; is just sugar for A!(int).A a;.

Nope, if implicit template properties is in action, A!(int) is the only valid way to refer to the template instance. If that weren't the case, consider: template A(T) { struct A { int A; }} what is A!(int).A ?

Ah, I see. You're right that A!(int).A does not compile. However I can still understand that the compiler would stringize it as "A!(int).A", since that's how it's defined and how it's represented. I suppose that the question of whether .stringof should give compilable code or not is under debate.
Feb 26 2008
prev sibling next sibling parent reply Matti Niemenmaa <see_signature for.real.address> writes:
Oskar Linde wrote:
 Regarding stringof. The following is irritating, given:
 
 template A(T) { struct A {} }
 template B(T) { struct A {} struct B {} }
 
 A!(int) a;
 B!(int).B b;
 
 How do I reliably get the string representation of the type of a and b?
 
 There are two ways that I know of:
 
 1. typeid(typeof(x)).toString
 2. typeof(x).stringof

Don't forget that .stringof can be overridden in structs/classes. For instance: import tango.io.Stdout; class A { static char[] stringof = "foo"; } class B {} void main() { A a; B b; Stdout(A.stringof).newline; Stdout(typeof(a).stringof).newline; Stdout((new A).stringof).newline; Stdout(B.stringof).newline; Stdout(typeof(b).stringof).newline; Stdout((new B).stringof).newline; } The above prints: foo foo foo B B new B So .stringof can't really be considered "reliable" per se. Library developers should probably always document in big, bold letters: ".stringof should never be redefined!!" I wouldn't be surprised if something like the above were to break much existing template code. (Although I don't really know how much .stringof is used in practice.) -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Feb 26 2008
parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
On Tue, 26 Feb 2008, Matti Niemenmaa wrote:

 Oskar Linde wrote:
 Regarding stringof. The following is irritating, given:
 
 template A(T) { struct A {} }
 template B(T) { struct A {} struct B {} }
 
 A!(int) a;
 B!(int).B b;
 
 How do I reliably get the string representation of the type of a and b?
 
 There are two ways that I know of:
 
 1. typeid(typeof(x)).toString
 2. typeof(x).stringof

Don't forget that .stringof can be overridden in structs/classes. For instance: import tango.io.Stdout; class A { static char[] stringof = "foo"; } class B {} void main() { A a; B b; Stdout(A.stringof).newline; Stdout(typeof(a).stringof).newline; Stdout((new A).stringof).newline; Stdout(B.stringof).newline; Stdout(typeof(b).stringof).newline; Stdout((new B).stringof).newline; } The above prints: foo foo foo B B new B So .stringof can't really be considered "reliable" per se. Library developers should probably always document in big, bold letters: ".stringof should never be redefined!!"

Oh god. Here's some other results of overriding properties. Again some signs of inconsistency can be found: override can be used on property can be overridden runtime compiletime .stringof - y y y .tupleof - y n n .mangleof - n* n y .init - y y y .sizeof - n* n y * = override gives error, but still works on compile time Are there any good reasons for overriding any of those? The override doesn't even need to be of the same type.
 I wouldn't be surprised if something like the above were to break much 
 existing template code. (Although I don't really know how much .stringof is 
 used in practice.)

.stringof is pretty much the only way to provide decent compile time reflection with D1.
Feb 26 2008
prev sibling parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

---1463811840-1942746821-1204051296=:23763
Content-Type: TEXT/PLAIN; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8BIT

On Tue, 26 Feb 2008, Oskar Linde wrote:

 Jari-Matti Mäkelä wrote:
 Some further ideas:
 
 catching exceptions, displaying the values and types of structs/classes and 
 their members recursively (if the default uses toString) -- hopefully this 
 will encourage Walter to fix some of the unspecified behavior with 
 .stringof, exporting the current state to a file, locating symbol 
 definitions.

Catching exceptions actually already work:

Cool.
 Regarding stringof. The following is irritating, given:

 template A(T) { struct A {} }
 template B(T) { struct A {} struct B {} }

 A!(int) a;
 B!(int).B b;

 How do I reliably get the string representation of the type of a and b?

 There are two ways that I know of:

 1. typeid(typeof(x)).toString
 2. typeof(x).stringof

 The problem is that the results are:

 1A: test.A!(int).A	WRONG
 1B: test.B!(int).B	CORRECT

 2A: A!(int) 		CORRECT (although not fully qualified)
 2B: B 			WRONG

demangle(x.mangleof), x.init.stringof, and typeid(typeof(x)).stringof) seem to be the only ways to return the full FQN (including template member names) on compile time, but one needs to have a demangle routine then first.
 Your other points are interesting and useful, but some of them are quite 
 hard. I can't do much more than the D compiler can do at compile + runtime 
 together.

The reflection stuff should be possible to do on compile time (only enums fail). I'm not sure about exporting current state, now that I heard how the utility works. Locating definitions is probably the hardest and needs FQNs, maybe something more. ---1463811840-1942746821-1204051296=:23763--
Feb 26 2008
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Oskar Linde:
 I got the idea to investigate the possibility of an interactive D 
 interpreter. A lazy afternoon of hacking resulted in a proof of concept, 
 and what follows is a short demo.

Now I have realized that such interpreter may allow to port to D one *wonderful* thing present in the Python std lib, that I sorely miss, that is the doctest, it's the lowest-complexity unit testing (invented by Tim Peters and partially by Peter Norvig): http://docs.python.org/lib/module-doctest.html This module alone can justify this work of yours, Oskar. Bye, bearophile
Mar 06 2008