mirror of https://github.com/rui314/chibicc
Handle block scope
This commit is contained in:
parent
5617cca877
commit
d7b0a41a5d
58
parse.c
58
parse.c
|
@ -18,11 +18,26 @@
|
|||
|
||||
#include "chibicc.h"
|
||||
|
||||
// Scope for local or global variables.
|
||||
typedef struct VarScope VarScope;
|
||||
struct VarScope {
|
||||
VarScope *next;
|
||||
char *name;
|
||||
int depth;
|
||||
Var *var;
|
||||
};
|
||||
|
||||
// All local variable instances created during parsing are
|
||||
// accumulated to this list.
|
||||
static Var *locals;
|
||||
static Var *globals;
|
||||
|
||||
static VarScope *var_scope;
|
||||
|
||||
// scope_depth is incremented by one at the beginning of a block
|
||||
// scope and decremented by one at the end of a block scope.
|
||||
static int scope_depth;
|
||||
|
||||
static Type *typespec(Token **rest, Token *tok);
|
||||
static Type *declarator(Token **rest, Token *tok, Type *ty);
|
||||
static Node *declaration(Token **rest, Token *tok);
|
||||
|
@ -39,16 +54,21 @@ static Node *postfix(Token **rest, Token *tok);
|
|||
static Node *unary(Token **rest, Token *tok);
|
||||
static Node *primary(Token **rest, Token *tok);
|
||||
|
||||
// Find a local variable by name.
|
||||
static void enter_scope(void) {
|
||||
scope_depth++;
|
||||
}
|
||||
|
||||
static void leave_scope(void) {
|
||||
scope_depth--;
|
||||
while (var_scope && var_scope->depth > scope_depth)
|
||||
var_scope = var_scope->next;
|
||||
}
|
||||
|
||||
// Find a variable by name.
|
||||
static Var *find_var(Token *tok) {
|
||||
for (Var *var = locals; var; var = var->next)
|
||||
if (strlen(var->name) == tok->len && !strncmp(tok->loc, var->name, tok->len))
|
||||
return var;
|
||||
|
||||
for (Var *var = globals; var; var = var->next)
|
||||
if (strlen(var->name) == tok->len && !strncmp(tok->loc, var->name, tok->len))
|
||||
return var;
|
||||
|
||||
for (VarScope *sc = var_scope; sc; sc = sc->next)
|
||||
if (equal(tok, sc->name))
|
||||
return sc->var;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -84,10 +104,22 @@ static Node *new_var_node(Var *var, Token *tok) {
|
|||
return node;
|
||||
}
|
||||
|
||||
static VarScope *push_scope(char *name, Var *var) {
|
||||
VarScope *sc = calloc(1, sizeof(VarScope));
|
||||
sc->name = name;
|
||||
sc->var = var;
|
||||
sc->depth = scope_depth;
|
||||
|
||||
sc->next = var_scope;
|
||||
var_scope = sc;
|
||||
return sc;
|
||||
}
|
||||
|
||||
static Var *new_var(char *name, Type *ty) {
|
||||
Var *var = calloc(1, sizeof(Var));
|
||||
var->name = name;
|
||||
var->ty = ty;
|
||||
push_scope(name, var);
|
||||
return var;
|
||||
}
|
||||
|
||||
|
@ -293,9 +325,11 @@ static Node *stmt(Token **rest, Token *tok) {
|
|||
// compound-stmt = (declaration | stmt)* "}"
|
||||
static Node *compound_stmt(Token **rest, Token *tok) {
|
||||
Node *node = new_node(ND_BLOCK, tok);
|
||||
|
||||
Node head = {};
|
||||
Node *cur = &head;
|
||||
|
||||
enter_scope();
|
||||
|
||||
while (!equal(tok, "}")) {
|
||||
if (is_typename(tok))
|
||||
cur = cur->next = declaration(&tok, tok);
|
||||
|
@ -304,6 +338,8 @@ static Node *compound_stmt(Token **rest, Token *tok) {
|
|||
add_type(cur);
|
||||
}
|
||||
|
||||
leave_scope();
|
||||
|
||||
node->body = head.next;
|
||||
*rest = tok->next;
|
||||
return node;
|
||||
|
@ -616,12 +652,14 @@ static Token *function(Token *tok, Type *basety) {
|
|||
fn->is_function = true;
|
||||
|
||||
locals = NULL;
|
||||
enter_scope();
|
||||
create_param_lvars(ty->params);
|
||||
fn->params = locals;
|
||||
|
||||
tok = skip(tok, "{");
|
||||
fn->body = compound_stmt(&tok, tok);
|
||||
fn->locals = locals;
|
||||
leave_scope();
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
|
4
test.sh
4
test.sh
|
@ -216,4 +216,8 @@ assert 2 'int main() { /* return 1; */ return 2; }'
|
|||
assert 2 'int main() { // return 1;
|
||||
return 2; }'
|
||||
|
||||
assert 2 'int main() { int x=2; { int x=3; } return x; }'
|
||||
assert 2 'int main() { int x=2; { int x=3; } { int y=4; return x; }}'
|
||||
assert 3 'int main() { int x=2; { x=3; } return x; }'
|
||||
|
||||
echo OK
|
||||
|
|
Loading…
Reference in New Issue