CCARP - (trans)Compile C And Rust Partially
CCARP is a command line utility made with the sole purpose of transcompiling or transpiling C programs into Rust.
Does it actually work?
Somewhat.
At the moment CCARP can be used to rustify simple C programs, but for more complex programs it will most likely run into an error. If it succeeds however, it will produce a Rust program which either compiles or almost compiles, in either way its meaning will be similar to the C code (if one manages to solve all conflicts within the generated code).
An example
Example C code:
int
int
Generated Rust code (after formatting and simplification):
How to use it?
CCARP can be both a library and an executable.
You can use it as a dependency
in this case translate
, translate_single_file
and translate_project
functions are available.
Or alternatively you can install it as an executable via
After that a
command will show you how it can be used.
What does CCARP implement from C?
CCARP mainly implements the core of C, as in the syntax approximate meaning of C without most macros and standard library. (Also without goto
, labels and variadic functions amongst other things.)
What will most likely work:
- standard primitive types (
char
,short
,int
,long
,long long
, etc.) - expressions with primitive types (e.g.
1 + 2
,a + b
,1 ? a << 2 : b & c * 2
) - fixed size arrays (
int arr[5]
,{1,2,3}
) - simple declarations (
int c=0;
,typedef int int32;
) - most statements
if (1==2) { a=1; } else { a=2; }
for (int i=0;i<10;i++) { a+=2; }
while (a<5) { a++; }
- switch with some restrictions
switch
in general:
switch
- function definitions (
int add_two(int n) { return n+2; }
)
How does CCARP deal with types?
Primitive types
Primitive types are translated to the following Rust types:
c type | rust type |
---|---|
char | u8 |
unsigned char | u8 |
signed char | i8 |
short | i16 |
unsigned short | u16 |
int | i32 |
unsigned int | u32 |
long | i64 |
unsigned long | u64 |
long long | i64 |
unsigned long long | u64 |
float | f32 |
double | f64 |
long double | f64 |
bool | ~i8 |
void | () |
Arrays and Pointers
Arrays and pointers are somewhat dependent on compiler flags in translation. Basic array and pointer types:
c type | rust type |
---|---|
int * | *mut i32 |
const int * | *const i32 |
int *const | &mut i32 |
const int *const | &i32 |
int arr[N] | [i32;N] |
Conversions
CCARP applies a best-effort conversion between types, but not all types can be trivially converted into another. This is why for example void *
does not compile to valid Rust at the moment.
How does CCARP work?
CCARP uses Pest for parsing its inputs into tokens; after tokenisation it parses tokens into C translation units and creates a C AST (Abstract Syntax Tree for short) from it; the next step after that is logically morphing the C AST into a Rust AST and from that the program can produce a Rust code (which might or might not work).
In fewer words:
- C Code
- Tokenisation
- Parsing tokens into structures
- C AST
- Rust AST
- Rust Code