C³designer's blog

Yes, I'm C³wife's husband ;)

Status Update + IPG

Not much happened on this blog and c3wife's blog lately because I was back at work at Beenox for 3 months. They urgently needed someone for a specific task and I was happy to get back to work for a short time, giving me time to think about the next steps for C3. My sabbatical will be extended to December 2011, making it a complete year as scheduled.

Since my return at home, I worked on IPG and I decided that I would complete this project before continuing work on C3. I think the best thing to do now is to get things rolling as soon as possible. I hope to get experience with the dynamics of releasing open source software and hopefully accepting patches and interacting with users and collaborators.

IPG stands for "Incremental Parser Generator". The basic idea is to create a parser generator (such as Yacc or Bison) but with a few twists:

IPG was created to implement the following design choices for C3:

  • Have a single grammar for multiple purposes: easily modifiy the syntax, generate the parser (potentially in many languages), learn the syntax
  • Have a single code path for all parsing needs: compilation, syntax-highlighting, refactoring, etc.
  • Have a completely incremental process from code to execution (that can happen on the fly)

The current implementation generates C++ code. One interesting property is that the interface to traverse the parse tree is an STL-style iterator, making the client code very clean and terse. I will continue to work improving the interface and implementation but I will soon make a real first release.

 

Aims and Rules of Thumb for the Design of C³: a Request for Comments

I wrote a working document called "Aims and Rules of Thumb for the Design of C³", based on the chapter 4 of The Design and Evolution of C++ by Bjarne Stroustrup. The conclusion of the document is the following list of rules and I would like to know what you think of them.

Aims
 
C³ makes programming more enjoyable for serious programmers.
 
C³ is a general-purpose programming language that supports
– low-level programming
– data abstraction
– object-oriented programming
– generic programming
– functional programming
– metaprogramming
 
General rules
 
C³’s evolution must be driven by real experience.
Do the simplest thing that makes C³ better at fulfilling its aims.
C³ must be useful now.
Provide the best available implementation as a default for every feature.
Always provide a transition path.
C³ is a language, not a runtime system.
Provide comprehensive and customizable support for each supported style.
Don’t try to force people to use a specific programming style.
 
Design support rules
 
Support sound design notions.
Provide facilities for program organization.
Say what you mean.
Don't set policy.
Provide a mean to set policy.
Unleash large-scale collaboration.
 
Language-Technical Rules
 
No implicit violations of the static type system
Provide as good support for user-defined types as for built-in types.
Locality is good.
Avoid order dependencies.
Each individual feature must be easy to teach.
Syntax matters.
External tools usage should be eliminated.
All facilities have an interface in C³.
All facilities not directly supported by the environment are implemented in C³.
 
Low-level programming support rules
 
Leave no room for a lower-level language below C³ (including assembler).
What you don’t use, you don’t pay for (zero-overhead rule).
All implementation choices can be made by the user.
C³ allows mapping to any native environment.

 

Short update on my progress

I have been working on C³ for more than 5 months now. It was hard and slow in the beginning. Some people asked a lot about my progress and I did not have anything to show. It can be explained in part because I was focused on some other things in my life. It was a little difficult adapting to my new life but I now have a great pacing.  I can separate what I did month by month:

September: mostly vacation-style, recovering from 6 years of intense work in the game industry!

October: After seeing my doctor, I decided to focus on my health (I am diabetic). I learned to cook and made sure my blood glucose was neither too low nor too high. Unfortunately, it means that I did not work that much on C³.

November: I decided to get a new computer and I spent a lot of time setting it up. At least, now I have a great setup for both work and games. I also worked on a document that specifies the aims and rules for the design of C³, similar to chapter 4 of "The Design and Evolution of C++".

December: I started coding for real. I finished a first pass on IPG which is, despite the name (Incremental Parser Generator), not incremental at all for now. My target was for it to be good enough to write my first C³ parser. I used it for that and I'm happy to announce that it worked great and I was able to build a parser that builds an AST for a small C³ subset in just 2 days! I also coded my first code generator with LLVM and it worked great as well! This is only a prototype but it prove that I'm able to emit native code from some code.

