Add example and readme, update header

This commit is contained in:
2026-02-07 14:04:32 +11:00
parent 6b3aa87b13
commit b31f2aaaa5
3 changed files with 246 additions and 15 deletions

105
README.md Normal file
View File

@@ -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 <zc.h>` 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.

93
bank.zc Normal file
View File

@@ -0,0 +1,93 @@
#include <string.h>
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));
}

61
zc.h
View File

@@ -1,18 +1,23 @@
#if 0 #if 0
# This is under construction!
# zc compiler (in a Bash script) # 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: # What this does:
# * Creates a .zcbuild folder # * Creates a .zc-build folder
# * Adds some boilerplate # * Adds some boilerplate
# * Inserts your code # * Inserts your code
# * Compiles and produces an executable # * 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. # 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.h>" > .zc-build/main.c
cat "$@" >> .zc-build/main.c
gcc .zc-build/main.c
rm -r .zc-build
exit exit
@@ -21,6 +26,12 @@ exit
#ifndef ZC_H #ifndef ZC_H
#define 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
@@ -64,6 +75,8 @@ exit
#define and && #define and &&
#define or || #define or ||
#define pass (void)0
/* /*
* TYPES * TYPES
* Creates friendlier names for different types. * Creates friendlier names for different types.
@@ -102,19 +115,15 @@ default: printf("unknown type\n") \
__new_something;\ __new_something;\
end) 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\ #define many(x, size) (then\
x* __new_something is malloc(sizeof(x) * size);\ x* __new_something is malloc(sizeof(x) * size);\
if (__new_something equals NULL) { print("Couldn't malloc :("); exit(1); }\ if (__new_something equals NULL) { print("Couldn't malloc :("); exit(1); }\
__new_something;\ __new_something;\
end) end)
#define forget free #define forget(var) _Generic((var), \
default: var.destructor_fn(&var) \
)
#define resize(var, size) then\ #define resize(var, size) then\
typeof(*var)* __resized_something is realloc(var, sizeof(typeof(*var)) * size);\ typeof(*var)* __resized_something is realloc(var, sizeof(typeof(*var)) * size);\
@@ -128,12 +137,36 @@ end
*/ */
#define constructor(class, ...) class new##class(__VA_ARGS__) #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) #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 destroyInteger(Integer* self) {}
static inline void destroyFloat(Float* self) {} static inline void destroyFloat(Float* self) {}
static inline void destroyDouble(Double* self) {} static inline void destroyDouble(Double* self) {}