Scramble is a C preprocessor which allows to write C code which looks a bit like Python code with a full Python3 environment available for meta programming. That is, no semantics at all are changed - when using Scramble you still write C code. But it has a syntax more similar to Python.
Similar (and better) projects:Scramble is used like this:
scramble.py -i input.py -c output.c -h output.h -n name
For example, if you have a file main.py, then you could run:
scramble.py -i src/main.py -c build/c/main.c -h build/h/main.h -n main
And if your src/main.c would look like to the left, the resulting files would look like to the right (The red color indicates what the -n options does):
src/main.py import stdio, string, math int def main(int argc, char **argv): if argc == 2: printf("%f\n", sin(strtod(argv[1])) return 0 else: fprintf(stderr, "Need exactly one argument!\n") return 1 |
build/c/main.c #include "main.h" int main(int argc, char **argv) { if (argc == 2) { printf("%f\n", sin(strtod(argv[1])); return 0; } else { fprintf(stderr, "Need exactly one argument!\n"); return 1; } } build/h/main.h #ifndef _MAIN_ #include "stdio.h" #include "string.h" #include "math.h" extern int main(int argc, char **argv); #endif |
usage: scramble [-?] [-i INPUT] [-c CFILE] [-C] [-h HFILE] [-n NAME] [-p PREFIX] [-N] [-s SFILE] [--noc99] [-j JOIN [JOIN ...]] [-o OUTPUT] [-t CTYPES] optional arguments: -?, --help -i INPUT, --input INPUT input file -c CFILE, --cfile CFILE c output file -C, --comments keep comments -h HFILE, --hfile HFILE h output file -n NAME, --name NAME module name -p PREFIX, --prefix PREFIX header guard prefix -N, --no-lines don't generate #line directives -s SFILE, --sfile SFILE intermediate code output file --noc99 do not use C99 -j JOIN [JOIN ...], --join JOIN [JOIN ...] files to join -o OUTPUT, --output OUTPUT source code output file -t CTYPES, --ctypes CTYPES ctypes output file
All C, C++ and Python keywords basically are also Scramble keywords. The following control flow constructs are used by scramble: while, switch...case, do...while, for X while Y with Z [for (X; Y; Z) in C], for...in, if...elif...else, label [: in C], goto.
And these declarations: class [struct in C], def, enum, global, import, macro [#define in C], static, struct, typedef, union.
These Python operators are used instead of the C++ ones: and [&& in C], max, min, not [! in C], or [|| in C].
And there's a few new constants: True, False, None.
In general, here is what scramble will do:
if x == 2: x = 3 y = 3 |
translates to |
if (x == 2) { x = 3; y = 2; } |
def f1(): pass def f2(int x, y, z): pass int def f3(): pass |
translates to |
void f1(void) { } void f2(int x, int y, int z) { } int f3(void) { } |
test.py class A: int x class B: A *a static class C: B *b static A *def a_new(): A *self = calloc(1, sizeof *self) return self B *def b_new(): B *self = calloc(1, sizeof *self) self->a = a_new() return self |
translates to |
test.c #include "test.h" typedef struct C C; struct C { B *b; }; static A *a_new(void) { A *self = calloc(1, sizeof *self); return self; } B *b_new(void) { B *self = calloc(1, sizeof *self); self->a = a_new(); return self; } and test.h #ifndef _TEST_ typedef struct A A; typedef struct B B; struct A { int x; }; struct B { A *a; }; B *a_new(void); #endif |
import test, global stdio |
translates to |
#include "test.h" #include <stdio.h> |
***scramble for x in ["A", "B", "C"]: parse("char def function" + x + "(): return '" + x + "'") *** |
translates to |
char functionA(void) { return 'A'; } char functionB(void) { return 'B'; } char functionC(void) { return 'C'; } |
for MyElem *x in MyArray *arr: handle(x) |
translates to |
MyArrayIterator __iter__ = MyArrayIterator_first(arr); for (MyElem *x = MyArrayIterator_item(arr, &__iter__); MyArrayIterator_next(arr, &__iter__); x = MyArrayIterator_item(arr, &__iter__)) { handle(x); } |