refactory code

This commit is contained in:
方而静 2023-02-07 21:32:38 +08:00
parent 1d6c3ce4c0
commit 440bc22ac7
24 changed files with 231 additions and 211 deletions

3
.gitignore vendored
View File

@ -8,6 +8,9 @@
*.obj *.obj
*.elf *.elf
# Debugger
*.pdb
# Linker output # Linker output
*.ilk *.ilk
*.map *.map

View File

@ -1,8 +1,10 @@
#ifndef ACC_FATALS_H #ifndef ACC_FATALS_H
#define ACC_FATALS_H #define ACC_FATALS_H
#include "noreturn.h" #include <stddef.h>
#include <stdnoreturn.h>
void* malloc_or_fail(size_t s, const char *func_name);
noreturn void fail_malloc(const char *func_name); noreturn void fail_malloc(const char *func_name);
noreturn void fail_ast_op(int op, const char *func_name); noreturn void fail_ast_op(int op, const char *func_name);
noreturn void fail_ce_expect(const char *expected, const char *got); noreturn void fail_ce_expect(const char *expected, const char *got);

View File

@ -1,6 +0,0 @@
#ifndef ACC_NORETURN_H
#define ACC_NORETURN_H
#define noreturn _Noreturn
#endif

View File

@ -19,9 +19,9 @@ enum {
T_EQ, T_NE, T_LT, T_GT, T_LE, T_GE, T_EQ, T_NE, T_LT, T_GT, T_LE, T_GE,
T_INT, T_VOID, T_CHAR, T_LONG, T_INT, T_VOID, T_CHAR, T_LONG,
T_PRINT, T_IF, T_ELSE, T_WHILE, T_FOR, T_PRINT, T_IF, T_ELSE, T_WHILE, T_FOR,
T_INTLIT, T_LONGLIT, T_INDENT, T_I32_LIT, T_I64_LIT, T_INDENT,
}; };
extern const char *token_typename[29]; extern const char *token_typename[63];
void token_free(struct token *t); void token_free(struct token *t);
struct token token_make_eof(void); struct token token_make_eof(void);

View File

@ -13,13 +13,19 @@ struct linklist {
}; };
struct llist_node* llist_createnode(void *val); struct llist_node* llist_createnode(void *val);
void llist_pushback(struct linklist *l, void *val);
void llist_pushback_notnull(struct linklist *l, void *val);
void* llist_get(struct linklist *l, int x);
void llist_set(struct linklist *l, int x, void *val);
void llist_init(struct linklist *l); void llist_init(struct linklist *l);
void llist_free(struct linklist *l); void llist_free(struct linklist *l);
void llist_free_full(struct linklist *l);
void llist_pushback(struct linklist *l, void *val);
void llist_pushback_notnull(struct linklist *l, void *val);
void* llist_get(struct linklist *l, int x);
void llist_set(struct linklist *l, int x, void *val);
void llist_insert(struct linklist *l, int x, void *val); void llist_insert(struct linklist *l, int x, void *val);
void llist_popfront(struct linklist *l); void* llist_popfront(struct linklist *l);
void* llist_remove(struct linklist *l, int index);
#endif #endif

View File

@ -1,7 +1,9 @@
#ifndef ACC_UTIL_MISC_H #ifndef ACC_UTIL_MISC_H
#define ACC_UTIL_MISC_H #define ACC_UTIL_MISC_H
int strequal(const char *s1, const char *s2); #include <stdbool.h>
bool strequal(const char *s1, const char *s2);
char *strclone(const char *s); char *strclone(const char *s);
#endif #endif

View File

