diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index e9ab379..60d828d 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -9,13 +9,13 @@
]
},
"fable": {
- "version": "4.0.0-theta-003",
+ "version": "4.0.0-theta-006",
"commands": [
"fable"
]
},
"fantomas": {
- "version": "5.0.0-beta-009",
+ "version": "5.0.0",
"commands": [
"fantomas"
]
diff --git a/README.md b/README.md
index dccee94..1880dba 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,6 @@ and many more. Some bindings have already been added:
- Python Standard Libray
- Jupyter
- Flask
-- MicroBit
- CogniteSdk
## Version
@@ -30,8 +29,8 @@ how to deal with Python version handling.
Prerequisite for compiling F# to Python using Fable:
```sh
-> dotnet tool install --global fable --version 4.0.0-theta-003
-> dotnet add package Fable.Core --version 4.0.0-theta-001
+> dotnet tool install --global fable --prerelease
+> dotnet add package Fable.Core --prerelease
```
To use the `Fable.Python` library in your Fable project:
@@ -62,7 +61,6 @@ It contains example code for using Fable Python with:
- [Flask](https://github.com/dbrattli/Fable.Python/tree/main/examples/flask).
References [Feliz.ViewEngine](https://github.com/dbrattli/Feliz.ViewEngine)
as a nuget package.
-- [MicroBit](https://github.com/dbrattli/Fable.Python/tree/main/examples/microbit)
- [Timeflies](https://github.com/dbrattli/Fable.Python/tree/main/examples/timeflies),
Cool demo using Tkinter and references
[FSharp.Control.AsyncRx](https://github.com/dbrattli/AsyncRx) as a nuget
@@ -87,12 +85,9 @@ It contains example code for using Fable Python with:
## Poetry
Fable.Python uses [Poetry](https://python-poetry.org/) for package and
-dependency management. This means that packages generated within
-`fable_modules` must be referenced as [path
-dependencies](https://python-poetry.org/docs/dependency-specification/#path-dependencies).
-It is also possible to reference
-[fable-library](https://pypi.org/project/fable-library/) from PyPI to
-avoid bundling the code.
+dependency management. To handle dependencies when adding Fable Python
+compatible NuGet packages, you should use
+[Femto](https://github.com/Zaid-Ajaj/Femto).
## Contributing
diff --git a/examples/microbit/.paket/Paket.Restore.targets b/examples/microbit/.paket/Paket.Restore.targets
deleted file mode 100644
index e230bb2..0000000
--- a/examples/microbit/.paket/Paket.Restore.targets
+++ /dev/null
@@ -1,557 +0,0 @@
-
-
-
-
-
-
- $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
-
- $(MSBuildVersion)
- 15.0.0
- false
- true
-
- true
- $(MSBuildThisFileDirectory)
- $(MSBuildThisFileDirectory)..\
- $(PaketRootPath)paket-files\paket.restore.cached
- $(PaketRootPath)paket.lock
- classic
- proj
- assembly
- native
- /Library/Frameworks/Mono.framework/Commands/mono
- mono
-
-
- $(PaketRootPath)paket.bootstrapper.exe
- $(PaketToolsPath)paket.bootstrapper.exe
- $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\
-
- "$(PaketBootStrapperExePath)"
- $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"
-
-
-
-
- true
- true
-
-
- True
-
-
- False
-
- $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/'))
-
-
-
-
-
-
-
-
- $(PaketRootPath)paket
- $(PaketToolsPath)paket
-
-
-
-
-
- $(PaketRootPath)paket.exe
- $(PaketToolsPath)paket.exe
-
-
-
-
-
- <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json"))
- <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"'))
- <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false
-
-
-
-
-
-
-
-
-
-
- <_PaketCommand>dotnet paket
-
-
-
-
-
- $(PaketToolsPath)paket
- $(PaketBootStrapperExeDir)paket
-
-
- paket
-
-
-
-
- <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))
- <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"
- <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
- <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- $(NoWarn);NU1603;NU1604;NU1605;NU1608
- false
- true
-
-
-
-
-
-
-
-
- $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))
-
-
-
-
-
-
- $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``))
- $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``))
-
-
-
-
- %(PaketRestoreCachedKeyValue.Value)
- %(PaketRestoreCachedKeyValue.Value)
-
-
-
-
- true
- false
- true
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached
-
- $(MSBuildProjectFullPath).paket.references
-
- $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references
-
- $(MSBuildProjectDirectory)\paket.references
-
- false
- true
- true
- references-file-or-cache-not-found
-
-
-
-
- $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)'))
- $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)'))
- references-file
- false
-
-
-
-
- false
-
-
-
-
- true
- target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths)
-
-
-
-
-
-
-
-
-
-
- false
- true
-
-
-
-
-
-
-
-
-
-
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7])
-
-
- %(PaketReferencesFileLinesInfo.PackageVersion)
- All
- runtime
- $(ExcludeAssets);contentFiles
- $(ExcludeAssets);build;buildMultitargeting;buildTransitive
- true
- true
-
-
-
-
- $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools
-
-
-
-
-
-
-
-
- $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0])
- $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1])
-
-
- %(PaketCliToolFileLinesInfo.PackageVersion)
-
-
-
-
-
-
-
-
-
- false
-
-
-
-
-
- <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/>
-
-
-
-
-
- $(MSBuildProjectDirectory)/$(MSBuildProjectFile)
- true
- false
- true
- false
- true
- false
- true
- false
- true
- false
- true
- $(PaketIntermediateOutputPath)\$(Configuration)
- $(PaketIntermediateOutputPath)
-
-
-
- <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/microbit/Build.fs b/examples/microbit/Build.fs
deleted file mode 100644
index bc68bb5..0000000
--- a/examples/microbit/Build.fs
+++ /dev/null
@@ -1,46 +0,0 @@
-open System.IO
-open Fake.Core
-open Fake.IO
-
-open Helpers
-
-initializeContext()
-
-let srcPath = Path.getFullName "src"
-let appName = "app.py"
-
-Target.create "Clean" (fun _ ->
- run dotnet "fable-py clean --yes" srcPath // Delete *.py files created by Fable
-)
-
-Target.create "Build" (fun _ ->
- run dotnet $"fable-py -c Release" srcPath
-
- // Rewrite imports to flat file system.
- let python = File.ReadAllText($"{srcPath}/{appName}")
- let python = python.Replace("fable_modules.fable_library.", "")
- File.WriteAllText($"{srcPath}/{appName}", python)
-)
-
-Target.create "Flash" (fun _ ->
- run flash appName srcPath
-)
-
-Target.create "FableLibrary" (fun _ ->
- run ufs $"put util.py" srcPath
-)
-
-open Fake.Core.TargetOperators
-
-let dependencies = [
- "Clean"
- ==> "Build"
- "Clean"
- ==> "Build"
- ==> "Flash"
- "Clean"
- ==> "FableLibrary"
-]
-
-[]
-let main args = runOrDefault args
\ No newline at end of file
diff --git a/examples/microbit/Helpers.fs b/examples/microbit/Helpers.fs
deleted file mode 100644
index 819fad3..0000000
--- a/examples/microbit/Helpers.fs
+++ /dev/null
@@ -1,107 +0,0 @@
-module Helpers
-
-open Fake.Core
-
-let initializeContext () =
- let execContext = Context.FakeExecutionContext.Create false "build.fsx" [ ]
- Context.setExecutionContext (Context.RuntimeContext.Fake execContext)
-
-module Proc =
- module Parallel =
- open System
-
- let locker = obj()
-
- let colors =
- [| ConsoleColor.Blue
- ConsoleColor.Yellow
- ConsoleColor.Magenta
- ConsoleColor.Cyan
- ConsoleColor.DarkBlue
- ConsoleColor.DarkYellow
- ConsoleColor.DarkMagenta
- ConsoleColor.DarkCyan |]
-
- let print color (colored: string) (line: string) =
- lock locker
- (fun () ->
- let currentColor = Console.ForegroundColor
- Console.ForegroundColor <- color
- Console.Write colored
- Console.ForegroundColor <- currentColor
- Console.WriteLine line)
-
- let onStdout index name (line: string) =
- let color = colors.[index % colors.Length]
- if isNull line then
- print color $"{name}: --- END ---" ""
- else if String.isNotNullOrEmpty line then
- print color $"{name}: " line
-
- let onStderr name (line: string) =
- let color = ConsoleColor.Red
- if isNull line |> not then
- print color $"{name}: " line
-
- let redirect (index, (name, createProcess)) =
- createProcess
- |> CreateProcess.redirectOutputIfNotRedirected
- |> CreateProcess.withOutputEvents (onStdout index name) (onStderr name)
-
- let printStarting indexed =
- for (index, (name, c: CreateProcess<_>)) in indexed do
- let color = colors.[index % colors.Length]
- let wd =
- c.WorkingDirectory
- |> Option.defaultValue ""
- let exe = c.Command.Executable
- let args = c.Command.Arguments.ToStartInfo
- print color $"{name}: {wd}> {exe} {args}" ""
-
- let run cs =
- cs
- |> Seq.toArray
- |> Array.indexed
- |> fun x -> printStarting x; x
- |> Array.map redirect
- |> Array.Parallel.map Proc.run
-
-let createProcess exe arg dir =
- CreateProcess.fromRawCommandLine exe arg
- |> CreateProcess.withWorkingDirectory dir
- |> CreateProcess.ensureExitCode
-
-let dotnet = createProcess "dotnet"
-let flash = createProcess "uflash"
-let ufs = createProcess "ufs"
-
-let npm =
- let npmPath =
- match ProcessUtils.tryFindFileOnPath "npm" with
- | Some path -> path
- | None ->
- "npm was not found in path. Please install it and make sure it's available from your path. " +
- "See https://safe-stack.github.io/docs/quickstart/#install-pre-requisites for more info"
- |> failwith
-
- createProcess npmPath
-
-let run proc arg dir =
- proc arg dir
- |> Proc.run
- |> ignore
-
-let runParallel processes =
- processes
- |> Proc.Parallel.run
- |> ignore
-
-let runOrDefault args =
- try
- match args with
- | [| target |] -> Target.runOrDefault target
- | _ -> Target.runOrDefault "Run"
- 0
- with e ->
- printfn "%A" e
- 1
diff --git a/examples/microbit/README.md b/examples/microbit/README.md
deleted file mode 100644
index 20ea4ee..0000000
--- a/examples/microbit/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Fable Python on BBC micro:bit
-
-Write your F# program in `src/App.fs`.
-
-Note that the Fable Library is not supported on the micro:bit so it's
-very limited what we can do. Parts of Fable Library needs to
-be ported to work with MicroPython see `util.fs` as an example.
-
-The micro:bit have a flat file-system so all files needs to be in the
-same top-level directory. For more information see
-https://microbit-micropython.readthedocs.io/en/latest/tutorials/storage.html
-
-## Install Dependecies
-
-To flash the microbit we use
-[`uFlash`](https://uflash.readthedocs.io/en/latest/) to flash the app
-and [`MicroFS`](https://microfs.readthedocs.io/en/latest/) to transfer
-any Fable Libary (modified) files.
-
-These tools are needed by the Build script:
-
-```sh
-pip install uflash
-pip install microfs
-
-dotnet tool restore
-dotnet restore
-```
-
-## Build
-
-```sh
-dotnet run Build
-```
-
-## Flash to MicroBit
-
-```sh
-dotnet run Flash
-```
-
-## Copy Fable Library
-
-Flashing will not copy the Fable Library (just `util.py` for now), so it
-needs to be transferred separately:
-
-```sh
-dotnet run FableLibrary
-```
-
diff --git a/examples/microbit/paket.dependencies b/examples/microbit/paket.dependencies
deleted file mode 100644
index 75611ca..0000000
--- a/examples/microbit/paket.dependencies
+++ /dev/null
@@ -1,9 +0,0 @@
-source https://api.nuget.org/v3/index.json
-framework: net5.0
-storage: none
-
-nuget Fable.Core.Experimental >= 4.0.0-alpha-022
-nuget Fable.Python
-
-nuget Fake.Core.Target
-nuget Fake.IO.FileSystem
diff --git a/examples/microbit/paket.lock b/examples/microbit/paket.lock
deleted file mode 100644
index 23dcfae..0000000
--- a/examples/microbit/paket.lock
+++ /dev/null
@@ -1,54 +0,0 @@
-STORAGE: NONE
-RESTRICTION: == net5.0
-NUGET
- remote: https://api.nuget.org/v3/index.json
- Fable.Core.Experimental (4.0.0-alpha-002)
- FSharp.Core (>= 4.7.2)
- Fable.Python (0.9)
- Fable.Core.Experimental (>= 4.0.0-alpha-002)
- FSharp.Core (>= 6.0)
- Fake.Core.CommandLineParsing (5.20.4)
- FParsec (>= 1.1.1)
- FSharp.Core (>= 4.7.2)
- Fake.Core.Context (5.20.4)
- FSharp.Core (>= 4.7.2)
- Fake.Core.Environment (5.20.4)
- FSharp.Core (>= 4.7.2)
- Fake.Core.FakeVar (5.20.4)
- Fake.Core.Context (>= 5.20.4)
- FSharp.Core (>= 4.7.2)
- Fake.Core.Process (5.20.4)
- Fake.Core.Environment (>= 5.20.4)
- Fake.Core.FakeVar (>= 5.20.4)
- Fake.Core.String (>= 5.20.4)
- Fake.Core.Trace (>= 5.20.4)
- Fake.IO.FileSystem (>= 5.20.4)
- FSharp.Core (>= 4.7.2)
- System.Collections.Immutable (>= 1.7.1)
- Fake.Core.String (5.20.4)
- FSharp.Core (>= 4.7.2)
- Fake.Core.Target (5.20.4)
- Fake.Core.CommandLineParsing (>= 5.20.4)
- Fake.Core.Context (>= 5.20.4)
- Fake.Core.Environment (>= 5.20.4)
- Fake.Core.FakeVar (>= 5.20.4)
- Fake.Core.Process (>= 5.20.4)
- Fake.Core.String (>= 5.20.4)
- Fake.Core.Trace (>= 5.20.4)
- FSharp.Control.Reactive (>= 4.4.2)
- FSharp.Core (>= 4.7.2)
- Fake.Core.Trace (5.20.4)
- Fake.Core.Environment (>= 5.20.4)
- Fake.Core.FakeVar (>= 5.20.4)
- FSharp.Core (>= 4.7.2)
- Fake.IO.FileSystem (5.20.4)
- Fake.Core.String (>= 5.20.4)
- FSharp.Core (>= 4.7.2)
- FParsec (1.1.1)
- FSharp.Core (>= 4.3.4)
- FSharp.Control.Reactive (5.0.2)
- FSharp.Core (>= 4.7.2)
- System.Reactive (>= 5.0)
- FSharp.Core (6.0)
- System.Collections.Immutable (5.0)
- System.Reactive (5.0)
diff --git a/examples/microbit/paket.references b/examples/microbit/paket.references
deleted file mode 100644
index 40aad72..0000000
--- a/examples/microbit/paket.references
+++ /dev/null
@@ -1,2 +0,0 @@
-Fake.Core.Target
-Fake.IO.FileSystem
diff --git a/examples/microbit/src/App.fs b/examples/microbit/src/App.fs
deleted file mode 100644
index e5ec232..0000000
--- a/examples/microbit/src/App.fs
+++ /dev/null
@@ -1,32 +0,0 @@
-module App
-
-open Fable.Python.MicroBit
-
-//display.scroll ("Fable Python!") |> ignore
-
-let mutable time = 0
-let mutable start = 0
-let mutable running = false
-
-while true do
- if running then
- display.show (Image.HEART)
- sleep (300)
- display.show (Image.HEART_SMALL)
- sleep (300)
- else
- display.show (Image.ASLEEP)
-
- if button_a.was_pressed () then
- running <- true
- start <- running_time ()
-
- if button_b.was_pressed () then
- if running then
- time <- time + running_time () - start
-
- running <- false
-
- if pin_logo.is_touched () then
- if not running then
- display.scroll (int (time / 1000))
diff --git a/examples/microbit/src/MicroBit.fsproj b/examples/microbit/src/MicroBit.fsproj
deleted file mode 100644
index 974f566..0000000
--- a/examples/microbit/src/MicroBit.fsproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- net5.0
- false
- Dag Brattli
- Dag Brattli
- Exe
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/microbit/src/app.py b/examples/microbit/src/app.py
deleted file mode 100644
index ab3b19c..0000000
--- a/examples/microbit/src/app.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from microbit import display
-
-value = display.scroll("Fable Python!")
-
diff --git a/examples/microbit/src/paket.references b/examples/microbit/src/paket.references
deleted file mode 100644
index 1d37423..0000000
--- a/examples/microbit/src/paket.references
+++ /dev/null
@@ -1 +0,0 @@
-Fable.Core
\ No newline at end of file
diff --git a/examples/microbit/src/types.py b/examples/microbit/src/types.py
deleted file mode 100755
index 9ce7184..0000000
--- a/examples/microbit/src/types.py
+++ /dev/null
@@ -1,249 +0,0 @@
-from __future__ import annotations
-
-from .util import equals
-from .util import IComparable
-
-
-class FSharpRef:
- def __init__(self, contentsOrGetter, setter=None) -> None:
-
- contents = contentsOrGetter
-
- def set_contents(value):
- nonlocal contents
- contents = value
-
- if callable(setter):
- self.getter = contentsOrGetter
- self.setter = setter
- else:
- self.getter = lambda: contents
- self.setter = set_contents
-
- @property
- def contents(self) -> T:
- return self.getter()
-
- @contents.setter
- def contents(self, v) -> None:
- self.setter(v)
-
-
-class Union(IComparable):
- def __init__(self):
- self.tag: int
- self.fields = ()
-
- def cases():
- ...
-
- @property
- def name(self) -> str:
- return self.cases()[self.tag]
-
- def to_JSON(self) -> str:
- raise NotImplementedError
- # return str([self.name] + self.fields) if len(self.fields) else self.name
-
- def __str__(self) -> str:
- if not len(self.fields):
- return self.name
-
- fields = ""
- with_parens = True
- if len(self.fields) == 1:
- field = str(self.fields[0])
- with_parens = field.find(" ") >= 0
- fields = field
- else:
- fields = ", ".join(map(str, self.fields))
-
- return self.name + (" (" if with_parens else " ") + fields + (")" if with_parens else "")
-
- def __hash__(self) -> int:
- hashes = map(hash, self.fields)
- return hash([hash(self.tag), *hashes])
-
- def __eq__(self, other) -> bool:
- if self is other:
- return True
- if not isinstance(other, Union):
- return False
-
- if self.tag == other.tag:
- return self.fields == other.fields
-
- return False
-
- def __lt__(self, other) -> bool:
- if self.tag == other.tag:
- return self.fields < other.fields
-
- return self.tag < other.tag
-
-
-def recordEquals(self, other):
- if self is other:
- return True
-
- a = self.__dict__ if hasattr(self, "__dict__") else self
- b = other.__dict__ if hasattr(other, "__dict__") else other
-
- return a == b
-
-
-def recordCompareTo(self, other):
- if self is other:
- return 0
-
- else:
- for name in self.__dict__.keys():
- if self.__dict__[name] < other.__dict__.get(name):
- return -1
- elif self.__dict__[name] > other.__dict__.get(name):
- return 1
-
- return 0
-
-
-def recordToString(self):
- return "{ " + "\n ".join(map(lambda kv: kv[0] + " = " + str(kv[1]), self.__dict__.items())) + " }"
-
-
-def recordGetHashCode(self):
- return hash(*self.values())
-
-
-class Record(IComparable):
- def toJSON(self) -> str:
- return record_to_JSON(self)
-
- def __str__(self) -> str:
- return recordToString(self)
-
- def GetHashCode(self) -> int:
- return recordGetHashCode(self)
-
- def Equals(self, other: Record) -> bool:
- return recordEquals(self, other)
-
- def CompareTo(self, other: Record) -> int:
- return recordCompareTo(self, other)
-
- def __lt__(self, other) -> bool:
- return True if self.CompareTo(other) == -1 else False
-
- def __eq__(self, other) -> bool:
- return self.Equals(other)
-
- def __hash__(self) -> int:
- return recordGetHashCode(self)
-
-
-class Attribute:
- pass
-
-
-def seq_to_string(self):
- str = "["
-
- for count, x in enumerate(self):
- if count == 0:
- str += to_string(x)
-
- elif count == 100:
- str += "; ..."
- break
-
- else:
- str += "; " + to_string(x)
-
- return str + "]"
-
-
-def to_string(x, callStack=0):
- if x is not None:
- # if (typeof x.toString === "function") {
- # return x.toString();
-
- if isinstance(x, str):
- return str(x)
-
- # if isinstance(x, Iterable):
- # return seq_to_string(x)
-
- # else: // TODO: Date?
- # const cons = Object.getPrototypeOf(x).constructor;
- # return cons === Object && callStack < 10
- # // Same format as recordToString
- # ? "{ " + Object.entries(x).map(([k, v]) => k + " = " + toString(v, callStack + 1)).join("\n ") + " }"
- # : cons.name;
-
- return str(x)
-
-
-class Exception(Exception):
- def __init__(self, msg=None):
- self.msg = msg
-
- def __eq__(self, other):
- if self is other:
- return True
-
- if other is None:
- return False
-
- return self.msg == other.msg
-
-
-class FSharpException(Exception, IComparable):
- def __init__(self):
- self.Data0 = None
-
- def toJSON(self):
- return record_to_JSON(self)
-
- def __str__(self):
- return recordToString(self)
-
- def __eq__(self, other):
- if self is other:
- return True
-
- if other is None:
- return False
-
- return self.Data0 == other.Data0
-
- def __lt__(self, other: Any) -> bool:
- if not isinstance(other, FSharpException):
- return False
-
- if self.Data0:
- if other.Data0:
- return self.Data0 < other.Data0
- else:
- return False
-
- elif not self.Data0:
- if other.Data0:
- return False
- else:
- return True
-
- return super().__lt__(other)
-
- def __hash__(self) -> int:
- return hash(self.Data0)
-
- def GetHashCode(self):
- recordGetHashCode(self)
-
- def Equals(self, other: FSharpException):
- return recordEquals(self, other)
-
- def CompareTo(self, other: FSharpException):
- return recordCompareTo(self, other)
-
-
-__all__ = ["Attribute", "Exception", "FSharpRef", "to_string", "Union"]
diff --git a/examples/microbit/src/util.py b/examples/microbit/src/util.py
deleted file mode 100755
index 874bc8b..0000000
--- a/examples/microbit/src/util.py
+++ /dev/null
@@ -1,412 +0,0 @@
-import builtins
-import math
-
-
-class ObjectDisposedException(Exception):
- def __init__(self):
- super().__init__("Cannot access a disposed object")
-
-
-class IDisposable:
- def dispose(self):
- ...
-
- def __enter__(self):
- """Enter context management."""
- return self
-
- def __exit__(self, exctype, excinst, exctb):
- """Exit context management."""
-
- self.dispose()
- return False
-
- @staticmethod
- def create(action):
- """Create disposable from action. Will call action when
- disposed."""
- return AnonymousDisposable(action)
-
-
-class AnonymousDisposable(IDisposable):
- def __init__(self, action):
- self._is_disposed = False
- self._action = action
-
- def dispose(self):
- """Performs the task of cleaning up resources."""
-
- dispose = False
- if not self._is_disposed:
- dispose = True
- self._is_disposed = True
-
- if dispose:
- self._action()
-
- def __enter__(self):
- if self._is_disposed:
- raise ObjectDisposedException()
- return self
-
-
-class IEquatable:
- def GetHashCode(self):
- return hash(self)
-
- def __eq__(self, other):
- return NotImplemented
-
- def __hash__(self):
- raise NotImplementedError
-
-
-class IComparable(IEquatable):
- def CompareTo(self, other):
- if self < other:
- return -1
- elif self == other:
- return 0
- return 1
-
- def __lt__(self, other):
- raise NotImplementedError
-
-
-def equals(a, b):
- return a == b
-
-
-def is_comparable(x):
- return hasattr(x, "CompareTo") and callable(x.CompareTo)
-
-
-def compare(a, b):
- if a is b:
- return 0
-
- if a is None:
- return -1 if b else 0
-
- if b is None:
- return 1 if a else 0
-
- if is_comparable(a):
- return a.CompareTo(b)
-
- if hasattr(a, "__eq__") and callable(a.__eq__) and a == b:
- return 0
-
- if hasattr(a, "__lt__") and callable(a.__lt__) and a < b:
- return -1
-
- return 1
-
-
-def compare_arrays(a, b):
- return compare(a, b)
-
-
-def equal_arrays_with(x, y, eq):
- if x is None:
- return y is None
- if y is None:
- return False
-
- if len(x) != len(y):
- return False
-
- return eq(x, y)
-
-
-def equal_arrays(x, y):
- return equal_arrays_with(x, y, equals)
-
-
-def compare_primitives(x, y):
- return 0 if x == y else (-1 if x < y else 1)
-
-
-def min(comparer, x, y):
- return x if comparer(x, y) < 0 else y
-
-
-def max(comparer, x, y):
- return x if comparer(x, y) > 0 else y
-
-
-def clamp(comparer, value, min, max):
- # return (comparer(value, min) < 0) ? min : (comparer(value, max) > 0) ? max : value;
- return min if (comparer(value, min) < 0) else max if comparer(value, max) > 0 else value
-
-
-def create_atom(value=None):
- atom = value
-
- def _(value=None, isSetter=None):
- nonlocal atom
-
- if not isSetter:
- return atom
- else:
- atom = value
- return None
-
- return _
-
-
-def create_obj(fields):
- # TODO: return dict(filelds) ?
- obj = {}
-
- for k, v in fields:
- obj[k] = v
-
- return obj
-
-
-def int16to_string(i, radix=10):
- if radix == 10:
- return "{:d}".format(i)
- if radix == 16:
- return "{:x}".format(i)
- if radix == 2:
- return "{:b}".format(i)
- return str(i)
-
-
-def int32to_string(i: int, radix: int = 10):
- if radix == 10:
- return "{:d}".format(i)
- if radix == 16:
- return "{:x}".format(i)
- if radix == 2:
- return "{:b}".format(i)
- return str(i)
-
-
-class IEnumerator(IDisposable):
- def Current(self):
- ...
-
- def MoveNext(self):
- ...
-
- def Reset(self):
- ...
-
- def Dispose(self):
- ...
-
- def __getattr__(self, name):
- return {
- "System_Collections_Generic_IEnumerator_00601_get_Current": self.Current,
- "System_Collections.IEnumerator_get_Current": self.Current,
- "System_Collections_IEnumerator_MoveNext": self.MoveNext,
- "System_Collections.IEnumerator_Reset": self.Reset,
- }[name]
-
-
-class IEnumerable:
- def GetEnumerator(self):
- ...
-
-
-class Enumerator:
- def __init__(self, iter):
- self.iter = iter
- self.current = None
-
- def Current(self):
- if self.current is not None:
- return self.current
- return None
-
- def MoveNext(self):
- try:
- cur = next(self.iter)
- self.current = cur
- return True
- except StopIteration:
- return False
-
- def Reset(self):
- raise Exception("Python iterators cannot be reset")
-
- def Dispose(self):
- return
-
-
-def get_enumerator(o):
- attr = getattr(o, "GetEnumerator", None)
- if attr:
- return attr()
- else:
- return Enumerator(iter(o))
-
-
-CURRIED_KEY = "__CURRIED__"
-
-
-def uncurry(arity: int, f):
- # f may be a function option with None value
- if f is None:
- return f
-
- fns = {
- 2: lambda a1, a2: f(a1)(a2),
- 3: lambda a1, a2, a3: f(a1)(a2)(a3),
- 4: lambda a1, a2, a3, a4: f(a1)(a2)(a3)(a4),
- 5: lambda a1, a2, a3, a4, a5: f(a1)(a2)(a3)(a4)(a5),
- 6: lambda a1, a2, a3, a4, a5, a6: f(a1)(a2)(a3)(a4)(a5)(a6),
- 7: lambda a1, a2, a3, a4, a5, a6, a7: f(a1)(a2)(a3)(a4)(a5)(a6)(a7),
- 8: lambda a1, a2, a3, a4, a5, a6, a7, a8: f(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8),
- }
-
- try:
- uncurriedFn = fns[arity]
- except Exception:
- raise Exception("Uncurrying to more than 8-arity is not supported:", arity)
-
- setattr(f, CURRIED_KEY, f)
- return uncurriedFn
-
-
-def curry(arity: int, f):
- if f is None or arity == 1:
- return f
-
- if hasattr(f, CURRIED_KEY):
- return getattr(f, CURRIED_KEY)
-
- if arity == 2:
- return lambda a1: lambda a2: f(a1, a2)
- elif arity == 3:
- return lambda a1: lambda a2: lambda a3: f(a1, a2, a3)
- elif arity == 4:
- return lambda a1: lambda a2: lambda a3: lambda a4: f(a1, a2, a3, a4)
- elif arity == 4:
- return lambda a1: lambda a2: lambda a3: lambda a4: lambda a5: f(a1, a2, a3, a4, a5)
- elif arity == 6:
- return lambda a1: lambda a2: lambda a3: lambda a4: lambda a5: lambda a6: f(a1, a2, a3, a4, a5, a6)
- elif arity == 7:
- return lambda a1: lambda a2: lambda a3: lambda a4: lambda a5: lambda a6: lambda a7: f(
- a1, a2, a3, a4, a5, a6, a7
- )
- elif arity == 8:
- return lambda a1: lambda a2: lambda a3: lambda a4: lambda a5: lambda a6: lambda a7: lambda a8: f(
- a1, a2, a3, a4, a5, a6, a7, a8
- )
- else:
- raise Exception("Currying to more than 8-arity is not supported: %d" % arity)
-
-
-def is_array_like(x):
- return hasattr(x, "__len__") and callable(x.__len__)
-
-
-def is_disposable(x):
- return x is not None and isinstance(x, IDisposable)
-
-
-def is_hashable(x):
- return hasattr(x, "GetHashCode")
-
-
-def is_hashable_py(x):
- return hasattr(x, "__hash__") and callable(x.__hash__)
-
-
-def to_iterator(en):
- class Iterator:
- def __iter__(self):
- return self
-
- def __next__(self):
- has_next = getattr(en, "System_Collections_IEnumerator_MoveNext")()
- if not has_next:
- raise StopIteration
- return getattr(en, "System_Collections_IEnumerator_get_Current")()
-
- return Iterator()
-
-
-class ObjectRef:
- id_map = dict()
- count = 0
-
- @staticmethod
- def id(o):
- _id = id(o)
- if not _id in ObjectRef.id_map:
- count = ObjectRef.count + 1
- ObjectRef.id_map[_id] = count
-
- return ObjectRef.id_map[_id]
-
-
-def safe_hash(x):
- return 0 if x is None else x.GetHashCode() if is_hashable(x) else number_hash(ObjectRef.id(x))
-
-
-def string_hash(s):
- h = 5381
- for c in s:
- h = (h * 33) ^ ord(c)
-
- return h
-
-
-def number_hash(x):
- return x * 2654435761 | 0
-
-
-def identity_hash(x):
- if x is None:
- return 0
-
- if is_hashable(x):
- return x.GetHashCode()
-
- if is_hashable_py(x):
- return hash(x)
-
- return physical_hash(x)
-
-
-def combine_hash_codes(hashes):
- if not hashes:
- return 0
-
- # return functools.reduce(lambda h1, h2: ((h1 << 5) + h1) ^ h2, hashes)
- return 0
-
-
-def structural_hash(x):
- print("structural_hash: ", x)
- return hash(x)
-
-
-def array_hash(xs):
- hashes = []
- for i, x in enumerate(xs):
- hashes.append(structural_hash(x))
-
- return combine_hash_codes(hashes)
-
-
-def physical_hash(x):
- if hasattr(x, "__hash__") and callable(x.__hash__):
- return hash(x)
-
- return number_hash(ObjectRef.id(x))
-
-
-def round(value, digits=0):
- m = pow(10, digits)
- n = +(value * m if digits else value)
- i = math.floor(n)
- f = n - i
- e = 1e-8
- r = (i if (i % 2 == 0) else i + 1) if (f > 0.5 - e and f < 0.5 + e) else builtins.round(n)
- return r / m if digits else r
diff --git a/examples/timeflies/Program.fs b/examples/timeflies/Program.fs
index 28ad828..3265525 100644
--- a/examples/timeflies/Program.fs
+++ b/examples/timeflies/Program.fs
@@ -15,7 +15,8 @@ let root = Tk()
root.title ("Fable Python Rocks on Tkinter!")
let queue = Queue()
-let source, mouseMoves: IAsyncObserver * IAsyncObservable = AsyncRx.subject ()
+let source, mouseMoves: IAsyncObserver * IAsyncObservable =
+ AsyncRx.subject ()
let workerAsync (mb: MailboxProcessor) =
let rec messageLoop () =
@@ -38,11 +39,10 @@ let stream =
Seq.toList "TIME FLIES LIKE AN ARROW"
|> Seq.mapi (fun i c -> i, Label(frame, text = (string c), fg = "black", bg = "white"))
|> AsyncRx.ofSeq
- |> AsyncRx.flatMap
- (fun (i, label) ->
- mouseMoves
- |> AsyncRx.delay (100 * i)
- |> AsyncRx.map (fun (x, y) -> label, x + i * 12 + 15, y))
+ |> AsyncRx.flatMap (fun (i, label) ->
+ mouseMoves
+ |> AsyncRx.delay (100 * i)
+ |> AsyncRx.map (fun (x, y) -> label, x + i * 12 + 15, y))
let sink (ev: Notification