colored demo

This commit is contained in:
Yaossg 2025-03-10 00:46:24 +08:00
parent 1bcff515b7
commit e425464aab
5 changed files with 183 additions and 35 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ cov
*.s
*.ans
*.elf
*.html

88
boot.c
View file

@ -20,13 +20,10 @@ void exit(int status);
int fprintf(void* file, char* format, ...);
int ungetc(int ch, void* file);
void ungetchar(int ch) {
ungetc(ch, stdin);
}
// limitations
enum {
ECHO_BUFFER_SIZE = 65536,
STRING_TABLE_SIZE = 65536,
STRING_LUT_SIZE = 4096,
ID_TABLE_SIZE = 65536,
@ -35,6 +32,28 @@ enum {
REG_SIZE = 4096,
};
// hooks
char echo_buffer[ECHO_BUFFER_SIZE];
int echo_size;
int readchar() {
int ch = getchar();
if (ch != '\n') {
echo_buffer[echo_size++] = ch;
} else {
echo_buffer[echo_size++] = 0;
printf("#@%s\n", echo_buffer);
echo_size = 0;
}
return ch;
}
void ungetchar(int ch) {
--echo_size;
ungetc(ch, stdin);
}
// constants
enum {
@ -220,7 +239,7 @@ int is_id_cont(int ch) {
int parse_int(int ch) {
int num = ch - '0';
while (is_digit(ch = getchar())) {
while (is_digit(ch = readchar())) {
num *= 10;
num += ch - '0';
}
@ -229,7 +248,7 @@ int parse_int(int ch) {
}
int get_escaped_char() {
int ch = getchar();
int ch = readchar();
if (ch == 'n') return '\n';
if (ch == 't') return '\t';
if (ch == 'r') return '\r';
@ -252,7 +271,7 @@ int string_lut_size;
int parse_string() {
int offset = string_offset;
int ch;
while ((ch = getchar()) != '"') {
while ((ch = readchar()) != '"') {
if (ch == -1 || ch == '\n') {
fprintf(stderr, "expecting '\"'\n");
exit(1);
@ -292,7 +311,7 @@ int id_lut_size;
int parse_id(int ch) {
int offset = id_offset;
id_table[id_offset++] = ch;
while (is_id_cont(ch = getchar())) {
while (is_id_cont(ch = readchar())) {
id_table[id_offset++] = ch;
}
ungetchar(ch);
@ -366,9 +385,9 @@ void next_token() {
token_state = 0;
return;
}
int ch = getchar();
int ch = readchar();
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
ch = getchar();
ch = readchar();
}
if (ch == -1) {
token_type = TOKEN_EOF;
@ -385,7 +404,7 @@ void next_token() {
} else if (ch == '}') {
token_type = TOKEN_BRACE_RIGHT;
} else if (ch == '+') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '+') {
token_type = TOKEN_INC;
} else if (ch2 == '=') {
@ -395,7 +414,7 @@ void next_token() {
token_type = TOKEN_ADD;
}
} else if (ch == '-') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '-') {
token_type = TOKEN_DEC;
} else if (ch2 == '=') {
@ -405,7 +424,7 @@ void next_token() {
token_type = TOKEN_SUB;
}
} else if (ch == '*') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_MUL_ASSIGN;
} else {
@ -413,22 +432,22 @@ void next_token() {
token_type = TOKEN_MUL;
}
} else if (ch == '/') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_DIV_ASSIGN;
} else if (ch2 == '/') {
do ch = getchar(); while (ch != -1 && ch != '\n');
do ch = readchar(); while (ch != -1 && ch != '\n');
next_token();
return;
} else if (ch2 == '*') {
while (1) {
ch = getchar();
ch = readchar();
if (ch == -1) {
fprintf(stderr, "expecting '*/'\n");
exit(1);
}
if (ch == '*') {
ch = getchar();
ch = readchar();
if (ch == '/') {
break;
}
@ -441,7 +460,7 @@ void next_token() {
token_type = TOKEN_DIV;
}
} else if (ch == '%') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_REM_ASSIGN;
} else {
@ -457,11 +476,11 @@ void next_token() {
} else if (ch == ',') {
token_type = TOKEN_COMMA;
} else if (ch == '<') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_LE;
} else if (ch2 == '<') {
int ch3 = getchar();
int ch3 = readchar();
if (ch3 == '=') {
token_type = TOKEN_LSHIFT_ASSIGN;
} else {
@ -473,11 +492,11 @@ void next_token() {
token_type = TOKEN_LT;
}
} else if (ch == '>') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_GE;
} else if (ch2 == '>') {
int ch3 = getchar();
int ch3 = readchar();
if (ch3 == '=') {
token_type = TOKEN_RSHIFT_ASSIGN;
} else {
@ -489,7 +508,7 @@ void next_token() {
token_type = TOKEN_GT;
}
} else if (ch == '=') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_EQ;
} else {
@ -497,7 +516,7 @@ void next_token() {
token_type = TOKEN_ASSIGN;
}
} else if (ch == '!') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_NE;
} else {
@ -505,7 +524,7 @@ void next_token() {
token_type = TOKEN_NOT;
}
} else if (ch == '&') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_AND_ASSIGN;
} else if (ch2 == '&') {
@ -515,7 +534,7 @@ void next_token() {
token_type = TOKEN_AND;
}
} else if (ch == '|') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_OR_ASSIGN;
} else if (ch2 == '|') {
@ -525,7 +544,7 @@ void next_token() {
token_type = TOKEN_OR;
}
} else if (ch == '^') {
int ch2 = getchar();
int ch2 = readchar();
if (ch2 == '=') {
token_type = TOKEN_XOR_ASSIGN;
} else {
@ -536,11 +555,11 @@ void next_token() {
token_type = TOKEN_INV;
} else if (ch == '\'') {
token_type = TOKEN_NUMBER;
token_data = getchar();
token_data = readchar();
if (token_data == '\\') {
token_data = get_escaped_char();
}
if (getchar() != '\'') {
if (readchar() != '\'') {
fprintf(stderr, "expecting '\n");
exit(1);
}
@ -550,8 +569,8 @@ void next_token() {
dedup_string();
} else if (ch == '.') {
token_type = 0;
if (getchar() == '.') {
if (getchar() == '.') {
if (readchar() == '.') {
if (readchar() == '.') {
token_type = TOKEN_ELLIPSIS;
}
}
@ -826,7 +845,7 @@ void load(int rd, int rs) {
}
rs = rd;
}
printf(" %s %s, 0(%s) # load non-trivial register\n", op, rd_name, reg_name(rs));
printf(" %s %s, 0(%s)\n", op, rd_name, reg_name(rs));
}
// store a trivial register into a non-trivial one
@ -839,7 +858,7 @@ void store(char* rs, int reg) {
}
reg = REG_T2;
}
printf(" %s %s, 0(%s) # store non-trivial register\n", op, rs, reg_name(reg));
printf(" %s %s, 0(%s)\n", op, rs, reg_name(reg));
}
int is_nontrivial(int reg) {
@ -972,7 +991,7 @@ int lookup(int id) {
char* name = id_table + id_lut[id];
if (global_kind[id]) {
if (global_kind[id] == KIND_FUNCTION) {
fprintf(stderr, "function name must not appear outside function call: %s\n", name);
fprintf(stderr, "function name can only be directly called: %s\n", name);
exit(1);
}
int rd = next_reg(TYPE_VOID_PTR);
@ -1974,6 +1993,7 @@ void parse_top_level() {
}
void dump_string_table() {
printf("# string table: \n");
printf(".data\n");
for (int i = 0; i < string_lut_size; ++i) {
printf(".LC%d: .string \"", i);

4
compile.sh Normal file
View file

@ -0,0 +1,4 @@
gcc boot.c -o boot.elf &&
./boot.elf < $1 > $1.s
python3 transcript.py < $1.s > $1.html
rm boot.elf

9
demo/for.c Normal file
View file

@ -0,0 +1,9 @@
int printf(char* format, ...);
int main() {
int i;
for (i = 0;
i < 10;
++i)
printf("hello %d\n", i);
}

114
transcript.py Normal file
View file

@ -0,0 +1,114 @@
import sys
import html
src = ''
asm = ''
style = 0
flip = False
def decorate(line):
return f'<span class="style{style}">{html.escape(line)}</span>'
for line in sys.stdin:
if line.startswith("#@"):
line = line.removeprefix("#@")
src += decorate(line) if flip else line
style += 1
style %= 5
flip = False
elif line.startswith("# string table: "):
asm += line
break
else:
asm += decorate(line)
flip = True
for line in sys.stdin:
asm += line
title = 'RVBTCC Code Gen Demo'
template = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%title%></title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
}
header {
background-color: #4CAF50;
color: white;
padding: 1em;
text-align: center;
width: 100%;
}
.container {
display: flex;
width: 80%;
margin: 2em 0;
}
.column {
flex: 1;
margin: 0 1em;
}
pre {
background-color: #f4f4f4;
padding: 1em;
border: 1px solid #ddd;
overflow-x: auto;
}
code {
font-family: 'Consolas', Consolas, monospace;
font-size: 20px;
}
.style0 {
background-color: rgba(255,129,130,0.4);
}
.style1 {
background-color: rgba(212,167,44,0.4);
}
.style2 {
background-color: rgba(74,194,107,0.4);
}
.style3 {
background-color: rgba(84,174,255,0.4);
}
.style4 {
background-color: rgba(194,151,255,0.4);
}
</style>
</head>
<body>
<header>
<h1><%title%></h1>
</header>
<div class="container">
<div class="column">
<h2>Source Code</h2>
<pre>
<code><%src%></code>
</pre>
</div>
<div class="column">
<h2>Assembly</h2>
<pre>
<code><%asm%></code>
</pre>
</div>
</div>
</body>
</html>
'''
print(template.replace("<%title%>", title).replace("<%src%>", src).replace("<%asm%>", asm))