mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: optionals default value
This commit is contained in:
parent
4e64a58ac1
commit
df5faf35e5
@ -174,9 +174,9 @@ fn (v mut V) cc() {
|
|||||||
println('$path not found... building module $imp')
|
println('$path not found... building module $imp')
|
||||||
if path.ends_with('vlib/ui.o') {
|
if path.ends_with('vlib/ui.o') {
|
||||||
println('copying ui...')
|
println('copying ui...')
|
||||||
os.cp('$vdir/thirdparty/ui/ui.o', path)
|
_ = os.cp('$vdir/thirdparty/ui/ui.o', path) or { panic('error copying ui files') }
|
||||||
os.cp('$vdir/thirdparty/ui/ui.vh', v_modules_path +
|
_ = os.cp('$vdir/thirdparty/ui/ui.vh', v_modules_path +
|
||||||
'/vlib/ui.vh')
|
'/vlib/ui.vh') or { panic('error copying ui files') }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
os.system('$vexe build module vlib${os.path_separator}$imp_path')
|
os.system('$vexe build module vlib${os.path_separator}$imp_path')
|
||||||
|
@ -11,12 +11,15 @@ fn (p mut Parser) gen_or_else(pos int) string {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// returns the type of the new variable
|
// returns the type of the new variable
|
||||||
fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
|
fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
|
||||||
// Generate expression to tmp because we need its type first
|
// Generate expression to tmp because we need its type first
|
||||||
// `[typ] [name] = bool_expression();`
|
// `[typ] [name] = bool_expression();`
|
||||||
pos := p.cgen.add_placeholder()
|
pos := p.cgen.add_placeholder()
|
||||||
|
p.is_var_decl = true
|
||||||
mut typ := p.bool_expression()
|
mut typ := p.bool_expression()
|
||||||
|
p.is_var_decl = false
|
||||||
if typ.starts_with('...') { typ = typ[3..] }
|
if typ.starts_with('...') { typ = typ[3..] }
|
||||||
//p.gen('/*after expr*/')
|
//p.gen('/*after expr*/')
|
||||||
// Option check ? or {
|
// Option check ? or {
|
||||||
@ -68,10 +71,13 @@ fn (p mut Parser) gen_blank_identifier_assign() {
|
|||||||
is_indexer := p.peek() == .lsbr
|
is_indexer := p.peek() == .lsbr
|
||||||
is_fn_call, next_expr := p.is_next_expr_fn_call()
|
is_fn_call, next_expr := p.is_next_expr_fn_call()
|
||||||
pos := p.cgen.add_placeholder()
|
pos := p.cgen.add_placeholder()
|
||||||
|
p.is_var_decl = true
|
||||||
typ := p.bool_expression()
|
typ := p.bool_expression()
|
||||||
|
p.is_var_decl = false
|
||||||
if !is_indexer && !is_fn_call {
|
if !is_indexer && !is_fn_call {
|
||||||
p.error_with_token_index('assigning `$next_expr` to `_` is redundant', assign_error_tok_idx)
|
p.error_with_token_index('assigning `$next_expr` to `_` is redundant', assign_error_tok_idx)
|
||||||
}
|
}
|
||||||
|
// handle or
|
||||||
if p.tok == .key_orelse {
|
if p.tok == .key_orelse {
|
||||||
p.gen_handle_option_or_else(typ, '', pos)
|
p.gen_handle_option_or_else(typ, '', pos)
|
||||||
} else {
|
} else {
|
||||||
@ -93,6 +99,7 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
|
|||||||
p.cgen.set_placeholder(fn_call_ph, '$typ $tmp = ')
|
p.cgen.set_placeholder(fn_call_ph, '$typ $tmp = ')
|
||||||
typ = typ[7..]
|
typ = typ[7..]
|
||||||
p.genln(';')
|
p.genln(';')
|
||||||
|
or_tok_idx := p.token_idx
|
||||||
p.check(.key_orelse)
|
p.check(.key_orelse)
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
p.register_var(Var {
|
p.register_var(Var {
|
||||||
@ -107,15 +114,26 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
|
|||||||
is_mut: false
|
is_mut: false
|
||||||
is_used: true
|
is_used: true
|
||||||
})
|
})
|
||||||
|
if is_assign {
|
||||||
|
p.genln('$typ $name;')
|
||||||
|
}
|
||||||
p.genln('if (!$tmp .ok) {')
|
p.genln('if (!$tmp .ok) {')
|
||||||
p.genln('string err = $tmp . error;')
|
p.genln('string err = $tmp . error;')
|
||||||
p.genln('int errcode = $tmp . ecode;')
|
p.genln('int errcode = $tmp . ecode;')
|
||||||
p.statements()
|
last_ph := p.cgen.add_placeholder()
|
||||||
if is_assign {
|
last_typ := p.statements()
|
||||||
p.genln('$typ $name = *($typ*) $tmp . data;')
|
if is_assign && last_typ == typ {
|
||||||
|
expr_line := p.cgen.lines[p.cgen.lines.len-3]
|
||||||
|
last_expr := expr_line[last_ph..]
|
||||||
|
p.cgen.lines[p.cgen.lines.len-3] = ''
|
||||||
|
p.genln('if (!$tmp .ok) {')
|
||||||
|
p.genln('$name = $last_expr;')
|
||||||
|
p.genln('}')
|
||||||
|
} else if is_assign {
|
||||||
|
p.genln('$name = *($typ*) $tmp . data;')
|
||||||
}
|
}
|
||||||
if !p.returns && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break {
|
if !p.returns && last_typ != typ && is_assign && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break {
|
||||||
p.error('`or` block must return/exit/continue/break/panic')
|
p.error_with_token_index('`or` block must provide a default value or return/exit/continue/break/panic', or_tok_idx)
|
||||||
}
|
}
|
||||||
p.returns = false
|
p.returns = false
|
||||||
return typ
|
return typ
|
||||||
|
@ -45,6 +45,7 @@ mut:
|
|||||||
inside_return_expr bool
|
inside_return_expr bool
|
||||||
inside_unsafe bool
|
inside_unsafe bool
|
||||||
is_struct_init bool
|
is_struct_init bool
|
||||||
|
is_var_decl bool
|
||||||
if_expr_cnt int
|
if_expr_cnt int
|
||||||
for_expr_cnt int // to detect whether `continue` can be used
|
for_expr_cnt int // to detect whether `continue` can be used
|
||||||
ptr_cast bool
|
ptr_cast bool
|
||||||
@ -1700,6 +1701,7 @@ fn (p mut Parser) name_expr() string {
|
|||||||
// p.error('`$f.name` used as value')
|
// p.error('`$f.name` used as value')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn_call_ph := p.cgen.add_placeholder()
|
||||||
// println('call to fn $f.name of type $f.typ')
|
// println('call to fn $f.name of type $f.typ')
|
||||||
// TODO replace the following dirty hacks (needs ptr access to fn table)
|
// TODO replace the following dirty hacks (needs ptr access to fn table)
|
||||||
new_f := f
|
new_f := f
|
||||||
@ -1713,6 +1715,17 @@ fn (p mut Parser) name_expr() string {
|
|||||||
}
|
}
|
||||||
f = new_f
|
f = new_f
|
||||||
|
|
||||||
|
// optional function call `function() or {}`, no return assignment
|
||||||
|
is_or_else := p.tok == .key_orelse
|
||||||
|
if !p.is_var_decl && is_or_else {
|
||||||
|
f.typ = p.gen_handle_option_or_else(f.typ, '', fn_call_ph)
|
||||||
|
}
|
||||||
|
else if !p.is_var_decl && !is_or_else && !p.inside_return_expr &&
|
||||||
|
f.typ.starts_with('Option_') {
|
||||||
|
opt_type := f.typ[7..]
|
||||||
|
p.error('unhandled option type: `?$opt_type`')
|
||||||
|
}
|
||||||
|
|
||||||
// dot after a function call: `get_user().age`
|
// dot after a function call: `get_user().age`
|
||||||
if p.tok == .dot {
|
if p.tok == .dot {
|
||||||
mut typ := ''
|
mut typ := ''
|
||||||
@ -2049,11 +2062,21 @@ struct $typ.name {
|
|||||||
return field.typ
|
return field.typ
|
||||||
}
|
}
|
||||||
// method
|
// method
|
||||||
method := p.table.find_method(typ, field_name) or {
|
mut method := p.table.find_method(typ, field_name) or {
|
||||||
p.error_with_token_index('could not find method `$field_name`', fname_tidx) // should never happen
|
p.error_with_token_index('could not find method `$field_name`', fname_tidx) // should never happen
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
p.fn_call(mut method, method_ph, '', str_typ)
|
p.fn_call(mut method, method_ph, '', str_typ)
|
||||||
|
// optional method call `a.method() or {}`, no return assignment
|
||||||
|
is_or_else := p.tok == .key_orelse
|
||||||
|
if !p.is_var_decl && is_or_else {
|
||||||
|
method.typ = p.gen_handle_option_or_else(method.typ, '', method_ph)
|
||||||
|
}
|
||||||
|
else if !p.is_var_decl && !is_or_else && !p.inside_return_expr &&
|
||||||
|
method.typ.starts_with('Option_') {
|
||||||
|
opt_type := method.typ[7..]
|
||||||
|
p.error('unhandled option type: `?$opt_type`')
|
||||||
|
}
|
||||||
// Methods returning `array` should return `array_string` etc
|
// Methods returning `array` should return `array_string` etc
|
||||||
if method.typ == 'array' && typ.name.starts_with('array_') {
|
if method.typ == 'array' && typ.name.starts_with('array_') {
|
||||||
return typ.name
|
return typ.name
|
||||||
@ -3098,7 +3121,9 @@ fn (p mut Parser) if_st(is_expr bool, elif_depth int) string {
|
|||||||
var_name := p.lit
|
var_name := p.lit
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.decl_assign)
|
p.check(.decl_assign)
|
||||||
|
p.is_var_decl = true
|
||||||
option_type, expr := p.tmp_expr()// := p.bool_expression()
|
option_type, expr := p.tmp_expr()// := p.bool_expression()
|
||||||
|
p.is_var_decl = false
|
||||||
typ := option_type[7..]
|
typ := option_type[7..]
|
||||||
// Option_User tmp = get_user(1);
|
// Option_User tmp = get_user(1);
|
||||||
// if (tmp.ok) {
|
// if (tmp.ok) {
|
||||||
|
@ -46,6 +46,8 @@ fn test_defer_early_exit() {
|
|||||||
|
|
||||||
fn test_defer_option() {
|
fn test_defer_option() {
|
||||||
mut ok := Num{0}
|
mut ok := Num{0}
|
||||||
set_num_opt(mut ok)
|
set_num_opt(mut ok) or {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
assert ok.val == 1
|
assert ok.val == 1
|
||||||
}
|
}
|
||||||
|
@ -58,3 +58,15 @@ fn test_if_opt() {
|
|||||||
assert 1 == 1
|
assert 1 == 1
|
||||||
println('nice')
|
println('nice')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn for_opt_default() ?string {
|
||||||
|
return error('awww')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_opt_default() {
|
||||||
|
a := for_opt_default() or {
|
||||||
|
// panic(err)
|
||||||
|
'default'
|
||||||
|
}
|
||||||
|
assert a == 'default'
|
||||||
|
}
|
||||||
|
@ -55,7 +55,7 @@ pub fn new() &Digest {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d mut Digest) write(p_ []byte) ?int {
|
pub fn (d mut Digest) write(p_ []byte) int {
|
||||||
mut p := p_
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
|
@ -58,7 +58,7 @@ pub fn new() &Digest {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d mut Digest) write(p_ []byte) ?int {
|
pub fn (d mut Digest) write(p_ []byte) int {
|
||||||
mut p := p_
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
|
@ -92,7 +92,7 @@ pub fn new224() &Digest {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (d mut Digest) write(p_ []byte) ?int {
|
fn (d mut Digest) write(p_ []byte) int {
|
||||||
mut p := p_
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
|
@ -151,7 +151,7 @@ fn new384() &Digest {
|
|||||||
return new_digest(.sha384)
|
return new_digest(.sha384)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (d mut Digest) write(p_ []byte) ?int {
|
fn (d mut Digest) write(p_ []byte) int {
|
||||||
mut p := p_
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
|
@ -32,9 +32,9 @@ fn test_encoding_csv_reader() {
|
|||||||
fn test_encoding_csv_writer() {
|
fn test_encoding_csv_writer() {
|
||||||
mut csv_writer := csv.new_writer()
|
mut csv_writer := csv.new_writer()
|
||||||
|
|
||||||
csv_writer.write(['name', 'email', 'phone', 'other'])
|
csv_writer.write(['name', 'email', 'phone', 'other']) or {}
|
||||||
csv_writer.write(['joe', 'joe@blow.com', '0400000000', 'test'])
|
csv_writer.write(['joe', 'joe@blow.com', '0400000000', 'test']) or {}
|
||||||
csv_writer.write(['sam', 'sam@likesham.com', '0433000000', 'needs, quoting'])
|
csv_writer.write(['sam', 'sam@likesham.com', '0433000000', 'needs, quoting']) or {}
|
||||||
|
|
||||||
assert csv_writer.str() == 'name,email,phone,other\njoe,joe@blow.com,0400000000,test\nsam,sam@likesham.com,0433000000,"needs, quoting"\n'
|
assert csv_writer.str() == 'name,email,phone,other\njoe,joe@blow.com,0400000000,test\nsam,sam@likesham.com,0433000000,"needs, quoting"\n'
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ fn (req &Request) http_do(port int, method, host_name, path string) ?Response {
|
|||||||
s := req.build_request_headers(method, host_name, path)
|
s := req.build_request_headers(method, host_name, path)
|
||||||
|
|
||||||
client := net.dial( host_name, port) or { return error(err) }
|
client := net.dial( host_name, port) or { return error(err) }
|
||||||
client.send( s.str, s.len )
|
client.send( s.str, s.len ) or {}
|
||||||
for {
|
for {
|
||||||
readbytes := client.crecv( rbuffer, bufsize )
|
readbytes := client.crecv( rbuffer, bufsize )
|
||||||
if readbytes < 0 { return error('http_do error reading response. readbytes: $readbytes') }
|
if readbytes < 0 { return error('http_do error reading response. readbytes: $readbytes') }
|
||||||
if readbytes == 0 { break }
|
if readbytes == 0 { break }
|
||||||
sb.write( tos(rbuffer, readbytes) )
|
sb.write( tos(rbuffer, readbytes) )
|
||||||
}
|
}
|
||||||
client.close()
|
client.close() or {}
|
||||||
return parse_response(sb.str())
|
return parse_response(sb.str())
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,9 @@ fn test_socket() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message := 'Hello World'
|
message := 'Hello World'
|
||||||
socket.send(message.str, message.len)
|
socket.send(message.str, message.len) or {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
$if debug { println('message send: $message') }
|
$if debug { println('message send: $message') }
|
||||||
$if debug { println('send socket: $socket.sockfd') }
|
$if debug { println('send socket: $socket.sockfd') }
|
||||||
|
|
||||||
@ -24,7 +26,7 @@ fn test_socket() {
|
|||||||
|
|
||||||
assert message == received
|
assert message == received
|
||||||
|
|
||||||
server.close()
|
server.close() or {}
|
||||||
client.close()
|
client.close() or {}
|
||||||
socket.close()
|
socket.close() or {}
|
||||||
}
|
}
|
||||||
|
@ -537,7 +537,7 @@ fn parse_url(rawurl string, via_request bool) ?URL {
|
|||||||
// raw_path is a hint of the encoding of path. We don't want to set it if
|
// raw_path is a hint of the encoding of path. We don't want to set it if
|
||||||
// the default escaping of path is equivalent, to help make sure that people
|
// the default escaping of path is equivalent, to help make sure that people
|
||||||
// don't rely on it in general.
|
// don't rely on it in general.
|
||||||
_ = url.set_path(rest) or {
|
url.set_path(rest) or {
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
return url
|
return url
|
||||||
@ -974,7 +974,7 @@ pub fn (u &URL) resolve_reference(ref &URL) ?URL {
|
|||||||
// The 'absoluteURI' or 'net_path' cases.
|
// The 'absoluteURI' or 'net_path' cases.
|
||||||
// We can ignore the error from set_path since we know we provided a
|
// We can ignore the error from set_path since we know we provided a
|
||||||
// validly-escaped path.
|
// validly-escaped path.
|
||||||
url.set_path(resolve_path(ref.escaped_path(), ''))
|
url.set_path(resolve_path(ref.escaped_path(), '')) or {return error(err)}
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
if ref.opaque != '' {
|
if ref.opaque != '' {
|
||||||
@ -992,7 +992,7 @@ pub fn (u &URL) resolve_reference(ref &URL) ?URL {
|
|||||||
// The 'abs_path' or 'rel_path' cases.
|
// The 'abs_path' or 'rel_path' cases.
|
||||||
url.host = u.host
|
url.host = u.host
|
||||||
url.user = u.user
|
url.user = u.user
|
||||||
url.set_path(resolve_path(u.escaped_path(), ref.escaped_path()))
|
url.set_path(resolve_path(u.escaped_path(), ref.escaped_path())) or { return error(err) }
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import sqlite
|
|||||||
|
|
||||||
fn test_sqlite() {
|
fn test_sqlite() {
|
||||||
db := sqlite.connect('users.db')
|
db := sqlite.connect('users.db')
|
||||||
|
db.exec("drop table if exists users")
|
||||||
db.exec("create table users (id integer primary key, name text default '');")
|
db.exec("create table users (id integer primary key, name text default '');")
|
||||||
|
|
||||||
db.exec("insert into users (name) values ('Sam')")
|
db.exec("insert into users (name) values ('Sam')")
|
||||||
|
Loading…
Reference in New Issue
Block a user