Skip to content

Commit

Permalink
Mutually recursive members (#237) and other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsogarciacaro committed Jun 6, 2018
1 parent 086d465 commit 326873d
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 43 deletions.
7 changes: 3 additions & 4 deletions src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ module Helpers =
let isModuleMember (memb: FSharpMemberOrFunctionOrValue) =
match memb.DeclaringEntity with
| Some ent -> ent.IsFSharpModule
// Actually it's true in this case, but we don't consider compiler-generated members
| None -> false
| None -> true // Compiler-generated members

/// Using memb.IsValue doesn't work for function values
/// (e.g. `let ADD = adder()` when adder returns a function)
Expand Down Expand Up @@ -393,13 +392,13 @@ module TypeHelpers =
match Map.tryFind genParam.Name ctxTypeArgs with
| None -> Fable.GenericParam genParam.Name
| Some typ -> typ

let rec makeGenArgs (com: ICompiler) ctxTypeArgs (genArgs: IList<FSharpType>) =
genArgs |> Seq.map (fun genArg ->
if genArg.IsGenericParameter
then resolveGenParam ctxTypeArgs genArg.GenericParameter
else makeType com ctxTypeArgs genArg)
|> Seq.toList
|> Seq.toList

and makeTypeFromDelegate com ctxTypeArgs (genArgs: IList<FSharpType>) (tdef: FSharpEntity) (fullName: string) =
if fullName.StartsWith("System.Action") then
Expand Down
33 changes: 27 additions & 6 deletions src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,10 @@ let private transformMemberFunction (com: IFableCompiler) ctx isPublic name (mem

let private transformMemberFunctionOrValue (com: IFableCompiler) ctx (memb: FSharpMemberOrFunctionOrValue) args (body: FSharpExpr) =
let isPublic = isPublicMember memb
let name = getMemberDeclarationName com memb
com.AddUsedVarName(name)
let name =
match tryGetBoundExpr ctx None memb with
| Some(Fable.IdentExpr id) -> id.Name
| _ -> failwithf "Cannot find name of member %s in scope" memb.FullName
match tryImportAttribute memb.Attributes with
| Some(selector, path) ->
let typ = makeType com Map.empty memb.FullType
Expand Down Expand Up @@ -768,8 +770,28 @@ let private transformMemberDecl (com: FableCompiler) (ctx: Context) (memb: FShar
then transformOverride com ctx memb args body
else transformMemberFunctionOrValue com ctx memb args body

let addMemberNamesToScope (com: IFableCompiler) (ctx: Context) fsDecls =
(ctx, fsDecls) ||> List.fold (fun ctx fsDecl ->
match fsDecl with
| FSharpImplementationFileDeclaration.Entity _ -> ctx
| FSharpImplementationFileDeclaration.InitAction _ -> ctx
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue(memb,_,_) ->
if memb.IsImplicitConstructor || memb.IsOverrideOrExplicitInterfaceImplementation
then ctx // Do nothing
else
let name =
// Compiler-generated module members can have duplicated names, see #237
if memb.IsCompilerGenerated && isModuleMember memb
then memb.CompiledName + com.GetUniqueVar("")
else
let name = getMemberDeclarationName com memb
com.AddUsedVarName(name)
name
{ ctx with Scope = (memb, makeIdentExpr name)::ctx.Scope })

let private transformDeclarations (com: FableCompiler) fsDecls =
let rec transformDeclarationsInner com (ctx: Context) fsDecls =
let rec transformDeclarationsInner com (ctx: Context) fsDecls: Fable.Declaration list =
let ctx = addMemberNamesToScope com ctx fsDecls
fsDecls |> List.collect (fun fsDecl ->
match fsDecl with
| FSharpImplementationFileDeclaration.Entity(ent, sub) ->
Expand All @@ -787,9 +809,8 @@ let private transformDeclarations (com: FableCompiler) fsDecls =
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue(meth, args, body) ->
transformMemberDecl com ctx meth args body
| FSharpImplementationFileDeclaration.InitAction fe ->
let e = transformExpr com ctx fe
let decl = Fable.ActionDeclaration e
[decl])
[transformExpr com ctx fe |> Fable.ActionDeclaration]
)
let decls = transformDeclarationsInner com (Context.Create()) fsDecls
let interfaceImplementations =
com.InterfaceImplementations.Values |> Seq.map (fun (info, objMember) ->
Expand Down
13 changes: 7 additions & 6 deletions src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ module Util =
NullLiteral () :> Expression

let ident (id: Fable.Ident) =
Identifier id.Name
Identifier(id.Name, ?loc=id.Range)

let identAsPattern (id: Fable.Ident): Pattern =
Identifier id.Name :> Pattern
Identifier(id.Name, ?loc=id.Range) :> Pattern

let identAsExpr (id: Fable.Ident) =
Identifier id.Name :> Expression
Identifier(id.Name, ?loc=id.Range) :> Expression

let ofInt i =
NumericLiteral(float i) :> Expression
Expand Down Expand Up @@ -216,6 +216,7 @@ module Util =

let multiVarDeclaration kind (namesAndValue: (string * Expression option) list) =
let varDeclarators =
// TODO: Log error if there're duplicated non-empty var declarations
List.distinctBy fst namesAndValue
|> List.map (fun (name, value) ->
VariableDeclarator(Identifier name, ?init=value))
Expand Down Expand Up @@ -994,7 +995,7 @@ module Util =

| Fable.Value kind -> transformValue com ctx kind

| Fable.IdentExpr ident -> upcast Identifier ident.Name
| Fable.IdentExpr id -> upcast ident id

| Fable.Import(selector, path, kind, _, r) ->
transformImport com ctx r selector path kind
Expand Down Expand Up @@ -1052,8 +1053,8 @@ module Util =
| Fable.Value kind ->
[transformValue com ctx kind |> resolveExpr kind.Type returnStrategy]

| Fable.IdentExpr ident ->
[Identifier ident.Name :> Expression |> resolveExpr ident.Type returnStrategy]
| Fable.IdentExpr id ->
[ident id :> Expression |> resolveExpr id.Type returnStrategy]

| Fable.Import(selector, path, kind, t, r) ->
[transformImport com ctx r selector path kind |> resolveExpr t returnStrategy]
Expand Down
2 changes: 1 addition & 1 deletion src/js/fable-core/String.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ export function replicate(n: number, x: string) {
}

export function getCharAtIndex(input: string, index: number) {
if (index < 0 || index > input.length) {
if (index < 0 || index >= input.length) {
throw new Error("System.IndexOutOfRangeException: Index was outside the bounds of the array.");
}
return input[index];
Expand Down
2 changes: 1 addition & 1 deletion src/js/fable-loader/RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### 2.0.0-alpha-002
### 2.0.0-alpha-003

* Fable 2 alpha

Expand Down
4 changes: 2 additions & 2 deletions src/js/fable-loader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fable-loader",
"version": "2.0.0-alpha-002",
"version": "2.0.0-alpha-003",
"main": "index.js",
"description": "Webpack loader for Fable compiler",
"keywords": [
Expand All @@ -20,7 +20,7 @@
},
"homepage": "https://github.com/fable-compiler/Fable#readme",
"peerDependencies": {
"@babel/core": "^7.0.0-beta.47"
"babel-core": "^6.26.3"
},
"dependencies": {
"fable-utils": "^1.0.4"
Expand Down
2 changes: 1 addition & 1 deletion src/js/fable-splitter/RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### 2.0.0-alpha-001
### 2.0.0-alpha-002

* Fable 2 alpha

Expand Down
10 changes: 4 additions & 6 deletions src/js/fable-splitter/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fable-splitter",
"version": "2.0.0-alpha-001",
"version": "2.0.0-alpha-002",
"description": "File splitter for Fable (F# to JavaScript compiler)",
"author": "ncave",
"license": "Apache-2.0",
Expand All @@ -26,14 +26,12 @@
"prebuild": "node ../../../node_modules/tslint/bin/tslint index.ts",
"build": "node ../../../node_modules/typescript/bin/tsc"
},
"peerDependencies": {
"@babel/core": "^7.0.0-beta.47"
},
"optionalDependencies": {
"prepack": "^0.2.5"
"prepack": "^0.2.36"
},
"dependencies": {
"babel-core": "^6.26.3",
"fable-utils": "^1.0.6",
"chokidar": "^1.7.0"
"chokidar": "^2.0.3"
}
}
2 changes: 1 addition & 1 deletion src/js/fable-splitter/src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ switch (command) {
console.log(getVersion());
break;
default:
var entry = null, restArgs = args;
var entry = null, restArgs = args;
if (command && !command.startsWith('-')) {
entry = path.resolve(command);
restArgs = args.slice(1);
Expand Down
2 changes: 1 addition & 1 deletion src/js/fable-splitter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ async function transformAsync(path: string, options: FableSplitterOptions, info:

function setDefaultOptions(options: FableSplitterOptions) {
if (options.entry == null || options.entry.length === 0) {
throw new Error("Missing or empty: entry path")
throw new Error("Missing or empty: entry path");
}
options = Object.assign({}, options);
options.entry = getFullPath(options.entry); // Normalize path
Expand Down
2 changes: 1 addition & 1 deletion src/tools/ASTViewer/ASTViewer.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dotnet.ProjInfo" Version="0.9.0" />
<PackageReference Include="FSharp.Compiler.Service" Version="21.0.1" />
<PackageReference Include="FSharp.Compiler.Service" Version="23.0.3" />
</ItemGroup>
</Project>
17 changes: 8 additions & 9 deletions tests/Main/MiscTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ let delay (f:unit -> unit) = f

let mutable mutableValue = 0

// let rec recursive1 = delay (fun () -> recursive2())
// and recursive2 =
// mutableValue <- 5
// fun () -> mutableValue <- mutableValue * 2
let rec recursive1 = delay (fun () -> recursive2())
and recursive2 =
mutableValue <- 5
fun () -> mutableValue <- mutableValue * 2

let empty<'a> = [Unchecked.defaultof<'a>]

Expand Down Expand Up @@ -736,11 +736,10 @@ let tests =
match x with TestRef r2 -> !r2
|> equal true

// TODO!!!
// testCase "Recursive values work" <| fun () -> // See #237
// mutableValue |> equal 5
// recursive1()
// mutableValue |> equal 10
testCase "Recursive values work" <| fun () -> // See #237
mutableValue |> equal 5
recursive1()
mutableValue |> equal 10

testCase "Module generic methods without arguments work" <| fun () ->
let li = empty<string>
Expand Down
9 changes: 5 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,7 @@ chokidar@^1.7.0:
optionalDependencies:
fsevents "^1.0.0"

chokidar@^2.0.2:
chokidar@^2.0.2, chokidar@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
dependencies:
Expand Down Expand Up @@ -2262,10 +2262,11 @@ extsprintf@^1.2.0:
"fable-splitter@file:./src/js/fable-splitter":
version "2.0.0-alpha-001"
dependencies:
chokidar "^1.7.0"
babel-core "^6.26.3"
chokidar "^2.0.3"
fable-utils "^1.0.6"
optionalDependencies:
prepack "^0.2.5"
prepack "^0.2.36"

fable-utils@^1.0.4, fable-utils@^1.0.6:
version "1.0.6"
Expand Down Expand Up @@ -3495,7 +3496,7 @@ posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"

prepack@^0.2.5:
prepack@^0.2.36:
version "0.2.36"
resolved "https://registry.yarnpkg.com/prepack/-/prepack-0.2.36.tgz#2039a6ce8b927629a0cd94a0d5516774e44834a8"
dependencies:
Expand Down

0 comments on commit 326873d

Please sign in to comment.