Compare commits
46 Commits
f9079b6700
...
585cb9ec2b
Author | SHA1 | Date |
---|---|---|
kahsa | 585cb9ec2b | |
Delyan Angelov | f9515f7515 | |
yuyi | fcabcfc048 | |
yuyi | 7c46e94b25 | |
yuyi | 7b0dae5da7 | |
Ben | 95429e5cc8 | |
yuyi | b6fb1baadc | |
yuyi | 96b80bcf9f | |
yuyi | b717ef74f8 | |
Delyan Angelov | 73e421cd95 | |
Delyan Angelov | 461e50fb48 | |
yuyi | 1761b81130 | |
yuyi | bf15ed95af | |
Alexander Medvednikov | 9133671436 | |
Daniel Däschle | 0329536da3 | |
yuyi | 880223c2dd | |
spaceface | 86ba683536 | |
Delyan Angelov | a3516b116b | |
spaceface | 1a734a00d6 | |
yuyi | 9326cb9d67 | |
Alexander Medvednikov | 1679e07619 | |
Daniel Däschle | 38709f3e6f | |
Subhomoy Haldar | 534939d3df | |
Delyan Angelov | 1e0afc71e5 | |
yuyi | 0227573ea9 | |
Delyan Angelov | 39c1ae3a43 | |
Delyan Angelov | 89f0b16f23 | |
Delyan Angelov | d2dde3b247 | |
Ben | 01f263261c | |
Daniel Däschle | 53bc4c80d4 | |
Alexander Medvednikov | ec5ccb2995 | |
Vincenzo Palazzo | 3d723eb9bf | |
Daniel Däschle | 9e216fbd91 | |
Delyan Angelov | d71f8d336c | |
yuyi | d6fcd24e9d | |
yuyi | b1c2a72118 | |
yuyi | d79fdc075d | |
StunxFS | b15f50e9b1 | |
Delyan Angelov | 59d4e59ac6 | |
David 'Epper' Marshall | 801a88ad16 | |
David 'Epper' Marshall | b8a0315574 | |
crthpl | 2835a190e8 | |
yuyi | d5beaa0798 | |
crthpl | 63f03d0c61 | |
Daniel Däschle | 9ad7307e31 | |
yuyi | 1c0e0ec6a1 |
|
@ -15,6 +15,7 @@ concurrency:
|
|||
jobs:
|
||||
ubuntu-tcc:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -94,6 +95,7 @@ jobs:
|
|||
|
||||
ubuntu-tcc-boehm-gc:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -150,6 +152,7 @@ jobs:
|
|||
|
||||
macos:
|
||||
runs-on: macOS-latest
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
@ -239,6 +242,7 @@ jobs:
|
|||
|
||||
ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -338,6 +342,7 @@ jobs:
|
|||
|
||||
ubuntu-clang:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
@ -428,6 +433,7 @@ jobs:
|
|||
|
||||
windows-gcc:
|
||||
runs-on: windows-2019
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc gcc
|
||||
|
@ -490,6 +496,7 @@ jobs:
|
|||
|
||||
windows-msvc:
|
||||
runs-on: windows-2019
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc msvc
|
||||
|
@ -537,6 +544,7 @@ jobs:
|
|||
|
||||
windows-tcc:
|
||||
runs-on: windows-2019
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -586,7 +594,9 @@ jobs:
|
|||
- name: Build examples
|
||||
run: ./v build-examples
|
||||
- name: v2 self compilation
|
||||
run: .\v.exe -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v
|
||||
run: .\v.exe -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v && .\v3.exe -o v4.exe cmd/v
|
||||
- name: v2 self compilation with -gc boehm
|
||||
run: .\v.exe -o v2.exe -gc boehm cmd/v && .\v2.exe -o v3.exe -gc boehm cmd/v && .\v3.exe -o v4.exe -gc boehm cmd/v
|
||||
|
||||
## ## tcc32
|
||||
## - name: Build with make.bat -tcc32
|
||||
|
@ -631,6 +641,7 @@ jobs:
|
|||
|
||||
# ubuntu-autofree-selfcompile:
|
||||
# runs-on: ubuntu-20.04
|
||||
# if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
# timeout-minutes: 121
|
||||
# env:
|
||||
# VFLAGS: -cc gcc
|
||||
|
@ -644,6 +655,7 @@ jobs:
|
|||
|
||||
# ubuntu-musl:
|
||||
# runs-on: ubuntu-20.04
|
||||
# if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
# timeout-minutes: 121
|
||||
# env:
|
||||
# VFLAGS: -cc musl-gcc
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -49,6 +50,7 @@ jobs:
|
|||
|
||||
macos:
|
||||
runs-on: macos-11
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
|
||||
macos-cross:
|
||||
runs-on: macOS-latest
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
@ -48,6 +49,7 @@ jobs:
|
|||
|
||||
linux-cross:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -101,6 +103,7 @@ jobs:
|
|||
|
||||
windows-cross:
|
||||
runs-on: windows-2019
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -74,6 +74,7 @@ concurrency:
|
|||
jobs:
|
||||
tests-sanitize-undefined-clang:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
@ -101,6 +102,7 @@ jobs:
|
|||
|
||||
tests-sanitize-undefined-gcc:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc gcc
|
||||
|
@ -127,6 +129,7 @@ jobs:
|
|||
|
||||
tests-sanitize-address-clang:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
@ -158,6 +161,7 @@ jobs:
|
|||
|
||||
tests-sanitize-address-msvc:
|
||||
runs-on: windows-2019
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc msvc
|
||||
|
@ -189,6 +193,7 @@ jobs:
|
|||
|
||||
tests-sanitize-address-gcc:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc gcc
|
||||
|
@ -220,6 +225,7 @@ jobs:
|
|||
|
||||
tests-sanitize-memory-clang:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VFLAGS: -cc clang
|
||||
|
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
run:
|
||||
name: Run
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
|
|
@ -16,6 +16,7 @@ jobs:
|
|||
|
||||
alpine-docker-musl-gcc:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
container:
|
||||
# Alpine docker pre-built container
|
||||
|
@ -50,6 +51,7 @@ jobs:
|
|||
|
||||
ubuntu-docker-musl:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
container:
|
||||
image: thevlang/vlang:ubuntu-build
|
||||
|
|
|
@ -10,6 +10,7 @@ on:
|
|||
jobs:
|
||||
build-vc:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
env:
|
||||
VREPO: github.com/vlang/vc.git
|
||||
steps:
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
gg-regressions:
|
||||
runs-on: ubuntu-18.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
VFLAGS: -cc tcc
|
||||
|
|
|
@ -15,6 +15,7 @@ concurrency:
|
|||
jobs:
|
||||
no-gpl-by-accident:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -24,6 +25,7 @@ jobs:
|
|||
|
||||
code-formatting:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
VFLAGS: -cc gcc
|
||||
|
@ -40,6 +42,7 @@ jobs:
|
|||
|
||||
performance-regressions:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
VFLAGS: -cc gcc
|
||||
|
@ -64,6 +67,7 @@ jobs:
|
|||
|
||||
misc-tooling:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
@ -112,6 +116,7 @@ jobs:
|
|||
|
||||
parser-silent:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -16,6 +16,7 @@ jobs:
|
|||
|
||||
space-paths-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
MY_V_PATH: '你好 my $path, @с интервали'
|
||||
|
@ -41,6 +42,7 @@ jobs:
|
|||
|
||||
space-paths-macos:
|
||||
runs-on: macOS-latest
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
MY_V_PATH: '你好 my $path, @с интервали'
|
||||
|
@ -69,6 +71,7 @@ jobs:
|
|||
|
||||
space-paths-windows:
|
||||
runs-on: windows-2022
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
MY_V_PATH: 'path with some $punctuation, and some spaces'
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
v-compiles-sdl-examples:
|
||||
runs-on: ubuntu-18.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
VFLAGS: -cc tcc
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
toml-module-pass-external-test-suites:
|
||||
runs-on: ubuntu-18.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
TOML_BS_TESTS_PATH: vlib/toml/tests/testdata/burntsushi/toml-test
|
||||
|
|
|
@ -9,12 +9,13 @@ on:
|
|||
- "**.md"
|
||||
|
||||
concurrency:
|
||||
group: build-other-${{ github.event.pull_request.number || github.sha }}
|
||||
group: build-v-apps-and-modules-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
v-apps-compile:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
vab-compiles-v-examples:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VAB_FLAGS: --api 30 --build-tools 29.0.0 -v 3
|
||||
|
|
|
@ -13,6 +13,7 @@ on:
|
|||
jobs:
|
||||
vinix-build:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
jobs:
|
||||
websocket_tests:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||
timeout-minutes: 121
|
||||
env:
|
||||
VFLAGS: -cc tcc -no-retry-compilation
|
||||
|
|
|
@ -207,7 +207,7 @@ fn change_detection_loop(ocontext &Context) {
|
|||
}
|
||||
|
||||
fn (mut context Context) kill_pgroup() {
|
||||
if context.child_process == 0 {
|
||||
if unsafe { context.child_process == 0 } {
|
||||
return
|
||||
}
|
||||
if context.child_process.is_alive() {
|
||||
|
|
|
@ -239,7 +239,15 @@ see also `v help build`.
|
|||
|
||||
-dump-c-flags file.txt
|
||||
Write all C flags into `file.txt`, one flag per line.
|
||||
If `file.txt` is `-`, then write the flags to stdout, one flag per line.
|
||||
If `file.txt` is `-`, write to stdout instead.
|
||||
|
||||
-dump-modules file.txt
|
||||
Write all module names used by the program in `file.txt`, one module per line.
|
||||
If `file.txt` is `-`, write to stdout instead.
|
||||
|
||||
-dump-files file.txt
|
||||
Write all used V file paths used by the program in `file.txt`, one module per line.
|
||||
If `file.txt` is `-`, write to stdout instead.
|
||||
|
||||
-no-rsp
|
||||
By default, V passes all C compiler options to the backend C compiler
|
||||
|
|
|
@ -7,6 +7,8 @@ const pwidth = 800
|
|||
|
||||
const pheight = 600
|
||||
|
||||
const chunk_height = 2 // the image is recalculated in chunks, each chunk processed in a separate thread
|
||||
|
||||
const zoom_factor = 1.1
|
||||
|
||||
struct ViewRect {
|
||||
|
@ -17,22 +19,47 @@ mut:
|
|||
y_max f64
|
||||
}
|
||||
|
||||
fn (v &ViewRect) width() f64 {
|
||||
return v.x_max - v.x_min
|
||||
}
|
||||
|
||||
fn (v &ViewRect) height() f64 {
|
||||
return v.y_max - v.y_min
|
||||
}
|
||||
|
||||
struct AppState {
|
||||
mut:
|
||||
gg &gg.Context = 0
|
||||
iidx int
|
||||
pixels []u32 = []u32{len: pwidth * pheight}
|
||||
npixels []u32 = []u32{len: pwidth * pheight} // all drawing happens here, results are copied at the end
|
||||
pixels &u32 = unsafe { vcalloc(pwidth * pheight * sizeof(u32)) }
|
||||
npixels &u32 = unsafe { vcalloc(pwidth * pheight * sizeof(u32)) } // all drawing happens here, results are swapped at the end
|
||||
view ViewRect = ViewRect{-2.7610033817025625, 1.1788897130338223, -1.824584023871934, 2.1153096311072788}
|
||||
ntasks int = runtime.nr_jobs()
|
||||
}
|
||||
|
||||
const colors = [gx.black, gx.blue, gx.red, gx.green, gx.yellow, gx.orange, gx.purple, gx.white,
|
||||
gx.indigo, gx.violet, gx.black]
|
||||
gx.indigo, gx.violet, gx.black].map(u32(it.abgr8()))
|
||||
|
||||
struct MandelChunk {
|
||||
cview ViewRect
|
||||
ymin f64
|
||||
ymax f64
|
||||
}
|
||||
|
||||
fn (mut state AppState) update() {
|
||||
mut sw := time.new_stopwatch()
|
||||
mut chunk_channel := chan MandelChunk{cap: state.ntasks}
|
||||
mut chunk_ready_channel := chan bool{cap: 1000}
|
||||
mut threads := []thread{cap: state.ntasks}
|
||||
defer {
|
||||
chunk_channel.close()
|
||||
threads.wait()
|
||||
}
|
||||
for t in 0 .. state.ntasks {
|
||||
threads << go state.worker(t, chunk_channel, chunk_ready_channel)
|
||||
}
|
||||
//
|
||||
mut oview := ViewRect{}
|
||||
mut sw := time.new_stopwatch()
|
||||
for {
|
||||
sw.restart()
|
||||
cview := state.view
|
||||
|
@ -40,39 +67,56 @@ fn (mut state AppState) update() {
|
|||
time.sleep(5 * time.millisecond)
|
||||
continue
|
||||
}
|
||||
sheight := pheight / state.ntasks
|
||||
mut threads := []thread{}
|
||||
for start := 0; start < pheight; start += sheight {
|
||||
threads << go state.recalc_lines(cview, start, start + sheight)
|
||||
// schedule chunks, describing the work:
|
||||
mut nchunks := 0
|
||||
for start := 0; start < pheight; start += chunk_height {
|
||||
chunk_channel <- MandelChunk{
|
||||
cview: cview
|
||||
ymin: start
|
||||
ymax: start + chunk_height
|
||||
}
|
||||
nchunks++
|
||||
}
|
||||
threads.wait()
|
||||
state.pixels = state.npixels
|
||||
// wait for all chunks to be processed:
|
||||
for _ in 0 .. nchunks {
|
||||
_ := <-chunk_ready_channel
|
||||
}
|
||||
// everything is done, swap the buffer pointers
|
||||
state.pixels, state.npixels = state.npixels, state.pixels
|
||||
println('$state.ntasks threads; $sw.elapsed().milliseconds() ms / frame')
|
||||
oview = cview
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut state AppState) recalc_lines(cview ViewRect, ymin f64, ymax f64) {
|
||||
for y_pixel := ymin; y_pixel < ymax && y_pixel < pheight; y_pixel++ {
|
||||
y0 := (y_pixel / pheight) * (cview.y_max - cview.y_min) + cview.y_min
|
||||
for x_pixel := 0.0; x_pixel < pwidth; x_pixel++ {
|
||||
x0 := (x_pixel / pwidth) * (cview.x_max - cview.x_min) + cview.x_min
|
||||
mut x, mut y := x0, y0
|
||||
mut iter := 0
|
||||
for ; iter < 80; iter++ {
|
||||
x, y = x * x - y * y + x0, 2 * x * y + y0
|
||||
if x * x + y * y > 4 {
|
||||
break
|
||||
fn (mut state AppState) worker(id int, input chan MandelChunk, ready chan bool) {
|
||||
for {
|
||||
chunk := <-input or { break }
|
||||
yscale := chunk.cview.height() / pheight
|
||||
xscale := chunk.cview.width() / pwidth
|
||||
for y_pixel := chunk.ymin; y_pixel < chunk.ymax && y_pixel < pheight; y_pixel++ {
|
||||
y0 := y_pixel * yscale + chunk.cview.y_min
|
||||
for x_pixel := 0.0; x_pixel < pwidth; x_pixel++ {
|
||||
x0 := x_pixel * xscale + chunk.cview.x_min
|
||||
mut x, mut y := x0, y0
|
||||
mut iter := 0
|
||||
for ; iter < 80; iter++ {
|
||||
x, y = x * x - y * y + x0, 2 * x * y + y0
|
||||
if x * x + y * y > 4 {
|
||||
break
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
state.npixels[int(y_pixel * pwidth) + int(x_pixel)] = colors[iter & 7]
|
||||
}
|
||||
}
|
||||
state.npixels[int(y_pixel) * pwidth + int(x_pixel)] = u32(colors[iter % 8].abgr8())
|
||||
}
|
||||
ready <- true
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut state AppState) draw() {
|
||||
mut istream_image := state.gg.get_cached_image_by_idx(state.iidx)
|
||||
istream_image.update_pixel_data(&state.pixels[0])
|
||||
istream_image.update_pixel_data(state.pixels)
|
||||
size := gg.window_size()
|
||||
state.gg.draw_image(0, 0, size.width, size.height, istream_image)
|
||||
}
|
||||
|
@ -110,8 +154,8 @@ fn graphics_frame(mut state AppState) {
|
|||
fn graphics_click(x f32, y f32, btn gg.MouseButton, mut state AppState) {
|
||||
if btn == .right {
|
||||
size := gg.window_size()
|
||||
m_x := (x / size.width) * (state.view.x_max - state.view.x_min) + state.view.x_min
|
||||
m_y := (y / size.height) * (state.view.y_max - state.view.y_min) + state.view.y_min
|
||||
m_x := (x / size.width) * state.view.width() + state.view.x_min
|
||||
m_y := (y / size.height) * state.view.height() + state.view.y_min
|
||||
state.center(m_x, m_y)
|
||||
}
|
||||
}
|
||||
|
@ -119,8 +163,8 @@ fn graphics_click(x f32, y f32, btn gg.MouseButton, mut state AppState) {
|
|||
fn graphics_move(x f32, y f32, mut state AppState) {
|
||||
if state.gg.mouse_buttons.has(.left) {
|
||||
size := gg.window_size()
|
||||
d_x := (f64(state.gg.mouse_dx) / size.width) * (state.view.x_max - state.view.x_min)
|
||||
d_y := (f64(state.gg.mouse_dy) / size.height) * (state.view.y_max - state.view.y_min)
|
||||
d_x := (f64(state.gg.mouse_dx) / size.width) * state.view.width()
|
||||
d_y := (f64(state.gg.mouse_dy) / size.height) * state.view.height()
|
||||
state.view.x_min -= d_x
|
||||
state.view.x_max -= d_x
|
||||
state.view.y_min -= d_y
|
||||
|
@ -133,8 +177,8 @@ fn graphics_scroll(e &gg.Event, mut state AppState) {
|
|||
}
|
||||
|
||||
fn graphics_keydown(code gg.KeyCode, mod gg.Modifier, mut state AppState) {
|
||||
s_x := (state.view.x_max - state.view.x_min) / 5
|
||||
s_y := (state.view.y_max - state.view.y_min) / 5
|
||||
s_x := state.view.width() / 5
|
||||
s_y := state.view.height() / 5
|
||||
// movement
|
||||
mut d_x, mut d_y := 0.0, 0.0
|
||||
if code == .enter {
|
||||
|
|
|
@ -95,7 +95,7 @@ pub fn (mut s System) explode(x f32, y f32) {
|
|||
|
||||
pub fn (mut s System) free() {
|
||||
for p in s.pool {
|
||||
if p == 0 {
|
||||
if unsafe { p == 0 } {
|
||||
print(ptr_str(p) + ' ouch')
|
||||
continue
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ pub fn (mut s System) free() {
|
|||
}
|
||||
s.pool.clear()
|
||||
for p in s.bin {
|
||||
if p == 0 {
|
||||
if unsafe { p == 0 } {
|
||||
print(ptr_str(p) + ' ouch')
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/*
|
||||
Compability header for stdatomic.h that works for all compilers supported
|
||||
by V. For TCC libatomic from the operating system is used
|
||||
|
||||
Compatibility header for stdatomic.h that works for all compilers supported by V.
|
||||
For TCC, we use libatomic from the OS.
|
||||
*/
|
||||
#ifndef __ATOMIC_H
|
||||
#define __ATOMIC_H
|
||||
|
|
|
@ -59,14 +59,13 @@ $if dynamic_boehm ? {
|
|||
#flag $first_existing("/usr/local/lib/libgc.a", "/usr/lib/libgc.a")
|
||||
#flag -lpthread
|
||||
} $else $if windows {
|
||||
#flag -DGC_NOT_DLL=1
|
||||
#flag -DGC_WIN32_THREADS=1
|
||||
$if tinyc {
|
||||
#flag -I@VEXEROOT/thirdparty/libgc/include
|
||||
#flag -L@VEXEROOT/thirdparty/tcc/lib
|
||||
#flag -lgc
|
||||
#flag @VEXEROOT/thirdparty/tcc/lib/libgc.a
|
||||
#flag -luser32
|
||||
} $else {
|
||||
#flag -DGC_NOT_DLL=1
|
||||
#flag -DGC_WIN32_THREADS=1
|
||||
#flag -DGC_BUILTIN_ATOMIC=1
|
||||
#flag -I@VEXEROOT/thirdparty/libgc/include
|
||||
#flag @VEXEROOT/thirdparty/libgc/gc.o
|
||||
}
|
||||
|
|
|
@ -113,14 +113,6 @@ struct Option {
|
|||
// derived Option_xxx types
|
||||
}
|
||||
|
||||
fn opt_ok(data voidptr, mut option Option, size int) {
|
||||
unsafe {
|
||||
*option = Option{}
|
||||
// use err to get the end of OptionBase and then memcpy into it
|
||||
vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
|
||||
}
|
||||
}
|
||||
|
||||
// option is the base of V's internal optional return system.
|
||||
struct _option {
|
||||
state u8
|
||||
|
@ -130,6 +122,14 @@ struct _option {
|
|||
// derived _option_xxx types
|
||||
}
|
||||
|
||||
fn _option_ok(data voidptr, mut option _option, size int) {
|
||||
unsafe {
|
||||
*option = _option{}
|
||||
// use err to get the end of OptionBase and then memcpy into it
|
||||
vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
|
||||
}
|
||||
}
|
||||
|
||||
fn opt_ok2(data voidptr, mut option _option, size int) {
|
||||
unsafe {
|
||||
*option = _option{}
|
||||
|
|
|
@ -32,9 +32,10 @@ mut:
|
|||
[unsafe]
|
||||
fn vmemory_block_new(prev &VMemoryBlock, at_least isize) &VMemoryBlock {
|
||||
mut v := unsafe { &VMemoryBlock(C.calloc(1, sizeof(VMemoryBlock))) }
|
||||
if prev != 0 {
|
||||
if unsafe { prev != 0 } {
|
||||
v.id = prev.id + 1
|
||||
}
|
||||
|
||||
v.previous = prev
|
||||
block_size := if at_least < prealloc_block_size { prealloc_block_size } else { at_least }
|
||||
v.start = unsafe { C.malloc(block_size) }
|
||||
|
@ -79,7 +80,7 @@ fn prealloc_vcleanup() {
|
|||
// The second loop however should *not* allocate at all.
|
||||
mut nr_mallocs := i64(0)
|
||||
mut mb := g_memory_block
|
||||
for mb != 0 {
|
||||
for unsafe { mb != 0 } {
|
||||
nr_mallocs += mb.mallocs
|
||||
eprintln('> freeing mb.id: ${mb.id:3} | cap: ${mb.cap:7} | rem: ${mb.remaining:7} | start: ${voidptr(mb.start)} | current: ${voidptr(mb.current)} | diff: ${u64(mb.current) - u64(mb.start):7} bytes | mallocs: $mb.mallocs')
|
||||
mb = mb.previous
|
||||
|
|
|
@ -37,26 +37,26 @@ pub enum StrIntpType {
|
|||
}
|
||||
|
||||
pub fn (x StrIntpType) str() string {
|
||||
match x {
|
||||
.si_no_str { return 'no_str' }
|
||||
.si_c { return 'c' }
|
||||
.si_u8 { return 'u8' }
|
||||
.si_i8 { return 'i8' }
|
||||
.si_u16 { return 'u16' }
|
||||
.si_i16 { return 'i16' }
|
||||
.si_u32 { return 'u32' }
|
||||
.si_i32 { return 'i32' }
|
||||
.si_u64 { return 'u64' }
|
||||
.si_i64 { return 'i64' }
|
||||
.si_f32 { return 'f32' }
|
||||
.si_f64 { return 'f64' }
|
||||
.si_g32 { return 'f32' } // g32 format use f32 data
|
||||
.si_g64 { return 'f64' } // g64 format use f64 data
|
||||
.si_e32 { return 'f32' } // e32 format use f32 data
|
||||
.si_e64 { return 'f64' } // e64 format use f64 data
|
||||
.si_s { return 's' }
|
||||
.si_p { return 'p' }
|
||||
.si_vp { return 'vp' }
|
||||
return match x {
|
||||
.si_no_str { 'no_str' }
|
||||
.si_c { 'c' }
|
||||
.si_u8 { 'u8' }
|
||||
.si_i8 { 'i8' }
|
||||
.si_u16 { 'u16' }
|
||||
.si_i16 { 'i16' }
|
||||
.si_u32 { 'u32' }
|
||||
.si_i32 { 'i32' }
|
||||
.si_u64 { 'u64' }
|
||||
.si_i64 { 'i64' }
|
||||
.si_f32 { 'f32' }
|
||||
.si_f64 { 'f64' }
|
||||
.si_g32 { 'f32' } // g32 format use f32 data
|
||||
.si_g64 { 'f64' } // g64 format use f64 data
|
||||
.si_e32 { 'f32' } // e32 format use f32 data
|
||||
.si_e64 { 'f64' } // e64 format use f64 data
|
||||
.si_s { 's' }
|
||||
.si_p { 'p' }
|
||||
.si_vp { 'vp' }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ pub fn (cmd Command) str() string {
|
|||
res << ' cb execute: $cmd.execute'
|
||||
res << ' cb pre_execute: $cmd.pre_execute'
|
||||
res << ' cb post_execute: $cmd.post_execute'
|
||||
if cmd.parent == 0 {
|
||||
if unsafe { cmd.parent == 0 } {
|
||||
res << ' parent: &Command(0)'
|
||||
} else {
|
||||
res << ' parent: &Command{$cmd.parent.name ...}'
|
||||
|
|
|
@ -49,7 +49,7 @@ pub fn print_help_for_command(help_cmd Command) ? {
|
|||
}
|
||||
print(cmd.help_message())
|
||||
} else {
|
||||
if help_cmd.parent != 0 {
|
||||
if unsafe { help_cmd.parent != 0 } {
|
||||
print(help_cmd.parent.help_message())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pub fn print_manpage_for_command(man_cmd Command) ? {
|
|||
}
|
||||
print(cmd.manpage())
|
||||
} else {
|
||||
if man_cmd.parent != 0 {
|
||||
if unsafe { man_cmd.parent != 0 } {
|
||||
print(man_cmd.parent.manpage())
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ pub fn (cmd Command) manpage() string {
|
|||
mdoc += '.Os\n.Sh NAME\n.Nm ${cmd.full_name().replace(' ', '-')}\n.Nd $cmd.description\n'
|
||||
mdoc += '.Sh SYNOPSIS\n'
|
||||
mdoc += '.Nm $cmd.root().name\n'
|
||||
if cmd.parent != 0 {
|
||||
if unsafe { cmd.parent != 0 } {
|
||||
mut parents := []Command{}
|
||||
if !cmd.parent.is_root() {
|
||||
parents.prepend(cmd.parent)
|
||||
|
@ -96,7 +96,7 @@ pub fn (cmd Command) manpage() string {
|
|||
}
|
||||
if cmd.commands.len > 0 {
|
||||
mdoc += '.Nm $cmd.root().name\n'
|
||||
if cmd.parent != 0 {
|
||||
if unsafe { cmd.parent != 0 } {
|
||||
mut parents := []Command{}
|
||||
if !cmd.parent.is_root() {
|
||||
parents.prepend(cmd.parent)
|
||||
|
@ -158,7 +158,7 @@ pub fn (cmd Command) manpage() string {
|
|||
if cmd.commands.len > 0 {
|
||||
mdoc += '.Sh SEE ALSO\n'
|
||||
mut cmds := []string{}
|
||||
if cmd.parent != 0 {
|
||||
if unsafe { cmd.parent != 0 } {
|
||||
cmds << cmd.parent.full_name().replace(' ', '-')
|
||||
}
|
||||
for c in cmd.commands {
|
||||
|
|
|
@ -76,13 +76,13 @@ pub fn (mut bst BSTree<T>) insert(value T) bool {
|
|||
// insert_helper walks the tree and inserts the given node.
|
||||
fn (mut bst BSTree<T>) insert_helper(mut node BSTreeNode<T>, value T) bool {
|
||||
if node.value < value {
|
||||
if node.right != 0 && node.right.is_init {
|
||||
if unsafe { node.right != 0 } && node.right.is_init {
|
||||
return bst.insert_helper(mut node.right, value)
|
||||
}
|
||||
node.right = new_node(node, value)
|
||||
return true
|
||||
} else if node.value > value {
|
||||
if node.left != 0 && node.left.is_init {
|
||||
if unsafe { node.left != 0 } && node.left.is_init {
|
||||
return bst.insert_helper(mut node.left, value)
|
||||
}
|
||||
node.left = new_node(node, value)
|
||||
|
@ -99,7 +99,7 @@ pub fn (bst &BSTree<T>) contains(value T) bool {
|
|||
// contains_helper is a helper function to walk the tree, and return
|
||||
// the absence or presence of the `value`.
|
||||
fn (bst &BSTree<T>) contains_helper(node &BSTreeNode<T>, value T) bool {
|
||||
if node == 0 || !node.is_init {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return false
|
||||
}
|
||||
if node.value < value {
|
||||
|
@ -124,12 +124,12 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
|||
return false
|
||||
}
|
||||
if node.value == value {
|
||||
if node.left != 0 && node.left.is_init {
|
||||
if unsafe { node.left != 0 } && node.left.is_init {
|
||||
// In order to remove the element we need to bring up as parent the max of the
|
||||
// left sub-tree.
|
||||
mut max_node := bst.get_max_from_right(node.left)
|
||||
node.bind(mut max_node, true)
|
||||
} else if node.right != 0 && node.right.is_init {
|
||||
} else if unsafe { node.right != 0 } && node.right.is_init {
|
||||
// Bring up the element with the minimum value in the right sub-tree.
|
||||
mut min_node := bst.get_min_from_left(node.right)
|
||||
node.bind(mut min_node, false)
|
||||
|
@ -153,11 +153,11 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
|||
|
||||
// get_max_from_right returns the max element of the BST following the right branch.
|
||||
fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
if node == 0 {
|
||||
if unsafe { node == 0 } {
|
||||
return new_none_node<T>(false)
|
||||
}
|
||||
right_node := node.right
|
||||
if right_node == 0 || !right_node.is_init {
|
||||
if unsafe { right_node == 0 } || !right_node.is_init {
|
||||
return node
|
||||
}
|
||||
return bst.get_max_from_right(right_node)
|
||||
|
@ -165,11 +165,11 @@ fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
|||
|
||||
// get_min_from_left returns the min element of the BST by following the left branch.
|
||||
fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||
if node == 0 {
|
||||
if unsafe { node == 0 } {
|
||||
return new_none_node<T>(false)
|
||||
}
|
||||
left_node := node.left
|
||||
if left_node == 0 || !left_node.is_init {
|
||||
if unsafe { left_node == 0 } || !left_node.is_init {
|
||||
return node
|
||||
}
|
||||
return bst.get_min_from_left(left_node)
|
||||
|
@ -177,7 +177,7 @@ fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
|||
|
||||
// is_empty checks if the BST is empty
|
||||
pub fn (bst &BSTree<T>) is_empty() bool {
|
||||
return bst.root == 0
|
||||
return unsafe { bst.root == 0 }
|
||||
}
|
||||
|
||||
// in_order_traversal traverses the BST in order, and returns the result as an array.
|
||||
|
@ -189,7 +189,7 @@ pub fn (bst &BSTree<T>) in_order_traversal() []T {
|
|||
|
||||
// in_order_traversal_helper helps traverse the BST, and accumulates the result in the `result` array.
|
||||
fn (bst &BSTree<T>) in_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
if node == 0 || !node.is_init {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
bst.in_order_traversal_helper(node.left, mut result)
|
||||
|
@ -207,7 +207,7 @@ pub fn (bst &BSTree<T>) post_order_traversal() []T {
|
|||
// post_order_traversal_helper is a helper function that traverses the BST in post order,
|
||||
// accumulating the result in an array.
|
||||
fn (bst &BSTree<T>) post_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
if node == 0 || !node.is_init {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ pub fn (bst &BSTree<T>) pre_order_traversal() []T {
|
|||
// pre_order_traversal_helper is a helper function to traverse the BST
|
||||
// in pre order and accumulates the results in an array.
|
||||
fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||
if node == 0 || !node.is_init {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return
|
||||
}
|
||||
result << node.value
|
||||
|
@ -236,7 +236,7 @@ fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result [
|
|||
|
||||
// get_node is a helper method to ge the internal rapresentation of the node with the `value`.
|
||||
fn (bst &BSTree<T>) get_node(node &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||
if node == 0 || !node.is_init {
|
||||
if unsafe { node == 0 } || !node.is_init {
|
||||
return new_none_node<T>(false)
|
||||
}
|
||||
if node.value == value {
|
||||
|
|
|
@ -251,7 +251,7 @@ pub fn (mut list DoublyLinkedList<T>) delete(idx int) {
|
|||
pub fn (list DoublyLinkedList<T>) str() string {
|
||||
mut result_array := []T{}
|
||||
mut node := list.head
|
||||
for node != 0 {
|
||||
for unsafe { node != 0 } {
|
||||
result_array << node.data
|
||||
node = node.next
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@ pub fn (list LinkedList<T>) first() ?T {
|
|||
|
||||
// last returns the last element of the linked list
|
||||
pub fn (list LinkedList<T>) last() ?T {
|
||||
if list.head == 0 {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
mut node := list.head
|
||||
for node.next != 0 {
|
||||
for unsafe { node.next != 0 } {
|
||||
node = node.next
|
||||
}
|
||||
return node.data
|
||||
|
@ -42,12 +42,12 @@ pub fn (list LinkedList<T>) last() ?T {
|
|||
|
||||
// index returns the element at the given index of the linked list
|
||||
pub fn (list LinkedList<T>) index(idx int) ?T {
|
||||
if list.head == 0 {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
mut node := list.head
|
||||
mut iterations := 0
|
||||
for node.next != 0 && iterations < idx {
|
||||
for unsafe { node.next != 0 } && iterations < idx {
|
||||
node = node.next
|
||||
iterations++
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ pub fn (mut list LinkedList<T>) push(item T) {
|
|||
new_node := &ListNode<T>{
|
||||
data: item
|
||||
}
|
||||
if list.head == 0 {
|
||||
if unsafe { list.head == 0 } {
|
||||
// first node case
|
||||
list.head = new_node
|
||||
} else {
|
||||
mut node := list.head
|
||||
for node.next != 0 {
|
||||
for unsafe { node.next != 0 } {
|
||||
node = node.next
|
||||
}
|
||||
node.next = new_node
|
||||
|
@ -79,17 +79,17 @@ pub fn (mut list LinkedList<T>) push(item T) {
|
|||
|
||||
// pop removes the last element of the linked list
|
||||
pub fn (mut list LinkedList<T>) pop() ?T {
|
||||
if list.head == 0 {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
}
|
||||
mut node := list.head
|
||||
mut to_return := node.data
|
||||
if node.next == 0 {
|
||||
if unsafe { node.next == 0 } {
|
||||
// first node case
|
||||
// set to null
|
||||
list.head = voidptr(0)
|
||||
} else {
|
||||
for node.next.next != 0 {
|
||||
for unsafe { node.next.next != 0 } {
|
||||
node = node.next
|
||||
}
|
||||
to_return = node.next.data
|
||||
|
@ -102,7 +102,7 @@ pub fn (mut list LinkedList<T>) pop() ?T {
|
|||
|
||||
// shift removes the first element of the linked list
|
||||
pub fn (mut list LinkedList<T>) shift() ?T {
|
||||
if list.head == 0 {
|
||||
if unsafe { list.head == 0 } {
|
||||
return error('Linked list is empty')
|
||||
} else {
|
||||
list.len -= 1
|
||||
|
@ -149,7 +149,7 @@ pub fn (mut list LinkedList<T>) prepend(item T) {
|
|||
pub fn (list LinkedList<T>) str() string {
|
||||
mut result_array := []T{}
|
||||
mut node := list.head
|
||||
for node != 0 {
|
||||
for unsafe { node != 0 } {
|
||||
result_array << node.data
|
||||
node = node.next
|
||||
}
|
||||
|
|
|
@ -71,6 +71,11 @@ fn decode_i64(root &C.cJSON) i64 {
|
|||
return i64(root.valuedouble) // i64 is double in C
|
||||
}
|
||||
|
||||
// TODO: remove when `byte` is removed
|
||||
fn decode_byte(root &C.cJSON) byte {
|
||||
return byte(decode_u8(root))
|
||||
}
|
||||
|
||||
fn decode_u8(root &C.cJSON) u8 {
|
||||
if isnil(root) {
|
||||
return u8(0)
|
||||
|
@ -132,8 +137,6 @@ fn decode_string(root &C.cJSON) string {
|
|||
if isnil(root.valuestring) {
|
||||
return ''
|
||||
}
|
||||
// println('decode string valuestring="$root.valuestring"')
|
||||
// return tos(root.valuestring, _strlen(root.valuestring))
|
||||
return unsafe { tos_clone(&u8(root.valuestring)) } // , _strlen(root.valuestring))
|
||||
}
|
||||
|
||||
|
@ -145,6 +148,7 @@ fn decode_bool(root &C.cJSON) bool {
|
|||
}
|
||||
|
||||
// ///////////////////
|
||||
|
||||
fn encode_int(val int) &C.cJSON {
|
||||
return C.cJSON_CreateNumber(val)
|
||||
}
|
||||
|
@ -161,6 +165,11 @@ fn encode_i64(val i64) &C.cJSON {
|
|||
return C.cJSON_CreateNumber(val)
|
||||
}
|
||||
|
||||
// TODO: remove when `byte` is removed
|
||||
fn encode_byte(root byte) &C.cJSON {
|
||||
return encode_u8(u8(root))
|
||||
}
|
||||
|
||||
fn encode_u8(val u8) &C.cJSON {
|
||||
return C.cJSON_CreateNumber(val)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,25 @@ fn test_simple() ? {
|
|||
assert y.title == .worker
|
||||
}
|
||||
|
||||
const currency_id = 'cconst'
|
||||
|
||||
struct Price {
|
||||
net f64
|
||||
currency_id string [json: currencyId] = currency_id
|
||||
}
|
||||
|
||||
fn test_field_with_default_expr() ? {
|
||||
data := '[{"net":1},{"net":2,"currencyId":"cjson"}]'
|
||||
prices := json.decode([]Price, data)?
|
||||
assert prices == [Price{
|
||||
net: 1
|
||||
currency_id: 'cconst'
|
||||
}, Price{
|
||||
net: 2
|
||||
currency_id: 'cjson'
|
||||
}]
|
||||
}
|
||||
|
||||
fn test_decode_top_level_array() {
|
||||
s := '[{"name":"Peter", "age": 29}, {"name":"Bob", "age":31}]'
|
||||
x := json.decode([]Employee, s) or { panic(err) }
|
||||
|
@ -454,3 +473,11 @@ fn test_encode_sumtype_defined_ahead() {
|
|||
println(ret)
|
||||
assert ret == '{"value":0,"_type":"GPScale"}'
|
||||
}
|
||||
|
||||
struct StByteArray {
|
||||
ba []byte
|
||||
}
|
||||
|
||||
fn test_byte_array() {
|
||||
assert json.encode(StByteArray{ ba: [byte(1), 2, 3, 4, 5] }) == '{"ba":[1,2,3,4,5]}'
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ pub fn exp2(x f64) f64 {
|
|||
return expmulti(hi, lo, k)
|
||||
}
|
||||
|
||||
// ldexp calculates frac*(2**exp)
|
||||
pub fn ldexp(frac f64, exp int) f64 {
|
||||
return scalbn(frac, exp)
|
||||
}
|
||||
|
@ -146,6 +147,7 @@ pub fn frexp(x f64) (f64, int) {
|
|||
return f64_from_bits(y), e_
|
||||
}
|
||||
|
||||
// expm1 calculates e**x - 1
|
||||
// special cases are:
|
||||
// expm1(+inf) = +inf
|
||||
// expm1(-inf) = -1
|
||||
|
@ -176,7 +178,6 @@ pub fn expm1(x f64) f64 {
|
|||
}
|
||||
}
|
||||
|
||||
// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
|
||||
fn expmulti(hi f64, lo f64, k int) f64 {
|
||||
exp_p1 := 1.66666666666666657415e-01 // 0x3FC55555; 0x55555555
|
||||
exp_p2 := -2.77777777770155933842e-03 // 0xBF66C16C; 0x16BEBD93
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module math
|
||||
|
||||
// hypot returns the hypotenuse of the triangle give two sides
|
||||
pub fn hypot(x f64, y f64) f64 {
|
||||
if is_inf(x, 0) || is_inf(y, 0) {
|
||||
return inf(1)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module math
|
||||
|
||||
import math.internal
|
||||
// acosh returns the non negative area hyperbolic cosine of x
|
||||
|
||||
pub fn acosh(x f64) f64 {
|
||||
if x == 0.0 {
|
||||
|
@ -19,6 +20,7 @@ pub fn acosh(x f64) f64 {
|
|||
}
|
||||
}
|
||||
|
||||
// asinh returns the area hyperbolic sine of x
|
||||
pub fn asinh(x f64) f64 {
|
||||
a := abs(x)
|
||||
s := if x < 0 { -1.0 } else { 1.0 }
|
||||
|
@ -34,6 +36,7 @@ pub fn asinh(x f64) f64 {
|
|||
}
|
||||
}
|
||||
|
||||
// atanh returns the area hyperbolic tangent of x
|
||||
pub fn atanh(x f64) f64 {
|
||||
a := abs(x)
|
||||
s := if x < 0 { -1.0 } else { 1.0 }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module math
|
||||
|
||||
// log_n returns log base b of x
|
||||
pub fn log_n(x f64, b f64) f64 {
|
||||
y := log(x)
|
||||
z := log(b)
|
||||
|
@ -24,6 +25,7 @@ pub fn log2(x f64) f64 {
|
|||
return log(frac) * (1.0 / ln2) + f64(exp)
|
||||
}
|
||||
|
||||
// log1p returns log(1+x)
|
||||
pub fn log1p(x f64) f64 {
|
||||
y := 1.0 + x
|
||||
z := y - 1.0
|
||||
|
|
|
@ -155,6 +155,7 @@ pub fn signbit(x f64) bool {
|
|||
return f64_bits(x) & sign_mask != 0
|
||||
}
|
||||
|
||||
// tolerance checks if a and b difference are less than or equal to the tolerance value
|
||||
pub fn tolerance(a f64, b f64, tol f64) bool {
|
||||
mut ee := tol
|
||||
// Multiplying by ee here can underflow denormal values to zero.
|
||||
|
@ -178,14 +179,17 @@ pub fn tolerance(a f64, b f64, tol f64) bool {
|
|||
return d < ee
|
||||
}
|
||||
|
||||
// close checks if a and b are within 1e-14 of each other
|
||||
pub fn close(a f64, b f64) bool {
|
||||
return tolerance(a, b, 1e-14)
|
||||
}
|
||||
|
||||
// veryclose checks if a and b are within 4e-16 of each other
|
||||
pub fn veryclose(a f64, b f64) bool {
|
||||
return tolerance(a, b, 4e-16)
|
||||
}
|
||||
|
||||
// alike checks if a and b are equal
|
||||
pub fn alike(a f64, b f64) bool {
|
||||
if is_nan(a) && is_nan(b) {
|
||||
return true
|
||||
|
|
|
@ -4,13 +4,13 @@ fn C.cosf(x f32) f32
|
|||
|
||||
fn C.sinf(x f32) f32
|
||||
|
||||
// cosf calculates cosine. (float32)
|
||||
// cosf calculates cosine in radians (float32)
|
||||
[inline]
|
||||
pub fn cosf(a f32) f32 {
|
||||
return C.cosf(a)
|
||||
}
|
||||
|
||||
// sinf calculates sine. (float32)
|
||||
// sinf calculates sine in radians (float32)
|
||||
[inline]
|
||||
pub fn sinf(a f32) f32 {
|
||||
return C.sinf(a)
|
||||
|
|
|
@ -4,13 +4,13 @@ fn JS.Math.cos(x f64) f64
|
|||
|
||||
fn JS.Math.sin(x f64) f64
|
||||
|
||||
// cos calculates cosine.
|
||||
// cos calculates cosine in radians
|
||||
[inline]
|
||||
pub fn cos(a f64) f64 {
|
||||
return JS.Math.cos(a)
|
||||
}
|
||||
|
||||
// sin calculates sine.
|
||||
// sin calculates sine in radians
|
||||
[inline]
|
||||
pub fn sin(a f64) f64 {
|
||||
return JS.Math.sin(a)
|
||||
|
|
|
@ -44,6 +44,7 @@ const (
|
|||
}
|
||||
)
|
||||
|
||||
// sin calculates the sine of the angle in radians
|
||||
pub fn sin(x f64) f64 {
|
||||
p1 := 7.85398125648498535156e-1
|
||||
p2 := 3.77489470793079817668e-8
|
||||
|
@ -82,6 +83,7 @@ pub fn sin(x f64) f64 {
|
|||
}
|
||||
}
|
||||
|
||||
// cos calculates the cosine of the angle in radians
|
||||
pub fn cos(x f64) f64 {
|
||||
p1 := 7.85398125648498535156e-1
|
||||
p2 := 3.77489470793079817668e-8
|
||||
|
@ -122,18 +124,19 @@ pub fn cos(x f64) f64 {
|
|||
}
|
||||
}
|
||||
|
||||
// cosf calculates cosine. (float32).
|
||||
// cosf calculates cosine in radians (float32).
|
||||
[inline]
|
||||
pub fn cosf(a f32) f32 {
|
||||
return f32(cos(a))
|
||||
}
|
||||
|
||||
// sinf calculates sine. (float32)
|
||||
// sinf calculates sine in radians (float32)
|
||||
[inline]
|
||||
pub fn sinf(a f32) f32 {
|
||||
return f32(sin(a))
|
||||
}
|
||||
|
||||
// sincos calculates the sine and cosine of the angle in radians
|
||||
pub fn sincos(x f64) (f64, f64) {
|
||||
p1 := 7.85398125648498535156e-1
|
||||
p2 := 3.77489470793079817668e-8
|
||||
|
|
|
@ -4,13 +4,13 @@ fn JS.Math.cosh(x f64) f64
|
|||
|
||||
fn JS.Math.sinh(x f64) f64
|
||||
|
||||
// cosh calculates hyperbolic cosine.
|
||||
// cosh calculates hyperbolic cosine in radians
|
||||
[inline]
|
||||
pub fn cosh(a f64) f64 {
|
||||
return JS.Math.cosh(a)
|
||||
}
|
||||
|
||||
// sinh calculates hyperbolic sine.
|
||||
// sinh calculates hyperbolic sine in radians
|
||||
[inline]
|
||||
pub fn sinh(a f64) f64 {
|
||||
return JS.Math.sinh(a)
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn sinh(x_ f64) f64 {
|
|||
return temp
|
||||
}
|
||||
|
||||
// cosh returns the hyperbolic cosine of x.
|
||||
// cosh returns the hyperbolic cosine of x in radians
|
||||
//
|
||||
// special cases are:
|
||||
// cosh(±0) = 1
|
||||
|
|
|
@ -2,7 +2,7 @@ module stats
|
|||
|
||||
import math
|
||||
|
||||
// Measure of Occurance
|
||||
// freq calculates the Measure of Occurance
|
||||
// Frequency of a given number
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/frequency-distribution.html
|
||||
|
@ -19,8 +19,8 @@ pub fn freq<T>(data []T, val T) int {
|
|||
return count
|
||||
}
|
||||
|
||||
// Measure of Central Tendancy
|
||||
// Mean of the given input array
|
||||
// mean calculates the average
|
||||
// of the given input array, sum(data)/data.len
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn mean<T>(data []T) T {
|
||||
|
@ -34,8 +34,8 @@ pub fn mean<T>(data []T) T {
|
|||
return sum / T(data.len)
|
||||
}
|
||||
|
||||
// Measure of Central Tendancy
|
||||
// Geometric Mean of the given input array
|
||||
// geometric_mean calculates the central tendency
|
||||
// of the given input array, product(data)**1/data.len
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/numbers/geometric-mean.html
|
||||
pub fn geometric_mean<T>(data []T) T {
|
||||
|
@ -49,8 +49,8 @@ pub fn geometric_mean<T>(data []T) T {
|
|||
return math.pow(sum, 1.0 / T(data.len))
|
||||
}
|
||||
|
||||
// Measure of Central Tendancy
|
||||
// Harmonic Mean of the given input array
|
||||
// harmonic_mean calculates the reciprocal of the average of reciprocals
|
||||
// of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/numbers/harmonic-mean.html
|
||||
pub fn harmonic_mean<T>(data []T) T {
|
||||
|
@ -64,8 +64,7 @@ pub fn harmonic_mean<T>(data []T) T {
|
|||
return T(data.len) / sum
|
||||
}
|
||||
|
||||
// Measure of Central Tendancy
|
||||
// Median of the given input array ( input array is assumed to be sorted )
|
||||
// median returns the middlemost value of the given input array ( input array is assumed to be sorted )
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn median<T>(sorted_data []T) T {
|
||||
|
@ -80,8 +79,7 @@ pub fn median<T>(sorted_data []T) T {
|
|||
}
|
||||
}
|
||||
|
||||
// Measure of Central Tendancy
|
||||
// Mode of the given input array
|
||||
// mode calculates the highest occuring value of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/central-measures.html
|
||||
pub fn mode<T>(data []T) T {
|
||||
|
@ -101,7 +99,7 @@ pub fn mode<T>(data []T) T {
|
|||
return data[max]
|
||||
}
|
||||
|
||||
// Root Mean Square of the given input array
|
||||
// rms, Root Mean Square, calculates the sqrt of the mean of the squares of the given input array
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Root_mean_square
|
||||
pub fn rms<T>(data []T) T {
|
||||
|
@ -115,8 +113,8 @@ pub fn rms<T>(data []T) T {
|
|||
return math.sqrt(sum / T(data.len))
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Population Variance of the given input array
|
||||
// population_variance is the Measure of Dispersion / Spread
|
||||
// of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
|
@ -128,8 +126,8 @@ pub fn population_variance<T>(data []T) T {
|
|||
return population_variance_mean<T>(data, data_mean)
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Population Variance of the given input array
|
||||
// population_variance_mean is the Measure of Dispersion / Spread
|
||||
// of the given input array, with the provided mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
pub fn population_variance_mean<T>(data []T, mean T) T {
|
||||
|
@ -143,8 +141,7 @@ pub fn population_variance_mean<T>(data []T, mean T) T {
|
|||
return sum / T(data.len)
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Sample Variance of the given input array
|
||||
// sample_variance calculates the spread of dataset around the mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
|
@ -156,8 +153,7 @@ pub fn sample_variance<T>(data []T) T {
|
|||
return sample_variance_mean<T>(data, data_mean)
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Sample Variance of the given input array
|
||||
// sample_variance calculates the spread of dataset around the provided mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
pub fn sample_variance_mean<T>(data []T, mean T) T {
|
||||
|
@ -171,8 +167,7 @@ pub fn sample_variance_mean<T>(data []T, mean T) T {
|
|||
return sum / T(data.len - 1)
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Population Standard Deviation of the given input array
|
||||
// population_stddev calculates how spread out the dataset is
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
|
@ -183,8 +178,7 @@ pub fn population_stddev<T>(data []T) T {
|
|||
return math.sqrt(population_variance<T>(data))
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Population Standard Deviation of the given input array
|
||||
// population_stddev_mean calculates how spread out the dataset is, with the provide mean
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/standard-deviation.html
|
||||
[inline]
|
||||
|
@ -219,8 +213,7 @@ pub fn sample_stddev_mean<T>(data []T, mean T) T {
|
|||
return T(math.sqrt(f64(sample_variance_mean<T>(data, mean))))
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Mean Absolute Deviation of the given input array
|
||||
// absdev calculates the average distance between each data point and the mean
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Average_absolute_deviation
|
||||
[inline]
|
||||
|
@ -232,8 +225,7 @@ pub fn absdev<T>(data []T) T {
|
|||
return absdev_mean<T>(data, data_mean)
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// Mean Absolute Deviation of the given input array
|
||||
// absdev_mean calculates the average distance between each data point and the provided mean
|
||||
// Based on
|
||||
// https://en.wikipedia.org/wiki/Average_absolute_deviation
|
||||
pub fn absdev_mean<T>(data []T, mean T) T {
|
||||
|
@ -247,7 +239,7 @@ pub fn absdev_mean<T>(data []T, mean T) T {
|
|||
return sum / T(data.len)
|
||||
}
|
||||
|
||||
// Sum of squares
|
||||
// tts, Sum of squares, calculates the sum over all squared differences between values and overall mean
|
||||
[inline]
|
||||
pub fn tss<T>(data []T) T {
|
||||
if data.len == 0 {
|
||||
|
@ -257,7 +249,7 @@ pub fn tss<T>(data []T) T {
|
|||
return tss_mean<T>(data, data_mean)
|
||||
}
|
||||
|
||||
// Sum of squares about the mean
|
||||
// tts_mean, Sum of squares, calculates the sum over all squared differences between values and the provided mean
|
||||
pub fn tss_mean<T>(data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
|
@ -269,7 +261,7 @@ pub fn tss_mean<T>(data []T, mean T) T {
|
|||
return tss
|
||||
}
|
||||
|
||||
// Minimum of the given input array
|
||||
// min finds the minimum value from the dataset
|
||||
pub fn min<T>(data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
|
@ -283,7 +275,7 @@ pub fn min<T>(data []T) T {
|
|||
return min
|
||||
}
|
||||
|
||||
// Maximum of the given input array
|
||||
// max finds the maximum value from the dataset
|
||||
pub fn max<T>(data []T) T {
|
||||
if data.len == 0 {
|
||||
return T(0)
|
||||
|
@ -297,7 +289,7 @@ pub fn max<T>(data []T) T {
|
|||
return max
|
||||
}
|
||||
|
||||
// Minimum and maximum of the given input array
|
||||
// minmax finds the minimum and maximum value from the dataset
|
||||
pub fn minmax<T>(data []T) (T, T) {
|
||||
if data.len == 0 {
|
||||
return T(0), T(0)
|
||||
|
@ -315,7 +307,7 @@ pub fn minmax<T>(data []T) (T, T) {
|
|||
return min, max
|
||||
}
|
||||
|
||||
// Minimum of the given input array
|
||||
// min_index finds the first index of the minimum value
|
||||
pub fn min_index<T>(data []T) int {
|
||||
if data.len == 0 {
|
||||
return 0
|
||||
|
@ -331,7 +323,7 @@ pub fn min_index<T>(data []T) int {
|
|||
return min_index
|
||||
}
|
||||
|
||||
// Maximum of the given input array
|
||||
// max_index finds the first index of the maximum value
|
||||
pub fn max_index<T>(data []T) int {
|
||||
if data.len == 0 {
|
||||
return 0
|
||||
|
@ -347,7 +339,7 @@ pub fn max_index<T>(data []T) int {
|
|||
return max_index
|
||||
}
|
||||
|
||||
// Minimum and maximum of the given input array
|
||||
// minmax_index finds the first index of the minimum and maximum value
|
||||
pub fn minmax_index<T>(data []T) (int, int) {
|
||||
if data.len == 0 {
|
||||
return 0, 0
|
||||
|
@ -369,7 +361,7 @@ pub fn minmax_index<T>(data []T) (int, int) {
|
|||
return min_index, max_index
|
||||
}
|
||||
|
||||
// Measure of Dispersion / Spread
|
||||
// range calculates the difference between the min and max
|
||||
// Range ( Maximum - Minimum ) of the given input array
|
||||
// Based on
|
||||
// https://www.mathsisfun.com/data/range.html
|
||||
|
@ -381,6 +373,8 @@ pub fn range<T>(data []T) T {
|
|||
return max - min
|
||||
}
|
||||
|
||||
// covariance calculates directional association between datasets
|
||||
// positive value denotes variables move in same direction and negative denotes variables move in opposite directions
|
||||
[inline]
|
||||
pub fn covariance<T>(data1 []T, data2 []T) T {
|
||||
mean1 := mean<T>(data1)
|
||||
|
@ -388,7 +382,7 @@ pub fn covariance<T>(data1 []T, data2 []T) T {
|
|||
return covariance_mean<T>(data1, data2, mean1, mean2)
|
||||
}
|
||||
|
||||
// Compute the covariance of a dataset using
|
||||
// covariance_mean computes the covariance of a dataset with means provided
|
||||
// the recurrence relation
|
||||
pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
|
||||
n := int(math.min(data1.len, data2.len))
|
||||
|
@ -404,13 +398,16 @@ pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
|
|||
return covariance
|
||||
}
|
||||
|
||||
// lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
|
||||
// of a dataset, based on the mean
|
||||
[inline]
|
||||
pub fn lag1_autocorrelation<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
return lag1_autocorrelation_mean<T>(data, data_mean)
|
||||
}
|
||||
|
||||
// Compute the lag-1 autocorrelation of a dataset using
|
||||
// lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
|
||||
// of a dataset, using
|
||||
// the recurrence relation
|
||||
pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
|
||||
if data.len == 0 {
|
||||
|
@ -427,6 +424,7 @@ pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
|
|||
return q / v
|
||||
}
|
||||
|
||||
// kurtosis calculates the measure of the 'tailedness' of the data by finding mean and standard of deviation
|
||||
[inline]
|
||||
pub fn kurtosis<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
|
@ -434,7 +432,7 @@ pub fn kurtosis<T>(data []T) T {
|
|||
return kurtosis_mean_stddev<T>(data, data_mean, sd)
|
||||
}
|
||||
|
||||
// Takes a dataset and finds the kurtosis
|
||||
// kurtosis_mean_stddev calculates the measure of the 'tailedness' of the data
|
||||
// using the fourth moment the deviations, normalized by the sd
|
||||
pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
mut avg := T(0) // find the fourth moment the deviations, normalized by the sd
|
||||
|
@ -449,6 +447,7 @@ pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
|
|||
return avg - T(3.0)
|
||||
}
|
||||
|
||||
// skew calculates the mean and standard of deviation to find the skew from the data
|
||||
[inline]
|
||||
pub fn skew<T>(data []T) T {
|
||||
data_mean := mean<T>(data)
|
||||
|
@ -456,6 +455,7 @@ pub fn skew<T>(data []T) T {
|
|||
return skew_mean_stddev<T>(data, data_mean, sd)
|
||||
}
|
||||
|
||||
// skew_mean_stddev calculates the skewness of data
|
||||
pub fn skew_mean_stddev<T>(data []T, mean T, sd T) T {
|
||||
mut skew := T(0) // find the sum of the cubed deviations, normalized by the sd.
|
||||
/*
|
||||
|
|
|
@ -14,26 +14,32 @@ pub mut:
|
|||
hi Uint128 = uint128_zero // upper 128 bit half
|
||||
}
|
||||
|
||||
// uint256_from_128 creates a new `unsigned.Uint256` from the given Uint128 value
|
||||
pub fn uint256_from_128(v Uint128) Uint256 {
|
||||
return Uint256{v, uint128_zero}
|
||||
}
|
||||
|
||||
// uint256_from_64 creates a new `unsigned.Uint256` from the given u64 value
|
||||
pub fn uint256_from_64(v u64) Uint256 {
|
||||
return uint256_from_128(uint128_from_64(v))
|
||||
}
|
||||
|
||||
// is_zero checks if specified Uint256 is zero
|
||||
pub fn (u Uint256) is_zero() bool {
|
||||
return u.lo.is_zero() && u.hi.is_zero()
|
||||
}
|
||||
|
||||
// equals checks if the two Uint256 values match one another
|
||||
pub fn (u Uint256) equals(v Uint256) bool {
|
||||
return u.lo.equals(v.lo) && u.hi.equals(v.hi)
|
||||
}
|
||||
|
||||
pub fn (u Uint256) euqals_128(v Uint128) bool {
|
||||
// equals_128 checks if the Uint256 value matches the Uint128 value
|
||||
pub fn (u Uint256) equals_128(v Uint128) bool {
|
||||
return u.lo.equals(v) && u.hi.is_zero()
|
||||
}
|
||||
|
||||
// cmp returns 1 if u is greater than v, -1 if u is less than v, or 0 if equal
|
||||
pub fn (u Uint256) cmp(v Uint256) int {
|
||||
h := u.hi.cmp(v.hi)
|
||||
if h != 0 {
|
||||
|
@ -42,6 +48,7 @@ pub fn (u Uint256) cmp(v Uint256) int {
|
|||
return u.lo.cmp(v.lo)
|
||||
}
|
||||
|
||||
// cmp_128 returns 1 if u is greater than v (Uint128), -1 if u is less than v, or 0 if equal
|
||||
pub fn (u Uint256) cmp_128(v Uint128) int {
|
||||
if !u.hi.is_zero() {
|
||||
return 1
|
||||
|
@ -49,34 +56,42 @@ pub fn (u Uint256) cmp_128(v Uint128) int {
|
|||
return u.lo.cmp(v)
|
||||
}
|
||||
|
||||
// not returns a binary negation of the Uint256 value
|
||||
pub fn (u Uint256) not() Uint256 {
|
||||
return Uint256{u.lo.not(), u.hi.not()}
|
||||
}
|
||||
|
||||
// and returns a Uint256 value that is the bitwise and of u and v
|
||||
pub fn (u Uint256) and(v Uint256) Uint256 {
|
||||
return Uint256{u.lo.and(v.lo), u.hi.and(v.hi)}
|
||||
}
|
||||
|
||||
// and_128 returns a Uint256 value that is the bitwise and of u and v, which is a Uint128
|
||||
pub fn (u Uint256) and_128(v Uint128) Uint256 {
|
||||
return Uint256{u.lo.and(v), uint128_zero}
|
||||
}
|
||||
|
||||
// or_ returns a Uint256 value that is the bitwise or of u and v
|
||||
pub fn (u Uint256) or_(v Uint256) Uint256 {
|
||||
return Uint256{u.lo.or_(v.lo), u.hi.or_(v.hi)}
|
||||
}
|
||||
|
||||
// or_128 returns a Uint256 value that is the bitwise or of u and v, which is a Uint128
|
||||
pub fn (u Uint256) or_128(v Uint128) Uint256 {
|
||||
return Uint256{u.lo.or_(v), u.hi}
|
||||
}
|
||||
|
||||
// xor returns a Uint256 value that is the bitwise xor of u and v
|
||||
pub fn (u Uint256) xor(v Uint256) Uint256 {
|
||||
return Uint256{u.lo.xor(v.lo), u.hi.xor(v.hi)}
|
||||
}
|
||||
|
||||
// xor_128 returns a Uint256 value that is the bitwise xor of u and v, which is a Uint128
|
||||
pub fn (u Uint256) xor_128(v Uint128) Uint256 {
|
||||
return Uint256{u.lo.xor(v), u.hi}
|
||||
}
|
||||
|
||||
// add_256 - untested
|
||||
pub fn add_256(x Uint256, y Uint256, carry u64) (Uint256, u64) {
|
||||
mut sum := Uint256{}
|
||||
mut carry_out := u64(0)
|
||||
|
@ -85,6 +100,7 @@ pub fn add_256(x Uint256, y Uint256, carry u64) (Uint256, u64) {
|
|||
return sum, carry_out
|
||||
}
|
||||
|
||||
// sub_256 - untested
|
||||
pub fn sub_256(x Uint256, y Uint256, borrow u64) (Uint256, u64) {
|
||||
mut diff := Uint256{}
|
||||
mut borrow_out := u64(0)
|
||||
|
@ -93,6 +109,7 @@ pub fn sub_256(x Uint256, y Uint256, borrow u64) (Uint256, u64) {
|
|||
return diff, borrow_out
|
||||
}
|
||||
|
||||
// mul_256 - untested
|
||||
pub fn mul_256(x Uint256, y Uint256) (Uint256, Uint256) {
|
||||
mut hi := Uint256{}
|
||||
mut lo := Uint256{}
|
||||
|
@ -114,31 +131,37 @@ pub fn mul_256(x Uint256, y Uint256) (Uint256, Uint256) {
|
|||
return hi, lo
|
||||
}
|
||||
|
||||
// add returns a Uint256 that is equal to u+v
|
||||
pub fn (u Uint256) add(v Uint256) Uint256 {
|
||||
sum, _ := add_256(u, v, 0)
|
||||
return sum
|
||||
}
|
||||
|
||||
// overflowing_add - untested
|
||||
pub fn (u Uint256) overflowing_add(v Uint256) (Uint256, u64) {
|
||||
sum, overflow := add_256(u, v, 0)
|
||||
return sum, overflow
|
||||
}
|
||||
|
||||
// add_128 returns a Uint256 that is equal to u+v, v being a Uint128
|
||||
pub fn (u Uint256) add_128(v Uint128) Uint256 {
|
||||
lo, c0 := add_128(u.lo, v, 0)
|
||||
return Uint256{lo, u.hi.add_64(c0)}
|
||||
}
|
||||
|
||||
// sub returns a Uint256 that is equal to u-v
|
||||
pub fn (u Uint256) sub(v Uint256) Uint256 {
|
||||
diff, _ := sub_256(u, v, 0)
|
||||
return diff
|
||||
}
|
||||
|
||||
// sub_128 returns a Uint256 that is equal to u-v, v being a Uint128
|
||||
pub fn (u Uint256) sub_128(v Uint128) Uint256 {
|
||||
lo, b0 := sub_128(u.lo, v, 0)
|
||||
return Uint256{lo, u.hi.sub_64(b0)}
|
||||
}
|
||||
|
||||
// mul returns a Uint256 that is eqal to u*v
|
||||
pub fn (u Uint256) mul(v Uint256) Uint256 {
|
||||
mut hi, mut lo := mul_128(u.lo, v.lo)
|
||||
hi = hi.add(u.hi.mul(v.lo))
|
||||
|
@ -146,11 +169,13 @@ pub fn (u Uint256) mul(v Uint256) Uint256 {
|
|||
return Uint256{lo, hi}
|
||||
}
|
||||
|
||||
// mul_128 returns a Uint256 that is eqal to u*v, v being a Uint128
|
||||
pub fn (u Uint256) mul_128(v Uint128) Uint256 {
|
||||
hi, lo := mul_128(u.lo, v)
|
||||
return Uint256{lo, hi.add(u.hi.mul(v))}
|
||||
}
|
||||
|
||||
// quo_rem - untested
|
||||
pub fn (u Uint256) quo_rem(v Uint256) (Uint256, Uint256) {
|
||||
if v.hi.is_zero() {
|
||||
q, r := u.quo_rem_128(v.lo)
|
||||
|
@ -173,6 +198,7 @@ pub fn (u Uint256) quo_rem(v Uint256) (Uint256, Uint256) {
|
|||
return q, r
|
||||
}
|
||||
|
||||
// quo_rem_128 - untested
|
||||
pub fn (u Uint256) quo_rem_128(v Uint128) (Uint256, Uint128) {
|
||||
if u.hi.cmp(v) < 0 {
|
||||
lo, r := div_128(u.hi, u.lo, v)
|
||||
|
@ -184,6 +210,7 @@ pub fn (u Uint256) quo_rem_128(v Uint128) (Uint256, Uint128) {
|
|||
return Uint256{lo, hi}, r2
|
||||
}
|
||||
|
||||
// quo_rem_64 - untested
|
||||
pub fn (u Uint256) quo_rem_64(v u64) (Uint256, u64) {
|
||||
mut q := Uint256{}
|
||||
mut r := u64(0)
|
||||
|
@ -192,6 +219,7 @@ pub fn (u Uint256) quo_rem_64(v u64) (Uint256, u64) {
|
|||
return q, r
|
||||
}
|
||||
|
||||
// rsh returns a new Uint256 that has been right bit shifted
|
||||
pub fn (u Uint256) rsh(n_ u32) Uint256 {
|
||||
mut n := n_
|
||||
if n > 128 {
|
||||
|
@ -205,6 +233,7 @@ pub fn (u Uint256) rsh(n_ u32) Uint256 {
|
|||
return Uint256{Uint128{u.lo.lo >> n | u.lo.hi << (64 - n), u.lo.hi >> n | u.hi.lo << (64 - n)}, Uint128{u.hi.lo >> n | u.hi.hi << (64 - n), u.hi.hi >> n}}
|
||||
}
|
||||
|
||||
// lsh returns a new Uint256 that has been left bit shifted
|
||||
pub fn (u Uint256) lsh(n_ u32) Uint256 {
|
||||
mut n := n_
|
||||
if n > 128 {
|
||||
|
@ -219,36 +248,43 @@ pub fn (u Uint256) lsh(n_ u32) Uint256 {
|
|||
return Uint256{Uint128{u.lo.lo << n, u.lo.hi << n | u.lo.lo >> (64 - n)}, Uint128{u.hi.lo << n | u.lo.hi >> (64 - n), u.hi.hi << n | u.hi.lo >> (64 - n)}}
|
||||
}
|
||||
|
||||
// div - untested
|
||||
pub fn (u Uint256) div(v Uint256) Uint256 {
|
||||
q, _ := u.quo_rem(v)
|
||||
return q
|
||||
}
|
||||
|
||||
// div_128 - untested
|
||||
pub fn (u Uint256) div_128(v Uint128) Uint256 {
|
||||
q, _ := u.quo_rem_128(v)
|
||||
return q
|
||||
}
|
||||
|
||||
// div_64 - untested
|
||||
pub fn (u Uint256) div_64(v u64) Uint256 {
|
||||
q, _ := u.quo_rem_64(v)
|
||||
return q
|
||||
}
|
||||
|
||||
// mod - untested
|
||||
pub fn (u Uint256) mod(v Uint256) Uint256 {
|
||||
_, r := u.quo_rem(v)
|
||||
return r
|
||||
}
|
||||
|
||||
// mod_128 - untested
|
||||
pub fn (u Uint256) mod_128(v Uint128) Uint128 {
|
||||
_, r := u.quo_rem_128(v)
|
||||
return r
|
||||
}
|
||||
|
||||
// mod_64 - untested
|
||||
pub fn (u Uint256) mod_64(v u64) u64 {
|
||||
_, r := u.quo_rem_64(v)
|
||||
return r
|
||||
}
|
||||
|
||||
// rotate_left returns a new Uint256 that has been left bit shifted
|
||||
pub fn (u Uint256) rotate_left(k int) Uint256 {
|
||||
mut n := u32(k) & 255
|
||||
if n < 64 {
|
||||
|
@ -283,10 +319,12 @@ pub fn (u Uint256) rotate_left(k int) Uint256 {
|
|||
return Uint256{Uint128{u.lo.hi << n | u.lo.lo >> (64 - n), u.hi.lo << n | u.lo.hi >> (64 - n)}, Uint128{u.hi.hi << n | u.hi.lo >> (64 - n), u.lo.lo << n | u.hi.hi >> (64 - n)}}
|
||||
}
|
||||
|
||||
// rotate_right returns a new Uint256 that has been right bit shifted
|
||||
pub fn (u Uint256) rotate_right(k int) Uint256 {
|
||||
return u.rotate_left(-k)
|
||||
}
|
||||
|
||||
// len returns the length of the binary value without the leading zeros
|
||||
pub fn (u Uint256) len() int {
|
||||
if !u.hi.is_zero() {
|
||||
return 128 + u.hi.len()
|
||||
|
@ -294,6 +332,7 @@ pub fn (u Uint256) len() int {
|
|||
return u.lo.len()
|
||||
}
|
||||
|
||||
// leading_zeros returns the number of 0s at the beginning of the binary value of the Uint256 value [0, 256]
|
||||
pub fn (u Uint256) leading_zeros() int {
|
||||
if !u.hi.is_zero() {
|
||||
return u.hi.leading_zeros()
|
||||
|
@ -301,6 +340,7 @@ pub fn (u Uint256) leading_zeros() int {
|
|||
return 128 + u.lo.leading_zeros()
|
||||
}
|
||||
|
||||
// trailing_zeros returns the number of 0s at the end of the binary value of the Uint256 value [0,256]
|
||||
pub fn (u Uint256) trailing_zeros() int {
|
||||
if !u.lo.is_zero() {
|
||||
return u.lo.trailing_zeros()
|
||||
|
@ -309,10 +349,12 @@ pub fn (u Uint256) trailing_zeros() int {
|
|||
return 128 + u.hi.trailing_zeros()
|
||||
}
|
||||
|
||||
// ones_count returns the number of ones in the binary value of the Uint256 value
|
||||
pub fn (u Uint256) ones_count() int {
|
||||
return u.lo.ones_count() + u.hi.ones_count()
|
||||
}
|
||||
|
||||
// str returns the decimal representation of the unsigned integer
|
||||
pub fn (u_ Uint256) str() string {
|
||||
mut u := u_
|
||||
if u.hi.is_zero() {
|
||||
|
@ -339,6 +381,7 @@ pub fn (u_ Uint256) str() string {
|
|||
return ''
|
||||
}
|
||||
|
||||
// uint256_from_dec_str creates a new `unsigned.Uint256` from the given string if possible
|
||||
pub fn uint256_from_dec_str(value string) ?Uint256 {
|
||||
mut res := unsigned.uint256_zero
|
||||
for b_ in value.bytes() {
|
||||
|
|
|
@ -21,12 +21,10 @@ mut:
|
|||
debug_file os.File
|
||||
}
|
||||
|
||||
[if debug]
|
||||
[if debug_html ?]
|
||||
fn (mut dom DocumentObjectModel) print_debug(data string) {
|
||||
$if debug {
|
||||
if data.len > 0 {
|
||||
dom.debug_file.writeln(data) or { eprintln(err) }
|
||||
}
|
||||
if data.len > 0 {
|
||||
dom.debug_file.writeln(data) or { eprintln(err) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ fn test_access_parent() {
|
|||
mut dom := parse(generate_temp_html())
|
||||
div_tags := dom.get_tag('div')
|
||||
parent := div_tags[0].parent
|
||||
assert parent != 0
|
||||
assert unsafe { parent != 0 }
|
||||
for div_tag in div_tags {
|
||||
assert div_tag.parent == parent
|
||||
}
|
||||
|
|
|
@ -49,12 +49,10 @@ fn (parser Parser) builder_str() string {
|
|||
return parser.lexical_attributes.lexeme_builder.after(0)
|
||||
}
|
||||
|
||||
[if debug]
|
||||
[if debug_html ?]
|
||||
fn (mut parser Parser) print_debug(data string) {
|
||||
$if debug {
|
||||
if data.len > 0 {
|
||||
parser.debug_file.writeln(data) or { panic(err) }
|
||||
}
|
||||
if data.len > 0 {
|
||||
parser.debug_file.writeln(data) or { panic(err) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,7 +153,8 @@ pub fn (mut parser Parser) split_parse(data string) {
|
|||
parser.lexical_attributes.current_tag.attributes[lattr] = nval
|
||||
parser.lexical_attributes.current_tag.last_attribute = ''
|
||||
} else {
|
||||
parser.lexical_attributes.current_tag.attributes[temp_lexeme.to_lower()] = '' // parser.print_debug(temp_lexeme)
|
||||
parser.lexical_attributes.current_tag.attributes[temp_lexeme.to_lower()] = ''
|
||||
// parser.print_debug(temp_lexeme)
|
||||
}
|
||||
parser.lexical_attributes.lexeme_builder.go_back_to(0)
|
||||
} else {
|
||||
|
|
|
@ -599,7 +599,7 @@ fn parse_host(host string) ?string {
|
|||
return host1 + host2 + host3
|
||||
}
|
||||
if idx := host.last_index(':') {
|
||||
colon_port = host[idx..]
|
||||
colon_port = host[idx..i]
|
||||
if !valid_optional_port(colon_port) {
|
||||
return error(error_msg('parse_host: invalid port $colon_port after host ',
|
||||
''))
|
||||
|
|
|
@ -98,3 +98,25 @@ fn test_parse_empty_query_two() ? {
|
|||
assert qvalues_map == {}
|
||||
assert query_str == query_encode
|
||||
}
|
||||
|
||||
fn test_parse() ? {
|
||||
urls := [
|
||||
'jdbc:mysql://test_user:ouupppssss@localhost:3306/sakila?profileSQL=true',
|
||||
'ftp://ftp.is.co.za/rfc/rfc1808.txt',
|
||||
'http://www.ietf.org/rfc/rfc2396.txt#header1',
|
||||
'ldap://[2001:db8::7]/c=GB?objectClass=one&objectClass=two',
|
||||
'mailto:John.Doe@example.com',
|
||||
'news:comp.infosystems.www.servers.unix',
|
||||
'tel:+1-816-555-1212',
|
||||
'telnet://192.0.2.16:80/',
|
||||
'urn:oasis:names:specification:docbook:dtd:xml:4.1.2',
|
||||
'foo://example.com:8042/over/there?name=ferret#nose',
|
||||
]
|
||||
for url in urls {
|
||||
_ := urllib.parse(url) or {
|
||||
eprintln(err)
|
||||
assert false
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
module os
|
||||
|
||||
import strings
|
||||
import strings.textscanner
|
||||
|
||||
// Collection of useful functions for manipulation, validation and analysis of system paths.
|
||||
// The following functions handle paths depending on the operating system,
|
||||
// therefore results may be different for certain operating systems.
|
||||
|
||||
const (
|
||||
fslash = `/`
|
||||
bslash = `\\`
|
||||
dot = `.`
|
||||
fslash = `/`
|
||||
bslash = `\\`
|
||||
dot = `.`
|
||||
qmark = `?`
|
||||
dot_dot = '..'
|
||||
empty_str = ''
|
||||
dot_str = '.'
|
||||
)
|
||||
|
||||
// is_abs_path returns `true` if the given `path` is absolute.
|
||||
|
@ -16,11 +23,152 @@ pub fn is_abs_path(path string) bool {
|
|||
return false
|
||||
}
|
||||
$if windows {
|
||||
return is_device_path(path) || is_drive_rooted(path) || is_normal_path(path)
|
||||
return is_unc_path(path) || is_drive_rooted(path) || is_normal_path(path)
|
||||
}
|
||||
return path[0] == os.fslash
|
||||
}
|
||||
|
||||
// abs_path joins the current working directory
|
||||
// with the given `path` (if the `path` is relative)
|
||||
// and returns the absolute path representation.
|
||||
pub fn abs_path(path string) string {
|
||||
wd := getwd()
|
||||
if path.len == 0 {
|
||||
return wd
|
||||
}
|
||||
npath := norm_path(path)
|
||||
if npath == os.dot_str {
|
||||
return wd
|
||||
}
|
||||
if !is_abs_path(npath) {
|
||||
mut sb := strings.new_builder(npath.len)
|
||||
sb.write_string(wd)
|
||||
sb.write_string(path_separator)
|
||||
sb.write_string(npath)
|
||||
return norm_path(sb.str())
|
||||
}
|
||||
return npath
|
||||
}
|
||||
|
||||
// norm_path returns the normalized version of the given `path`
|
||||
// by resolving backlinks (..), turning forward slashes into
|
||||
// back slashes on a Windows system and eliminating:
|
||||
// - references to current directories (.)
|
||||
// - redundant path separators
|
||||
// - the last path separator
|
||||
[direct_array_access]
|
||||
pub fn norm_path(path string) string {
|
||||
if path.len == 0 {
|
||||
return os.dot_str
|
||||
}
|
||||
rooted := is_abs_path(path)
|
||||
volume := get_volume(path)
|
||||
volume_len := volume.len
|
||||
cpath := clean_path(path[volume_len..])
|
||||
if cpath.len == 0 && volume_len == 0 {
|
||||
return os.dot_str
|
||||
}
|
||||
spath := cpath.split(path_separator)
|
||||
if os.dot_dot !in spath {
|
||||
return if volume_len != 0 { volume + cpath } else { cpath }
|
||||
}
|
||||
// resolve backlinks (..)
|
||||
spath_len := spath.len
|
||||
mut sb := strings.new_builder(cpath.len)
|
||||
if rooted {
|
||||
sb.write_string(path_separator)
|
||||
}
|
||||
mut new_path := []string{cap: spath_len}
|
||||
mut backlink_count := 0
|
||||
for i := spath_len - 1; i >= 0; i-- {
|
||||
part := spath[i]
|
||||
if part == os.empty_str {
|
||||
continue
|
||||
}
|
||||
if part == os.dot_dot {
|
||||
backlink_count++
|
||||
continue
|
||||
}
|
||||
if backlink_count != 0 {
|
||||
backlink_count--
|
||||
continue
|
||||
}
|
||||
new_path.prepend(part)
|
||||
}
|
||||
// append backlink(s) to the path if backtracking
|
||||
// is not possible and the given path is not rooted
|
||||
if backlink_count != 0 && !rooted {
|
||||
for i in 0 .. backlink_count {
|
||||
sb.write_string(os.dot_dot)
|
||||
if new_path.len == 0 && i == backlink_count - 1 {
|
||||
break
|
||||
}
|
||||
sb.write_string(path_separator)
|
||||
}
|
||||
}
|
||||
sb.write_string(new_path.join(path_separator))
|
||||
res := sb.str()
|
||||
if res.len == 0 {
|
||||
if volume_len != 0 {
|
||||
return volume
|
||||
}
|
||||
if !rooted {
|
||||
return os.dot_str
|
||||
}
|
||||
return path_separator
|
||||
}
|
||||
if volume_len != 0 {
|
||||
return volume + res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// clean_path returns the "cleaned" version of the given `path`
|
||||
// by turning forward slashes into back slashes
|
||||
// on a Windows system and eliminating:
|
||||
// - references to current directories (.)
|
||||
// - redundant separators
|
||||
// - the last path separator
|
||||
fn clean_path(path string) string {
|
||||
if path.len == 0 {
|
||||
return os.empty_str
|
||||
}
|
||||
mut sb := strings.new_builder(path.len)
|
||||
mut sc := textscanner.new(path)
|
||||
for sc.next() != -1 {
|
||||
curr := u8(sc.current())
|
||||
back := sc.peek_back()
|
||||
peek := sc.peek()
|
||||
// skip current path separator if last byte was a path separator
|
||||
if back != -1 && is_slash(u8(back)) && is_slash(curr) {
|
||||
continue
|
||||
}
|
||||
// skip reference to current dir (.)
|
||||
if (back == -1 || is_slash(u8(back))) && curr == os.dot
|
||||
&& (peek == -1 || is_slash(u8(peek))) {
|
||||
// skip if the next byte is a path separator
|
||||
if peek != -1 && is_slash(u8(peek)) {
|
||||
sc.skip_n(1)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// turn foward slash into a back slash on a Windows system
|
||||
$if windows {
|
||||
if curr == os.fslash {
|
||||
sb.write_u8(os.bslash)
|
||||
continue
|
||||
}
|
||||
}
|
||||
sb.write_u8(u8(sc.current()))
|
||||
}
|
||||
res := sb.str()
|
||||
// eliminate the last path separator
|
||||
if res.len > 1 && is_slash(res[res.len - 1]) {
|
||||
return res[..res.len - 1]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// win_volume_len returns the length of the
|
||||
// Windows volume/drive from the given `path`.
|
||||
fn win_volume_len(path string) int {
|
||||
|
@ -32,7 +180,7 @@ fn win_volume_len(path string) int {
|
|||
return 2
|
||||
}
|
||||
// its UNC path / DOS device path?
|
||||
if path.len >= 5 && starts_w_slash_slash(path) && !is_slash(path[2]) {
|
||||
if plen >= 5 && starts_w_slash_slash(path) && !is_slash(path[2]) {
|
||||
for i := 3; i < plen; i++ {
|
||||
if is_slash(path[i]) {
|
||||
if i + 1 >= plen || is_slash(path[i + 1]) {
|
||||
|
@ -51,6 +199,20 @@ fn win_volume_len(path string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
fn get_volume(path string) string {
|
||||
$if !windows {
|
||||
return os.empty_str
|
||||
}
|
||||
volume := path[..win_volume_len(path)]
|
||||
if volume.len == 0 {
|
||||
return os.empty_str
|
||||
}
|
||||
if volume[0] == os.fslash {
|
||||
return volume.replace('/', '\\')
|
||||
}
|
||||
return volume
|
||||
}
|
||||
|
||||
fn is_slash(b u8) bool {
|
||||
$if windows {
|
||||
return b == os.bslash || b == os.fslash
|
||||
|
@ -58,7 +220,7 @@ fn is_slash(b u8) bool {
|
|||
return b == os.fslash
|
||||
}
|
||||
|
||||
fn is_device_path(path string) bool {
|
||||
fn is_unc_path(path string) bool {
|
||||
return win_volume_len(path) >= 5 && starts_w_slash_slash(path)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,3 +27,103 @@ fn test_is_abs_path() {
|
|||
assert !is_abs_path('./')
|
||||
assert !is_abs_path('.')
|
||||
}
|
||||
|
||||
fn test_clean_path() {
|
||||
$if windows {
|
||||
assert clean_path(r'\\path\to\files/file.v') == r'\path\to\files\file.v'
|
||||
assert clean_path(r'\/\//\/') == '\\'
|
||||
assert clean_path(r'./path\\dir/\\./\/\\/file.v\.\\\.') == r'path\dir\file.v'
|
||||
assert clean_path(r'\./path/dir\\file.exe') == r'\path\dir\file.exe'
|
||||
assert clean_path(r'.') == ''
|
||||
assert clean_path(r'./') == ''
|
||||
assert clean_path(r'\./') == '\\'
|
||||
assert clean_path(r'//\/\/////') == '\\'
|
||||
return
|
||||
}
|
||||
assert clean_path('./../.././././//') == '../..'
|
||||
assert clean_path('.') == ''
|
||||
assert clean_path('./path/to/file.v//./') == 'path/to/file.v'
|
||||
assert clean_path('./') == ''
|
||||
assert clean_path('/.') == '/'
|
||||
assert clean_path('//path/./to/.///files/file.v///') == '/path/to/files/file.v'
|
||||
assert clean_path('path/./to/.///files/.././file.v///') == 'path/to/files/../file.v'
|
||||
assert clean_path('\\') == '\\'
|
||||
assert clean_path('//////////') == '/'
|
||||
}
|
||||
|
||||
fn test_norm_path() {
|
||||
$if windows {
|
||||
assert norm_path(r'C:/path/to//file.v\\') == r'C:\path\to\file.v'
|
||||
assert norm_path(r'C:path\.\..\\\.\to//file.v') == r'C:to\file.v'
|
||||
assert norm_path(r'D:path\.\..\..\\\\.\to//dir/..\') == r'D:..\to'
|
||||
assert norm_path(r'D:/path\.\..\/..\file.v') == r'D:\file.v'
|
||||
assert norm_path(r'') == '.'
|
||||
assert norm_path(r'/') == '\\'
|
||||
assert norm_path(r'\/') == '\\'
|
||||
assert norm_path(r'path\../dir\..') == '.'
|
||||
assert norm_path(r'.\.\') == '.'
|
||||
assert norm_path(r'G:.\.\dir\././\.\.\\\\///to/././\file.v/./\\') == r'G:dir\to\file.v'
|
||||
assert norm_path(r'G:\..\..\.\.\file.v\\\.') == r'G:\file.v'
|
||||
assert norm_path(r'\\Server\share\\\dir/..\file.v\./.') == r'\\Server\share\file.v'
|
||||
assert norm_path(r'\\.\device\\\dir/to/./file.v\.') == r'\\.\device\dir\to\file.v'
|
||||
assert norm_path(r'C:dir/../dir2/../../../file.v') == r'C:..\..\file.v'
|
||||
assert norm_path(r'\\.\C:\\\Users/\Documents//..') == r'\\.\C:\Users'
|
||||
assert norm_path(r'\\.\C:\Users') == r'\\.\C:\Users'
|
||||
assert norm_path(r'\\') == '\\'
|
||||
assert norm_path(r'//') == '\\'
|
||||
assert norm_path(r'\\\') == '\\'
|
||||
assert norm_path(r'.') == '.'
|
||||
assert norm_path(r'\\Server') == '\\Server'
|
||||
assert norm_path(r'\\Server\') == '\\Server'
|
||||
return
|
||||
}
|
||||
assert norm_path('/path/././../to/file//file.v/.') == '/to/file/file.v'
|
||||
assert norm_path('path/././to/files/../../file.v/.') == 'path/file.v'
|
||||
assert norm_path('path/././/../../to/file.v/.') == '../to/file.v'
|
||||
assert norm_path('/path/././/../..///.././file.v/././') == '/file.v'
|
||||
assert norm_path('path/././//../../../to/dir//.././file.v/././') == '../../to/file.v'
|
||||
assert norm_path('path/../dir/..') == '.'
|
||||
assert norm_path('../dir/..') == '..'
|
||||
assert norm_path('/../dir/..') == '/'
|
||||
assert norm_path('//././dir/../files/././/file.v') == '/files/file.v'
|
||||
assert norm_path('/\\../dir/////////.') == '/\\../dir'
|
||||
assert norm_path('/home/') == '/home'
|
||||
assert norm_path('/home/////./.') == '/home'
|
||||
assert norm_path('...') == '...'
|
||||
}
|
||||
|
||||
fn test_abs_path() {
|
||||
wd := getwd()
|
||||
wd_w_sep := wd + path_separator
|
||||
$if windows {
|
||||
assert abs_path('path/to/file.v') == '${wd_w_sep}path\\to\\file.v'
|
||||
assert abs_path('path/to/file.v') == '${wd_w_sep}path\\to\\file.v'
|
||||
assert abs_path('/') == r'\'
|
||||
assert abs_path(r'C:\path\to\files\file.v') == r'C:\path\to\files\file.v'
|
||||
assert abs_path(r'C:\/\path\.\to\../files\file.v\.\\\.\') == r'C:\path\files\file.v'
|
||||
assert abs_path(r'\\Host\share\files\..\..\.') == r'\\Host\share\'
|
||||
assert abs_path(r'\\.\HardDiskvolume2\files\..\..\.') == r'\\.\HardDiskvolume2\'
|
||||
assert abs_path(r'\\?\share') == r'\\?\share'
|
||||
assert abs_path(r'\\.\') == r'\'
|
||||
assert abs_path(r'G:/\..\\..\.\.\file.v\\.\.\\\\') == r'G:\file.v'
|
||||
assert abs_path('files') == '${wd_w_sep}files'
|
||||
assert abs_path('') == wd
|
||||
assert abs_path('.') == wd
|
||||
assert abs_path('files/../file.v') == '${wd_w_sep}file.v'
|
||||
assert abs_path('///') == r'\'
|
||||
assert abs_path('/path/to/file.v') == r'\path\to\file.v'
|
||||
assert abs_path('D:/') == r'D:\'
|
||||
assert abs_path(r'\\.\HardiskVolume6') == r'\\.\HardiskVolume6'
|
||||
return
|
||||
}
|
||||
assert abs_path('/') == '/'
|
||||
assert abs_path('.') == wd
|
||||
assert abs_path('files') == '${wd_w_sep}files'
|
||||
assert abs_path('') == wd
|
||||
assert abs_path('files/../file.v') == '${wd_w_sep}file.v'
|
||||
assert abs_path('///') == '/'
|
||||
assert abs_path('/path/to/file.v') == '/path/to/file.v'
|
||||
assert abs_path('/path/to/file.v/../..') == '/path'
|
||||
assert abs_path('path/../file.v/..') == wd
|
||||
assert abs_path('///') == '/'
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ fn (mut p Process) win_write_string(idx int, s string) {
|
|||
|
||||
fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
|
||||
mut wdata := &WProcess(p.wdata)
|
||||
if wdata == 0 {
|
||||
if unsafe { wdata == 0 } {
|
||||
return '', 0
|
||||
}
|
||||
mut rhandle := &u32(0)
|
||||
|
@ -207,7 +207,7 @@ fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
|
|||
|
||||
fn (mut p Process) win_slurp(idx int) string {
|
||||
mut wdata := &WProcess(p.wdata)
|
||||
if wdata == 0 {
|
||||
if unsafe { wdata == 0 } {
|
||||
return ''
|
||||
}
|
||||
mut rhandle := &u32(0)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module buffer
|
||||
|
||||
pub struct PRNGBuffer {
|
||||
mut:
|
||||
bytes_left int
|
||||
buffer u64
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module config
|
||||
|
||||
import rand.seed
|
||||
|
@ -12,3 +15,35 @@ pub struct PRNGConfigStruct {
|
|||
pub:
|
||||
seed_ []u32 = seed.time_seed_array(2)
|
||||
}
|
||||
|
||||
// Configuration struct for generating normally distributed floats. The default value for
|
||||
// `mu` is 0 and the default value for `sigma` is 1.
|
||||
[params]
|
||||
pub struct NormalConfigStruct {
|
||||
pub:
|
||||
mu f64 = 0.0
|
||||
sigma f64 = 1.0
|
||||
}
|
||||
|
||||
// Configuration struct for the shuffle functions.
|
||||
// The start index is inclusive and the end index is exclusive.
|
||||
// Set the end to 0 to shuffle until the end of the array.
|
||||
[params]
|
||||
pub struct ShuffleConfigStruct {
|
||||
pub:
|
||||
start int
|
||||
end int
|
||||
}
|
||||
|
||||
// validate_for is a helper function for validating the configuration struct for the given array.
|
||||
pub fn (config ShuffleConfigStruct) validate_for<T>(a []T) ? {
|
||||
if config.start < 0 || config.start >= a.len {
|
||||
return error("argument 'config.start' must be in range [0, a.len)")
|
||||
}
|
||||
if config.end < 0 || config.end > a.len {
|
||||
return error("argument 'config.end' must be in range [0, a.len]")
|
||||
}
|
||||
if config.end != 0 && config.end <= config.start {
|
||||
return error("argument 'config.end' must be greater than 'config.start'")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
# Non-Uniform Distribution Functions
|
||||
|
||||
This module contains functions for sampling from non-uniform distributions.
|
||||
|
||||
All implementations of the `rand.PRNG` interface generate numbers from uniform
|
||||
distributions. This library exists to allow the generation of pseudorandom numbers
|
||||
sampled from non-uniform distributions. Additionally, it allows the user to use any
|
||||
PRNG of their choice. This is because the default RNG can be reassigned to a different
|
||||
generator. It can either be one of the pre-existing one (which are well-tested and
|
||||
recommended) or a custom user-defined one. See `rand.set_rng()`.
|
|
@ -1,85 +0,0 @@
|
|||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module dist
|
||||
|
||||
import math
|
||||
import rand
|
||||
|
||||
fn check_probability_range(p f64) {
|
||||
if p < 0 || p > 1 {
|
||||
panic('$p is not a valid probability value.')
|
||||
}
|
||||
}
|
||||
|
||||
// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
|
||||
pub fn bernoulli(p f64) bool {
|
||||
check_probability_range(p)
|
||||
return rand.f64() <= p
|
||||
}
|
||||
|
||||
// binomial returns the number of successful trials out of n when the
|
||||
// probability of success for each trial is p.
|
||||
pub fn binomial(n int, p f64) int {
|
||||
check_probability_range(p)
|
||||
mut count := 0
|
||||
for _ in 0 .. n {
|
||||
if bernoulli(p) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Configuration struct for the `normal_pair` function. The default value for
|
||||
// `mu` is 0 and the default value for `sigma` is 1.
|
||||
pub struct NormalConfigStruct {
|
||||
mu f64 = 0.0
|
||||
sigma f64 = 1.0
|
||||
}
|
||||
|
||||
// normal_pair returns a pair of normally distributed random numbers with the mean mu
|
||||
// and standard deviation sigma. If not specified, mu is 0 and sigma is 1. Intended usage is
|
||||
// `x, y := normal_pair(mu: mean, sigma: stdev)`, or `x, y := normal_pair()`.
|
||||
pub fn normal_pair(config NormalConfigStruct) (f64, f64) {
|
||||
if config.sigma <= 0 {
|
||||
panic('The standard deviation has to be positive.')
|
||||
}
|
||||
// This is an implementation of the Marsaglia polar method
|
||||
// See: https://doi.org/10.1137%2F1006063
|
||||
// Also: https://en.wikipedia.org/wiki/Marsaglia_polar_method
|
||||
for {
|
||||
u := rand.f64_in_range(-1, 1) or { 0.0 }
|
||||
v := rand.f64_in_range(-1, 1) or { 0.0 }
|
||||
|
||||
s := u * u + v * v
|
||||
if s >= 1 || s == 0 {
|
||||
continue
|
||||
}
|
||||
t := math.sqrt(-2 * math.log(s) / s)
|
||||
x := config.mu + config.sigma * t * u
|
||||
y := config.mu + config.sigma * t * v
|
||||
return x, y
|
||||
}
|
||||
return config.mu, config.mu
|
||||
}
|
||||
|
||||
// normal returns a normally distributed random number with the mean mu and standard deviation
|
||||
// sigma. If not specified, mu is 0 and sigma is 1. Intended usage is
|
||||
// `x := normal(mu: mean, sigma: etdev)` or `x := normal()`.
|
||||
// **NOTE:** If you are generating a lot of normal variates, use `the normal_pair` function
|
||||
// instead. This function discards one of the two variates generated by the `normal_pair` function.
|
||||
pub fn normal(config NormalConfigStruct) f64 {
|
||||
x, _ := normal_pair(config)
|
||||
return x
|
||||
}
|
||||
|
||||
// exponential returns an exponentially distributed random number with the rate paremeter
|
||||
// lambda. It is expected that lambda is positive.
|
||||
pub fn exponential(lambda f64) f64 {
|
||||
if lambda <= 0 {
|
||||
panic('The rate (lambda) must be positive.')
|
||||
}
|
||||
// Use the inverse transform sampling method
|
||||
return -math.log(rand.f64()) / lambda
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import math
|
||||
import rand
|
||||
import rand.dist
|
||||
|
||||
const (
|
||||
// The sample size to be used
|
||||
|
@ -20,7 +19,7 @@ fn test_bernoulli() {
|
|||
for p in ps {
|
||||
mut successes := 0
|
||||
for _ in 0 .. count {
|
||||
if dist.bernoulli(p) {
|
||||
if rand.bernoulli(p) or { false } {
|
||||
successes++
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +42,7 @@ fn test_binomial() {
|
|||
mut sum := 0
|
||||
mut var := 0.0
|
||||
for _ in 0 .. count {
|
||||
x := dist.binomial(n, p)
|
||||
x := rand.binomial(n, p) or { 0 }
|
||||
sum += x
|
||||
dist := (x - np)
|
||||
var += dist * dist
|
||||
|
@ -68,7 +67,7 @@ fn test_normal_pair() {
|
|||
mut sum := 0.0
|
||||
mut var := 0.0
|
||||
for _ in 0 .. count {
|
||||
x, y := dist.normal_pair(mu: mu, sigma: sigma)
|
||||
x, y := rand.normal_pair(mu: mu, sigma: sigma) or { 0.0, 0.0 }
|
||||
sum += x + y
|
||||
dist_x := x - mu
|
||||
dist_y := y - mu
|
||||
|
@ -95,7 +94,7 @@ fn test_normal() {
|
|||
mut sum := 0.0
|
||||
mut var := 0.0
|
||||
for _ in 0 .. count {
|
||||
x := dist.normal(mu: mu, sigma: sigma)
|
||||
x := rand.normal(mu: mu, sigma: sigma) or { 0.0 }
|
||||
sum += x
|
||||
dist := x - mu
|
||||
var += dist * dist
|
||||
|
@ -120,7 +119,7 @@ fn test_exponential() {
|
|||
mut sum := 0.0
|
||||
mut var := 0.0
|
||||
for _ in 0 .. count {
|
||||
x := dist.exponential(lambda)
|
||||
x := rand.exponential(lambda)
|
||||
sum += x
|
||||
dist := x - mu
|
||||
var += dist * dist
|
|
@ -0,0 +1,130 @@
|
|||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
|
||||
// NOTE: mini_math.v exists, so that we can avoid `import math`,
|
||||
// just for the math.log and math.sqrt functions needed for the
|
||||
// non uniform random number redistribution functions.
|
||||
// Importing math is relatively heavy, both in terms of compilation
|
||||
// speed (more source to process), and in terms of increases in the
|
||||
// generated executable sizes (if the rest of the program does not use
|
||||
// math already; many programs do not need math, for example the
|
||||
// compiler itself does not, while needing random number generation.
|
||||
|
||||
const sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974
|
||||
|
||||
[inline]
|
||||
fn msqrt(a f64) f64 {
|
||||
if a == 0 {
|
||||
return a
|
||||
}
|
||||
mut x := a
|
||||
z, ex := frexp(x)
|
||||
w := x
|
||||
// approximate square root of number between 0.5 and 1
|
||||
// relative error of approximation = 7.47e-3
|
||||
x = 4.173075996388649989089e-1 + 5.9016206709064458299663e-1 * z // adjust for odd powers of 2
|
||||
if (ex & 1) != 0 {
|
||||
x *= rand.sqrt2
|
||||
}
|
||||
x = scalbn(x, ex >> 1)
|
||||
// newton iterations
|
||||
x = 0.5 * (x + w / x)
|
||||
x = 0.5 * (x + w / x)
|
||||
x = 0.5 * (x + w / x)
|
||||
return x
|
||||
}
|
||||
|
||||
// a simplified approximation (without the edge cases), see math.log
|
||||
fn mlog(a f64) f64 {
|
||||
ln2_lo := 1.90821492927058770002e-10
|
||||
ln2_hi := 0.693147180369123816490
|
||||
l1 := 0.6666666666666735130
|
||||
l2 := 0.3999999999940941908
|
||||
l3 := 0.2857142874366239149
|
||||
l4 := 0.2222219843214978396
|
||||
l5 := 0.1818357216161805012
|
||||
l6 := 0.1531383769920937332
|
||||
l7 := 0.1479819860511658591
|
||||
x := a
|
||||
mut f1, mut ki := frexp(x)
|
||||
if f1 < rand.sqrt2 / 2 {
|
||||
f1 *= 2
|
||||
ki--
|
||||
}
|
||||
f := f1 - 1
|
||||
k := f64(ki)
|
||||
s := f / (2 + f)
|
||||
s2 := s * s
|
||||
s4 := s2 * s2
|
||||
t1 := s2 * (l1 + s4 * (l3 + s4 * (l5 + s4 * l7)))
|
||||
t2 := s4 * (l2 + s4 * (l4 + s4 * l6))
|
||||
r := t1 + t2
|
||||
hfsq := 0.5 * f * f
|
||||
return k * ln2_hi - ((hfsq - (s * (hfsq + r) + k * ln2_lo)) - f)
|
||||
}
|
||||
|
||||
fn frexp(x f64) (f64, int) {
|
||||
mut y := f64_bits(x)
|
||||
ee := int((y >> 52) & 0x7ff)
|
||||
if ee == 0 {
|
||||
if x != 0.0 {
|
||||
x1p64 := f64_from_bits(u64(0x43f0000000000000))
|
||||
z, e_ := frexp(x * x1p64)
|
||||
return z, e_ - 64
|
||||
}
|
||||
return x, 0
|
||||
} else if ee == 0x7ff {
|
||||
return x, 0
|
||||
}
|
||||
e_ := ee - 0x3fe
|
||||
y &= u64(0x800fffffffffffff)
|
||||
y |= u64(0x3fe0000000000000)
|
||||
return f64_from_bits(y), e_
|
||||
}
|
||||
|
||||
fn scalbn(x f64, n_ int) f64 {
|
||||
mut n := n_
|
||||
x1p1023 := f64_from_bits(u64(0x7fe0000000000000))
|
||||
x1p53 := f64_from_bits(u64(0x4340000000000000))
|
||||
x1p_1022 := f64_from_bits(u64(0x0010000000000000))
|
||||
|
||||
mut y := x
|
||||
if n > 1023 {
|
||||
y *= x1p1023
|
||||
n -= 1023
|
||||
if n > 1023 {
|
||||
y *= x1p1023
|
||||
n -= 1023
|
||||
if n > 1023 {
|
||||
n = 1023
|
||||
}
|
||||
}
|
||||
} else if n < -1022 {
|
||||
/*
|
||||
make sure final n < -53 to avoid double
|
||||
rounding in the subnormal range
|
||||
*/
|
||||
y *= x1p_1022 * x1p53
|
||||
n += 1022 - 53
|
||||
if n < -1022 {
|
||||
y *= x1p_1022 * x1p53
|
||||
n += 1022 - 53
|
||||
if n < -1022 {
|
||||
n = -1022
|
||||
}
|
||||
}
|
||||
}
|
||||
return y * f64_from_bits(u64((0x3ff + n)) << 52)
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn f64_from_bits(b u64) f64 {
|
||||
return *unsafe { &f64(&b) }
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn f64_bits(f f64) u64 {
|
||||
return *unsafe { &u64(&f) }
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module mt19937
|
||||
|
||||
import rand.buffer
|
||||
import rand.seed
|
||||
|
||||
/*
|
||||
|
@ -60,11 +61,10 @@ const (
|
|||
// MT19937RNG is generator that uses the Mersenne Twister algorithm with period 2^19937.
|
||||
// **NOTE**: The RNG is not seeded when instantiated so remember to seed it before use.
|
||||
pub struct MT19937RNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
state []u64 = get_first_state(seed.time_seed_array(2))
|
||||
mti int = mt19937.nn
|
||||
bytes_left int
|
||||
buffer u64
|
||||
state []u64 = get_first_state(seed.time_seed_array(2))
|
||||
mti int = mt19937.nn
|
||||
}
|
||||
|
||||
fn get_first_state(seed_data []u32) []u64 {
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
module musl
|
||||
|
||||
import rand.seed
|
||||
import rand.buffer
|
||||
|
||||
pub const seed_len = 1
|
||||
|
||||
// MuslRNG ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c
|
||||
pub struct MuslRNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
state u32 = seed.time_seed_32()
|
||||
bytes_left int
|
||||
buffer u32
|
||||
state u32 = seed.time_seed_32()
|
||||
}
|
||||
|
||||
// seed sets the current random state based on `seed_data`.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module pcg32
|
||||
|
||||
import rand.seed
|
||||
import rand.buffer
|
||||
|
||||
pub const seed_len = 4
|
||||
|
||||
|
@ -11,11 +12,10 @@ pub const seed_len = 4
|
|||
// https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.c, and
|
||||
// https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.h
|
||||
pub struct PCG32RNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
state u64 = u64(0x853c49e6748fea9b) ^ seed.time_seed_64()
|
||||
inc u64 = u64(0xda3e39cb94b95bdb) ^ seed.time_seed_64()
|
||||
bytes_left int
|
||||
buffer u32
|
||||
state u64 = u64(0x853c49e6748fea9b) ^ seed.time_seed_64()
|
||||
inc u64 = u64(0xda3e39cb94b95bdb) ^ seed.time_seed_64()
|
||||
}
|
||||
|
||||
// seed seeds the PCG32RNG with 4 `u32` values.
|
||||
|
|
109
vlib/rand/rand.v
109
vlib/rand/rand.v
|
@ -274,34 +274,79 @@ pub fn (mut rng PRNG) ascii(len int) string {
|
|||
return internal_string_from_set(mut rng, rand.ascii_chars, len)
|
||||
}
|
||||
|
||||
// Configuration struct for the shuffle functions.
|
||||
// The start index is inclusive and the end index is exclusive.
|
||||
// Set the end to 0 to shuffle until the end of the array.
|
||||
[params]
|
||||
pub struct ShuffleConfigStruct {
|
||||
pub:
|
||||
start int
|
||||
end int
|
||||
// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
|
||||
pub fn (mut rng PRNG) bernoulli(p f64) ?bool {
|
||||
if p < 0 || p > 1 {
|
||||
return error('$p is not a valid probability value.')
|
||||
}
|
||||
return rng.f64() <= p
|
||||
}
|
||||
|
||||
fn (config ShuffleConfigStruct) validate_for<T>(a []T) ? {
|
||||
if config.start < 0 || config.start >= a.len {
|
||||
return error("argument 'config.start' must be in range [0, a.len)")
|
||||
// normal returns a normally distributed pseudorandom f64 in range `[0, 1)`.
|
||||
// NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
|
||||
pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) ?f64 {
|
||||
x, _ := rng.normal_pair(conf)?
|
||||
return x
|
||||
}
|
||||
|
||||
// normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`.
|
||||
pub fn (mut rng PRNG) normal_pair(conf config.NormalConfigStruct) ?(f64, f64) {
|
||||
if conf.sigma <= 0 {
|
||||
return error('Standard deviation must be positive')
|
||||
}
|
||||
if config.end < 0 || config.end > a.len {
|
||||
return error("argument 'config.end' must be in range [0, a.len]")
|
||||
// This is an implementation of the Marsaglia polar method
|
||||
// See: https://doi.org/10.1137%2F1006063
|
||||
// Also: https://en.wikipedia.org/wiki/Marsaglia_polar_method
|
||||
for {
|
||||
u := rng.f64_in_range(-1, 1) or { 0.0 }
|
||||
v := rng.f64_in_range(-1, 1) or { 0.0 }
|
||||
|
||||
s := u * u + v * v
|
||||
if s >= 1 || s == 0 {
|
||||
continue
|
||||
}
|
||||
t := msqrt(-2 * mlog(s) / s)
|
||||
x := conf.mu + conf.sigma * t * u
|
||||
y := conf.mu + conf.sigma * t * v
|
||||
return x, y
|
||||
}
|
||||
return error('Implementation error. Please file an issue.')
|
||||
}
|
||||
|
||||
// binomial returns the number of successful trials out of n when the
|
||||
// probability of success for each trial is p.
|
||||
pub fn (mut rng PRNG) binomial(n int, p f64) ?int {
|
||||
if p < 0 || p > 1 {
|
||||
return error('$p is not a valid probability value.')
|
||||
}
|
||||
mut count := 0
|
||||
for _ in 0 .. n {
|
||||
if rng.bernoulli(p)! {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// exponential returns an exponentially distributed random number with the rate paremeter
|
||||
// lambda. It is expected that lambda is positive.
|
||||
pub fn (mut rng PRNG) exponential(lambda f64) f64 {
|
||||
if lambda <= 0 {
|
||||
panic('The rate (lambda) must be positive.')
|
||||
}
|
||||
// Use the inverse transform sampling method
|
||||
return -mlog(rng.f64()) / lambda
|
||||
}
|
||||
|
||||
// shuffle randomly permutates the elements in `a`. The range for shuffling is
|
||||
// optional and the entire array is shuffled by default. Leave the end as 0 to
|
||||
// shuffle all elements until the end.
|
||||
[direct_array_access]
|
||||
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config ShuffleConfigStruct) ? {
|
||||
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? {
|
||||
config.validate_for(a)?
|
||||
new_end := if config.end == 0 { a.len } else { config.end }
|
||||
for i in config.start .. new_end {
|
||||
x := rng.int_in_range(i, new_end) or { config.start }
|
||||
x := rng.int_in_range(i, new_end) or { config.start + i }
|
||||
// swap
|
||||
a_i := a[i]
|
||||
a[i] = a[x]
|
||||
|
@ -311,7 +356,7 @@ pub fn (mut rng PRNG) shuffle<T>(mut a []T, config ShuffleConfigStruct) ? {
|
|||
|
||||
// shuffle_clone returns a random permutation of the elements in `a`.
|
||||
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
|
||||
pub fn (mut rng PRNG) shuffle_clone<T>(a []T, config ShuffleConfigStruct) ?[]T {
|
||||
pub fn (mut rng PRNG) shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ?[]T {
|
||||
mut res := a.clone()
|
||||
rng.shuffle(mut res, config)?
|
||||
return res
|
||||
|
@ -541,13 +586,13 @@ pub fn ascii(len int) string {
|
|||
// shuffle randomly permutates the elements in `a`. The range for shuffling is
|
||||
// optional and the entire array is shuffled by default. Leave the end as 0 to
|
||||
// shuffle all elements until the end.
|
||||
pub fn shuffle<T>(mut a []T, config ShuffleConfigStruct) ? {
|
||||
pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? {
|
||||
default_rng.shuffle(mut a, config)?
|
||||
}
|
||||
|
||||
// shuffle_clone returns a random permutation of the elements in `a`.
|
||||
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
|
||||
pub fn shuffle_clone<T>(a []T, config ShuffleConfigStruct) ?[]T {
|
||||
pub fn shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ?[]T {
|
||||
return default_rng.shuffle_clone(a, config)
|
||||
}
|
||||
|
||||
|
@ -563,3 +608,31 @@ pub fn choose<T>(array []T, k int) ?[]T {
|
|||
pub fn sample<T>(array []T, k int) []T {
|
||||
return default_rng.sample(array, k)
|
||||
}
|
||||
|
||||
// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
|
||||
pub fn bernoulli(p f64) ?bool {
|
||||
return default_rng.bernoulli(p)
|
||||
}
|
||||
|
||||
// normal returns a normally distributed pseudorandom f64 in range `[0, 1)`.
|
||||
// NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
|
||||
pub fn normal(conf config.NormalConfigStruct) ?f64 {
|
||||
return default_rng.normal(conf)
|
||||
}
|
||||
|
||||
// normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`.
|
||||
pub fn normal_pair(conf config.NormalConfigStruct) ?(f64, f64) {
|
||||
return default_rng.normal_pair(conf)
|
||||
}
|
||||
|
||||
// binomial returns the number of successful trials out of n when the
|
||||
// probability of success for each trial is p.
|
||||
pub fn binomial(n int, p f64) ?int {
|
||||
return default_rng.binomial(n, p)
|
||||
}
|
||||
|
||||
// exponential returns an exponentially distributed random number with the rate paremeter
|
||||
// lambda. It is expected that lambda is positive.
|
||||
pub fn exponential(lambda f64) f64 {
|
||||
return default_rng.exponential(lambda)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
module splitmix64
|
||||
|
||||
import rand.seed
|
||||
import rand.buffer
|
||||
|
||||
pub const seed_len = 2
|
||||
|
||||
// SplitMix64RNG ported from http://xoshiro.di.unimi.it/splitmix64.c
|
||||
pub struct SplitMix64RNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
state u64 = seed.time_seed_64()
|
||||
bytes_left int
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module sys
|
||||
|
||||
import math.bits
|
||||
import rand.buffer
|
||||
import rand.seed
|
||||
|
||||
// Implementation note:
|
||||
|
@ -36,10 +37,9 @@ fn calculate_iterations_for(bits int) int {
|
|||
|
||||
// SysRNG is the PRNG provided by default in the libc implementiation that V uses.
|
||||
pub struct SysRNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
seed u32 = seed.time_seed_32()
|
||||
buffer int
|
||||
bytes_left int
|
||||
seed u32 = seed.time_seed_32()
|
||||
}
|
||||
|
||||
// r.seed() sets the seed of the accepting SysRNG to the given data.
|
||||
|
@ -71,7 +71,7 @@ pub fn (mut r SysRNG) u8() u8 {
|
|||
r.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
r.buffer = r.default_rand()
|
||||
r.buffer = u64(r.default_rand())
|
||||
r.bytes_left = sys.rand_bytesize - 1
|
||||
value := u8(r.buffer)
|
||||
r.buffer >>= 8
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module wyrand
|
||||
|
||||
import hash
|
||||
import rand.buffer
|
||||
import rand.seed
|
||||
|
||||
// Redefinition of some constants that we will need for pseudorandom number generation.
|
||||
|
@ -16,6 +17,7 @@ pub const seed_len = 2
|
|||
|
||||
// WyRandRNG is a RNG based on the WyHash hashing algorithm.
|
||||
pub struct WyRandRNG {
|
||||
buffer.PRNGBuffer
|
||||
mut:
|
||||
state u64 = seed.time_seed_64()
|
||||
bytes_left int
|
||||
|
|
|
@ -645,7 +645,7 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
|||
unsafe {
|
||||
*subscr[i].prev = subscr[i].nxt
|
||||
}
|
||||
if subscr[i].nxt != 0 {
|
||||
if unsafe { subscr[i].nxt != 0 } {
|
||||
subscr[i].nxt.prev = subscr[i].prev
|
||||
// just in case we have missed a semaphore during restore
|
||||
subscr[i].nxt.sem.post()
|
||||
|
@ -659,7 +659,7 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
|||
unsafe {
|
||||
*subscr[i].prev = subscr[i].nxt
|
||||
}
|
||||
if subscr[i].nxt != 0 {
|
||||
if unsafe { subscr[i].nxt != 0 } {
|
||||
subscr[i].nxt.prev = subscr[i].prev
|
||||
subscr[i].nxt.sem.post()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ mut:
|
|||
}
|
||||
|
||||
fn restore_terminal_state() {
|
||||
if ui.ctx_ptr != 0 {
|
||||
if unsafe { ui.ctx_ptr != 0 } {
|
||||
if ui.ctx_ptr.cfg.use_alternate_buffer {
|
||||
// clear the terminal and set the cursor to the origin
|
||||
print('\x1b[2J\x1b[3J')
|
||||
|
@ -84,7 +84,7 @@ pub fn init(cfg Config) &Context {
|
|||
for code in ctx.cfg.reset {
|
||||
os.signal_opt(code, fn (_ os.Signal) {
|
||||
mut c := ui.ctx_ptr
|
||||
if c != 0 {
|
||||
if unsafe { c != 0 } {
|
||||
c.cleanup()
|
||||
}
|
||||
exit(0)
|
||||
|
|
|
@ -44,7 +44,7 @@ fn restore_terminal_state_signal(_ os.Signal) {
|
|||
fn restore_terminal_state() {
|
||||
termios_reset()
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
if unsafe { c != 0 } {
|
||||
c.paused = true
|
||||
load_title()
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
os.signal_opt(.tstp, restore_terminal_state_signal) or {}
|
||||
os.signal_opt(.cont, fn (_ os.Signal) {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
if unsafe { c != 0 } {
|
||||
c.termios_setup() or { panic(err) }
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
mut event := &Event{
|
||||
|
@ -136,7 +136,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
for code in ctx.cfg.reset {
|
||||
os.signal_opt(code, fn (_ os.Signal) {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
if unsafe { c != 0 } {
|
||||
c.cleanup()
|
||||
}
|
||||
exit(0)
|
||||
|
@ -145,7 +145,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
|
||||
os.signal_opt(.winch, fn (_ os.Signal) {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
if unsafe { c != 0 } {
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
|
||||
mut event := &Event{
|
||||
|
@ -200,7 +200,7 @@ fn termios_reset() {
|
|||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
||||
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
||||
c := ctx_ptr
|
||||
if c != 0 && c.cfg.use_alternate_buffer {
|
||||
if unsafe { c != 0 } && c.cfg.use_alternate_buffer {
|
||||
print('\x1b[?1049l')
|
||||
}
|
||||
os.flush()
|
||||
|
@ -267,7 +267,7 @@ fn (mut ctx Context) parse_events() {
|
|||
ctx.shift(1)
|
||||
}
|
||||
}
|
||||
if event != 0 {
|
||||
if unsafe { event != 0 } {
|
||||
ctx.event(event)
|
||||
nr_iters = 0
|
||||
}
|
||||
|
|
|
@ -4,36 +4,35 @@
|
|||
module time
|
||||
|
||||
import strings
|
||||
import math
|
||||
|
||||
// format returns a date string in "YYYY-MM-DD HH:mm" format (24h).
|
||||
pub fn (t Time) format() string {
|
||||
return t.get_fmt_str(.hyphen, .hhmm24, .yyyymmdd)
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}'
|
||||
}
|
||||
|
||||
// format_ss returns a date string in "YYYY-MM-DD HH:mm:ss" format (24h).
|
||||
pub fn (t Time) format_ss() string {
|
||||
return t.get_fmt_str(.hyphen, .hhmmss24, .yyyymmdd)
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}'
|
||||
}
|
||||
|
||||
// format_ss_milli returns a date string in "YYYY-MM-DD HH:mm:ss.123" format (24h).
|
||||
pub fn (t Time) format_ss_milli() string {
|
||||
return t.get_fmt_str(.hyphen, .hhmmss24_milli, .yyyymmdd)
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}.${(t.microsecond / 1000):03d}'
|
||||
}
|
||||
|
||||
// format_ss_micro returns a date string in "YYYY-MM-DD HH:mm:ss.123456" format (24h).
|
||||
pub fn (t Time) format_ss_micro() string {
|
||||
return t.get_fmt_str(.hyphen, .hhmmss24_micro, .yyyymmdd)
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}.${t.microsecond:06d}'
|
||||
}
|
||||
|
||||
// hhmm returns a date string in "HH:mm" format (24h).
|
||||
pub fn (t Time) hhmm() string {
|
||||
return t.get_fmt_time_str(.hhmm24)
|
||||
return '${t.hour:02d}:${t.minute:02d}'
|
||||
}
|
||||
|
||||
// hhmmss returns a date string in "HH:mm:ss" format (24h).
|
||||
pub fn (t Time) hhmmss() string {
|
||||
return t.get_fmt_time_str(.hhmmss24)
|
||||
return '${t.hour:02d}:${t.minute:02d}:${t.second:02d}'
|
||||
}
|
||||
|
||||
// hhmm12 returns a date string in "hh:mm" format (12h).
|
||||
|
@ -238,15 +237,15 @@ pub fn (t Time) custom_format(s string) string {
|
|||
sb.write_string('${(t.hour + 1):02}')
|
||||
}
|
||||
'w' {
|
||||
sb.write_string('${math.ceil((t.day + days_before[t.month - 1] +
|
||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7):.0}')
|
||||
}
|
||||
'ww' {
|
||||
sb.write_string('${math.ceil((t.day + days_before[t.month - 1] +
|
||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7):02.0}')
|
||||
}
|
||||
'wo' {
|
||||
sb.write_string(ordinal_suffix(int(math.ceil((t.day + days_before[t.month - 1] +
|
||||
sb.write_string(ordinal_suffix(int(mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7))))
|
||||
}
|
||||
'Q' {
|
||||
|
@ -439,3 +438,14 @@ pub fn (t Time) utc_string() string {
|
|||
utc_string := '$day_str, $t.day $month_str $t.year ${t.hour:02d}:${t.minute:02d}:${t.second:02d} UTC'
|
||||
return utc_string
|
||||
}
|
||||
|
||||
// mceil returns the least integer value greater than or equal to x.
|
||||
fn mceil(x f64) f64 {
|
||||
if x > 0 {
|
||||
return 1 + int(x)
|
||||
}
|
||||
if x < 0 {
|
||||
return -int(-x)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ pub fn pref_arch_to_table_language(pref_arch pref.Arch) Language {
|
|||
// * Table.type_kind(typ) not TypeSymbol.kind.
|
||||
// Each TypeSymbol is entered into `Table.types`.
|
||||
// See also: Table.sym.
|
||||
|
||||
[minify]
|
||||
pub struct TypeSymbol {
|
||||
pub:
|
||||
|
@ -548,6 +547,15 @@ pub fn (t &Table) type_kind(typ Type) Kind {
|
|||
return t.sym(typ).kind
|
||||
}
|
||||
|
||||
pub fn (t &Table) type_is_for_pointer_arithmetic(typ Type) bool {
|
||||
typ_sym := t.sym(typ)
|
||||
if typ_sym.kind == .struct_ {
|
||||
return false
|
||||
} else {
|
||||
return typ.is_any_kind_of_pointer() || typ.is_int_valptr()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Kind {
|
||||
placeholder
|
||||
void
|
||||
|
|
|
@ -215,6 +215,9 @@ pub fn (mut b Builder) parse_imports() {
|
|||
}
|
||||
exit(0)
|
||||
}
|
||||
if b.pref.dump_files != '' {
|
||||
b.dump_files(b.parsed_files.map(it.path))
|
||||
}
|
||||
b.rebuild_modules()
|
||||
}
|
||||
|
||||
|
@ -241,6 +244,7 @@ pub fn (mut b Builder) resolve_deps() {
|
|||
for node in deps_resolved.nodes {
|
||||
mods << node.name
|
||||
}
|
||||
b.dump_modules(mods)
|
||||
if b.pref.is_verbose {
|
||||
eprintln('------ imported modules: ------')
|
||||
eprintln(mods.str())
|
||||
|
@ -270,7 +274,7 @@ pub fn (b &Builder) import_graph() &depgraph.DepGraph {
|
|||
deps << 'builtin'
|
||||
if b.pref.backend == .c {
|
||||
// TODO JavaScript backend doesn't handle os for now
|
||||
if b.pref.is_vsh && p.mod.name !in ['os', 'dl'] {
|
||||
if b.pref.is_vsh && p.mod.name !in ['os', 'dl', 'strings.textscanner'] {
|
||||
deps << 'os'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -483,17 +483,6 @@ fn (mut v Builder) setup_output_name() {
|
|||
v.ccoptions.o_args << '-o "$v.pref.out_name"'
|
||||
}
|
||||
|
||||
fn (mut v Builder) dump_c_options(all_args []string) {
|
||||
if v.pref.dump_c_flags != '' {
|
||||
non_empty_args := all_args.filter(it != '').join('\n') + '\n'
|
||||
if v.pref.dump_c_flags == '-' {
|
||||
print(non_empty_args)
|
||||
} else {
|
||||
os.write_file(v.pref.dump_c_flags, non_empty_args) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut v Builder) cc() {
|
||||
if os.executable().contains('vfmt') {
|
||||
return
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
module builder
|
||||
|
||||
import os
|
||||
|
||||
pub fn (b &Builder) dump_c_options(all_args []string) {
|
||||
dump_list(b.pref.dump_c_flags, all_args)
|
||||
}
|
||||
|
||||
pub fn (b &Builder) dump_modules(mods []string) {
|
||||
dump_list(b.pref.dump_modules, mods)
|
||||
}
|
||||
|
||||
pub fn (b &Builder) dump_files(files []string) {
|
||||
dump_list(b.pref.dump_files, files)
|
||||
}
|
||||
|
||||
fn dump_list(file_path string, list []string) {
|
||||
if file_path != '' {
|
||||
content := list.filter(it != '').join('\n') + '\n'
|
||||
if file_path == '-' {
|
||||
print(content)
|
||||
} else {
|
||||
os.write_file(file_path, content) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -346,10 +346,7 @@ pub fn (mut v Builder) cc_msvc() {
|
|||
defines := sflags.defines
|
||||
other_flags := sflags.other_flags
|
||||
// Include the base paths
|
||||
a << '-I "$r.ucrt_include_path"'
|
||||
a << '-I "$r.vs_include_path"'
|
||||
a << '-I "$r.um_include_path"'
|
||||
a << '-I "$r.shared_include_path"'
|
||||
a << r.include_paths()
|
||||
a << defines
|
||||
a << inc_paths
|
||||
a << other_flags
|
||||
|
@ -358,9 +355,7 @@ pub fn (mut v Builder) cc_msvc() {
|
|||
a << '/link'
|
||||
a << '/NOLOGO'
|
||||
a << '/OUT:"$v.pref.out_name"'
|
||||
a << '/LIBPATH:"$r.ucrt_lib_path"'
|
||||
a << '/LIBPATH:"$r.um_lib_path"'
|
||||
a << '/LIBPATH:"$r.vs_lib_path"'
|
||||
a << r.library_paths()
|
||||
if !all_cflags.contains('/DEBUG') {
|
||||
// only use /DEBUG, if the user *did not* provide its own:
|
||||
a << '/DEBUG:FULL' // required for prod builds to generate a PDB file
|
||||
|
@ -375,6 +370,7 @@ pub fn (mut v Builder) cc_msvc() {
|
|||
if env_ldflags != '' {
|
||||
a << env_ldflags
|
||||
}
|
||||
v.dump_c_options(a)
|
||||
args := a.join(' ')
|
||||
// write args to a file so that we dont smash createprocess
|
||||
os.write_file(out_name_cmd_line, args) or {
|
||||
|
@ -420,17 +416,18 @@ fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags
|
|||
}
|
||||
println('$obj_path not found, building it (with msvc)...')
|
||||
cfile := '${path_without_o_postfix}.c'
|
||||
// println('cfile: $cfile')
|
||||
flags := msvc_string_flags(moduleflags)
|
||||
inc_dirs := flags.inc_paths.join(' ')
|
||||
defines := flags.defines.join(' ')
|
||||
include_string := '-I "$msvc.ucrt_include_path" -I "$msvc.vs_include_path" -I "$msvc.um_include_path" -I "$msvc.shared_include_path" $inc_dirs'
|
||||
//
|
||||
mut oargs := []string{}
|
||||
env_cflags := os.getenv('CFLAGS')
|
||||
mut all_cflags := '$env_cflags $v.pref.cflags'
|
||||
if all_cflags != ' ' {
|
||||
oargs << all_cflags
|
||||
}
|
||||
oargs << '/NOLOGO'
|
||||
oargs << '/volatile:ms'
|
||||
//
|
||||
if v.pref.is_prod {
|
||||
oargs << '/O2'
|
||||
|
@ -440,12 +437,18 @@ fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags
|
|||
oargs << '/MDd'
|
||||
oargs << '/D_DEBUG'
|
||||
}
|
||||
oargs << defines
|
||||
oargs << msvc.include_paths()
|
||||
oargs << inc_dirs
|
||||
oargs << '/c "$cfile"'
|
||||
oargs << '/Fo"$obj_path"'
|
||||
env_ldflags := os.getenv('LDFLAGS')
|
||||
if env_ldflags != '' {
|
||||
oargs << env_ldflags
|
||||
}
|
||||
v.dump_c_options(oargs)
|
||||
str_oargs := oargs.join(' ')
|
||||
cmd := '"$msvc.full_cl_exe_path" /volatile:ms $str_oargs $defines $include_string /c "$cfile" /Fo"$obj_path"'
|
||||
cmd := '"$msvc.full_cl_exe_path" $str_oargs'
|
||||
// Note: the quotes above ARE balanced.
|
||||
$if trace_thirdparty_obj_files ? {
|
||||
println('>>> build_thirdparty_obj_file_with_msvc cmd: $cmd')
|
||||
|
@ -510,7 +513,7 @@ pub fn msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
|
|||
}
|
||||
mut lpaths := []string{}
|
||||
for l in lib_paths {
|
||||
lpaths << '/LIBPATH:"' + os.real_path(l) + '"'
|
||||
lpaths << '/LIBPATH:"${os.real_path(l)}"'
|
||||
}
|
||||
return MsvcStringFlags{
|
||||
real_libs: real_libs
|
||||
|
@ -520,3 +523,34 @@ pub fn msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
|
|||
other_flags: other_flags
|
||||
}
|
||||
}
|
||||
|
||||
fn (r MsvcResult) include_paths() []string {
|
||||
mut res := []string{cap: 4}
|
||||
if r.ucrt_include_path != '' {
|
||||
res << '-I "$r.ucrt_include_path"'
|
||||
}
|
||||
if r.vs_include_path != '' {
|
||||
res << '-I "$r.vs_include_path"'
|
||||
}
|
||||
if r.um_include_path != '' {
|
||||
res << '-I "$r.um_include_path"'
|
||||
}
|
||||
if r.shared_include_path != '' {
|
||||
res << '-I "$r.shared_include_path"'
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn (r MsvcResult) library_paths() []string {
|
||||
mut res := []string{cap: 3}
|
||||
if r.ucrt_lib_path != '' {
|
||||
res << '/LIBPATH:"$r.ucrt_lib_path"'
|
||||
}
|
||||
if r.um_lib_path != '' {
|
||||
res << '/LIBPATH:"$r.um_lib_path"'
|
||||
}
|
||||
if r.vs_lib_path != '' {
|
||||
res << '/LIBPATH:"$r.vs_lib_path"'
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
left_type = left_type.set_nr_muls(1)
|
||||
}
|
||||
} else if left_type.has_flag(.shared_f) {
|
||||
left_type = left_type.clear_flag(.shared_f)
|
||||
left_type = left_type.clear_flag(.shared_f).deref()
|
||||
}
|
||||
if ident_var_info.share == .atomic_t {
|
||||
left_type = left_type.set_flag(.atomic_f)
|
||||
|
|
|
@ -940,8 +940,13 @@ pub fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_re
|
|||
node.pos)
|
||||
}
|
||||
if !expr_return_type.has_flag(.optional) {
|
||||
c.error('to propagate an option, the call must also return an optional type',
|
||||
node.pos)
|
||||
if expr_return_type.has_flag(.result) {
|
||||
c.warn('propagating a result like an option is deprecated, use `foo()!` instead of `foo()?`',
|
||||
node.pos)
|
||||
} else {
|
||||
c.error('to propagate an option, the call must also return an optional type',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -2150,25 +2155,25 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
|
|||
c.inside_if_guard = true
|
||||
node.expr_type = c.expr(node.expr)
|
||||
c.inside_if_guard = old_inside_if_guard
|
||||
if !node.expr_type.has_flag(.optional) {
|
||||
mut no_opt := true
|
||||
if !node.expr_type.has_flag(.optional) && !node.expr_type.has_flag(.result) {
|
||||
mut no_opt_or_res := true
|
||||
match mut node.expr {
|
||||
ast.IndexExpr {
|
||||
no_opt = false
|
||||
no_opt_or_res = false
|
||||
node.expr_type = node.expr_type.set_flag(.optional)
|
||||
node.expr.is_option = true
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
if node.expr.op == .arrow {
|
||||
no_opt = false
|
||||
no_opt_or_res = false
|
||||
node.expr_type = node.expr_type.set_flag(.optional)
|
||||
node.expr.is_option = true
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
if no_opt {
|
||||
c.error('expression should return an option', node.expr.pos())
|
||||
if no_opt_or_res {
|
||||
c.error('expression should either return an option or a result', node.expr.pos())
|
||||
}
|
||||
}
|
||||
return ast.bool_type
|
||||
|
@ -2312,6 +2317,10 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
|||
mut to_sym := c.table.sym(to_type) // type to be used as cast
|
||||
mut final_to_sym := c.table.final_sym(to_type)
|
||||
|
||||
if to_type.has_flag(.optional) {
|
||||
c.error('casting to optional type is forbidden', node.pos)
|
||||
}
|
||||
|
||||
if (to_sym.is_number() && from_sym.name == 'JS.Number')
|
||||
|| (to_sym.is_number() && from_sym.name == 'JS.BigInt')
|
||||
|| (to_sym.is_string() && from_sym.name == 'JS.String')
|
||||
|
@ -2672,7 +2681,7 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
typ = obj.expr.expr_type.clear_flag(.optional)
|
||||
typ = obj.expr.expr_type.clear_flag(.optional).clear_flag(.result)
|
||||
}
|
||||
} else {
|
||||
typ = c.expr(obj.expr)
|
||||
|
|
|
@ -80,8 +80,12 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
|||
// }
|
||||
array_info := type_sym.array_info()
|
||||
node.elem_type = array_info.elem_type
|
||||
// clear optional flag incase of: `fn opt_arr ?[]int { return [] }`
|
||||
return c.expected_type.clear_flag(.optional)
|
||||
// clear optional flag incase of: `fn opt_arr() ?[]int { return [] }`
|
||||
return if c.expected_type.has_flag(.shared_f) {
|
||||
c.expected_type.clear_flag(.shared_f).deref()
|
||||
} else {
|
||||
c.expected_type
|
||||
}.clear_flag(.optional)
|
||||
}
|
||||
// [1,2,3]
|
||||
if node.exprs.len > 0 && node.elem_type == ast.void_type {
|
||||
|
|
|
@ -559,12 +559,12 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
if !found && mut node.left is ast.IndexExpr {
|
||||
c.expr(node.left)
|
||||
sym := c.table.sym(node.left.left_type)
|
||||
sym := c.table.final_sym(node.left.left_type)
|
||||
if sym.info is ast.Array {
|
||||
elem_sym := c.table.sym(sym.info.elem_type)
|
||||
if elem_sym.info is ast.FnType {
|
||||
node.return_type = elem_sym.info.func.return_type
|
||||
return elem_sym.info.func.return_type
|
||||
func = elem_sym.info.func
|
||||
found = true
|
||||
} else {
|
||||
c.error('cannot call the element of the array, it is not a function',
|
||||
node.pos)
|
||||
|
@ -572,23 +572,21 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
} else if sym.info is ast.Map {
|
||||
value_sym := c.table.sym(sym.info.value_type)
|
||||
if value_sym.info is ast.FnType {
|
||||
node.return_type = value_sym.info.func.return_type
|
||||
return value_sym.info.func.return_type
|
||||
func = value_sym.info.func
|
||||
found = true
|
||||
} else {
|
||||
c.error('cannot call the value of the map, it is not a function', node.pos)
|
||||
}
|
||||
} else if sym.info is ast.ArrayFixed {
|
||||
elem_sym := c.table.sym(sym.info.elem_type)
|
||||
if elem_sym.info is ast.FnType {
|
||||
node.return_type = elem_sym.info.func.return_type
|
||||
return elem_sym.info.func.return_type
|
||||
func = elem_sym.info.func
|
||||
found = true
|
||||
} else {
|
||||
c.error('cannot call the element of the array, it is not a function',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
found = true
|
||||
return ast.string_type
|
||||
}
|
||||
if !found && mut node.left is ast.CallExpr {
|
||||
c.expr(node.left)
|
||||
|
@ -788,12 +786,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
c.warn('`error($arg)` can be shortened to just `$arg`', node.pos)
|
||||
}
|
||||
}
|
||||
// TODO: typ optimize.. this node can get processed more than once
|
||||
if node.expected_arg_types.len == 0 {
|
||||
for param in func.params {
|
||||
node.expected_arg_types << param.typ
|
||||
}
|
||||
}
|
||||
c.set_node_expected_arg_types(mut node, func)
|
||||
if !c.pref.backend.is_js() && node.args.len > 0 && func.params.len == 0 {
|
||||
c.error('too many arguments in call to `$func.name` (non-js backend: $c.pref.backend)',
|
||||
node.pos)
|
||||
|
@ -904,15 +897,6 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
c.check_expected_call_arg(arg_typ, c.unwrap_generic(param.typ), node.language,
|
||||
call_arg) or {
|
||||
// str method, allow type with str method if fn arg is string
|
||||
// Passing an int or a string array produces a c error here
|
||||
// Deleting this condition results in propper V error messages
|
||||
// if arg_typ_sym.kind == .string && typ_sym.has_method('str') {
|
||||
// continue
|
||||
// }
|
||||
if arg_typ_sym.kind == .void && param_typ_sym.kind == .string {
|
||||
continue
|
||||
}
|
||||
if param.typ.has_flag(.generic) {
|
||||
continue
|
||||
}
|
||||
|
@ -997,7 +981,6 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if func.language != .c && !c.inside_unsafe && arg_typ.nr_muls() != param.typ.nr_muls()
|
||||
&& !(call_arg.is_mut && param.is_mut) && !(!call_arg.is_mut && !param.is_mut)
|
||||
&& param.typ !in [ast.byteptr_type, ast.charptr_type, ast.voidptr_type] {
|
||||
// sym := c.table.sym(typ)
|
||||
c.warn('automatic referencing/dereferencing is deprecated and will be removed soon (got: $arg_typ.nr_muls() references, expected: $param.typ.nr_muls() references)',
|
||||
call_arg.pos)
|
||||
}
|
||||
|
@ -1463,10 +1446,8 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if got_arg_typ != ast.void_type {
|
||||
c.error('$err.msg() in argument ${i + 1} to `${left_sym.name}.$method_name`',
|
||||
arg.pos)
|
||||
}
|
||||
c.error('$err.msg() in argument ${i + 1} to `${left_sym.name}.$method_name`',
|
||||
arg.pos)
|
||||
}
|
||||
}
|
||||
if method.is_unsafe && !c.inside_unsafe {
|
||||
|
@ -1476,12 +1457,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||
if !c.table.cur_fn.is_deprecated && method.is_deprecated {
|
||||
c.deprecate_fnmethod('method', '${left_sym.name}.$method.name', method, node)
|
||||
}
|
||||
// TODO: typ optimize.. this node can get processed more than once
|
||||
if node.expected_arg_types.len == 0 {
|
||||
for i in 1 .. method.params.len {
|
||||
node.expected_arg_types << method.params[i].typ
|
||||
}
|
||||
}
|
||||
c.set_node_expected_arg_types(mut node, method)
|
||||
if is_method_from_embed {
|
||||
node.receiver_type = node.from_embed_types.last().derive(method.params[0].typ)
|
||||
} else if is_generic {
|
||||
|
@ -1619,6 +1595,15 @@ fn (mut c Checker) go_expr(mut node ast.GoExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) set_node_expected_arg_types(mut node ast.CallExpr, func &ast.Fn) {
|
||||
if node.expected_arg_types.len == 0 {
|
||||
start_idx := if func.is_method { 1 } else { 0 }
|
||||
for i in start_idx .. func.params.len {
|
||||
node.expected_arg_types << func.params[i].typ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) deprecate_fnmethod(kind string, name string, the_fn ast.Fn, node ast.CallExpr) {
|
||||
mut deprecation_message := ''
|
||||
now := time.now()
|
||||
|
|
|
@ -592,6 +592,14 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
}
|
||||
c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name`',
|
||||
left_right_pos)
|
||||
} else if left_type.is_ptr() {
|
||||
for_ptr_op := c.table.type_is_for_pointer_arithmetic(left_type)
|
||||
if left_sym.language == .v && !c.pref.translated && !c.inside_unsafe && !for_ptr_op
|
||||
&& right_type.is_int() {
|
||||
sugg := ' (you can use it inside an `unsafe` block)'
|
||||
c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name` $sugg',
|
||||
left_right_pos)
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (node.left is ast.InfixExpr &&
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/checker_comparison_between_obj_and_int.vv:10:5: error: infix expr: cannot use `int literal` (right expression) as `Foo` (you can use it inside an `unsafe` block)
|
||||
8 |
|
||||
9 | fn insert_helper(mut node Foo) {
|
||||
10 | if node == 0 {
|
||||
| ~~~~~~~~~
|
||||
11 | }
|
||||
12 | }
|
|
@ -0,0 +1,14 @@
|
|||
struct Foo {}
|
||||
|
||||
// inside a unsafe block it is valid
|
||||
fn insert_helper_unsafe(mut node Foo) {
|
||||
if unsafe { node == 0 } {
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_helper(mut node Foo) {
|
||||
if node == 0 {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,7 +1,7 @@
|
|||
vlib/v/checker/tests/expression_should_return_an_option.vv:28:10: error: expression should return an option
|
||||
vlib/v/checker/tests/expression_should_return_an_option.vv:28:10: error: expression should either return an option or a result
|
||||
26 | }
|
||||
27 | // should be an checker error:
|
||||
28 | if x := return_string() {
|
||||
| ~~~~~~~~~~~~~~~
|
||||
29 | println('x: $x')
|
||||
30 | }
|
||||
30 | }
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/fn_call_arg_mismatch_err_c.vv:13:18: error: `os.chdir(files) ?` (no value) used as value in argument 1 to `os.ls`
|
||||
11 | println(files)
|
||||
12 | } else {
|
||||
13 | println(os.ls(os.chdir(files)?)?)
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
14 | }
|
||||
15 | println(files)
|
|
@ -0,0 +1,29 @@
|
|||
module main
|
||||
|
||||
import os
|
||||
|
||||
fn list_files() ?[][]string {
|
||||
mut unchecked_files := os.ls('utilities/modules')?
|
||||
println(unchecked_files)
|
||||
for files in unchecked_files {
|
||||
println(files)
|
||||
if os.is_file(files) == true {
|
||||
println(files)
|
||||
} else {
|
||||
println(os.ls(os.chdir(files)?)?)
|
||||
}
|
||||
println(files)
|
||||
}
|
||||
mut modules := [['Module:', 'Path:', 'Description']]
|
||||
return modules
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut data := [
|
||||
['Module:', 'Path:', 'Description'],
|
||||
]
|
||||
mods := list_files() or { [['null', 'null', 'null']] }
|
||||
for _, mod in mods {
|
||||
data << mod
|
||||
}
|
||||
}
|
|
@ -1,7 +1,20 @@
|
|||
vlib/v/checker/tests/fn_type_mismatch.vv:11:15: error: invalid array element: expected `fn (int, int) f32`, not `fn (f32, f32) f32`
|
||||
9 |
|
||||
9 |
|
||||
10 | fn main() {
|
||||
11 | fns := [add, div]
|
||||
| ~~~
|
||||
12 | println(fns[0](10.0, 5.0))
|
||||
13 | println(fns[1](10.0, 5.0))
|
||||
vlib/v/checker/tests/fn_type_mismatch.vv:12:17: error: cannot use `float literal` as `int` in argument 1 to ``
|
||||
10 | fn main() {
|
||||
11 | fns := [add, div]
|
||||
12 | println(fns[0](10.0, 5.0))
|
||||
| ~~~~
|
||||
13 | println(fns[1](10.0, 5.0))
|
||||
14 | }
|
||||
vlib/v/checker/tests/fn_type_mismatch.vv:13:17: error: cannot use `float literal` as `int` in argument 1 to ``
|
||||
11 | fns := [add, div]
|
||||
12 | println(fns[0](10.0, 5.0))
|
||||
13 | println(fns[1](10.0, 5.0))
|
||||
| ~~~~
|
||||
14 | }
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
vlib/v/checker/tests/main_and_script_err.vv:1:1: error: function `main` is already defined
|
||||
1 | fn main() {
|
||||
| ^
|
||||
2 | println('main')
|
||||
3 | }
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/method_call_arg_mismatch.vv:9:10: error: `baz()` (no value) used as value in argument 1 to `Foo.bar`
|
||||
7 | fn main() {
|
||||
8 | foo := Foo{}
|
||||
9 | foo.bar(baz())
|
||||
| ~~~~~
|
||||
10 | }
|
|
@ -0,0 +1,10 @@
|
|||
struct Foo {}
|
||||
|
||||
fn (f Foo) bar(baz fn ()) {}
|
||||
|
||||
fn baz() {}
|
||||
|
||||
fn main() {
|
||||
foo := Foo{}
|
||||
foo.bar(baz())
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
vlib/v/checker/tests/optional_variable_err.vv:2:7: error: casting to optional type is forbidden
|
||||
1 | fn main() {
|
||||
2 | _ := ?bool(false)
|
||||
| ~~~~~~~~~~~~
|
||||
3 | }
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
_ := ?bool(false)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/propagate_option_with_result_err.vv:6:7: error: to propagate an option, the call must also return an optional type
|
||||
vlib/v/checker/tests/propagate_option_with_result_err.vv:6:7: warning: propagating a result like an option is deprecated, use `foo()!` instead of `foo()?`
|
||||
4 |
|
||||
5 | fn bar() ?string {
|
||||
6 | foo()?
|
||||
|
|
|
@ -7,7 +7,6 @@ import strings
|
|||
import v.ast
|
||||
import v.util
|
||||
import v.pref
|
||||
import v.mathutil
|
||||
|
||||
const (
|
||||
bs = '\\'
|
||||
|
@ -41,6 +40,7 @@ pub mut:
|
|||
used_imports []string // to remove unused imports
|
||||
import_syms_used map[string]bool // to remove unused import symbols.
|
||||
mod2alias map[string]string // for `import time as t`, will contain: 'time'=>'t'
|
||||
mod2syms map[string]string // import time { now } 'time.now'=>'now'
|
||||
use_short_fn_args bool
|
||||
single_line_fields bool // should struct fields be on a single line
|
||||
it_name string // the name to replace `it` with
|
||||
|
@ -71,8 +71,16 @@ pub fn fmt(file ast.File, table &ast.Table, pref &pref.Preferences, is_debug boo
|
|||
if res.len == 1 {
|
||||
return f.out_imports.str().trim_space() + '\n'
|
||||
}
|
||||
bounded_import_pos := mathutil.min(res.len, f.import_pos)
|
||||
return res[..bounded_import_pos] + f.out_imports.str() + res[bounded_import_pos..]
|
||||
if res.len <= f.import_pos {
|
||||
imp_str := f.out_imports.str().trim_space()
|
||||
if imp_str.len > 0 {
|
||||
return res + '\n' + imp_str + '\n'
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
} else {
|
||||
return res[..f.import_pos] + f.out_imports.str() + res[f.import_pos..]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) process_file_imports(file &ast.File) {
|
||||
|
@ -82,6 +90,9 @@ pub fn (mut f Fmt) process_file_imports(file &ast.File) {
|
|||
f.mod2alias['${imp.mod}.$sym.name'] = sym.name
|
||||
f.mod2alias['${imp.mod.all_after_last('.')}.$sym.name'] = sym.name
|
||||
f.mod2alias[sym.name] = sym.name
|
||||
f.mod2syms['${imp.mod}.$sym.name'] = sym.name
|
||||
f.mod2syms['${imp.mod.all_after_last('.')}.$sym.name'] = sym.name
|
||||
f.mod2syms[sym.name] = sym.name
|
||||
f.import_syms_used[sym.name] = false
|
||||
}
|
||||
}
|
||||
|
@ -208,8 +219,8 @@ pub fn (mut f Fmt) short_module(name string) string {
|
|||
if !name.contains('.') || name.starts_with('JS.') {
|
||||
return name
|
||||
}
|
||||
if name in f.mod2alias {
|
||||
return f.mod2alias[name]
|
||||
if name in f.mod2syms {
|
||||
return f.mod2syms[name]
|
||||
}
|
||||
if name.ends_with('>') {
|
||||
generic_levels := name.trim_string_right('>').split('<')
|
||||
|
@ -1639,6 +1650,7 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
|||
for arg in node.args {
|
||||
f.comments(arg.comments)
|
||||
}
|
||||
mut is_method_newline := false
|
||||
if node.is_method {
|
||||
if node.name in ['map', 'filter', 'all', 'any'] {
|
||||
f.in_lambda_depth++
|
||||
|
@ -1650,7 +1662,8 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
|||
// `time.now()` without `time imported` is processed as a method call with `time` being
|
||||
// a `node.left` expression. Import `time` automatically.
|
||||
// TODO fetch all available modules
|
||||
if node.left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
|
||||
if node.left.name in ['time', 'os', 'strings', 'math', 'json', 'base64']
|
||||
&& !node.left.scope.known_var(node.left.name) {
|
||||
f.file.imports << ast.Import{
|
||||
mod: node.left.name
|
||||
alias: node.left.name
|
||||
|
@ -1658,6 +1671,11 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
|||
}
|
||||
}
|
||||
f.expr(node.left)
|
||||
is_method_newline = node.left.pos().last_line != node.name_pos.line_nr
|
||||
if is_method_newline {
|
||||
f.indent++
|
||||
f.writeln('')
|
||||
}
|
||||
f.write('.' + node.name)
|
||||
} else {
|
||||
f.write_language_prefix(node.language)
|
||||
|
@ -1680,6 +1698,9 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
|||
f.write(')')
|
||||
f.or_expr(node.or_block)
|
||||
f.comments(node.comments, has_nl: false)
|
||||
if is_method_newline {
|
||||
f.indent--
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut f Fmt) write_generic_call_if_require(node ast.CallExpr) {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
fn main() {
|
||||
options := cmdline
|
||||
.only_options(args)
|
||||
.filter(it != '-') // options, not including '-'
|
||||
.map(if it.bytes().len > 1 {
|
||||
1
|
||||
})
|
||||
|
||||
println(options)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
fn main() {
|
||||
options := cmdline
|
||||
.only_options(args)
|
||||
.filter(it != '-') // options, not including '-'
|
||||
.map(if it.bytes().len>1{
|
||||
1
|
||||
})
|
||||
|
||||
println(options)
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
module proto
|
||||
import emily33901.vproto
|
||||
|
||||
import emily33901.vproto
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import rand
|
||||
import rand.seed
|
||||
|
||||
fn main() {
|
||||
rand.seed(seed.time_seed_array(2))
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import json
|
||||
|
||||
struct Request {
|
||||
a int
|
||||
}
|
||||
|
||||
fn parse(s string) ?Request {
|
||||
return json.decode(Request, s)
|
||||
}
|
||||
|
||||
fn parse2(s string) ?Request {
|
||||
req := json.decode(Request, s)?
|
||||
return req
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println(parse('{"a": 22} ')?)
|
||||
println(parse2('{"a": 22} ')?)
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
strings := 'hello'
|
||||
a := strings.repeat(2)
|
||||
println(a)
|
||||
}
|
|
@ -389,6 +389,9 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
|||
g.write('*')
|
||||
}
|
||||
g.expr(left)
|
||||
if !is_decl && var_type.has_flag(.shared_f) {
|
||||
g.write('->val') // don't reset the mutex, just change the value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +435,6 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
|||
}
|
||||
*/
|
||||
}
|
||||
g.is_shared = var_type.has_flag(.shared_f)
|
||||
if !cloned {
|
||||
if is_fixed_array_var {
|
||||
// TODO Instead of the translated check, check if it's a pointer already
|
||||
|
@ -445,6 +447,7 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
|||
g.expr(val)
|
||||
g.write(', sizeof($typ_str))')
|
||||
} else if is_decl {
|
||||
g.is_shared = var_type.has_flag(.shared_f)
|
||||
if is_fixed_array_init && !has_val {
|
||||
if val is ast.ArrayInit {
|
||||
g.array_init(val, ident.name)
|
||||
|
@ -476,11 +479,11 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
|||
if op_overloaded {
|
||||
g.op_arg(val, op_expected_right, val_type)
|
||||
} else {
|
||||
exp_type := if left.is_auto_deref_var() {
|
||||
exp_type := if left.is_auto_deref_var() || var_type.has_flag(.shared_f) {
|
||||
var_type.deref()
|
||||
} else {
|
||||
var_type
|
||||
}
|
||||
}.clear_flag(.shared_f) // don't reset the mutex, just change the value
|
||||
g.expr_with_cast(val, val_type, exp_type)
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue