This is pure brainstorming but there is several ideas I have, which are mainly made of what I don't like about C and C++ replaced, and what I like being kept.
I'd make it somehow C-like, but with the following differences/simplifications :
- { and } are not used, ( and ) are used instead, so that they are easy to access on a swiss keyboard (I know { and } are easy to access an american keyboard, but they aren't for me).
- Operators are all overloadable for any types
- bool is the only type, other types are built using solely bool, array, struct, union and pointers. char for example would be a typedef for an array of 8 bool
- No opeartor such as '+' or '-' is build in, they are just part of a standard library that can be changed if the user wishes to. Only the boolean &, | and ^ are implemented by default. Everything else sits inside a library.
- Assignement is made with <- operator instead of = which is confusing because it could mean equality.
- Arrays are dereferenced with () instead of []
- Structs and unions are acessed with () just like arrays (basically, everything is always deferenced with ())
- There is no const-correctness, the compiler determines whenever a "variable" is constant and applies the appropriate optimisations when it is
- To avoid the passage by value or reference issue, the arguments of a function are always readonly (i.e. const). If the user wishes to modify them he has to make a local copy manually
- Inside for loops, ',' is used instead of ';' to separate instructions
- It's easy to do pseudo-OO when there's a need to by adding function pointers in a struct, yet it's not "pure" OO or any bullshit like that
- The syntax for function pointers is fixed so that it makes sense (I don't know how yet I admit)
- The while part of a do/while loop is optional, when only "do" is used that's an infinite loop
- Returned values are named, and are usable as local variables. (if no name is given "return" is used automatically)
- It's possible to return multiple values (a.k.a. unnamed structs) easily
- Compile time constant automatically decay in an usable array of bits
- Type modifiers are always arround the type name instead of the declaration name (i.e. bool[8] i, not bool i[8] for declaring a 8-bit integer)
Here you are a sample at what the language I have in mind might be looking :
Code: Select all
typedef char bool[8]; // Define a 8-bit integer type
char operator==(char a, char b)
(
return <- (a(0) == b(0)) &
(a(1) == b(1)) &
(a(2) == b(2)) &
(a(3) == b(3)) &
(a(4) == b(4)) &
(a(5) == b(5)) &
(a(6) == b(6)) &
(a(7) == b(7));
)
char operator!=(char a, char b)
(
return <- !(a==b);
)
// Unsigned comparison
char operator<(char a, char b)
(
if(a(7) != b(7)) return b(7);
if(a(6) != b(6)) return b(6);
if(a(5) != b(5)) return b(5);
if(a(4) != b(4)) return b(4);
if(a(3) != b(3)) return b(3);
if(a(2) != b(2)) return b(2);
if(a(1) != b(1)) return b(1);
if(a(0) != b(0)) return b(0);
)
bool operator<=(char a, char b)
(
if(a == b) return <- true;
else return <- a<b;
)
bool operator>=(char a, char b)
(
return <- !(a<b);
)
bool operator>(char a, char b)
(
return <- !(a<=b);
)
// Now we can compare 8-bit integers. Let's create a library so that we can add and substract them
(bool sum, bool cin) full_adder(bool a, bool b, bool cin)
(
sum <- a ^ b ^ cin;
cout <- (a ^ b & cin) + (a & b);
)
// Define incrementation (using auto-vectorisation) the compiler optimizes the incrementation in an inc instruction
(char res) operator++(char a)
(
bool carry;
(res(0), carry) <- full_adder(a(0), 1, 0);
(res(1), carry) <- full_adder(a(1), 0, carry);
(res(2), carry) <- full_adder(a(2), 0, carry);
(res(3), carry) <- full_adder(a(3), 0, carry);
(res(4), carry) <- full_adder(a(4), 0, carry);
(res(5), carry) <- full_adder(a(5), 0, carry);
(res(6), carry) <- full_adder(a(6), 0, carry);
(res(7), carry) <- full_adder(a(7), 0, carry);
)
(char res) opearator+(char a, char b) (using auto-vectorisation the compiler optimises this into a simple add operation)
(
char i;
bool carry;
for(i <- 0, i != 7, ++i)
(
(res(i), carry) <- full_adder(a(i), b(i), 0);
)
)
// Now let's define a vector type
typedef char[8] vector;
// We can add vectors
(vector res) operator+(vector a, vector b)
(
char i;
bool carry;
for(i <- 0, i != 7, ++i)
(
(res(i), carry) <- full_adder(a(i), b(i), 0);
)
)
// Let's create a 8x8 matrix type
typedef vector[8] mat64_t;
// We can add matrixes
(mat64_t res) operator+(mat64_t a, mat64_t b)
(
char i;
bool carry;
for(i <- 0, i != 7, ++i)
(
(res(i), carry) <- full_adder(a(i), b(i), 0);
)
)
(vector result) bubble_sort(vector data)
(
result <- data; // data CANNOT be modified because it is automatically called as a const-reference, so we have to copy here
bool sorted;
do
(
sorted <- true;
for(int i <- 0, i<7, ++i)
(
if(result(i) < result(i+1))
(
int temp <- data(i);
data(i+1) <- result(i);
sorted <- false;
)
)
)
while(!sorted); //If we ommited this line the program would still be legal but would never exit, it would *NOT* be a syntax error
)
void main()
(
bool[8] a <- (true, false, false, true, true, false, true, false); // primitive way of assigning 154 to a 8-bit value
char b <- 154; // The intent is here more clearer
bool[8] c <- 154; // It makes it explicit the value is a 8-bit one
char d <- 0x94; // Still the exact same, using hexadecimal notation
char e <- (154); // Equivalent, an array of 1 element is the same as the element iself
char f <- (1, 0, 0, 1, 1, 0, 1, 0); // Yet another way to do it, each digit turns into an array of 1 bit and is thus equivalent
char g <- b + c; // How to make computations and store them in variables
if(b) // ERROR, b is not boolean type
(
)
if(b == 0) // Correct, as 0 will automatically be converted to an array of the correct size (here 8)
(
)
vector h <- 0; // Incorrect, because cannot convert from bool[1] to bool[8][8]
vector i <- (1, 2, 3, 4, 5, 6, 7, 8); // This is correct
vector j <- (((1, 2, 3, 4, 5, 6, 7, 8))); // Also correct, the type is bool[n][8][1][1] which decays into bool[8][8] as arrays of 1 elements are the same as the element itself
char[6] k <- ('h', 'e', 'l', 'l', 'o', 0); // How to build a string
char[6] l <- "hello"; //Would somehow be equivalent
vector m <- "hello "; // Correct, with the null termination this makes a 8-character array
vector n <- "hello"; // Incorrect, cannot convert bool[8][6] into bool[8][8]
vector o <- m+n; //Legal ! We add vectors with a simple '+' !
n <- sort(m); // The vector n is directly tied to "result", so no more than 1 copy was necessary
m <- sort(m); // The copy is optimized out, as the function notices the references points to the same variable
mat64_t p <- (m, n, o, m, n, o, m, n); //Define a 8x8 matrix
mat64_t q <- (m+n, o+n, m+o, p(3), p(2), o, m, n, (1, 2, 3, 4, 5, 4, 3, 2)); //Define another 8x8 matrix
mat64_t r <- p + q; // Legal ! We add matrixes with a '+' !
// Now let's assume types like string, int, etc.. are defined, with operators overloaded so that they are usable like in C
// As well as a print() function
struct
(
string name,
int age,
double height,
) student <- ("max", 21, 1.78); // Affects fields globally
++student(age); // Affects fields individually
student(heigth) <- 1.88;
// Can be done via a normal function overloaded for multiple types
print(student(name)); //Prints max
print(student(age)); //Prints 22
print(student(heigth)); //Prints 1.88
// Can also be done via operator overloading of << if one prefers
print << student(name) << student(age) << student(height);
)