<commit_before>Overview
========

I started libCello (then called C+) as a fun experiment to play around with the various implementations of _Object Orientation in C_. Most had some fun features and cool tricks but tended to break down around about the time of inheritence. Assertions began to pile up, syntax became horrible, or the programmer had to do too many things manually. Several based around message passing relied too heavily on error-prone strings.

One thing I did notice is that essentially they begin to resemble the C backend to scripting languages such as Python.

I wondered if by making different or simplified assumptions it would allow for nicer syntax, cleaner semantics and fewer manual steps for the programmer. I thought I might be able to create scripting language like semantics, but with the performance and frontend of C.

libCello consists of some global changes and a number of cute hacks. The global changes are not too original, but combined with the cute hacks create a library that is fairly comfortable to use.

I've tried to make this article short so have skipped somewhat on the nitty gritty details. Anyone interested is encouraged to send me an e-mail or take a peek at the source code!


Types
-----

To change a language behaviour one must either change the compiler or the runtime. A language like C essentially has no runtime system. It generates object code that looks like any other. But we can add one ourselves. We only need to add one powerful construct to do almost anything we want. This is the familiar _type_.

For example if we wish to add `new` and `delete` to a language, our system (the runtime), must know the size of the memory to allocate. This is just _metadata_ also known as _type_ information. We must store this somewhere while the program is running. It could be in a separate table, but is often useful to tie to the object we wish to manipulate itself.

For example we can make all _rich_ objects contain some pointer to their _type_ or _metadata_ at the beginning of the struct.

    typedef struct {
      type_t* meta_data;
      int other_data;
    } some_struct;

When we wish to manipulating these objects we can then follow the pointer to the metadata and extract the information we need. If this entry is always the first entry in the struct, whatever struct we encounter, we always know where to find it. It is a simple system, but unfortunately introduces our first and somewhat unavoidable assumption.

All _rich_ objects must start with this entry - but adding it is at the discretion of the programmer, __who may forget__.

As we know, C is famous for having no hidden costs. You pay only for what you use. This is why it is unavoidable. C allows you no way to insert this entry into a programmer's structs unknowingly. Doing so would be dishonest, and C hates liars.

What about having the type information in a separate table which we index using the struct memory location? This does work well, but also means any structure creation must go via some function we define (so we can add the type information to our table). In many cases this is fine, but sometimes it is more useful to have usable data come from outside of this function, for example created the stack (see _The Dollar_).

Anyway, if we swallow this cost, we can add many new behaviours to the language that seem like magic to the outside world. Onto the next stage, designing our _metadata_ object!


Metadata
--------

There are many ways to design a metadata object, but we must be careful. Already we have one constraint. Our metadata should be a _rich_ object. Meaning its first entry must be a pointer to _its_ type. But what is the type of a Type object? Well its type is just _Type_, who's type is _Type_ again.

Confused? Another problem is in constant initializers. In C many data types can't be used to initialize a metadata structure at compile time. But no one wants to have to declare all their types at runtime! This is why it must be carefully designed. The entries must be constant literals. The first entry must be its type. Yet it must express everything we need about an object.

In libCello I use a NULL terminated list of pairs. Each pair consists of a pointer to something and a string identifier.

    var MyType = {
      { Type,       "Type" },
      { MyTypeName, "Name" },
      { MyTypeNew,  "New"  },
      { MyTypeOrd,  "Ord"  },<commit_msg>minor correction<commit_after>Overview
========

I started libCello (then called C+) as a fun experiment to play around with the various implementations of _Object Orientation in C_. Most had some fun features and cool tricks but tended to break down around about the time of inheritence. Assertions began to pile up, syntax became horrible, or the programmer had to do too many things manually. Several based around message passing relied too heavily on error-prone strings.

One thing I did notice is that essentially they begin to resemble the C backend to scripting languages such as Python.

I wondered if by making different or simplified assumptions it would allow for nicer syntax, cleaner semantics and fewer manual steps for the programmer. I thought I might be able to create scripting language like semantics, but with the performance and frontend of C.

libCello consists of some global changes and a number of cute hacks. The global changes are not too original, but combined with the cute hacks create a library that is fairly comfortable to use.

I've tried to make this article short so have skipped somewhat on the nitty gritty details. Anyone interested is encouraged to send me an e-mail or take a peek at the source code!


Types
-----

To change a language behaviour one must either change the compiler or the runtime. A language like C essentially has no runtime system. It generates object code that looks like any other. But we can add one ourselves. We only need to add one powerful construct to do almost anything we want. This is the familiar _type_.

For example if we wish to add `new` and `delete` to a language, our system (the runtime), must know the size of the memory to allocate. This is just _metadata_ also known as _type_ information. We must store this somewhere while the program is running. It could be in a separate table, but is often useful to tie to the object we wish to manipulate itself.

For example we can make all _rich_ objects contain some pointer to their _type_ or _metadata_ at the beginning of the struct.

    typedef struct {
      type_t* meta_data;
      int other_data;
    } some_struct;

When we wish to manipulating these objects we can then follow the pointer to the metadata and extract the information we need. If this entry is always the first entry in the struct, whatever struct we encounter, we always know where to find it. It is a simple system, but unfortunately introduces our first and somewhat unavoidable assumption.

All _rich_ objects must start with this entry - but adding it is at the discretion of the programmer, __who may forget__.

As we know, C is famous for having no hidden costs. You pay only for what you use. This is why it is unavoidable. C allows you no way to insert this entry into a programmer's structs unknowingly. Doing so would be dishonest, and C hates liars.

What about having the type information in a separate table which we index using the struct memory location? This does work well, but also means any structure creation must go via some function we define (so we can add the type information to our table). In many cases this is fine, but sometimes it is more useful to have usable data come from outside of this function, for example created on the stack (see _The Dollar_).

Anyway, if we swallow this cost, we can add many new behaviours to the language that seem like magic to the outside world. Onto the next stage, designing our _metadata_ object!


Metadata
--------

There are many ways to design a metadata object, but we must be careful. Already we have one constraint. Our metadata should be a _rich_ object. Meaning its first entry must be a pointer to _its_ type. But what is the type of a Type object? Well its type is just _Type_, who's type is _Type_ again.

Confused? Another problem is in constant initializers. In C many data types can't be used to initialize a metadata structure at compile time. But no one wants to have to declare all their types at runtime! This is why it must be carefully designed. The entries must be constant literals. The first entry must be its type. Yet it must express everything we need about an object.

In libCello I use a NULL terminated list of pairs. Each pair consists of a pointer to something and a string identifier.

    var MyType = {
      { Type,       "Type" },
      { MyTypeName, "Name" },
      { MyTypeNew,  "New"  },
      { MyTypeOrd,  "Ord"  },
{'fraction_non_alphanumeric': 0.033905967450271246, 'fraction_numerical': 0.0, 'mean_word_length': 3.897066961815163, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2621809', 'n_tokens_mistral': 2110, 'n_tokens_neox': 2012, 'n_words': 1492}