mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
Merge branch 'master' of https://github.com/vlang/v into fix/gen_struct_equality_fn
This commit is contained in:
commit
cf9bd20726
34 changed files with 420 additions and 309 deletions
|
@ -441,7 +441,7 @@ fn run_repl(workdir string, vrepl_prefix string) int {
|
|||
prompt = '... '
|
||||
}
|
||||
oline := r.get_one_line(prompt) or { break }
|
||||
line := oline.trim_space()
|
||||
line := oline.all_before('//').trim_space()
|
||||
if line == '' {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ pub:
|
|||
attrs []string // the attributes of the field f
|
||||
is_pub bool // f is in a `pub:` section
|
||||
is_mut bool // f is in a `mut:` section
|
||||
is_embed bool // f is a embedded struct
|
||||
|
||||
is_shared bool // `f shared Abc`
|
||||
is_atomic bool // `f atomic int` , TODO
|
||||
|
|
|
@ -54,7 +54,7 @@ fn C.isdigit(c int) bool
|
|||
fn C.popen(c &char, t &char) voidptr
|
||||
|
||||
// <libproc.h>
|
||||
pub fn proc_pidpath(int, voidptr, int) int
|
||||
fn C.proc_pidpath(int, voidptr, int) int
|
||||
|
||||
fn C.realpath(const_path &char, resolved_path &char) &char
|
||||
|
||||
|
|
40
vlib/builtin/input_rune_iterator.v
Normal file
40
vlib/builtin/input_rune_iterator.v
Normal file
|
@ -0,0 +1,40 @@
|
|||
module builtin
|
||||
|
||||
// input_rune returns a single rune from the standart input (an unicode codepoint).
|
||||
// It expects, that the input is utf8 encoded.
|
||||
// It will return `none` on EOF.
|
||||
pub fn input_rune() ?rune {
|
||||
x := input_character()
|
||||
if x <= 0 {
|
||||
return none
|
||||
}
|
||||
char_len := utf8_char_len(u8(x))
|
||||
if char_len == 1 {
|
||||
return x
|
||||
}
|
||||
mut b := u8(x)
|
||||
b = b << char_len
|
||||
mut res := rune(b)
|
||||
mut shift := 6 - char_len
|
||||
for i := 1; i < char_len; i++ {
|
||||
c := rune(input_character())
|
||||
res = rune(res) << shift
|
||||
res |= c & 63 // 0x3f
|
||||
shift = 6
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InputRuneIterator is an iterator over the input runes.
|
||||
pub struct InputRuneIterator {}
|
||||
|
||||
// next returns the next rune from the input stream.
|
||||
pub fn (mut self InputRuneIterator) next() ?rune {
|
||||
return input_rune()
|
||||
}
|
||||
|
||||
// input_rune_iterator returns an iterator to allow for `for i, r in input_rune_iterator() {`.
|
||||
// When the input stream is closed, the loop will break.
|
||||
pub fn input_rune_iterator() InputRuneIterator {
|
||||
return InputRuneIterator{}
|
||||
}
|
52
vlib/builtin/input_rune_iterator_test.v
Normal file
52
vlib/builtin/input_rune_iterator_test.v
Normal file
|
@ -0,0 +1,52 @@
|
|||
// vtest build: !windows
|
||||
// vtest retry: 2
|
||||
import os
|
||||
import time
|
||||
|
||||
fn test_input_rune_iterator_with_unicode_input() {
|
||||
mut p := os.new_process(@VEXE)
|
||||
p.set_args(['-e', 'for i, r in input_rune_iterator() { println("> i: \${i:04} | r: `\${r}`") }'])
|
||||
p.set_redirect_stdio()
|
||||
p.run()
|
||||
spawn fn [mut p] () {
|
||||
time.sleep(10 * time.millisecond)
|
||||
dump(p.pid)
|
||||
p.stdin_write('Проба Abc 你好 🌍 123')
|
||||
time.sleep(10 * time.millisecond)
|
||||
p.stdin_write('\0x00') // 0 should break the input stream
|
||||
time.sleep(10 * time.millisecond)
|
||||
eprintln('>>> done')
|
||||
}()
|
||||
mut olines := []string{}
|
||||
for p.is_alive() {
|
||||
if oline := p.pipe_read(.stdout) {
|
||||
olines << oline
|
||||
}
|
||||
time.sleep(1 * time.millisecond)
|
||||
}
|
||||
p.close()
|
||||
p.wait()
|
||||
assert p.code == 0
|
||||
eprintln('done')
|
||||
solines := olines.join('\n').trim_space().replace('\r', '')
|
||||
eprintln('solines.len: ${solines.len} | solines: ${solines}')
|
||||
assert solines.len > 100
|
||||
assert solines == '> i: 0000 | r: `П`
|
||||
> i: 0001 | r: `р`
|
||||
> i: 0002 | r: `о`
|
||||
> i: 0003 | r: `б`
|
||||
> i: 0004 | r: `а`
|
||||
> i: 0005 | r: ` `
|
||||
> i: 0006 | r: `A`
|
||||
> i: 0007 | r: `b`
|
||||
> i: 0008 | r: `c`
|
||||
> i: 0009 | r: ` `
|
||||
> i: 0010 | r: `你`
|
||||
> i: 0011 | r: `好`
|
||||
> i: 0012 | r: ` `
|
||||
> i: 0013 | r: `🌍`
|
||||
> i: 0014 | r: ` `
|
||||
> i: 0015 | r: `1`
|
||||
> i: 0016 | r: `2`
|
||||
> i: 0017 | r: `3`'
|
||||
}
|
|
@ -3,7 +3,7 @@ module builtin
|
|||
// Note: this file will be removed soon
|
||||
|
||||
// byteptr.vbytes() - makes a V []u8 structure from a C style memory buffer. Note: the data is reused, NOT copied!
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (data byteptr) vbytes(len int) []u8 {
|
||||
return unsafe { voidptr(data).vbytes(len) }
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ pub fn (data byteptr) vbytes(len int) []u8 {
|
|||
// vstring converts a C style string to a V string. Note: the string data is reused, NOT copied.
|
||||
// strings returned from this function will be normal V strings beside that (i.e. they would be
|
||||
// freed by V's -autofree mechanism, when they are no longer used).
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (bp byteptr) vstring() string {
|
||||
return string{
|
||||
str: bp
|
||||
|
@ -21,7 +21,7 @@ pub fn (bp byteptr) vstring() string {
|
|||
|
||||
// vstring_with_len converts a C style string to a V string.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (bp byteptr) vstring_with_len(len int) string {
|
||||
return string{
|
||||
str: bp
|
||||
|
@ -32,7 +32,7 @@ pub fn (bp byteptr) vstring_with_len(len int) string {
|
|||
|
||||
// vstring converts C char* to V string.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (cp charptr) vstring() string {
|
||||
return string{
|
||||
str: byteptr(cp)
|
||||
|
@ -43,7 +43,7 @@ pub fn (cp charptr) vstring() string {
|
|||
|
||||
// vstring_with_len converts C char* to V string.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (cp charptr) vstring_with_len(len int) string {
|
||||
return string{
|
||||
str: byteptr(cp)
|
||||
|
@ -59,7 +59,7 @@ pub fn (cp charptr) vstring_with_len(len int) string {
|
|||
// This is suitable for readonly strings, C string literals etc,
|
||||
// that can be read by the V program, but that should not be
|
||||
// managed by it, for example `os.args` is implemented using it.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (bp byteptr) vstring_literal() string {
|
||||
return string{
|
||||
str: bp
|
||||
|
@ -70,7 +70,7 @@ pub fn (bp byteptr) vstring_literal() string {
|
|||
|
||||
// vstring_with_len converts a C style string to a V string.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (bp byteptr) vstring_literal_with_len(len int) string {
|
||||
return string{
|
||||
str: bp
|
||||
|
@ -82,7 +82,7 @@ pub fn (bp byteptr) vstring_literal_with_len(len int) string {
|
|||
// vstring_literal converts C char* to V string.
|
||||
// See also vstring_literal defined on byteptr for more details.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (cp charptr) vstring_literal() string {
|
||||
return string{
|
||||
str: byteptr(cp)
|
||||
|
@ -94,7 +94,7 @@ pub fn (cp charptr) vstring_literal() string {
|
|||
// vstring_literal_with_len converts C char* to V string.
|
||||
// See also vstring_literal_with_len defined on byteptr.
|
||||
// Note: the string data is reused, NOT copied.
|
||||
@[unsafe]
|
||||
@[reused; unsafe]
|
||||
pub fn (cp charptr) vstring_literal_with_len(len int) string {
|
||||
return string{
|
||||
str: byteptr(cp)
|
||||
|
|
|
@ -181,10 +181,7 @@ fn divide_digit_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut
|
|||
cmp_result := compare_digit_array(operand_a, operand_b)
|
||||
// a == b => q, r = 1, 0
|
||||
if cmp_result == 0 {
|
||||
quotient << 1
|
||||
for quotient.len > 1 {
|
||||
quotient.delete_last()
|
||||
}
|
||||
quotient[0] = 1
|
||||
remainder.clear()
|
||||
return
|
||||
}
|
||||
|
@ -192,7 +189,9 @@ fn divide_digit_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut
|
|||
// a < b => q, r = 0, a
|
||||
if cmp_result < 0 {
|
||||
quotient.clear()
|
||||
remainder << operand_a
|
||||
for i in 0 .. operand_a.len {
|
||||
remainder[i] = operand_a[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
if operand_b.len == 1 {
|
||||
|
@ -210,38 +209,36 @@ fn divide_array_by_digit(operand_a []u64, divisor u64, mut quotient []u64, mut r
|
|||
// 1 digit for both dividend and divisor
|
||||
dividend := operand_a[0]
|
||||
q := dividend / divisor
|
||||
if q != 0 {
|
||||
quotient << q
|
||||
}
|
||||
quotient[0] = q
|
||||
|
||||
rem := dividend % divisor
|
||||
if rem != 0 {
|
||||
remainder << rem
|
||||
}
|
||||
remainder[0] = rem
|
||||
|
||||
shrink_tail_zeros(mut quotient)
|
||||
shrink_tail_zeros(mut remainder)
|
||||
return
|
||||
}
|
||||
// Dividend has more digits
|
||||
mut rem := u64(0)
|
||||
mut quo := u64(0)
|
||||
mut qtemp := []u64{len: quotient.cap}
|
||||
divisor64 := u64(divisor)
|
||||
|
||||
// Perform division step by step
|
||||
for index := operand_a.len - 1; index >= 0; index-- {
|
||||
hi := rem >> (64 - digit_bits)
|
||||
lo := rem << digit_bits | operand_a[index]
|
||||
quo, rem = bits.div_64(hi, lo, divisor64)
|
||||
qtemp[index] = quo & max_digit
|
||||
quo, rem = bits.div_64(hi, lo, divisor)
|
||||
quotient[index] = quo & max_digit
|
||||
}
|
||||
|
||||
// Remove leading zeros from quotient
|
||||
shrink_tail_zeros(mut qtemp)
|
||||
quotient << qtemp
|
||||
remainder << rem
|
||||
shrink_tail_zeros(mut quotient)
|
||||
remainder[0] = rem
|
||||
shrink_tail_zeros(mut remainder)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
fn divide_array_by_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut remainder []u64) {
|
||||
binary_divide_array_by_array(operand_a, operand_b, mut quotient, mut remainder)
|
||||
knuth_divide_array_by_array(operand_a, operand_b, mut quotient, mut remainder)
|
||||
}
|
||||
|
||||
// Shifts the contents of the original array by the given amount of bits to the left.
|
||||
|
|
|
@ -136,8 +136,8 @@ fn test_compare_digit_array_02() {
|
|||
fn test_divide_digit_array_01() {
|
||||
a := [u64(14)]
|
||||
b := [u64(2)]
|
||||
mut q := []u64{cap: 1}
|
||||
mut r := []u64{cap: 1}
|
||||
mut q := []u64{len: 1}
|
||||
mut r := []u64{len: 1}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(7)]
|
||||
|
@ -147,8 +147,8 @@ fn test_divide_digit_array_01() {
|
|||
fn test_divide_digit_array_02() {
|
||||
a := [u64(14)]
|
||||
b := [u64(15)]
|
||||
mut q := []u64{cap: 1}
|
||||
mut r := []u64{cap: 1}
|
||||
mut q := []u64{len: 1}
|
||||
mut r := []u64{len: 1}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == []u64{len: 0}
|
||||
|
@ -158,8 +158,8 @@ fn test_divide_digit_array_02() {
|
|||
fn test_divide_digit_array_03() {
|
||||
a := [u64(0), 4]
|
||||
b := [u64(0), 1]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(4)]
|
||||
|
@ -169,8 +169,8 @@ fn test_divide_digit_array_03() {
|
|||
fn test_divide_digit_array_04() {
|
||||
a := [u64(2), 4]
|
||||
b := [u64(0), 1]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(4)]
|
||||
|
@ -180,8 +180,8 @@ fn test_divide_digit_array_04() {
|
|||
fn test_divide_digit_array_05() {
|
||||
a := [u64(3)]
|
||||
b := [u64(2)]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(1)]
|
||||
|
|
|
@ -2,57 +2,6 @@ module big
|
|||
|
||||
import math.bits
|
||||
|
||||
// suppose operand_a bigger than operand_b and both not null.
|
||||
// Both quotient and remaider are allocated but of length 0
|
||||
@[direct_array_access]
|
||||
fn binary_divide_array_by_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut remainder []u64) {
|
||||
remainder << operand_a
|
||||
|
||||
len_diff := operand_a.len - operand_b.len
|
||||
$if debug {
|
||||
assert len_diff >= 0
|
||||
}
|
||||
|
||||
// we must do in place shift and operations.
|
||||
mut divisor := []u64{cap: operand_b.len}
|
||||
for _ in 0 .. len_diff {
|
||||
divisor << u64(0)
|
||||
}
|
||||
divisor << operand_b
|
||||
for _ in 0 .. len_diff + 1 {
|
||||
quotient << u64(0)
|
||||
}
|
||||
|
||||
lead_zer_remainder := u32(bits.leading_zeros_64(remainder.last()) - (64 - digit_bits))
|
||||
lead_zer_divisor := u32(bits.leading_zeros_64(divisor.last()) - (64 - digit_bits))
|
||||
bit_offset := (u32(digit_bits) * u32(len_diff)) + (lead_zer_divisor - lead_zer_remainder)
|
||||
|
||||
// align
|
||||
if lead_zer_remainder < lead_zer_divisor {
|
||||
left_shift_in_place(mut divisor, lead_zer_divisor - lead_zer_remainder)
|
||||
} else if lead_zer_remainder > lead_zer_divisor {
|
||||
left_shift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
}
|
||||
|
||||
$if debug {
|
||||
assert left_align_p(divisor[divisor.len - 1], remainder[remainder.len - 1])
|
||||
}
|
||||
for bit_idx := int(bit_offset); bit_idx >= 0; bit_idx-- {
|
||||
if greater_equal_from_end(remainder, divisor) {
|
||||
bit_set(mut quotient, bit_idx)
|
||||
subtract_align_last_byte_in_place(mut remainder, divisor)
|
||||
}
|
||||
right_shift_in_place(mut divisor, 1)
|
||||
}
|
||||
|
||||
// adjust
|
||||
if lead_zer_remainder > lead_zer_divisor {
|
||||
right_shift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
}
|
||||
shrink_tail_zeros(mut remainder)
|
||||
shrink_tail_zeros(mut quotient)
|
||||
}
|
||||
|
||||
// help routines for cleaner code but inline for performance
|
||||
// quicker than BitField.set_bit
|
||||
@[direct_array_access; inline]
|
||||
|
@ -65,80 +14,112 @@ fn bit_set(mut a []u64, n int) {
|
|||
a[byte_offset] |= mask
|
||||
}
|
||||
|
||||
// a.len is greater or equal to b.len
|
||||
// returns true if a >= b (completed with zeroes)
|
||||
@[direct_array_access; inline]
|
||||
fn greater_equal_from_end(a []u64, b []u64) bool {
|
||||
$if debug {
|
||||
assert a.len >= b.len
|
||||
}
|
||||
offset := a.len - b.len
|
||||
for index := a.len - 1; index >= offset; index-- {
|
||||
if a[index] > b[index - offset] {
|
||||
return true
|
||||
} else if a[index] < b[index - offset] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@[direct_array_access]
|
||||
fn knuth_divide_array_by_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut remainder []u64) {
|
||||
m := operand_a.len - operand_b.len
|
||||
n := operand_b.len
|
||||
mut u := []u64{len: operand_a.len + 1}
|
||||
mut v := []u64{len: n}
|
||||
leading_zeros := bits.leading_zeros_64(operand_b.last()) - (64 - digit_bits)
|
||||
|
||||
// a := a - b supposed a >= b
|
||||
// attention the b operand is align with the a operand before the subtraction
|
||||
@[direct_array_access; inline]
|
||||
fn subtract_align_last_byte_in_place(mut a []u64, b []u64) {
|
||||
if leading_zeros > 0 {
|
||||
mut carry := u64(0)
|
||||
mut new_carry := u64(0)
|
||||
offset := a.len - b.len
|
||||
for index := a.len - b.len; index < a.len; index++ {
|
||||
if a[index] < (b[index - offset] + carry) || (b[index - offset] == max_digit && carry > 0) {
|
||||
new_carry = 1
|
||||
amount := digit_bits - leading_zeros
|
||||
for i in 0 .. operand_a.len {
|
||||
temp := (operand_a[i] << leading_zeros) | carry
|
||||
u[i] = temp & max_digit
|
||||
carry = operand_a[i] >> amount
|
||||
}
|
||||
u[operand_a.len] = carry
|
||||
carry = 0
|
||||
for i in 0 .. operand_b.len {
|
||||
temp := (operand_b[i] << leading_zeros) | carry
|
||||
v[i] = temp & max_digit
|
||||
carry = operand_b[i] >> amount
|
||||
}
|
||||
} else {
|
||||
new_carry = 0
|
||||
for i in 0 .. operand_a.len {
|
||||
u[i] = operand_a[i]
|
||||
}
|
||||
a[index] -= (b[index - offset] + carry)
|
||||
a[index] = a[index] & max_digit
|
||||
carry = new_carry
|
||||
for i in 0 .. operand_b.len {
|
||||
v[i] = operand_b[i]
|
||||
}
|
||||
$if debug {
|
||||
assert carry == 0
|
||||
}
|
||||
}
|
||||
|
||||
// logical left shift
|
||||
// there is no overflow. We know that the last bits are zero
|
||||
// and that n <= `digit_bits`
|
||||
@[direct_array_access; inline]
|
||||
fn left_shift_in_place(mut a []u64, n u32) {
|
||||
if remainder.len >= (n + 1) {
|
||||
remainder.trim(n + 1)
|
||||
} else {
|
||||
remainder = []u64{len: n + 1}
|
||||
}
|
||||
|
||||
v_n_1 := v[n - 1]
|
||||
v_n_2 := v[n - 2]
|
||||
for j := m; j >= 0; j-- {
|
||||
u_j_n := u[j + n]
|
||||
u_j_n_1 := u[j + n - 1]
|
||||
u_j_n_2 := u[j + n - 2]
|
||||
|
||||
mut qhat, mut rhat := bits.div_64(u_j_n >> (64 - digit_bits), (u_j_n << digit_bits) | u_j_n_1,
|
||||
v_n_1)
|
||||
mut x1, mut x2 := bits.mul_64(qhat, v_n_2)
|
||||
x2 = x2 & max_digit
|
||||
x1 = (x1 << (64 - digit_bits)) | (x2 >> digit_bits)
|
||||
for greater_than(x1, x2, rhat, u_j_n_2) {
|
||||
qhat--
|
||||
prev := rhat
|
||||
rhat += v_n_1
|
||||
if rhat < prev {
|
||||
break
|
||||
}
|
||||
x1, x2 = bits.mul_64(qhat, v_n_2)
|
||||
x2 = x2 & max_digit
|
||||
x1 = (x1 << (64 - digit_bits)) | (x2 >> digit_bits)
|
||||
}
|
||||
mut carry := u64(0)
|
||||
mut prec_carry := u64(0)
|
||||
mask := ((u64(1) << n) - 1) << (digit_bits - n)
|
||||
for index in 0 .. a.len {
|
||||
prec_carry = carry >> (digit_bits - n)
|
||||
carry = a[index] & mask
|
||||
a[index] <<= n
|
||||
a[index] = a[index] & max_digit
|
||||
a[index] |= prec_carry
|
||||
for i in 0 .. n {
|
||||
hi, lo := bits.mul_add_64(v[i], qhat, carry)
|
||||
remainder[i] = lo & max_digit
|
||||
carry = (hi << (64 - digit_bits)) | (lo >> digit_bits)
|
||||
}
|
||||
}
|
||||
remainder[n] = carry
|
||||
|
||||
// logical right shift without control because these digits have already been
|
||||
// shift left before
|
||||
@[direct_array_access; inline]
|
||||
fn right_shift_in_place(mut a []u64, n u32) {
|
||||
mut borrow := u64(0)
|
||||
for i in 0 .. n + 1 {
|
||||
result := u[j + i] - remainder[i] - borrow
|
||||
u[j + i] = result & max_digit
|
||||
borrow = (result >> digit_bits) & 1
|
||||
}
|
||||
if borrow == 1 {
|
||||
qhat--
|
||||
carry = u64(0)
|
||||
for i in 0 .. n {
|
||||
sum := u[j + i] + v[i] + carry
|
||||
u[j + i] = sum & max_digit
|
||||
carry = sum >> digit_bits
|
||||
}
|
||||
}
|
||||
quotient[j] = qhat
|
||||
}
|
||||
|
||||
remainder.delete_last()
|
||||
if leading_zeros > 0 {
|
||||
mut carry := u64(0)
|
||||
mut prec_carry := u64(0)
|
||||
mask := (u64(1) << n) - 1
|
||||
for index := a.len - 1; index >= 0; index-- {
|
||||
carry = a[index] & mask
|
||||
a[index] >>= n
|
||||
a[index] |= prec_carry << (digit_bits - n)
|
||||
prec_carry = carry
|
||||
max_leading_digit := (u64(1) << leading_zeros) - 1
|
||||
for i := n - 1; i >= 0; i-- {
|
||||
current_limb := u[i]
|
||||
remainder[i] = (current_limb >> leading_zeros) | carry
|
||||
carry = (current_limb & max_leading_digit) << (digit_bits - leading_zeros)
|
||||
}
|
||||
} else {
|
||||
for i in 0 .. n {
|
||||
remainder[i] = u[i]
|
||||
}
|
||||
}
|
||||
shrink_tail_zeros(mut quotient)
|
||||
shrink_tail_zeros(mut remainder)
|
||||
}
|
||||
|
||||
// for assert
|
||||
@[inline]
|
||||
fn left_align_p(a u64, b u64) bool {
|
||||
return bits.leading_zeros_64(a) == bits.leading_zeros_64(b)
|
||||
fn greater_than(x1 u64, x2 u64, y1 u64, y2 u64) bool {
|
||||
return x1 > y1 || (x1 == y1 && x2 > y2)
|
||||
}
|
||||
|
|
|
@ -2,92 +2,11 @@ module big
|
|||
|
||||
import rand
|
||||
|
||||
fn test_left_shift_in_place() {
|
||||
mut a := [u64(1), 1, 1, 1, 1]
|
||||
left_shift_in_place(mut a, 1)
|
||||
assert a == [u64(2), 2, 2, 2, 2]
|
||||
left_shift_in_place(mut a, 7)
|
||||
assert a == [u64(256), 256, 256, 256, 256]
|
||||
mut b := [u64(0x08000000_00000001), 0x0c000000_00000000, 0x08000000_00000000, 0x07ffffff_ffffffff]
|
||||
left_shift_in_place(mut b, 1)
|
||||
assert b == [u64(2), 0x08000000_00000001, 1, 0x0fffffff_ffffffff]
|
||||
mut c := [u64(0x00ffffff_ffffffff), 0x00f0f0f0_f0f0f0f0, 1, 0x03ffffff_ffffffff, 1]
|
||||
left_shift_in_place(mut c, 2)
|
||||
assert c == [u64(0x03ffffff_fffffffc), 0x03c3c3c3_c3c3c3c0, 4, 0x0fffffff_fffffffc, 4]
|
||||
}
|
||||
|
||||
fn test_right_shift_in_place() {
|
||||
mut a := [u64(2), 2, 2, 2, 2]
|
||||
right_shift_in_place(mut a, 1)
|
||||
assert a == [u64(1), 1, 1, 1, 1]
|
||||
a = [u64(256), 256, 256, 256, 256]
|
||||
right_shift_in_place(mut a, 7)
|
||||
assert a == [u64(2), 2, 2, 2, 2]
|
||||
a = [u64(0), 0, 1]
|
||||
right_shift_in_place(mut a, 1)
|
||||
assert a == [u64(0), 0x08000000_00000000, 0]
|
||||
mut b := [u64(3), 0x08000000_00000001, 1, 0x0fffffff_ffffffff]
|
||||
right_shift_in_place(mut b, 1)
|
||||
assert b == [u64(0x08000000_00000001), 0x0c000000_00000000, 0x08000000_00000000,
|
||||
0x07ffffff_ffffffff]
|
||||
mut c := [u64(0x03ffffff), 0x03c3c3c3_c3c3c3c0, 7, 0xfffffffc, 4]
|
||||
right_shift_in_place(mut c, 2)
|
||||
assert c == [u64(0x00ffffff), 0x0cf0f0f0_f0f0f0f0, 1, 0x3fffffff, 1]
|
||||
}
|
||||
|
||||
fn test_subtract_align_last_byte_in_place() {
|
||||
mut a := [u64(2), 2, 2, 2, 2]
|
||||
mut b := [u64(1), 1, 2, 1, 1]
|
||||
subtract_align_last_byte_in_place(mut a, b)
|
||||
assert a == [u64(1), 1, 0, 1, 1]
|
||||
|
||||
a = [u64(0), 0, 0, 0, 1]
|
||||
b = [u64(0), 0, 1]
|
||||
subtract_align_last_byte_in_place(mut a, b)
|
||||
assert a == [u64(0), 0, 0, 0, 0]
|
||||
|
||||
a = [u64(0), 0, 0, 0, 1, 13]
|
||||
b = [u64(1), 0, 1]
|
||||
mut c := []u64{len: a.len}
|
||||
mut d := [u64(0), 0, 0]
|
||||
d << b // to have same length
|
||||
subtract_digit_array(a, d, mut c)
|
||||
subtract_align_last_byte_in_place(mut a, b)
|
||||
assert a == [u64(0), 0, 0, u64(-1) & max_digit, 0, 12]
|
||||
assert c == a
|
||||
}
|
||||
|
||||
fn test_greater_equal_from_end() {
|
||||
mut a := [u64(1), 2, 3, 4, 5, 6]
|
||||
mut b := [u64(3), 4, 5, 6]
|
||||
assert greater_equal_from_end(a, b) == true
|
||||
|
||||
a = [u64(1), 2, 3, 4, 5, 6]
|
||||
b = [u64(1), 2, 3, 4, 5, 6]
|
||||
assert greater_equal_from_end(a, b) == true
|
||||
|
||||
a = [u64(1), 2, 3, 4, 5, 6]
|
||||
b = [u64(2), 2, 3, 4, 5, 6]
|
||||
assert greater_equal_from_end(a, b) == false
|
||||
|
||||
a = [u64(0), 0, 0, 4, 5, 6]
|
||||
b = [u64(4), 5, 6]
|
||||
assert greater_equal_from_end(a, b) == true
|
||||
|
||||
a = [u64(0), 0, 0, 4, 5, 6]
|
||||
b = [u64(4), 6, 6]
|
||||
assert greater_equal_from_end(a, b) == false
|
||||
|
||||
a = [u64(0), 0, 0, 4, 5, 5]
|
||||
b = [u64(4), 5, 6]
|
||||
assert greater_equal_from_end(a, b) == false
|
||||
}
|
||||
|
||||
fn test_divide_digit_array_03() {
|
||||
a := [u64(0), 4]
|
||||
b := [u64(0), 1]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(4)]
|
||||
|
@ -97,8 +16,8 @@ fn test_divide_digit_array_03() {
|
|||
fn test_divide_digit_array_04() {
|
||||
a := [u64(2), 4]
|
||||
b := [u64(0), 1]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(4)]
|
||||
|
@ -108,8 +27,8 @@ fn test_divide_digit_array_04() {
|
|||
fn test_divide_digit_array_05() {
|
||||
a := [u64(2), 4, 5]
|
||||
b := [u64(0), 1]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(4), 5]
|
||||
|
@ -119,8 +38,8 @@ fn test_divide_digit_array_05() {
|
|||
fn test_divide_digit_array_06() {
|
||||
a := [u64(2), 4, 5, 3]
|
||||
b := [u64(0), 0x8000]
|
||||
mut q := []u64{cap: a.len - b.len + 1}
|
||||
mut r := []u64{cap: a.len}
|
||||
mut q := []u64{len: a.len - b.len + 1}
|
||||
mut r := []u64{len: a.len}
|
||||
|
||||
divide_digit_array(a, b, mut q, mut r)
|
||||
assert q == [u64(0xa000_00000000), 0x6000_00000000]
|
||||
|
|
|
@ -393,8 +393,8 @@ pub fn (multiplicand Integer) * (multiplier Integer) Integer {
|
|||
//
|
||||
// DO NOT use this method if the divisor has any chance of being 0.
|
||||
fn (dividend Integer) div_mod_internal(divisor Integer) (Integer, Integer) {
|
||||
mut q := []u64{cap: int_max(1, dividend.digits.len - divisor.digits.len + 1)}
|
||||
mut r := []u64{cap: dividend.digits.len}
|
||||
mut q := []u64{len: int_max(1, dividend.digits.len - divisor.digits.len + 1)}
|
||||
mut r := []u64{len: dividend.digits.len}
|
||||
mut q_signum := 0
|
||||
mut r_signum := 0
|
||||
|
||||
|
|
|
@ -87,7 +87,9 @@ fn (pr &HttpProxy) build_proxy_headers(host string) string {
|
|||
fn (pr &HttpProxy) http_do(host urllib.URL, method Method, path string, req &Request) !Response {
|
||||
host_name, port := net.split_address(host.hostname())!
|
||||
|
||||
s := req.build_request_headers(req.method, host_name, port, path)
|
||||
port_part := if port == 80 || port == 0 { '' } else { ':${port}' }
|
||||
|
||||
s := req.build_request_headers(req.method, host_name, port, '${host.scheme}://${host_name}${port_part}${path}')
|
||||
if host.scheme == 'https' {
|
||||
mut client := pr.ssl_dial('${host.host}:443')!
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module http
|
||||
|
||||
import encoding.base64
|
||||
import net.urllib
|
||||
import os
|
||||
|
||||
const sample_proxy_url = 'https://localhost'
|
||||
const sample_auth_proxy_url = 'http://user:pass@localhost:8888'
|
||||
|
@ -46,3 +48,29 @@ fn test_proxy_headers_authenticated() ? {
|
|||
assert headers == 'CONNECT 127.0.0.1:1337 HTTP/1.1\r\n' + 'Host: 127.0.0.1\r\n' +
|
||||
'Proxy-Connection: Keep-Alive\r\nProxy-Authorization: Basic ${auth_token}\r\n\r\n'
|
||||
}
|
||||
|
||||
fn test_http_proxy_do() {
|
||||
env := os.environ()
|
||||
mut env_proxy := ''
|
||||
|
||||
for envvar in ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY'] {
|
||||
prox_val := env[envvar] or { continue }
|
||||
if prox_val != '' {
|
||||
env_proxy = env[envvar]
|
||||
}
|
||||
}
|
||||
if env_proxy != '' {
|
||||
println('Has usable proxy env vars')
|
||||
proxy := new_http_proxy(env_proxy)!
|
||||
mut header := new_header(key: .user_agent, value: 'vlib')
|
||||
header.add_custom('X-Vlang-Test', 'proxied')!
|
||||
res := proxy.http_do(urllib.parse('http://httpbin.org/headers')!, Method.get,
|
||||
'/headers', &Request{ proxy: proxy, header: header })!
|
||||
println(res.status_code)
|
||||
println('he4aders ${res.header}')
|
||||
assert res.status_code == 200
|
||||
// assert res.header.data['X-Vlang-Test'] == 'proxied'
|
||||
} else {
|
||||
println('Proxy env vars (HTTP_PROXY or HTTPS_PROXY) not set. Skipping test.')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -393,7 +393,9 @@ fn test_orm() {
|
|||
// Note: usually updated_time_mod.created != t, because t has
|
||||
// its microseconds set, while the value retrieved from the DB
|
||||
// has them zeroed, because the db field resolution is seconds.
|
||||
assert modules.first().created.format_ss() == t.format_ss()
|
||||
// Note: the database also stores the time in UTC, so the
|
||||
// comparison must be done on the unix timestamp.
|
||||
assert modules.first().created.unix() == t.unix()
|
||||
|
||||
users = sql db {
|
||||
select from User where (name == 'Sam' && is_customer == true) || id == 1
|
||||
|
|
|
@ -5,6 +5,10 @@ import strings
|
|||
#include <sys/stat.h> // #include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
$if macos {
|
||||
#include <libproc.h>
|
||||
}
|
||||
|
||||
$if freebsd || openbsd {
|
||||
#include <sys/sysctl.h>
|
||||
}
|
||||
|
@ -715,7 +719,7 @@ pub fn executable() string {
|
|||
}
|
||||
$if macos {
|
||||
pid := C.getpid()
|
||||
ret := proc_pidpath(pid, &result[0], max_path_len)
|
||||
ret := C.proc_pidpath(pid, &result[0], max_path_len)
|
||||
if ret <= 0 {
|
||||
eprintln('os.executable() failed at calling proc_pidpath with pid: ${pid} . proc_pidpath returned ${ret} ')
|
||||
return executable_fallback()
|
||||
|
|
|
@ -3,13 +3,16 @@ module time
|
|||
// operator `==` returns true if provided time is equal to time
|
||||
@[inline]
|
||||
pub fn (t1 Time) == (t2 Time) bool {
|
||||
return t1.unix() == t2.unix() && t1.nanosecond == t2.nanosecond
|
||||
return t1.nanosecond == t2.nanosecond && t1.is_local == t2.is_local
|
||||
&& t1.local_unix() == t2.local_unix()
|
||||
}
|
||||
|
||||
// operator `<` returns true if provided time is less than time
|
||||
@[inline]
|
||||
pub fn (t1 Time) < (t2 Time) bool {
|
||||
return t1.unix() < t2.unix() || (t1.unix() == t2.unix() && t1.nanosecond < t2.nanosecond)
|
||||
t1u := t1.unix()
|
||||
t2u := t2.unix()
|
||||
return t1u < t2u || (t1u == t2u && t1.nanosecond < t2.nanosecond)
|
||||
}
|
||||
|
||||
// Time subtract using operator overloading.
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// tests that use and test private functions
|
||||
module time
|
||||
|
||||
// test the old behavior is same as new, the unix time should always be local time
|
||||
fn test_new_is_same_as_old_for_all_platforms() {
|
||||
t := C.time(0)
|
||||
tm := C.localtime(&t)
|
||||
old_time := convert_ctime(tm, 0)
|
||||
new_time := now()
|
||||
diff := new_time.unix - old_time.unix
|
||||
// could in very rare cases be that the second changed between calls
|
||||
dump(diff)
|
||||
assert (diff >= -2 && diff <= 2) == true
|
||||
}
|
|
@ -106,6 +106,12 @@ pub fn (t Time) smonth() string {
|
|||
// unix returns the UNIX time with second resolution.
|
||||
@[inline]
|
||||
pub fn (t Time) unix() i64 {
|
||||
return time_with_unix(t.local_to_utc()).unix
|
||||
}
|
||||
|
||||
// local_unix returns the UNIX local time with second resolution.
|
||||
@[inline]
|
||||
pub fn (t Time) local_unix() i64 {
|
||||
return time_with_unix(t).unix
|
||||
}
|
||||
|
||||
|
@ -135,14 +141,26 @@ pub fn (t Time) add(duration_in_nanosecond Duration) Time {
|
|||
// ... so instead, handle the addition manually in parts ¯\_(ツ)_/¯
|
||||
mut increased_time_nanosecond := i64(t.nanosecond) + duration_in_nanosecond.nanoseconds()
|
||||
// increased_time_second
|
||||
mut increased_time_second := t.unix() + (increased_time_nanosecond / second)
|
||||
mut increased_time_second := t.local_unix() + (increased_time_nanosecond / second)
|
||||
increased_time_nanosecond = increased_time_nanosecond % second
|
||||
if increased_time_nanosecond < 0 {
|
||||
increased_time_second--
|
||||
increased_time_nanosecond += second
|
||||
}
|
||||
res := unix_nanosecond(increased_time_second, int(increased_time_nanosecond))
|
||||
return if t.is_local { res.as_local() } else { res }
|
||||
|
||||
if t.is_local {
|
||||
// we need to reset unix to 0, because we don't know the offset
|
||||
// and we can't calculate it without it without causing infinite recursion
|
||||
// so unfortunately we need to recalculate unix next time it is needed
|
||||
return Time{
|
||||
...res
|
||||
is_local: true
|
||||
unix: 0
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// add_seconds returns a new time struct with an added number of seconds.
|
||||
|
@ -177,7 +195,7 @@ pub fn since(t Time) Duration {
|
|||
// ```
|
||||
pub fn (t Time) relative() string {
|
||||
znow := now()
|
||||
mut secs := znow.unix - t.unix()
|
||||
mut secs := znow.unix() - t.unix()
|
||||
mut prefix := ''
|
||||
mut suffix := ''
|
||||
if secs < 0 {
|
||||
|
@ -239,7 +257,7 @@ pub fn (t Time) relative() string {
|
|||
// ```
|
||||
pub fn (t Time) relative_short() string {
|
||||
znow := now()
|
||||
mut secs := znow.unix - t.unix()
|
||||
mut secs := znow.unix() - t.unix()
|
||||
mut prefix := ''
|
||||
mut suffix := ''
|
||||
if secs < 0 {
|
||||
|
@ -364,9 +382,9 @@ pub fn days_in_month(month int, year int) !int {
|
|||
return res
|
||||
}
|
||||
|
||||
// debug returns detailed breakdown of time (`Time{ year: YYYY month: MM day: dd hour: HH: minute: mm second: ss nanosecond: nanos unix: unix }`).
|
||||
// debug returns detailed breakdown of time (`Time{ year: YYYY month: MM day: dd hour: HH: minute: mm second: ss nanosecond: nanos unix: unix is_local: false }`).
|
||||
pub fn (t Time) debug() string {
|
||||
return 'Time{ year: ${t.year:04} month: ${t.month:02} day: ${t.day:02} hour: ${t.hour:02} minute: ${t.minute:02} second: ${t.second:02} nanosecond: ${t.nanosecond:09} unix: ${t.unix:07} }'
|
||||
return 'Time{ year: ${t.year:04} month: ${t.month:02} day: ${t.day:02} hour: ${t.hour:02} minute: ${t.minute:02} second: ${t.second:02} nanosecond: ${t.nanosecond:09} unix: ${t.unix:07} is_local: ${t.is_local} }'
|
||||
}
|
||||
|
||||
// offset returns time zone UTC offset in seconds.
|
||||
|
|
|
@ -12,7 +12,7 @@ const time_to_test = time.Time{
|
|||
fn test_now_format() {
|
||||
t := time.now()
|
||||
u := t.unix()
|
||||
assert t.format() == time.unix(int(u)).format()
|
||||
assert t.format() == time.unix(int(u)).utc_to_local().format()
|
||||
}
|
||||
|
||||
fn test_format() {
|
||||
|
|
|
@ -15,7 +15,7 @@ fn test_tm_gmtoff() {
|
|||
dump(t2)
|
||||
dump(t1.nanosecond)
|
||||
dump(t2.nanosecond)
|
||||
diff := int(t1.unix() - t2.unix())
|
||||
diff := int(t1.local_unix() - t2.unix())
|
||||
dump(diff)
|
||||
dump(info.tm_gmtoff)
|
||||
assert diff in [info.tm_gmtoff - 1, info.tm_gmtoff, info.tm_gmtoff + 1]
|
||||
|
|
|
@ -90,17 +90,10 @@ fn test_unix() {
|
|||
assert t6.hour == 6
|
||||
assert t6.minute == 9
|
||||
assert t6.second == 29
|
||||
assert local_time_to_test.unix() == 332198622
|
||||
assert utc_time_to_test.unix() == 332198622
|
||||
}
|
||||
|
||||
fn test_format_rfc3339() {
|
||||
// assert '1980-07-11T19:23:42.123Z'
|
||||
res := local_time_to_test.format_rfc3339()
|
||||
assert res.ends_with('23:42.123Z')
|
||||
assert res.starts_with('1980-07-1')
|
||||
assert res.contains('T')
|
||||
|
||||
// assert '1980-07-11T19:23:42.123Z'
|
||||
utc_res := utc_time_to_test.format_rfc3339()
|
||||
assert utc_res.ends_with('23:42.123Z')
|
||||
|
@ -109,11 +102,6 @@ fn test_format_rfc3339() {
|
|||
}
|
||||
|
||||
fn test_format_rfc3339_micro() {
|
||||
res := local_time_to_test.format_rfc3339_micro()
|
||||
assert res.ends_with('23:42.123456Z')
|
||||
assert res.starts_with('1980-07-1')
|
||||
assert res.contains('T')
|
||||
|
||||
utc_res := utc_time_to_test.format_rfc3339_micro()
|
||||
assert utc_res.ends_with('23:42.123456Z')
|
||||
assert utc_res.starts_with('1980-07-1')
|
||||
|
@ -121,11 +109,6 @@ fn test_format_rfc3339_micro() {
|
|||
}
|
||||
|
||||
fn test_format_rfc3339_nano() {
|
||||
res := local_time_to_test.format_rfc3339_nano()
|
||||
assert res.ends_with('23:42.123456789Z')
|
||||
assert res.starts_with('1980-07-1')
|
||||
assert res.contains('T')
|
||||
|
||||
utc_res := utc_time_to_test.format_rfc3339_nano()
|
||||
assert utc_res.ends_with('23:42.123456789Z')
|
||||
assert utc_res.starts_with('1980-07-1')
|
||||
|
|
|
@ -1398,7 +1398,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, mut sb strings.Builder) (
|
|||
}
|
||||
ast.SelectorExpr {
|
||||
if c.comptime.comptime_for_field_var != '' && cond.expr is ast.Ident {
|
||||
if (cond.expr as ast.Ident).name == c.comptime.comptime_for_field_var && cond.field_name in ['is_mut', 'is_pub', 'is_shared', 'is_atomic', 'is_option', 'is_array', 'is_map', 'is_chan', 'is_struct', 'is_alias', 'is_enum'] {
|
||||
if (cond.expr as ast.Ident).name == c.comptime.comptime_for_field_var && cond.field_name in ['is_mut', 'is_pub', 'is_embed', 'is_shared', 'is_atomic', 'is_option', 'is_array', 'is_map', 'is_chan', 'is_struct', 'is_alias', 'is_enum'] {
|
||||
is_true = c.type_resolver.get_comptime_selector_bool_field(cond.field_name)
|
||||
sb.write_string('${is_true}')
|
||||
return is_true, true
|
||||
|
|
|
@ -221,11 +221,14 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !node.is_comptime || (node.is_comptime && comptime_match_branch_result) {
|
||||
if node.is_expr {
|
||||
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
|
||||
} else {
|
||||
c.stmts(mut branch.stmts)
|
||||
}
|
||||
}
|
||||
c.smartcast_mut_pos = token.Pos{}
|
||||
c.smartcast_cond_pos = token.Pos{}
|
||||
if node.is_expr {
|
||||
|
|
|
@ -98,6 +98,21 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
|
|||
if obj.expr is ast.IfGuardExpr {
|
||||
continue
|
||||
}
|
||||
if obj.expr is ast.UnsafeExpr && obj.expr.expr is ast.CallExpr
|
||||
&& (obj.expr.expr as ast.CallExpr).is_method {
|
||||
if left_var := scope.objects[obj.expr.expr.left.str()] {
|
||||
if func := g.table.find_method(g.table.final_sym(left_var.typ),
|
||||
obj.expr.expr.name)
|
||||
{
|
||||
if func.attrs.contains('reused') && left_var is ast.Var
|
||||
&& left_var.expr is ast.CastExpr {
|
||||
if left_var.expr.expr.is_literal() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.autofree_variable(obj)
|
||||
}
|
||||
else {}
|
||||
|
|
|
@ -740,6 +740,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
|
|||
g.writeln('\t${node.val_var}.unaliased_typ = ${int(unaliased_styp.idx())};\t// ${g.table.type_to_str(unaliased_styp)}')
|
||||
g.writeln('\t${node.val_var}.is_pub = ${field.is_pub};')
|
||||
g.writeln('\t${node.val_var}.is_mut = ${field.is_mut};')
|
||||
g.writeln('\t${node.val_var}.is_embed = ${field.is_embed};')
|
||||
|
||||
g.writeln('\t${node.val_var}.is_shared = ${field.typ.has_flag(.shared_f)};')
|
||||
g.writeln('\t${node.val_var}.is_atomic = ${field.typ.has_flag(.atomic_f)};')
|
||||
|
@ -779,9 +780,14 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
|
|||
g.write('\t${node.val_var}.value = ')
|
||||
if g.pref.translated && node.typ.is_number() {
|
||||
g.writeln('_const_main__${val};')
|
||||
} else {
|
||||
node_sym := g.table.sym(node.typ)
|
||||
if node_sym.info is ast.Alias {
|
||||
g.writeln('${g.styp(node_sym.info.parent_type)}__${val};')
|
||||
} else {
|
||||
g.writeln('${g.styp(node.typ)}__${val};')
|
||||
}
|
||||
}
|
||||
enum_attrs := sym.info.attrs[val]
|
||||
if enum_attrs.len == 0 {
|
||||
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
|
||||
|
|
|
@ -431,7 +431,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||
if variant_sym.kind == .enum {
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('u64')}(*${var_data}${field_op}_${variant_typ}));')
|
||||
} else if variant_sym.name == 'time.Time' {
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('i64')}(${var_data}${field_op}_${variant_typ}->__v_unix));')
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('i64')}(time__Time_unix(*${var_data}${field_op}_${variant_typ})));')
|
||||
} else {
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name(variant_typ)}(*${var_data}${field_op}_${variant_typ}));')
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||
}
|
||||
} else if variant_sym.name == 'time.Time' {
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "_type", cJSON_CreateString("${unmangled_variant_name}"));')
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "value", ${js_enc_name('i64')}(${var_data}${field_op}_${variant_typ}->__v_unix));')
|
||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "value", ${js_enc_name('i64')}(time__Time_unix(*${var_data}${field_op}_${variant_typ})));')
|
||||
} else {
|
||||
enc.writeln('\t\tcJSON_free(o);')
|
||||
enc.writeln('\t\to = ${js_enc_name(variant_typ)}(*${var_data}${field_op}_${variant_typ});')
|
||||
|
@ -968,9 +968,9 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
|
|||
// time struct requires special treatment
|
||||
// it has to be encoded as a unix timestamp number
|
||||
if is_option {
|
||||
enc.writeln('${indent}cJSON_AddItemToObject(o, "${name}", json__encode_u64((*(${g.base_type(field.typ)}*)(${prefix_enc}${op}${c_name(field.name)}.data)).__v_unix));')
|
||||
enc.writeln('${indent}cJSON_AddItemToObject(o, "${name}", json__encode_u64(time__Time_unix(*(${g.base_type(field.typ)}*)(${prefix_enc}${op}${c_name(field.name)}.data))));')
|
||||
} else {
|
||||
enc.writeln('${indent}cJSON_AddItemToObject(o, "${name}", json__encode_u64(${prefix_enc}${op}${c_name(field.name)}.__v_unix));')
|
||||
enc.writeln('${indent}cJSON_AddItemToObject(o, "${name}", json__encode_u64(time__Time_unix(${prefix_enc}${op}${c_name(field.name)})));')
|
||||
}
|
||||
} else {
|
||||
if !field.typ.is_any_kind_of_pointer() {
|
||||
|
|
10
vlib/v/gen/c/testdata/autofree_reused.c.must_have
vendored
Normal file
10
vlib/v/gen/c/testdata/autofree_reused.c.must_have
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
VV_LOC void main__main(void) {
|
||||
byteptr b = ((byteptr)("a"));
|
||||
Array_u8 s = byteptr_vbytes(b, 1);
|
||||
string _t1 = Array_u8_str(s); println(_t1); string_free(&_t1);
|
||||
;
|
||||
byteptr bb = ((byteptr)("a"));
|
||||
string ss = byteptr_vstring(bb);
|
||||
println(ss);
|
||||
}
|
||||
|
2
vlib/v/gen/c/testdata/autofree_reused.out
vendored
Normal file
2
vlib/v/gen/c/testdata/autofree_reused.out
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[97]
|
||||
a
|
10
vlib/v/gen/c/testdata/autofree_reused.vv
vendored
Normal file
10
vlib/v/gen/c/testdata/autofree_reused.vv
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// vtest vflags: -autofree
|
||||
fn main() {
|
||||
b := byteptr(c'a')
|
||||
s := unsafe { b.vbytes(1) }
|
||||
println(s)
|
||||
|
||||
bb := byteptr(c'a')
|
||||
ss := unsafe { bb.vstring() }
|
||||
println(ss)
|
||||
}
|
5
vlib/v/slow_tests/repl/line_comment.repl
Normal file
5
vlib/v/slow_tests/repl/line_comment.repl
Normal file
|
@ -0,0 +1,5 @@
|
|||
math.pi
|
||||
math.pi // some comment
|
||||
===output===
|
||||
3.141592653589793
|
||||
3.141592653589793
|
|
@ -5,6 +5,8 @@ enum CharacterGroup {
|
|||
special
|
||||
}
|
||||
|
||||
type AnotherCharGroup = CharacterGroup
|
||||
|
||||
fn (self CharacterGroup) value() string {
|
||||
return match self {
|
||||
.chars { 'first' }
|
||||
|
@ -33,3 +35,21 @@ fn test_main() {
|
|||
assert values == [CharacterGroup.chars, CharacterGroup.alphanumerics, CharacterGroup.numeric,
|
||||
CharacterGroup.special]
|
||||
}
|
||||
|
||||
fn test_alias_enum() {
|
||||
mut values := []EnumData{}
|
||||
$for entry in AnotherCharGroup.values {
|
||||
values << entry
|
||||
}
|
||||
assert values[0].value == int(CharacterGroup.chars)
|
||||
assert values[0].name == CharacterGroup.chars.str()
|
||||
|
||||
assert values[1].value == int(CharacterGroup.alphanumerics)
|
||||
assert values[1].name == CharacterGroup.alphanumerics.str()
|
||||
|
||||
assert values[2].value == int(CharacterGroup.numeric)
|
||||
assert values[2].name == CharacterGroup.numeric.str()
|
||||
|
||||
assert values[3].value == int(CharacterGroup.special)
|
||||
assert values[3].name == CharacterGroup.special.str()
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
struct App {
|
||||
Inner
|
||||
a string
|
||||
b string
|
||||
mut:
|
||||
|
@ -12,6 +13,8 @@ pub mut:
|
|||
h u8
|
||||
}
|
||||
|
||||
struct Inner {}
|
||||
|
||||
@['foo/bar/three']
|
||||
fn (mut app App) run() {
|
||||
}
|
||||
|
@ -85,13 +88,16 @@ fn test_comptime_for_fields() {
|
|||
assert field.name in ['d', 'e']
|
||||
}
|
||||
if field.is_mut {
|
||||
assert field.name in ['c', 'd', 'g', 'h']
|
||||
assert field.name in ['c', 'd', 'g', 'h', 'Inner']
|
||||
}
|
||||
if field.is_pub {
|
||||
assert field.name in ['e', 'f', 'g', 'h']
|
||||
assert field.name in ['e', 'f', 'g', 'h', 'Inner']
|
||||
}
|
||||
if field.is_pub && field.is_mut {
|
||||
assert field.name in ['g', 'h']
|
||||
assert field.name in ['g', 'h', 'Inner']
|
||||
}
|
||||
if field.is_embed {
|
||||
assert field.name == 'Inner'
|
||||
}
|
||||
if field.name == 'f' {
|
||||
assert sizeof(field) == 8
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
module main
|
||||
|
||||
fn func[T]() bool {
|
||||
$match T {
|
||||
u8, u16 {
|
||||
return true
|
||||
}
|
||||
$else {
|
||||
// return false
|
||||
$compile_error('fail')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_comptime_match_eval_only_true_branch() {
|
||||
assert func[u8]()
|
||||
}
|
|
@ -224,6 +224,7 @@ pub fn (mut t TypeResolver) get_comptime_selector_bool_field(field_name string)
|
|||
match field_name {
|
||||
'is_pub' { return field.is_pub }
|
||||
'is_mut' { return field.is_mut }
|
||||
'is_embed' { return field.is_embed }
|
||||
'is_shared' { return field_typ.has_flag(.shared_f) }
|
||||
'is_atomic' { return field_typ.has_flag(.atomic_f) }
|
||||
'is_option' { return field.typ.has_flag(.option) }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue