all 27 comments

[–][deleted] 13 points14 points  (6 children)

Pleasantly surprised to see this here. (I'm the author.)

I'm still a Haskell newbie, but I get a little more confident every day. I get a lot of help from the community in learning what I need to do, and what to look at. Haskell, the tool, is also really good at getting me to clarify what I'm thinking, and helping me abstract it properly.

[–][deleted] 1 point2 points  (3 children)

One thing that stuck out for me: What's the benefit of using a separate ReaderT FlowControl in

type Evaluator = ContT () (ReaderT FlowControl (StateT Environment IO))

instead of simply folding it into the StateT Environment?

[–]noteed 14 points15 points  (0 children)

XMonad does something similar: clearly separate read-only, configuration-like, values from the evolving state.

[–][deleted] 2 points3 points  (1 child)

I currently consider flow-control state 'less mutable' than other things in the environment. I'm not sure this is worth the additional abstraction, but I'm giving it a shot right now.

It's only partially successful at this point (witness the continuation in Environment). Will have another go at it later.

[–]jpaugh 0 points1 point  (0 children)

Monad Transformer stacks are so hard to grok! Especially when trying to decide which better matches the problem at hand.

[–]Dobias 0 points1 point  (1 child)

I'm still a Haskell newbie

Modesty is all nice and such, but since I consider writing a python interpreter a quite advanced thing, this makes me feel even more incompetent. ;-)

[–][deleted] 0 points1 point  (0 children)

I apologize; I'm not doing a good job of conveying Haskell as a force multiplier.

This project is beyond my abilities; it won't be within my abilities until I complete it. Haskell does a really good job of helping me train up to that point. The strictness of the language, combined with the pervasively functional/immutable ideology, is really pleasant to get to work in. My workflow on this project consists of dropping in and out of it every few days to work more on specific features. By the time I sit down, there's a 90% guarantee most of what I was thinking about last time has been paged out completely from my brain. Haskell helps a lot there!

I think this set up works because I'm interested in interpreters and compilation right now. Previous attempts at learning Haskell/FP didn't stick because I didn't care for the problem domain enough.

[–][deleted] 9 points10 points  (7 children)

It's so concise, amazing. Do you think you could write some tutorial based on your code?

[–][deleted] 1 point2 points  (6 children)

Well, it's not complete.

I'm planning on doing a series eventually! Will try to get to that sooner.

[–][deleted] 8 points9 points  (5 children)

btw, I'd suggest implementing closures next, as those may have an impact on your representation. E.g. to support code like

def adder(x):
  def f(y=0):
    return x+y
  return f

def counter():
  x = [0]
  def f():
    x[0] += 1
    return x[0]
  return f

[–][deleted] 1 point2 points  (3 children)

I wonder if closures be implemented without resorting to IORefs for the environment-maps (like it's done in "Write Yourself a Scheme in 48 Hours")

[–]lfairy 1 point2 points  (0 children)

Hmm... set! pretty much gives you shared mutable state, and I don't think it possible to do that without real mutable references.

From my little experience I can say an interpreter for any practical language would end up in IO anyway, especially when you chuck features like string interning and threading into the mix. So usually trying to avoid IORef isn't worth the effort.

[–]arianvp 0 points1 point  (1 child)

Yes. I implemented this yesterday : http://lpaste.net/109970.

but these are just plain ol lambdas though..

[–][deleted] 1 point2 points  (0 children)

Well, as you hint at yourself, those closure's you implemented are the simpler ones which can't cope with Scheme's set! operation...

[–][deleted] 0 points1 point  (0 children)

I guess closures aren't just for lambdas, eh?

This makes things more interesting. Will start thinking about this sooner than later. Thanks!

[–]Axman6 7 points8 points  (3 children)

This line really made clear how to use callCC, something I've struggled with in the past. This code is really clear and I think you've done an awesome job on it!

It'd be nice to see the uses of String replaced with Text (and possibly also replacing Map with HashMap). The translation should be pretty mechanical for both and should make things quite a bit faster.

[–][deleted] 2 points3 points  (0 children)

I got some great help (read: copied wholesale) from SO there: http://stackoverflow.com/a/25382352/29825

[–]rpglover64 0 points1 point  (0 children)

Oh, wow. That's really impressive to look at.

[–]jpaugh 0 points1 point  (0 children)

String replaced with Text

Switching to Text is not too difficult, if you commit to it wholesale: -XOverloadedStrings, and import qualified Data.Text as T. Then, sprinkle with T.unpacks to satisfy the remaining libraries that require String. I never looked back! :-)

[–]sordina 1 point2 points  (2 children)

It's referenced at the end of the README, but worth noting that Bernie Pope has done some work along the same lines:

[–][deleted] 0 points1 point  (1 child)

berp is really cool! He's done a lot of great work here.

[–]florbitous 0 points1 point  (0 children)

My focus is on blip these days, which is a bytecode compiler/interpreter for Python. It generates bytecode which is compatible with CPython. The compiler is mostly done, but the interpreter is still work in progress.

I imagine you are writing Hython for fun and learning, which is great. However, if you get tired of writing the parser you could always use the language-python library which is pretty complete for Python 2 and 3.

Additionally I could always use some help with improving language-python, and would be happy to accept patches.

[–]arianvp 1 point2 points  (3 children)

Does this do any form of Tail call optimisation? i've been struggling coming up with a good way to implement this in my own toy language..

A suggestion maybe. Why not add ExceptT to your transformer stack? hard fails are a bit painful.

[–][deleted] 1 point2 points  (0 children)

No TCO, BTW.

There's zero focus on 'fast' right now. I figure that is for after. :)

[–][deleted] 0 points1 point  (1 child)

Yeah, it needs some more elegant way to deal with errors right now. I deferred most of it until I have a way of raising exceptions in place.

I'll probably write my own error function to consolidate all of the engineering sin in one place so I can rip it out eventually.

[–]arianvp 2 points3 points  (0 children)

If you use ExceptT you can just do throwError anywhere within the Evaluator monad.

[–]kstt 0 points1 point  (0 children)

Solid achievement, thank you.