

Show HN: Vivaldi programming language - jeorgun
https://github.com/jeorgun/Vivaldi

======
jeorgun
So this[1] post recently made its way across the HN front page, which I found
serendipitous given my current side project. There's nothing terribly
groundbreaking in my language— everything in it is basically taken from Ruby,
Scheme, or Python— but I certainly learned a lot making it, and maybe some of
y'all will find something of interest in it.

[1]
[https://news.ycombinator.com/item?id=9040029](https://news.ycombinator.com/item?id=9040029)

~~~
juliangregorian
Got any recommendations for resources to get started creating one's own
language?

~~~
rtpg
For the parsing aspects, reading about parser generators or the like would be
super useful

~~~
gorgas
I would not recommend using a parser generator tool to build a recognizer por
any programming language,unless you design your language to be LL(1) or LL(k)
witk a low value of k. Otherwise you are going to suffer a lot with parsing
issues.

Parser generators usually have a very limited number of target languages, so
you might find yourself stuck into a language you do not want to code in.

~~~
rtpg
hmm, your results may vary (whitespace-sensitive languages, but that's tricky
in pretty much any toolkit), but in my experience most DSLs that people want
to write fit well within LL(k). Java works in it, after all.

I started out with Yacc, though, and that helped me out a lot more...

------
hk__2
> Interpreted language inspired by Python, Ruby, Lisp, and so forth

For a few seconds I wasn’t sure if this was a pun with a reference to the
Forth programming language, but it’s not.

------
fenaer
There is another project called Vivaldi, a new web browser. It's been featured
on HN a few times.

[https://vivaldi.com/](https://vivaldi.com/)

~~~
_random_
Well, Apple stole 'Swift' from a different language (was quickly changed to
"parallel scripting language"):

[http://en.wikipedia.org/wiki/Swift_(parallel_scripting_langu...](http://en.wikipedia.org/wiki/Swift_\(parallel_scripting_language\))

He created something in an entirely different category. Both projects have
similar chances to succeed. What is the problem?

~~~
chrisdone
People just like sharing that kind of thing. When I made this little page
[http://chrisdone.com/z](http://chrisdone.com/z) because I couldn't be
bothered thinking of a better name, there were dozens of people commenting and
emailing me expressing concern that there is already a Z programming language
and I should respect other authors etc.

------
tomphoolery
I really wish Ruby had some kind of `var` or `let` syntax so it was a bit
easier to determine when one was calling the method "foo=" or when one was
assigning the local var "foo" to something. Having this would reduce the
amount of `self`s in the code for class definitions.

~~~
chrisdone
Oh, that is evil.

------
bsurmanski
Looks like a fairly well put together language.

A few things that were not explained in the README:

Why did you decide to create your own programming language?

> every type in Vivaldi inherits from Object (which in turn inherits from...
> itself)

What was the reason behind making Object inherit from itself?

What is the largest program currently written in Vivaldi?

edit: It looks like the first commit on github is 22 days ago, did you make
the whole language in 22 days?

~~~
jeorgun
1\. Mainly for fun! Languages are pretty complex, so I got to learn about
number of things (e.g. recursive-descent parsing, closures, Ruby and Python
internals) in making it, and it's pretty rewarding watching programs run
successfully.

2\. Mainly that, because of the way objects are defined in the C++ (in
value.h), it had to inherit from _some_ type. I could just fudge it and make
it inherit from nil or something, but there isn't any particular downside to
the current system, and it has the added benefit of ensuring that
obj.type().parent() is always successful.

3\. Nothing much beyond a few test scripts (ProjectEuler solutions, etc) at
the moment. Since there isn't a C API yet, it's pretty hard to make anything
that requires networking, GUIs, etc., so adding that is near the top of my
TODO list.

4\. I might have started a few days before the initial commit (I can't
remember ATM), but more or less, yeah.

------
buren
Is there any build/install instructions? Want to play around :)

EDIT:

    
    
      git clone git@github.com:jeorgun/Vivaldi.git
      cd Vivaldi
      # if you don't have boost then run 
      brew install boost
      mkdir build
      cd build
      cmake .. && make # cmake version 3 or greater is required

~~~
jeorgun
Oh, whoops— sorry about that! I added some instructions based on yours to the
README; better?

Also, if you run in to any issues, feel free to let me know; I only have my
MBP and an old Thinkpad T60 running Arch Linux to test on, so I could very
well have unwittingly done something non-portable (I'm assuming that Windows
support is a complete no-op, but I'd be happy to hear I'm wrong).

------
munificent
This looks really cool! Some random feedback. It's your baby, so feel free to
ignore any and all of this you don't agree with.

First off, you did two things right that a lot of hobbyists (including myself,
multiple times) do wrong right out of the gate:

1\. You wrote some nice, readable introductory docs.

2\. You didn't make the language syntactically weird for no good reasons. I
can instantly read your code samples and understand them. Yay!

\---

There's a good chance you'll end up regretting making strings mutable. It
means APIs that receive and store a string have to either copy the parameter
(slow, easy to forget) or run the risk of having something that they would be
unchanging change under them.

This is a problem with mutability in general, but I think strings hit the pain
point most strongly since they're immutable in other languages.

\---

You have lots of methods that don't take arguments (size(), start(), end(),
etc.). Some kind of getter syntax would be nice to lose the pointless "()".

\---

I like your range syntax. I'm using ".." and "..." (like Ruby) in a hobby
language of mine[1], and it's definitely not intuitive to many users.

[1]: [https://github.com/munificent/wren](https://github.com/munificent/wren)

\---

Your mixture of ":" for functions and control flow but "do ... end" for blocks
hurts my soul in some hard to define way. There's nothing intrinsically wrong
with it, but I see ":" and expect Python-style indentation then see "end" and
get all confused.

It might be nice to try to pick one or the other -- use indentation for
blocks, or "end" for functions and control flow.

\---

I think you may eventually find the way "self" is dynamically bound to be an
annoying frustration. What you have is semantically simple and follows JS and
Lua.

But it trips people up when people want to do things like store a reference to
a method in a callback and invoke it later. When that helps, you'll have
forgotten the old "self" reference.

Of course, solving this is also fairly complex. It usually requires some kind
of explicit function/method distinction (makes the language more complex) or
an explicit way to close over "self" (easy for the user to forget).

\---

"All variables must be declared before use:"

Damn straight. Implicitly declaration gives me hives. :)

\---

I like your cond statement, though I've never personally dug the name "cond".
The semantics are neat, though.

\---

You could get rid of "try" and just allow any block to have a catch clause.
That's what Ruby does, and I've always found it elegant.

~~~
jeorgun
Not at all— any feedback is appreciated :)

I'm beginning to have doubts about String mutability. Fortunately the only
actually mutating method at the moment is append, which is redundant with add
but for the mutability, so I might just tear that out.

Required parentheses on functions are pretty unfortunate. I'm mainly trying to
avoid the situation in Ruby where trying to access functions as first-class
objects requires all sorts of weird syntactic overhead. Possibly I could have
some kind of prefix operator, so (say) &obj.method would return the function
object, and obj.method would call it?

I agree about the ':' 'do/end' ugliness. Originally blocks were delimited by
braces, but I think the Ruby-style delimiters look nicer. Frankly I'd prefer
to get rid of the ':', but for single-expression functions that looks pretty
awful. I could do Haskell-style '=' (Haskell of course being where the
'function-body-is-single-expression' thing came from), but

    
    
        fn foo(x) = do
          ...
        end
    

is also pretty weird-looking; kind of like Scala's function definitions, which
I find really abrasive for reasons I can't fully explain.

Binding 'self' is also basically a compromise. Originally it was stored in the
method, but that required copying each type's methods (and each parents'
methods) into an object on instantiation, which was a pretty much unacceptable
performance hit. My thinking is that, whenever you'd want to pass a method
'obj.method', it's equally possible to pass 'fn (x): obj.method(x)'.

I need to rework the 'try...catch' statements in any case; their current
semantics are incredibly horrible (it wraps, then immediately calls, the try
body in a temporary lambda). Maybe I will just incorporate them into blocks—
thanks for the idea!

~~~
munificent
> Originally it was stored in the method, but that required copying each
> type's methods (and each parents' methods) into an object on instantiation,
> which was a pretty much unacceptable performance hit.

I think more a typical solution is to dynamically bind `self` like you do now
on normal method calls. But when a reference to a method is stored, you bind
`self` to the original receiver at that point in time.

Basically, you treat it like a closure.

------
pekk
This looks like Ruby. Why not just use Ruby?

