unify printing + add basic strings

This commit is contained in:
r4 2021-12-25 12:16:06 +01:00
parent 92c4c5c991
commit f02dae603d
8 changed files with 162 additions and 52 deletions

23
ir.c
View File

@ -72,32 +72,11 @@ void irtoks_eat_irtoks(IRToks *v, IRToks *other, size_t jmp_offset) {
free(other->toks); free(other->toks);
} }
static void print_val(const Value *v);
static void print_irparam(const IRParam *p); static void print_irparam(const IRParam *p);
static void print_val(const Value *v) {
switch (v->type.kind) {
case TypeFloat:
printf("%f", v->Float);
break;
case TypeInt:
printf("%zd", v->Int);
break;
case TypeBool:
printf("%s", v->Bool ? "true" : "false");
break;
case TypeChar:
printf("'%c'", v->Char);
break;
default:
printf("(unknown type)");
break;
}
}
static void print_irparam(const IRParam *p) { static void print_irparam(const IRParam *p) {
if (p->kind == IRParamLiteral) { if (p->kind == IRParamLiteral) {
print_val(&p->Literal); print_value(&p->Literal, false);
} else if (p->kind == IRParamAddr) { } else if (p->kind == IRParamAddr) {
printf("%%%zd", p->Addr); printf("%%%zd", p->Addr);
} }

48
lex.c
View File

@ -54,7 +54,7 @@ static char get_esc_char(char c) {
} }
} }
TokList lex(const char *s) { TokList lex(const char *s, Pool *static_vars) {
TokList toks; TokList toks;
toklist_init(&toks); toklist_init(&toks);
Pos pos = { .ln = 1, .col = 1 }; Pos pos = { .ln = 1, .col = 1 };
@ -299,6 +299,52 @@ TokList lex(const char *s) {
emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = { .type = { .kind = TypeChar, }, .Char = c, }, }); emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = { .type = { .kind = TypeChar, }, .Char = c, }, });
break; break;
} }
case '"': {
consume(&pos, *(s++));
const char *start = s;
Pos start_pos = pos;
size_t size = 0;
/* count the string size before allocating */
while (s[0] != '"') {
if (!s[0]) {
set_err("Unexpected EOF in string literal");
return toks;
} else if (s[0] == '\\')
consume(&pos, *(s++));
consume(&pos, *(s++));
size++;
}
/* go through the actual string */
s = start;
pos = start_pos;
char *str = pool_alloc(static_vars, type_size[TypeChar] * size);
for (size_t i = 0; i < size; i++) {
char c = s[0];
if (c == '\\') {
consume(&pos, *(s++));
c = get_esc_char(s[0]);
if (!c) {
set_err("Unrecognized escape sequence: '\\%c'", c);
return toks;
}
}
consume(&pos, *(s++));
str[i] = c;
}
emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = {
.type.kind = TypeArr,
.Arr = {
.is_string = true,
.type.kind = TypeChar,
.vals = str,
.len = size,
.cap = size,
},
},});
break;
}
default: default:
set_err("Unrecognized character: '%c'", s[0]); set_err("Unrecognized character: '%c'", s[0]);
return toks; return toks;

2
lex.h
View File

@ -3,6 +3,6 @@
#include "tok.h" #include "tok.h"
TokList lex(const char *s); TokList lex(const char *s, Pool *static_vars);
#endif /* LEX_H */ #endif /* LEX_H */

17
main.c
View File

