# iex (iwr 'https://gist.github.com/anonhostpi/e33c2fb4e3282ff75962cf12a2a9af6a/raw/wasm.ps1').content & { # Install-Module "Wasmtime" $package = Get-Package -Name "Wasmtime" $directory = $package.Source | Split-Path $runtime = "win-x64" # "win/linux/osx-arm64/x64" $native = "$directory\runtimes\$runtime\native" | Resolve-Path $env:PATH += ";$native" Add-Type -Path "$directory\lib\netstandard2.1\Wasmtime.Dotnet.dll" } function New-WasmEngine { [CmdletBinding()] param( [Parameter(ValueFromPipeline=$true)] [Wasmtime.Config] $config = $null ) If ($null -eq $config) { return [Wasmtime.Engine]::new() } else { return [Wasmtime.Engine]::new($config) } } function ConvertTo-Wasm { [CmdletBinding()] param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $Text ) return [Wasmtime.Module]::ConvertText($Text) } function New-WasmModule { [CmdletBinding(DefaultParameterSetName='InputObject')] param ( [Parameter(Mandatory=$true)] [Wasmtime.Engine] $Engine, [Parameter(ParameterSetName='InputObject', Mandatory=$true)] [string] $Name, [Parameter(ParameterSetName='InputObject', Mandatory=$true, ValueFromPipeline=$true)] $Input, [Parameter(ParameterSetName='InputObject')] [switch] $Binary, # Default is .wat (text) [Parameter(ParameterSetName='InputObject')] [switch] $Stream, [Parameter(ParameterSetName='File', Mandatory=$true, ValueFromPipeline=$true)] [string] $Path, [Parameter(ParameterSetName='File')] [switch] $Text # Default is .wasm (binary) ) switch ($PSCmdlet.ParameterSetName) { 'InputObject' { If($Binary) { If($Stream) { return [Wasmtime.Module]::FromStream($Engine, $Name, $Input) } return [Wasmtime.Module]::FromBytes($Engine, $Name, $Input) } Else { If($Stream) { return [Wasmtime.Module]::FromTextStream($Engine, $Name, $Input) } return [Wasmtime.Module]::FromText($Engine, $Name, $Input) } } 'File' { If($Text) { return [Wasmtime.Module]::FromFileText($Engine, $Path) } Else { return [Wasmtime.Module]::FromFile($Engine, $Path) } } } } function New-WasmLinker { [CmdletBinding()] param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [Wasmtime.Engine] $Engine ) return [Wasmtime.Linker]::new($Engine) } function New-WasmStore { [CmdletBinding()] param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [Wasmtime.Engine] $Engine, [System.Object] $Context = $Null ) If($null -eq $Context){ return [Wasmtime.Store]::new($Engine) } else { return [Wasmtime.Store]::new($Engine, $Context) } } # NOTE: does not support return values. To return values, declare the function explicitly! function New-WasmFunction { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [Wasmtime.Store] $Store, [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [scriptblock] $Callback, [Type[]] $Parameters = (&{ $callback.Ast.ParamBlock.Parameters.StaticType }) ) $cb = If($Parameters.Count -gt 0) { "[System.Action[$(($Parameters | ForEach-Object { $_.FullName }) -join ',')]] `$Callback" } Else { "[System.Action] `$Callback" } return [Wasmtime.Function]::FromCallback($Store, (Invoke-Expression $cb)) } $engine = New-WasmEngine $linker = New-WasmLinker -Engine $engine $store = New-WasmStore -Engine $engine # -Context @{} $import = @{ "say" = @{ "hello" = { Write-Host "Hello, world!" } } } $signatures = @() $import.GetEnumerator() | ForEach-Object { $from = $_.Key $_.Value.GetEnumerator() | ForEach-Object { $name = $_.Key $function = New-WasmFunction -Store $store -Callback $_.Value $linker.Define($from, $name, $function) $signatures += "$from.$name" } } $module = & { $labels = @() $functions = $signatures | ForEach-Object { $from, $name = $_ -split '\.' $label = '$' + (@($from, $name) -join '_') $labels += $label return "(func $label (import `"$from`" `"$name`"))" } $calls = & { $result = @() $labels | ForEach-Object { $result += "(call $_)" } return $result -join " " } $run = "(func (export `"run`") $calls)" $functions = @($functions, $run) return "(module $($functions -join " "))" } $module = $module | New-WasmModule -Engine $engine -Name "Main" $module_instance = $linker.Instantiate($store, $module) $module_instance.GetFunction("run").Invoke()