diff --git a/README.md b/README.md new file mode 100644 index 0000000..2096845 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# zc + +What if C, but easier? + +## What is zc? + +zc is a headerfile which makes a bunch of macros which mess with the way the C programming language works. + +One of the primary advantages of using zc is easier object orientated patterns, without the bloat of C++. (The syntax does need a little getting used to.) + +## Setup + +``` +sudo make install +``` + +## Usage + +There are 2 ways to use zc: + +* Inside of C - do `#include ` and you've now got access to all that zc has to offer. +* Using a .zc file and the zc command - you won't be yelled at as much. Type `zc filename.zc` to compile. + +However, using either will allow you to program in the same way. + +## Syntax + +This section is WIP + +Define an entry point: + +```c +entry { + +} +``` + +Create variables: + +```c +entry { + Integer x is 5; +} +``` + +Print something out: + +```c +entry { + Integer x is 5; + print(x); +} +``` + +Create a list of something: + +```c +entry { + Integer list x is many(Integer, 5); + x[0] is 5; + x[1] is 10; + x[2] is 15; + x[3] is 20; + x[4] is 25; + + // Resize the list + resize(x, 10); +} +``` + +Create a class, constructor, destructor, and methods: + +```c +class(Car, { + String make; + Integer year; + Method(Car, drive, void); + Destructor(Car); +}); + +method(Car, drive, void) { + // self allows you to access elements inside the class + printf("Car %s from %d goes vroom vroom\n", self->make, self->year); +} + +destructor(Car) { + free(self->make); +} + +constructor(Car, String make, Integer year) { + return (Car) { + .make = make, + .year = year, + .drive = &__Car_drive, + .destructor_fn = &destroyCar, + }; +} + +entry { + Car myCar = newCar("Toyota", 1996); + myCar.drive(&myCar); +} +``` + +See `bank.zc` for a full example. diff --git a/bank.zc b/bank.zc new file mode 100644 index 0000000..48faf78 --- /dev/null +++ b/bank.zc @@ -0,0 +1,93 @@ +#include + +class(BankAccount, { + Integer money; + String name; + Method(BankAccount, deposit, Integer, Integer amount); + Method(BankAccount, withdraw, Integer, Integer amount); + Method(BankAccount, getAmount, Integer); + Destructor(BankAccount); +}); + +method(BankAccount, deposit, Integer, Integer amount) { + self->money += amount; + return self->money; +} + +method(BankAccount, withdraw, Integer, Integer amount) { + self->money -= amount; + return self->money; +} + +method(BankAccount, getAmount, Integer) { + return self->money; +} + +destructor(BankAccount) {} + +constructor(BankAccount, String name) { + return (BankAccount) { + .money = 10, + .name = name, + .deposit = &__BankAccount_deposit, + .withdraw = &__BankAccount_withdraw, + .getAmount = &__BankAccount_getAmount, + .destructor_fn = &destroyBankAccount + }; +} + +class(Bank, { + Integer size; + Integer capacity; + BankAccount list accounts; + Method(Bank, addAccount, BankAccount*, BankAccount account); + Method(Bank, getAccount, BankAccount*, String name); + Destructor(Bank); +}); + +method(Bank, addAccount, BankAccount*, BankAccount account) { + if (self->size plus 1 greaterorequalto self->capacity) { + resize(self->accounts, self->capacity * 2); + } + self->accounts[self->size] = account; + self->size increment; + return &self->accounts[self->size - 1]; +} + +method(Bank, getAccount, BankAccount*, String name) { + for (Integer i = 0; i lessthan self->size; i increment) { + if (strcmp(name, self->accounts[i].name) equals 0) { + return &self->accounts[i]; + } + } + return NULL; +} + +destructor(Bank) { + for (Integer i = 0; i lessthan self->size; i increment) { + forget(self->accounts[i]); + } + free(self->accounts); +} + +constructor(Bank) { + return (Bank) { + .size = 0, + .capacity = 32, + .accounts = many(BankAccount, 32), + .addAccount = &__Bank_addAccount, + .getAccount = &__Bank_getAccount, + .destructor_fn = &destroyBank + }; +} + +entry { + Bank myBank = newBank(); + myBank.addAccount(&myBank, newBankAccount("Maxwell")); + myBank.addAccount(&myBank, newBankAccount("John Citizen")); + myBank.addAccount(&myBank, newBankAccount("Jane Citizen")); + + BankAccount* max = myBank.getAccount(&myBank, "Maxwell"); + max->deposit(max, 100); + print(max->getAmount(max)); +} diff --git a/zc.h b/zc.h index cc0a20b..e312844 100644 --- a/zc.h +++ b/zc.h @@ -1,18 +1,23 @@ #if 0 -# This is under construction! - # zc compiler (in a Bash script) -# If you dont want to write in the style of C, write as a zc script! +# If you dont want to write in the style of C, write as a .zc script! # What this does: -# * Creates a .zcbuild folder +# * Creates a .zc-build folder # * Adds some boilerplate # * Inserts your code # * Compiles and produces an executable +# * Removes the .zc-build folder, unless there was an error, so you can debug # Alternatively, you can use zc as a C library, if you wish. -echo "Work in progress! Please come back later" +set -e + +mkdir -p .zc-build +echo "#include " > .zc-build/main.c +cat "$@" >> .zc-build/main.c +gcc .zc-build/main.c +rm -r .zc-build exit @@ -21,6 +26,12 @@ exit #ifndef ZC_H #define ZC_H +/* + * zc - What if C, but easier? + * A work in progress project by Maxwell Jeffress + * Licenced to you under the MIT license. + */ + #include #include #include @@ -64,6 +75,8 @@ exit #define and && #define or || +#define pass (void)0 + /* * TYPES * Creates friendlier names for different types. @@ -102,19 +115,15 @@ default: printf("unknown type\n") \ __new_something;\ end) -#define newlist(...) (then\ - void* __new_something is malloc(sizeof({__VA_ARGS__}));\ - if (__new_something equals NULL) { print("Couldn't malloc :("); exit(1); }\ - __new_something;\ -end) - #define many(x, size) (then\ x* __new_something is malloc(sizeof(x) * size);\ if (__new_something equals NULL) { print("Couldn't malloc :("); exit(1); }\ __new_something;\ end) -#define forget free +#define forget(var) _Generic((var), \ + default: var.destructor_fn(&var) \ +) #define resize(var, size) then\ typeof(*var)* __resized_something is realloc(var, sizeof(typeof(*var)) * size);\ @@ -125,15 +134,39 @@ end /* * CLASSES * These macros assist with creating classes. - */ +*/ #define constructor(class, ...) class new##class(__VA_ARGS__) -// #define destructor(class, ...) void destroy##class(class* self, __VA_ARGS__) +#define destructor(class, ...) void destroy##class(class* self, ##__VA_ARGS__) -#define class typedef struct +#define Destructor(class) void (*destructor_fn)(struct class* self) + +#define Method(class, name, return, ...) return (*name)(struct class* self, ##__VA_ARGS__) +#define method(class, name, return, ...) return __##class##_##name(class* self, ##__VA_ARGS__) + +#define class(className, body) struct className; typedef struct className body className #define entry Integer main(Integer argc, String list argv) +static inline Integer newInteger() { + return 0; +} +static inline Float newFloat() { + return 0; +} +static inline Double newDouble() { + return 0; +} +static inline Character newCharacter() { + return 0; +} +static inline String newString() { + return ""; +} +static inline Boolean newBoolean() { + return false; +} + static inline void destroyInteger(Integer* self) {} static inline void destroyFloat(Float* self) {} static inline void destroyDouble(Double* self) {}