@ -34,15 +34,7 @@ static void die(const char *fmt, ...) {
} }
static Value fn_put(Value *args) { static Value fn_put(Value *args) {
switch (args[0].type.kind) { print_value(&args[0], true);
case TypeVoid: printf("(void)"); break;
case TypeFloat: printf("%f", args[0].Float); break;
case TypeInt: printf("%zd", args[0].Int); break;
case TypeBool: printf("%s", args[0].Bool ? "true" : "false"); break;
case TypeChar: printf("%c", args[0].Char); break;
default:
ASSERT_UNREACHED();
}
return (Value){0}; return (Value){0};
} }
@ -136,9 +128,11 @@ int main(int argc, const char **argv) {
} }
fclose(fp); fclose(fp);
/* lex source file */ /* lex source file */
TokList tokens = lex(file); Pool *static_vars = pool_new(4096);
TokList tokens = lex(file, static_vars);
if (err) { if (err) {
toklist_term(&tokens); toklist_term(&tokens);
pool_term(static_vars);
free(file); free(file);
fprintf(stderr, C_IRED "Lexer error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf); fprintf(stderr, C_IRED "Lexer error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf);
return 1; return 1;
@ -158,6 +152,7 @@ int main(int argc, const char **argv) {
if (err) { if (err) {
irtoks_term(&ir); irtoks_term(&ir);
toklist_term(&tokens); toklist_term(&tokens);
pool_term(static_vars);
fprintf(stderr, C_IRED "Parser error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf); fprintf(stderr, C_IRED "Parser error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf);
return 1; return 1;
} }
@ -169,9 +164,11 @@ int main(int argc, const char **argv) {
run(&ir, funcs); run(&ir, funcs);
if (err) { if (err) {
irtoks_term(&ir); irtoks_term(&ir);
pool_term(static_vars);
fprintf(stderr, C_IRED "Runtime error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf); fprintf(stderr, C_IRED "Runtime error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf);
return 1; return 1;
} }
} }
irtoks_term(&ir); irtoks_term(&ir);
pool_term(static_vars);
} }

90
tok.c
View File

