
Ask HN: Help me improve my C-like language, C3 - Nuoji
I&#x27;m working on a &quot;alternative to C&quot; called C3, but unlike most (e.g. Zig, Odin, Jai, Rust etc) it tries to stay really close to C syntax as far as possible and I&#x27;d love to hear what people like and what they dislike, especially if they write a lot of C.<p>The site here has an overview of the language and code samples: http:&#x2F;&#x2F;www.c3-lang.org<p>You can try it out in the browser here: https:&#x2F;&#x2F;ide.judge0.com&#x2F;?1EFo with the list of implemented features&#x2F;not yet implemented features in the compiler found here: https:&#x2F;&#x2F;github.com&#x2F;c3lang&#x2F;c3c<p>Currently the spec has a bit too many features so I will try to remove the superfluous to make the language more easy to grasp in its entirety.<p>The syntax tries to stay true to C, with things added on top that C can&#x27;t easily add due to backwards compatibility:<p>- Module system<p>- Generics<p>- Semantic Macros<p>- Error handling<p>- Defer<p>- Value methods<p>- Associated enum data<p>- Subtypes (Go&#x27;s embedded structs)<p>- Optional contracts<p>- Built-in strings, maps, subarrays and vararrays<p>P.S. I know the change to use `func` with functions is controversial – it&#x27;s great for a simpler grammar and to make function types stand out, but is quite a departure.<p>P.P.S. &quot;Why not just use C?&quot; Well, we&#x27;re seeing C++ inspired languages (like Rust) taking mindshare both from C++ and C communities. I would like to see an alternative that keeps to the simplicity of C code instead of taking C++ syntactic complexity as a base line.
======
qppo
Here are the things I would need to migrate from C/C++/Rust to a new language:

    
    
        Automatic memory management, with optional manual control, 
        no garbage collection. 
        
        A universal or widely accepted build system (Cargo, CMake) 
        
        A public package registry and dependency resolver, designed 
        for deterministic builds, multiple versions of the same 
        package on one machine, etc, and support for private/proprietary
        registries (Cargo, Conan)
    
        A modern query-oriented/reactive/responsive (non-batch) compiler, 
        that supports static analysis, linting, language server features, 
        AST traversals/queries, etc. 
    
        Support for debugging with GDB/LLDB. 
    
        A (substantial) subset of the language with a stable ABI. 
        
        Fast debug builds, fast release binaries. 
    

Syntax/semantics of the language are significantly less important to me than
all of the above.

~~~
Nuoji
\- Plan is to be able to at least build a robust ref counting lib in the
standard library, supported by subtyping and defer this could be at least as
easy as in ObjC _before_ automatic refcounting. Temporary allocators (like
Odin) will solve most of the temporary allocs (like when you work with strings
etc). I'd need some time to explain how that works in detail, but memory
management can be made much easier without even having GC or refcounting.

\- The build system is part of the compiler.

\- Package registry: still on the fence with that one. We'll see.

\- The compiler is not built as a responsive compiler. Working on the compiler
I don't feel that the workflow of a compiler is the same as is needed for an
IDE. The most important thing is not that the compiler is responsive, but that
the language amends itself to be compiled in isolation in a modular way. This
is a property of the language, and it's been designed with IDE friendliness in
mind.

\- Adding more DWARF support is on the todo and obviously a requirement for a
serious language

\- LLVM prevents anything based on LLVM to be really slow to compile. It takes
something like 99% of all compile time, even on debug builds with no
optimizations. To have really fast debug builds a custom backend is needed for
each platform. That will happen eventually.

------
gus_massa

      /**
       * @ensure const(foo), const(bar.x)
       **/
    

Does the compiler see inside comments? I think that Python does that for types
because they want to preserve backward compatibility, but I never like it. Why
not something like:

    
    
      #ensure const(foo), const(bar.x)
    

or

    
    
      @ensure const(foo), const(bar.x)

~~~
Nuoji
Three reasons:

1\. Implementing pre/post condition checks are optional for a conforming
compiler. Putting the checks in special docs comments underscores that the
checks are optional. The more C way would perhaps be to use pragma.

2\. Putting checks either between comments and function signature, function
signature and body, or at the start of the signature body visually divides
function signature from code that’s actually run.

3\. Since these are hard requirements on calling functions the information
needs to be in the documentation anyway. This ensures that docs and contracts
are always in sync.

But yes, I think your opposition to this is a valid one. It is not ideal,
rather it is the best trade off I could find. Given the above.

------
zzo38computer
I might like to have, in a better version of C:

\- GNU extensions, such as zero-length arrays, ?: with nothing in between, and
statements inside of expressions

\- Less confusing syntax for types

\- Full LLVM features

\- Non-Unicode

\- Both normal include files and token macros, as well as namespacing and
hygienic macros supported too

\- Standard macros for testing alignment, endianness, etc

\- Macros that can call compile-time execution of codes which can deal with
the AST

\- Reduced runtime requirements

\- Support for setjmp/longjmp with catch blocks; if you longjmp past such a
block, it should execute the catch block to clean up as needed before that
block jumps again back to the target of the longjmp operation

\- The goto command.

The worst thing about C is I think the confusing syntax for types. Pointer
arithmetic and goto are both good, though, so keep those.

I can do without automatic memory management.

~~~
Nuoji
\- Some GNU extensions are already there, let me know what else you need.

\- ?: and statement expressions (slightly extended) are available in C3 today.

\- Type syntax is simplified in C3 more in line with other languages, e.g.
java style array declarations.

\- What does "full LLVM features" mean?

\- What do you mean by "Non-Unicode"?

\- You'll likely be able to include files (and more), but token macros are out
I'm afraid. I've tried to cover all uses, but I know it's not quite complete
:(

\- All the stuff with offset, alignment etc will of course be available.

\- Macros can act like compile time functions, but direct manipulation of the
AST is not there to make the macros easier and safer to use. There is stil a
lot of things one can do with using conditional compilation etc, but no manual
construction of AST nodes. It's about trying to keep the language fairly
uniform even though you add a very powerful macro system. I'm sorry.

\- What do you mean by "reduced runtime requirements"? The ability to run it
freestanding? If so, yes then this is a goal.

\- No setjmp/longjmp, instead it has a system with implicit "Result" style
returns. But it has a unique flavour. A brief overview can be found here:
[http://www.c3-lang.org/errorhandling/](http://www.c3-lang.org/errorhandling/)

\- Sadly I had to give up on goto. To replace it: labelled blocks and labelled
for/do/while/if, switch-jumps with "next", error handling using "failable"
Result types and defer. The reason for removing goto was due to the amount of
compiler complexity needed to support unstructured jumps. I didn't remove it
willingly.

------
allochi
This is quit interesting project, I'm loving its direction. Something I hoped
for long time ago. I like that it's trying to make a better C not eliminating
it. Will keep a close eye.

