272272struct FastcSourceHeader {
273273 module_name string
274274 imports map [string ]string
275+ has_globals bool
275276}
276277
277278struct FastcSourceFile {
@@ -332,6 +333,7 @@ struct Parser {
332333 constants map [string ]string
333334 public_constants map [string ]bool
334335 globals map [string ]string
336+ public_globals map [string ]bool
335337 used_function_names map [string ]bool
336338 module_init_calls []string
337339 selfhost bool
@@ -401,15 +403,16 @@ fn generate_source_files(sources []FastcSourceFile, prefs &pref.Preferences) !st
401403 mut constants := map [string ]string {}
402404 mut public_constants := map [string ]bool {}
403405 mut globals := map [string ]string {}
406+ mut public_globals := map [string ]bool {}
404407 for source_file in sources {
405408 collect_declared_types (source_file.source, source_file.path,
406409 source_file.header.module_name, prefs, mut declared_types, mut declared_kinds)!
407410 }
408411 for source_file in sources {
409412 collect_constant_names (source_file.source, source_file.path,
410413 source_file.header.module_name, prefs, mut constants, mut public_constants)!
411- collect_global_names (source_file.source, source_file.path, source_file.header.module_name,
412- prefs , mut globals )!
414+ collect_global_names (source_file.source, source_file.path, source_file.header, prefs, mut
415+ globals , mut public_globals )!
413416 }
414417 mut functions := map [string ]FastcFunctionSignature{}
415418 mut interface_methods := map [string ]bool {}
@@ -439,13 +442,13 @@ fn generate_source_files(sources []FastcSourceFile, prefs &pref.Preferences) !st
439442 mut global_types := map [string ]string {}
440443 fastc_render_struct_field_defaults (prefs, declared_types, declared_kinds, struct_fields, mut
441444 struct_field_info, functions, constants, public_constants, constant_types, globals,
442- global_types)!
445+ public_globals, global_types)!
443446 constant_output := fastc_generate_constant_declarations (sources, prefs, declared_types,
444- declared_kinds, struct_fields, struct_field_info, functions, constants, public_constants, mut
445- constant_types)!
447+ declared_kinds, struct_fields, struct_field_info, functions, constants, public_constants,
448+ globals, public_globals, mut constant_types)!
446449 global_output := fastc_generate_global_declarations (sources, prefs, declared_types,
447450 declared_kinds, struct_fields, struct_field_info, functions, constants, public_constants,
448- constant_types, globals, mut global_types)!
451+ constant_types, globals, public_globals, mut global_types)!
449452 for constant_type in constant_types.values () {
450453 fastc_register_composite_type (constant_type, mut composite_types)
451454 }
@@ -472,6 +475,7 @@ fn generate_source_files(sources []FastcSourceFile, prefs &pref.Preferences) !st
472475 constants: constants
473476 public_constants: public_constants
474477 globals: globals
478+ public_globals: public_globals
475479 used_function_names: used_function_names
476480 module_init_calls: module_init_calls
477481 selfhost: prefs.building_v
@@ -687,6 +691,7 @@ fn fastc_resolve_source_files(paths []string, prefs &pref.Preferences) ![]FastcS
687691 header = FastcSourceHeader{
688692 module_name: queued.module_name
689693 imports: header.imports
694+ has_globals: header.has_globals
690695 }
691696 }
692697 sources << FastcSourceFile{
@@ -806,9 +811,26 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
806811 scan.init (file, source)
807812 mut module_name := ''
808813 mut imports := map [string ]string {}
814+ mut has_globals := false
809815 mut brace_depth := 0
810816 mut tok := scan.scan ()
811817 for tok != .eof {
818+ if module_name == '' && tok == .attribute {
819+ mut attribute_depth := 1
820+ tok = scan.scan ()
821+ for attribute_depth > 0 && tok != .eof {
822+ if tok == .name && scan.lit == 'has_globals' {
823+ has_globals = true
824+ }
825+ if tok == .lsbr {
826+ attribute_depth++
827+ } else if tok == .rsbr {
828+ attribute_depth--
829+ }
830+ tok = scan.scan ()
831+ }
832+ continue
833+ }
812834 if module_name == '' && tok == .key_module {
813835 tok = scan.scan ()
814836 if tok != .name {
@@ -865,6 +887,7 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
865887 return FastcSourceHeader{
866888 module_name: module_name
867889 imports: imports
890+ has_globals: has_globals
868891 }
869892}
870893
@@ -1077,35 +1100,39 @@ fn fastc_register_constant(module_name string, name string, is_public bool, path
10771100 }
10781101}
10791102
1080- fn collect_global_names (source string , path string , module_name string , prefs & pref.Preferences, mut globals map [string ]string ) ! {
1103+ fn collect_global_names (source string , path string , header FastcSourceHeader , prefs & pref.Preferences, mut globals map [string ]string , mut public_globals map [ string ] bool ) ! {
10811104 mut file_set := token.FileSet.new ()
10821105 mut file := file_set.add_file (path, source.len)
10831106 file.index_lines (source)
10841107 mut scan := scanner.new_scanner (prefs, .normal)
10851108 scan.init (file, source)
10861109 mut depth := 0
1110+ mut previous_tok := token.Token.unknown
10871111 mut tok := scan.scan ()
10881112 for tok != .eof {
10891113 if depth == 0 && tok == .key_global {
1114+ is_public := previous_tok == .key_pub
10901115 tok = scan.scan ()
10911116 if tok == .lpar {
10921117 tok = scan.scan ()
10931118 mut at_start := true
10941119 for tok != .rpar && tok != .eof {
10951120 if tok == .semicolon {
10961121 at_start = true
1097- } else if at_start && tok == .name && scan.lit != 'C' {
1098- key := fastc_global_key (module_name, scan.lit)
1099- globals[key] = fastc_c_global_name (key)
1122+ } else if at_start && tok == .name {
1123+ if scan.lit != 'C' {
1124+ fastc_register_global (header, scan.lit, is_public, path, prefs, mut
1125+ globals, mut public_globals)!
1126+ }
11001127 at_start = false
11011128 }
11021129 tok = scan.scan ()
11031130 }
11041131 continue
11051132 }
11061133 if tok == .name && scan.lit != 'C' {
1107- key := fastc_global_key (module_name , scan.lit)
1108- globals[key] = fastc_c_global_name (key)
1134+ fastc_register_global (header , scan.lit, is_public, path, prefs, mut globals, mut
1135+ public_globals) !
11091136 }
11101137 continue
11111138 }
@@ -1114,11 +1141,27 @@ fn collect_global_names(source string, path string, module_name string, prefs &p
11141141 } else if tok == .rcbr && depth > 0 {
11151142 depth--
11161143 }
1144+ previous_tok = tok
11171145 tok = scan.scan ()
11181146 }
11191147}
11201148
1121- fn fastc_generate_global_declarations (sources []FastcSourceFile, prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , constant_types map [string ]string , globals map [string ]string , mut global_types map [string ]string ) ! FastcGlobalDeclarations {
1149+ fn fastc_register_global (header FastcSourceHeader, name string , is_public bool , path string , prefs & pref.Preferences, mut globals map [string ]string , mut public_globals map [string ]bool ) ! {
1150+ if ! prefs.enable_globals && ! prefs.building_v && header.module_name != 'builtin'
1151+ && ! header.has_globals {
1152+ return error ('use `v -enable-globals ...` to enable globals in ${path }' )
1153+ }
1154+ key := fastc_global_key (header.module_name, name)
1155+ if key in globals {
1156+ return error ('fastc parser does not support duplicate global `${name }` in ${path }' )
1157+ }
1158+ globals[key] = fastc_c_global_name (key)
1159+ if is_public {
1160+ public_globals[key] = true
1161+ }
1162+ }
1163+
1164+ fn fastc_generate_global_declarations (sources []FastcSourceFile, prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , constant_types map [string ]string , globals map [string ]string , public_globals map [string ]bool , mut global_types map [string ]string ) ! FastcGlobalDeclarations {
11221165 mut out := strings.new_builder (1024 )
11231166 mut initializers := strings.new_builder (1024 )
11241167 ordered_sources := fastc_sources_in_dependency_order (sources)!
@@ -1138,6 +1181,7 @@ fn fastc_generate_global_declarations(sources []FastcSourceFile, prefs &pref.Pre
11381181 constants: constants
11391182 public_constants: public_constants
11401183 globals: globals
1184+ public_globals: public_globals
11411185 selfhost: prefs.building_v
11421186 s: scanner.new_scanner (prefs, .normal)
11431187 out: strings.new_builder (0 )
@@ -1233,7 +1277,7 @@ fn (mut g Parser) parse_global_declaration(mut out strings.Builder, mut initiali
12331277 g.skip_semicolons ()
12341278}
12351279
1236- fn fastc_render_struct_field_defaults (prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , mut struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , constant_types map [string ]string , globals map [string ]string , global_types map [string ]string ) ! {
1280+ fn fastc_render_struct_field_defaults (prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , mut struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , constant_types map [string ]string , globals map [string ]string , public_globals map [ string ] bool , global_types map [string ]string ) ! {
12371281 mut type_names := struct_field_info.keys ()
12381282 type_names.sort ()
12391283 for type_name in type_names {
@@ -1258,6 +1302,7 @@ fn fastc_render_struct_field_defaults(prefs &pref.Preferences, declared_types ma
12581302 constants: constants
12591303 public_constants: public_constants
12601304 globals: globals
1305+ public_globals: public_globals
12611306 selfhost: prefs.building_v
12621307 s: scanner.new_scanner (prefs, .normal)
12631308 out: strings.new_builder (0 )
@@ -1292,7 +1337,7 @@ fn fastc_render_struct_field_defaults(prefs &pref.Preferences, declared_types ma
12921337 }
12931338}
12941339
1295- fn fastc_generate_constant_declarations (sources []FastcSourceFile, prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , mut constant_types map [string ]string ) ! FastcConstantDeclarations {
1340+ fn fastc_generate_constant_declarations (sources []FastcSourceFile, prefs & pref.Preferences, declared_types map [string ]bool , declared_kinds map [string ]FastcDeclaredTypeKind, struct_fields map [string ]map [string ]string , struct_field_info map [string ][]FastcStructField, functions map [string ]FastcFunctionSignature, constants map [string ]string , public_constants map [string ]bool , globals map [ string ] string , public_globals map [ string ] bool , mut constant_types map [string ]string ) ! FastcConstantDeclarations {
12961341 mut values := []FastcConstantValue{}
12971342 ordered_sources := fastc_sources_in_dependency_order (sources)!
12981343 for source_file in ordered_sources {
@@ -1310,6 +1355,8 @@ fn fastc_generate_constant_declarations(sources []FastcSourceFile, prefs &pref.P
13101355 struct_field_info: struct_field_info
13111356 constants: constants
13121357 public_constants: public_constants
1358+ globals: globals
1359+ public_globals: public_globals
13131360 selfhost: prefs.building_v
13141361 s: scanner.new_scanner (prefs, .normal)
13151362 out: strings.new_builder (256 )
@@ -9931,12 +9978,20 @@ fn (g &Parser) expression_name(previous token.Token, qualified_name_owner string
99319978 if constant_key in g.constants && constant_key ! in g.public_constants {
99329979 return g.unsupported ('private constant `${g .lit }` from imported module `${imported_module }`' )
99339980 }
9981+ g.validate_imported_global_visibility (imported_module, g.lit)!
99349982 }
99359983 }
99369984 g.validate_expression_name (g.lit, previous)!
99379985 return g.resolved_expression_name (g.lit, previous)
99389986}
99399987
9988+ fn (g &Parser) validate_imported_global_visibility (imported_module string , name string ) ! {
9989+ global_key := fastc_global_key (imported_module, name)
9990+ if global_key in g.globals && global_key ! in g.public_globals {
9991+ return g.unsupported ('private global `${name }` from imported module `${imported_module }`' )
9992+ }
9993+ }
9994+
99409995fn (g &Parser) resolved_expression_name (name string , previous token.Token) string {
99419996 if previous != .dot && name == 'C' {
99429997 return ''
@@ -10823,9 +10878,9 @@ fn (g &Parser) infer_expression_type(tokens []FastcExpressionToken) !string {
1082310878 if fastc_constant_key (imported_module, tokens[start + 2 ].lit) in g.constants {
1082410879 return 'integer literal'
1082510880 }
10826- if global_type := g.global_types[ fastc_global_key (imported_module,
10827- tokens[start + 2 ].lit)]
10828- {
10881+ global_name := tokens[start + 2 ].lit
10882+ if global_type := g.global_types[ fastc_global_key (imported_module, global_name)] {
10883+ g. validate_imported_global_visibility (imported_module, global_name) !
1082910884 return global_type
1083010885 }
1083110886 }
0 commit comments