
Cello: Higher level programming in C - mntmn
http://libcello.org/
======
breckinloggins
I want to make a few observations about this, and why I found it seemingly
less "hacky" than other such attempts:

\- As I said in an earlier comment, "var" is just a typedef'd "void *". The
downside is that libCello code is essentially untyped, but the upsides are
that the C preprocessor is now enough to do the processing needed for the rest
of the macros in the language, and that you can still mix regular typed C with
libCello code for a "best of both worlds" mix.

\- Looks pretty, right? What you're responding to is not just the nice non-
capitalized macros and the $ keyword, but the syntax highlighting in his
examples. Fire up a text editor and write you some libCello code without this
highlighting and it probably won't feel as nice.

I'm extremely interested in the idea of taking the syntax highlighting,
formatting, and code completion OUT of these specialized IDEs and plugins and
into some kind of standard "bidirectional channel" between a language
processor or compiler, its macro system, and the user's editor of choice.

We should be able to make entire DSLs and specialized syntaxes that not only
compile, but are able to provide rich information to the surrounding
development environment in a standardized way. I'm not alone on this. F#'s
Type Providers do exactly that. But imagine being able to control not only the
"intellisense", but also the syntax highlighting, argument/return tooltips,
documentation, preferred formatting, snippets, etc.

And by "surrounding development environment" I mean everything from the
command line to vim and emacs all the way to Sublime Text, Eclipse, and Visual
Studio. Even github! Why do you have to register a new syntax highlighter on
github for a language and hope they turn it on?

~~~
williamcotton
> I'm extremely interested in the idea of taking the syntax highlighting,
> formatting, and code completion OUT of these specialized IDEs and plugins
> and into some kind of standard "bidirectional channel" between a language
> processor or compiler, its macro system, and the user's editor of choice.

Well maybe if we stopped using ASCII files as our source code and used a
richer type of document we could start to make some improvements!

What kind of rich document? Well, what about HTML? Did you know you can even
embed interactive elements in such documents? What if we started embedding our
source code and editors in our documents instead of the other way around? The
whole model is inverted, but mainly for historical reasons, because you know,
in 1979 all we had was VT100 to interface with our machines... it's like we
never moved on... why is my "code" a splattering of ASCII files in a
directory? A package definition, tests, dotfiles for this and for that... ship
the editor, the tests, the docs, the examples, and the source ALL as one
document!

~~~
t1m
That may have been the case in 1979, but in 1980, we got Smalltalk. This
environment was (almost) completely without the concept of a file. Code was
stored in a persistent 'image', like everything else, and was accessible
through normal object based data structures. This, and the fact that all of
the source code for the system was immediately available, made it extremely
easy to build and extend language level tools like browsers and debuggers.

I would say the downside of this 'rich' environment is that your tools tend to
become language dependent. Early Smalltalk code versioning tools were fairly
easy to build (I'm guessing), but would definitely be Smalltalk centred. The
unfortunate advantage of an ASCII text file is that it very difficult to have
more than one interpretation of it's non-existent meta-data.

~~~
williamcotton
Thank you for mentioning Smalltalk! My comment was heavily inspired by that
"computing environment".

If you look at JavaScript and the web browser... well, it's more like a
Smalltalk system than a UNIX system! There are no files! It has a weird little
dynamic multi-paradigm language! The web browser become the spiritual
offspring of Smalltalk as soon as Brendan tacked on JS. :)

Look how WEIRD package management gets for JS when you try and make it
supported by UNIX and the filesystem!

As for tools becoming language dependent... what about sourceMaps? Look at how
CoffeeScript integrates with our workflow tools these days!

The biggest problem with Smalltalk was that it was made for Personal
Computing, and ALWAYS had issues running other people's code or integrating
well with collaborators.

The web browser and JavaScript solve a lot of these issues with the whole
sandboxed code environment...

The web has NOTHING to do with files, so it seems like the perfect place to
just forget about them and move forward...

