
How to Implement a Programming Language in JavaScript - cristiantincu
http://lisperator.net/pltut/
======
chubot
I've written multiple parsers/interpreters in both JS and Python -- Python
being my favorite language. From that experience, I've come around to the fact
that they're both the wrong language for writing languages -- lexers, parsers,
interpreter loops, compilers.

I have a good analogy to explain this. Take this OCaml program.

    
    
        let sum_file filename =
          let file = In_channel.create filename in
          let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in
          let sum = List.fold ~init:0 ~f:(+) numbers in
          In_channel.close file;
          sum
        ;;
    

This is roughly equivalent to:

    
    
        def sum_file(filename):
          with open(filename) as f:
            return sum([int(x) for x in f])
           

Now think of the degree to which OCaml is awkward here. That's exactly how
awkward Python and JS are for writing languages :)

OCaml is based around ML-style typed records, which are exactly what you need
for manipulating languages.

I am not a type safety guy, but when you write languages, there are tons of
nested conditionals. In Python in JS or C, you end up with bugs in those
corners. It is quite easy to crash any non-trivial parser, like the CPython
parser, or Clang's parsers, etc. The type safety that ML offers helps a lot
with this.

The code for writing parsers and interpreters is just SHORTER in OCaml than in
Python. I used to think Python was the most concise language. But no, it
depends on the problem domain. Try it and you'll see.

Someone saying the same thing here:

[http://flint.cs.yale.edu/cs421/case-for-
ml.html](http://flint.cs.yale.edu/cs421/case-for-ml.html)

~~~
mightybyte
I 100% agree that JS and Python are the wrong language for writing languages.
Haskell, however gets you the best of both worlds. Your sum_file function in
Haskell would look like this:

    
    
        sumFile :: FilePath -> IO Int
        sumFile file = sum . map read . lines <$> readFile file
    

I don't think many people would dispute that Haskell is at least as good as
OCaml for writing languages. And strangely enough, the most advanced Perl 6
implementation is even written in Haskell!

~~~
chubot
Right, I was referring to all ML-based languages -- so SML, OCaml, Haskell,
F#, and possibly even Rust.

Do you know how this would look in Haskell?

    
    
        # Return K most common lines in a file
    
        def top_k(f, k):
          counts = collections.defaultdict(int)
          for line in f:
            counts[line] += 1
    
          return sorted(counts.items(), key=lambda x: x[1], reverse=True))[:k]
        
           

I was actually looking for the OCaml example which does this. I think it was
in "Real World OCaml", and I remember it being horribly ugly compared to
Python. I couldn't find it though.

~~~
mightybyte
I would do it something like this:

    
    
        top xs = map fst $ sortBy (compare `on` Down . snd) $
            M.toList $ foldr (\x -> M.insertWith (+) x 1) mempty xs
    

This has the type `top :: Ord a => [a] -> [a]`. You might object that I didn't
include your k parameter. Because Haskell is a lazy language, I can get your
behavior very simply by doing `take n . top` and it will lazily only calculate
the first n values. This gives you more abstractive power and lets you write
more composable code.

~~~
chubot
Yeah, so this sort of proves my point :)

I don't begrudge anyone if they want to use Haskell or OCaml for everything.

But personally I am interested in using ML-like languages for language
engineering and not general purpose programming (maybe Rust could change that,
but I'm not convinced). I program in 5+ different languages regularly so I've
dealt with all the friction involved, mainly by explicitly designing systems
as heterogeneous collections of Unix processes.

~~~
mightybyte
Hmmm, I'm not sure what you're saying. What point does it prove? I've been
using Haskell for general purpose programming for five years now and I've
found it to be exceptionally well-suited.

------
arcatek
Another really good course to learn the basic about programming language
design:

[http://nathansuniversity.com/](http://nathansuniversity.com/)

And if you want to actually build a "real" programming language, I advise you
to try llvm - it really takes away the pain of generating bytecode, and gives
you everything you need to deal with the actual design of your language.

------
fredkelly
Interesting read.

Possibly more digestable, I recommend the walkthrough of building "Egg" in the
fantastic (and free!) Eloquent JavaScript by Marijn Haverbeke:
[http://eloquentjavascript.net/11_language.html](http://eloquentjavascript.net/11_language.html)

------
tinco
Given the domain name I was hoping they'd first implement a Lisp in 12 lines
of Javascript, and then implement the new language in that lisp, that would've
been an interesting tutorial.

I get that it's a beginners tutorial and they have some constraints, but it
starts off with "let's dream up a language" and then presents a super standard
language, it's basically just Javascript with obligatory semicolons..

~~~
mishoo
... and then it gets continuations, and that's where it becomes interesting.

Any case, the intent was purely didactic, but I did implement a Scheme dialect
based on half of that code. To be released some day...

------
thomasfoster96
I'm glad they didn't write a tutorial that made another Lisp - I'd your
audience is javacript developers, a lisp isn't all that appealing usually.

Anyways, this is such a detailed series of tutorials I may be distracted for
days bringing my half finished programming language back from the dead.

~~~
moron4hire
I do a lot of JavaScript and Lisp is extremely appealing to me. JavaScript is
a functional language, but not a very good one. Lisps are much better at doing
functional programming than JavaScript. So a Lisp that translates to
JavaScript is right up my alley.

~~~
samatman
You might enjoy wisp:
[https://github.com/Gozala/wisp](https://github.com/Gozala/wisp)

------
noiv
I remember reading this the first time as a JS rookie. Every time the author
mentions "this is same in JS" a light went on in my head and all the JS quirks
found earlier became just natural. It still deserves its place in the
Christmas tree bookmark section.

