Compare commits
24 Commits
b7f2ef78b2
...
9b1f7f5e94
| Author | SHA1 | Date |
|---|---|---|
|
|
9b1f7f5e94 | |
|
|
25df4fa143 | |
|
|
2109a6a85c | |
|
|
d1a0ac26fd | |
|
|
735817374e | |
|
|
f8ed4ab9d0 | |
|
|
3c8b67521b | |
|
|
23117e6802 | |
|
|
893e2ff6cb | |
|
|
7fc9e3a4c1 | |
|
|
da71bced46 | |
|
|
59ddaa9ede | |
|
|
134b594e4d | |
|
|
c2ecfb32d9 | |
|
|
03d2258b6d | |
|
|
48749b0b24 | |
|
|
47dccd56a2 | |
|
|
705e260180 | |
|
|
31bee98607 | |
|
|
444d8c7a81 | |
|
|
47c18c4570 | |
|
|
bf75a873b5 | |
|
|
f9bd107a84 | |
|
|
624f022ddc |
|
|
@ -90,6 +90,7 @@ making pullrequests, and you can just do normal git operations such as:
|
|||
|
||||
5. When finished with a feature/bugfix/change, you can:
|
||||
`git checkout -b fix_alabala`
|
||||
- Don't forget to keep formatting standards, run `v fmt -w YOUR_MODIFIED_FILES` before committing
|
||||
6. `git push pullrequest` # (NOTE: the `pullrequest` remote was setup on step 4)
|
||||
7. On GitHub's web interface, go to: https://github.com/vlang/v/pulls
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ language, very similar to the way it is right now.
|
|||
|
||||
### Linux, macOS, Windows, *BSD, Solaris, WSL, Android, etc.
|
||||
|
||||
Usually installing V is quite simple if you have an environment that already has a
|
||||
functional `git` installation.
|
||||
Usually installing V is quite simple if you have an environment that already has a
|
||||
functional `git` installation.
|
||||
|
||||
* *(* ***PLEASE NOTE:*** *If you run into any trouble or you have a different operating
|
||||
system or Linux distribution that doesn't install or work immediately, please see
|
||||
system or Linux distribution that doesn't install or work immediately, please see
|
||||
[Installation Issues](https://github.com/vlang/v/discussions/categories/installation-issues)
|
||||
and search for your OS and problem. If you can't find your problem, please add it to an
|
||||
existing discussion if one exists for your OS, or create a new one if a main discussion
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ see also `v help build`.
|
|||
Passing -no-std will remove that flag, and you can then use -cflags ''
|
||||
to pass the other options for your specific C compiler.
|
||||
|
||||
-assert aborts
|
||||
-assert aborts
|
||||
Call abort() after an assertion failure. Debuggers usually
|
||||
install signal handlers for SIGABRT, so your program will stop and you
|
||||
will get a backtrace. If you are running your program outside of a
|
||||
|
|
@ -267,3 +267,14 @@ see also `v help build`.
|
|||
Call print_backtrace() after an assertion failure. Note that
|
||||
backtraces are not implemented yet on all combinations of
|
||||
platform/compiler.
|
||||
|
||||
-thread-stack-size 4194304
|
||||
Set the thread stack size to 4MB. Use multiples of 4096.
|
||||
The default is 8MB, which is enough for compiling V programs, with deeply
|
||||
nested expressions (~40 levels).
|
||||
It may need to be increased, if you are getting stack overflow errors for
|
||||
deeply recursive programs like some of the stages of the V compiler itself,
|
||||
that use relatively few threads.
|
||||
It may be decreased, to reduce the memory footprint of programs that launch
|
||||
hundreds/thousands of threads, but where each of the threads does not need
|
||||
a big stack.
|
||||
|
|
|
|||
|
|
@ -112,9 +112,7 @@ fn (mut app App) time() vweb.Result {
|
|||
|
||||
<img width=662 src="https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/img/time.png?raw=true">
|
||||
|
||||
>You have to rebuild and restart the website every time you change the code.
|
||||
In the future, Vweb will detect changes and recompile the website in the background
|
||||
while it's running.
|
||||
>TIP: run the following command to live-reload the server: `v watch run blog.v`
|
||||
|
||||
The `.text(string)` method returns a plain text document with the provided
|
||||
text, which isn't frequently used in websites.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub fn min<T>(a []T) ?T {
|
|||
return val
|
||||
}
|
||||
|
||||
// max returns the maximum the maximum value in the array
|
||||
// max returns the maximum value in the array
|
||||
// Example: arrays.max([1,2,3,0,9]) // => 9
|
||||
pub fn max<T>(a []T) ?T {
|
||||
if a.len == 0 {
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ fn unhandled_exception_handler(e &ExceptionPointers) int {
|
|||
match e.exception_record.code {
|
||||
// These are 'used' by the backtrace printer
|
||||
// so we dont want to catch them...
|
||||
0x4001000A, 0x40010006 {
|
||||
0x4001000A, 0x40010006, 0xE06D7363 {
|
||||
return 0
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
module builtin
|
||||
|
||||
// struct C.FILE {}
|
||||
|
||||
// <string.h>
|
||||
fn C.memcpy(dest voidptr, const_src voidptr, n usize) voidptr
|
||||
|
||||
|
|
@ -10,11 +12,13 @@ fn C.memmove(dest voidptr, const_src voidptr, n usize) voidptr
|
|||
fn C.memset(str voidptr, c int, n usize) voidptr
|
||||
|
||||
[trusted]
|
||||
fn C.calloc(int, int) &byte
|
||||
fn C.calloc(int, int) &u8
|
||||
|
||||
fn C.malloc(int) &byte
|
||||
fn C.atoi(&char) int
|
||||
|
||||
fn C.realloc(a &byte, b int) &byte
|
||||
fn C.malloc(int) &u8
|
||||
|
||||
fn C.realloc(a &u8, b int) &u8
|
||||
|
||||
fn C.free(ptr voidptr)
|
||||
|
||||
|
|
@ -120,6 +124,8 @@ fn C.chdir(path &char) int
|
|||
|
||||
fn C.rewind(stream &C.FILE) int
|
||||
|
||||
fn C.ftell(&C.FILE) int
|
||||
|
||||
fn C.stat(&char, voidptr) int
|
||||
|
||||
fn C.lstat(path &char, buf &C.stat) int
|
||||
|
|
|
|||
|
|
@ -295,6 +295,17 @@ pub fn (cp &char) vstring_literal_with_len(len int) string {
|
|||
}
|
||||
}
|
||||
|
||||
// len_utf8 returns the number of runes contained in the string `s`.
|
||||
pub fn (s string) len_utf8() int {
|
||||
mut l := 0
|
||||
mut i := 0
|
||||
for i < s.len {
|
||||
l++
|
||||
i += ((0xe5000000 >> ((unsafe { s.str[i] } >> 3) & 0x1e)) & 3) + 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// clone_static returns an independent copy of a given array.
|
||||
// It should be used only in -autofree generated code.
|
||||
fn (a string) clone_static() string {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,14 @@ fn test_add() {
|
|||
assert a.ends_with('3')
|
||||
}
|
||||
|
||||
fn test_len_utf8() {
|
||||
assert 'Vlang'.len_utf8() == 5
|
||||
assert 'María'.len_utf8() == 5
|
||||
assert '姓名'.len_utf8() == 2
|
||||
assert 'Слово'.len_utf8() == 5
|
||||
assert 'Λέξη'.len_utf8() == 4
|
||||
}
|
||||
|
||||
fn test_ends_with() {
|
||||
a := 'browser.v'
|
||||
assert a.ends_with('.v')
|
||||
|
|
|
|||
|
|
@ -66,6 +66,19 @@ pub fn utf32_decode_to_buffer(code u32, buf &u8) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// utf8_str_len returns the number of runes contained in the string.
|
||||
[deprecated: 'use `string.len_utf8()` instead']
|
||||
[deprecated_after: '2022-05-28']
|
||||
pub fn utf8_str_len(s string) int {
|
||||
mut l := 0
|
||||
mut i := 0
|
||||
for i < s.len {
|
||||
l++
|
||||
i += ((0xe5000000 >> ((unsafe { s.str[i] } >> 3) & 0x1e)) & 3) + 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// Convert utf8 to utf32
|
||||
// the original implementation did not check for
|
||||
// valid utf8 in the string, and could result in
|
||||
|
|
@ -134,17 +147,6 @@ fn utf8_len(c u8) int {
|
|||
return b
|
||||
}
|
||||
|
||||
// Calculate string length for in number of codepoints
|
||||
pub fn utf8_str_len(s string) int {
|
||||
mut l := 0
|
||||
mut i := 0
|
||||
for i < s.len {
|
||||
l++
|
||||
i += ((0xe5000000 >> ((unsafe { s.str[i] } >> 3) & 0x1e)) & 3) + 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// Calculate string length for formatting, i.e. number of "characters"
|
||||
// This is simplified implementation. if you need specification compliant width,
|
||||
// use utf8.east_asian.display_width.
|
||||
|
|
|
|||
160
vlib/gg/draw.c.v
160
vlib/gg/draw.c.v
|
|
@ -250,57 +250,47 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
|
|||
mut dx := f32(0)
|
||||
mut dy := f32(0)
|
||||
|
||||
// left top quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
if r != 0 {
|
||||
// left top quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// right top quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// right top quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// right bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// right bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// left bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// left bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
sgl.end()
|
||||
}
|
||||
sgl.end()
|
||||
|
||||
// Currently don't use 'gg.draw_line()' directly, it will repeatedly execute '*ctx.scale'.
|
||||
sgl.begin_lines()
|
||||
|
|
@ -358,61 +348,51 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
|
|||
mut dx := f32(0)
|
||||
mut dy := f32(0)
|
||||
|
||||
// left top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
if r != 0 {
|
||||
// left top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
sgl.v2f(ltx, lty)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
sgl.v2f(ltx, lty)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// right top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// right top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
sgl.v2f(rtx, rty)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
sgl.v2f(rtx, rty)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// right bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// right bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
sgl.v2f(rbx, rby)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
sgl.v2f(rbx, rby)
|
||||
}
|
||||
sgl.end()
|
||||
sgl.end()
|
||||
|
||||
// left bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
// left bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
for i in 0 .. 31 {
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
sgl.v2f(lbx, lby)
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
sgl.v2f(lbx, lby)
|
||||
sgl.end()
|
||||
}
|
||||
sgl.end()
|
||||
|
||||
// Separate drawing is to prevent transparent color overlap
|
||||
// top rectangle
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module math
|
||||
module main
|
||||
|
||||
import math
|
||||
import benchmark
|
||||
|
||||
const max_iter = 1000
|
||||
|
|
@ -7,8 +8,8 @@ const max_iter = 1000
|
|||
fn test_benchmark_acos() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = acos(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.acos(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -16,8 +17,8 @@ fn test_benchmark_acos() {
|
|||
fn test_benchmark_acosh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = acosh(1.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.acosh(1.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -25,8 +26,8 @@ fn test_benchmark_acosh() {
|
|||
fn test_benchmark_asin() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = asin(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.asin(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -34,8 +35,8 @@ fn test_benchmark_asin() {
|
|||
fn test_benchmark_asinh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = asinh(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.asinh(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -43,8 +44,8 @@ fn test_benchmark_asinh() {
|
|||
fn test_benchmark_atan() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = atan(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.atan(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -52,8 +53,8 @@ fn test_benchmark_atan() {
|
|||
fn test_benchmark_atanh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = atanh(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.atanh(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -61,8 +62,8 @@ fn test_benchmark_atanh() {
|
|||
fn test_benchmark_atan2() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = atan2(0.5, 1)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.atan2(0.5, 1)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -70,8 +71,8 @@ fn test_benchmark_atan2() {
|
|||
fn test_benchmark_cbrt() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = cbrt(10)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.cbrt(10)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -79,19 +80,17 @@ fn test_benchmark_cbrt() {
|
|||
fn test_benchmark_ceil() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = ceil(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.ceil(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const copysign_neg = -1.0
|
||||
|
||||
fn test_benchmark_copysign() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = copysign(0.5, math.copysign_neg)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.copysign(0.5, -1.0)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -99,8 +98,8 @@ fn test_benchmark_copysign() {
|
|||
fn test_benchmark_cos() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = cos(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.cos(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -108,8 +107,8 @@ fn test_benchmark_cos() {
|
|||
fn test_benchmark_cosh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = cosh(2.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.cosh(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -117,8 +116,8 @@ fn test_benchmark_cosh() {
|
|||
fn test_benchmark_erf() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = erf(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.erf(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -126,8 +125,8 @@ fn test_benchmark_erf() {
|
|||
fn test_benchmark_erfc() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = erfc(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.erfc(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -135,8 +134,8 @@ fn test_benchmark_erfc() {
|
|||
fn test_benchmark_exp() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = exp(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.exp(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -144,8 +143,8 @@ fn test_benchmark_exp() {
|
|||
fn test_benchmark_expm1() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = expm1(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.expm1(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -153,19 +152,17 @@ fn test_benchmark_expm1() {
|
|||
fn test_benchmark_exp2() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = exp2(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.exp2(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const abs_pos = 0.5
|
||||
|
||||
fn test_benchmark_abs() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = abs(math.abs_pos)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.abs(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -173,8 +170,8 @@ fn test_benchmark_abs() {
|
|||
fn test_benchmark_floor() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = floor(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.floor(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -182,8 +179,8 @@ fn test_benchmark_floor() {
|
|||
fn test_benchmark_max() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = max(10, 3)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.max(10, 3)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -191,8 +188,8 @@ fn test_benchmark_max() {
|
|||
fn test_benchmark_min() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = min(10, 3)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.min(10, 3)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -200,8 +197,8 @@ fn test_benchmark_min() {
|
|||
fn test_benchmark_mod() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = mod(10, 3)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.mod(10, 3)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -210,8 +207,8 @@ fn test_benchmark_frexp() {
|
|||
mut x := 0.0
|
||||
mut y := 0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x, y = frexp(8)
|
||||
for i in 0 .. max_iter {
|
||||
x, y = math.frexp(8)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -219,8 +216,8 @@ fn test_benchmark_frexp() {
|
|||
fn test_benchmark_gamma() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = gamma(2.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.gamma(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -228,8 +225,8 @@ fn test_benchmark_gamma() {
|
|||
fn test_benchmark_hypot() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = hypot(3, 4)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.hypot(3, 4)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -237,8 +234,8 @@ fn test_benchmark_hypot() {
|
|||
fn test_benchmark_ldexp() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = ldexp(0.5, 2)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.ldexp(0.5, 2)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -246,8 +243,8 @@ fn test_benchmark_ldexp() {
|
|||
fn test_benchmark_log_gamma() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log_gamma(2.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log_gamma(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -255,8 +252,8 @@ fn test_benchmark_log_gamma() {
|
|||
fn test_benchmark_log() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -264,8 +261,8 @@ fn test_benchmark_log() {
|
|||
fn test_benchmark_log_b() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log_b(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log_b(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -273,8 +270,8 @@ fn test_benchmark_log_b() {
|
|||
fn test_benchmark_log1p() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log1p(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log1p(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -282,8 +279,8 @@ fn test_benchmark_log1p() {
|
|||
fn test_benchmark_log10() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log10(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log10(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -291,8 +288,8 @@ fn test_benchmark_log10() {
|
|||
fn test_benchmark_log2() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = log2(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.log2(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -301,8 +298,8 @@ fn test_benchmark_modf() {
|
|||
mut x := 0.0
|
||||
mut y := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x, y = modf(1.5)
|
||||
for i in 0 .. max_iter {
|
||||
x, y = math.modf(1.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -310,8 +307,8 @@ fn test_benchmark_modf() {
|
|||
fn test_benchmark_nextafter32() {
|
||||
mut x := f32(0.0)
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = nextafter32(0.5, 1)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.nextafter32(0.5, 1)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -319,8 +316,8 @@ fn test_benchmark_nextafter32() {
|
|||
fn test_benchmark_nextafter64() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = nextafter(0.5, 1)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.nextafter(0.5, 1)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -328,8 +325,8 @@ fn test_benchmark_nextafter64() {
|
|||
fn test_benchmark_pow_int() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = pow(2, 2)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.pow(2, 2)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -337,41 +334,35 @@ fn test_benchmark_pow_int() {
|
|||
fn test_benchmark_pow_frac() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = pow(2.5, 1.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.pow(2.5, 1.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const pow10pos = int(300)
|
||||
|
||||
fn test_benchmark_pow10_pos() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = pow10(math.pow10pos)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.pow10(300)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const pow10neg = int(-300)
|
||||
|
||||
fn test_benchmark_pow10_neg() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = pow10(math.pow10neg)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.pow10(-300)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const round_neg = f64(-2.5)
|
||||
|
||||
fn test_benchmark_round() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = round(math.round_neg)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.round(-2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -379,19 +370,17 @@ fn test_benchmark_round() {
|
|||
fn test_benchmark_round_to_even() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = round_to_even(math.round_neg)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.round_to_even(-2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const signbit_pos = 2.5
|
||||
|
||||
fn test_benchmark_signbit() {
|
||||
mut x := false
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = signbit(math.signbit_pos)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.signbit(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -399,8 +388,8 @@ fn test_benchmark_signbit() {
|
|||
fn test_benchmark_sin() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = sin(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.sin(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -409,8 +398,8 @@ fn test_benchmark_sincos() {
|
|||
mut x := 0.0
|
||||
mut y := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x, y = sincos(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x, y = math.sincos(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -418,17 +407,17 @@ fn test_benchmark_sincos() {
|
|||
fn test_benchmark_sinh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = sinh(2.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.sinh(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
fn test_benchmark_sqrt_indirect() {
|
||||
mut x, y := 0.0, 10.0
|
||||
f := sqrt
|
||||
f := math.sqrt
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
for i in 0 .. max_iter {
|
||||
x += f(y)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
|
|
@ -437,17 +426,17 @@ fn test_benchmark_sqrt_indirect() {
|
|||
fn test_benchmark_sqrt_latency() {
|
||||
mut x := 10.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = sqrt(x)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.sqrt(x)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
fn test_benchmark_sqrt_indirect_latency() {
|
||||
mut x := 10.0
|
||||
f := sqrt
|
||||
f := math.sqrt
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
for i in 0 .. max_iter {
|
||||
x = f(x)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
|
|
@ -459,7 +448,7 @@ fn is_prime(i int) bool {
|
|||
// the benefit of using a direct sqrt instruction on systems
|
||||
// that have one, whereas the obvious loop seems not to
|
||||
// demonstrate such a benefit.
|
||||
for j := 2; f64(j) <= sqrt(f64(i)); j++ {
|
||||
for j := 2; f64(j) <= math.sqrt(f64(i)); j++ {
|
||||
if i % j == 0 {
|
||||
return false
|
||||
}
|
||||
|
|
@ -470,7 +459,7 @@ fn is_prime(i int) bool {
|
|||
fn test_benchmark_sqrt_prime() {
|
||||
mut x := false
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
for i in 0 .. max_iter {
|
||||
x = is_prime(100003)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
|
|
@ -479,8 +468,8 @@ fn test_benchmark_sqrt_prime() {
|
|||
fn test_benchmark_tan() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = tan(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.tan(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -488,8 +477,8 @@ fn test_benchmark_tan() {
|
|||
fn test_benchmark_tanh() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = tanh(2.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.tanh(2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
@ -497,50 +486,44 @@ fn test_benchmark_tanh() {
|
|||
fn test_benchmark_trunc() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = trunc(0.5)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.trunc(0.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
fn test_benchmark_f64_bits() {
|
||||
mut y := u64(0)
|
||||
mut x := u64(0)
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
y = f64_bits(math.round_neg)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.f64_bits(-2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const round_u64 = u64(5)
|
||||
|
||||
fn test_benchmark_f64_from_bits() {
|
||||
mut x := 0.0
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = f64_from_bits(math.round_u64)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.f64_from_bits(5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const round_f32 = f32(-2.5)
|
||||
|
||||
fn test_benchmark_f32_bits() {
|
||||
mut y := u32(0)
|
||||
mut x := u32(0)
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
y = f32_bits(math.round_f32)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.f32_bits(-2.5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
||||
const round_u32 = u32(5)
|
||||
|
||||
fn test_benchmark_f32_from_bits() {
|
||||
mut x := f32(0.0)
|
||||
mut bmark := benchmark.start()
|
||||
for i in 0 .. math.max_iter {
|
||||
x = f32_from_bits(math.round_u32)
|
||||
for i in 0 .. max_iter {
|
||||
x = math.f32_from_bits(5)
|
||||
}
|
||||
bmark.measure(@FN)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import time
|
||||
|
||||
fn test_custom_format() {
|
||||
date := time.now()
|
||||
assert date.custom_format('YYYY-MM-DD HH:mm') == date.format()
|
||||
assert date.custom_format('MMM') == date.smonth()
|
||||
|
||||
test_str := 'M MM MMM MMMM\nD DD DDD DDDD\nd dd ddd dddd\nYY YYYY a A\nH HH h hh k kk e\nm mm s ss Z ZZ ZZZ\nDo DDDo Q Qo QQ\nN NN w wo ww\nM/D/YYYY N-HH:mm:ss Qo?a'
|
||||
|
||||
println(date.custom_format(test_str))
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
// that can be found in the LICENSE file.
|
||||
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)
|
||||
|
|
@ -53,6 +56,264 @@ pub fn (t Time) md() string {
|
|||
return t.get_fmt_date_str(.space, .mmmd)
|
||||
}
|
||||
|
||||
// appends ordinal suffix to a number
|
||||
fn ordinal_suffix(n int) string {
|
||||
if n > 3 && n < 21 {
|
||||
return '${n}th'
|
||||
}
|
||||
match n % 10 {
|
||||
1 {
|
||||
return '${n}st'
|
||||
}
|
||||
2 {
|
||||
return '${n}nd'
|
||||
}
|
||||
3 {
|
||||
return '${n}rd'
|
||||
}
|
||||
else {
|
||||
return '${n}th'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tokens_2 = ['MM', 'DD', 'Do', 'YY', 'ss', 'kk', 'NN', 'mm', 'hh', 'HH', 'ZZ', 'dd', 'Qo',
|
||||
'QQ', 'wo', 'ww']
|
||||
|
||||
const tokens_3 = ['MMM', 'DDD', 'ZZZ', 'ddd']
|
||||
|
||||
const tokens_4 = ['MMMM', 'DDDD', 'DDDo', 'dddd', 'YYYY']
|
||||
|
||||
// custom_format returns a date with custom format
|
||||
// | | Token | Output |
|
||||
// | :----------- | -------: | :--------- |
|
||||
// | Month | M | 1 2 ... 11 12 |
|
||||
// | | Mo | 1st 2nd ... 11th 12th |
|
||||
// | | MM | 01 02 ... 11 12 |
|
||||
// | | MMM | Jan Feb ... Nov Dec |
|
||||
// | | MMMM | January February ... November December |
|
||||
// | Quarter | Q | 1 2 3 4 |
|
||||
// | | QQ | 01 02 03 04 |
|
||||
// | | Qo | 1st 2nd 3rd 4th |
|
||||
// | Day of Month | D | 1 2 ... 30 31 |
|
||||
// | | Do | 1st 2nd ... 30th 31st |
|
||||
// | | DD | 01 02 ... 30 31 |
|
||||
// | Day of Year | DDD | 1 2 ... 364 365 |
|
||||
// | | DDDo | 1st 2nd ... 364th 365th |
|
||||
// | | DDDD | 001 002 ... 364 365 |
|
||||
// | Day of Week | d | 0 1 ... 5 6 (Sun-Sat) |
|
||||
// | | c | 1 2 ... 6 7 (Mon-Sun) |
|
||||
// | | dd | Su Mo ... Fr Sa |
|
||||
// | | ddd | Sun Mon ... Fri Sat |
|
||||
// | | dddd | Sunday Monday ... Friday Saturday |
|
||||
// | Week of Year | w | 1 2 ... 52 53 |
|
||||
// | | wo | 1st 2nd ... 52nd 53rd |
|
||||
// | | ww | 01 02 ... 52 53 |
|
||||
// | Year | YY | 70 71 ... 29 30 |
|
||||
// | | YYYY | 1970 1971 ... 2029 2030 |
|
||||
// | Era | N | BC AD |
|
||||
// | | NN | Before Christ, Anno Domini |
|
||||
// | AM/PM | A | AM PM |
|
||||
// | | a | am pm |
|
||||
// | Hour | H | 0 1 ... 22 23 |
|
||||
// | | HH | 00 01 ... 22 23 |
|
||||
// | | h | 1 2 ... 11 12 |
|
||||
// | | hh | 01 02 ... 11 12 |
|
||||
// | | k | 1 2 ... 23 24 |
|
||||
// | | kk | 01 02 ... 23 24 |
|
||||
// | Minute | m | 0 1 ... 58 59 |
|
||||
// | | mm | 00 01 ... 58 59 |
|
||||
// | Second | s | 0 1 ... 58 59 |
|
||||
// | | ss | 00 01 ... 58 59 |
|
||||
// | Offset | Z | -7 -6 ... +5 +6 |
|
||||
// | | ZZ | -0700 -0600 ... +0500 +0600 |
|
||||
// | | ZZZ | -07:00 -06:00 ... +05:00 +06:00 |
|
||||
pub fn (t Time) custom_format(s string) string {
|
||||
mut tokens := []string{}
|
||||
for i := 0; i < s.len; {
|
||||
for j := 4; j > 0; j-- {
|
||||
if i > s.len - j {
|
||||
continue
|
||||
}
|
||||
if j == 1 || (j == 2 && s[i..i + j] in time.tokens_2)
|
||||
|| (j == 3 && s[i..i + j] in time.tokens_3)
|
||||
|| (j == 4 && s[i..i + j] in time.tokens_4) {
|
||||
tokens << s[i..i + j]
|
||||
i += (j - 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
mut sb := strings.new_builder(128)
|
||||
|
||||
for token in tokens {
|
||||
match token {
|
||||
'M' {
|
||||
sb.write_string(t.month.str())
|
||||
}
|
||||
'MM' {
|
||||
sb.write_string('${t.month:02}')
|
||||
}
|
||||
'Mo' {
|
||||
sb.write_string(ordinal_suffix(t.month))
|
||||
}
|
||||
'MMM' {
|
||||
sb.write_string(long_months[t.month - 1][0..3])
|
||||
}
|
||||
'MMMM' {
|
||||
sb.write_string(long_months[t.month - 1])
|
||||
}
|
||||
'D' {
|
||||
sb.write_string(t.day.str())
|
||||
}
|
||||
'DD' {
|
||||
sb.write_string('${t.day:02}')
|
||||
}
|
||||
'Do' {
|
||||
sb.write_string(ordinal_suffix(t.day))
|
||||
}
|
||||
'DDD' {
|
||||
sb.write_string((t.day + days_before[t.month - 1] + int(is_leap_year(t.year))).str())
|
||||
}
|
||||
'DDDD' {
|
||||
sb.write_string('${t.day + days_before[t.month - 1] + int(is_leap_year(t.year)):03}')
|
||||
}
|
||||
'DDDo' {
|
||||
sb.write_string(ordinal_suffix(t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))))
|
||||
}
|
||||
'd' {
|
||||
sb.write_string(t.day_of_week().str())
|
||||
}
|
||||
'dd' {
|
||||
sb.write_string(long_days[t.day_of_week() - 1][0..2])
|
||||
}
|
||||
'ddd' {
|
||||
sb.write_string(long_days[t.day_of_week() - 1][0..3])
|
||||
}
|
||||
'dddd' {
|
||||
sb.write_string(long_days[t.day_of_week() - 1])
|
||||
}
|
||||
'YY' {
|
||||
sb.write_string(t.year.str()[2..4])
|
||||
}
|
||||
'YYYY' {
|
||||
sb.write_string(t.year.str())
|
||||
}
|
||||
'H' {
|
||||
sb.write_string(t.hour.str())
|
||||
}
|
||||
'HH' {
|
||||
sb.write_string('${t.hour:02}')
|
||||
}
|
||||
'h' {
|
||||
sb.write_string((t.hour % 12).str())
|
||||
}
|
||||
'hh' {
|
||||
sb.write_string('${(t.hour % 12):02}')
|
||||
}
|
||||
'm' {
|
||||
sb.write_string(t.minute.str())
|
||||
}
|
||||
'mm' {
|
||||
sb.write_string('${t.minute:02}')
|
||||
}
|
||||
's' {
|
||||
sb.write_string(t.second.str())
|
||||
}
|
||||
'ss' {
|
||||
sb.write_string('${t.second:02}')
|
||||
}
|
||||
'k' {
|
||||
sb.write_string((t.hour + 1).str())
|
||||
}
|
||||
'kk' {
|
||||
sb.write_string('${(t.hour + 1):02}')
|
||||
}
|
||||
'w' {
|
||||
sb.write_string('${math.ceil((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] +
|
||||
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] +
|
||||
int(is_leap_year(t.year))) / 7))))
|
||||
}
|
||||
'Q' {
|
||||
sb.write_string('${(t.month % 4) + 1}')
|
||||
}
|
||||
'QQ' {
|
||||
sb.write_string('${(t.month % 4) + 1:02}')
|
||||
}
|
||||
'Qo' {
|
||||
sb.write_string(ordinal_suffix((t.month % 4) + 1))
|
||||
}
|
||||
'c' {
|
||||
sb.write_string('${t.day_of_week() + 1}')
|
||||
}
|
||||
'N' {
|
||||
// TODO integrate BC
|
||||
sb.write_string('AD')
|
||||
}
|
||||
'NN' {
|
||||
// TODO integrate Before Christ
|
||||
sb.write_string('Anno Domini')
|
||||
}
|
||||
'Z' {
|
||||
mut hours := offset() / seconds_per_hour
|
||||
if hours >= 0 {
|
||||
sb.write_string('+$hours')
|
||||
} else {
|
||||
hours = -hours
|
||||
sb.write_string('-$hours')
|
||||
}
|
||||
}
|
||||
'ZZ' {
|
||||
// TODO update if minute differs?
|
||||
mut hours := offset() / seconds_per_hour
|
||||
if hours >= 0 {
|
||||
sb.write_string('+${hours:02}00')
|
||||
} else {
|
||||
hours = -hours
|
||||
sb.write_string('-${hours:02}00')
|
||||
}
|
||||
}
|
||||
'ZZZ' {
|
||||
// TODO update if minute differs?
|
||||
mut hours := offset() / seconds_per_hour
|
||||
if hours >= 0 {
|
||||
sb.write_string('+${hours:02}:00')
|
||||
} else {
|
||||
hours = -hours
|
||||
sb.write_string('-${hours:02}:00')
|
||||
}
|
||||
}
|
||||
'a' {
|
||||
if t.hour > 12 {
|
||||
sb.write_string('pm')
|
||||
} else {
|
||||
sb.write_string('am')
|
||||
}
|
||||
}
|
||||
'A' {
|
||||
if t.hour > 12 {
|
||||
sb.write_string('PM')
|
||||
} else {
|
||||
sb.write_string('AM')
|
||||
}
|
||||
}
|
||||
else {
|
||||
sb.write_string(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.str()
|
||||
}
|
||||
|
||||
// clean returns a date string in a following format:
|
||||
// - a date string in "HH:MM" format (24h) for current day
|
||||
// - a date string in "MMM D HH:MM" format (24h) for date of current year
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ module time
|
|||
|
||||
pub const (
|
||||
days_string = 'MonTueWedThuFriSatSun'
|
||||
long_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
|
||||
'Sunday']
|
||||
month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
months_string = 'JanFebMarAprMayJunJulAugSepOctNovDec'
|
||||
long_months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
|
||||
'September', 'October', 'November', 'December']
|
||||
// The unsigned zero year for internal calculations.
|
||||
// Must be 1 mod 400, and times before it will not compute correctly,
|
||||
// but otherwise can be changed at will.
|
||||
|
|
@ -30,8 +34,6 @@ pub const (
|
|||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
|
||||
]
|
||||
long_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
|
||||
'Sunday']
|
||||
)
|
||||
|
||||
// Time contains various time units for a point in time.
|
||||
|
|
@ -83,7 +85,7 @@ pub enum FormatDelimiter {
|
|||
no_delimiter
|
||||
}
|
||||
|
||||
// smonth returns month name.
|
||||
// smonth returns month name abbreviation.
|
||||
pub fn (t Time) smonth() string {
|
||||
if t.month <= 0 || t.month > 12 {
|
||||
return '---'
|
||||
|
|
@ -224,10 +226,10 @@ pub fn (t Time) day_of_week() int {
|
|||
return day_of_week(t.year, t.month, t.day)
|
||||
}
|
||||
|
||||
// weekday_str returns the current day as a string.
|
||||
// weekday_str returns the current day as a string abbreviation.
|
||||
pub fn (t Time) weekday_str() string {
|
||||
i := t.day_of_week() - 1
|
||||
return time.days_string[i * 3..(i + 1) * 3]
|
||||
return time.long_days[i][0..3]
|
||||
}
|
||||
|
||||
// weekday_str returns the current day as a string.
|
||||
|
|
|
|||
|
|
@ -520,6 +520,7 @@ pub:
|
|||
attrs []Attr
|
||||
ctdefine_idx int = -1 // the index in fn.attrs of `[if xyz]`, when such attribute exists
|
||||
pub mut:
|
||||
idx int // index in an external container; can be used to refer to the function in a more efficient way, just by its integer index
|
||||
params []Param
|
||||
stmts []Stmt
|
||||
defer_stmts []DeferStmt
|
||||
|
|
@ -707,6 +708,7 @@ pub:
|
|||
is_generated bool // true for `[generated] module xyz` files; turn off notices
|
||||
is_translated bool // true for `[translated] module xyz` files; turn off some checks
|
||||
pub mut:
|
||||
idx int // index in an external container; can be used to refer to the file in a more efficient way, just by its integer index
|
||||
path string // absolute path of the source file - '/projects/v/file.v'
|
||||
path_base string // file name - 'file.v' (useful for tracing)
|
||||
scope &Scope
|
||||
|
|
@ -2075,6 +2077,17 @@ pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut lx IndexExpr) recursive_arraymap_set_is_setter() {
|
||||
lx.is_setter = true
|
||||
if mut lx.left is IndexExpr {
|
||||
lx.left.recursive_arraymap_set_is_setter()
|
||||
} else if mut lx.left is SelectorExpr {
|
||||
if mut lx.left.expr is IndexExpr {
|
||||
lx.left.expr.recursive_arraymap_set_is_setter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return all the registers for the given architecture
|
||||
pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject {
|
||||
mut res := map[string]ScopeObject{}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ pub mut:
|
|||
mdeprecated_msg map[string]string // module deprecation message
|
||||
mdeprecated_after map[string]time.Time // module deprecation date
|
||||
builtin_pub_fns map[string]bool
|
||||
pointer_size int
|
||||
}
|
||||
|
||||
// used by vls to avoid leaks
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import v.builder
|
||||
import v.parser
|
||||
import v.pref
|
||||
|
||||
struct T01 {
|
||||
a int
|
||||
b byte
|
||||
c int
|
||||
}
|
||||
|
||||
type T02 = string
|
||||
type T03 = int | string
|
||||
type T04 = []T03
|
||||
type T05 = [47]T03
|
||||
|
||||
interface T06 {
|
||||
a int
|
||||
}
|
||||
|
||||
interface T07 {
|
||||
T06
|
||||
b int
|
||||
}
|
||||
|
||||
struct T08 {
|
||||
T01
|
||||
x string
|
||||
}
|
||||
|
||||
fn test_type_size() ? {
|
||||
mut pref := pref.new_preferences()
|
||||
$if x64 {
|
||||
pref.m64 = true
|
||||
}
|
||||
mut b := builder.new_builder(pref)
|
||||
mut files := b.get_builtin_files()
|
||||
b.set_module_lookup_paths()
|
||||
parser.parse_files(files, b.table, b.pref)
|
||||
b.parse_imports()
|
||||
parser.parse_file(@FILE, b.table, .parse_comments, b.pref)
|
||||
|
||||
mut t := b.table
|
||||
|
||||
assert sizeof(T01) == t.type_size(t.type_idxs['main.T01'] ?)
|
||||
assert sizeof(T02) == t.type_size(t.type_idxs['main.T02'] ?)
|
||||
assert sizeof(T03) == t.type_size(t.type_idxs['main.T03'] ?)
|
||||
assert sizeof(T04) == t.type_size(t.type_idxs['main.T04'] ?)
|
||||
assert sizeof(T05) == t.type_size(t.type_idxs['main.T05'] ?)
|
||||
assert sizeof(T06) == t.type_size(t.type_idxs['main.T06'] ?)
|
||||
assert sizeof(T07) == t.type_size(t.type_idxs['main.T07'] ?)
|
||||
assert sizeof(T08) == t.type_size(t.type_idxs['main.T08'] ?)
|
||||
|
||||
println('done')
|
||||
}
|
||||
|
|
@ -823,6 +823,97 @@ pub fn (t &TypeSymbol) is_builtin() bool {
|
|||
return t.mod == 'builtin'
|
||||
}
|
||||
|
||||
// type_size returns the size in bytes of `typ`, similarly to C's `sizeof()`.
|
||||
pub fn (t &Table) type_size(typ Type) int {
|
||||
if typ.has_flag(.optional) {
|
||||
return t.type_size(ast.error_type_idx)
|
||||
}
|
||||
if typ.nr_muls() > 0 {
|
||||
return t.pointer_size
|
||||
}
|
||||
sym := t.sym(typ)
|
||||
match sym.kind {
|
||||
.placeholder, .void, .none_ {
|
||||
return 0
|
||||
}
|
||||
.voidptr, .byteptr, .charptr, .function, .usize, .isize, .any, .thread, .chan {
|
||||
return t.pointer_size
|
||||
}
|
||||
.i8, .u8, .char, .bool {
|
||||
return 1
|
||||
}
|
||||
.i16, .u16 {
|
||||
return 2
|
||||
}
|
||||
.int, .u32, .rune, .f32, .enum_ {
|
||||
return 4
|
||||
}
|
||||
.i64, .u64, .int_literal, .f64, .float_literal {
|
||||
return 8
|
||||
}
|
||||
.alias {
|
||||
return t.type_size((sym.info as Alias).parent_type)
|
||||
}
|
||||
.struct_, .string, .multi_return {
|
||||
mut max_alignment := 0
|
||||
mut total_size := 0
|
||||
types := if sym.info is Struct {
|
||||
sym.info.fields.map(it.typ)
|
||||
} else {
|
||||
(sym.info as MultiReturn).types
|
||||
}
|
||||
for ftyp in types {
|
||||
field_size := t.type_size(ftyp)
|
||||
alignment := if field_size > t.pointer_size { t.pointer_size } else { field_size }
|
||||
if alignment > max_alignment {
|
||||
max_alignment = alignment
|
||||
}
|
||||
total_size = round_up(total_size, alignment) + field_size
|
||||
}
|
||||
return round_up(total_size, max_alignment)
|
||||
}
|
||||
.sum_type, .interface_, .aggregate {
|
||||
match sym.info {
|
||||
SumType, Aggregate {
|
||||
return (sym.info.fields.len + 2) * t.pointer_size
|
||||
}
|
||||
Interface {
|
||||
mut res := (sym.info.fields.len + 2) * t.pointer_size
|
||||
for etyp in sym.info.embeds {
|
||||
res += t.type_size(etyp) - 2 * t.pointer_size
|
||||
}
|
||||
return res
|
||||
}
|
||||
else {
|
||||
// unreachable
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
.array_fixed {
|
||||
info := sym.info as ArrayFixed
|
||||
return info.size * t.type_size(info.elem_type)
|
||||
}
|
||||
// TODO hardcoded:
|
||||
.map {
|
||||
return if t.pointer_size == 8 { 120 } else { 80 }
|
||||
}
|
||||
.array {
|
||||
return if t.pointer_size == 8 { 32 } else { 24 }
|
||||
}
|
||||
.generic_inst {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// round_up rounds the number `n` up to the next multiple `multiple`.
|
||||
// Note: `multiple` must be a power of 2.
|
||||
[inline]
|
||||
fn round_up(n int, multiple int) int {
|
||||
return (n + multiple - 1) & -multiple
|
||||
}
|
||||
|
||||
// for debugging/errors only, perf is not an issue
|
||||
pub fn (k Kind) str() string {
|
||||
return match k {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ pub fn new_builder(pref &pref.Preferences) Builder {
|
|||
if pref.use_color == .never {
|
||||
util.emanager.set_support_color(false)
|
||||
}
|
||||
table.pointer_size = if pref.m64 { 8 } else { 4 }
|
||||
msvc := find_msvc(pref.m64) or {
|
||||
if pref.ccompiler == 'msvc' {
|
||||
// verror('Cannot find MSVC on this OS')
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ pub fn interpret_v(mut b builder.Builder) {
|
|||
|
||||
util.timing_start('INTERPRET')
|
||||
mut e := eval.new_eval(b.table, b.pref)
|
||||
e.eval(b.parsed_files)
|
||||
e.eval(mut b.parsed_files)
|
||||
util.timing_measure('INTERPRET')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -709,38 +709,3 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr
|
|||
c.need_recheck_generic_fns = true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) sizeof_integer(a ast.Type) int {
|
||||
t := if a in ast.unsigned_integer_type_idxs { a.flip_signedness() } else { a }
|
||||
r := match t {
|
||||
ast.char_type_idx, ast.i8_type_idx {
|
||||
1
|
||||
}
|
||||
ast.i16_type_idx {
|
||||
2
|
||||
}
|
||||
ast.int_type_idx {
|
||||
4
|
||||
}
|
||||
ast.rune_type_idx {
|
||||
4
|
||||
}
|
||||
ast.i64_type_idx {
|
||||
8
|
||||
}
|
||||
ast.isize_type_idx {
|
||||
if c.pref.m64 { 8 } else { 4 }
|
||||
}
|
||||
ast.int_literal_type {
|
||||
s := c.table.type_to_str(a)
|
||||
panic('`$s` has unknown size')
|
||||
0
|
||||
}
|
||||
else {
|
||||
s := c.table.type_to_str(a)
|
||||
panic('`$s` is not an integer')
|
||||
0
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,8 +643,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
} else if is_left_type_signed != is_right_type_signed
|
||||
&& left_type != ast.int_literal_type_idx
|
||||
&& right_type != ast.int_literal_type_idx {
|
||||
ls := c.sizeof_integer(left_type)
|
||||
rs := c.sizeof_integer(right_type)
|
||||
ls := c.table.type_size(left_type)
|
||||
rs := c.table.type_size(right_type)
|
||||
// prevent e.g. `u32 == i16` but not `u16 == i32` as max_u16 fits in i32
|
||||
// TODO u32 == i32, change < to <=
|
||||
if (is_left_type_signed && ls < rs) || (is_right_type_signed && rs < ls) {
|
||||
|
|
@ -702,13 +702,11 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
&& c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive() {
|
||||
left_sym = c.table.sym((left_sym.info as ast.Alias).parent_type)
|
||||
}
|
||||
|
||||
if c.pref.translated && node.op in [.plus, .minus, .mul]
|
||||
&& left_type.is_any_kind_of_pointer()
|
||||
&& (right_type.is_any_kind_of_pointer() || right_type.is_int()) {
|
||||
&& left_type.is_any_kind_of_pointer() && right_type.is_any_kind_of_pointer() {
|
||||
return_type = left_type
|
||||
}
|
||||
// Check if the alias type is not a primitive then allow using operator overloading for aliased `arrays` and `maps`
|
||||
else if !c.pref.translated && left_sym.kind == .alias && left_sym.info is ast.Alias
|
||||
} else if !c.pref.translated && left_sym.kind == .alias && left_sym.info is ast.Alias
|
||||
&& !(c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive()) {
|
||||
if left_sym.has_method(node.op.str()) {
|
||||
if method := left_sym.find_method(node.op.str()) {
|
||||
|
|
@ -745,7 +743,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
if left_sym.kind in [.array, .array_fixed, .map, .struct_] {
|
||||
|
||||
if !c.pref.translated && left_sym.kind in [.array, .array_fixed, .map, .struct_] {
|
||||
if left_sym.has_method_with_generic_parent(node.op.str()) {
|
||||
if method := left_sym.find_method_with_generic_parent(node.op.str()) {
|
||||
return_type = method.return_type
|
||||
|
|
@ -762,7 +761,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
c.error('mismatched types `$left_name` and `$right_name`', left_right_pos)
|
||||
}
|
||||
}
|
||||
} else if right_sym.kind in [.array, .array_fixed, .map, .struct_] {
|
||||
} else if !c.pref.translated && right_sym.kind in [.array, .array_fixed, .map, .struct_] {
|
||||
if right_sym.has_method_with_generic_parent(node.op.str()) {
|
||||
if method := right_sym.find_method_with_generic_parent(node.op.str()) {
|
||||
return_type = method.return_type
|
||||
|
|
@ -935,13 +934,13 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
return ast.void_type
|
||||
} else if left_value_sym.kind == .sum_type {
|
||||
if right_final.kind != .array {
|
||||
if !c.table.is_sumtype_or_in_variant(left_value_type, right_type) {
|
||||
if !c.table.is_sumtype_or_in_variant(left_value_type, ast.mktyp(right_type)) {
|
||||
c.error('cannot append `$right_sym.name` to `$left_sym.name`',
|
||||
right_pos)
|
||||
}
|
||||
} else {
|
||||
right_value_type := c.table.value_type(right_type)
|
||||
if !c.table.is_sumtype_or_in_variant(left_value_type, right_value_type) {
|
||||
if !c.table.is_sumtype_or_in_variant(left_value_type, ast.mktyp(right_value_type)) {
|
||||
c.error('cannot append `$right_sym.name` to `$left_sym.name`',
|
||||
right_pos)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,30 +127,7 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp
|
|||
// return expr.val.i64()
|
||||
// }
|
||||
ast.SizeOf {
|
||||
xtype := expr.typ
|
||||
if xtype.is_real_pointer() {
|
||||
if c.pref.m64 {
|
||||
return 8 // 64bit platform
|
||||
}
|
||||
return 4 // 32bit platform
|
||||
}
|
||||
if int(xtype) == xtype.idx() {
|
||||
match xtype {
|
||||
ast.char_type { return 1 }
|
||||
ast.i8_type { return 1 }
|
||||
ast.i16_type { return 2 }
|
||||
ast.int_type { return 4 }
|
||||
ast.i64_type { return 8 }
|
||||
//
|
||||
ast.byte_type { return 1 }
|
||||
// ast.u8_type { return 1 }
|
||||
ast.u16_type { return 2 }
|
||||
ast.u32_type { return 4 }
|
||||
ast.u64_type { return 8 }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
return none
|
||||
return c.table.type_size(expr.typ)
|
||||
}
|
||||
ast.FloatLiteral {
|
||||
x := expr.val.f64()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,16 @@ fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
|
|||
}
|
||||
c.expr(node.cond)
|
||||
if node.has_inc {
|
||||
if node.inc is ast.AssignStmt {
|
||||
for right in node.inc.right {
|
||||
if right is ast.CallExpr {
|
||||
if right.or_block.stmts.len > 0 {
|
||||
c.error('optionals are not allowed in `for statement increment` (yet)',
|
||||
right.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c.stmt(node.inc)
|
||||
}
|
||||
c.check_loop_label(node.label, node.pos)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/for_c_stmt_with_optional_call.vv:15:31: error: optionals are not allowed in `for statement increment` (yet)
|
||||
13 | for t := 0; t < tests; t++ {
|
||||
14 | mut v := []bool{len: nmax, init: false}
|
||||
15 | for x := 0; !v[x]; x = rand.intn(n) or { 0 } {
|
||||
| ~~~~~~~
|
||||
16 | v[x] = true
|
||||
17 | sum++
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import rand
|
||||
import math { abs }
|
||||
|
||||
const nmax = 20
|
||||
|
||||
fn ana(n int) f64 {
|
||||
return 1.0 // haven't started
|
||||
}
|
||||
|
||||
fn avg(n int) f64 {
|
||||
tests := 1e4
|
||||
mut sum := 0
|
||||
for t := 0; t < tests; t++ {
|
||||
mut v := []bool{len: nmax, init: false}
|
||||
for x := 0; !v[x]; x = rand.intn(n) or { 0 } {
|
||||
v[x] = true
|
||||
sum++
|
||||
}
|
||||
}
|
||||
return f64(sum) / tests
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println(' N average analytical (error)')
|
||||
println('=== ========= ============ =========')
|
||||
for n in 1 .. nmax + 1 {
|
||||
a := avg(n)
|
||||
b := ana(n)
|
||||
println('${n:3} ${a:9.4f} ${b:12.4f} (${(abs(a - b) / b * 100):6.2f}%)')
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/interface_method_name_err.vv:2:2: error: method name `Fizz` cannot contain uppercase letters, use snake_case instead
|
||||
1 | interface Foo {
|
||||
2 | Fizz()
|
||||
| ~~~~~~
|
||||
3 | }
|
||||
4 |
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
interface Foo {
|
||||
Fizz()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
@ -1,13 +1,20 @@
|
|||
vlib/v/checker/tests/struct_field_name_err.vv:2:2: error: field name `Architecture` cannot contain uppercase letters, use snake_case instead
|
||||
vlib/v/checker/tests/struct_field_name_err.vv:2:2: error: field name `Foo` cannot contain uppercase letters, use snake_case instead
|
||||
1 | struct Release {
|
||||
2 | Architecture []string
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
3 | Components []string
|
||||
4 | }
|
||||
vlib/v/checker/tests/struct_field_name_err.vv:3:2: error: field name `Components` cannot contain uppercase letters, use snake_case instead
|
||||
2 | Foo string
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
3 | Bar &int
|
||||
4 | Architecture []string
|
||||
vlib/v/checker/tests/struct_field_name_err.vv:3:2: error: field name `Bar` cannot contain uppercase letters, use snake_case instead
|
||||
1 | struct Release {
|
||||
2 | Architecture []string
|
||||
3 | Components []string
|
||||
2 | Foo string
|
||||
3 | Bar &int
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
4 | Architecture []string
|
||||
5 | }
|
||||
vlib/v/checker/tests/struct_field_name_err.vv:4:2: error: field name `Architecture` cannot contain uppercase letters, use snake_case instead
|
||||
2 | Foo string
|
||||
3 | Bar &int
|
||||
4 | Architecture []string
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
4 | }
|
||||
5 |
|
||||
5 | }
|
||||
6 |
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
struct Release {
|
||||
Foo string
|
||||
Bar &int
|
||||
Architecture []string
|
||||
Components []string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
r := Release{}
|
||||
println(r)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,28 +30,37 @@ pub mut:
|
|||
return_values []Object
|
||||
cur_mod string
|
||||
cur_file string
|
||||
back_trace []string
|
||||
//
|
||||
trace_file_paths []string
|
||||
trace_function_names []string
|
||||
back_trace []EvalTrace
|
||||
}
|
||||
|
||||
pub fn (mut e Eval) eval(files []&ast.File) {
|
||||
e.register_symbols(files)
|
||||
pub struct EvalTrace {
|
||||
fn_idx int
|
||||
file_idx int
|
||||
line int
|
||||
}
|
||||
|
||||
pub fn (mut e Eval) eval(mut files []&ast.File) {
|
||||
e.register_symbols(mut files)
|
||||
// println(files.map(it.path_base))
|
||||
e.run_func(e.mods['main']['main'] or { ast.EmptyStmt{} } as ast.FnDecl)
|
||||
}
|
||||
|
||||
// first arg is reciever (if method)
|
||||
pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) {
|
||||
e.back_trace << func.name
|
||||
e.back_trace << EvalTrace{func.idx, func.source_file.idx, func.pos.line_nr}
|
||||
old_mod := e.cur_mod
|
||||
e.cur_mod = func.mod
|
||||
|
||||
old_file := e.cur_file
|
||||
e.cur_mod = func.mod
|
||||
e.cur_file = func.file
|
||||
defer {
|
||||
e.cur_mod = old_mod
|
||||
e.cur_file = old_file
|
||||
e.back_trace.pop()
|
||||
}
|
||||
//
|
||||
mut args := _args.clone()
|
||||
if func.params.len != args.len && !func.is_variadic {
|
||||
e.error('mismatched parameter length for $func.name: got `$args.len`, expected `$func.params.len`')
|
||||
|
|
@ -90,7 +99,7 @@ pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) {
|
|||
}
|
||||
if func.is_method {
|
||||
print(e.back_trace)
|
||||
println(func.receiver.typ - 65536)
|
||||
println(func.receiver.typ.set_nr_muls(0))
|
||||
e.local_vars[func.receiver.name] = Var{
|
||||
val: args[0]
|
||||
scope_idx: e.scope_idx
|
||||
|
|
@ -104,13 +113,18 @@ pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut e Eval) register_symbols(files []&ast.File) {
|
||||
for file in files {
|
||||
// eprintln('registering file: $file.path_base')
|
||||
pub fn (mut e Eval) register_symbols(mut files []&ast.File) {
|
||||
for mut file in files {
|
||||
file.idx = e.trace_file_paths.len
|
||||
e.trace_file_paths << file.path
|
||||
mod := file.mod.name
|
||||
e.register_symbol_stmts(file.stmts[1..], mod, file.path)
|
||||
|
||||
// eprintln('registered file: $file.path_base')
|
||||
for mut stmt in file.stmts {
|
||||
if mut stmt is ast.FnDecl {
|
||||
stmt.idx = e.trace_function_names.len
|
||||
e.trace_function_names << stmt.name
|
||||
}
|
||||
}
|
||||
e.register_symbol_stmts(file.stmts, mod, file.path)
|
||||
}
|
||||
for mod, const_files in e.future_register_consts {
|
||||
e.cur_mod = mod
|
||||
|
|
@ -133,14 +147,16 @@ pub fn (mut e Eval) register_symbols(files []&ast.File) {
|
|||
}
|
||||
|
||||
pub fn (mut e Eval) register_symbol_stmts(stmts []ast.Stmt, mod string, file string) {
|
||||
for stmt in stmts { // first is just module declaration, so ignore
|
||||
for stmt in stmts {
|
||||
e.register_symbol(stmt, mod, file)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) {
|
||||
match stmt {
|
||||
ast.Module {}
|
||||
ast.Module {
|
||||
// ignore module declarations for now
|
||||
}
|
||||
ast.FnDecl {
|
||||
// this mess because c error
|
||||
x := ast.Stmt(stmt)
|
||||
|
|
@ -188,7 +204,7 @@ pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
eprintln('unsupported expression')
|
||||
e.error('unsupported expression')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -205,5 +221,11 @@ pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) {
|
|||
}
|
||||
|
||||
fn (e Eval) error(msg string) {
|
||||
eprintln('> V interpeter backtrace:')
|
||||
for t in e.back_trace {
|
||||
file_path := e.trace_file_paths[t.file_idx] or { t.file_idx.str() }
|
||||
fn_name := e.trace_function_names[t.fn_idx] or { t.fn_idx.str() }
|
||||
eprintln(' $file_path:${t.line + 1}:$fn_name}')
|
||||
}
|
||||
util.verror('interpreter', msg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module eval
|
||||
|
||||
import v.pref
|
||||
import v.ast
|
||||
import v.util
|
||||
import math
|
||||
|
|
@ -24,13 +25,21 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
|
|||
e.error('c does not have methods')
|
||||
}
|
||||
match expr.name.all_after('C.') {
|
||||
'read' {
|
||||
return Int{C.read(args[0].int_val(), args[1] as voidptr, args[2].int_val()), 64}
|
||||
}
|
||||
'write' {
|
||||
return Int{C.write(args[0].int_val(), args[1] as voidptr,
|
||||
args[2].int_val()), 32}
|
||||
args[2].int_val()), 64}
|
||||
}
|
||||
'malloc' {
|
||||
return Ptr{
|
||||
val: unsafe { C.malloc(args[0].int_val()) }
|
||||
}
|
||||
}
|
||||
'calloc' {
|
||||
return Ptr{
|
||||
val: vcalloc(int(args[0].int_val() * args[1].int_val()))
|
||||
val: unsafe { C.calloc(args[0].int_val(), args[1].int_val()) }
|
||||
}
|
||||
}
|
||||
'getcwd' {
|
||||
|
|
@ -126,27 +135,16 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
|
|||
do_if = true
|
||||
} else {
|
||||
if branch.cond is ast.Ident {
|
||||
match branch.cond.name {
|
||||
'windows' {
|
||||
do_if = e.pref.os == .windows
|
||||
}
|
||||
'macos' {
|
||||
do_if = e.pref.os == .macos
|
||||
}
|
||||
'linux' {
|
||||
do_if = e.pref.os == .linux
|
||||
}
|
||||
'android' {
|
||||
do_if = e.pref.os == .android
|
||||
}
|
||||
'freebsd' {
|
||||
do_if = e.pref.os == .freebsd
|
||||
}
|
||||
'prealloc' {
|
||||
do_if = e.pref.prealloc
|
||||
}
|
||||
else {
|
||||
e.error('unknown compile time if: $branch.cond.name')
|
||||
if known_os := pref.os_from_string(branch.cond.name) {
|
||||
do_if = e.pref.os == known_os
|
||||
} else {
|
||||
match branch.cond.name {
|
||||
'prealloc' {
|
||||
do_if = e.pref.prealloc
|
||||
}
|
||||
else {
|
||||
e.error('unknown compile time if: $branch.cond.name')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if branch.cond is ast.PostfixExpr {
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) {
|
|||
g.write(' = ${styp}_${util.replace_op(extracted_op)}(')
|
||||
method := g.table.find_method(left_sym, extracted_op) or {
|
||||
// the checker will most likely have found this, already...
|
||||
g.error('assignemnt operator `$extracted_op=` used but no `$extracted_op` method defined',
|
||||
g.error('assignment operator `$extracted_op=` used but no `$extracted_op` method defined',
|
||||
node.pos)
|
||||
ast.Fn{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@ import v.depgraph
|
|||
import sync.pool
|
||||
|
||||
const (
|
||||
// Note: some of the words in c_reserved, are not reserved in C,
|
||||
// but are in C++, or have special meaning in V, thus need escaping too.
|
||||
// `small` should not be needed, but see: https://stackoverflow.com/questions/5874215/what-is-rpcndr-h
|
||||
// Note: some of the words in c_reserved, are not reserved in C, but are
|
||||
// in C++, or have special meaning in V, thus need escaping too. `small`
|
||||
// should not be needed, but see:
|
||||
// https://stackoverflow.com/questions/5874215/what-is-rpcndr-h
|
||||
c_reserved = ['array', 'auto', 'bool', 'break', 'calloc', 'case', 'char', 'class', 'complex',
|
||||
'const', 'continue', 'default', 'delete', 'do', 'double', 'else', 'enum', 'error', 'exit',
|
||||
'export', 'extern', 'false', 'float', 'for', 'free', 'goto', 'if', 'inline', 'int', 'link',
|
||||
|
|
@ -1590,10 +1591,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
if !g.skip_stmt_pos {
|
||||
g.set_current_pos_as_last_stmt_pos()
|
||||
}
|
||||
defer {
|
||||
}
|
||||
// println('g.stmt()')
|
||||
// g.writeln('//// stmt start')
|
||||
match node {
|
||||
ast.EmptyStmt {}
|
||||
ast.AsmStmt {
|
||||
|
|
@ -3146,7 +3143,7 @@ fn (mut g Gen) char_literal(node ast.CharLiteral) {
|
|||
return
|
||||
}
|
||||
// TODO: optimize use L-char instead of u32 when possible
|
||||
if utf8_str_len(node.val) < node.val.len {
|
||||
if node.val.len_utf8() < node.val.len {
|
||||
g.write('((rune)0x$node.val.utf32_code().hex() /* `$node.val` */)')
|
||||
return
|
||||
}
|
||||
|
|
@ -3267,8 +3264,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
|||
info := sym.info as ast.ArrayFixed
|
||||
g.write('$info.size')
|
||||
return
|
||||
}
|
||||
if sym.kind == .chan && (node.field_name == 'len' || node.field_name == 'closed') {
|
||||
} else if sym.kind == .chan && (node.field_name == 'len' || node.field_name == 'closed') {
|
||||
g.write('sync__Channel_${node.field_name}(')
|
||||
g.expr(node.expr)
|
||||
g.write(')')
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ const c_common_macros = '
|
|||
#endif
|
||||
|
||||
#ifdef __TINYC__
|
||||
#define _Atomic volatile
|
||||
#undef EMPTY_STRUCT_DECLARATION
|
||||
#define EMPTY_STRUCT_DECLARATION voidptr _dummy_pad
|
||||
#undef EMPTY_ARRAY_OF_ELEMS
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
|
|||
}
|
||||
info := var.obj as ast.Var
|
||||
if g.table.sym(info.typ).kind != .function {
|
||||
g.writeln('${g.typ(info.typ)}$deref $var.name;')
|
||||
g.writeln('${g.typ(info.typ)}$deref ${c_name(var.name)};')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1777,7 +1777,14 @@ fn (mut g Gen) go_expr(node ast.GoExpr) {
|
|||
}
|
||||
} else {
|
||||
g.writeln('pthread_t thread_$tmp;')
|
||||
g.writeln('int ${tmp}_thr_res = pthread_create(&thread_$tmp, NULL, (void*)$wrapper_fn_name, $arg_tmp_var);')
|
||||
mut sthread_attributes := 'NULL'
|
||||
if g.pref.os != .vinix {
|
||||
g.writeln('pthread_attr_t thread_${tmp}_attributes;')
|
||||
g.writeln('pthread_attr_init(&thread_${tmp}_attributes);')
|
||||
g.writeln('pthread_attr_setstacksize(&thread_${tmp}_attributes, $g.pref.thread_stack_size);')
|
||||
sthread_attributes = '&thread_${tmp}_attributes'
|
||||
}
|
||||
g.writeln('int ${tmp}_thr_res = pthread_create(&thread_$tmp, $sthread_attributes, (void*)$wrapper_fn_name, $arg_tmp_var);')
|
||||
g.writeln('if (${tmp}_thr_res) panic_error_number(tos3("`go ${name}()`: "), ${tmp}_thr_res);')
|
||||
if !node.is_expr {
|
||||
g.writeln('pthread_detach(thread_$tmp);')
|
||||
|
|
@ -1915,6 +1922,13 @@ fn (mut g Gen) go_expr(node ast.GoExpr) {
|
|||
g.gowrappers.write_string(call_args_str)
|
||||
} else {
|
||||
for i in 0 .. expr.args.len {
|
||||
expected_nr_muls := expr.expected_arg_types[i].nr_muls()
|
||||
arg_nr_muls := expr.args[i].typ.nr_muls()
|
||||
if arg_nr_muls > expected_nr_muls {
|
||||
g.gowrappers.write_string('*'.repeat(arg_nr_muls - expected_nr_muls))
|
||||
} else if arg_nr_muls < expected_nr_muls {
|
||||
g.gowrappers.write_string('&'.repeat(expected_nr_muls - arg_nr_muls))
|
||||
}
|
||||
g.gowrappers.write_string('arg->arg${i + 1}')
|
||||
if i != expr.args.len - 1 {
|
||||
g.gowrappers.write_string(', ')
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
## Purpose: tests data for the output of V's C code generator
|
||||
|
||||
## TLDR: `v vlib/v/gen/c/coutput_test.v`
|
||||
## TLDR: `v run vlib/v/gen/c/coutput_test.v`
|
||||
|
||||
coutput_test.v is a *test runner*, that checks whether the generated C
|
||||
coutput_test.v is a *test runner*, that checks whether the generated C
|
||||
source code matches *all* expectations, specified in *.c.must_have files,
|
||||
in the folder vlib/v/gen/c/testdata/ .
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
int a = 5;
|
||||
int b = 7;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
5
|
||||
7
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
fn main() {
|
||||
a := 'Vlang'.len
|
||||
b := r'Vlang\n'.len
|
||||
println(a)
|
||||
println(b)
|
||||
}
|
||||
|
|
@ -423,7 +423,7 @@ pub fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_iden
|
|||
right := p.expr(precedence - 1)
|
||||
pos.update_last_line(p.prev_tok.line_nr)
|
||||
if mut node is ast.IndexExpr {
|
||||
node.recursive_mapset_is_setter(true)
|
||||
node.recursive_arraymap_set_is_setter()
|
||||
}
|
||||
node = ast.InfixExpr{
|
||||
left: node
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
is_field_volatile = true
|
||||
}
|
||||
is_embed := ((p.tok.lit.len > 1 && p.tok.lit[0].is_capital()
|
||||
&& (p.peek_tok.line_nr != p.tok.line_nr || p.peek_tok.kind !in [.name, .amp])
|
||||
&& (p.peek_tok.kind != .lsbr || p.peek_token(2).kind != .rsbr))
|
||||
|| p.peek_tok.kind == .dot) && language == .v && p.peek_tok.kind != .key_fn
|
||||
is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_global)
|
||||
|
|
@ -515,7 +516,8 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||
mut mut_pos := -1
|
||||
mut ifaces := []ast.InterfaceEmbedding{}
|
||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||
if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital() {
|
||||
if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
|
||||
&& p.peek_tok.kind != .lpar {
|
||||
iface_pos := p.tok.pos()
|
||||
mut iface_name := p.tok.lit
|
||||
iface_type := p.parse_type()
|
||||
|
|
@ -583,10 +585,6 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||
p.error_with_pos('duplicate method `$name`', method_start_pos)
|
||||
return ast.InterfaceDecl{}
|
||||
}
|
||||
if language == .v && util.contains_capital(name) {
|
||||
p.error('interface methods cannot contain uppercase letters, use snake_case instead')
|
||||
return ast.InterfaceDecl{}
|
||||
}
|
||||
// field_names << name
|
||||
args2, _, is_variadic := p.fn_args() // TODO merge ast.Param and ast.Arg to avoid this
|
||||
mut args := [
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ pub mut:
|
|||
nofloat bool // for low level code, like kernels: replaces f32 with u32 and f64 with u64
|
||||
// checker settings:
|
||||
checker_match_exhaustive_cutoff_limit int = 12
|
||||
thread_stack_size int = 8388608 // Change with `-thread-stack-size 4194304`. Note: on macos it was 524288, which is too small for more complex programs with many nested callexprs.
|
||||
}
|
||||
|
||||
pub fn parse_args(known_external_commands []string, args []string) (&Preferences, string) {
|
||||
|
|
@ -571,6 +572,10 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
|||
res.message_limit = cmdline.option(current_args, arg, '5').int()
|
||||
i++
|
||||
}
|
||||
'-thread-stack-size' {
|
||||
res.thread_stack_size = cmdline.option(current_args, arg, res.thread_stack_size.str()).int()
|
||||
i++
|
||||
}
|
||||
'-cc' {
|
||||
res.ccompiler = cmdline.option(current_args, '-cc', 'cc')
|
||||
res.build_options << '$arg "$res.ccompiler"'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
type Typ_var = f64 | int
|
||||
|
||||
fn test_array_of_sumtype_append_literal_type() {
|
||||
mut arr := []Typ_var{}
|
||||
|
||||
// literal int/float type error
|
||||
arr << 123
|
||||
arr << 1.23
|
||||
|
||||
// cast/wrap in type
|
||||
arr << int(123)
|
||||
arr << f64(1.23)
|
||||
arr << Typ_var(456)
|
||||
arr << Typ_var(4.56)
|
||||
|
||||
println(arr)
|
||||
|
||||
assert arr[0] == Typ_var(123)
|
||||
assert arr[1] == Typ_var(1.23)
|
||||
}
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
import term
|
||||
import os
|
||||
import runtime
|
||||
import time
|
||||
|
||||
struct App {
|
||||
|
|
@ -13,7 +10,7 @@ fn test_atomic() {
|
|||
for i in 0 .. 10 {
|
||||
go app.run()
|
||||
}
|
||||
time.sleep(2 * time.second)
|
||||
time.sleep(200 * time.millisecond)
|
||||
println('idx=$app.idx')
|
||||
assert app.idx == 10
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
fn test_complex_map_op1() {
|
||||
mut test_map := map[string]Point_map{}
|
||||
|
||||
test_map['test1'].points['point3'] << Point{10, 20}
|
||||
test_map['test2'].points['point4'] << Point{50, 60}
|
||||
|
||||
println(test_map)
|
||||
|
||||
assert test_map.len == 2
|
||||
assert Point{10, 20} in test_map['test1'].points['point3']
|
||||
assert Point{50, 60} in test_map['test2'].points['point4']
|
||||
assert Point{10, 20} !in test_map['test2'].points['point4']
|
||||
assert Point{1, 2} !in test_map['test1'].points['point3']
|
||||
}
|
||||
|
||||
fn test_complex_map_op2() {
|
||||
mut test_map := map[string]map[string][]Point{}
|
||||
|
||||
test_map['test1']['point3'] << Point{10, 20}
|
||||
test_map['test2']['point4'] << Point{50, 60}
|
||||
|
||||
println(test_map)
|
||||
|
||||
assert test_map.len == 2
|
||||
assert Point{10, 20} in test_map['test1']['point3']
|
||||
assert Point{50, 60} in test_map['test2']['point4']
|
||||
assert Point{10, 20} !in test_map['test2']['point4']
|
||||
assert Point{1, 2} !in test_map['test1']['point3']
|
||||
}
|
||||
|
||||
struct Point {
|
||||
mut:
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
struct Point_map {
|
||||
mut:
|
||||
points map[string][]Point
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
fn f(x u8) u8 {
|
||||
eprintln('> f: $x')
|
||||
if x == 0 {
|
||||
return 0
|
||||
}
|
||||
mut local := [131072]u8{}
|
||||
local[local.len - 1] = x + f(x - 1)
|
||||
return local[0] + local[local.len - 1]
|
||||
}
|
||||
|
||||
fn abc(depth u8) u8 {
|
||||
return f(depth)
|
||||
}
|
||||
|
||||
fn test_default_stack_depth() {
|
||||
$if tinyc && windows {
|
||||
exit(0) // skip for now testing on windows-tcc
|
||||
}
|
||||
// Note: 10 levels of recursing f, requires a little over 1.4MB,
|
||||
// and would have failed on macos, where the default thread size
|
||||
// is just 512KB, if V was not changed to have a default for
|
||||
// `-thread-stack-size` of 8MB.
|
||||
t := go abc(10)
|
||||
res := t.wait()
|
||||
assert res == 55
|
||||
}
|
||||
|
|
@ -154,3 +154,24 @@ fn num() int {
|
|||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
fn close(i int) {
|
||||
eprintln('Close $i')
|
||||
}
|
||||
|
||||
fn test_defer_with_reserved_words() {
|
||||
if 1 == 1 {
|
||||
single := 1
|
||||
defer {
|
||||
close(single)
|
||||
}
|
||||
}
|
||||
if 2 == 2 {
|
||||
double := 9
|
||||
defer {
|
||||
close(double)
|
||||
}
|
||||
}
|
||||
eprintln('Done')
|
||||
assert true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
struct Foo {
|
||||
bar string
|
||||
}
|
||||
|
||||
fn test_go_anon_fn_call_with_ref_arg() {
|
||||
foo := &Foo{
|
||||
bar: 'hello'
|
||||
}
|
||||
g := go fn (foo Foo) string {
|
||||
return foo.bar
|
||||
}(foo)
|
||||
ret := g.wait()
|
||||
println(ret)
|
||||
assert ret == 'hello'
|
||||
}
|
||||
|
|
@ -636,6 +636,12 @@ pub fn (mut t Transformer) expr(mut node ast.Expr) ast.Expr {
|
|||
}
|
||||
ast.SelectorExpr {
|
||||
node.expr = t.expr(mut node.expr)
|
||||
if mut node.expr is ast.StringLiteral && node.field_name == 'len' {
|
||||
return ast.IntegerLiteral{
|
||||
val: node.expr.val.len.str()
|
||||
pos: node.pos
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.SizeOf {
|
||||
node.expr = t.expr(mut node.expr)
|
||||
|
|
|
|||
Loading…
Reference in New Issue