Skip to content

v3: fix cmd/v compilation path #3499

v3: fix cmd/v compilation path

v3: fix cmd/v compilation path #3499

Workflow file for this run

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