@ -5,6 +5,75 @@
#include "util.h" #include "util.h"
size_t type_size[TypeEnumSize] = {
[TypeVoid] = 0,
[TypeFloat] = sizeof(((Value*)NULL)->Float),
[TypeInt] = sizeof(((Value*)NULL)->Int),
[TypeBool] = sizeof(((Value*)NULL)->Bool),
[TypeChar] = sizeof(((Value*)NULL)->Char),
[TypeArr] = sizeof(((Value*)NULL)->Arr),
};
void print_value(const Value *v, bool raw) {
switch (v->type.kind) {
case TypeVoid:
printf("(void)");
break;
case TypeFloat:
printf("%f", v->Float);
break;
case TypeInt:
printf("%zd", v->Int);
break;
case TypeBool:
printf("%s", v->Bool ? "true" : "false");
break;
case TypeChar:
if (raw)
printf("%c", v->Char);
else {
const char *esc = unescape_char(v->Char);
if (esc) printf("'%s'", esc);
else printf("'%c'", v->Char);
}
break;
case TypeArr:
if (v->Arr.is_string) {
if (v->Arr.type.kind != TypeChar)
ASSERT_UNREACHED();
char *str = v->Arr.vals;
if (!raw)
printf("\"");
for (size_t i = 0; i < v->Arr.len; i++) {
char c = str[i];
if (raw)
printf("%c", c);
else {
const char *esc = unescape_char(c);
if (esc) printf("%s", esc);
else printf("%c", c);
}
}
if (!raw)
printf("\"");
} else {
printf("[");
for (size_t i = 0;; i++) {
size_t ty_sz = type_size[v->Arr.type.kind];
Value ty_val = { .type = v->Arr.type };
memcpy(&ty_val.Void, (uint8_t*)v->Arr.vals + ty_sz * i, ty_sz);
print_value(&ty_val, false);
if (i == v->Arr.len-1) break;
printf(", ");
}
printf("]");
}
break;
default:
ASSERT_UNREACHED();
}
}
int8_t op_prec[OperatorEnumSize] = { int8_t op_prec[OperatorEnumSize] = {
[OpEOF] = PREC_DELIM, [OpEOF] = PREC_DELIM,
[OpNewLn] = PREC_DELIM, [OpNewLn] = PREC_DELIM,
@ -108,24 +177,9 @@ void print_toks(TokList *l) {
printf(": " C_ICYAN "%s" C_RESET, op_str[i->tok.Op]); printf(": " C_ICYAN "%s" C_RESET, op_str[i->tok.Op]);
break; break;
case TokVal: case TokVal:
printf(C_IYELLOW "Val" C_RESET); printf(C_IYELLOW "Val" C_RESET ": " C_ICYAN);
switch (i->tok.Val.type.kind) { print_value(&i->tok.Val, false);
case TypeFloat: printf(C_RESET);
printf(": " C_ICYAN "%f" C_RESET, i->tok.Val.Float);
break;
case TypeInt:
printf(": " C_ICYAN "%zd" C_RESET, i->tok.Val.Int);
break;
case TypeBool:
printf(": " C_ICYAN "%s" C_RESET, i->tok.Val.Bool ? "true" : "false");
break;
case TypeChar:
printf(": " C_ICYAN "'%c'" C_RESET, i->tok.Val.Char);
break;
default:
printf(" " C_ICYAN "(unknown type)" C_RESET);
break;
}
break; break;
case TokIdent: case TokIdent:
printf(C_IYELLOW "Ident" C_RESET); printf(C_IYELLOW "Ident" C_RESET);

13
tok.h
View File

@ -13,23 +13,36 @@ typedef struct Type {
TypeInt, TypeInt,
TypeBool, TypeBool,
TypeChar, TypeChar,
TypeArr,
TypeEnumSize,
} kind; } kind;
/*union { /*union {
};*/ };*/
} Type; } Type;
extern size_t type_size[TypeEnumSize];
typedef struct Value { typedef struct Value {
Type type; Type type;
union { union {
pseudo_void Void;
double Float; double Float;
ssize_t Int; ssize_t Int;
bool Bool; bool Bool;
char Char; char Char;
struct {
bool is_string : 1;
Type type;
void *vals;
size_t len, cap;
} Arr;
}; };
} Value; } Value;
void print_value(const Value *v, bool raw);
enum Operator { enum Operator {
OpLCurl = '{', OpLCurl = '{',
OpRCurl = '}', OpRCurl = '}',

17
util.c
View File

@ -168,6 +168,23 @@ double stod(const char *s, size_t n, ssize_t *endpos) {
return res; return res;
} }
const char *unescape_char(char c) {
switch (c) {
case '\a': return "\\a";
case '\b': return "\\b";
case '\033': return "\\e";
case '\f': return "\\f";
case '\n': return "\\n";
case '\r': return "\\r";
case '\t': return "\\t";
case '\v': return "\\v";
case '\\': return "\\\\";
case '\'': return "\\'";
case '"': return "\\\"";
default: return NULL;
}
}
char *mreadfile(FILE *fp) { char *mreadfile(FILE *fp) {
if (fseek(fp, 0l, SEEK_END) == -1) if (fseek(fp, 0l, SEEK_END) == -1)
return NULL; return NULL;

4
util.h
View File

@ -8,6 +8,8 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
typedef uint8_t pseudo_void;
/* some ANSI color codes */ /* some ANSI color codes */
#define C_RED "\x1b[31m" #define C_RED "\x1b[31m"
#define C_GREEN "\x1b[32m" #define C_GREEN "\x1b[32m"
@ -67,6 +69,8 @@ char *psndup(Pool *p, const char *s, size_t n);
intmax_t stoimax(const char *s, size_t n, size_t base, ssize_t *endpos /* -1 on success */); intmax_t stoimax(const char *s, size_t n, size_t base, ssize_t *endpos /* -1 on success */);
/* convert a non-null-terminated string to a double */ /* convert a non-null-terminated string to a double */
double stod(const char *s, size_t n, ssize_t *endpos /* -1 on success */); double stod(const char *s, size_t n, ssize_t *endpos /* -1 on success */);
/* return the escape sequence for a given character; return NULL if there is none */
const char *unescape_char(char c);
/* sets errno on failure */ /* sets errno on failure */
char *mreadfile(FILE *fp); char *mreadfile(FILE *fp);