274274struct FastcSourceHeader {
275275 module_name string
276276 imports map [string ]string
277+ import_order []string
277278 blank_imports []string
278279 has_globals bool
279280}
@@ -736,6 +737,7 @@ fn fastc_resolve_source_files(paths []string, prefs &pref.Preferences) ![]FastcS
736737 header = FastcSourceHeader{
737738 module_name: queued.module_name
738739 imports: header.imports
740+ import_order: header.import_order
739741 blank_imports: header.blank_imports
740742 has_globals: header.has_globals
741743 }
@@ -773,9 +775,12 @@ fn fastc_resolve_source_files(paths []string, prefs &pref.Preferences) ![]FastcS
773775}
774776
775777fn fastc_header_imported_modules (header FastcSourceHeader) []string {
776- mut modules := header.imports.values ()
777- modules << header.blank_imports
778- return modules
778+ if header.import_order.len > 0 {
779+ return header.import_order.clone ()
780+ }
781+ mut fallback := header.imports.values ()
782+ fallback << header.blank_imports
783+ return fallback
779784}
780785
781786fn fastc_sources_in_dependency_order (sources []FastcSourceFile) ! []FastcSourceFile {
@@ -870,7 +875,6 @@ fn fastc_append_module_sources(module_name string, sources []FastcSourceFile, mu
870875 }
871876 }
872877 }
873- dependencies.sort ()
874878 for dependency in dependencies {
875879 fastc_append_module_sources (dependency, sources, mut visiting, mut visited, mut ordered)!
876880 }
@@ -897,6 +901,7 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
897901 scan.init (file, source)
898902 mut module_name := ''
899903 mut imports := map [string ]string {}
904+ mut import_order := []string {}
900905 mut blank_imports := []string {}
901906 mut has_globals := false
902907 mut brace_depth := 0
@@ -953,6 +958,9 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
953958 fastc_register_import_alias (import_path, alias, path, mut imports, mut
954959 blank_imports)!
955960 fastc_register_selective_imports (import_path, selected_names, path, mut imports)!
961+ if import_path ! in import_order {
962+ import_order << import_path
963+ }
956964 tok = next_token
957965 }
958966 if tok == .rpar {
@@ -963,18 +971,28 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
963971 import_path , alias , selected_names , next_token := fastc_scan_import (mut scan, tok, path)!
964972 fastc_register_import_alias (import_path, alias, path, mut imports, mut blank_imports)!
965973 fastc_register_selective_imports (import_path, selected_names, path, mut imports)!
974+ if import_path ! in import_order {
975+ import_order << import_path
976+ }
966977 tok = next_token
967978 }
968979 if module_name == '' {
969980 module_name = 'main'
970981 }
971982 if prefs.building_v && prefs.backend == 'fastc' && imports['driver' ] == 'v3.driver'
972983 && 'fastcdriver' in imports {
973- imports['driver' ] = imports['fastcdriver' ]
984+ fastcdriver_module := imports['fastcdriver' ]
985+ imports['driver' ] = fastcdriver_module
986+ for i, imported_module in import_order {
987+ if imported_module == 'v3.driver' {
988+ import_order[i] = fastcdriver_module
989+ }
990+ }
974991 }
975992 return FastcSourceHeader{
976993 module_name: module_name
977994 imports: imports
995+ import_order: import_order
978996 blank_imports: blank_imports
979997 has_globals: has_globals
980998 }
@@ -10685,6 +10703,19 @@ fn (g &Parser) is_enum_type_name(name string) bool {
1068510703 return g.declared_kinds[type_key] == .enum_
1068610704}
1068710705
10706+ fn (g &Parser) declared_cast_type_key (tokens []FastcExpressionToken, name_index int ) ? string {
10707+ if name_index > = 2 && tokens[name_index - 1 ].tok == .dot && tokens[name_index - 2 ].tok == .name {
10708+ module_name := g.imports[tokens[name_index - 2 ].lit] or { return none }
10709+ type_key := fastc_type_key (module_name, tokens[name_index].lit)
10710+ return if type_key in g.declared_types { type_key } else { none }
10711+ }
10712+ if name_index > 0 && tokens[name_index - 1 ].tok == .dot {
10713+ return none
10714+ }
10715+ return fastc_resolve_declared_type_key (g.module_name, tokens[name_index].lit, g.imports,
10716+ g.declared_types)
10717+ }
10718+
1068810719fn (g &Parser) validate_expression_calls (tokens []FastcExpressionToken) ! {
1068910720 mut i := 0
1069010721 for i + 1 < tokens.len {
@@ -10824,16 +10855,15 @@ fn (g &Parser) validate_expression_calls(tokens []FastcExpressionToken) ! {
1082410855 i = call_end + 1
1082510856 continue
1082610857 }
10827- if i == 0 || tokens[i - 1 ].tok != .dot {
10828- if _ := fastc_resolve_declared_type_key (g.module_name, name, g.imports,
10829- g.declared_types)
10830- {
10831- if call_args.len != 1 {
10832- return g.unsupported ('cast `${name }` with ${call_args .len } arguments' )
10833- }
10834- i = call_end + 1
10835- continue
10858+ if type_key := g.declared_cast_type_key (tokens, i) {
10859+ if call_args.len != 1 {
10860+ return g.unsupported ('cast `${name }` with ${call_args .len } arguments' )
1083610861 }
10862+ g.validate_declared_cast (type_key, call_args[0 ], tokens[i].unsafe_depth > 0 )!
10863+ i = call_end + 1
10864+ continue
10865+ }
10866+ if i == 0 || tokens[i - 1 ].tok != .dot {
1083710867 if primitive_type := fastc_primitive_c_type (name) {
1083810868 if call_args.len != 1 {
1083910869 return g.unsupported ('cast `${name }` with ${call_args .len } arguments' )
@@ -10967,6 +10997,51 @@ fn (g &Parser) validate_primitive_cast(target_type string, operand []FastcExpres
1096710997 return g.unsupported ('cast from `${actual_type }` to `${target_type }`' )
1096810998}
1096910999
11000+ fn (g &Parser) validate_declared_cast (type_key string , operand []FastcExpressionToken, in_unsafe bool ) ! {
11001+ if g.selfhost {
11002+ return
11003+ }
11004+ target_type := fastc_c_declared_type_name (type_key)
11005+ actual_type := fastc_normalize_inferred_type (g.infer_expression_type (operand)! )
11006+ if actual_type == '' {
11007+ return g.unsupported ('unverifiable operand type for cast to `${target_type }`' )
11008+ }
11009+ match g.declared_kinds[type_key] {
11010+ .alias_ {
11011+ target_base := g.underlying_alias_type (target_type)
11012+ if target_base == target_type {
11013+ return g.unsupported ('unverifiable declared alias cast to `${target_type }`' )
11014+ }
11015+ if g.declared_kinds[g.semantic_type_key (target_base)] == .enum_ {
11016+ return g.validate_declared_enum_cast (target_base, actual_type, in_unsafe)
11017+ }
11018+ actual_base := g.underlying_alias_type (actual_type)
11019+ if actual_type == target_type || actual_base == target_base
11020+ || g.primitive_cast_types_are_compatible (actual_base, target_base, in_unsafe) {
11021+ return
11022+ }
11023+ return g.unsupported ('cast from `${actual_type }` to `${target_type }` (alias to `${target_base }`)' )
11024+ }
11025+ .enum_ {
11026+ return g.validate_declared_enum_cast (target_type, actual_type, in_unsafe)
11027+ }
11028+ else {}
11029+ }
11030+ }
11031+
11032+ fn (g &Parser) validate_declared_enum_cast (target_type string , actual_type string , in_unsafe bool ) ! {
11033+ actual_base := g.underlying_alias_type (actual_type)
11034+ if g.semantic_type_key (actual_base) == g.semantic_type_key (target_type) {
11035+ return
11036+ }
11037+ if ! fastc_is_integer_expression_type (actual_base) {
11038+ return g.unsupported ('cast from `${actual_type }` to enum `${target_type }`' )
11039+ }
11040+ if ! in_unsafe {
11041+ return g.unsupported ('cast from `${actual_type }` to enum `${target_type }` outside an `unsafe` block' )
11042+ }
11043+ }
11044+
1097011045fn (g &Parser) primitive_cast_types_are_compatible (actual_type string , target_type string , in_unsafe bool ) bool {
1097111046 if actual_type == target_type {
1097211047 return true
0 commit comments