Browse Source

Implement Explicit context creation #639

gingerBill 5 years ago
parent
commit
f661d34049
6 changed files with 39 additions and 11 deletions
  1. 2 2
      core/fmt/fmt.odin
  2. 6 0
      core/runtime/core.odin
  3. 9 0
      src/check_expr.cpp
  4. 14 8
      src/check_type.cpp
  5. 5 0
      src/checker.cpp
  6. 3 1
      src/checker.hpp

+ 2 - 2
core/fmt/fmt.odin

@@ -125,7 +125,7 @@ bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
 }
 
 
-assertf :: proc "contextless" (condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
+assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
 	if !condition {
 		p := context.assertion_failure_proc;
 		if p == nil {
@@ -137,7 +137,7 @@ assertf :: proc "contextless" (condition: bool, fmt: string, args: ..any, loc :=
 	return condition;
 }
 
-panicf :: proc "contextless" (fmt: string, args: ..any, loc := #caller_location) {
+panicf :: proc(fmt: string, args: ..any, loc := #caller_location) {
 	p := context.assertion_failure_proc;
 	if p == nil {
 		p = runtime.default_assertion_failure_proc;

+ 6 - 0
core/runtime/core.odin

@@ -440,6 +440,12 @@ default_logger :: proc() -> Logger {
 }
 
 
+default_context :: proc "contextless" () -> Context {
+	c: Context;
+	__init_context(&c);
+	return c;
+}
+
 @private
 __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
 	if c == nil do return;

+ 9 - 0
src/check_expr.cpp

@@ -7724,6 +7724,15 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 				return kind;
 			}
 
+			if (unparen_expr(c->assignment_lhs_hint) == node) {
+				c->scope->flags |= ScopeFlag_ContextDefined;
+			}
+
+			if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
+				error(node, "'context' has not been defined within this scope");
+				// Continue with value
+			}
+
 			init_core_context(c->checker);
 			o->mode = Addressing_Context;
 			o->type = t_context;

+ 14 - 8
src/check_type.cpp

@@ -2501,6 +2501,19 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 	c->curr_proc_sig = type;
 	c->in_proc_sig = true;
 
+	
+	ProcCallingConvention cc = pt->calling_convention;
+	if (cc == ProcCC_ForeignBlockDefault) {
+		cc = ProcCC_CDecl;
+		if (c->foreign_context.default_cc > 0) {
+			cc = c->foreign_context.default_cc;
+		}
+	}
+	GB_ASSERT(cc > 0);
+	if (cc == ProcCC_Odin) {
+		c->scope->flags |= ScopeFlag_ContextDefined;
+	}
+
 	bool variadic = false;
 	isize variadic_index = -1;
 	bool success = true;
@@ -2534,14 +2547,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 	}
 
 
-	ProcCallingConvention cc = pt->calling_convention;
-	if (cc == ProcCC_ForeignBlockDefault) {
-		cc = ProcCC_CDecl;
-		if (c->foreign_context.default_cc > 0) {
-			cc = c->foreign_context.default_cc;
-		}
-	}
-	GB_ASSERT(cc > 0);
+
 
 	bool optional_ok = (pt->tags & ProcTag_optional_ok) != 0;
 	if (optional_ok) {

+ 5 - 0
src/checker.cpp

@@ -231,6 +231,11 @@ Scope *create_scope(Scope *parent, gbAllocator allocator, isize init_elements_ca
 	if (parent != nullptr && parent != builtin_pkg->scope) {
 		DLIST_APPEND(parent->first_child, parent->last_child, s);
 	}
+
+	if (parent != nullptr && parent->flags & ScopeFlag_ContextDefined) {
+		s->flags |= ScopeFlag_ContextDefined;
+	}
+
 	return s;
 }
 

+ 3 - 1
src/checker.hpp

@@ -158,7 +158,7 @@ struct ProcInfo {
 
 
 
-enum ScopeFlag {
+enum ScopeFlag : i32 {
 	ScopeFlag_Pkg    = 1<<1,
 	ScopeFlag_Global = 1<<2,
 	ScopeFlag_File   = 1<<3,
@@ -167,6 +167,8 @@ enum ScopeFlag {
 	ScopeFlag_Type   = 1<<6,
 
 	ScopeFlag_HasBeenImported = 1<<10, // This is only applicable to file scopes
+	
+	ScopeFlag_ContextDefined = 1<<16, 
 };
 
 struct Scope {