Relays and switches only got us so far... Machine code only got us so far...
UNIX only got us so far...

Why have we lost the courage to continue looking for better solutions and
being brave enough to throw away certain concepts?

I mean, look at mobile and touch computing! iOS and Android are completely
abandoning the concept of files!

Why? Because they don't really have to be there... Again, look at Smalltalk...
and I know, it "failed", but do you really think it failed because it didn't
have files? Is that the one reason? Is it even a reason at all??

~~~
pjmlp
One of the reasons Smalltalk failed is called Java.

Smalltalk was actually getting a foothold in the enterprise when Java happened
and everyone switched to it.

Eclipse was originally a Smalltalk environment (Visual Age for Smalltalk).

Yes, files also played big a role, because it was not possible to use source
control systems with Smalltalk that worked across implementations. So you were
bound to a specific vendor.

~~~
flyinRyan
And actually Sun approached Viacom to license Smalltalk at much less than what
they were currently charging. Viacom wouldn't budge so Sun invested in "Oak"
that they were already playing with in house.

~~~
pjmlp
Thanks for sharing the information.

~~~
flyinRyan
np, sorry I was too lazy to post any links but I think I gave enough info to
find it on the internet.

------
jacquesm
Super stuff this, that's a very interesting approach.

I spent the better part of the last two years writing a (closed source, sorry)
library that does some of this, and some other stuff besides (state machines,
events, 'proper' strings with automatic garbage collection and allocation,
message passing).

Maintaining static typing was a big pre-requisite for that library, without it
too much of value would be lost to offset the gains. It was a very educational
project for me, it definitely re-inforced the 'half of common lisp' meme.

To program a piece of software using that library no longer felt like
programming in C, every now and then you'd see a bit of C shine through in the
lower level code. The whole thing relied to a ridiculous degree on macro
cleverness (something to be avoided, for sure) and other deep knowledge of how
C works under the hood to get certain effects, and I found this part of it
less than elegant (even if the results were quite a big step up from
programming in C).

The main justification for doing all this was to straighten out a project that
had become bogged down under increasing complexity and a failure to abstract
out the common elements. Choosing C for this project was a poor decision but
since there was not going to be any budging on that front I tried to make the
job work out as good as possible.

It's quite interesting to see how far you can push C but at the same time you
really have to ask yourself if you are on the right road if you find yourself
doing things in such a manner.

Like Cello, the lib I wrote is a way to force the language to become another
language, which always has drawbacks in terms of unintended side effects and
long term support.

Probably better to switch to a platform that is closer to your problem domain
(in this case, such as erlang, clojure or even go), as much as I liked
tinkering with C it felt like we were making life harder than it needed to be.

------
makmanalp
Slightly related tangent:

I'm looking for standards / set of libraries / best practices for "modern" C
development, but I've yet to find a comprehensive resource.

Stuff like typedefing a manual fixed sized int type to be cross-platform
compatible, that books don't really tell you to do but are important and come
up often.

I'd be okay with a small, well written example library too. Does anyone happen
to know something like this?

