Skip to content

Commit

Permalink
Merge pull request #1615 from ncave/flow
Browse files Browse the repository at this point in the history
Adding Babel types
  • Loading branch information
MangelMaxime authored May 6, 2020
2 parents f9b86cd + b23f9f4 commit 99bc5a4
Show file tree
Hide file tree
Showing 21 changed files with 824 additions and 274 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"name": "bench-compile (Node)",
"program": "${workspaceRoot}/src/fable-standalone/test/bench-compiler/out-node/app.js",
// "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests", "--commonjs"],
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--commonjs", "--optimize-fcs"],
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--typescript"],
"cwd": "${workspaceRoot}/src/fable-standalone/test/bench-compiler"
},
{
Expand All @@ -59,7 +59,7 @@
"name": "bench-compile (.NET)",
"program": "${workspaceFolder}/src/fable-standalone/test/bench-compiler/bin/Debug/netcoreapp2.1/bench-compiler.dll",
// "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests", "--commonjs"],
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--commonjs", "--optimize-fcs"],
"args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--typescript"],
"cwd": "${workspaceFolder}/src/fable-standalone/test/bench-compiler"
},
{
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Cli/Parser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ let private parseDic (key: string) (o: JObject): IDictionary<string,string> =
let toCompilerOptions (msg: Message): CompilerOptions =
{ typedArrays = msg.typedArrays
clampByteArrays = msg.clampByteArrays
typeDecls = msg.extra.ContainsKey("typescript")
debugMode = Array.contains "DEBUG" msg.define
verbosity = GlobalParams.Singleton.Verbosity
outputPublicInlinedFunctions = Array.contains "FABLE_REPL_LIB" msg.define
Expand Down
261 changes: 195 additions & 66 deletions src/Fable.Transforms/AST/AST.Babel.fs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,15 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr =
| BasicPatterns.DefaultValue (FableType com ctx typ) ->
return Replacements.defaultof com ctx typ

// Capture variable generic type mapping
| BasicPatterns.Let((var, value), (BasicPatterns.Application(_body, genArgs, _args) as expr)) ->
let genArgs = Seq.map (makeType com ctx.GenericArgs) genArgs
let ctx = { ctx with GenericArgs = matchGenericParamsFrom var genArgs |> Map }
let! value = transformExpr com ctx value
let ctx, ident = putBindingInScope com ctx var value
let! body = transformExpr com ctx expr
return Fable.Let([ident, value], body)

// Assignments
| BasicPatterns.Let((var, value), body) ->
if isInline var then
Expand Down
626 changes: 496 additions & 130 deletions src/Fable.Transforms/Fable2Babel.fs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Fable.Transforms/Global/Compiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type Verbosity =
type CompilerOptions =
{ typedArrays: bool
clampByteArrays: bool
typeDecls: bool
debugMode: bool
verbosity: Verbosity
/// Meant for precompiled libraries (like the Repl Lib)
Expand Down
2 changes: 1 addition & 1 deletion src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,7 @@ let types (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr optio
let fsharpType methName (r: SourceLocation option) t (i: CallInfo) (args: Expr list) =
match methName with
| "MakeTupleType" ->
Helper.CoreCall("Reflection", "tuple", t, args, i.SignatureArgTypes, hasSpread=true, ?loc=r) |> Some
Helper.CoreCall("Reflection", "tuple_type", t, args, i.SignatureArgTypes, hasSpread=true, ?loc=r) |> Some
// Prevent name clash with FSharpValue.GetRecordFields
| "GetRecordFields" ->
Helper.CoreCall("Reflection", "getRecordElements", t, args, i.SignatureArgTypes, ?loc=r) |> Some
Expand Down
3 changes: 2 additions & 1 deletion src/fable-compiler-js/src/Platform.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ open Fable.Core.JsInterop
type CmdLineOptions = {
commonjs: bool
optimize: bool
watchMode: bool
sourceMaps: bool
typeDecls: bool
watchMode: bool
}

module JS =
Expand Down
12 changes: 10 additions & 2 deletions src/fable-compiler-js/src/app.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ let printErrors showWarnings (errors: Fable.Standalone.Error[]) =
errors |> Array.iter printError
failwith "Too many errors."

let toFableCompilerConfig (options: CmdLineOptions): Fable.Standalone.CompilerConfig =
{ typedArrays = not (options.typeDecls)
clampByteArrays = false
typeDecls = options.typeDecls
precompiledLib = None }

let parseFiles projectFileName outDir options =
// parse project
let (dllRefs, fileNames, otherOptions) = parseProject projectFileName
Expand Down Expand Up @@ -64,7 +70,8 @@ let parseFiles projectFileName outDir options =

// Fable (F# to Babel)
let fableLibraryDir = "fable-library"
let parseFable (res, fileName) = fable.CompileToBabelAst(fableLibraryDir, res, fileName)
let fableConfig = options |> toFableCompilerConfig
let parseFable (res, fileName) = fable.CompileToBabelAst(fableLibraryDir, res, fileName, fableConfig)
let trimPath (path: string) = path.Replace("../", "").Replace("./", "").Replace(":", "")
let projDir = projectFileName |> normalizeFullPath |> Path.GetDirectoryName
let libDir = getFableLibDir() |> normalizeFullPath
Expand All @@ -89,8 +96,9 @@ let run opts projectFileName outDir =
let options = {
commonjs = Option.isSome commandToRun || opts |> Array.contains "--commonjs"
optimize = opts |> Array.contains "--optimize-fcs"
watchMode = opts |> Array.contains "--watch"
sourceMaps = opts |> Array.contains "--sourceMaps"
typeDecls = opts |> Array.contains "--typescript"
watchMode = opts |> Array.contains "--watch"
}
parseFiles projectFileName outDir options
commandToRun |> Option.iter runCmdAndExitIfFails
Expand Down
2 changes: 1 addition & 1 deletion src/fable-compiler-js/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function transformAndSaveBabelAst(babelAst, filePath, projDir, outDir, li
// this solves a weird commonjs issue where some imports are not properly qualified
babelAst = JSON.parse(serializeToJson(babelAst)); // somehow this helps with that
const sourcePath = babelAst.fileName;
const jsPath = filePath.replace(FSHARP_EXT, ".js");
const jsPath = filePath.replace(FSHARP_EXT, options.typeDecls ? ".ts" : ".js");
let outPath = Path.resolve(outDir, jsPath);
outPath = ensureUniquePath(sourcePath, outPath);
ensureDirExists(Path.dirname(outPath));
Expand Down
2 changes: 1 addition & 1 deletion src/fable-library/FSharp.Core.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module Operators =
let nullArg x = raise(System.ArgumentNullException(x))

[<CompiledName("Using")>]
let using (resource : 'T when 'T :> System.IDisposable) (action: 'T -> 'a) =
let using (resource: System.IDisposable) action =
try action(resource)
finally match (box resource) with null -> () | _ -> resource.Dispose()

Expand Down
7 changes: 0 additions & 7 deletions src/fable-library/Map.d.ts

This file was deleted.

52 changes: 26 additions & 26 deletions src/fable-library/Reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,25 @@ export function compare(t1: TypeInfo, t2: TypeInfo): number {
}
}

export function type(fullname: string, generics?: TypeInfo[]): TypeInfo {
export function generic_type(fullname: string, generics?: TypeInfo[]): TypeInfo {
return new TypeInfo(fullname, generics);
}

export function record(
export function record_type(
fullname: string,
generics: TypeInfo[],
constructor: Constructor,
fields: () => FieldInfo[]): TypeInfo {
return new TypeInfo(fullname, generics, constructor, fields);
}

export function anonRecord(...fields: FieldInfo[]): TypeInfo {
export function anonRecord_type(...fields: FieldInfo[]): TypeInfo {
return new TypeInfo("", undefined, undefined, () => fields);
}

export type CaseInfoInput = string | [string, FieldInfo[]];

export function union(
export function union_type(
fullname: string,
generics: TypeInfo[],
constructor: Constructor,
Expand All @@ -93,48 +93,48 @@ export function union(
return t;
}

export function tuple(...generics: TypeInfo[]): TypeInfo {
export function tuple_type(...generics: TypeInfo[]): TypeInfo {
return new TypeInfo("System.Tuple`" + generics.length, generics);
}

export function delegate(...generics: TypeInfo[]): TypeInfo {
export function delegate_type(...generics: TypeInfo[]): TypeInfo {
return new TypeInfo("System.Func`" + generics.length, generics);
}

export function lambda(argType: TypeInfo, returnType: TypeInfo): TypeInfo {
export function lambda_type(argType: TypeInfo, returnType: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Core.FSharpFunc`2", [argType, returnType]);
}

export function option(generic: TypeInfo): TypeInfo {
export function option_type(generic: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Core.FSharpOption`1", [generic]);
}

export function list(generic: TypeInfo): TypeInfo {
export function list_type(generic: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Collections.FSharpList`1", [generic]);
}

export function array(generic: TypeInfo): TypeInfo {
export function array_type(generic: TypeInfo): TypeInfo {
return new TypeInfo(generic.fullname + "[]", [generic]);
}

export function enumType(fullname: string, underlyingType: TypeInfo, enumCases: EnumCase[]): TypeInfo {
export function enum_type(fullname: string, underlyingType: TypeInfo, enumCases: EnumCase[]): TypeInfo {
return new TypeInfo(fullname, [underlyingType], undefined, undefined, undefined, enumCases);
}

export const obj: TypeInfo = new TypeInfo("System.Object");
export const unit: TypeInfo = new TypeInfo("Microsoft.FSharp.Core.Unit");
export const char: TypeInfo = new TypeInfo("System.Char");
export const string: TypeInfo = new TypeInfo("System.String");
export const bool: TypeInfo = new TypeInfo("System.Boolean");
export const int8: TypeInfo = new TypeInfo("System.SByte");
export const uint8: TypeInfo = new TypeInfo("System.Byte");
export const int16: TypeInfo = new TypeInfo("System.Int16");
export const uint16: TypeInfo = new TypeInfo("System.UInt16");
export const int32: TypeInfo = new TypeInfo("System.Int32");
export const uint32: TypeInfo = new TypeInfo("System.UInt32");
export const float32: TypeInfo = new TypeInfo("System.Single");
export const float64: TypeInfo = new TypeInfo("System.Double");
export const decimal: TypeInfo = new TypeInfo("System.Decimal");
export const obj_type: TypeInfo = new TypeInfo("System.Object");
export const unit_type: TypeInfo = new TypeInfo("Microsoft.FSharp.Core.Unit");
export const char_type: TypeInfo = new TypeInfo("System.Char");
export const string_type: TypeInfo = new TypeInfo("System.String");
export const bool_type: TypeInfo = new TypeInfo("System.Boolean");
export const int8_type: TypeInfo = new TypeInfo("System.SByte");
export const uint8_type: TypeInfo = new TypeInfo("System.Byte");
export const int16_type: TypeInfo = new TypeInfo("System.Int16");
export const uint16_type: TypeInfo = new TypeInfo("System.UInt16");
export const int32_type: TypeInfo = new TypeInfo("System.Int32");
export const uint32_type: TypeInfo = new TypeInfo("System.UInt32");
export const float32_type: TypeInfo = new TypeInfo("System.Single");
export const float64_type: TypeInfo = new TypeInfo("System.Double");
export const decimal_type: TypeInfo = new TypeInfo("System.Decimal");

export function name(info: FieldInfo | CaseInfo | TypeInfo): string {
if (Array.isArray(info)) {
Expand Down Expand Up @@ -182,7 +182,7 @@ export function isEnum(t: TypeInfo) {
* but it should be enough for type comparison purposes
*/
export function getGenericTypeDefinition(t: TypeInfo) {
return t.generics == null ? t : new TypeInfo(t.fullname, t.generics.map(() => obj));
return t.generics == null ? t : new TypeInfo(t.fullname, t.generics.map(() => obj_type));
}

export function getEnumUnderlyingType(t: TypeInfo) {
Expand Down
7 changes: 0 additions & 7 deletions src/fable-library/Set.d.ts

This file was deleted.

9 changes: 8 additions & 1 deletion src/fable-standalone/src/Interfaces.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ type IBabelResult =
abstract BabelAst: obj
abstract FableErrors: Error[]

type CompilerConfig =
{ typedArrays: bool
clampByteArrays: bool
typeDecls: bool
precompiledLib: (string -> (string * string) option) option
}

type IFableManager =
abstract CreateChecker: references: string[] * readAllBytes: (string -> byte[]) * otherOptions: string[] -> IChecker
abstract ClearParseCaches: checker: IChecker -> unit
Expand All @@ -57,5 +64,5 @@ type IFableManager =
abstract GetDeclarationLocation: parseResults: IParseResults * line: int * col: int * lineText: string -> Async<Range option>
abstract GetToolTipText: parseResults: IParseResults * line: int * col: int * lineText: string -> Async<string[]>
abstract GetCompletionsAtLocation: parseResults: IParseResults * line: int * col: int * lineText: string -> Async<Completion[]>
abstract CompileToBabelAst: fableLibrary: string * parseResults: IParseResults * fileName: string * ?precompiledLib: (string->(string*string) option) -> IBabelResult
abstract CompileToBabelAst: fableLibrary: string * parseResults: IParseResults * fileName: string * ?config: CompilerConfig -> IBabelResult
abstract FSharpAstToString: parseResults: IParseResults * fileName: string -> string
31 changes: 19 additions & 12 deletions src/fable-standalone/src/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,22 @@ let getCompletionsAtLocation (parseResults: ParseResults) (line: int) (col: int)
return [||]
}

let makeCompiler fableLibrary fileName (project: Project) precompiledLib (otherFSharpOptions: string[]) =
let options: Fable.CompilerOptions =
{ typedArrays = true
clampByteArrays = false
debugMode = otherFSharpOptions |> Array.exists (fun x -> x = "--define:DEBUG" || x = "-d:DEBUG")
verbosity = Fable.Verbosity.Normal
outputPublicInlinedFunctions = false
precompiledLib = precompiledLib }
let com = Compiler(fileName, project, options, fableLibrary)
com
let defaultCompilerConfig: CompilerConfig =
{ typedArrays = true
clampByteArrays = false
typeDecls = false
precompiledLib = None }

let makeCompilerOptions (config: CompilerConfig option) (otherFSharpOptions: string[]): Fable.CompilerOptions =
let config = defaultArg config defaultCompilerConfig
let isDebug = otherFSharpOptions |> Array.exists (fun x -> x = "--define:DEBUG" || x = "-d:DEBUG")
{ typedArrays = config.typedArrays
clampByteArrays = config.clampByteArrays
typeDecls = config.typeDecls
debugMode = isDebug
verbosity = Fable.Verbosity.Normal
outputPublicInlinedFunctions = false
precompiledLib = config.precompiledLib }

let compileAst (com: Compiler) (project: Project) =
FSharp2Fable.Compiler.transformFile com project.ImplementationFiles
Expand Down Expand Up @@ -270,10 +276,11 @@ let init () =
let res = parseResults :?> ParseResults
getCompletionsAtLocation res line col lineText

member __.CompileToBabelAst(fableLibrary:string, parseResults:IParseResults, fileName:string, ?precompiledLib) =
member __.CompileToBabelAst(fableLibrary:string, parseResults:IParseResults, fileName:string, ?config) =
let res = parseResults :?> ParseResults
let project = res.GetProject()
let com = makeCompiler fableLibrary fileName project precompiledLib parseResults.OtherFSharpOptions
let options = makeCompilerOptions config parseResults.OtherFSharpOptions
let com = Compiler(fileName, project, options, fableLibrary)
let ast = compileAst com project
let errors =
com.GetLogs()
Expand Down
10 changes: 9 additions & 1 deletion src/fable-standalone/src/Worker/Worker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,19 @@ let rec loop (box: MailboxProcessor<WorkerRequest>) (state: State) = async {

| Some fable, CompileCode(fsharpCode, otherFSharpOptions) ->
try
// detect (and remove) a passed non-F# compiler option to avoid changing msg contract
let useTypeDeclarations = otherFSharpOptions |> Array.contains "--typescript"
let otherFSharpOptions = otherFSharpOptions |> Array.filter ((<>) "--typescript")
// Check if we need to recreate the FableState because otherFSharpOptions have changed
let! fable = makeFableState (Initialized fable) otherFSharpOptions
let (parseResults, parsingTime) = measureTime (fun () -> fable.Manager.ParseFSharpScript(fable.Checker, FILE_NAME, fsharpCode, otherFSharpOptions)) ()
let (res, fableTransformTime) = measureTime (fun () ->
fable.Manager.CompileToBabelAst("fable-library", parseResults, FILE_NAME, fun x -> resolveLibCall(fable.LibMap, x))) ()
let fableConfig =
{ typedArrays = true
clampByteArrays = false
typeDecls = useTypeDeclarations
precompiledLib = Some (fun x -> resolveLibCall(fable.LibMap, x)) }
fable.Manager.CompileToBabelAst("fable-library", parseResults, FILE_NAME, fableConfig)) ()
let (jsCode, babelTime, babelErrors) =
try
let code, t = measureTime fable.BabelAstCompiler res.BabelAst
Expand Down
8 changes: 8 additions & 0 deletions src/fable-standalone/test/bench-compiler/Platform.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
module Fable.Compiler.Platform

type CmdLineOptions = {
commonjs: bool
optimize: bool
sourceMaps: bool
typeDecls: bool
watchMode: bool
}

#if DOTNET_FILE_SYSTEM && !FABLE_COMPILER

open System.IO
Expand Down
17 changes: 9 additions & 8 deletions src/fable-standalone/test/bench-compiler/app.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ let printErrors showWarnings (errors: Fable.Standalone.Error[]) =
errors |> Array.iter printError
failwith "Too many errors."

type CmdLineOptions = {
commonjs: bool
optimize: bool
watchMode: bool
sourceMaps: bool
}
let toFableCompilerConfig (options: CmdLineOptions): Fable.Standalone.CompilerConfig =
{ typedArrays = not (options.typeDecls)
clampByteArrays = false
typeDecls = options.typeDecls
precompiledLib = None }

let parseFiles projectFileName outDir options =
// parse project
Expand Down Expand Up @@ -64,7 +63,8 @@ let parseFiles projectFileName outDir options =

// Fable (F# to Babel)
let fableLibraryDir = "fable-library"
let parseFable (res, fileName) = fable.CompileToBabelAst(fableLibraryDir, res, fileName)
let fableConfig = options |> toFableCompilerConfig
let parseFable (res, fileName) = fable.CompileToBabelAst(fableLibraryDir, res, fileName, fableConfig)
let trimPath (path: string) = path.Replace("../", "").Replace("./", "").Replace(":", "")
let projDir = projectFileName |> normalizeFullPath |> Path.GetDirectoryName

Expand Down Expand Up @@ -98,8 +98,9 @@ let parseArguments (argv: string[]) =
let options = {
commonjs = opts |> Array.contains "--commonjs"
optimize = opts |> Array.contains "--optimize-fcs"
watchMode = opts |> Array.contains "--watch"
sourceMaps = opts |> Array.contains "--sourceMaps"
typeDecls = opts |> Array.contains "--typescript"
watchMode = opts |> Array.contains "--watch"
}
parseFiles projectFileName outDir options
| _ -> printfn "%s" usage
Expand Down
Loading

0 comments on commit 99bc5a4

Please sign in to comment.