name: CI Windows MSVC on: push: branches: - master paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_msvc.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_msvc.yml' - '!**/windows-install-sqlite.bat' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: msvc-windows: runs-on: windows-2022 timeout-minutes: 70 env: VFLAGS: -cc msvc VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v7 - uses: ilammy/msvc-dev-cmd@v1 with: arch: x64 - name: Verify MSVC tools run: | where.exe cl.exe where.exe link.exe where.exe dumpbin.exe - name: Build run: | echo %VFLAGS% echo $VFLAGS .\makev.bat -msvc .\v.exe symlink - name: backend x64 regressions if: ${{ false }} # Temporarily disabled. run: | function Assert-LastExit([string] $label) { if ($LASTEXITCODE -ne 0) { throw "$label failed with exit code $LASTEXITCODE" } } $env:VJOBS = '1' .\v.exe test ` vlib/v2_toberemoved/abi ` vlib/v2_toberemoved/gen/x64/x64_abi_test.v ` vlib/v2_toberemoved/gen/x64/x64_backend_diagnostics_test.v ` vlib/v2_toberemoved/gen/x64/x64_object_format_test.v ` vlib/v2_toberemoved/gen/x64/x64_pe_linker_test.v ` vlib/v2_toberemoved/ssa/tree_sumtype_lowering_test.v Assert-LastExit 'stable V2 x64 unit tests' .\v.exe test -run-only test_module_qualified_alias_array_field_index_has_alias_element_type,test_module_storage_legacy_direct_import_nested_module_selector_uses_declared_leaf_module,test_module_storage_flat_direct_import_nested_module_selector_uses_declared_leaf_module vlib/v2_toberemoved/ssa/module_storage_test.v Assert-LastExit 'targeted vlib/v2_toberemoved/ssa/module_storage_test.v regressions' .\v.exe test -run-only test_x64_macos_windows_math_log_20_stdout_exact_bytes,test_x64_macos_windows_generic_sumtype_repeated_base_specialization_stdout_exact_bytes,test_x64_macos_windows_formatted_int_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_int_width_100_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_f64_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_string_return_lifetime_stdout_exact_bytes,test_x64_macos_windows_spectral_reduced_formatted_stdout_exact_bytes,test_x64_macos_windows_bits_len32_stdout_exact_bytes,test_x64_macos_windows_rand_u32n_interface_result_stdout_exact_bytes,test_x64_macos_windows_rand_intn_range_interface_result_stdout_exact_bytes,test_x64_macos_windows_textscanner_embedded_parser_stdout_exact_bytes,test_x64_macos_windows_struct_positional_side_effect_stdout_exact_bytes,test_x64_macos_windows_struct_named_side_effect_stdout_exact_bytes,test_x64_macos_windows_unrelated_same_shape_struct_stdout_exact_bytes,test_x64_macos_windows_named_init_embedded_value_stdout_exact_bytes,test_x64_macos_windows_get_raw_line_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_recursive_descent_example_stdin_stdout_exact_bytes vlib/v2_toberemoved/gen/x64/x64_runtime_smoke_test.v Assert-LastExit 'reduced V2 x64 runtime smoke tests' Remove-Item Env:\VJOBS -ErrorAction SilentlyContinue .\v.exe test vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v Assert-LastExit 'vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v' .\v.exe test vlib/v2_toberemoved/ssa/optimize Assert-LastExit 'vlib/v2_toberemoved/ssa/optimize' $env:V2_VERIFY_STRICT = '1' .\v.exe test vlib/v2_toberemoved/ssa/optimize Assert-LastExit 'strict vlib/v2_toberemoved/ssa/optimize' Remove-Item Env:\V2_VERIFY_STRICT -ErrorAction SilentlyContinue - name: backend x64 examples if: ${{ false }} # Temporarily disabled. run: | function Assert-LastExit([string] $label) { if ($LASTEXITCODE -ne 0) { throw "$label failed with exit code $LASTEXITCODE" } } function Assert-ByteArrayEqual([byte[]] $actual, [byte[]] $expected, [string] $label) { if ($actual.Length -ne $expected.Length) { $actual_text = [System.Text.Encoding]::UTF8.GetString($actual) $expected_text = [System.Text.Encoding]::UTF8.GetString($expected) throw "$label mismatch. Expected length $($expected.Length), got $($actual.Length).`nExpected:`n$expected_text`nActual:`n$actual_text" } for ($i = 0; $i -lt $actual.Length; $i++) { if ($actual[$i] -ne $expected[$i]) { $actual_text = [System.Text.Encoding]::UTF8.GetString($actual) $expected_text = [System.Text.Encoding]::UTF8.GetString($expected) throw "$label mismatch at byte $i.`nExpected:`n$expected_text`nActual:`n$actual_text" } } } function Get-PeImportedDlls([string] $exe) { $output = & dumpbin.exe /imports $exe 2>&1 if ($LASTEXITCODE -ne 0) { $text = ($output | Out-String).Trim() throw "dumpbin import inspection failed for $exe with exit code $LASTEXITCODE`n$text" } $dlls = [System.Collections.Generic.List[string]]::new() foreach ($lineObject in $output) { $line = [string] $lineObject if ($line -match '^\s*([A-Za-z0-9_.-]+\.dll)\s*$') { $dlls.Add($matches[1].ToLowerInvariant()) } } return $dlls | Sort-Object -Unique } function Assert-TinyPeImports([string] $name, [string] $exe, [string] $pe_import_mode) { if ($pe_import_mode -eq '') { return } if ($pe_import_mode -eq 'tiny-used') { [string[]] $allowed_dlls = @('kernel32.dll') } elseif ($pe_import_mode -eq 'tiny-shell32-argv') { [string[]] $allowed_dlls = @('kernel32.dll', 'shell32.dll') } else { throw "$name has unknown PE import validation mode: $pe_import_mode" } [string[]] $dlls = @(Get-PeImportedDlls $exe) if ($dlls.Count -eq 0) { throw "$name PE import validation found no imported DLLs with dumpbin.exe" } $crt_dlls = $dlls | Where-Object { $_ -match '^(msvcrt|ucrtbase|vcruntime)[0-9]*\.dll$' -or $_ -match '^api-ms-win-crt-.*\.dll$' } if ($crt_dlls.Count -gt 0) { throw "$name tiny PE unexpectedly imports CRT DLL(s): $($crt_dlls -join ', ')" } $unexpected_dlls = $dlls | Where-Object { $_ -notin $allowed_dlls } if ($unexpected_dlls.Count -gt 0) { throw "$name PE imports unexpected DLL(s): $($unexpected_dlls -join ', ')" } $missing_dlls = $allowed_dlls | Where-Object { $_ -notin $dlls } if ($missing_dlls.Count -gt 0) { throw "$name PE import validation missed expected DLL(s): $($missing_dlls -join ', ')" } } function Invoke-NativeX64Example([string] $source, [string] $name, [byte[]] $expected_stdout, [string] $pe_import_mode = '', [string[]] $program_args = @()) { $exe = Join-Path $tmp "$name.exe" $stdout_path = Join-Path $tmp "$name.out" $stderr_path = Join-Path $tmp "$name.err" $compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1 $compile_exit = $LASTEXITCODE foreach ($line in $compile_output) { Write-Host $line } if ($compile_exit -ne 0) { throw "compile $source failed with exit code $compile_exit" } Assert-TinyPeImports $name $exe $pe_import_mode Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue if ($program_args.Count -gt 0) { $process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } else { $process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } if ($process.ExitCode -ne 0) { if (Test-Path -LiteralPath $stderr_path) { Get-Content -LiteralPath $stderr_path } throw "$source exited with code $($process.ExitCode)" } [byte[]] $stdout = if (Test-Path -LiteralPath $stdout_path) { [System.IO.File]::ReadAllBytes($stdout_path) } else { New-Object byte[] 0 } [byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 } $empty = New-Object byte[] 0 Assert-ByteArrayEqual $stdout $expected_stdout "$source stdout" Assert-ByteArrayEqual $stderr $empty "$source stderr" } function Invoke-NativeX64ExampleWithStdin([string] $source, [string] $name, [byte[]] $expected_stdout, [string] $stdin_path, [string] $pe_import_mode = '', [string[]] $program_args = @()) { $exe = Join-Path $tmp "$name.exe" $stdout_path = Join-Path $tmp "$name.out" $stderr_path = Join-Path $tmp "$name.err" $compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1 $compile_exit = $LASTEXITCODE foreach ($line in $compile_output) { Write-Host $line } if ($compile_exit -ne 0) { throw "compile $source failed with exit code $compile_exit" } Assert-TinyPeImports $name $exe $pe_import_mode Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue if ($program_args.Count -gt 0) { $process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } else { $process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } if ($process.ExitCode -ne 0) { if (Test-Path -LiteralPath $stderr_path) { Get-Content -LiteralPath $stderr_path } throw "$source exited with code $($process.ExitCode)" } [byte[]] $stdout = if (Test-Path -LiteralPath $stdout_path) { [System.IO.File]::ReadAllBytes($stdout_path) } else { New-Object byte[] 0 } [byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 } $empty = New-Object byte[] 0 Assert-ByteArrayEqual $stdout $expected_stdout "$source stdout" Assert-ByteArrayEqual $stderr $empty "$source stderr" } function Invoke-NativeX64ExampleCapture([string] $source, [string] $name, [string[]] $program_args = @()) { $exe = Join-Path $tmp "$name.exe" $stdout_path = Join-Path $tmp "$name.out" $stderr_path = Join-Path $tmp "$name.err" $compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1 $compile_exit = $LASTEXITCODE foreach ($line in $compile_output) { Write-Host $line } if ($compile_exit -ne 0) { throw "compile $source failed with exit code $compile_exit" } Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue if ($program_args.Count -gt 0) { $process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } else { $process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path } if ($process.ExitCode -ne 0) { if (Test-Path -LiteralPath $stderr_path) { Get-Content -LiteralPath $stderr_path } throw "$source exited with code $($process.ExitCode)" } [byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 } $empty = New-Object byte[] 0 Assert-ByteArrayEqual $stderr $empty "$source stderr" return $stdout_path } function Assert-RandomIpsStdout([string] $path) { [string[]] $lines = [System.IO.File]::ReadAllLines($path) if ($lines.Count -ne 10) { throw "random_ips expected 10 lines, got $($lines.Count)" } $rows = [System.Collections.Generic.List[string]]::new() $all_second_zero = $true $all_fourth_zero = $true foreach ($line in $lines) { [string[]] $parts = $line.Split('.') if ($parts.Count -ne 4) { throw "random_ips invalid IPv4 shape: $line" } [int[]] $octets = @() foreach ($part in $parts) { if ($part -notmatch '^[0-9]+$') { throw "random_ips non-numeric octet: $line" } $value = [int] $part if ($value -lt 0 -or $value -gt 254) { throw "random_ips octet out of range: $line" } $octets += $value } if ($octets[1] -ne 0) { $all_second_zero = $false } if ($octets[3] -ne 0) { $all_fourth_zero = $false } $rows.Add(($octets -join '.')) } if (($rows | Sort-Object -Unique).Count -lt 3) { throw 'random_ips output has too little row diversity' } if ($all_second_zero -and $all_fourth_zero) { throw 'random_ips suspicious old x.0.x.0 pattern' } } function Assert-Rule110Stdout([string] $path, [int] $width) { [string[]] $lines = [System.IO.File]::ReadAllLines($path) $title = 'Rule 110 V Implementation' $idx = -1 for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i].Contains($title)) { $idx = $i break } } if ($idx -lt 0) { throw 'rule110 missing title' } [string[]] $generations = @() if ($idx + 1 -lt $lines.Count) { $generations = @($lines[($idx + 1)..($lines.Count - 1)]) } if ($generations.Count -gt 0 -and $generations[0] -eq '') { if ($generations.Count -eq 1) { $generations = @() } else { $generations = @($generations[1..($generations.Count - 1)]) } } if ($generations.Count -ne $width) { throw "rule110 expected $width generation lines, got $($generations.Count)" } $has_live_cell = $false foreach ($line in $generations) { if ($line.Length -ne $width) { throw "rule110 generation line has width $($line.Length), expected $width`: '$line'" } if ($line -match '[^ *]') { throw "rule110 invalid generation chars: '$line'" } if ($line.Contains('*')) { $has_live_cell = $true } } if (-not $has_live_cell) { throw 'rule110 expected at least one live cell' } if (($generations | Sort-Object -Unique).Count -lt 3) { throw 'rule110 expected at least 3 distinct generation lines' } } $tmp = Join-Path $env:RUNNER_TEMP 'v2_x64_native' New-Item -ItemType Directory -Force -Path $tmp | Out-Null function Get-VRunExpectedBytes([string] $source, [string] $name, [string[]] $program_args = @()) { $stdout_path = Join-Path $tmp "$name.vrun.out" $stderr_path = Join-Path $tmp "$name.vrun.err" Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue $v_args = @('run', $source) + $program_args $process = Start-Process -FilePath '.\v.exe' -ArgumentList $v_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path if ($process.ExitCode -ne 0) { if (Test-Path -LiteralPath $stderr_path) { Get-Content -LiteralPath $stderr_path } throw "v run $source $($program_args -join ' ') failed with code $($process.ExitCode)" } [byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 } $empty = New-Object byte[] 0 Assert-ByteArrayEqual $stderr $empty "v run $source stderr" return [System.IO.File]::ReadAllBytes($stdout_path) } function Get-VRunExpectedBytesWithStdin([string] $source, [string] $name, [string] $stdin_path, [string[]] $program_args = @()) { $stdout_path = Join-Path $tmp "$name.vrun.out" $stderr_path = Join-Path $tmp "$name.vrun.err" Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue $v_args = @('run', $source) + $program_args $process = Start-Process -FilePath '.\v.exe' -ArgumentList $v_args -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path if ($process.ExitCode -ne 0) { if (Test-Path -LiteralPath $stderr_path) { Get-Content -LiteralPath $stderr_path } throw "v run $source $($program_args -join ' ') failed with code $($process.ExitCode)" } [byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 } $empty = New-Object byte[] 0 Assert-ByteArrayEqual $stderr $empty "v run $source stderr" return [System.IO.File]::ReadAllBytes($stdout_path) } $hello_expected = [System.Text.Encoding]::UTF8.GetBytes("Hello, World!`n") Invoke-NativeX64Example 'examples/hello_world.v' 'hello_world' $hello_expected 'tiny-used' $fizz_lines = 1..100 | ForEach-Object { if ($_ % 15 -eq 0) { 'FizzBuzz' } elseif ($_ % 3 -eq 0) { 'Fizz' } elseif ($_ % 5 -eq 0) { 'Buzz' } else { [string] $_ } } $fizz_expected = [System.Text.Encoding]::UTF8.GetBytes(($fizz_lines -join "`n") + "`n") Invoke-NativeX64Example 'examples/fizz_buzz.v' 'fizz_buzz' $fizz_expected 'tiny-used' $fibonacci_expected = [System.Text.Encoding]::UTF8.GetBytes("1`n1`n2`n3`n5`n8`n13`n21`n34`n55`n89`n") Invoke-NativeX64Example 'examples/fibonacci.v' 'fibonacci' $fibonacci_expected 'tiny-shell32-argv' @('10') $dump_factorial_expected = [System.Text.Encoding]::UTF8.GetBytes("120`n") Invoke-NativeX64Example 'examples/dump_factorial.v' 'dump_factorial' $dump_factorial_expected 'tiny-used' function Get-HanoiExpectedLines([int] $n, [string] $a, [string] $b, [string] $c) { if ($n -eq 1) { "Disc 1 from $a to $c..." return } Get-HanoiExpectedLines ($n - 1) $a $c $b "Disc $n from $a to $c..." Get-HanoiExpectedLines ($n - 1) $b $a $c } $hanoi_lines = @(Get-HanoiExpectedLines 7 'A' 'B' 'C') $hanoi_expected = [System.Text.Encoding]::UTF8.GetBytes(($hanoi_lines -join "`n") + "`n") Invoke-NativeX64Example 'examples/hanoi.v' 'hanoi' $hanoi_expected 'tiny-used' function Get-SudokuExpectedLines { $puzzle = @( ,@(0, 3, 0, 0, 7, 0, 0, 0, 0) ,@(0, 0, 0, 1, 3, 5, 0, 0, 0) ,@(0, 0, 1, 0, 0, 0, 0, 5, 0) ,@(1, 0, 0, 0, 6, 0, 0, 0, 3) ,@(4, 0, 0, 8, 0, 3, 0, 0, 1) ,@(7, 0, 0, 0, 2, 0, 0, 0, 6) ,@(0, 0, 0, 0, 0, 0, 2, 1, 0) ,@(0, 0, 0, 4, 1, 2, 0, 0, 5) ,@(0, 0, 0, 0, 0, 0, 0, 7, 4) ) $solution = @( ,@(2, 3, 5, 6, 7, 8, 1, 4, 9) ,@(9, 4, 7, 1, 3, 5, 8, 6, 2) ,@(6, 8, 1, 2, 4, 9, 3, 5, 7) ,@(1, 2, 8, 7, 6, 4, 5, 9, 3) ,@(4, 5, 6, 8, 9, 3, 7, 2, 1) ,@(7, 9, 3, 5, 2, 1, 4, 8, 6) ,@(3, 6, 4, 9, 5, 7, 2, 1, 8) ,@(8, 7, 9, 4, 1, 2, 6, 3, 5) ,@(5, 1, 2, 3, 8, 6, 9, 7, 4) ) $lines = [System.Collections.Generic.List[string]]::new() function Add-SudokuGrid([string] $label, [object[]] $grid) { $lines.Add($label) for ($i = 0; $i -lt $grid.Count; $i++) { if ($i % 3 -eq 0 -and $i -ne 0) { $lines.Add('- - - - - - - - - - - -') } $line = '' for ($j = 0; $j -lt $grid[$i].Count; $j++) { if ($j % 3 -eq 0 -and $j -ne 0) { $line += ' | ' } $line += "$($grid[$i][$j]) " } $lines.Add($line) } } Add-SudokuGrid 'Sudoku Puzzle:' $puzzle $lines.Add('Solving...') Add-SudokuGrid 'Solution:' $solution return $lines.ToArray() } $sudoku_lines = @(Get-SudokuExpectedLines) $sudoku_expected = [System.Text.Encoding]::UTF8.GetBytes(($sudoku_lines -join "`n") + "`n") if ($sudoku_expected.Length -ne 582) { throw "sudoku stdout oracle shape changed: $($sudoku_expected.Length) bytes" } Invoke-NativeX64Example 'examples/sudoku.v' 'sudoku' $sudoku_expected $function_types_expected = [System.Text.Encoding]::UTF8.GetBytes("HELLO WORLD`nHELLO WORLD`nHELLO WORLD`n") Invoke-NativeX64Example 'examples/function_types.v' 'function_types' $function_types_expected $submodule_expected = [System.Text.Encoding]::UTF8.GetBytes("5`n3`n") Invoke-NativeX64Example 'examples/submodule/main.v' 'submodule' $submodule_expected 'tiny-used' function Get-TreeOfNodesExpectedLines { @( 'tree structure:' ' Node{' ' value: 10' ' left: Tree(Node{' ' value: 30' ' left: Tree(Empty{})' ' right: Tree(Empty{})' ' })' ' right: Tree(Node{' ' value: 20' ' left: Tree(Empty{})' ' right: Tree(Empty{})' ' })' '}' 'tree size: 3' ) } $tree_of_nodes_lines = @(Get-TreeOfNodesExpectedLines) $tree_of_nodes_expected = [System.Text.Encoding]::UTF8.GetBytes(($tree_of_nodes_lines -join "`n") + "`n") if ($tree_of_nodes_expected.Length -ne 259) { throw "tree_of_nodes stdout oracle shape changed: $($tree_of_nodes_expected.Length) bytes" } Invoke-NativeX64Example 'examples/tree_of_nodes.v' 'tree_of_nodes' $tree_of_nodes_expected $js_hello_world_expected = [System.Text.Encoding]::UTF8.GetBytes("Hello from V.js (0)`nHello from V.js (1)`nHello from V.js (2)`n") Invoke-NativeX64Example 'examples/js_hello_world.v' 'js_hello_world' $js_hello_world_expected 'tiny-used' function Get-VSingleQuotedLiteralBytes([string] $literal) { $bytes = [System.Collections.Generic.List[byte]]::new() for ($i = 0; $i -lt $literal.Length; $i++) { $ch = $literal[$i] if ($ch -eq '\') { $i++ if ($i -ge $literal.Length) { throw 'unterminated escape in V single-quoted literal' } $escaped = $literal[$i] switch ([int][char] $escaped) { 110 { [void] $bytes.Add(10) } 116 { [void] $bytes.Add(9) } 114 { [void] $bytes.Add(13) } 92 { [void] $bytes.Add(92) } 39 { [void] $bytes.Add(39) } 34 { [void] $bytes.Add(34) } default { foreach ($byte in [System.Text.Encoding]::UTF8.GetBytes([string] $escaped)) { [void] $bytes.Add($byte) } } } } else { foreach ($byte in [System.Text.Encoding]::UTF8.GetBytes([string] $ch)) { [void] $bytes.Add($byte) } } } return $bytes.ToArray() } function Get-VasciiExpectedBytes() { $source = [System.IO.File]::ReadAllText((Join-Path (Get-Location) 'examples/vascii.v'), [System.Text.Encoding]::UTF8) $start_marker = "println('" $end_marker = "')" $first = $source.IndexOf($start_marker, [System.StringComparison]::Ordinal) if ($first -lt 0) { throw 'missing vascii println literal start' } $second = $source.IndexOf($start_marker, $first + $start_marker.Length, [System.StringComparison]::Ordinal) if ($second -ne -1) { throw 'vascii stdout oracle expects one single-quoted println literal' } $start = $first + $start_marker.Length $end = $source.LastIndexOf($end_marker, [System.StringComparison]::Ordinal) if ($end -lt $start) { throw 'missing vascii println literal end' } if ($source.Substring($end + $end_marker.Length).Trim() -ne '}') { throw 'vascii stdout oracle expects the println literal to be the final main statement' } [byte[]] $bytes = Get-VSingleQuotedLiteralBytes ($source.Substring($start, $end - $start)) return $bytes + [byte] 10 } [byte[]] $vascii_expected = Get-VasciiExpectedBytes Invoke-NativeX64Example 'examples/vascii.v' 'vascii' $vascii_expected 'tiny-used' [byte[]] $rune_expected = 0xF0, 0x9F, 0x98, 0x80, 0x0A, 0x40, 0x0A Invoke-NativeX64Example 'examples/rune.v' 'rune' $rune_expected 'tiny-used' [byte[]] $bfs_expected = Get-VRunExpectedBytes 'examples/graphs/bfs.v' 'bfs' Invoke-NativeX64Example 'examples/graphs/bfs.v' 'bfs' $bfs_expected [byte[]] $bfs3_expected = Get-VRunExpectedBytes 'examples/graphs/bfs3.v' 'bfs3' Invoke-NativeX64Example 'examples/graphs/bfs3.v' 'bfs3' $bfs3_expected [byte[]] $primes_expected = Get-VRunExpectedBytes 'examples/primes.v' 'primes' @('20') Invoke-NativeX64Example 'examples/primes.v' 'primes' $primes_expected '' @('20') [byte[]] $dfs_expected = Get-VRunExpectedBytes 'examples/graphs/dfs.v' 'dfs' Invoke-NativeX64Example 'examples/graphs/dfs.v' 'dfs' $dfs_expected [byte[]] $dijkstra_expected = Get-VRunExpectedBytes 'examples/graphs/dijkstra.v' 'dijkstra' Invoke-NativeX64Example 'examples/graphs/dijkstra.v' 'dijkstra' $dijkstra_expected [byte[]] $topological_sorting_greedy_expected = Get-VRunExpectedBytes 'examples/graphs/topological_sorting_greedy.v' 'topological_sorting_greedy' Invoke-NativeX64Example 'examples/graphs/topological_sorting_greedy.v' 'topological_sorting_greedy' $topological_sorting_greedy_expected [byte[]] $topological_sorting_dfs_expected = Get-VRunExpectedBytes 'examples/graphs/topological_sorting_dfs.v' 'topological_sorting_dfs' Invoke-NativeX64Example 'examples/graphs/topological_sorting_dfs.v' 'topological_sorting_dfs' $topological_sorting_dfs_expected [byte[]] $dfs2_expected = Get-VRunExpectedBytes 'examples/graphs/dfs2.v' 'dfs2' Invoke-NativeX64Example 'examples/graphs/dfs2.v' 'dfs2' $dfs2_expected [byte[]] $minimal_spann_tree_prim_expected = Get-VRunExpectedBytes 'examples/graphs/minimal_spann_tree_prim.v' 'minimal_spann_tree_prim' Invoke-NativeX64Example 'examples/graphs/minimal_spann_tree_prim.v' 'minimal_spann_tree_prim' $minimal_spann_tree_prim_expected [byte[]] $bellman_ford_expected = Get-VRunExpectedBytes 'examples/graphs/bellman-ford.v' 'bellman_ford' Invoke-NativeX64Example 'examples/graphs/bellman-ford.v' 'bellman_ford' $bellman_ford_expected [byte[]] $binary_search_tree_expected = Get-VRunExpectedBytes 'examples/binary_search_tree.v' 'binary_search_tree' Invoke-NativeX64Example 'examples/binary_search_tree.v' 'binary_search_tree' $binary_search_tree_expected # normal-required: IError/custom errors [byte[]] $errors_expected = [System.Text.Encoding]::UTF8.GetBytes("wrong format`nempty input`n") Invoke-NativeX64Example 'examples/errors.v' 'errors' $errors_expected [byte[]] $custom_error_expected = Get-VRunExpectedBytes 'examples/custom_error.v' 'custom_error' Invoke-NativeX64Example 'examples/custom_error.v' 'custom_error' $custom_error_expected # normal-required: spectral norm/math.sqrt/formatted f64 interpolation [byte[]] $spectral_expected = Get-VRunExpectedBytes 'examples/spectral.v' 'spectral' @('10') Invoke-NativeX64Example 'examples/spectral.v' 'spectral' $spectral_expected '' @('10') [byte[]] $quick_sort_expected = [System.Text.Encoding]::UTF8.GetBytes("length of random array is 1000`nbefore quick sort whether array is sorted: false`nafter quick sort whether array is sorted: true`n") Invoke-NativeX64Example 'examples/quick_sort.v' 'quick_sort' $quick_sort_expected $get_raw_line_input = Join-Path $tmp 'get_raw_line.in' [System.IO.File]::WriteAllText($get_raw_line_input, "hello`nworld`n", [System.Text.UTF8Encoding]::new($false)) [byte[]] $get_raw_line_expected = Get-VRunExpectedBytesWithStdin 'examples/get_raw_line.v' 'get_raw_line' $get_raw_line_input Invoke-NativeX64ExampleWithStdin 'examples/get_raw_line.v' 'get_raw_line' $get_raw_line_expected $get_raw_line_input $mini_calculator_input = Join-Path $tmp 'mini_calculator.in' [System.IO.File]::WriteAllText($mini_calculator_input, "3+4*2`nexit`n", [System.Text.UTF8Encoding]::new($false)) [byte[]] $mini_calculator_expected = Get-VRunExpectedBytesWithStdin 'examples/mini_calculator.v' 'mini_calculator' $mini_calculator_input Invoke-NativeX64ExampleWithStdin 'examples/mini_calculator.v' 'mini_calculator' $mini_calculator_expected $mini_calculator_input $mini_calculator_recursive_descent_input = Join-Path $tmp 'mini_calculator_recursive_descent.in' [System.IO.File]::WriteAllText($mini_calculator_recursive_descent_input, "3+4*2`nexit`n", [System.Text.UTF8Encoding]::new($false)) [byte[]] $mini_calculator_recursive_descent_expected = Get-VRunExpectedBytesWithStdin 'examples/mini_calculator_recursive_descent.v' 'mini_calculator_recursive_descent' $mini_calculator_recursive_descent_input Invoke-NativeX64ExampleWithStdin 'examples/mini_calculator_recursive_descent.v' 'mini_calculator_recursive_descent' $mini_calculator_recursive_descent_expected $mini_calculator_recursive_descent_input $random_ips_stdout = Invoke-NativeX64ExampleCapture 'examples/random_ips.v' 'random_ips' Assert-RandomIpsStdout $random_ips_stdout $rule110_stdout = Invoke-NativeX64ExampleCapture 'examples/rule110.v' 'rule110' @('31') Assert-Rule110Stdout $rule110_stdout 31 - name: Build V with WX run: v -cflags /WX self - name: All code is formatted run: v -silent test-cleancode - name: Test -cc msvc works run: v -no-retry-compilation run examples/hello_world.v - name: Install dependencies run: | v retry -- v setup-freetype .\.github\workflows\windows-install-sqlite.bat - name: v doctor run: | v doctor - name: Verify `v test` works run: | echo $VFLAGS v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: Test pure V math module run: v -silent -exclude @vlib/math/*.c.v test vlib/math/ - name: Self tests run: v -silent test-self vlib - name: Test v->js run: v -o hi.js examples/js_hello_world.v && node hi.js - name: Test v binaries run: v build-vbinaries - name: Build examples run: v build-examples - name: v2 self compilation run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v