diff --git a/code/demo.odin b/code/demo.odin index 54ad01201..660594bae 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,19 +1,3 @@ -#import "fmt.odin"; -#import "os.odin"; - main :: proc() { - immutable program := "+ + * - /"; - accumulator := 0; - - for token in program { - match token { - case '+': accumulator += 1; - case '-': accumulator -= 1; - case '*': accumulator *= 2; - case '/': accumulator /= 2; - default: // Ignore everything else - } - } - - fmt.printf("The program \"%s\" calculates the value %d\n", program, accumulator); + /* } diff --git a/core/opengl.odin b/core/opengl.odin index 1de71a4d5..1886e424e 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -54,6 +54,7 @@ GenSamplers: proc(count: i32, buffers: ^u32) #cc_c; DeleteBuffers: proc(count: i32, buffers: ^u32) #cc_c; BindBuffer: proc(target: i32, buffer: u32) #cc_c; BindVertexArray: proc(buffer: u32) #cc_c; +DeleteVertexArrays: proc(count: i32, arrays: ^u32) #cc_c; BindSampler: proc(position: i32, sampler: u32) #cc_c; BufferData: proc(target: i32, size: int, data: rawptr, usage: i32) #cc_c; BufferSubData: proc(target: i32, offset, size: int, data: rawptr) #cc_c; @@ -120,6 +121,7 @@ init :: proc() { set_proc_address(&BindBuffer, "glBindBuffer\x00"); set_proc_address(&BindSampler, "glBindSampler\x00"); set_proc_address(&BindVertexArray, "glBindVertexArray\x00"); + set_proc_address(&DeleteVertexArrays, "glDeleteVertexArrays\x00"); set_proc_address(&BufferData, "glBufferData\x00"); set_proc_address(&BufferSubData, "glBufferSubData\x00"); diff --git a/src/check_decl.c b/src/check_decl.c index 587877be7..3778197c6 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -44,6 +44,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex e->type = t; } + e->parent_proc_decl = c->context.curr_proc_decl; + check_assignment(c, operand, e->type, context_name); if (operand->mode == Addressing_Invalid) { return NULL; @@ -122,6 +124,8 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { return; } + e->parent_proc_decl = c->context.curr_proc_decl; + e->Constant.value = operand->value; } @@ -497,6 +501,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { c->context.scope = d->scope; c->context.decl = d; + e->parent_proc_decl = c->context.curr_proc_decl; + switch (e->kind) { case Entity_Variable: check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr); @@ -535,6 +541,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod c->context.scope = decl->scope; c->context.decl = decl; c->context.proc_name = proc_name; + c->context.curr_proc_decl = decl; GB_ASSERT(type->kind == Type_Proc); if (type->Proc.param_count > 0) { diff --git a/src/check_expr.c b/src/check_expr.c index 414b15f06..089f706e4 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1208,6 +1208,16 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * } return NULL; } + if (e->parent_proc_decl != NULL && + e->parent_proc_decl != c->context.curr_proc_decl) { + if (e->kind == Entity_Variable) { + error(n->Ident, "Nested procedures do not capture its parent's variables: %.*s", LIT(name)); + return NULL; + } else if (e->kind == Entity_Label) { + error(n->Ident, "Nested procedures do not capture its parent's labels: %.*s", LIT(name)); + return NULL; + } + } bool is_overloaded = false; isize overload_count = 0; diff --git a/src/check_stmt.c b/src/check_stmt.c index 99e972727..2d25e88a9 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -425,6 +425,7 @@ void check_label(Checker *c, AstNode *label) { Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident, t_invalid, label); add_entity(c, c->context.scope, l->name, e); + e->parent_proc_decl = c->context.curr_proc_decl; if (ok) { BlockLabel bl = {name, label}; @@ -1448,7 +1449,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } AstNode *ident = bs->label; String name = ident->Ident.string; - Entity *e = scope_lookup_entity(c->context.scope, name); + Operand o = {0}; + Entity *e = check_ident(c, &o, ident, NULL, NULL, false); if (e == NULL) { error_node(ident, "Undeclared label name: %.*s", LIT(name)); return; @@ -1473,8 +1475,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { bool is_selector = false; if (expr->kind == AstNode_Ident) { - String name = expr->Ident.string; - e = scope_lookup_entity(c->context.scope, name); + Operand o = {0}; + e = check_ident(c, &o, expr, NULL, NULL, true); } else if (expr->kind == AstNode_SelectorExpr) { Operand o = {0}; e = check_selector(c, &o, expr, NULL); @@ -1548,6 +1550,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (entity == NULL) { entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); } + entity->parent_proc_decl = c->context.curr_proc_decl; entities[entity_count++] = entity; } diff --git a/src/checker.c b/src/checker.c index c2d5a3bf6..fae2eef2d 100644 --- a/src/checker.c +++ b/src/checker.c @@ -299,6 +299,7 @@ typedef struct CheckerContext { bool in_defer; // TODO(bill): Actually handle correctly String proc_name; Type * type_hint; + DeclInfo * curr_proc_decl; } CheckerContext; // CheckerInfo stores all the symbol information for a type-checked program @@ -489,14 +490,14 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit if (found) { Entity *e = *found; if (gone_thru_proc) { - if (e->kind == Entity_Label) { - continue; - } - if (e->kind == Entity_Variable && - !e->scope->is_file && - !e->scope->is_global) { - continue; - } + // if (e->kind == Entity_Label) { + // continue; + // } + // if (e->kind == Entity_Variable && + // !e->scope->is_file && + // !e->scope->is_global) { + // continue; + // } } if (entity_) *entity_ = e; @@ -1079,7 +1080,7 @@ void pop_procedure(Checker *c) { array_pop(&c->proc_stack); } -Type *const curr_procedure(Checker *c) { +Type *const curr_procedure_type(Checker *c) { isize count = c->proc_stack.count; if (count > 0) { return c->proc_stack.e[count-1]; diff --git a/src/entity.c b/src/entity.c index 18b318a1f..465d75640 100644 --- a/src/entity.c +++ b/src/entity.c @@ -1,6 +1,7 @@ -typedef struct Scope Scope; -typedef struct Checker Checker; -typedef struct Type Type; +typedef struct Scope Scope; +typedef struct Checker Checker; +typedef struct Type Type; +typedef struct DeclInfo DeclInfo; // typedef enum BuiltinProcId BuiltinProcId; @@ -67,6 +68,7 @@ struct Entity { Scope * scope; Type * type; AstNode * identifier; // Can be NULL + DeclInfo * parent_proc_decl; // NULL if in file/global scope // TODO(bill): Cleanup how `using` works for entities Entity * using_parent; @@ -169,6 +171,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T token.pos = parent->token.pos; Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type); entity->using_parent = parent; + entity->parent_proc_decl = parent->parent_proc_decl; entity->flags |= EntityFlag_Using; return entity; } diff --git a/src/tokenizer.c b/src/tokenizer.c index 9dcade195..bc979a784 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -909,7 +909,9 @@ Token tokenizer_get_token(Tokenizer *t) { isize comment_scope = 1; advance_to_next_rune(t); while (comment_scope > 0) { - if (t->curr_rune == '/') { + if (t->curr_rune == GB_RUNE_EOF) { + break; + } else if (t->curr_rune == '/') { advance_to_next_rune(t); if (t->curr_rune == '*') { advance_to_next_rune(t);