January: I was planning to continue to work on my prototype compiler but I decided to take a step back and think a lot about the best way to make my grand plan a reality. I said: "I could continue to work on this prototype but I will end up in 6 months with a compiler that does nothing more than a C compiler". I needed some smaller subset with at least one good innovation that does not exist in any other language. I worked on an elevator pitch that would help me sell my project. Not much technical work was done but I think this was useful to better define my goal. I also juggled with the idea of going back to university to get a master degree but decided that I was too practical to get into the ivory tower. Furthermore, I am able to read books by myself to get the theory that I miss. I just need to be more efficient in my quest for knowledge.

February: Back to technical work. I am now 100% in design phase, working top-down from what I need to compile two C³ programs: first, a "hello, world" and second, one that demonstrates the optimizations that C³ allows, but not C++. Once the minimal abstractions will be defined, I will start programming the real C³ compiler. I spent some time defining its architecture. I defined it in enough details to justify scraping my prototype and restarting with the new design. The result of this sprint will be the basis for the following sprints and I wanted a good foundation.

Let's Take Sabbaticals!*

It is now official: I am on sabbatical for a year! I will make my dream a reality: I will be at home working on IPG, the incremental parser generator, and then on the C³ compiler and tools, using LLVM as a foundation.

It’s been a busy year for my wife and me as we were both working at Beenox on Spider-Man: Shattered Dimensions. Marie-Eve is an associate producer and I am a technology programmer. I like this job and I will be happy to come back in a year when I expect C³ to have gained enough momentum to attract some additional people to help.

I know I did not talk that much about C³ this year but lack of time is not the only reason: there is simply not that much to talk about yet. Since my progress will soon be at a much faster pace, I should have more things to say, through this blog or with the help of my wife on http://c3wife.com/.

The best is to come!

*Some people may have noticed that I borrowed this title from a Joel on Software post dated December 24th, 1999. This is intentional.

About the Go Programming Language

In the last installment of my "husband's notes" series on my wife's blog (c3wife.com), I talked about new languages that add “just a little bit” of overhead and that have garbage collection and built-in types like strings and maps. It was a voluntarily general statement. Such languages include the D programming language (digitalmars.com/d) but of course I was thinking in particular about the recently released language Go (golang.org). Somebody asked me some questions about my opinion on Go, so here are my answers.

Q. What do you think of Google’s recently revealed Go language as a competitor for the systems audience?

A. I think creating a new language is a fine strategy for Google in order to fulfill their own need for high performance and parallelism. I see three main reasons for that. First, they are aware that for some applications, Python performances cannot scale for systems that run on servers used by millions of people. Second, they are obviously tired of the very poor dependency system of C++ based on header files and its consequences on compile time. Finally, they need to make extensive usage of parallelism and neither of these languages have good support for the high-level concurrency primitives that would make it easier.

However, because it is created with these specific objectives in mind, Go deviates from my own definition of a "systems programming language". They don't have any intention to run Go code on embedded systems, gaming consoles, or inside an OS kernel. Being a game programmer, I can already see that I would need some way to configure the hidden thread pool that runs goroutines. When doing real systems programming, you must have the assurance that if you know that the hardware is able to do something, you are able to do it. If you don't need that, that's fine, but your job does not fit my definition of a systems programmer.

So, yes, I think Go have an audience but I think it is limited to server-side developers that for some reason need better performance than dynamic languages and prefer a more productive language than existing compiled languages.

Q. Does it have any features that inspire you?

A. Goroutines and channels are, together, a great and inspiring concept. Higher-level concurrency primitives is really what we need to enable programmers to fully take advantage of multi-core computers. They would fit nicely as a programming technique in C³ code and could be even more powerful using the C³ type system. However, I am happy to say that goroutines and channels won't make their way into the core C³ language! In fact, they won't need to because it will be easy to implement them as a C³ library.

Interfaces are a more fundamental concept that must be integrated into the core language. Interfaces in Go and C³ are somewhat similar. In both languages, they allow the handling of data structures without coupling to their implementation. Like the Go designers, I am not fond of type hierarchies and I was not sure if I should get rid of them.  I am happy to see that Go confirms that it is a viable design choice. Inheritance will probably appear in C³ but would work more like Go embedded fields. This is an area of C³ that needs further design but I already decided that inheritance is not a fundamental concept in C³ and it won't be in the first iterations.

Q. Does it have any things that could be done significantly better?

A. I really don't like the allocation primitives new and make. They make a completely unnecessary distinction between pointers (explicit pointers to values) and references (pointers disguised as values). Moreover, references are a special case for slices, maps and channels and are not available for user-defined types. C³ will be much more orthogonal in this regard. In fact, it will completely decouple memory allocation from object construction, enabling reuse of user-defined types in all kinds of environment, including those where no heap is available!

