From 69508071612c30b8d2d9f836616b10e78f260913 Mon Sep 17 00:00:00 2001 From: szdytom Date: Sun, 11 Jun 2023 20:50:44 +0800 Subject: [PATCH] leg Signed-off-by: szdytom --- .gitignore | 1 + include/ast.h | 22 ++- include/cg.h | 4 +- include/ir.h | 21 +++ include/util/array.h | 1 + include/util/hashmap.h | 12 ++ src/ast.c | 76 ++++++---- src/cg.c | 4 +- src/cg_ast.c | 16 ++- src/cg_x64.c | 308 ----------------------------------------- src/parse.c | 62 ++++----- src/util/array.c | 23 ++- tests/input08 | 6 + tests/input08.ans | 1 + 14 files changed, 174 insertions(+), 383 deletions(-) create mode 100644 include/ir.h create mode 100644 include/util/hashmap.h delete mode 100644 src/cg_x64.c create mode 100644 tests/input08 create mode 100644 tests/input08.ans diff --git a/.gitignore b/.gitignore index d14260a..416f3c6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # Debugger *.pdb +out.txt # Linker output *.ilk diff --git a/include/ast.h b/include/ast.h index 89c26f1..5a0595d 100644 --- a/include/ast.h +++ b/include/ast.h @@ -1,6 +1,7 @@ #ifndef ACC_AST_H #define ACC_AST_H +#include #include "util/linklist.h" // AST operation types @@ -8,12 +9,21 @@ enum { A_ASSIGN, A_ADD, A_SUB, A_MUL, A_DIV, A_EQ, A_NE, A_LT, A_GT, A_LE, A_GE, - A_INTLIT, A_VAR, + A_LIT, A_VAR, A_BLOCK, A_PRINT, A_IF, A_WHILE, A_SOUL // what? }; +// value type +enum { + V_I32, V_I64, V_BOOL +}; + +struct value_type { + int vt; // base value type +}; + // AST nodde types enum { N_BIN, N_UN, N_MULTI, N_LEAF, N_ASSIGN @@ -51,10 +61,11 @@ struct ASTblocknode { struct linklist st; // statements linklist }; -// AST int literal node -struct ASTintnode { +// AST literal node +struct ASTlitnode { int op; - int val; + struct value_type type; + void *val; }; // AST assign literal node @@ -71,7 +82,8 @@ struct ASTvarnode { }; struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *right); -struct ASTnode* ast_make_intlit(int val); +struct ASTnode* ast_make_lit_i32(int32_t x); +struct ASTnode* ast_make_lit_i64(int64_t x); struct ASTnode* ast_make_unary(int op, struct ASTnode *c); struct ASTnode* ast_make_block(); struct ASTnode* ast_make_var(int id); diff --git a/include/cg.h b/include/cg.h index bcce7ee..bf6bd64 100644 --- a/include/cg.h +++ b/include/cg.h @@ -11,10 +11,10 @@ void open_outputfile(char *filename); void cg_unload(void); // cg_x64.c -void cgx64_generate(struct ASTnode *rt); +//void cgx64_generate(struct ASTnode *rt); // cg_llvm.c -void cgllvm_generate(struct ASTnode *rt); +//void cgllvm_generate(struct ASTnode *rt); // cg_ast.c void cgast_generate(struct ASTnode *rt); diff --git a/include/ir.h b/include/ir.h new file mode 100644 index 0000000..a0a3b28 --- /dev/null +++ b/include/ir.h @@ -0,0 +1,21 @@ +#ifndef ACC_ACIR_H +#define ACC_ACIR_H + +// operations in the ACC IR(ACIR) +enum { + IR_ADD, IR_SUB, IR_MUL, IR_DIV, + IR_EQ, IR_NE, IR_LT, IR_GT, IR_LE, IR_GE, + IR_NEG, + IR_LIT, +}; + +struct IRinstruction { + int op; + union { + struct { IRinstruction *left, *right; }; + int val; + }; +}; + + +#endif \ No newline at end of file diff --git a/include/util/array.h b/include/util/array.h index 5369e40..3445168 100644 --- a/include/util/array.h +++ b/include/util/array.h @@ -12,5 +12,6 @@ void array_pushback(struct array *a, void *val); void array_free(struct array *a); void* array_get(struct array *a, int index); void array_set(struct array *a, int index, void *val); +void* array_popback(struct array *a); #endif diff --git a/include/util/hashmap.h b/include/util/hashmap.h new file mode 100644 index 0000000..57045c1 --- /dev/null +++ b/include/util/hashmap.h @@ -0,0 +1,12 @@ +#ifndef ACC_UTIL_HASHMAP +#define ACC_UTIL_HASHMAP + +struct hashmap { + int size; + int cap; + linklist *data; +}; + +void hashmap_init(); + +#endif \ No newline at end of file diff --git a/src/ast.c b/src/ast.c index 436aa8f..8ad5b2c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1,5 +1,5 @@ -#include #include +#include #include "ast.h" #include "fatals.h" #include "util/linklist.h" @@ -14,12 +14,25 @@ struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *ri return ((struct ASTnode*)x); } -// Make an AST int literal node -struct ASTnode* ast_make_intlit(int val) { - struct ASTintnode *x = malloc_or_fail(sizeof(struct ASTintnode), __FUNCTION__); +// Make an AST int32 literal node +struct ASTnode* ast_make_lit_i32(int32_t v) { + struct ASTlitnode *x = malloc_or_fail(sizeof(struct ASTlitnode), __FUNCTION__); - x->op = A_INTLIT; - x->val = val; + x->op = A_LIT; + x->type.vt = V_I32; + x->val = malloc_or_fail(sizeof(int32_t), __FUNCTION__); + *(int64_t*)x->val = v; + return ((struct ASTnode*)x); +} + +// Make an AST int32 literal node +struct ASTnode* ast_make_lit_i64(int64_t v) { + struct ASTlitnode *x = malloc_or_fail(sizeof(struct ASTlitnode), __FUNCTION__); + + x->op = A_LIT; + x->type.vt = V_I64; + x->val = malloc_or_fail(sizeof(int64_t), __FUNCTION__); + *(int64_t*)x->val = v; return ((struct ASTnode*)x); } @@ -74,21 +87,20 @@ struct ASTnode* ast_make_if(struct ASTnode *left, struct ASTnode *right, struct // Translate ast operation type to ast node type int ast_type(int t) { switch (t) { - case A_ADD: case A_SUB: case A_MUL: case A_DIV: - case A_EQ: case A_NE: case A_GT: case A_LT: case A_GE: case A_LE: - case A_IF: case A_WHILE: - return (N_BIN); - case A_ASSIGN: - return (N_ASSIGN); - case A_INTLIT: case A_VAR: - return (N_LEAF); - case A_BLOCK: - return (N_MULTI); - case A_PRINT: - return (N_UN); - default: - fprintf(stderr, "%s: unknown operation type %d.\n", __FUNCTION__, t); - exit(1); + case A_ADD: case A_SUB: case A_MUL: case A_DIV: + case A_EQ: case A_NE: case A_GT: case A_LT: case A_GE: case A_LE: + case A_IF: case A_WHILE: + return (N_BIN); + case A_ASSIGN: + return (N_ASSIGN); + case A_LIT: case A_VAR: + return (N_LEAF); + case A_BLOCK: + return (N_MULTI); + case A_PRINT: + return (N_UN); + default: + fail_ast_op(t, __FUNCTION__); } } @@ -98,21 +110,24 @@ void ast_free(struct ASTnode *x) { return; } - int nt = ast_type(x->op); - if (nt == N_ASSIGN) { + switch (ast_type(x->op)) { + case N_ASSIGN: { struct ASTassignnode *t = (struct ASTassignnode*)x; ast_free(t->right); - } else if (nt == N_BIN) { + } break; + case N_BIN: { struct ASTbinnode *t = (struct ASTbinnode*)x; ast_free(t->left); ast_free(t->right); if (x->op == A_IF) { ast_free(((struct ASTifnode*)x)->cond); } - } else if (nt == N_UN) { + } break; + case N_UN: { struct ASTunnode *t = (struct ASTunnode*)x; ast_free(t->c); - } else if (nt == N_MULTI) { + } break; + case N_MULTI: { struct ASTblocknode *t = (struct ASTblocknode*)x; struct llist_node *p = t->st.head; while (p) { @@ -120,6 +135,15 @@ void ast_free(struct ASTnode *x) { p = p->nxt; } llist_free(&t->st); + } break; + case N_LEAF: { + struct ASTlitnode *t = (struct ASTlitnode*)x; + if (t->op == A_LIT) { + if (t->val) { + free(t->val); + } + } + } break; } free(x); } diff --git a/src/cg.c b/src/cg.c index edf15e4..d82cadc 100644 --- a/src/cg.c +++ b/src/cg.c @@ -25,9 +25,9 @@ void cg_unload(void) { // generates code void cg_main(int target, struct ASTnode *rt) { if (target == CG_X64) { - cgx64_generate(rt); + //cgx64_generate(rt); } else if (target == CG_LLVM) { - cgllvm_generate(rt); + //cgllvm_generate(rt); } else if (target == CG_AST) { cgast_generate(rt); } else { diff --git a/src/cg_ast.c b/src/cg_ast.c index 8e2d468..6f7ed16 100644 --- a/src/cg_ast.c +++ b/src/cg_ast.c @@ -32,10 +32,20 @@ static void cgenerate_dfs(struct ASTnode *x) { int nt = ast_type(x->op); if (nt == N_LEAF) { - if (x->op == A_INTLIT) { - struct ASTintnode *t = (struct ASTintnode*)x; + if (x->op == A_LIT) { + struct ASTlitnode *t = (struct ASTlitnode*)x; cgprint_tabs(); - fprintf(Outfile, "--->INT %d.\n", t->val); + switch (t->type.vt) { + case V_I32: + fprintf(Outfile, "--->INT %d.\n", *(int32_t*)t->val); + break; + case V_I64: + fprintf(Outfile, "--->INT64 %lld.\n", *(int64_t*)t->val); + break; + default: + fprintf(stderr, "%s: Unknow literal type %d.\n", __FUNCTION__, t->type.vt); + exit(1); + } } else if (x->op == A_VAR) { struct ASTvarnode *t = (struct ASTvarnode*)x; cgprint_tabs(); diff --git a/src/cg_x64.c b/src/cg_x64.c deleted file mode 100644 index e2f0452..0000000 --- a/src/cg_x64.c +++ /dev/null @@ -1,308 +0,0 @@ -#include -#include -#include -#include "cg.h" -#include "ast.h" -#include "symbol.h" -#include "fatals.h" -#include "util/array.h" -#include "util/linklist.h" - -// List of available registers -// and their names -static const int reg_count = 4; -static char *reglist[4] = { "%r8", "%r9", "%r10", "%r11" }; -static int usedreg[4]; - -// Get a label number for jump -static int alloc_label(void) { - static int id = 0; - return (id++); -} - -// Set all registers free -static void free_all_reg(void) { - for (int i = 0; i < reg_count; ++i) { - usedreg[i] = 0; - } -} - -// Allocate a new register to use or report "Out of registers" -static int alloc_reg(void) { - for (int i = 0; i < reg_count; ++i) { - if (!usedreg[i]) { - usedreg[i] = 1; - return (i); - } - } - fprintf(stderr, "Out of registers.\n"); - exit(0); -} - -// Return a register to the list of available registers. -// Check to see if it's not already there. -static void free_reg(int r) { - if (r == -1) { - return; - } - - if (!usedreg[r]) { - fprintf(stderr, "Error trying to free register %d: not allocated.\n", r); - exit(1); - } - usedreg[r] = 0; -} - -// Print out the assembly preamble -static void cgpreamble(void) { - free_all_reg(); - fputs( "\t.text\n" - ".LC0:\n" - "\t.string\t\"%d\\n\"\n" - "printint:\n" - "\tpushq\t%rbp\n" - "\tmovq\t%rsp, %rbp\n" - "\tsubq\t$16, %rsp\n" - "\tmovl\t%edi, -4(%rbp)\n" - "\tmovl\t-4(%rbp), %eax\n" - "\tmovl\t%eax, %esi\n" - "\tleaq .LC0(%rip), %rdi\n" - "\tmovl $0, %eax\n" - "\tcall printf@PLT\n" - "\tnop\n" - "\tleave\n" - "\tret\n" - "\n" - "\t.globl\tmain\n" - "main:\n" - "\tpushq\t%rbp\n" - "\tmovq %rsp, %rbp\n", Outfile); -} - -// Print out the assembly postamble -static void cgpostamble(void) { - fputs( "\tmovl $0, %eax\n" - "\tpopq %rbp\n" - "\tret\n", Outfile); -} - -// Load an integer literal to a register. -// Return the id of the register -static int cgload_int(int val) { - int r = alloc_reg(); - fprintf(Outfile, "\tmovl\t$%d, %sd\n", val, reglist[r]); - return (r); -} - -// Add two registers together and return -// the number of the register with the result -static int cgadd(int r1, int r2) { - fprintf(Outfile, "\taddq\t%s, %s\n", reglist[r1], reglist[r2]); - free_reg(r1); - return (r2); -} - -// Subtract the second register from the first and -// return the number of the register with the result -static int cgsub(int r1, int r2) { - fprintf(Outfile, "\tsubq\t%s, %s\n", reglist[r2], reglist[r1]); - free_reg(r2); - return (r1); -} - -// Multiply two registers together and return -// the number of the register with the result -static int cgmul(int r1, int r2) { - fprintf(Outfile, "\timulq\t%s, %s\n", reglist[r1], reglist[r2]); - free_reg(r1); - return (r2); -} - -// Divide the first register by the second and -// return the number of the register with the result -static int cgdiv(int r1, int r2) { - fprintf(Outfile, "\tmovq\t%s,%%rax\n", reglist[r1]); - fprintf(Outfile, "\tcqo\n"); - fprintf(Outfile, "\tidivq\t%s\n", reglist[r2]); - fprintf(Outfile, "\tmovq\t%%rax,%s\n", reglist[r1]); - free_reg(r2); - return (r1); -} - -// Call printint() with the given register -static void cgprint(int r) { - fprintf(Outfile, "\tmovq\t%s, %%rdi\n", reglist[r]); - fprintf(Outfile, "\tcall\tprintint\n"); - free_reg(r); -} - -// Load a global variable into a register -static int cgload_glob(char *name) { - int r = alloc_reg(); - fprintf(Outfile, "\tmovq\t%s(%%rip), %s\n", name, reglist[r]); - return (r); -} - -// Store a register's value into a variable -static int cgstore_glob(int r, char *name) { - fprintf(Outfile, "\tmovq\t%s, %s(%%rip)\n", reglist[r], name); - return (r); -} - -// Compare two registers. -static int cgcompare(int r1, int r2, int op) { - static const int map_s[] = { A_EQ, A_NE, A_LT, A_LE, A_GT, A_GE, 0}; - static const char *map_t[] = { "sete", "setne","setl", "setle","setg", "setge",NULL}; - int how = -1; - for (int i = 0; map_t[i] != NULL; ++i) { - if (map_s[i] == op) { - how = i; - break; - } - } - - if (how == -1) { - fprintf(stderr, "%s: unknown compare operator %d.\n", __FUNCTION__, op); - exit(1); - } - - fprintf(Outfile, "\tcmpq\t%s, %s\n", reglist[r2], reglist[r1]); - fprintf(Outfile, "\t%s\t%sb\n", map_t[how], reglist[r2]); - fprintf(Outfile, "\tandq\t$255,%s\n", reglist[r2]); - free_reg(r1); - return (r2); -} - -// Jump to label when condition register is false(0). -static void cgjmp_condfalse(int Lt, int x) { - fprintf(Outfile, "\tcmpq\t$0, %s\n", reglist[x]); - fprintf(Outfile, "\tje\t.L%d\n", Lt); - free_reg(x); -} - -// Jump to label no matter what. -static void cgjmp_always(int Lt) { - fprintf(Outfile, "\tjmp\t.L%d\n", Lt); -} - -// Print label to Outfile -static void cgprint_label(int Lt) { - fprintf(Outfile, ".L%d:\n", Lt); -} - -// init a global variable -static void cginit_glob(char *name) { - fprintf(Outfile, "\t.comm\t%s,8,8\n", name); -} - -// Given a AST('s root) -// Generate ASM code. -// Return value register id. -static int cgenerate_ast(struct ASTnode *rt) { - int nt = ast_type(rt->op); - - if (nt == N_LEAF) { - if (rt->op == A_INTLIT) { - struct ASTintnode *x = (struct ASTintnode*)rt; - return (cgload_int(x->val)); - } else if (rt->op == A_VAR) { - struct ASTvarnode *x = (struct ASTvarnode*)rt; - return (cgload_glob(array_get(&Gsym, x->id))); - } else { - fail_ast_op(rt->op, __FUNCTION__); - } - } else if (nt == N_BIN) { - if (rt->op == A_IF) { - struct ASTifnode *x = (struct ASTifnode*)rt; - int Lelse = alloc_label(); - int Lend = alloc_label(); - int condv = cgenerate_ast(x->cond); - - cgjmp_condfalse(Lelse, condv); - free_reg(cgenerate_ast(x->left)); - cgjmp_always(Lend); - - cgprint_label(Lelse); - free_reg(cgenerate_ast(x->right)); - - cgprint_label(Lend); - return (-1); - } else if (rt->op == A_WHILE) { - struct ASTbinnode *x = (struct ASTbinnode*)rt; - int Lstart = alloc_label(); - int Lend = alloc_label(); - - cgprint_label(Lstart); - int condv = cgenerate_ast(x->left); - cgjmp_condfalse(Lend, condv); - free_reg(cgenerate_ast(x->right)); - cgjmp_always(Lstart); - - cgprint_label(Lend); - return (-1); - } - - struct ASTbinnode *x = (struct ASTbinnode*)rt; - int lv = cgenerate_ast(x->left); - int rv = cgenerate_ast(x->right); - - if (rt->op == A_ADD) { - return (cgadd(lv, rv)); - } else if (rt->op == A_SUB) { - return (cgsub(lv, rv)); - } else if (rt->op == A_MUL) { - return (cgmul(lv, rv)); - } else if (rt->op == A_DIV) { - return (cgdiv(lv, rv)); - } else if (A_EQ <= rt->op && rt->op <= A_GE) { - // a compare operator - return (cgcompare(lv, rv, rt->op)); - } else { - fail_ast_op(rt->op, __FUNCTION__); - } - } else if (nt == N_UN) { - struct ASTunnode *x = (struct ASTunnode*)rt; - int cv = cgenerate_ast(x->c); - - if (rt->op == A_PRINT) { - cgprint(cv); - return (-1); - } else { - fail_ast_op(rt->op, __FUNCTION__); - } - } else if (nt == N_ASSIGN) { - struct ASTassignnode *x = (struct ASTassignnode*)rt; - int cv = cgenerate_ast(x->right); - - if (rt->op == A_ASSIGN) { - return (cgstore_glob(cv, array_get(&Gsym, x->left))); - } else { - fail_ast_op(rt->op, __FUNCTION__); - } - } else if (nt == N_MULTI) { - struct ASTblocknode *x = (struct ASTblocknode*)rt; - int val = -1; - struct llist_node *p = x->st.head; - while (p) { - val = cgenerate_ast(p->val); - if (p->nxt) { - free_reg(val); - } - p = p->nxt; - } - return val; - } else { - fail_ast_op(rt->op, __FUNCTION__); - } -} - -// generates code -void cgx64_generate(struct ASTnode *rt) { - for (int i = 0; i < Gsym.length; ++i) { - cginit_glob(array_get(&Gsym, i)); - } - - cgpreamble(); - free_reg(cgenerate_ast(rt)); - cgpostamble(); -} diff --git a/src/parse.c b/src/parse.c index 3486517..efd27cf 100644 --- a/src/parse.c +++ b/src/parse.c @@ -75,16 +75,18 @@ static void next(void) { } // preview next kth token from input stream -static struct token preview(int k) { +static struct token* preview(int k) { if (Tokens.length <= k) { - return (token_make_eof()); + static struct token token_eof; + token_eof = token_make_eof(); + return (&token_eof); } struct token* res = llist_get(&Tokens, k); - return (*res); + return (res); } // return current token from input stream -static struct token current(void) { +static struct token* current(void) { return (preview(0)); } @@ -92,17 +94,17 @@ static struct token current(void) { static void match(int t) { if (t == T_SEMI && skip_semi) { skip_semi = 0; - } else if (current().type == t) { + } else if (current()->type == t) { next(); } else { - fail_ce_expect(token_typename[current().type], token_typename[t]); + fail_ce_expect(token_typename[current()->type], token_typename[t]); } } // check current token's type or report syntax error. static void check(int t) { - if (current().type != t) { - fail_ce_expect(token_typename[current().type], token_typename[t]); + if (current()->type != t) { + fail_ce_expect(token_typename[current()->type], token_typename[t]); } } @@ -114,22 +116,20 @@ static struct ASTnode* expression(void); static struct ASTnode* primary(void) { struct ASTnode *res; - if (current().type == T_LP) { + if (current()->type == T_LP) { // ( expr ) considered as primary next(); res = expression(); match(T_RP); - } else if (current().type == T_I32_LIT) { - res = ast_make_intlit(*(int32_t*)current().val); + } else if (current()->type == T_I32_LIT) { + res = ast_make_lit_i32(*(int32_t*)current()->val); next(); - } else if (current().type == T_I64_LIT) { - // todo - fprintf(stderr, "TOOD: T_I64_LIT.\n"); - exit(1); - } else if (current().type == T_INDENT) { - int id = findglob((char*)current().val); + } else if (current()->type == T_I64_LIT) { + res = ast_make_lit_i64(*(int64_t*)current()->val); + } else if (current()->type == T_INDENT) { + int id = findglob((char*)current()->val); if (id == -1) { - fprintf(stderr, "syntax error on line %d: unknown indentifier %s.\n", Line, (char*)current().val); + fprintf(stderr, "syntax error on line %d: unknown indentifier %s.\n", Line, (char*)current()->val); exit(1); } next(); @@ -151,7 +151,7 @@ static struct ASTnode* binexpr(int precedence) { struct ASTnode *left, *right; left = primary(); - int tt = current().type; + int tt = current()->type; if (!is_binop(tt)) { return (left); } @@ -168,7 +168,7 @@ static struct ASTnode* binexpr(int precedence) { left = ast_make_binary(arithop(tt), left, right); // join right into left } - tt = current().type; + tt = current()->type; if (!is_binop(tt)) { return (left); } @@ -180,18 +180,18 @@ static struct ASTnode* binexpr(int precedence) { // parse one block of code, e.g. { a; b; } static struct ASTnode* parse_block(void) { match(T_LB); - if (current().type == T_RB) { + if (current()->type == T_RB) { next(); return NULL; } struct ASTblocknode* res = (struct ASTblocknode*)ast_make_block(); - while (current().type != T_RB) { + while (current()->type != T_RB) { struct ASTnode *x; x = statement(); llist_pushback_notnull(&res->st, x); - if (current().type == T_EOF) { + if (current()->type == T_EOF) { break; } } @@ -202,7 +202,7 @@ static struct ASTnode* parse_block(void) { // parse an expression static struct ASTnode* expression(void) { - if (current().type == T_LB) { + if (current()->type == T_LB) { return (parse_block()); } return (binexpr(0)); @@ -220,10 +220,10 @@ static struct ASTnode* print_statement(void) { static struct ASTnode* var_declaration(void) { match(T_INT); check(T_INDENT); - if (findglob((char*)current().val) != -1) { + if (findglob((char*)current()->val) != -1) { fail_ce("variable declared twice."); } - addglob((char*)current().val); + addglob((char*)current()->val); next(); match(T_SEMI); return (NULL); @@ -237,7 +237,7 @@ static struct ASTnode* if_statement(void) { match(T_RP); // ) struct ASTnode* then = statement(); struct ASTnode* else_then; - if (current().type == T_ELSE) { + if (current()->type == T_ELSE) { next(); // else else_then = statement(); } else { @@ -263,15 +263,15 @@ static struct ASTnode* for_statement(void) { struct ASTnode *init = statement(); struct ASTnode *cond; - if (current().type != T_SEMI) { + if (current()->type != T_SEMI) { cond = expression(); } else { - cond = ast_make_intlit(1); + cond = ast_make_lit_i32(1); } next(); // skip the ; struct ASTnode *inc; - if (current().type != T_RP) { + if (current()->type != T_RP) { inc = expression(); } else { inc = NULL; @@ -298,7 +298,7 @@ static struct ASTnode* for_statement(void) { // parse one statement static struct ASTnode* statement(void) { - switch (current().type) { + switch (current()->type) { case T_SEMI: return (NULL); case T_PRINT: diff --git a/src/util/array.c b/src/util/array.c index e002d03..f5dddcf 100644 --- a/src/util/array.c +++ b/src/util/array.c @@ -2,6 +2,7 @@ #include #include #include "util/array.h" +#include "fatals.h" void array_init(struct array *a) { a->length = 0; @@ -18,15 +19,16 @@ void array_free(struct array *a) { static void array_enlarge(struct array *a) { if (a->cap == 0) { - a->cap = 128; + a->cap = 1; + } else if (a->cap <= 256) { + a->cap *= 8; } else { - a->cap *= 2; + a->cap *= 1.7; } - void **old = a->begin; - a->begin = malloc(sizeof(void*) * a->cap); - if (old) { - memcpy(a->begin, old, a->length * sizeof(void*)); + a->begin = realloc(a->begin, a->cap); + if (a->begin == NULL) { + fail_malloc(__FUNCTION__); } } @@ -56,3 +58,12 @@ void array_set(struct array *a, int index, void *val) { a->begin[index] = val; } + +void* array_popback(struct array *a) { + if (a->length == 0) { + return (NULL); + } + + a->length -= 1; + return (a->begin[a->length]); +} \ No newline at end of file diff --git a/tests/input08 b/tests/input08 new file mode 100644 index 0000000..e93b3e9 --- /dev/null +++ b/tests/input08 @@ -0,0 +1,6 @@ +{ + long a = 5; + long b = a + 5; + int c = b - 1; + print c; +} \ No newline at end of file diff --git a/tests/input08.ans b/tests/input08.ans new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/tests/input08.ans @@ -0,0 +1 @@ +9 \ No newline at end of file