Implementation of a language similar to the B as a recreational excercise. The goal is to represent the spirit of the language and there is no need to match it perfectly. It's B for modern systems.
/* Prints hello, world and a newline to the standard output using libc */
main()
extrn printf;
{
printf("hello, world*n");
}max(x0,x1,x2,x3,x4,x5) extrn printf; {
auto i, p, m;
p = &x0;
m = p[0];
i = 0;
while (p[i] != 0) {
if (p[i] > m) m = p[i];
++i;
}
return(m);
}
main() extrn printf; {
printf("max(1, 2) = %lld*n", max(1, 2, 0));
printf("max(1, 3, 2) = %lld*n", max(1, 3, 2, 0));
}Needs to be linked with Raylib. See Makefile.
main() {
extrn InitWindow, CloseWindow, WindowShouldClose, SetTargetFPS,
BeginDrawing, EndDrawing,
ClearBackground, DrawRectangle;
auto x, y, dx, dy;
dx = dy = 1;
x = y = 10;
InitWindow(800, 600, "Raylib from B");
SetTargetFPS(60);
while (!WindowShouldClose()) {
if (x <= 0 || x+100 >= 800) dx *= -1;
if (y <= 0 || y+60 >= 600) dy *= -1;
x += dx * 2;
y += dy * 2;
BeginDrawing();
ClearBackground(0);
DrawRectangle(x, y, 100, 60, 0xff80ff00);
EndDrawing();
}
CloseWindow();
}- Give myself a platform to explore algorithms used in compilers
- Allow to extend this language in weird ways and see results (base language doesn't have even types)
- Use self-hosted
libbinstaed oflibcby default (but option to link withlibcshould be possible) - Create some alternative history C
- Create self hosted version
Implementation progress b.c
One-pass compiler (meaning: compiler that in single pass outputs multi-pass assembly) that directly produces very unoptimized assembly. When all of the features of the language are implemented then I would start to make code generation better (including some optimizations), possibly splitting project in half - into one pass and multi pass backends.
- Literals
- Character literals
- String literals
- Decimal integer literals
- Hexadecimal integer literals
- Octal integer literals
- Multicharacter literals
- Definitions
- Functions
- Global variable definition
- Statements
-
extrn -
auto -
return -
while - expression statements
- compound statement
-
if - empty statement
-
goto - statement labels
-
switch -
case -
break -
continue
-
- Expressions
- Function call
- Constant
- Binary operators
- Additive operators:
+ - - Assigment
= - Bitwise operators:
& ^ | - Multiplicative operators:
* / % - Relational operatos:
< > <= >= == != - Compound assigment
op= - Shift operators:
<< >> - Index
- Logical (short circuting):
&& ||
- Additive operators:
- Unary operators
- Address of:
& - Bitwise complement:
~ - Indirection:
* - Logical Not:
! - Negation:
- - Post-increment/decrement
- Pre-increment/decrement
- Address of:
- Integer literals can have
_inside them, making constants like0xdeadc0demore readable:0xdead_c0de - Index operator behaves differently then pointer arithmetic -
a[b] != *(a + b). This is due to the B assuming that memory is made from word size cells, makinga[1]go to the second cell of array. Thusa[b] == *(a + b * 8), making also index of operator not commmutative. To fix this B would need a type system (or treat every pointer as a index of cell in memory but that would potentialy break ABI). Note that this property doesn't allow us for byte like access:*(a + 1)wouldn't allow to read second byte allocated bymalloc(2). Sadly it makes such classic iteration pattern likewhile (*p++)incorrect.