| ... | @@ -2405,7 +2405,7 @@ fn varDecl( | ... | @@ -2405,7 +2405,7 @@ fn varDecl( |
| 2405 | .name = ident_name, | 2405 | .name = ident_name, |
| 2406 | .ptr = init_scope.rl_ptr, | 2406 | .ptr = init_scope.rl_ptr, |
| 2407 | .token_src = name_token, | 2407 | .token_src = name_token, |
| 2408 | .is_comptime = true, | 2408 | .maybe_comptime = true, |
| 2409 | }; | 2409 | }; |
| 2410 | return &sub_scope.base; | 2410 | return &sub_scope.base; |
| 2411 | }, | 2411 | }, |
| ... | @@ -2461,7 +2461,7 @@ fn varDecl( | ... | @@ -2461,7 +2461,7 @@ fn varDecl( |
| 2461 | .name = ident_name, | 2461 | .name = ident_name, |
| 2462 | .ptr = var_data.alloc, | 2462 | .ptr = var_data.alloc, |
| 2463 | .token_src = name_token, | 2463 | .token_src = name_token, |
| 2464 | .is_comptime = is_comptime, | 2464 | .maybe_comptime = is_comptime, |
| 2465 | }; | 2465 | }; |
| 2466 | return &sub_scope.base; | 2466 | return &sub_scope.base; |
| 2467 | }, | 2467 | }, |
| ... | @@ -5405,7 +5405,7 @@ fn forExpr( | ... | @@ -5405,7 +5405,7 @@ fn forExpr( |
| 5405 | .name = index_name, | 5405 | .name = index_name, |
| 5406 | .ptr = index_ptr, | 5406 | .ptr = index_ptr, |
| 5407 | .token_src = index_token, | 5407 | .token_src = index_token, |
| 5408 | .is_comptime = is_inline, | 5408 | .maybe_comptime = is_inline, |
| 5409 | }; | 5409 | }; |
| 5410 | break :blk &index_scope.base; | 5410 | break :blk &index_scope.base; |
| 5411 | }; | 5411 | }; |
| ... | @@ -6188,7 +6188,7 @@ fn identifier( | ... | @@ -6188,7 +6188,7 @@ fn identifier( |
| 6188 | if (local_ptr.name == name_str_index) { | 6188 | if (local_ptr.name == name_str_index) { |
| 6189 | local_ptr.used = true; | 6189 | local_ptr.used = true; |
| 6190 | if (hit_namespace) { | 6190 | if (hit_namespace) { |
| 6191 | if (local_ptr.is_comptime) | 6191 | if (local_ptr.maybe_comptime) |
| 6192 | break | 6192 | break |
| 6193 | else | 6193 | else |
| 6194 | return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{ | 6194 | return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{ |
| ... | @@ -6836,9 +6836,32 @@ fn builtinCall( | ... | @@ -6836,9 +6836,32 @@ fn builtinCall( |
| 6836 | .identifier => { | 6836 | .identifier => { |
| 6837 | const ident_token = main_tokens[params[0]]; | 6837 | const ident_token = main_tokens[params[0]]; |
| 6838 | decl_name = try astgen.identAsString(ident_token); | 6838 | decl_name = try astgen.identAsString(ident_token); |
| 6839 | // TODO look for local variables in scope matching `decl_name` and emit a compile | 6839 | { |
| 6840 | // error. Only top-level declarations can be exported. Until this is done, the | 6840 | var s = scope; |
| 6841 | // compile error will end up being "use of undeclared identifier" in Sema. | 6841 | while (true) switch (s.tag) { |
| | 6842 | .local_val => { |
| | 6843 | const local_val = s.cast(Scope.LocalVal).?; |
| | 6844 | if (local_val.name == decl_name) { |
| | 6845 | local_val.used = true; |
| | 6846 | break; |
| | 6847 | } |
| | 6848 | s = local_val.parent; |
| | 6849 | }, |
| | 6850 | .local_ptr => { |
| | 6851 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| | 6852 | if (local_ptr.name == decl_name) { |
| | 6853 | if (!local_ptr.maybe_comptime) |
| | 6854 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); |
| | 6855 | local_ptr.used = true; |
| | 6856 | break; |
| | 6857 | } |
| | 6858 | s = local_ptr.parent; |
| | 6859 | }, |
| | 6860 | .gen_zir => s = s.cast(GenZir).?.parent, |
| | 6861 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| | 6862 | .namespace, .top => break, |
| | 6863 | }; |
| | 6864 | } |
| 6842 | }, | 6865 | }, |
| 6843 | .field_access => { | 6866 | .field_access => { |
| 6844 | const namespace_node = node_datas[params[0]].lhs; | 6867 | const namespace_node = node_datas[params[0]].lhs; |
| ... | @@ -6848,7 +6871,7 @@ fn builtinCall( | ... | @@ -6848,7 +6871,7 @@ fn builtinCall( |
| 6848 | decl_name = try astgen.identAsString(field_ident); | 6871 | decl_name = try astgen.identAsString(field_ident); |
| 6849 | }, | 6872 | }, |
| 6850 | else => return astgen.failNode( | 6873 | else => return astgen.failNode( |
| 6851 | params[0], "the first @export parameter must be an identifier", .{}, | 6874 | params[0], "symbol to export must identify a declaration", .{}, |
| 6852 | ), | 6875 | ), |
| 6853 | } | 6876 | } |
| 6854 | const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); | 6877 | const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); |
| ... | @@ -8431,7 +8454,8 @@ const Scope = struct { | ... | @@ -8431,7 +8454,8 @@ const Scope = struct { |
| 8431 | token_src: ast.TokenIndex, | 8454 | token_src: ast.TokenIndex, |
| 8432 | /// String table index. | 8455 | /// String table index. |
| 8433 | name: u32, | 8456 | name: u32, |
| 8434 | is_comptime: bool, | 8457 | /// true means we find out during Sema whether the value is comptime. false means it is already known at AstGen the value is runtime-known. |
| | 8458 | maybe_comptime: bool, |
| 8435 | /// has this variable been referenced? | 8459 | /// has this variable been referenced? |
| 8436 | used: bool = false, | 8460 | used: bool = false, |
| 8437 | }; | 8461 | }; |