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`:
// `mut numbers := [1,2,3]; reverse(mut numbers);`
if arg.is_mut {
if p.tok != .key_mut {
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name(...mut a...)`')
if p.tok != .key_mut && p.tok == .name {
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 {
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
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')
if T.fields.len > 0 {
mut index := p.cgen.cur_line.len - 1

View File

@ -793,7 +793,7 @@ fn (p mut Parser) error(s string) {
p.cgen.save()
// V git pull hint
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('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 ')
@ -1102,7 +1102,7 @@ fn (p mut Parser) vh_genln(s string) {
}
fn (p mut Parser) statement(add_semi bool) string {
if(p.returns) {
if p.returns { //&& !p.is_vweb {
p.error('unreachable code')
}
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()}')
//}
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.name.starts_with('Option_') {
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
import strings
@ -29,7 +33,7 @@ fn (p mut Parser) select_query(fn_ph int) string {
}
for field in typ.fields {
//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
// `where` statement

View File

@ -60,6 +60,7 @@ mut:
// It allows having things like `fn (f Foo) bar()` before `Foo` is defined.
// This information is needed in the first pass.
is_placeholder bool
gen_str bool // needs `.str()` method generation
}
// 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)
if typ.name.len == 0 {
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 << 4
}
// TODO
fn test_mut() {
mut a := [1,2,3]
foo(mut a)
mut numbers := [1,2,3]
foo(7, numbers)
//assert a.len == 4
assert a[0] == 7
assert numbers[0] == 7
//assert a[3] == 4
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}')
}
/*
pub fn (app mut App) index() {
$vweb.html()
}
*/
pub fn (app mut App) text() {
app.vweb.text('hello world')
}

View File

@ -4,6 +4,8 @@
module builtin
import strings
struct array {
pub:
// 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
}
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 array) free() {
//if a.is_slice {
@ -239,19 +216,19 @@ pub fn (a array) free() {
C.free(a.data)
}
// TODO generic
// "[ 'a', 'b', 'c' ]"
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++ {
val := a[i]
res += '"$val"'
sb.write('"$val"')
if i < a.len - 1 {
res += ', '
sb.write(', ')
}
}
res += ']'
return res
sb.write(']')
return sb.str()
}
pub fn (b []byte) hex() string {