@@ -14,7 +14,7 @@ type Import =
14
14
{ Selector: string
15
15
LocalIdent: string
16
16
ModuleName: string
17
- FullPath : string
17
+ ModulePath : string
18
18
Path: string }
19
19
20
20
type ITailCallOpportunity =
@@ -627,12 +627,14 @@ module TypeInfo =
627
627
| [:? string as macro] -> Some macro
628
628
| _ -> None
629
629
else None)
630
+
630
631
type PointerType =
631
632
| Rc
632
633
| Arc
634
+
633
635
let (| HasReferenceTypeAttribute | _ |) ( ent : Fable.Entity ) =
634
636
ent.Attributes |> Seq.tryPick ( fun att ->
635
- if att.Entity.FullName.StartsWith( Atts.refType ) then
637
+ if att.Entity.FullName.StartsWith( Atts.referenceType ) then
636
638
match att.ConstructorArgs with
637
639
| [:? int as ptrType] ->
638
640
match ptrType with
@@ -2691,15 +2693,18 @@ module Util =
2691
2693
let relPath = Fable.Path.getRelativeFileOrDirPath false com.CurrentFile false filePath
2692
2694
com.GetImportName( ctx, " *" , relPath, None) |> ignore
2693
2695
)
2694
- let makeModItems ( fullPath , moduleName ) =
2695
- let importPath = Fable.Path.getRelativePath com.CurrentFile fullPath
2696
- let attrs = [ mkEqAttr " path" importPath ]
2696
+ let makeModItems ( modulePath , moduleName ) =
2697
+ let relPath = Fable.Path.getRelativePath com.CurrentFile modulePath
2698
+ let attrs = [ mkEqAttr " path" relPath ]
2697
2699
let modItem = mkUnloadedModItem attrs moduleName
2698
2700
let useItem = mkGlobUseItem [] [ moduleName]
2699
2701
if isFableLibrary com
2700
2702
then [ modItem; useItem |> mkPublicItem] // export modules at top level
2701
2703
else [ modItem]
2702
- let modItems = com.GetAllModules() |> List.sortBy fst |> List.collect makeModItems
2704
+ let modItems =
2705
+ com.GetAllModules()
2706
+ |> List.sortBy fst
2707
+ |> List.collect makeModItems
2703
2708
modItems
2704
2709
else []
2705
2710
@@ -2709,14 +2714,14 @@ module Util =
2709
2714
| Some path ->
2710
2715
// add some imports for main
2711
2716
let asStr = getLibraryImportName com ctx " String" " string"
2712
- let asArr = getLibraryImportName com ctx " Native" " arrayFrom "
2717
+ let asArr = getLibraryImportName com ctx " Native" " array "
2713
2718
2714
2719
// main entrypoint
2715
2720
let mainName = String.concat " ::" path
2716
2721
let strBody = [
2717
2722
$" let args: Vec<String> = std::env::args().collect()"
2718
2723
$" let args: Vec<Rc<str>> = args[1..].iter().map(|s| {asStr}(s)).collect()"
2719
- $" {mainName}({asArr}(& args))"
2724
+ $" {mainName}({asArr}(args))"
2720
2725
]
2721
2726
let fnBody = strBody |> Seq.map mkEmitSemiStmt |> mkBlock |> Some
2722
2727
@@ -3643,14 +3648,18 @@ module Util =
3643
3648
3644
3649
match decl with
3645
3650
| Fable.ModuleDeclaration decl ->
3646
- // TODO: perhaps collect other use decls from usage in body
3647
- let useItem = mkGlobUseItem [] [ " super" ]
3648
- let useDecls = [ useItem]
3649
3651
let memberDecls = decl.Members |> List.collect ( transformDecl com ctx)
3650
- let attrs = []
3651
- let modDecls = useDecls @ memberDecls
3652
- let modItem = modDecls |> mkModItem attrs decl.Name
3653
- [ modItem |> mkPublicItem]
3652
+ if List.isEmpty memberDecls then
3653
+ [] // don't output empty modules
3654
+ else
3655
+ // TODO: perhaps collect other use decls from usage in body
3656
+ let useItem = mkGlobUseItem [] [ " super" ]
3657
+ let useDecls = [ useItem]
3658
+ let attrs = []
3659
+ let modDecls = useDecls @ memberDecls
3660
+ let modItem = modDecls |> mkModItem attrs decl.Name
3661
+ [ modItem |> mkPublicItem]
3662
+
3654
3663
3655
3664
| Fable.ActionDeclaration decl ->
3656
3665
// TODO: use ItemKind.Static with IIFE closure?
@@ -3668,34 +3677,50 @@ module Util =
3668
3677
| Fable.ClassDeclaration decl ->
3669
3678
transformClassDecl com ctx decl
3670
3679
3671
- let getImportFullPath ( com : IRustCompiler ) ( path : string ) =
3672
- let isAbsolutePath =
3673
- path.StartsWith( " /" ) || path.StartsWith( " \\ " ) || path.IndexOf( " :" ) = 1
3674
- let isLibraryPath =
3675
- path.StartsWith( com.LibraryDir)
3676
- if isAbsolutePath || isLibraryPath then
3677
- Fable.Path.normalizePath path
3678
- else
3679
- let currentDir = Fable.Path.GetDirectoryName( com.CurrentFile)
3680
- Fable.Path.Combine( currentDir, path)
3681
- |> Fable.Path.normalizeFullPath
3680
+ // F# hash function is unstable and gives different results in different runs
3681
+ // Taken from fable-library/Util.ts. Possible variant in https://stackoverflow.com/a/1660613
3682
+ let stableStringHash ( s : string ) =
3683
+ let mutable h = 5381
3684
+ for i = 0 to s.Length - 1 do
3685
+ h <- ( h * 33 ) ^^^ ( int s.[ i])
3686
+ h
3682
3687
3683
3688
let isFableLibrary ( com : IRustCompiler ) =
3684
3689
List.contains " FABLE_LIBRARY" com.Options.Define //TODO: look in project defines too
3685
3690
3686
- let isFableLibraryImport ( com : IRustCompiler ) ( path : string ) =
3687
- not ( isFableLibrary com) && path.StartsWith( com.LibraryDir)
3691
+ let isFableLibraryPath ( com : IRustCompiler ) ( path : string ) =
3692
+ not ( isFableLibrary com) && ( path.StartsWith( com.LibraryDir) || path = " fable_library_rust" )
3693
+
3694
+ let getImportModulePath ( com : IRustCompiler ) ( path : string ) =
3695
+ let isAbsolutePath =
3696
+ path.StartsWith( " /" ) || path.StartsWith( " \\ " ) || path.IndexOf( " :" ) = 1
3697
+ let modulePath =
3698
+ if isAbsolutePath || ( isFableLibraryPath com path) then
3699
+ Fable.Path.normalizePath path
3700
+ else
3701
+ let currentDir = Fable.Path.GetDirectoryName( com.CurrentFile)
3702
+ Fable.Path.Combine( currentDir, path)
3703
+ |> Fable.Path.normalizeFullPath
3704
+ modulePath
3705
+
3706
+ let getImportModuleName ( com : IRustCompiler ) ( modulePath : string ) =
3707
+ System.String.Format( " module_{0:x}" , stableStringHash modulePath)
3688
3708
3689
3709
let transformImports ( com : IRustCompiler ) ctx ( imports : Import list ): Rust.Item list =
3690
3710
imports
3691
- |> List.groupBy ( fun import -> import.FullPath)
3692
- |> List.collect ( fun ( _fullPath , moduleImports ) ->
3711
+ |> List.groupBy ( fun import -> import.ModulePath)
3712
+ |> List.sortBy ( fun ( modulePath , _ ) -> modulePath)
3713
+ |> List.collect ( fun ( _modulePath , moduleImports ) ->
3693
3714
moduleImports
3715
+ |> List.sortBy ( fun import -> import.Selector)
3694
3716
|> List.map ( fun import ->
3695
3717
let modPath =
3696
- if isFableLibraryImport com import.Path
3697
- then [ " fable_library_rust" ]
3698
- else [ " crate" ; import.ModuleName]
3718
+ if import.Path.Length = 0
3719
+ then [] // empty path, means direct import of the selector
3720
+ else
3721
+ if isFableLibraryPath com import.Path
3722
+ then [ " fable_library_rust" ]
3723
+ else [ " crate" ; import.ModuleName]
3699
3724
match import.Selector with
3700
3725
| " " | " *" | " default" ->
3701
3726
mkGlobUseItem [] modPath
@@ -3715,24 +3740,13 @@ module Util =
3715
3740
| _ -> splitFullName selector |> List.last
3716
3741
|> getUniqueNameInRootScope ctx
3717
3742
3718
- // F# hash function is unstable and gives different results in different runs
3719
- // Taken from fable-library/Util.ts. Possible variant in https://stackoverflow.com/a/1660613
3720
- let stableStringHash ( s : string ) =
3721
- let mutable h = 5381
3722
- for i = 0 to s.Length - 1 do
3723
- h <- ( h * 33 ) ^^^ ( int s.[ i])
3724
- h
3725
-
3726
- let getModuleName fullPath =
3727
- System.String.Format( " module_{0:x}" , stableStringHash fullPath)
3728
-
3729
3743
3730
3744
module Compiler =
3731
3745
open System.Collections .Generic
3732
3746
open System.Collections .Concurrent
3733
3747
open Util
3734
3748
3735
- // global level (across files)
3749
+ // global list of import modules (across files)
3736
3750
let importModules = ConcurrentDictionary< string, string>()
3737
3751
3738
3752
// per file
@@ -3745,42 +3759,42 @@ module Compiler =
3745
3759
if onlyOnceWarnings.Add( msg) then
3746
3760
addWarning com [] range msg
3747
3761
3748
- member this .GetImportName( ctx , selector , path , r ) =
3762
+ member self .GetImportName( ctx , selector , path , r ) =
3749
3763
if selector = Fable.Naming.placeholder then
3750
3764
" `importMember` must be assigned to a variable"
3751
3765
|> addError com [] r
3752
3766
let path = path |> Fable.Naming.replaceSuffix " .fs" " .rs"
3753
- if path.Contains( " ::" ) then
3754
- path + " ::" + selector // direct Rust import
3755
- else
3756
- let cacheKey = path + " ::" + selector
3757
- let import =
3758
- match imports.TryGetValue( cacheKey) with
3759
- | true , import -> import
3760
- | false , _ ->
3761
- let fullPath = getImportFullPath this path
3762
- let localIdent = getIdentForImport ctx path selector
3763
- let moduleName = getModuleName fullPath
3764
- let import = {
3765
- Selector = selector
3766
- LocalIdent = localIdent
3767
- ModuleName = moduleName
3768
- FullPath = fullPath
3769
- Path = path
3770
- }
3771
- if not ( isFableLibraryImport this path) then
3772
- importModules.TryAdd( fullPath, moduleName) |> ignore
3773
- imports.Add( cacheKey, import)
3774
- import
3775
- $" {import.LocalIdent}"
3767
+ let cacheKey =
3768
+ if ( isFableLibraryPath self path)
3769
+ then " fable_library_rust::" + selector
3770
+ elif path.Length = 0 then selector
3771
+ else path + " ::" + selector
3772
+ let import =
3773
+ match imports.TryGetValue( cacheKey) with
3774
+ | true , import -> import
3775
+ | false , _ ->
3776
+ let localIdent = getIdentForImport ctx path selector
3777
+ let modulePath = getImportModulePath self path
3778
+ let moduleName = getImportModuleName self modulePath
3779
+ let import = {
3780
+ Selector = selector
3781
+ LocalIdent = localIdent
3782
+ ModuleName = moduleName
3783
+ ModulePath = modulePath
3784
+ Path = path
3785
+ }
3786
+ // add import module to a global list (across files)
3787
+ if path.Length > 0 && not ( isFableLibraryPath self path) then
3788
+ importModules.TryAdd( modulePath, moduleName) |> ignore
3789
+
3790
+ imports.Add( cacheKey, import)
3791
+ import
3792
+ $" {import.LocalIdent}"
3776
3793
3777
3794
member _.GetAllImports () = imports.Values |> Seq.toList
3778
3795
member _.GetAllModules () = importModules |> Seq.map ( fun p -> p.Key, p.Value) |> Seq.toList
3779
3796
3780
- member this.TransformAsExpr ( ctx , e ) = transformAsExpr this ctx e
3781
- // member this.TransformAsStatements(ctx, ret, e) = transformAsStatements this ctx ret e
3782
- // member this.TransformFunction(ctx, name, args, body) = transformFunction this ctx name args body
3783
- // member this.TransformImport(ctx, selector, path) = transformImport this ctx None selector path
3797
+ member self.TransformAsExpr ( ctx , e ) = transformAsExpr self ctx e
3784
3798
3785
3799
member _.GetEntity ( fullName ) =
3786
3800
match com.TryGetEntity( fullName) with
0 commit comments