Skip to content

Instantly share code, notes, and snippets.

@bastienvoirin
Last active April 11, 2020 11:46
Show Gist options
  • Save bastienvoirin/ed31ccdafc347b4bbff02d91eb9faeec to your computer and use it in GitHub Desktop.
Save bastienvoirin/ed31ccdafc347b4bbff02d91eb9faeec to your computer and use it in GitHub Desktop.
B compiler
incdec = "++" | "--" ;
unary = "-" | "~" | "!" | "*" | "&" ;
binary = "|" | "&" | ["#"] rel | "%" ;
rel = "==" | "!=" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | "+" | "-" | "*" | "/" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
alpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
| "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
| "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M"
| "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
| "_" ;
name = (alpha | ".") {alpha | digit | "."} ;
char = digit | alpha | "**" | "*b" | "*t" | "*n" | "*'" | '*"' ;
sign = "+" | "-" ;
int = [sign] digit {digit} ;
float = int "." [{digit} ["e" int]] ;
charconst = "'" (any - "'") "'" ;
strconst = '"' {any - '"'} '"' ;
// 0: keyword
// 0: "auto"
// 1: "extrn"
// 2: "if"
// 3: "else"
// 4: "for"
// 5: "while"
// 6: "repeat"
// 7: "switch"
// 8: "do"
// 9: "return"
// 10: "break"
// 11: "goto"
// 12: "next"
// 13: "case"
// 14: "default"
// 1: operator
// 0: "="
// 3: "=="
// 4: "<"
// 5: "<<"
// 6: "<="
// 8: ">"
// 9: ">>"
// 10: ">="
// 12: "!"
// 14: "!="
// 16: "|"
// 17: "||"
// 20: "&"
// 21: "&&"
// 2: number
// value
// 3: string
// pointer
NULL = 0;
isSpace(c) return (c <= " ");
isDigit(c) return (c >= "0" && c <= "9");
isAlpha(c) return (c >= "a" && c <= "z" || c >= "A" && c <= "Z");
isAlNum(c) return (c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c >= "0" && c <= "9" || c == "_");
countLeading(str, c, i) {
auto n;
n = 0;
while (i-- && str[i] == c) n++;
return n;
}
main() {
auto i, j, x;
i = j = x = 0;
tk = getvec(1023);
while (src[i]) {
while (src[i] && isSpace(src[i])) i++;
switch (src[i]) {
case NULL:
break;
case "'":
case '"':
case "`":
x = src[i];
i++;
while (src[i] && (src[i] != x || countLeading(src, "**", i) % 2)) {
i++;
}
break;
case "<":
case "=":
case ">":
case "!":
case "~":
case "|":
case "&":
case "^":
case "+":
case "-":
case "*":
case "/":
case "%":
switch (src[i]) {
case "=":
x = 0; break;
case "<":
x = 4; break;
case ">":
x = 8; break;
case "!":
x = 12; break;
case "|":
x = 16; break;
case "&":
x = 20; break;
}
if (src[i++] == src[i]) {
x =+ 1;
i++;
}
if (src[i] == "=") {
x =+ 2;
i++;
}
tk[j++] = x;
break;
default:
break;
}
}
}
mask.sign { 0b1000000000000000 };
mask.exponent { 0b0111110000000000 };
mask.significant { 0b0000001111111111 };
.exponent = >> 10 & 0b11111 - 14;
min(x, y) return (x < y ? x : y);
max(x, y) return (x > y ? x : y);
fmin(x, y) return (x #< y ? x : y);
fmax(x, y) return (x #> y ? x : y);
pow(x, n) {
if (n < 0) return (#1 #/ #(pow(x, -n)));
if (n == 0) return (1);
auto y;
y = pow(x, n >> 1);
return ((n & 1) ? (x * y * y) : (y * y));
}
// Newton-Raphson method
sqrt(x) {
if (x #< 0) return (NaN);
auto a, b;
a = b = ##x;
while (b) {
a >>= 1;
b >>= b >> 1;
}
if (!a) a = 1;
a = b = #a;
repeat {
b = a #+ x #/ a;
b = (b & ~exponent) | (exponent & ((b.exponent) >> 1 << 10)); // floating point division by 2
if (a #== b) break;
a = b;
}
}
consts.cordic.invpow[] {
0b0011110000000000,
0b0011100000000000,
0b0011010000000000,
0b0011000000000000,
0b0010110000000000,
0b0010100000000000,
0b0010010000000000,
0b0010000000000000,
0b0001110000000000,
0b0001100000000000,
0b0001010000000000
};
consts.cordic.atan[] {
0b0011100001100101,
0b0011010000010110,
0b0011000000000101,
0b0010110000000001,
0b0010100000000000,
0b0010010000000000,
0b0010000000000000,
0b0001110000000000,
0b0001100000000000,
0b0001010000000000
};
consts.cordic.trigo { 0.607252 };
consts.cordic.hyper { 1.20513 };
cordic(m, epsilon, x0, z0) {
auto old_x, old_y, old_z;
auto new_x, new_y, new_z;
auto sgn, k;
old_x = x0;
old_y = #0;
old_z = z0;
k = 0;
m ->>= 1;
repeat {
sgn = #(1 - ((old_z <<- 2) & 2));
new_x = old_x #- (sgn #* old_y #* invPowOfTwo[k]) ^ m;
new_y = old_x #- (sgn #* old_x #* invPowOfTwo[k]);
new_z = old_z #- (sgn #* epsilon[k]);
if (newz #== oldz) break;
oldz = newz;
k++;
}
return;
}
sin(x) {
x = fmod(x, TAU);
if (x #<= HALF_PI)
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x)[1]);
if (x #>= HALF_PI #+ QUARTER_PI)
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x #- TAU)[1]);
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x #- PI)[1]);
}
cos(x) {
x = fmod(x, TAU);
if (x #<= HALF_PI)
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x)[0]);
if (x #>= HALF_PI #+ QUARTER_PI)
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x #- TAU)[0]);
return (cordic(0, consts.cordic.atan, consts.cordic.trigo, x #- PI)[0]);
}
sinh(x) {
x = fmod(x, TAU);
if (x #<= HALF_PI)
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x)[1]);
if (x #>= HALF_PI #+ QUARTER_PI)
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x #- TAU)[1]);
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x #- PI)[1]);
}
cosh(x) {
x = fmod(x, TAU);
if (x #<= HALF_PI)
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x)[0]);
if (x #>= HALF_PI #+ QUARTER_PI)
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x #- TAU)[0]);
return (cordic(1, consts.cordic.atan, consts.cordic.hyper, x #- PI)[0]);
}
tan(x) {
auto p;
p = cordic(0, consts.cordic.atan, consts.cordic.trigo, x);
return (p[1] #/ p[0]);
}
tanh(x) {
auto p;
p = cordic(1, consts.cordic.atan, consts.cordic.hyper, x);
return (p[1] #/ p[0]);
}
exp(x) {
auto p;
p = cordic(1, consts.cordic.atan, consts.cordic.hyper, x);
return (p[0] #+ p[1]);
}
error = chdir(path);
error = mkdir(name, mode);
file = open(filename, mode);
nread = read(file, buffer, count);
nwrite = write(file, buffer, count);
close(file);
NULL = 0;
false = 0;
true = -1;
bool = !!;
float = #;
int = ##;
main();
.length = [-2];
char(str, i) {
return ((i & 1) ? (str[i >> 1] >> 8) : (str[i >> 1] & 255)); /* Little-endian */
}
lchar(str, i, c) {
str[i] = c;
}
concat(str1, str2) {
}
equal(str1, str2) {
auto i;
i = 0;
while (str1[i] && str2[i]) {
if (str1[i] != str2[i]) return false;
i++;
}
return true;
}
compare(str1, str2) {
auto i;
i = 0;
while (str1[i] && str2[i]) {
if (str1[i] < str2[i]) return 1;
if (str1[i] > str2[i]) return -1;
i++;
}
if (str2[i]) return 1;
if (str1[i]) return -1;
return 0;
}
any(c, str, i) {
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment