generate `.str()` for all arrays
							parent
							
								
									f628d6d35d
								
							
						
					
					
						commit
						8c3475b902
					
				|  | @ -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);  | ||||||
|  | } '  | ||||||
|  | }  | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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)  | ||||||
|  |  | ||||||
|  | @ -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 
 | ||||||
|  |  | ||||||
|  | @ -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)) | ||||||
|  |  | ||||||
|  | @ -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  | ||||||
|  |  | ||||||
|  | @ -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)  | ||||||
|  | }  | ||||||
|  | @ -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') | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue