Skip to content

Commit

Permalink
[Rust] Support more System.Array methods and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave committed Oct 13, 2024
1 parent 69c237f commit 573e28f
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 136 deletions.
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [Rust] Added basic class inheritance support (by @ncave)
* [Rust] Added String.Replace(char, char) and test (by @ncave)
* [Rust] Support type extensions for external types (by @ncave)
* [Rust] Support more System.Array methods and tests (by @ncave)

## 4.22.0 - 2024-10-02

Expand Down
25 changes: 12 additions & 13 deletions src/Fable.Cli/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -489,19 +489,10 @@ and FableCompiler(checker: InteractiveChecker, projCracked: ProjectCracked, fabl

let startInThreadPool toMsg work = postTo toMsg work |> Async.Start

let runSynchronously toMsg work =
postTo toMsg work |> Async.RunSynchronously

let fableCompile state fileName =
let fableProj = state.FableProj

let runner =
// for Rust, sequential compilation captures all imports and namespaces
match projCracked.CliArgs.CompilerOptions.Language with
| Rust -> runSynchronously // sequential file compilation
| _ -> startInThreadPool // parallel file compilation

runner
startInThreadPool
FableFileCompiled
(fun () ->
async {
Expand Down Expand Up @@ -577,6 +568,17 @@ and FableCompiler(checker: InteractiveChecker, projCracked: ProjectCracked, fabl
return! loop state

| FSharpFileTypeChecked file ->
// It seems when there's a pair .fsi/.fs the F# compiler gives the .fsi extension to the implementation file
let fileName = file.FileName |> Path.normalizePath |> Path.ensureFsExtension

// For Rust, delay last file's compilation until other files finish compiling
if
projCracked.CliArgs.CompilerOptions.Language = Rust
&& fileName = Array.last state.FilesToCompile
&& state.FableFilesCompiledCount < state.FableFilesToCompileExpectedCount - 1
then
do! Async.Sleep(100)

Log.verbose (
lazy $"Type checked: {IO.Path.GetRelativePath(projCracked.CliArgs.RootDir, file.FileName)}"
)
Expand All @@ -587,9 +589,6 @@ and FableCompiler(checker: InteractiveChecker, projCracked: ProjectCracked, fabl
let outDir = IO.Path.GetDirectoryName(outPath)
Printers.printAst outDir [ file ]

// It seems when there's a pair .fsi/.fs the F# compiler gives the .fsi extension to the implementation file
let fileName = file.FileName |> Path.normalizePath |> Path.ensureFsExtension

let state =
if not (state.FilesToCompileSet.Contains(fileName)) then
state
Expand Down
24 changes: 13 additions & 11 deletions src/Fable.Transforms/Rust/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ let makeRefFromMutableFunc com ctx r t (value: Expr) = value
let toNativeIndex expr = TypeCast(expr, UNativeInt.Number)

let toLowerFirstWithArgsCountSuffix (args: Expr list) meth =
let argCount = List.length args
let argCount = List.length args - 1 // don't count first arg
let meth = Naming.lowerFirst meth

if argCount > 1 then
Expand Down Expand Up @@ -1185,11 +1185,7 @@ let chars (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr optio

Helper.LibCall(com, "Char", meth, t, args, i.SignatureArgTypes, ?loc = r)
|> Some
| ("GetNumericValue"
// | "GetUnicodeCategory"
| "ConvertToUtf32" as meth),
None,
_ ->
| ("GetNumericValue" | "GetUnicodeCategory" | "ConvertToUtf32" as meth), None, _ ->
let meth = getMethod meth args

Helper.LibCall(com, "Char", meth, t, args, i.SignatureArgTypes, ?loc = r)
Expand Down Expand Up @@ -1641,7 +1637,7 @@ let resizeArrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (this
Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some
| ("BinarySearch" | "CopyTo" | "IndexOf" | "LastIndexOf" | "Reverse") as meth, Some ar, args ->
// methods with some overrides
let meth = meth |> toLowerFirstWithArgsCountSuffix args
let meth = meth |> toLowerFirstWithArgsCountSuffix (ar :: args)
Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some
| "Sort", Some ar, [] -> Helper.LibCall(com, "NativeArray", "sort", t, (ar :: args), ?loc = r) |> Some
| "Sort", Some ar, [ ExprType(DelegateType _) ] ->
Expand Down Expand Up @@ -1728,11 +1724,17 @@ let arrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: E
| "Copy", None, [ _source; _sourceIndex; _target; _targetIndex; _count ] -> copyToArray com r t i args
| "Copy", None, [ source; target; count ] ->
copyToArray com r t i [ source; makeIntConst 0; target; makeIntConst 0; count ]
| "ConvertAll", None, [ source; mapping ] ->
Helper.LibCall(com, "NativeArray", "convertAll", t, args, ?loc = r) |> Some
| "IndexOf", None, [ ar; arg ] -> Helper.LibCall(com, "NativeArray", "indexOf", t, args, ?loc = r) |> Some
| "GetEnumerator", Some ar, _ -> Helper.LibCall(com, "Seq", "Enumerable::ofArray", t, [ ar ], ?loc = r) |> Some
| "Reverse", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "reverse", t, args, ?loc = r) |> Some
| ("ConvertAll" | "Exists" | "GetRange" | "ForEach" | "FindAll" | "Find" | "FindLast" | "FindIndex" | "FindLastIndex" | "TrueForAll") as meth,
None,
args ->
// methods without overrides
let meth = Naming.lowerFirst meth
Helper.LibCall(com, "NativeArray", meth, t, args, ?loc = r) |> Some
| ("BinarySearch" | "CopyTo" | "IndexOf" | "LastIndexOf" | "Reverse") as meth, None, args ->
// methods with some overrides
let meth = meth |> toLowerFirstWithArgsCountSuffix args
Helper.LibCall(com, "NativeArray", meth, t, args, ?loc = r) |> Some
| "Sort", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "sort", t, args, ?loc = r) |> Some
| "Sort", None, [ ar; ExprType(DelegateType _) as comparer ] ->
Helper.LibCall(com, "NativeArray", "sortBy", t, args, ?loc = r) |> Some
Expand Down
151 changes: 80 additions & 71 deletions src/fable-library-rust/src/Char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,39 @@ pub mod Char_ {
use crate::Native_::{compare, Lrc, MutCell, ToString, Vec};
use crate::String_::{getCharAt, length, string, toString};

// // https://docs.microsoft.com/en-us/dotnet/api/system.globalization.unicodecategory?view=net-6.0
// pub mod UnicodeCategory {
// pub const UppercaseLetter: u8 = 0;
// pub const LowercaseLetter: u8 = 1;
// pub const TitlecaseLetter: u8 = 2;
// pub const ModifierLetter: u8 = 3;
// pub const OtherLetter: u8 = 4;
// pub const NonSpacingMark: u8 = 5;
// pub const SpacingCombiningMark: u8 = 6;
// pub const EnclosingMark: u8 = 7;
// pub const DecimalDigitNumber: u8 = 8;
// pub const LetterNumber: u8 = 9;
// pub const OtherNumber: u8 = 10;
// pub const SpaceSeparator: u8 = 11;
// pub const LineSeparator: u8 = 12;
// pub const ParagraphSeparator: u8 = 13;
// pub const Control: u8 = 14;
// pub const Format: u8 = 15;
// pub const Surrogate: u8 = 16;
// pub const PrivateUse: u8 = 17;
// pub const ConnectorPunctuation: u8 = 18;
// pub const DashPunctuation: u8 = 19;
// pub const OpenPunctuation: u8 = 20;
// pub const ClosePunctuation: u8 = 21;
// pub const InitialQuotePunctuation: u8 = 22;
// pub const FinalQuotePunctuation: u8 = 23;
// pub const OtherPunctuation: u8 = 24;
// pub const MathSymbol: u8 = 25;
// pub const CurrencySymbol: u8 = 26;
// pub const ModifierSymbol: u8 = 27;
// pub const OtherSymbol: u8 = 28;
// pub const OtherNotAssigned: u8 = 29;
// }
// https://docs.microsoft.com/en-us/dotnet/api/system.globalization.unicodecategory?view=net-6.0
pub mod UnicodeCategory {
pub const UppercaseLetter: u8 = 0;
pub const LowercaseLetter: u8 = 1;
pub const TitlecaseLetter: u8 = 2;
pub const ModifierLetter: u8 = 3;
pub const OtherLetter: u8 = 4;
pub const NonSpacingMark: u8 = 5;
pub const SpacingCombiningMark: u8 = 6;
pub const EnclosingMark: u8 = 7;
pub const DecimalDigitNumber: u8 = 8;
pub const LetterNumber: u8 = 9;
pub const OtherNumber: u8 = 10;
pub const SpaceSeparator: u8 = 11;
pub const LineSeparator: u8 = 12;
pub const ParagraphSeparator: u8 = 13;
pub const Control: u8 = 14;
pub const Format: u8 = 15;
pub const Surrogate: u8 = 16;
pub const PrivateUse: u8 = 17;
pub const ConnectorPunctuation: u8 = 18;
pub const DashPunctuation: u8 = 19;
pub const OpenPunctuation: u8 = 20;
pub const ClosePunctuation: u8 = 21;
pub const InitialQuotePunctuation: u8 = 22;
pub const FinalQuotePunctuation: u8 = 23;
pub const OtherPunctuation: u8 = 24;
pub const MathSymbol: u8 = 25;
pub const CurrencySymbol: u8 = 26;
pub const ModifierSymbol: u8 = 27;
pub const OtherSymbol: u8 = 28;
pub const OtherNotAssigned: u8 = 29;
}

// The maximum character value.
pub const MaxValue: char = '\u{FFFF}';
Expand Down Expand Up @@ -84,31 +84,31 @@ pub mod Char_ {
// | 1 << UnicodeCategory::LineSeparator
// | 1 << UnicodeCategory::ParagraphSeparator;

// // Contains information about the C0, Basic Latin, C1, and Latin-1 Supplement ranges [ U+0000..U+00FF ], with:
// // - 0x80 bit if set means 'is whitespace'
// // - 0x40 bit if set means 'is uppercase letter'
// // - 0x20 bit if set means 'is lowercase letter'
// // - bottom 5 bits are the of: UnicodeCategory the character
// #[cfg_attr(rustfmt, rustfmt::skip)]
// const Latin1CharInfo: &[u8; 256] = &[
// // 0 1 2 3 4 5 6 7 8 9 A B C D E F
// 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x0E, 0x0E, // U+0000..U+000F
// 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0010..U+001F
// 0x8B, 0x18, 0x18, 0x18, 0x1A, 0x18, 0x18, 0x18, 0x14, 0x15, 0x18, 0x19, 0x18, 0x13, 0x18, 0x18, // U+0020..U+002F
// 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x18, 0x19, 0x19, 0x19, 0x18, // U+0030..U+003F
// 0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // U+0040..U+004F
// 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x14, 0x18, 0x15, 0x1B, 0x12, // U+0050..U+005F
// 0x1B, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+0060..U+006F
// 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x14, 0x19, 0x15, 0x19, 0x0E, // U+0070..U+007F
// 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x8E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0080..U+008F
// 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0090..U+009F
// 0x8B, 0x18, 0x1A, 0x1A, 0x1A, 0x1A, 0x1C, 0x18, 0x1B, 0x1C, 0x04, 0x16, 0x19, 0x0F, 0x1C, 0x1B, // U+00A0..U+00AF
// 0x1C, 0x19, 0x0A, 0x0A, 0x1B, 0x21, 0x18, 0x18, 0x1B, 0x0A, 0x04, 0x17, 0x0A, 0x0A, 0x0A, 0x18, // U+00B0..U+00BF
// 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // U+00C0..U+00CF
// 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, // U+00D0..U+00DF
// 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+00E0..U+00EF
// 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x19, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+00F0..U+00FF
// ];
// Contains information about the C0, Basic Latin, C1, and Latin-1 Supplement ranges [ U+0000..U+00FF ], with:
// - 0x80 bit if set means 'is whitespace'
// - 0x40 bit if set means 'is uppercase letter'
// - 0x20 bit if set means 'is lowercase letter'
// - bottom 5 bits are the of: UnicodeCategory the character
#[cfg_attr(rustfmt, rustfmt::skip)]
const Latin1CharInfo: &[u8; 256] = &[
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x0E, 0x0E, // U+0000..U+000F
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0010..U+001F
0x8B, 0x18, 0x18, 0x18, 0x1A, 0x18, 0x18, 0x18, 0x14, 0x15, 0x18, 0x19, 0x18, 0x13, 0x18, 0x18, // U+0020..U+002F
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x18, 0x19, 0x19, 0x19, 0x18, // U+0030..U+003F
0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // U+0040..U+004F
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x14, 0x18, 0x15, 0x1B, 0x12, // U+0050..U+005F
0x1B, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+0060..U+006F
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x14, 0x19, 0x15, 0x19, 0x0E, // U+0070..U+007F
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x8E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0080..U+008F
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, // U+0090..U+009F
0x8B, 0x18, 0x1A, 0x1A, 0x1A, 0x1A, 0x1C, 0x18, 0x1B, 0x1C, 0x04, 0x16, 0x19, 0x0F, 0x1C, 0x1B, // U+00A0..U+00AF
0x1C, 0x19, 0x0A, 0x0A, 0x1B, 0x21, 0x18, 0x18, 0x1B, 0x0A, 0x04, 0x17, 0x0A, 0x0A, 0x0A, 0x18, // U+00B0..U+00BF
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // U+00C0..U+00CF
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, // U+00D0..U+00DF
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+00E0..U+00EF
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x19, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // U+00F0..U+00FF
];

// true for all characters below or equal U+00ff, which is ASCII + Latin-1 Supplement.
#[inline]
Expand All @@ -121,19 +121,28 @@ pub mod Char_ {
// ((1 << uc) & uc_mask) != 0
// }

// pub fn GetUnicodeCategory(c: char) -> u8 {
// if (isLatin1(c)) {
// (Latin1CharInfo[c as usize] & UnicodeCategoryMask)
// } else {
// //TODO: implement this
// 0
// }
// }

// pub fn GetUnicodeCategory_2(s: string, index: i32) -> u8 {
// let c: char = getCharAt(s, index);
// GetUnicodeCategory(c)
// }
pub fn GetUnicodeCategory(c: char) -> i32 {
let category = if (isLatin1(c)) {
(Latin1CharInfo[c as usize] & UnicodeCategoryMask)
} else {
match c {
// very incomplete, TODO: get real unicode categories
c if IsUpper(c) => UnicodeCategory::UppercaseLetter,
c if IsLower(c) => UnicodeCategory::LowercaseLetter,
c if IsLetter(c) => UnicodeCategory::OtherLetter,
c if IsDigit(c) => UnicodeCategory::DecimalDigitNumber,
c if IsControl(c) => UnicodeCategory::Control,
c if IsSurrogate(c) => UnicodeCategory::Surrogate,
c => UnicodeCategory::OtherNotAssigned,
}
};
category as i32
}

pub fn GetUnicodeCategory_2(s: string, index: i32) -> i32 {
let c: char = getCharAt(s, index);
GetUnicodeCategory(c)
}

pub fn GetNumericValue(c: char) -> f64 {
match c.to_digit(10) {
Expand Down
2 changes: 1 addition & 1 deletion src/fable-library-rust/src/String.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ pub mod String_ {
}

pub fn splitStrings(s: string, ps: Array<string>, options: i32) -> Array<string> {
let mut a: Vec<&str> = vec![s.as_str()];
let mut a: Vec<&str> = [s.as_str()].into_iter().collect();
for p in ps.iter() {
a = a.iter().flat_map(|&s| s.split(p.as_str())).collect();
}
Expand Down
5 changes: 3 additions & 2 deletions src/fable-standalone/test/bench-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"prebuild-cli-js": "npm run clean && FABLE=fable-cli npm run build-lib-ts",
"build-cli-js": "npm run fable-cli -- src/bench-compiler.fsproj --outDir ./out-node --fableLib ./out-lib-js",
"postbuild-cli-js": "npm run rollup-bundle",
"build-cli-rust": "npm run fable-cli -- src/bench-compiler.fsproj --outDir ./out-rust --lang Rust --noCache --noParallelTypeCheck --test:MSBuildCracker",
"build-cli-rust": "npm run fable-cli -- src/bench-compiler.fsproj --outDir ./out-rust --lang Rust --noCache --test:MSBuildCracker",

"fable": "dotnet run -c Release --project src/bench-compiler.fsproj",
"prebuild-js": "npm run clean && FABLE=fable npm run build-lib-ts",
Expand Down Expand Up @@ -98,7 +98,8 @@
"speedscope": "speedscope profile.v8log.json",
"flamegraph": "perf script | ../../../../../FlameGraph/stackcollapse-perf.pl | ../../../../../FlameGraph/flamegraph.pl > perf.svg",
"trace-node": "node --trace-deopt out-node/app.js src/bench-compiler.fsproj --outDir ./out-node2 > deopt.log",
"trace-rust": "dotnet trace collect --duration 00:00:01:00 --format speedscope -- dotnet src/bin/Release/net8.0/bench-compiler.dll ../../../../tests/Rust/Fable.Tests.Rust.fsproj --outDir ./out-tests-rust --fableLib ./out-lib-rust --lang Rust",
"trace-rust": "dotnet trace collect --duration 00:00:03:00 --format speedscope -- dotnet src/bin/Release/net8.0/bench-compiler.dll src/bench-compiler.fsproj --outDir ./out-rust2 --fableLib ./out-lib-rust --lang Rust",
"trace-rust-tests": "dotnet trace collect --duration 00:00:01:00 --format speedscope -- dotnet src/bin/Release/net8.0/bench-compiler.dll ../../../../tests/Rust/Fable.Tests.Rust.fsproj --outDir ./out-tests-rust --fableLib ./out-lib-rust --lang Rust",
"heaptrack-native": "heaptrack ./src/bin/Release/net8.0/linux-x64/native/bench-compiler src/bench-compiler.fsproj --outDir ./out-node2 --benchmark",
"heaptrack-print": "heaptrack_print heaptrack.*.gz -F heap_alloc.log",
"heaptrack-flamegraph": "../../../../../FlameGraph/flamegraph.pl --title \"heaptrack: allocations\" --colors mem --countname allocations < heap_alloc.log > heap_alloc.svg",
Expand Down
3 changes: 2 additions & 1 deletion src/fable-standalone/test/bench-compiler/src/app.fs
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,9 @@ let parseFiles projectFileName options =
for fileName in fileNames do

// transform F# AST to target language AST
printf $"File: %s{fileName}"
let res, ms2 = measureTime parseFable (parseRes, fileName)
printfn $"File: %s{fileName}, Fable time: %d{ms2} ms"
printfn $", Fable time: %d{ms2} ms"
res.FableErrors |> printErrors showWarnings

// get output path
Expand Down
Loading

0 comments on commit 573e28f

Please sign in to comment.