edit: Ah, sorry if I misled you, that was just an example of the _kind_ of
tips and pointers I was looking for. Or weird bits like the linux kernel
list_head.
[http://kernelnewbies.org/FAQ/LinkedLists](http://kernelnewbies.org/FAQ/LinkedLists)
Or common libraries like bstring that make life easy. Or even a single,
comprehensive implementation of good data structures, since everyone seems to
have their own vector.h and/or hash.h that fails to cover much other than
their own use case.

~~~
VMG
As somebody with the same query, let me hop on - how does "Learn C the hard
way" fare? I've got it mentally bookmarked the for next time I touch C code.

~~~
falcolas
Pretty good, in my opinion. It's fairly comprehensive, and focuses a lot of
time and effort into pointing out why things in C break and how to be
preemptive about fixing them.

A fair bit of discussion around your standard exploits as well.

------
mjn
Wow, this is an impressive amount of high-level feel for relatively little
preprocessor code (and a fairly lightweight C library underneath that). Holds
together pretty consistently, which is hard to do with syntax extensions built
on top of the C preprocessor, vs in languages with more convenient syntax-
extension or macro systems.

------
hugs
I spent the last hour trying to get the example programs on the front page of
the libCello site to compile on OS X (10.8.4). I discovered I was missing some
include flags. This is what finally worked:

$ gcc -lCello -std=c99 -fnested-functions example.c -o example

Hope this helps someone!

------
breckinloggins
Note that "var" is a typedef'd "void *". This essentially bypasses C's
typechecker for libCello code. The author admits as such, and maybe that's
just fine for what you need to do, but you should be aware of it.

~~~
optymizer
random question: doesn't ObjC define 'nil' (or self?) as 'void*'? I did some
ObjC coding 2 years ago and I remember seeing something like this and
thinking: oh boy.

~~~
geon
The ’id’ type is a void *. It is used extensively, whenever there are multiple
possible return types. Even where inheritence could have been used to make it
more speciffic.

For example, ’alloc’ and all ’init’ returns it.

~~~
0x09
> The ’id’ type is a void __.

non

    
    
      typedef struct objc_class *Class;
      typedef struct objc_object {
          Class isa;
      } *id;
    

with

    
    
      struct objc_class {
          Class isa;
          /* objc v1 members omitted */
      };

------
dcope
After looking at the source, this appears to be a great beginners resource of
how to build on top of C. The source is very concise and straightforward. I'm
curious to see what will come from this.

~~~
kragen
No, dear God, no. Please, no.

~~~
McUsr
I see you believe in my axiom: "It can always get worse". :D

~~~
kragen
Libcello has its share of latent macro bugs, but it doesn't seem particularly
bad. However, I can hardly think of anything worse than debugging piles of
half-broken higher-order C macros written by beginners.

------
ExpiredLink
People interested in real-world high(er)-level C programming should take a
look at this book, "especially the class methodology in Chapter 4":
[http://www.duckware.com/bugfreec/index.html](http://www.duckware.com/bugfreec/index.html)

Side note: this book would certainly be down-voted on r/programming but I
expect more grown-ups here.

~~~
da02
(I'm not on r/programming.) Can you go into specifics as to why they would
downvote it?

~~~
ExpiredLink
Microsoft used this style of programming.

------
JonFish85
An interesting experiment, but even as the author states "it's a fun
experiment". It makes things easier to read & understand for beginners, maybe,
but he even states that it's not for beginners. If I have to be a C power user
to use it, I imagine I'd feel more comfortable without it. Just my opinion
though.

~~~
yk
I think quite similar about this, its in some way like training wheels on a
motorcycle.

But I think there could be quite interesting uses for Cello, namely you do
your prototyping with it and then you trow out the library and refactor the
code to pure C.

------
robododo
It looks pretty, but I'm already having nightmares about stepping through this
in a debugger.

------
JoachimSchipper
Pretty cool, even if I don't want to see the compiler warnings. ;-)

In the same vein, but more C-like:
[http://p99.gforge.inria.fr/p99-html/](http://p99.gforge.inria.fr/p99-html/).

------
ambrop7
What is this? It claims to be a (GNU99) C library, but I don't see how this
can be the case, considering all the non-C constructs in the sample code ($(),
try/catch, foreach). So it this just a language of its own that is compiled
into C?

~~~
mcpherrinm

      #define foreach(x, xs) \
        for(var x = iter_start(xs); x = iter_next(xs); x != iter_end(xs))
    

It's all C:
[http://libcello.org/documentation/hacking](http://libcello.org/documentation/hacking)

~~~
kragen
Imagine what happens when someone says

    
    
        foreach(x, get_next(queue)) f(x);
    

To solve this problem, with GCC, you have the option of defining foreach as

    
    
        { typeof (xs) _xs = xs; \
          for (var x = iter_start(_xs); x = iter_next(_xs); x != iter_end(_xs))
    

but then you need a corresponding endforeach to apply the matching }. If you
just leave off the opening {, then you end up with a mysterious compile error
on

    
    
        if (ready(queue)) foreach(x, get_next(queue)) f(x);
    

since the declaration of _xs is not a statement.

And this kind of thing is why a "macro system" means something very different
in C and in Lisp, and why Brad Cox wrote a compiler in 1983 instead of a macro
library.

~~~
dfbrown
You could do

    
    
        #define foreach(x, xs) \
            for (var _xs = xs, *x = iter_start(_xs); x = iter_next(_xs); x != iter_end(_xs))
    

Because var is just void* and anything you can iterate over will also be a
void*.

~~~
kragen
Oh, that's excellent! I don't know why the C9x for-declaration didn't occur to
me as a possible solution, particularly since the macro was _already using
it_. You should submit this as a fix!

------
georgeg
This is the kind of functionality that D language is really good at. If I were
to go beyond the fun bit of this project, i would have a look at D language.

~~~
Demiurge
I think it's more useful than D though, because I can just add a header file
to an old C project and make things better and still have things interoperate.

------
popee
Chello is nice proof of concept, but personally i'd like to see only one or
two changes to C standard:

1\. sizeof(function) -> would give user ability to copy functions around.

2\. maybe new reserved keyword _Func -> function tagged with _Func would
indicate that function must be compiled as function object (defined sizeof)
and compiler needs to address fact that function may be moved around and used
(relative addressing and i guess bunch or others problems that would arise).
Only code, nothing to do with ELF or other formats.

Another interesting thing to do would be to, somehow, eliminate function
pointers with _Func.

In any case, user would be responsible for creating environment for that
(lambda?) functions, like manually setting mprotect or setting up stack
(prologue.h & epilogue.h ???).

_Func int example_prototype(int i, int j) {

    
    
      return i + j;
    

}

And then do something like:

example_prototype func0;

memcpy(&func0, example_prototype, sizeof(example_prototype));

struct prologue_t *p_ptr = &func0;

p_ptr->sp = 0xdeedbeef; // Or some address that is used as stack

z = func0(5, 6)

So, what do you thing how hard would it be to implement something like that?

~~~
groue
Do you know C blocks
?[http://en.wikipedia.org/wiki/Blocks_(C_language_extension)](http://en.wikipedia.org/wiki/Blocks_\(C_language_extension\))

------
sovande
Not thread safe. For instance the exception stack is global.

~~~
al3xbio
Also see
[https://github.com/orangeduck/libCello/issues/35](https://github.com/orangeduck/libCello/issues/35)

------
eonil
Interesting at first, but lack of static type-check (or notation) voids
everything.

------
Demiurge
This looks nice. A lightweight macro for Class, that is just a struct with
function pointers, and I will use it over c++ :)

------
sspiff
The fact that this uses "void *" as a universal type makes me somewhat
reluctant to try this out.

------
jnbiche
This looks very nice indeed. The main thing that will interfere with usability
for me as a non-C guru is the lack of thread support. But I am really grateful
for the effort since my "spiritual home" among programming languages is
definitely the dynamic languages, yet I appreciate the need and beauty of C in
many instances when performance is necessary. libcello's apparent optional
static typing (the "var") is really nice -- it's one of the wonderful things
about using Cython alongside Python.

~~~
jnbiche
To follow up on my threadsafe remark above, I should add that it's only the
Exceptions that don't appear threadsafe, and it looks like that's fixable.

------
dubcanada
So, because I am a nub in this stuff... When it says C library, does that mean
anything that works with C (say a gui library for example GTK) will work
perfectly fine with this? I would just change the syntax as required and call
it good?

~~~
0x09
You can write regular C GTK+ code side by side with it, but you would need a
wrapper in order to use most of the constructs with GTK+, or anything else not
written with Cello's type system in mind (e.g. var w = $(GTKWidget) would not
work for multiple reasons).

------
guilloche
It seems interesting but I did not get it. Does it try to add some c++ syntax
sugar? Does it have performance advantage over c++ for similar functionality?

I am not a fan for C++ syntax, can I still get something from cello?

------
halayli
Just use C++11.

------
smegel
"Constructors/Destructors aid memory management"

Does it do RAII? Really, calling destructors implicitly on auto variables on
scope exit is the main thing missing in C here.

~~~
ExpiredLink
... and cannot be implemented in pure C.

------
dsego
If there is already new syntax, why not just make a completely new language
that compiles to C, like vala or something similar?

------
ilitirit
Why would one choose this:

    
    
      var int_item = $(Int, 5);
    

over this:

    
    
      int int_item = 5;
    
    

What am I missing?

~~~
pmelendez
Well with the var option you do something like this:

var item = $(Int, 5); ... code ... item = $(String, "5");

Not that you want to do that all the time but it is a way to implement duck
typing

------
guard-of-terra
They should neither use C++ keywords nor invent parallel terms (real vs float)
in order this to fly.

------
mogui
loving it, definitely I was playing with these sort of things these months and
eventually I was ending with something similar, but that is far away what I
was doing. I think I will contribute to this lib if i can instead of
continuing my shit :)

------
oscargrouch
i hope this get more and more popular.. in a way that the next natural step
would be implementing a special parser for it in GCC and Clang (as some sort
of C subset)..

totally awesome!

------
jlebrech
Someone build an nginx (openresty?) module with this.

------
akadien
Harrumph. Our
[http://github.com/redjack/libcork.git](http://github.com/redjack/libcork.git)
library is better.

~~~
nkurz
Took a look: interesting library. Documentation looks good. When following the
link to 'readthedocs.org', it took me to
[http://libcork.readthedocs.org/en/0.10.0/](http://libcork.readthedocs.org/en/0.10.0/)
which has a message on top that says it's not the newest version. Editing the
URL gets me to
[http://libcork.readthedocs.org/en/0.11.0/](http://libcork.readthedocs.org/en/0.11.0/).
Not sure where it should go, but might be worth checking. Thanks!

~~~
akadien
Thanks. We'll fix the link.

------
deletes
Does it have inheritance and polymorphism?

~~~
koenigdavidmj
It seems to be targeting the same market as Go or Haskell OO more than that of
C++. A class in this model basically means 'definitions for a set of methods
on this type', so it's more like what you understand as an interface.

For example, there's a "show" class that converts your object into a string.
Any object that implements the necessary methods can thus be printed.

Another example is an iterator class. If you implement a couple of methods
(move the cursor to the start, increment the cursor, see if the cursor is at
the end, and get the currently pointed-at item), then you can be iterated over
by a foreach loop.

Unlike Go, though, with Cello you seem to need to explicitly specify the
functions used to implement each class.

~~~
chongli
>Haskell OO

Huh? Haskell is not OO by any means.

~~~
jes5199
They were referring to haskell typeclasses, which is a way to dispatch to
different function definitions based upon your data's type - which, if you
squint, looks sort of like OO without inheritance.

~~~
mercurial
Typeclasses can have sorta-inheritance, in the way that x may have to be an
instance of typeclass X in order to implement typeclass Y.

~~~
jes5199
Yeah. It's not clear to me that you can just do arbitrary overrides, though,
like this type is the same as that one except with one function replaced. I
can imagine building such a system out of Haskell primatives, though

~~~
mercurial
Ah, I believe overrides are quite out the question. You already can't have two
methods with the same name and a different signatures...

~~~
jes5199
Of course someone has already written a paper on implementing OO on top of
Haskell:
[http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106...](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.772&rep=rep1&type=pdf)

------
brambit
Use macros?

------
mortdeus
Eww

------
claudiug
create a webframework now like rails/django and you will have some marketing
:P

------
cad
Why, why, why didn't I break his legs!

------
anuraj
Well - this looks more PHP now - given that PHP interpreter is actually a
shell on native C - I think it already achieves this.