Right now, Go is missing generics. Even if its creators acknowledge this limitation and are thinking about adding them, I think this a major omission. Bjarne Stroustrup said that one of his biggest mistakes in the development of C++ was not  adding templates earlier. In C³, built-in pointers will be templates! Implementations of containers using the Go empty interface hack will result in large amounts of ugly code.

I think what I dislike most about Go is the fact that it is a quite verbose language, like C. There is nothing that is taken care of automatically except memory. There is absolutely zero support for the creation of embedded DSL and everything that is not a built-in type use the verbose function or method syntax. Simple things like equality cannot be added to custom types. They even mention this limitation for why maps can't be used on structs! Also, there is no exception handling so we're back to explicit error code handling everywhere.

 

Equivalent to Lisp macros

I was reading Paul Graham's RAQs and found this interesting paragraph:

Couldn't you add something equivalent to Lisp macros to languages like Perl or Python?

Not without turning them into dialects of Lisp. Real macros need to operate on the parse tree of the program. To allow that in a language with syntax, you have to (a) make public the translation from source code to parse trees, and (b) give the programmer the opportunity to run programs on parse trees before they go on to the compiler.

But it would be hard to do that without creating a notation for parse trees; and once you do, your language has become a skin on Lisp, in much the same way that in OS X, the Mac OS became a skin on Unix.

The way he explains the problem is great but the answer is, in my humble opinion, wrong. Why? Because it understates the importance of a good interface:

Do I want to use raw Unix on a daily basis? No.
Do I want to use Mac OS X on a daily basis? Yes.

The same goes for programming languages. As a great visual interface makes an OS easier to use, a great and expressive syntax makes a programming language easier to use.

A programming language that requires me to state operation priority for every single computation is wasting my time.
A programming language that considers the simple concept of sequential instructions a special case that needs special syntax is an abstraction barrier that I want out of the way.

If C3 is one day described as a skin on Lisp, I would probably take this as a compliment because I think Lisp needs a skin to be usable. But I also think that Lisp base abstractions are to high for an all-prupose programming language. I have great ideas for making meta-programming in C3 as powerful as Lisp macros but I will talk about it "when it's done".

.

About vaporware and memory management

Michel Fortin posted an answer to this post about "values" in C3 from my wife. I was aware of most of the points made by Michel before his post but I guess I could say some words to clarify.

Is C3 vaporware? Yes, right now, it is. I was aware that C3 would be labeled like that when we decided to talk about it before writing a single line of compiler code (I did make a prototype parser in 2003 but nothing I can use in a real compiler). This is a great departure from the way I'm used to do things. I usually make sure that I show only finished and tested work. My wife and I decided that it was better to start a conversation with the developer community to have feedback as soon as possible. I'm still worried that the "vaporware" label will stick but I hope you will understand the dilemma.

I am a slow writer in english and I don't have much time. I decided it was better to spend my time actually coding the compiler (and necessary utilities) and refining the language specification. When my wife decided she wanted to help me in this project, her enthusiasm to document our experiment in an online journal was very welcome. Please keep in mind that she is trying to vulgarize this stuff. I could probably explain some details more thoroughly but that's not the point of her own blog posts. I will do from time to time (very rarely) in "husband's notes". The recurring pattern of these articles will be that they all contain C3 code (if the grammar change, I will go back and revise these examples). If I just want to talk about me or express opinions, I will do it here.

About RAII and garbage collection, optimizations that use garbage collection algorithms when we can afford delays in the release of resources will be possible in C3. However, the basic constructs of the language won't be dependant on garbage collection like Java, C# and D. I want to thank Michel for the explanation about the leaks in garbage collected programs and about the garbage collection techniques used in different languages. C3 is a meta-language which aim to ultimately support all these strategies and learning the details help me build the right abstractions in the language.

C3 will have the widest possible range of levels of abstraction. It will be both very low-level and high-level. That means that raw pointers that can point anywhere (including heap and stack objects) will exist in C3. They will be used as an implementation detail of other types of pointers but their usage won't appear more "integrated in the language" than smarter pointers. Their use in application-level software will be limited and not recommended but C3 will do as C do: trust the programmer.

To answer the last Michel question, I think that a non-managing weak pointer that becomes NULL when the object goes out of scope would be a good idea and would fit the requirement for a stack object pointer.

Thanks a lot to Michel for the feedback!