generate `.str()` for all arrays

pull/1576/head
Alexander Medvednikov 2019-08-10 23:02:48 +02:00
parent f628d6d35d
commit 8c3475b902
9 changed files with 92 additions and 42 deletions

View File

@ -236,3 +236,30 @@ fn (p mut Parser) comptime_method_call(typ Type) {
} }
} }
fn (p mut Parser) gen_array_str(typ mut Type) {
typ.add_method(Fn{
name: 'str',
typ: 'string'
args: [Var{typ: typ.name, is_arg:true}]
is_method: true
receiver_typ: typ.name
})
t := typ.name
elm_type := t.right(6)
p.cgen.fns << '
string ${t}_str($t a) {
strings__Builder sb = strings__new_builder(a.len * 3);
strings__Builder_write(&sb, tos2("[")) ;
for (int i = 0; i < a.len; i++) {
strings__Builder_write(&sb, ${elm_type}_str( (($elm_type *) a.data)[i]));
if (i < a.len - 1) {
strings__Builder_write(&sb, tos2(", ")) ;
}
}
strings__Builder_write(&sb, tos2("]")) ;
return strings__Builder_str(sb);
} '
}

View File

@ -794,8 +794,15 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
// If `arg` is mutable, the caller needs to provide `mut`: // If `arg` is mutable, the caller needs to provide `mut`:
// `mut numbers := [1,2,3]; reverse(mut numbers);` // `mut numbers := [1,2,3]; reverse(mut numbers);`
if arg.is_mut { if arg.is_mut {
if p.tok != .key_mut { if p.tok != .key_mut && p.tok == .name {
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name(...mut a...)`') mut dots_example := 'mut $p.lit'
if i > 0 {
dots_example = '.., ' + dots_example
}
if i < f.args.len - 1 {
dots_example = dots_example + ',..'
}
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name($dots_example)`')
} }
if p.peek() != .name { if p.peek() != .name {
p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`') p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`')
@ -831,6 +838,13 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
} }
// Make sure this type has a `str()` method // Make sure this type has a `str()` method
if !T.has_method('str') { if !T.has_method('str') {
// Arrays have automatic `str()` methods
if T.name.starts_with('array_') {
p.gen_array_str(mut T)
p.cgen.set_placeholder(ph, '${typ}_str(')
p.gen(')')
continue
}
error_msg := ('`$typ` needs to have method `str() string` to be printable') error_msg := ('`$typ` needs to have method `str() string` to be printable')
if T.fields.len > 0 { if T.fields.len > 0 {
mut index := p.cgen.cur_line.len - 1 mut index := p.cgen.cur_line.len - 1

View File

@ -793,7 +793,7 @@ fn (p mut Parser) error(s string) {
p.cgen.save() p.cgen.save()
// V git pull hint // V git pull hint
cur_path := os.getwd() cur_path := os.getwd()
if !p.pref.is_repl && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){ if !p.pref.is_repl && !p.pref.is_test && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){
println('\n=========================') println('\n=========================')
println('It looks like you are building V. It is being frequently updated every day.') println('It looks like you are building V. It is being frequently updated every day.')
println('If you didn\'t modify the compiler\'s code, most likely there was a change that ') println('If you didn\'t modify the compiler\'s code, most likely there was a change that ')
@ -1102,7 +1102,7 @@ fn (p mut Parser) vh_genln(s string) {
} }
fn (p mut Parser) statement(add_semi bool) string { fn (p mut Parser) statement(add_semi bool) string {
if(p.returns) { if p.returns { //&& !p.is_vweb {
p.error('unreachable code') p.error('unreachable code')
} }
p.cgen.is_tmp = false p.cgen.is_tmp = false
@ -1780,7 +1780,12 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
//println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}') //println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}')
//} //}
has_field := p.table.type_has_field(typ, field_name) has_field := p.table.type_has_field(typ, field_name)
has_method := p.table.type_has_method(typ, field_name) mut has_method := p.table.type_has_method(typ, field_name)
// generate `.str()`
if !has_method && field_name == 'str' && typ.name.starts_with('array_') {
p.gen_array_str(mut typ)
has_method = true
}
if !typ.is_c && !has_field && !has_method && !p.first_pass() { if !typ.is_c && !has_field && !has_method && !p.first_pass() {
if typ.name.starts_with('Option_') { if typ.name.starts_with('Option_') {
opt_type := typ.name.right(7) opt_type := typ.name.right(7)

View File

@ -1,3 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module main module main
import strings import strings
@ -29,7 +33,7 @@ fn (p mut Parser) select_query(fn_ph int) string {
} }
for field in typ.fields { for field in typ.fields {
//println('registering sql field var $field.name') //println('registering sql field var $field.name')
p.cur_fn.register_var({ field | is_used:true}) p.cur_fn.register_var({ field | is_used:true })
} }
q += table_name q += table_name
// `where` statement // `where` statement

View File

@ -60,6 +60,7 @@ mut:
// It allows having things like `fn (f Foo) bar()` before `Foo` is defined. // It allows having things like `fn (f Foo) bar()` before `Foo` is defined.
// This information is needed in the first pass. // This information is needed in the first pass.
is_placeholder bool is_placeholder bool
gen_str bool // needs `.str()` method generation
} }
// For debugging types // For debugging types
@ -434,7 +435,7 @@ fn (t mut Type) add_gen_type(type_name string) {
} }
*/ */
fn (p &Parser) find_type(name string) *Type { fn (p &Parser) find_type(name string) &Type {
typ := p.table.find_type(name) typ := p.table.find_type(name)
if typ.name.len == 0 { if typ.name.len == 0 {
return p.table.find_type(p.prepend_mod(name)) return p.table.find_type(p.prepend_mod(name))

View File

@ -1,14 +1,14 @@
fn foo(a mut []int) { fn foo(b int, a mut []int) {
a[0] = 7 a[0] = 7
a << 4 a << 4
} }
// TODO // TODO
fn test_mut() { fn test_mut() {
mut a := [1,2,3] mut numbers := [1,2,3]
foo(mut a) foo(7, numbers)
//assert a.len == 4 //assert a.len == 4
assert a[0] == 7 assert numbers[0] == 7
//assert a[3] == 4 //assert a[3] == 4
n := 1 n := 1

View File

@ -0,0 +1,16 @@
struct Foo {
a int
}
fn test_array_str() {
f := Foo{34}
println(f)
//s := f.str()
//println(s)
n := [i64(1), 2, 3]
assert n.str() == '[1, 2, 3]'
println(n) // make sure the array is printable
n2 := [4,5,6]
assert n2.str() == '[4, 5, 6]'
println(n2)
}

View File

@ -23,7 +23,13 @@ pub fn (app mut App) json_endpoint() {
app.vweb.json('{"a": 3}') app.vweb.json('{"a": 3}')
} }
/*
pub fn (app mut App) index() { pub fn (app mut App) index() {
$vweb.html()
}
*/
pub fn (app mut App) text() {
app.vweb.text('hello world') app.vweb.text('hello world')
} }

View File

@ -4,6 +4,8 @@
module builtin module builtin
import strings
struct array { struct array {
pub: pub:
// Using a void pointer allows to implement arrays without generics and without generating // Using a void pointer allows to implement arrays without generics and without generating
@ -206,31 +208,6 @@ pub fn (a array) reverse() array {
return arr return arr
} }
pub fn (a []int) str() string {
mut res := '['
for i := 0; i < a.len; i++ {
val := a[i]
res += '$val'
if i < a.len - 1 {
res += ', '
}
}
res += ']'
return res
}
pub fn (a []u64) str() string {
mut res := '['
for i := 0; i < a.len; i++ {
val := a[i]
res += '$val'
if i < a.len - 1 {
res += ', '
}
}
res += ']'
return res
}
//pub fn (a []int) free() { //pub fn (a []int) free() {
pub fn (a array) free() { pub fn (a array) free() {
//if a.is_slice { //if a.is_slice {
@ -239,19 +216,19 @@ pub fn (a array) free() {
C.free(a.data) C.free(a.data)
} }
// TODO generic
// "[ 'a', 'b', 'c' ]" // "[ 'a', 'b', 'c' ]"
pub fn (a []string) str() string { pub fn (a []string) str() string {
mut res := '[' mut sb := strings.new_builder(a.len * 3)
sb.write('[')
for i := 0; i < a.len; i++ { for i := 0; i < a.len; i++ {
val := a[i] val := a[i]
res += '"$val"' sb.write('"$val"')
if i < a.len - 1 { if i < a.len - 1 {
res += ', ' sb.write(', ')
} }
} }
res += ']' sb.write(']')
return res return sb.str()
} }
pub fn (b []byte) hex() string { pub fn (b []byte) hex() string {