logo

C3 Programming Language

Posted on: 2022-02-4

Conclusion

C3 has the feel of a language that has real use. It has the same sort of feel as Zig, Odin and V. Like these languages it has similarly well thought through and pragmatic answers. Overall I like quite alot.

Good

Not sure

Bad

Ugly

Discussion

Lots of good stuff

Not so sure

Uses C++ {} compound literal initialization.

Uses fn to introduce a function. Has slices built in.

Enums have min and max built in values, and .values is the array of all values.

Has defer. Has "substructs" feature. Seems to be like making the fields available in the outer struct. Introduces fault to enumerate error codes. It looks like an error code based mechanism.

Pre and post conditions use syntax as part of comment.

Macro system ... it seems interesting.

"Generic Modules", it seems like a parameterization of a whole module of code.

Interesting ideas around modules. Can be made up of multiple files. Importing imports any nested modules. Adds private modules and importing private. Importing private makes modules private internals available. Defining a module private means it's all private and importing doen't recursively import sub modules.

Types don't need to have module specified, if imported and not ambiguous. Everything else does.

Has a vector type. Syntax is int[<size>].

Has distinct types.

Can associate a static value with each enum value.

Similar struct subtyping mechanisms seen in JAI and others.

Bit structs are interesting. They specify a backing type. They can only hold integer types. To produce something more convoluted, perhaps they are then used within a struct. Possible to specify endianess too. Can have overlapping fields too.

Has slicing via start..end (inclusive(!)) and via start, len via start : len.

Like the contracts concept, and that it can be used for optimizations. Think it would be better with regular syntax, rather than placed in comments.

Has interesting "expression block" syntax via {| and |}.

The labelled break/continue, the label comes after the statment name. It's still a bit odd. In the example all caps is used. It is definately better than JAI style, and with parens around the condition, it's actually not too bad.

nextcase is ok, but I think I'd prefer next_case.

Has a similar idea from V?, where you can have switch, and use expressions to match.

Can create literals with

fn void test(int[3] x) { ... }
test(int[3] { 1, 2, 3 });

Not sure about the need for && for a pointer to a literal.

Error handling

For C the interface to C3, the fault is returned as the regular value, while the return value is instead returned as an out parameter.

// In C3
fn int! getValue();

// In C
OptEnum getValue(int *value);

Can use catch or try

File*! file = openFile("foo.txt");

if (catch err = file) ...
if (try file) ...

A function, method or macro call with one or more parameters will only execute if the optional result has the expected result. This makes optional result returns composable.

When catch is used, the variable is "unwrapped" after that point and can be used directly.

The error type is pointer sized.

Has ? suffix will return if expected result is missing. !! will panic on failure.

Has ?? to return a default if there is an error.

Conversion in general looks pretty solid. Has some unusual rules that seem pretty sensible.

Need to think more about macro system, but does seem reasonable.

Has reflection.

The "builtins" are prefixed with $$. Built in "constants" seem to replace preprocessor special names. For example $$FUNCTION and $$LINE. Builtin functions are prefixed, but lower case. Example $$memcpy.

There are maths functions, and it says...

Can be applied to float vectors or numbers. Returns the same type.

And there are vector functions, such as $$reduce_max and $$reduce_min.

Contracts system looks good, although I think would be better for support to be part of the language, not part of comments.

Has operator overloading - seems to only be around "[]", so for containers.

Library system is interesting in so far as it's a system to package source. The manifest provides target specific information. On the one hand this is quite different from other "library" systems, and certainly from C and C++. On the other hand it's super simple, and provides a way to migrate and fix things in the future. The obvious downsides are compilation speed, and the visibility of the source. For many use cases though this might work relatively well, and has some nice advantages.

Read

Links