Language manual
Version of 20200817.
The language is intended to be as equal to C as possible, with a few features from C++. This manual describes the implemented features.
The current implementation compiles the source to an AST (abstract syntax tree) in JSON format.
From the AST, a separated code generator produces assembly code for the Kobold K2 processor.
And finally, the Kobold K2 assembler produces binary code.
What is not implemented (yet)
- Preprocessor (for defines, includes and macros)
- library functions (like printf) and floating point
- function modifiers: static, inline
- storage specifiers: auto, extern, register
- type modifiers: long, short, unsigned
- multiplication and division
- goto statements
Program structure
The program is a list of declarations or definitions.
Declarations
Variable declarations
Variable declarations can have the form (example):
int n;
float x;
int p,q;
char c;
Some examples of more complex declarations:
int v[10]; //array
int *p; //pointer
int *v[10]; // array of pointers to int
int (*p)[10]; // pointer to array of int
int a[10][5] // 2-dimensional array of int
Variable declarations can be local or global.
Local variables can also be static.
Variables can also have an initializer.
Constant declarations
const number = 99;
const char hello[] = "Hello";
Structure declarations
A struct declaration has the form (example):
struct address;
The structure name can be used now, but its members must still be defined:
A struct can be defined as follows:
struct address {
char* name;
char* town;
int zip;
};
Variables address1 and address2 can be declared:
struct address address1, address2;
Or simply:
address address1, address2;
Union declarations
Unions are declared and defined in the same way as structs.
Use of typedef
A user-defined type can get a name by using "typedef", example:
typedef int * intpointer;
intpointer p1,p2;
This example defines variables p1 and p2 as pointer to int.
Functions
Function declarations
Function declarations have the form (example):
int compute(int,int);
This function declaration must be followed by a definition later.
A function definition has the form (example):
int compute(int x,int y) { int t; t = x+y; return t; } ;
void function2(int p,float z) { /* some action */ } ;
Function pointers
Function pointers are supported and work as in C++, example:
int (*v)(int); // declare a function pointer v
int f(int x) { // define a function to point to
return x+1;
}
int main()
{ int i;
v = f; // assign the function f to the function pointer
i=(*v)(3); // call the function that v points to
}
Function call
The number of actual arguments must be equal to the number of formal arguments in the definition.
Functions with variable number of arguments are also supported, but the macros that C uses to access them are not supported.
Expressions
This can be one of the following:
- identifier
- constant (only integer, char and string constants at the moment)
- function call
- ( expression )
- A operator B ( + - & | * && || )
- prefix-operator expression
- * (pointer dereferencing)
- & (referencing)
- ++
- --
- ~ (one's complement)
- sizeof
- - TODO
- expression postfix-operator
- expression [ expression ]
- expression . member-name
- expression -> member-name
Typecasting is supported for all built-in or 'typedef' types, and pointers to them.
Statements
- Assignment
- Function call
- If statement
- While statement
- Do statement
- For statement
- Switch statement
- Return statement
- Assignment-operators: -= +=
- Increment/decrement: i++; ++i; i--; --i;
Within loops, 'break' or 'continue' can be used.
In contrary to C practice, it is an error to use a statement at a position where an expression is
expected. So "if (d=6)" is illegal. This is because while programming in C, I did spend countless
hours tracing bugs, that could finally be solved by using a construction like "if (d==6)".
Assembly code can be inserted, like: ASM " mov a3,d0";
Comments
For comments, use /* .... */, or // for
comments for the rest of the line.