@ -6,10 +6,7 @@
// Build and return a binary AST node // Build and return a binary AST node
struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *right) { struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *right) {
struct ASTbinnode *x = malloc(sizeof(struct ASTbinnode)); struct ASTbinnode *x = malloc_or_fail(sizeof(struct ASTbinnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = op; x->op = op;
x->left = left; x->left = left;
@ -19,10 +16,7 @@ struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *ri
// Make an AST int literal node // Make an AST int literal node
struct ASTnode* ast_make_intlit(int val) { struct ASTnode* ast_make_intlit(int val) {
struct ASTintnode *x = malloc(sizeof(struct ASTintnode)); struct ASTintnode *x = malloc_or_fail(sizeof(struct ASTintnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = A_INTLIT; x->op = A_INTLIT;
x->val = val; x->val = val;
@ -31,10 +25,7 @@ struct ASTnode* ast_make_intlit(int val) {
// Make an AST variable value node // Make an AST variable value node
struct ASTnode* ast_make_var(int id) { struct ASTnode* ast_make_var(int id) {
struct ASTvarnode *x = malloc(sizeof(struct ASTvarnode)); struct ASTvarnode *x = malloc_or_fail(sizeof(struct ASTvarnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = A_VAR; x->op = A_VAR;
x->id = id; x->id = id;
@ -43,10 +34,7 @@ struct ASTnode* ast_make_var(int id) {
// Make a unary AST node: only one child // Make a unary AST node: only one child
struct ASTnode* ast_make_unary(int op, struct ASTnode *c) { struct ASTnode* ast_make_unary(int op, struct ASTnode *c) {
struct ASTunnode *x = malloc(sizeof(struct ASTunnode)); struct ASTunnode *x = malloc_or_fail(sizeof(struct ASTunnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = op; x->op = op;
x->c = c; x->c = c;
@ -55,10 +43,7 @@ struct ASTnode* ast_make_unary(int op, struct ASTnode *c) {
// Make a block ast node // Make a block ast node
struct ASTnode* ast_make_block() { struct ASTnode* ast_make_block() {
struct ASTblocknode *x = malloc(sizeof(struct ASTblocknode)); struct ASTblocknode *x = malloc_or_fail(sizeof(struct ASTblocknode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = A_BLOCK; x->op = A_BLOCK;
llist_init(&x->st); llist_init(&x->st);
@ -67,10 +52,7 @@ struct ASTnode* ast_make_block() {
// Make a assignment ast node // Make a assignment ast node
struct ASTnode* ast_make_assign(int op, int left, struct ASTnode *right) { struct ASTnode* ast_make_assign(int op, int left, struct ASTnode *right) {
struct ASTassignnode *x = malloc(sizeof(struct ASTassignnode)); struct ASTassignnode *x = malloc_or_fail(sizeof(struct ASTassignnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = op; x->op = op;
x->left = left; x->left = left;
@ -80,10 +62,7 @@ struct ASTnode* ast_make_assign(int op, int left, struct ASTnode *right) {
// Make a if statement ast node // Make a if statement ast node
struct ASTnode* ast_make_if(struct ASTnode *left, struct ASTnode *right, struct ASTnode *cond) { struct ASTnode* ast_make_if(struct ASTnode *left, struct ASTnode *right, struct ASTnode *cond) {
struct ASTifnode *x = malloc(sizeof(struct ASTifnode)); struct ASTifnode *x = malloc_or_fail(sizeof(struct ASTifnode), __FUNCTION__);
if (x == NULL) {
fail_malloc(__FUNCTION__);
}
x->op = A_IF; x->op = A_IF;
x->left = left; x->left = left;

View File

@ -53,7 +53,7 @@ static int cgcomp_i(int x, int y, char *op, char *ty) {
int r1 = alloc_tag(); int r1 = alloc_tag();
fprintf(Outfile, "\t%%%d = icmp %s %s %%%d, %%%d\n", r1, op, ty, x, y); fprintf(Outfile, "\t%%%d = icmp %s %s %%%d, %%%d\n", r1, op, ty, x, y);
int r2 = alloc_tag(); int r2 = alloc_tag();
if (ty[0] != 'i' || ty[1] != '1' || ty[2] != '\0') { if (strcmp(ty, "i1") != 0) { // special case for bool
fprintf(Outfile, "\t%%%d = zext i1 %%%d to %s\n", r2, r1, ty); fprintf(Outfile, "\t%%%d = zext i1 %%%d to %s\n", r2, r1, ty);
} }
return (r2); return (r2);

View File

@ -7,6 +7,14 @@ void fail_malloc(const char *func_name) {
exit(1); exit(1);
} }
void* malloc_or_fail(size_t s, const char *func_name) {
void *res = malloc(s);
if (res == NULL) {
fail_malloc(func_name);
}
return (res);
}
void fail_ast_op(int op, const char *func_name) { void fail_ast_op(int op, const char *func_name) {
fprintf(stderr, "%s: unknown ast operator %d.\n", func_name, op); fprintf(stderr, "%s: unknown ast operator %d.\n", func_name, op);
exit(1); exit(1);

View File

@ -1,5 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "scan.h" #include "scan.h"
#include "token.h" #include "token.h"
#include "ast.h" #include "ast.h"
@ -42,10 +44,10 @@ static int arithop(int t) {
{T_GT, A_GT}, {T_GT, A_GT},
{T_GE, A_GE}, {T_GE, A_GE},
{T_ASSIGN, A_ASSIGN}, {T_ASSIGN, A_ASSIGN},
{T_EOF} {-1}
}; };
for (int i = 0; map[i][0] != T_EOF; ++i) { for (int i = 0; map[i][0] != -1; ++i) {
if (t == map[i][0]) { if (t == map[i][0]) {
return map[i][1]; return map[i][1];
} }
@ -54,22 +56,21 @@ static int arithop(int t) {
} }
// operator ssociativity direction // operator ssociativity direction
// Return 0 if left to right, e.g. + // Returns false if left to right, e.g. +
// 1 if right to left, e.g. = // true if right to left, e.g. =
static int direction_rtl(int t) { static bool direction_rtl(int t) {
switch(t) { switch(t) {
case T_ASSIGN: case T_ASSIGN:
return (1); return (true);
default: default:
return (0); return (false);
} }
} }
// Next token // Next token
static void next(void) { static void next(void) {
if (Tokens.head) { if (Tokens.head) {
token_free(Tokens.head->val); token_free(llist_popfront(&Tokens));
llist_popfront(&Tokens);
} }
} }
@ -78,7 +79,8 @@ static struct token preview(int k) {
if (Tokens.length <= k) { if (Tokens.length <= k) {
return (token_make_eof()); return (token_make_eof());
} }
return (*((struct token*)llist_get(&Tokens, k))); struct token* res = llist_get(&Tokens, k);
return (*res);
} }
// return current token from input stream // return current token from input stream
@ -117,12 +119,12 @@ static struct ASTnode* primary(void) {
next(); next();
res = expression(); res = expression();
match(T_RP); match(T_RP);
} else if (current().type == T_INTLIT) { } else if (current().type == T_I32_LIT) {
res = ast_make_intlit(*((int*)current().val)); res = ast_make_intlit(*(int32_t*)current().val);
next(); next();
} else if (current().type == T_LONGLIT) { } else if (current().type == T_I64_LIT) {
// todo // todo
fprintf(stderr, "TOOD.\n"); fprintf(stderr, "TOOD: T_I64_LIT.\n");
exit(1); exit(1);
} else if (current().type == T_INDENT) { } else if (current().type == T_INDENT) {
int id = findglob((char*)current().val); int id = findglob((char*)current().val);
@ -296,29 +298,24 @@ static struct ASTnode* for_statement(void) {
// parse one statement // parse one statement
static struct ASTnode* statement(void) { static struct ASTnode* statement(void) {
if (current().type == T_SEMI) { switch (current().type) {
return (NULL); case T_SEMI:
} return (NULL);
else if (current().type == T_PRINT) { case T_PRINT:
return (print_statement()); return (print_statement());
} case T_INT:
else if (current().type == T_INT) { return (var_declaration());
return (var_declaration()); case T_IF:
} return (if_statement());
else if (current().type == T_IF) { case T_WHILE:
return (if_statement()); return (while_statement());
} case T_FOR:
else if (current().type == T_WHILE) { return (for_statement());
return (while_statement()); default:
} skip_semi = 0;
else if (current().type == T_FOR) { struct ASTnode* res = expression();
return (for_statement()); match(T_SEMI);
} return (res);
else {
skip_semi = 0;
struct ASTnode* res = expression();
match(T_SEMI);
return (res);
} }
} }

View File

@ -1,8 +1,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "token.h" #include "token.h"
#include "fatals.h" #include "fatals.h"
#include "util/misc.h" #include "util/misc.h"
@ -11,18 +12,6 @@ int Line = 1;
static int Preview; static int Preview;
static FILE *Infile; static FILE *Infile;
const char *token_typename[] = {
"EOF",
";",
"{", "}", "(", ")",
"=",
"+", "-", "*", "/",
"==", "!=", "<", ">", "<=", ">=",
"int", "void", "char", "long",
"print", "if", "else", "while", "for",
"an integer literal (type int)", "an integer literal (type long)", "an indentifier"
};
// preview one char, not getting it out from the stream // preview one char, not getting it out from the stream
static int preview(void) { static int preview(void) {
if (!Preview) { if (!Preview) {
@ -43,9 +32,7 @@ static void next(void) {
// Skip past input that we don't need to deal with, // Skip past input that we don't need to deal with,
// i.e. whitespace, newlines. // i.e. whitespace, newlines.
static void skip_whitespaces(void) { static void skip_whitespaces(void) {
int c; int c = preview();
c = preview();
while (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') { while (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') {
next(); next();
c = preview(); c = preview();
@ -53,7 +40,7 @@ static void skip_whitespaces(void) {
} }
// Scan and return an integer literal value from the input file. // Scan and return an integer literal value from the input file.
static void scanint(struct token *t) { static void scan_int(struct token *t) {
long long res = 0; long long res = 0;
int c = preview(); int c = preview();
while ('0' <= c && c <= '9') { while ('0' <= c && c <= '9') {
@ -62,40 +49,35 @@ static void scanint(struct token *t) {
c = preview(); c = preview();
} }
if (INT_MIN <= res && res <= INT_MAX) { if (INT32_MIN <= res && res <= INT32_MAX) {
t->type = T_INTLIT; t->type = T_I32_LIT;
t->val = malloc(sizeof(int)); t->val = malloc_or_fail(sizeof(int32_t), __FUNCTION__);
if (t->val == NULL) { *((int32_t *)t->val) = (int)res;
fail_malloc(__FUNCTION__);
}
*((int *)t->val) = (int)res;
} else { } else {
t->type = T_LONGLIT; t->type = T_I64_LIT;
t->val = malloc(sizeof(long long)); t->val = malloc_or_fail(sizeof(int64_t), __FUNCTION__);
if (t->val == NULL) { *((int64_t *)t->val) = res;
fail_malloc(__FUNCTION__);
}
*((long long *)t->val) = res;
} }
} }
// Scan an identifier from the input file and // Scan an identifier from the input file and
// Return the identifier (char*) // Return the identifier string (char*)
// Writes the length into _n_ or NULL
static char* scan_indentifier(int *n) { static char* scan_indentifier(int *n) {
int sz = 128, len = 0; int sz = 128, len = 0;
char *res = malloc(sz * sizeof(char)); char *res = malloc_or_fail(sz * sizeof(char), __FUNCTION__);
memset(res, 0, sz * sizeof(char)); memset(res, 0, sz * sizeof(char));
int c = preview(); int c = preview();
while (isdigit(c) || isalpha(c) || c == '_') { while (isdigit(c) || isalpha(c) || c == '_') {
if (len >= sz - 1) { if (len >= sz - 1) {
sz *= 2; sz *= 2;
char *old = res; char *res = realloc(res, sz * sizeof(char));
res = malloc(sz * sizeof(char)); if (res == NULL) {
memcpy(res, old, len * sizeof(char)); fail_malloc(__FUNCTION__);
}
memset(res + len * sizeof(char), 0, (sz - len) * sizeof(char)); memset(res + len * sizeof(char), 0, (sz - len) * sizeof(char));
free(old);
} }
res[len++] = c; res[len++] = c;
next(); next();
@ -108,8 +90,9 @@ static char* scan_indentifier(int *n) {
return (res); return (res);
} }
// Given a word from the input, scan if it is a keyword // Given a word from the input, scan if it is a keyword.
static int scan_keyword(struct token *t, char *s) { // Returns true if found keyword.
static bool scan_keyword(struct token *t, char *s) {
static const char *map_s[] = { static const char *map_s[] = {
"print", "print",
"int", "int",
@ -137,15 +120,15 @@ static int scan_keyword(struct token *t, char *s) {
for (int i = 0; map_s[i] != NULL; ++i) { for (int i = 0; map_s[i] != NULL; ++i) {
if (strequal(map_s[i], s)) { if (strequal(map_s[i], s)) {
t->type = map_t[i]; t->type = map_t[i];
return (1); return (true);
} }
} }
return (0); return (false);
} }
// Scan one char token // Scan one char token
// Return 1 if found // Return 1 if found
static int scan_1c(struct token *t) { static bool scan_1c(struct token *t) {
static const int map[][2] = { static const int map[][2] = {
{'+', T_PLUS}, {'+', T_PLUS},
{'-', T_MINUS}, {'-', T_MINUS},
@ -164,18 +147,15 @@ static int scan_1c(struct token *t) {
if (map[i][0] == c) { if (map[i][0] == c) {
t->type = map[i][1]; t->type = map[i][1];
next(); next();
return (1); return (true);
} }
} }
return (0); return (false);
} }
// Scan and return the next token found in the input. // Scan and return the next token found in the input.
static struct token* scan(void) { static struct token* scan(void) {
struct token *t = malloc(sizeof(struct token)); struct token *t = malloc_or_fail(sizeof(struct token), __FUNCTION__);
if (t == NULL) {
fail_malloc(__FUNCTION__);
}
t->val = NULL; t->val = NULL;
skip_whitespaces(); skip_whitespaces();
@ -204,8 +184,7 @@ static struct token* scan(void) {
t->type = T_NE; t->type = T_NE;
next(); next();
} else { } else {
fprintf(stderr, "Unrecognised character %c on line %d.\n", c, Line); fail_char(c);
exit(1);
} }
} else if (c == '<') { } else if (c == '<') {
t->type = T_LT; t->type = T_LT;
@ -226,7 +205,7 @@ static struct token* scan(void) {
} else { } else {
// If it's a digit, scan the integer literal value in // If it's a digit, scan the integer literal value in
if (isdigit(c)) { if (isdigit(c)) {
scanint(t); scan_int(t);
} else if (isalpha(c) || c == '_') { } else if (isalpha(c) || c == '_') {
t->val = scan_indentifier(NULL); t->val = scan_indentifier(NULL);
if (scan_keyword(t, t->val)) { if (scan_keyword(t, t->val)) {

View File

@ -2,6 +2,18 @@
#include <stdio.h> #include <stdio.h>
#include "token.h" #include "token.h"
const char *token_typename[63] = {
"EOF",
";",
"{", "}", "(", ")",
"=",
"+", "-", "*", "/",
"==", "!=", "<", ">", "<=", ">=",
"int", "void", "char", "long",
"print", "if", "else", "while", "for",
"a signed integer literal (size 32)", "a signed integer literal (size 64)", "an indentifier"
};
void token_free(struct token *t) { void token_free(struct token *t) {
if (t->val) { if (t->val) {
free(t->val); free(t->val);

View File

@ -3,6 +3,7 @@
#include "fatals.h" #include "fatals.h"
#include "util/linklist.h" #include "util/linklist.h"
// Create a linklist node using given value.
struct llist_node* llist_createnode(void *val) { struct llist_node* llist_createnode(void *val) {
struct llist_node *res = malloc(sizeof(struct llist_node)); struct llist_node *res = malloc(sizeof(struct llist_node));
if (res == NULL) { if (res == NULL) {
@ -13,6 +14,7 @@ struct llist_node* llist_createnode(void *val) {
return (res); return (res);
} }
// Appends an element in the linklist.
void llist_pushback(struct linklist *l, void *val) { void llist_pushback(struct linklist *l, void *val) {
l->length += 1; l->length += 1;
if (!l->tail) { if (!l->tail) {
@ -23,44 +25,51 @@ void llist_pushback(struct linklist *l, void *val) {
l->tail = l->tail->nxt; l->tail = l->tail->nxt;
} }
// A variant of pushback
// Only does pushback if _val_ is not null.
void llist_pushback_notnull(struct linklist *l, void *val) { void llist_pushback_notnull(struct linklist *l, void *val) {
if (val) { if (val) {
llist_pushback(l, val); llist_pushback(l, val);
} }
} }
void* llist_get(struct linklist *l, int x) { // Returns the _index_ thh element.
if (x >= l->length) { void* llist_get(struct linklist *l, int index) {
if (index >= l->length) {
fprintf(stderr, "linklist out of range.\n"); fprintf(stderr, "linklist out of range.\n");
abort(); abort();
} }
struct llist_node *p = l->head; struct llist_node *p = l->head;
for (int i = 0; i < x; ++i) { for (int i = 0; i < index; ++i) {
p = p->nxt; p = p->nxt;
} }
return (p->val); return (p->val);
} }
void llist_set(struct linklist *l, int x, void *val) { // Modify the _index_ thh element.
if (x >= l->length) { void llist_set(struct linklist *l, int index, void *val) {
if (index >= l->length) {
fprintf(stderr, "linklist out of range.\n"); fprintf(stderr, "linklist out of range.\n");
abort(); abort();
} }
struct llist_node *p = l->head; struct llist_node *p = l->head;
for (int i = 0; i < x; ++i) { for (int i = 0; i < index; ++i) {
p = p->nxt; p = p->nxt;
} }
p->val = val; p->val = val;
} }
// Init a empty linklist.
void llist_init(struct linklist *l) { void llist_init(struct linklist *l) {
l->length = 0; l->length = 0;
l->head = NULL; l->head = NULL;
l->tail = NULL; l->tail = NULL;
} }
// Frees the linklist.
// Caller must make sure all elements in the linklist has already been freed.
void llist_free(struct linklist *l) { void llist_free(struct linklist *l) {
struct llist_node *p = l->head; struct llist_node *p = l->head;
struct llist_node *nxt; struct llist_node *nxt;
@ -72,6 +81,24 @@ void llist_free(struct linklist *l) {
llist_init(l); llist_init(l);
} }
// Frees the linklist.
// Callee will free all elements in the link list.
void llist_free_full(struct linklist *l) {
struct llist_node *p = l->head;
struct llist_node *nxt;
while (p) {
nxt = p->nxt;
if (p->val) {
free(p->val);
}
free(p);
p = nxt;
}
llist_init(l);
}
// Insert _val_ into the linklist as the _index_ th element.
// If _index_ is too large, pushback only!
void llist_insert(struct linklist *l, int index, void *val) { void llist_insert(struct linklist *l, int index, void *val) {
if (index >= l->length) { if (index >= l->length) {
llist_pushback(l, val); llist_pushback(l, val);
@ -94,18 +121,46 @@ void llist_insert(struct linklist *l, int index, void *val) {
p->nxt = x; p->nxt = x;
} }
void llist_popfront(struct linklist *l) { // Pop the first element of the link list
// Return the first element.
void* llist_popfront(struct linklist *l) {
if (l->head == NULL) { if (l->head == NULL) {
return; return (NULL);
} }
l->length -= 1; l->length -= 1;
void *res = l->head->val;
if (l->length == 0) { if (l->length == 0) {
free(l->head); free(l->head);
l->head = l->tail = NULL; l->head = l->tail = NULL;
return (res);
} }
struct llist_node *p = l->head; struct llist_node *p = l->head;
l->head = p->nxt; l->head = p->nxt;
free(p); free(p);
return (res);
}
// Removes the _index_ th element from the linklist.
// Returns the removed value.
void* llist_remove(struct linklist *l, int index) {
if (index >= l->length) {
return (NULL);
}
if (index == 0) {
return (llist_popfront(l));
}
l->length -= 1;
struct llist_node *p = l->head;
for (int i = 0; i < index - 2; ++i) {
p = p->nxt;
}
struct llist_node *q = p->nxt;
p->nxt = q->nxt;
void *res = q->val;
free(q);
return res;
} }

View File

@ -1,22 +1,15 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "util/misc.h"
// check if two string are the same // check if two string are the same
int strequal(const char *s1, const char *s2) { bool strequal(const char *s1, const char *s2) {
for (int i = 1; ; ++i) { return (strcmp(s1, s2) == 0);
if (s1[i] != s2[i]) {
return (0);
}
if (s1[i] == '\0') {
break;
}
}
return (1);
} }
// A impl of C23 strdup() // A impl of C23 strdup()
char* strclone(char *s) { // Clones the given string
char* strclone(const char *s) {
int n = strlen(s); int n = strlen(s);
char *res = malloc(n + 1); char *res = malloc(n + 1);
memcpy(res, s, n * sizeof(char)); memcpy(res, s, n * sizeof(char));

50
tests/test_llvm.lua Normal file
View File

@ -0,0 +1,50 @@
local acc_path = nil
for _, path in ipairs({ "../acc", "../acc.exe", "../acc.out" }) do
if os.exists(path) then
acc_path = path
end
end
if acc_path == nil then
error("acc executable not found.")
end
local function compare_file(p1, p2)
local f1 = io.open(p1, "r");
local f2 = io.open(p2, "r");
repeat
local l1 = f1:read()
local l2 = f2:read()
if l1 ~= l2 then
f1:close()
f2:close()
return false
end
until l1 == nil
f1:close()
f2:close()
return true
end
for _, input in ipairs(os.files("tests/input*")) do
if input:endswith(".ans") then
goto continue
end
local ans = input .. ".ans"
if not os.exists(ans) then
cprint("${orange} [WARN] not found answer for case %s.", input)
goto continue
end
os.run("acc llvm %s out.ll", input)
os.run("clang out.ll -o test.exe")
local output = os.iorun("test.exe")
local output_path = os.tmpfile()
io.writefile(output_path, output)
if compare_file(output_path, ans) then
cprint("${green} [INFO] case %s: OK.", input)
else
cprint("${red} [INFO] case %s: FAILED.", input)
end
::continue::
end

View File

@ -1,30 +0,0 @@
#!/bin/sh
# Run each test and compare
# against known good output
set -e
echo "Testing for target llvm..."
if [ ! -f ../acc ]
then echo "Need to build ../acc first!"; exit 1
fi
for i in input*
do if [ ! -f "out.$i" ]
then echo "Can't run test on $i, no answer file!"
else
echo -n $i
../acc llvm $i
clang -o out out.ll -w
./out > trial.$i
cmp -s "out.$i" "trial.$i"
if [ "$?" -eq "1" ]
then echo ": failed"
diff -c "out.$i" "trial.$i"
echo
else echo ": OK"
fi
rm -f out out.ll "trial.$i"
fi
done

View File

@ -1,30 +0,0 @@
#!/bin/sh
# Run each test and compare
# against known good output
set -e
echo "Testing for target x86_64..."
if [ ! -f ../acc ]
then echo "Need to build ../acc first!"; exit 1
fi
for i in input*
do if [ ! -f "out.$i" ]
then echo "Can't run test on $i, no answer file!"
else
echo -n $i
../acc x86_64 $i
gcc -o out out.s
./out > trial.$i
cmp -s "out.$i" "trial.$i"
if [ "$?" -eq "1" ]
then echo ": failed"
diff -c "out.$i" "trial.$i"
echo
else echo ": OK"
fi
rm -f out out.s "trial.$i"
fi
done