Merge branch 'master' of https://github.com/vlang/v into add-rsa
commit
8f9e37a58f
|
@ -55,6 +55,9 @@ jobs:
|
|||
cd '${{env.MY_V_PATH}}'
|
||||
ls -la
|
||||
make
|
||||
## prebuild cmd/tools/builders/js_builder, to minimise the
|
||||
## chances of a sporadic "Killed" when running the tests later
|
||||
./v -b js run examples/hello_world.v
|
||||
- name: v doctor
|
||||
run: |
|
||||
cd '${{env.MY_V_PATH}}'
|
||||
|
|
|
@ -21,6 +21,7 @@ const (
|
|||
hide_warnings = '-hide-warnings' in os.args || '-w' in os.args
|
||||
show_progress = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args
|
||||
non_option_args = cmdline.only_non_options(os.args[2..])
|
||||
is_verbose = os.getenv('VERBOSE') != ''
|
||||
)
|
||||
|
||||
struct CheckResult {
|
||||
|
@ -75,7 +76,7 @@ fn main() {
|
|||
res += mdfile.check()
|
||||
}
|
||||
if res.errors == 0 && show_progress {
|
||||
term.clear_previous_line()
|
||||
clear_previous_line()
|
||||
}
|
||||
if res.warnings > 0 || res.errors > 0 || res.oks > 0 {
|
||||
println('\nWarnings: $res.warnings | Errors: $res.errors | OKs: $res.oks')
|
||||
|
@ -131,9 +132,7 @@ fn eline(file_path string, lnumber int, column int, message string) string {
|
|||
return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
|
||||
}
|
||||
|
||||
const (
|
||||
default_command = 'compile'
|
||||
)
|
||||
const default_command = 'compile'
|
||||
|
||||
struct VCodeExample {
|
||||
mut:
|
||||
|
@ -160,7 +159,7 @@ mut:
|
|||
|
||||
fn (mut f MDFile) progress(message string) {
|
||||
if show_progress {
|
||||
term.clear_previous_line()
|
||||
clear_previous_line()
|
||||
println('File: ${f.path:-30s}, Lines: ${f.lines.len:5}, $message')
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +393,7 @@ fn (mut f MDFile) debug() {
|
|||
}
|
||||
|
||||
fn cmdexecute(cmd string) int {
|
||||
verbose_println(cmd)
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code < 0 {
|
||||
return 1
|
||||
|
@ -405,6 +405,7 @@ fn cmdexecute(cmd string) int {
|
|||
}
|
||||
|
||||
fn silent_cmdexecute(cmd string) int {
|
||||
verbose_println(cmd)
|
||||
res := os.execute(cmd)
|
||||
return res.exit_code
|
||||
}
|
||||
|
@ -426,6 +427,7 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
}
|
||||
fname := os.base(f.path).replace('.md', '_md')
|
||||
uid := rand.ulid()
|
||||
cfile := os.join_path(os.temp_dir(), '${uid}.c')
|
||||
vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')
|
||||
mut should_cleanup_vfile := true
|
||||
// eprintln('>>> checking example $vfile ...')
|
||||
|
@ -438,8 +440,7 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
fmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) }
|
||||
match command {
|
||||
'compile' {
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}')
|
||||
os.rm('x.c') or {}
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors ${os.quoted_path(vfile)}')
|
||||
if res != 0 || fmt_res != 0 {
|
||||
if res != 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
|
||||
|
@ -454,9 +455,26 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
}
|
||||
oks++
|
||||
}
|
||||
'cgen' {
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
|
||||
os.rm(cfile) or {}
|
||||
if res != 0 || fmt_res != 0 {
|
||||
if res != 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, 'example failed to generate C code'))
|
||||
}
|
||||
if fmt_res != 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, 'example is not formatted'))
|
||||
}
|
||||
eprintln(vcontent)
|
||||
should_cleanup_vfile = false
|
||||
errors++
|
||||
continue
|
||||
}
|
||||
oks++
|
||||
}
|
||||
'globals' {
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o x.c ${os.quoted_path(vfile)}')
|
||||
os.rm('x.c') or {}
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
|
||||
os.rm(cfile) or {}
|
||||
if res != 0 || fmt_res != 0 {
|
||||
if res != 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals'))
|
||||
|
@ -472,7 +490,8 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
oks++
|
||||
}
|
||||
'live' {
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o x.c ${os.quoted_path(vfile)}')
|
||||
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
|
||||
os.rm(cfile) or {}
|
||||
if res != 0 || fmt_res != 0 {
|
||||
if res != 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
|
||||
|
@ -488,8 +507,8 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
oks++
|
||||
}
|
||||
'failcompile' {
|
||||
res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}')
|
||||
os.rm('x.c') or {}
|
||||
res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
|
||||
os.rm(cfile) or {}
|
||||
if res == 0 || fmt_res != 0 {
|
||||
if res == 0 {
|
||||
eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled'))
|
||||
|
@ -533,7 +552,7 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
}
|
||||
'nofmt' {}
|
||||
else {
|
||||
eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/failcompile/oksyntax/badsyntax'))
|
||||
eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/cgen/failcompile/oksyntax/badsyntax/nofmt'))
|
||||
should_cleanup_vfile = false
|
||||
errors++
|
||||
}
|
||||
|
@ -548,3 +567,16 @@ fn (mut f MDFile) check_examples() CheckResult {
|
|||
oks: oks
|
||||
}
|
||||
}
|
||||
|
||||
fn verbose_println(message string) {
|
||||
if is_verbose {
|
||||
println(message)
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_previous_line() {
|
||||
if is_verbose {
|
||||
return
|
||||
}
|
||||
term.clear_previous_line()
|
||||
}
|
||||
|
|
|
@ -259,7 +259,15 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path
|
|||
file_bak := '${file}.bak'
|
||||
os.cp(file, file_bak) or {}
|
||||
}
|
||||
mut perms_to_restore := u32(0)
|
||||
$if !windows {
|
||||
fm := os.inode(file)
|
||||
perms_to_restore = fm.bitmask()
|
||||
}
|
||||
os.mv_by_cp(formatted_file_path, file) or { panic(err) }
|
||||
$if !windows {
|
||||
os.chmod(file, int(perms_to_restore)) or { panic(err) }
|
||||
}
|
||||
eprintln('Reformatted file: $file')
|
||||
} else {
|
||||
eprintln('Already formatted file: $file')
|
||||
|
|
|
@ -13,6 +13,7 @@ Flags:
|
|||
NB: There are several special keywords, which you can put after the code fences for v.
|
||||
These are:
|
||||
compile - Default, can be omitted. The example will be compiled and formatting is verified.
|
||||
cgen - The example produces C code, which may not be compilable (when external libs are not installed). Formatting is verified.
|
||||
live - Compile hot reload examples with the ´-live´ flag set and verify formatting.
|
||||
ignore - Ignore the example, useful for examples that just use the syntax highlighting
|
||||
failcompile - Known failing compilation. Useful for examples demonstrating compiler errors.
|
||||
|
|
122
doc/docs.md
122
doc/docs.md
|
@ -163,7 +163,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
|||
|
||||
<!--
|
||||
NB: there are several special keywords, which you can put after the code fences for v:
|
||||
compile, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt
|
||||
compile, cgen, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt
|
||||
For more details, do: `v check-md`
|
||||
-->
|
||||
|
||||
|
@ -1393,7 +1393,7 @@ println(s)
|
|||
You can check the current type of a sum type using `is` and its negated form `!is`.
|
||||
|
||||
You can do it either in an `if`:
|
||||
```v
|
||||
```v cgen
|
||||
struct Abc {
|
||||
val string
|
||||
}
|
||||
|
@ -2789,38 +2789,52 @@ For more information, see [Dynamic casts](#dynamic-casts).
|
|||
|
||||
#### Interface method definitions
|
||||
|
||||
Also unlike Go, an interface may implement a method.
|
||||
These methods are not implemented by structs which implement that interface.
|
||||
Also unlike Go, an interface can have it's own methods, similar to how
|
||||
structs can have their methods. These 'interface methods' do not have
|
||||
to be implemented, by structs which implement that interface.
|
||||
They are just a convenient way to write `i.some_function()` instead of
|
||||
`some_function(i)`, similar to how struct methods can be looked at, as
|
||||
a convenience for writing `s.xyz()` instead of `xyz(s)`.
|
||||
|
||||
When a struct is wrapped in an interface that has implemented a method
|
||||
with the same name as one implemented by this struct, only the method
|
||||
implemented on the interface is called.
|
||||
N.B. This feature is NOT a "default implementation" like in C#.
|
||||
|
||||
For example, if a struct `cat` is wrapped in an interface `a`, that has
|
||||
implemented a method with the same name `speak`, as a method implemented by
|
||||
the struct, and you do `a.speak()`, *only* the interface method is called:
|
||||
|
||||
```v
|
||||
struct Cat {}
|
||||
|
||||
fn (c Cat) speak() string {
|
||||
return 'meow!'
|
||||
}
|
||||
|
||||
interface Adoptable {}
|
||||
|
||||
fn (a Adoptable) speak() string {
|
||||
return 'adopt me!'
|
||||
}
|
||||
|
||||
fn new_adoptable() Adoptable {
|
||||
return Cat{}
|
||||
struct Cat {}
|
||||
|
||||
fn (c Cat) speak() string {
|
||||
return 'meow!'
|
||||
}
|
||||
|
||||
struct Dog {}
|
||||
|
||||
fn main() {
|
||||
cat := Cat{}
|
||||
assert cat.speak() == 'meow!'
|
||||
a := new_adoptable()
|
||||
assert a.speak() == 'adopt me!'
|
||||
assert dump(cat.speak()) == 'meow!'
|
||||
//
|
||||
a := Adoptable(cat)
|
||||
assert dump(a.speak()) == 'adopt me!' // call Adoptable's `speak`
|
||||
if a is Cat {
|
||||
println(a.speak()) // meow!
|
||||
// Inside this `if` however, V knows that `a` is not just any
|
||||
// kind of Adoptable, but actually a Cat, so it will use the
|
||||
// Cat `speak`, NOT the Adoptable `speak`:
|
||||
dump(a.speak()) // meow!
|
||||
}
|
||||
//
|
||||
b := Adoptable(Dog{})
|
||||
assert dump(b.speak()) == 'adopt me!' // call Adoptable's `speak`
|
||||
// if b is Dog {
|
||||
// dump(b.speak()) // error: unknown method or field: Dog.speak
|
||||
// }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -5102,40 +5116,42 @@ For all supported options check the latest help:
|
|||
|
||||
#### `$if` condition
|
||||
```v
|
||||
// Support for multiple conditions in one branch
|
||||
$if ios || android {
|
||||
println('Running on a mobile device!')
|
||||
}
|
||||
$if linux && x64 {
|
||||
println('64-bit Linux.')
|
||||
}
|
||||
// Usage as expression
|
||||
os := $if windows { 'Windows' } $else { 'UNIX' }
|
||||
println('Using $os')
|
||||
// $else-$if branches
|
||||
$if tinyc {
|
||||
println('tinyc')
|
||||
} $else $if clang {
|
||||
println('clang')
|
||||
} $else $if gcc {
|
||||
println('gcc')
|
||||
} $else {
|
||||
println('different compiler')
|
||||
}
|
||||
$if test {
|
||||
println('testing')
|
||||
}
|
||||
// v -cg ...
|
||||
$if debug {
|
||||
println('debugging')
|
||||
}
|
||||
// v -prod ...
|
||||
$if prod {
|
||||
println('production build')
|
||||
}
|
||||
// v -d option ...
|
||||
$if option ? {
|
||||
println('custom option')
|
||||
fn main() {
|
||||
// Support for multiple conditions in one branch
|
||||
$if ios || android {
|
||||
println('Running on a mobile device!')
|
||||
}
|
||||
$if linux && x64 {
|
||||
println('64-bit Linux.')
|
||||
}
|
||||
// Usage as expression
|
||||
os := $if windows { 'Windows' } $else { 'UNIX' }
|
||||
println('Using $os')
|
||||
// $else-$if branches
|
||||
$if tinyc {
|
||||
println('tinyc')
|
||||
} $else $if clang {
|
||||
println('clang')
|
||||
} $else $if gcc {
|
||||
println('gcc')
|
||||
} $else {
|
||||
println('different compiler')
|
||||
}
|
||||
$if test {
|
||||
println('testing')
|
||||
}
|
||||
// v -cg ...
|
||||
$if debug {
|
||||
println('debugging')
|
||||
}
|
||||
// v -prod ...
|
||||
$if prod {
|
||||
println('production build')
|
||||
}
|
||||
// v -d option ...
|
||||
$if option ? {
|
||||
println('custom option')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -204,7 +204,9 @@ pub fn (mut a array) insert(i int, val voidptr) {
|
|||
panic('array.insert: index out of range (i == $i, a.len == $a.len)')
|
||||
}
|
||||
}
|
||||
a.ensure_cap(a.len + 1)
|
||||
if a.len >= a.cap {
|
||||
a.ensure_cap(a.len + 1)
|
||||
}
|
||||
unsafe {
|
||||
vmemmove(a.get_unsafe(i + 1), a.get_unsafe(i), (a.len - i) * a.element_size)
|
||||
a.set_unsafe(i, val)
|
||||
|
@ -569,7 +571,9 @@ fn (mut a array) set(i int, val voidptr) {
|
|||
}
|
||||
|
||||
fn (mut a array) push(val voidptr) {
|
||||
a.ensure_cap(a.len + 1)
|
||||
if a.len >= a.cap {
|
||||
a.ensure_cap(a.len + 1)
|
||||
}
|
||||
unsafe { vmemmove(&byte(a.data) + a.element_size * a.len, val, a.element_size) }
|
||||
a.len++
|
||||
}
|
||||
|
@ -578,16 +582,15 @@ fn (mut a array) push(val voidptr) {
|
|||
// `val` is array.data and user facing usage is `a << [1,2,3]`
|
||||
[unsafe]
|
||||
pub fn (mut a3 array) push_many(val voidptr, size int) {
|
||||
a3.ensure_cap(a3.len + size)
|
||||
if a3.data == val && !isnil(a3.data) {
|
||||
// handle `arr << arr`
|
||||
copy := a3.clone()
|
||||
a3.ensure_cap(a3.len + size)
|
||||
unsafe {
|
||||
// vmemcpy(a.data, copy.data, copy.element_size * copy.len)
|
||||
vmemcpy(a3.get_unsafe(a3.len), copy.data, a3.element_size * size)
|
||||
}
|
||||
} else {
|
||||
a3.ensure_cap(a3.len + size)
|
||||
if !isnil(a3.data) && !isnil(val) {
|
||||
unsafe { vmemcpy(a3.get_unsafe(a3.len), val, a3.element_size * size) }
|
||||
}
|
||||
|
|
|
@ -1166,7 +1166,9 @@ fn test_array_int_pop() {
|
|||
assert a.len == 3
|
||||
assert z == 4
|
||||
x1 := a.pop()
|
||||
println(x1)
|
||||
x2 := a.pop()
|
||||
println(x2)
|
||||
final := a.pop()
|
||||
assert final == 1
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ fn test_hex() {
|
|||
b := 1234
|
||||
assert b.hex() == '4d2'
|
||||
b1 := -1
|
||||
println(b1)
|
||||
// assert b1.hex() == 'ffffffff'
|
||||
// unsigned tests
|
||||
// assert u8(12).hex() == '0c'
|
||||
|
|
|
@ -372,6 +372,9 @@ fn test_map_assign() {
|
|||
'r': u16(6)
|
||||
's': 5
|
||||
}}
|
||||
println(a)
|
||||
println(b)
|
||||
println(c)
|
||||
}
|
||||
|
||||
fn test_postfix_op_directly() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import strings
|
||||
// import strings
|
||||
|
||||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
|
@ -636,6 +636,7 @@ fn test_for_loop_two() {
|
|||
|
||||
fn test_quote() {
|
||||
a := `'`
|
||||
println(a)
|
||||
println('testing double quotes')
|
||||
b := 'hi'
|
||||
assert b == 'hi'
|
||||
|
@ -727,6 +728,7 @@ fn test_raw() {
|
|||
|
||||
fn test_raw_with_quotes() {
|
||||
raw := r"some'" + r'"thing' // " should be escaped in the generated C code
|
||||
println(raw)
|
||||
// assert raw[0] == `s`
|
||||
// assert raw[5] == `"`
|
||||
// assert raw[6] == `t`
|
||||
|
|
|
@ -7,7 +7,7 @@ user's keyboard/mouse input.
|
|||
|
||||
## Example:
|
||||
|
||||
```v
|
||||
```v cgen
|
||||
module main
|
||||
|
||||
import gg
|
||||
|
|
|
@ -20,6 +20,22 @@ pub:
|
|||
execute bool
|
||||
}
|
||||
|
||||
// bitmask returns a 3 bit sequence in the order RWE where
|
||||
// the bit is set to 1 if the value is true or 0 otherwise.
|
||||
pub fn (p FilePermission) bitmask() u32 {
|
||||
mut mask := u32(0)
|
||||
if p.read {
|
||||
mask |= 4
|
||||
}
|
||||
if p.write {
|
||||
mask |= 2
|
||||
}
|
||||
if p.execute {
|
||||
mask |= 1
|
||||
}
|
||||
return mask
|
||||
}
|
||||
|
||||
struct FileMode {
|
||||
pub:
|
||||
typ FileType
|
||||
|
@ -28,6 +44,12 @@ pub:
|
|||
others FilePermission
|
||||
}
|
||||
|
||||
// bitmask returns a 9 bit sequence in the order owner + group + others.
|
||||
// This is a valid bitmask to use with `os.chmod`.
|
||||
pub fn (m FileMode) bitmask() u32 {
|
||||
return m.owner.bitmask() << 6 | m.group.bitmask() << 3 | m.others.bitmask()
|
||||
}
|
||||
|
||||
// inode returns the mode of the file/inode containing inode type and permission information
|
||||
// it supports windows for regular files but it doesn't matter if you use owner, group or others when checking permissions on windows
|
||||
pub fn inode(path string) FileMode {
|
||||
|
|
|
@ -41,3 +41,16 @@ fn test_inode_file_owner_permission() {
|
|||
assert mode.owner.write
|
||||
assert !mode.owner.execute
|
||||
}
|
||||
|
||||
fn test_inode_file_permissions_bitmask() {
|
||||
if user_os() == 'windows' {
|
||||
println('> skipping ${@FN} on windows')
|
||||
return
|
||||
}
|
||||
filename := './test3.txt'
|
||||
mut file := open_file(filename, 'w', 0o641) or { return }
|
||||
file.close()
|
||||
mode := inode(filename)
|
||||
rm(filename) or {}
|
||||
assert mode.bitmask() == 0o641
|
||||
}
|
||||
|
|
|
@ -2024,6 +2024,11 @@ pub fn (mut re RE) match_base(in_txt &byte, in_txt_len int) (int, int) {
|
|||
|
||||
re.prog[state.pc].group_rep++ // increase repetitions
|
||||
// println("GROUP $group_index END ${re.prog[state.pc].group_rep}")
|
||||
if re.prog[state.pc].group_rep > in_txt_len - 1 {
|
||||
m_state = .ist_quant_ng
|
||||
continue
|
||||
}
|
||||
|
||||
m_state = .ist_quant_pg
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -160,6 +160,11 @@ match_test_suite = [
|
|||
TestItem{"a", r"\S+",0,1},
|
||||
TestItem{"aaaa", r"\S+",0,4},
|
||||
TestItem{"aaaa ", r"\S+",0,4},
|
||||
|
||||
// multiple dot char
|
||||
TestItem{"aba", r"a*(b*)*a",0,3},
|
||||
TestItem{"/*x*/", r"/\**(.*)\**/",0,5},
|
||||
TestItem{"/*x*/", r"/*(.*)*/",0,5},
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -591,6 +596,21 @@ fn test_regex_func(){
|
|||
}
|
||||
}
|
||||
|
||||
fn my_repl_1(re regex.RE, in_txt string, start int, end int) string {
|
||||
s0 := re.get_group_by_id(in_txt,0)
|
||||
println("[$start, $end] => ${s0}")
|
||||
return "a" + s0.to_upper()
|
||||
}
|
||||
|
||||
fn test_regex_func_replace1(){
|
||||
txt := "abbabbbabbbbaabba"
|
||||
query := r"a(b+)"
|
||||
mut re := regex.regex_opt(query) or { panic(err) }
|
||||
result := re.replace_by_fn(txt, my_repl_1)
|
||||
|
||||
assert result == "aBBaBBBaBBBBaaBBa"
|
||||
}
|
||||
|
||||
fn my_repl(re regex.RE, in_txt string, start int, end int) string {
|
||||
s0 := re.get_group_by_id(in_txt,0)[0..1] + "X"
|
||||
s1 := re.get_group_by_id(in_txt,1)[0..1] + "X"
|
||||
|
@ -598,7 +618,6 @@ fn my_repl(re regex.RE, in_txt string, start int, end int) string {
|
|||
return "${s0}${s1}${s2}"
|
||||
}
|
||||
|
||||
|
||||
// test regex replace function
|
||||
fn test_regex_func_replace(){
|
||||
filler := "E il primo dei tre regni dell'Oltretomba cristiano visitato da Dante nel corso del viaggio, con la guida di Virgilio."
|
||||
|
|
|
@ -212,7 +212,7 @@ pub fn (mut re RE) find(in_txt string) (int, int) {
|
|||
[direct_array_access]
|
||||
pub fn (mut re RE) find_from(in_txt string, start int) (int, int) {
|
||||
old_flag := re.flag
|
||||
re.flag |= f_src // enable search mode
|
||||
// re.flag |= f_src // enable search mode
|
||||
|
||||
mut i := start
|
||||
if i < 0 {
|
||||
|
|
|
@ -11,7 +11,7 @@ Each `.h` file in the sokol source code is well-documented as can be seen here:
|
|||
|
||||
## Example from `@VROOTDIR/examples/sokol/sounds/simple_sin_tones.v`:
|
||||
|
||||
```v
|
||||
```v cgen
|
||||
import time
|
||||
import math
|
||||
import sokol.audio
|
||||
|
|
|
@ -446,6 +446,18 @@ pub fn (t &Table) find_method_with_embeds(sym &TypeSymbol, method_name string) ?
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (t &Table) get_embed_methods(sym &TypeSymbol) []Fn {
|
||||
mut methods := []Fn{}
|
||||
if sym.info is Struct {
|
||||
for embed in sym.info.embeds {
|
||||
embed_sym := t.sym(embed)
|
||||
methods << embed_sym.methods
|
||||
methods << t.get_embed_methods(embed_sym)
|
||||
}
|
||||
}
|
||||
return methods
|
||||
}
|
||||
|
||||
fn (t &Table) register_aggregate_field(mut sym TypeSymbol, name string) ?StructField {
|
||||
if sym.kind != .aggregate {
|
||||
t.panic('Unexpected type symbol: $sym.kind')
|
||||
|
@ -1428,7 +1440,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
if typ == 0 {
|
||||
return none
|
||||
}
|
||||
return typ.derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if typ.has_flag(.generic) {
|
||||
return typ.derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return typ.derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
match mut sym.info {
|
||||
Array {
|
||||
|
@ -1443,7 +1459,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
}
|
||||
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
|
||||
idx := t.find_or_register_array_with_dims(typ, dims)
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if typ.has_flag(.generic) {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
ArrayFixed {
|
||||
|
@ -1451,7 +1471,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
concrete_types)
|
||||
{
|
||||
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{})
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if typ.has_flag(.generic) {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
Chan {
|
||||
|
@ -1459,16 +1483,24 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
concrete_types)
|
||||
{
|
||||
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if typ.has_flag(.generic) {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
FnType {
|
||||
mut func := sym.info.func
|
||||
mut has_generic := false
|
||||
if func.return_type.has_flag(.generic) {
|
||||
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names,
|
||||
concrete_types)
|
||||
{
|
||||
func.return_type = typ
|
||||
if typ.has_flag(.generic) {
|
||||
has_generic = true
|
||||
}
|
||||
}
|
||||
}
|
||||
func.params = func.params.clone()
|
||||
|
@ -1478,12 +1510,19 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
concrete_types)
|
||||
{
|
||||
param.typ = typ
|
||||
if typ.has_flag(.generic) {
|
||||
has_generic = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func.name = ''
|
||||
idx := t.find_or_register_fn_type('', func, true, false)
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if has_generic {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
MultiReturn {
|
||||
mut types := []Type{}
|
||||
|
@ -1498,7 +1537,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
}
|
||||
if type_changed {
|
||||
idx := t.find_or_register_multi_return(types)
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if types.any(it.has_flag(.generic)) {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
Map {
|
||||
|
@ -1519,7 +1562,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
}
|
||||
if type_changed {
|
||||
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
if unwrapped_key_type.has_flag(.generic) || unwrapped_value_type.has_flag(.generic) {
|
||||
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
|
||||
} else {
|
||||
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
Struct, Interface, SumType {
|
||||
|
|
|
@ -963,6 +963,13 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
if func.generic_names.len > 0 {
|
||||
if has_generic {
|
||||
if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
|
||||
node.concrete_types)
|
||||
{
|
||||
if typ.has_flag(.generic) {
|
||||
node.return_type = typ
|
||||
}
|
||||
}
|
||||
return node.return_type
|
||||
} else if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
|
||||
concrete_types)
|
||||
|
|
|
@ -2471,10 +2471,8 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||
}
|
||||
// Generic dereferencing logic
|
||||
neither_void := ast.voidptr_type !in [got_type, expected_type]
|
||||
to_shared := expected_type.has_flag(.shared_f) && !got_type_raw.has_flag(.shared_f)
|
||||
&& !expected_type.has_flag(.optional)
|
||||
// from_shared := got_type_raw.has_flag(.shared_f) && !expected_type.has_flag(.shared_f)
|
||||
if to_shared {
|
||||
if expected_type.has_flag(.shared_f) && !got_type_raw.has_flag(.shared_f)
|
||||
&& !expected_type.has_flag(.optional) {
|
||||
shared_styp := exp_styp[0..exp_styp.len - 1] // `shared` implies ptr, so eat one `*`
|
||||
if got_type_raw.is_ptr() {
|
||||
g.error('cannot convert reference to `shared`', expr.pos())
|
||||
|
@ -2492,6 +2490,13 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||
g.is_shared = old_is_shared
|
||||
g.writeln('}, sizeof($shared_styp))')
|
||||
return
|
||||
} else if got_type_raw.has_flag(.shared_f) && !expected_type.has_flag(.shared_f) {
|
||||
if expected_type.is_ptr() {
|
||||
g.write('&')
|
||||
}
|
||||
g.expr(expr)
|
||||
g.write('->val')
|
||||
return
|
||||
}
|
||||
if got_is_ptr && !expected_is_ptr && neither_void && exp_sym.kind != .placeholder
|
||||
&& expr !is ast.InfixExpr {
|
||||
|
@ -3604,10 +3609,15 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
|||
}
|
||||
// struct embedding
|
||||
if sym.info in [ast.Struct, ast.Aggregate] {
|
||||
for embed in node.from_embed_types {
|
||||
for i, embed in node.from_embed_types {
|
||||
embed_sym := g.table.sym(embed)
|
||||
embed_name := embed_sym.embed_name()
|
||||
if node.expr_type.is_ptr() {
|
||||
is_left_ptr := if i == 0 {
|
||||
node.expr_type.is_ptr()
|
||||
} else {
|
||||
node.from_embed_types[i - 1].is_ptr()
|
||||
}
|
||||
if is_left_ptr {
|
||||
g.write('->')
|
||||
} else {
|
||||
g.write('.')
|
||||
|
@ -6310,10 +6320,6 @@ fn (mut g Gen) size_of(node ast.SizeOf) {
|
|||
g.write('sizeof(${util.no_dots(styp)})')
|
||||
}
|
||||
|
||||
fn (g &Gen) is_importing_os() bool {
|
||||
return 'os' in g.table.imports
|
||||
}
|
||||
|
||||
fn (mut g Gen) go_expr(node ast.GoExpr) {
|
||||
line := g.go_before_stmt(0)
|
||||
mut handle := ''
|
||||
|
@ -6797,16 +6803,13 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x)
|
|||
}
|
||||
else {}
|
||||
}
|
||||
if st_sym.info is ast.Struct {
|
||||
for embed in st_sym.info.embeds {
|
||||
embed_sym := g.table.sym(embed)
|
||||
for embed_method in embed_sym.methods {
|
||||
if embed_method.name !in method_names {
|
||||
methods << embed_method
|
||||
}
|
||||
}
|
||||
t_methods := g.table.get_embed_methods(st_sym)
|
||||
for t_method in t_methods {
|
||||
if t_method.name !in method_names {
|
||||
methods << t_method
|
||||
}
|
||||
}
|
||||
|
||||
for method in methods {
|
||||
mut name := method.name
|
||||
if inter_info.parent_type.has_flag(.generic) {
|
||||
|
@ -6834,6 +6837,7 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x)
|
|||
styp := g.cc_type(method.params[0].typ, true)
|
||||
mut method_call := '${styp}_$name'
|
||||
if !method.params[0].typ.is_ptr() {
|
||||
method_call = '${cctype}_$name'
|
||||
// inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); }
|
||||
iwpostfix := '_Interface_${interface_name}_method_wrapper'
|
||||
methods_wrapper.write_string('static inline ${g.typ(method.return_type)} ${cctype}_$name${iwpostfix}(')
|
||||
|
@ -6865,9 +6869,13 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x)
|
|||
embed_sym := g.table.sym(embed_types.last())
|
||||
method_name := '${embed_sym.cname}_$method.name'
|
||||
methods_wrapper.write_string('${method_name}(${fargs[0]}')
|
||||
for embed in embed_types {
|
||||
for idx_embed, embed in embed_types {
|
||||
esym := g.table.sym(embed)
|
||||
methods_wrapper.write_string('->$esym.embed_name()')
|
||||
if idx_embed == 0 || embed_types[idx_embed - 1].is_any_kind_of_pointer() {
|
||||
methods_wrapper.write_string('->$esym.embed_name()')
|
||||
} else {
|
||||
methods_wrapper.write_string('.$esym.embed_name()')
|
||||
}
|
||||
}
|
||||
methods_wrapper.writeln('${fargs[1..].join(', ')});')
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
fn test_generics_with_complex_nested_generics_type() {
|
||||
mut buf := []byte{}
|
||||
initial<string, u64>(buf)
|
||||
}
|
||||
|
||||
fn initial<K, V>(buf []byte) map[K]V {
|
||||
mut ret := map[K]V{}
|
||||
for _ in 0 .. 3 {
|
||||
k := get<K>(buf)
|
||||
v := get<V>(buf)
|
||||
ret[k] = v
|
||||
}
|
||||
println(ret)
|
||||
assert '$ret' == "{'get': 22}"
|
||||
return ret
|
||||
}
|
||||
|
||||
fn get<T>(buf []byte) T {
|
||||
$if T is string {
|
||||
return buf.bytestr() + 'get'
|
||||
} $else $if T is u64 {
|
||||
return u64(22)
|
||||
} $else {
|
||||
panic('oops!')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
fn test_interface_with_multi_nested_embed() {
|
||||
mut win := &Window{}
|
||||
mut ll := &LinearLayout{}
|
||||
mut lbl := &Label{
|
||||
x: 10
|
||||
y: 20
|
||||
}
|
||||
|
||||
ll.add(mut lbl)
|
||||
win.add(mut ll)
|
||||
|
||||
win.init()
|
||||
}
|
||||
|
||||
[heap]
|
||||
pub struct Window {
|
||||
mut:
|
||||
initables []&Initable
|
||||
}
|
||||
|
||||
interface Initable {
|
||||
mut:
|
||||
init(&Window)
|
||||
}
|
||||
|
||||
pub fn (mut w Window) add(mut initable Initable) {
|
||||
w.initables << initable
|
||||
}
|
||||
|
||||
interface Container {
|
||||
mut:
|
||||
layout()
|
||||
}
|
||||
|
||||
fn (mut w Window) init() {
|
||||
for wd in w.initables {
|
||||
if mut wd is Container {
|
||||
mut c := wd as Container
|
||||
c.layout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Rect {
|
||||
mut:
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
pub fn (r Rect) get_pos() (int, int) {
|
||||
return r.x, r.y
|
||||
}
|
||||
|
||||
pub struct LayoutBase {
|
||||
Rect
|
||||
}
|
||||
|
||||
pub struct Base {
|
||||
LayoutBase
|
||||
}
|
||||
|
||||
pub fn (mut b Base) init(window &Window) {}
|
||||
|
||||
[heap]
|
||||
pub struct Label {
|
||||
Base
|
||||
}
|
||||
|
||||
pub interface Layoutable {
|
||||
get_pos() (int, int)
|
||||
}
|
||||
|
||||
[heap]
|
||||
pub struct LinearLayout {
|
||||
Base
|
||||
mut:
|
||||
layoutables []Layoutable
|
||||
}
|
||||
|
||||
pub fn (mut ll LinearLayout) add(mut l Layoutable) {
|
||||
ll.layoutables << l
|
||||
}
|
||||
|
||||
pub fn (mut ll LinearLayout) layout() {
|
||||
for mut wl in ll.layoutables {
|
||||
x, y := wl.get_pos()
|
||||
println('$x, $y')
|
||||
assert x == 10
|
||||
assert y == 20
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
fn test_interface_with_multi_nested_embed() {
|
||||
mut ll := &LinearLayout{}
|
||||
mut lbl := &Label{
|
||||
x: 10
|
||||
y: 20
|
||||
}
|
||||
ll.add(mut lbl)
|
||||
|
||||
println(ll)
|
||||
|
||||
assert ll.x == 10
|
||||
assert ll.y == 20
|
||||
}
|
||||
|
||||
pub struct Rect {
|
||||
mut:
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
pub fn (r Rect) get_pos() (int, int) {
|
||||
return r.x, r.y
|
||||
}
|
||||
|
||||
pub struct LayoutBase {
|
||||
Rect
|
||||
}
|
||||
|
||||
pub struct Base {
|
||||
LayoutBase
|
||||
}
|
||||
|
||||
pub fn (mut b Base) init() {}
|
||||
|
||||
[heap]
|
||||
pub struct Label {
|
||||
Base
|
||||
}
|
||||
|
||||
pub interface Layoutable {
|
||||
get_pos() (int, int)
|
||||
mut:
|
||||
init()
|
||||
}
|
||||
|
||||
[heap]
|
||||
pub struct LinearLayout {
|
||||
Base
|
||||
mut:
|
||||
layoutables []Layoutable
|
||||
}
|
||||
|
||||
pub fn (mut ll LinearLayout) add(mut l Layoutable) {
|
||||
x, y := l.get_pos()
|
||||
ll.x += x
|
||||
ll.y += y
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
struct AA {
|
||||
b shared BB
|
||||
}
|
||||
|
||||
struct BB {
|
||||
a &int
|
||||
}
|
||||
|
||||
struct CC {
|
||||
a BB
|
||||
}
|
||||
|
||||
fn test_struct_shared_field_init() {
|
||||
a := 3
|
||||
table := &AA{
|
||||
b: BB{&a}
|
||||
}
|
||||
c := CC{
|
||||
a: table.b
|
||||
}
|
||||
assert *c.a.a == 3
|
||||
}
|
|
@ -7,6 +7,7 @@ import io
|
|||
|
||||
const (
|
||||
sport = 12380
|
||||
localserver = 'localhost:$sport'
|
||||
exit_after_time = 12000 // milliseconds
|
||||
vexe = os.getenv('VEXE')
|
||||
vweb_logfile = os.getenv('VWEB_LOGFILE')
|
||||
|
@ -116,7 +117,7 @@ fn assert_common_http_headers(x http.Response) ? {
|
|||
}
|
||||
|
||||
fn test_http_client_index() ? {
|
||||
x := http.get('http://127.0.0.1:$sport/') or { panic(err) }
|
||||
x := http.get('http://$localserver/') or { panic(err) }
|
||||
assert_common_http_headers(x) ?
|
||||
assert x.header.get(.content_type) ? == 'text/plain'
|
||||
assert x.text == 'Welcome to VWeb'
|
||||
|
@ -124,9 +125,9 @@ fn test_http_client_index() ? {
|
|||
|
||||
fn test_http_client_404() ? {
|
||||
url_404_list := [
|
||||
'http://127.0.0.1:$sport/zxcnbnm',
|
||||
'http://127.0.0.1:$sport/JHKAJA',
|
||||
'http://127.0.0.1:$sport/unknown',
|
||||
'http://$localserver/zxcnbnm',
|
||||
'http://$localserver/JHKAJA',
|
||||
'http://$localserver/unknown',
|
||||
]
|
||||
for url in url_404_list {
|
||||
res := http.get(url) or { panic(err) }
|
||||
|
@ -135,39 +136,39 @@ fn test_http_client_404() ? {
|
|||
}
|
||||
|
||||
fn test_http_client_simple() ? {
|
||||
x := http.get('http://127.0.0.1:$sport/simple') or { panic(err) }
|
||||
x := http.get('http://$localserver/simple') or { panic(err) }
|
||||
assert_common_http_headers(x) ?
|
||||
assert x.header.get(.content_type) ? == 'text/plain'
|
||||
assert x.text == 'A simple result'
|
||||
}
|
||||
|
||||
fn test_http_client_html_page() ? {
|
||||
x := http.get('http://127.0.0.1:$sport/html_page') or { panic(err) }
|
||||
x := http.get('http://$localserver/html_page') or { panic(err) }
|
||||
assert_common_http_headers(x) ?
|
||||
assert x.header.get(.content_type) ? == 'text/html'
|
||||
assert x.text == '<h1>ok</h1>'
|
||||
}
|
||||
|
||||
fn test_http_client_settings_page() ? {
|
||||
x := http.get('http://127.0.0.1:$sport/bilbo/settings') or { panic(err) }
|
||||
x := http.get('http://$localserver/bilbo/settings') or { panic(err) }
|
||||
assert_common_http_headers(x) ?
|
||||
assert x.text == 'username: bilbo'
|
||||
//
|
||||
y := http.get('http://127.0.0.1:$sport/kent/settings') or { panic(err) }
|
||||
y := http.get('http://$localserver/kent/settings') or { panic(err) }
|
||||
assert_common_http_headers(y) ?
|
||||
assert y.text == 'username: kent'
|
||||
}
|
||||
|
||||
fn test_http_client_user_repo_settings_page() ? {
|
||||
x := http.get('http://127.0.0.1:$sport/bilbo/gostamp/settings') or { panic(err) }
|
||||
x := http.get('http://$localserver/bilbo/gostamp/settings') or { panic(err) }
|
||||
assert_common_http_headers(x) ?
|
||||
assert x.text == 'username: bilbo | repository: gostamp'
|
||||
//
|
||||
y := http.get('http://127.0.0.1:$sport/kent/golang/settings') or { panic(err) }
|
||||
y := http.get('http://$localserver/kent/golang/settings') or { panic(err) }
|
||||
assert_common_http_headers(y) ?
|
||||
assert y.text == 'username: kent | repository: golang'
|
||||
//
|
||||
z := http.get('http://127.0.0.1:$sport/missing/golang/settings') or { panic(err) }
|
||||
z := http.get('http://$localserver/missing/golang/settings') or { panic(err) }
|
||||
assert z.status() == .not_found
|
||||
}
|
||||
|
||||
|
@ -182,7 +183,7 @@ fn test_http_client_json_post() ? {
|
|||
age: 123
|
||||
}
|
||||
json_for_ouser := json.encode(ouser)
|
||||
mut x := http.post_json('http://127.0.0.1:$sport/json_echo', json_for_ouser) or { panic(err) }
|
||||
mut x := http.post_json('http://$localserver/json_echo', json_for_ouser) or { panic(err) }
|
||||
$if debug_net_socket_client ? {
|
||||
eprintln('/json_echo endpoint response: $x')
|
||||
}
|
||||
|
@ -191,7 +192,7 @@ fn test_http_client_json_post() ? {
|
|||
nuser := json.decode(User, x.text) or { User{} }
|
||||
assert '$ouser' == '$nuser'
|
||||
//
|
||||
x = http.post_json('http://127.0.0.1:$sport/json', json_for_ouser) or { panic(err) }
|
||||
x = http.post_json('http://$localserver/json', json_for_ouser) or { panic(err) }
|
||||
$if debug_net_socket_client ? {
|
||||
eprintln('/json endpoint response: $x')
|
||||
}
|
||||
|
@ -213,7 +214,7 @@ $contents\r
|
|||
--$boundary--\r
|
||||
'
|
||||
mut x := http.fetch(
|
||||
url: 'http://127.0.0.1:$sport/form_echo'
|
||||
url: 'http://$localserver/form_echo'
|
||||
method: .post
|
||||
header: http.new_header(
|
||||
key: .content_type
|
||||
|
@ -228,7 +229,7 @@ $contents\r
|
|||
}
|
||||
|
||||
fn test_http_client_shutdown_does_not_work_without_a_cookie() {
|
||||
x := http.get('http://127.0.0.1:$sport/shutdown') or {
|
||||
x := http.get('http://$localserver/shutdown') or {
|
||||
assert err.msg == ''
|
||||
return
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ fn testsuite_end() {
|
|||
// This test is guaranteed to be called last.
|
||||
// It sends a request to the server to shutdown.
|
||||
x := http.fetch(
|
||||
url: 'http://127.0.0.1:$sport/shutdown'
|
||||
url: 'http://$localserver/shutdown'
|
||||
method: .get
|
||||
cookies: {
|
||||
'skey': 'superman'
|
||||
|
@ -268,7 +269,7 @@ fn simple_tcp_client(config SimpleTcpClientConfig) ?string {
|
|||
mut tries := 0
|
||||
for tries < config.retries {
|
||||
tries++
|
||||
client = net.dial_tcp('127.0.0.1:$sport') or {
|
||||
client = net.dial_tcp(localserver) or {
|
||||
if tries > config.retries {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -43,9 +43,8 @@ fn main() {
|
|||
timeout: timeout
|
||||
global_config: config
|
||||
}
|
||||
eprintln('>> webserver: started on http://127.0.0.1:$app.port/ , with maximum runtime of $app.timeout milliseconds.')
|
||||
// vweb.run<App>(mut app, http_port)
|
||||
vweb.run(app, http_port)
|
||||
eprintln('>> webserver: started on http://localhost:$app.port/ , with maximum runtime of $app.timeout milliseconds.')
|
||||
vweb.run_at(app, 'localhost', http_port)
|
||||
}
|
||||
|
||||
// pub fn (mut app App) init_server() {
|
||||
|
|
|
@ -376,10 +376,16 @@ interface DbInterface {
|
|||
db voidptr
|
||||
}
|
||||
|
||||
// run_app
|
||||
[manualfree]
|
||||
// run - start a new VWeb server, listening to all available addresses, at the specified `port`
|
||||
pub fn run<T>(global_app &T, port int) {
|
||||
mut l := net.listen_tcp(.ip6, ':$port') or { panic('failed to listen $err.code $err') }
|
||||
run_at<T>(global_app, '', port)
|
||||
}
|
||||
|
||||
// run_at - start a new VWeb server, listening only on a specific address `host`, at the specified `port`
|
||||
// Example: `vweb.run_at(app, 'localhost', 8099)`
|
||||
[manualfree]
|
||||
pub fn run_at<T>(global_app &T, host string, port int) {
|
||||
mut l := net.listen_tcp(.ip, '$host:$port') or { panic('failed to listen $err.code $err') }
|
||||
|
||||
// Parsing methods attributes
|
||||
mut routes := map[string]Route{}
|
||||
|
|
Loading…
Reference in New Issue