builtin: public/private functions, remove lots of duplicate functionality

(string.eq, compare_strings, etc)
pull/701/head
Alexander Medvednikov 2019-06-27 13:14:59 +02:00
parent b846d02cb2
commit 76bf732e63
15 changed files with 109 additions and 120 deletions

View File

@ -63,18 +63,18 @@ fn array_repeat(val voidptr, nr_repeats, elm_size int) array {
return arr
}
fn (a mut array) append_array(b array) {
pub fn (a mut array) append_array(b array) {
for i := 0; i < b.len; i++ {
val := b[i]
a._push(val)
}
}
fn (a mut array) sort_with_compare(compare voidptr) {
pub fn (a mut array) sort_with_compare(compare voidptr) {
C.qsort(a.data, a.len, a.element_size, compare)
}
fn (a mut array) insert(i int, val voidptr) {
pub fn (a mut array) insert(i int, val voidptr) {
if i >= a.len {
panic('array.insert: index larger than length')
return
@ -85,11 +85,11 @@ fn (a mut array) insert(i int, val voidptr) {
a.set(i, val)
}
fn (a mut array) prepend(val voidptr) {
pub fn (a mut array) prepend(val voidptr) {
a.insert(0, val)
}
fn (a mut array) delete(idx int) {
pub fn (a mut array) delete(idx int) {
size := a.element_size
C.memmove(a.data + idx * size, a.data + (idx + 1) * size, (a.len - idx) * size)
a.len--
@ -103,28 +103,28 @@ fn (a array) _get(i int) voidptr {
return a.data + i * a.element_size
}
fn (a array) first() voidptr {
pub fn (a array) first() voidptr {
if a.len == 0 {
panic('array.first: empty array')
}
return a.data + 0
}
fn (a array) last() voidptr {
pub fn (a array) last() voidptr {
if a.len == 0 {
panic('array.last: empty array')
}
return a.data + (a.len - 1) * a.element_size
}
fn (s array) left(n int) array {
pub fn (s array) left(n int) array {
if n >= s.len {
return s
}
return s.slice(0, n)
}
fn (s array) right(n int) array {
pub fn (s array) right(n int) array {
if n >= s.len {
return s
}
@ -149,14 +149,14 @@ pub fn (s array) slice(start, _end int) array {
return res
}
fn (a mut array) set(idx int, val voidptr) {
pub fn (a mut array) set(idx int, val voidptr) {
if idx < 0 || idx >= a.len {
panic('array index out of range: $idx / $a.len')
}
C.memcpy(a.data + a.element_size * idx, val, a.element_size)
}
fn (arr mut array) _push(val voidptr) {
pub fn (arr mut array) _push(val voidptr) {
if arr.len >= arr.cap - 1 {
cap := (arr.len + 1) * 2
// println('_push: realloc, new cap=$cap')
@ -172,7 +172,7 @@ fn (arr mut array) _push(val voidptr) {
arr.len++
}
fn (arr mut array) _push_many(val voidptr, size int) {
pub fn (arr mut array) _push_many(val voidptr, size int) {
if arr.len >= arr.cap - size {
cap := (arr.len + size) * 2
// println('_push: realloc, new cap=$cap')
@ -188,7 +188,7 @@ fn (arr mut array) _push_many(val voidptr, size int) {
arr.len += size
}
fn (a[]int) str() string {
pub fn (a[]int) str() string {
mut res := '['
for i := 0; i < a.len; i++ {
val := a[i]
@ -201,14 +201,14 @@ fn (a[]int) str() string {
return res
}
fn (a[]int) free() {
pub fn (a[]int) free() {
// println('array free')
C.free(a.data)
}
// TODO generic
// "[ 'a', 'b', 'c' ]"
fn (a[]string) str() string {
pub fn (a[]string) str() string {
mut res := '['
for i := 0; i < a.len; i++ {
val := a[i]

View File

@ -111,13 +111,4 @@ pub fn error(s string) Option {
}
}
// TODO this is not used anymore
fn range_int(start, end int) []int {
len := end - start
mut res := [0; len]
for i := 0; i < len; i++ {
res[i] = start + i
}
return res
}

View File

@ -4,31 +4,25 @@
module builtin
fn (d double) str() string {
pub fn (d double) str() string {
buf := malloc(sizeof(double) * 5 + 1)// TODO
C.sprintf(buf, '%f', d)
return tos(buf, _strlen(buf))
}
fn (d float) str() string {
pub fn (d f64) str() string {
buf := malloc(sizeof(double) * 5 + 1)// TODO
C.sprintf(buf, '%f', d)
return tos(buf, _strlen(buf))
}
fn (d f64) str() string {
pub fn (d f32) str() string {
buf := malloc(sizeof(double) * 5 + 1)// TODO
C.sprintf(buf, '%f', d)
return tos(buf, _strlen(buf))
}
fn (d f32) str() string {
buf := malloc(sizeof(double) * 5 + 1)// TODO
C.sprintf(buf, '%f', d)
return tos(buf, _strlen(buf))
}
fn ptr_str(ptr voidptr) string {
pub fn ptr_str(ptr voidptr) string {
buf := malloc(sizeof(double) * 5 + 1)// TODO
C.sprintf(buf, '%p', ptr)
return tos(buf, _strlen(buf))
@ -37,7 +31,7 @@ fn ptr_str(ptr voidptr) string {
// fn (nn i32) str() string {
// return i
// }
fn (nn int) str() string {
pub fn (nn int) str() string {
mut n = nn
if n == 0 {
return '0'
@ -65,8 +59,8 @@ fn (nn int) str() string {
return tos(buf + max - len, len)
}
fn (nn u8) str() string {
mut n = nn
pub fn (nn u8) str() string {
mut n = nn
if n == u8(0) {
return '0'
}
@ -93,7 +87,7 @@ fn (nn u8) str() string {
return tos(buf + max - len, len)
}
fn (nn i64) str() string {
pub fn (nn i64) str() string {
mut n = nn
if n == i64(0) {
return '0'
@ -121,28 +115,28 @@ fn (nn i64) str() string {
return tos(buf + max - len, len)
}
fn (b bool) str() string {
pub fn (b bool) str() string {
if b {
return 'true'
}
return 'false'
}
fn (n int) hex() string {
pub fn (n int) hex() string {
s := n.str()
hex := malloc(s.len + 2)
C.sprintf(hex, '0x%x', n)
return tos(hex, s.len + 2)
}
fn (n i64) hex() string {
pub fn (n i64) hex() string {
s := n.str()
hex := malloc(s.len + 2)
C.sprintf(hex, '0x%x', n)
return tos(hex, s.len + 2)
}
fn (a[]byte) contains(val byte) bool {
pub fn (a[]byte) contains(val byte) bool {
for aa in a {
if aa == val {
return true
@ -155,7 +149,7 @@ fn (a[]byte) contains(val byte) bool {
fn (c rune) str() string {
}
*/
fn (c byte) str() string {
pub fn (c byte) str() string {
mut str := string {
len: 1
str: malloc(2)

View File

@ -25,7 +25,7 @@ pub:
// next *Entry
}
fn new_map(cap, elm_size int) map {
pub fn new_map(cap, elm_size int) map {
res := map {
// len: len,
element_size: elm_size
@ -108,7 +108,7 @@ pub fn (m mut map) sort() {
m.is_sorted = true
}
fn (m map) keys() []string {
pub fn (m map) keys() []string {
mut keys := []string{}
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
@ -133,7 +133,7 @@ fn (m map) get(key string, out voidptr) bool {
return false
}
fn (m map) exists(key string) bool {
pub fn (m map) exists(key string) bool {
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
if entry.key == key {
@ -143,7 +143,7 @@ fn (m map) exists(key string) bool {
return false
}
fn (m map) print() {
pub fn (m map) print() {
println('<<<<<<<<')
for i := 0; i < m.entries.len; i++ {
// entry := m.entries[i]
@ -160,12 +160,12 @@ fn (m map) print() {
println('>>>>>>>>>>')
}
fn (m map) free() {
pub fn (m map) free() {
// C.free(m.table)
// C.free(m.keys_table)
}
fn (m map_string) str() string {
pub fn (m map_string) str() string {
// return 'not impl'
if m.entries.len == 0 {
return '{}'

View File

@ -21,8 +21,10 @@ pub:
// For C strings only
fn C.strlen(s byteptr) int
fn todo() { }
// Converts a C string to a V string
fn tos(s byteptr, len int) string {
pub fn tos(s byteptr, len int) string {
// This should never happen.
if isnil(s) {
panic('tos(): nil string')
@ -33,7 +35,7 @@ fn tos(s byteptr, len int) string {
}
}
fn tos_clone(s byteptr) string {
pub fn tos_clone(s byteptr) string {
if isnil(s) {
panic('tos: nil string')
return string{}
@ -43,7 +45,7 @@ fn tos_clone(s byteptr) string {
return res.clone()
}
// Same as `tos`, but calculates the length itself. TODO bad name.
// Same as `tos`, but calculates the length. Called by `string(bytes)` casts.
fn tos2(s byteptr) string {
if isnil(s) {
panic('tos2: nil string')
@ -54,7 +56,7 @@ fn tos2(s byteptr) string {
return res
}
fn (a string) clone() string {
pub fn (a string) clone() string {
mut b := string {
len: a.len
str: malloc(a.len + 1)
@ -66,7 +68,7 @@ fn (a string) clone() string {
return b
}
fn (s string) cstr() byteptr {
pub fn (s string) cstr() byteptr {
clone := s.clone()
return clone.str
}
@ -134,11 +136,11 @@ pub fn (s string) replace(rep, with string) string {
return tos(b, new_len)
}
fn (s string) int() int {
pub fn (s string) int() int {
return C.atoi(s.str)
}
fn (s string) f32() f32 {
pub fn (s string) f32() f32 {
return C.atof(s.str)
}
@ -195,7 +197,7 @@ fn (s string) ge(a string) bool {
}
// TODO `fn (s string) + (a string)` ? To be consistent with operator overloading syntax.
fn (s string) add(a string) string {
pub fn (s string) add(a string) string {
new_len := a.len + s.len
mut res := string {
len: new_len
@ -256,7 +258,7 @@ pub fn (s string) split(delim string) []string {
return res
}
fn (s string) split_single(delim byte) []string {
pub fn (s string) split_single(delim byte) []string {
mut res := []string
if int(delim) == 0 {
res << s
@ -460,7 +462,7 @@ pub fn (s string) to_upper() string {
// 'hey [man] how you doin'
// find_between('[', ']') == 'man'
fn (s string) find_between(start, end string) string {
pub fn (s string) find_between(start, end string) string {
start_pos := s.index(start)
if start_pos == -1 {
return ''
@ -475,7 +477,7 @@ fn (s string) find_between(start, end string) string {
}
// TODO generic
fn (ar[]string) contains(val string) bool {
pub fn (ar[]string) contains(val string) bool {
for s in ar {
if s == val {
return true
@ -485,7 +487,7 @@ fn (ar[]string) contains(val string) bool {
}
// TODO generic
fn (ar[]int) contains(val int) bool {
pub fn (ar[]int) contains(val int) bool {
for i, s in ar {
if s == val {
return true
@ -494,7 +496,7 @@ fn (ar[]int) contains(val int) bool {
return false
}
fn (a[]string) to_c() voidptr {
pub fn (a[]string) to_c() voidptr {
# char ** res = malloc(sizeof(char*) * a.len);
for i := 0; i < a.len; i++ {
val := a[i]
@ -508,7 +510,7 @@ fn is_space(c byte) bool {
return C.isspace(c)
}
fn (c byte) is_space() bool {
pub fn (c byte) is_space() bool {
return is_space(c)
}
@ -549,7 +551,7 @@ pub fn (s string) trim(c byte) string {
return res
}
fn (s string) trim_left(cutset string) string {
pub fn (s string) trim_left(cutset string) string {
mut start := s.index(cutset)
if start != 0 {
return s
@ -560,7 +562,7 @@ fn (s string) trim_left(cutset string) string {
return s.right(start)
}
fn (s string) trim_right(cutset string) string {
pub fn (s string) trim_right(cutset string) string {
pos := s.last_index(cutset)
if pos == -1 {
return s
@ -601,15 +603,15 @@ pub fn (s mut []string) sort() {
s.sort_with_compare(compare_strings)
}
fn (s mut []string) sort_ignore_case() {
pub fn (s mut []string) sort_ignore_case() {
s.sort_with_compare(compare_lower_strings)
}
fn (s mut []string) sort_by_len() {
pub fn (s mut []string) sort_by_len() {
s.sort_with_compare(compare_strings_by_len)
}
fn (s string) ustring() ustring {
pub fn (s string) ustring() ustring {
mut res := ustring {
s: s
// runes will have at least s.len elements, save reallocations
@ -631,7 +633,7 @@ fn (s string) ustring() ustring {
// It's called from functions like draw_text() where we know that the string is going to be freed
// right away. Uses global buffer for storing runes []int array.
# array_int g_ustring_runes;
fn (s string) ustring_tmp() ustring {
pub fn (s string) ustring_tmp() ustring {
mut res := ustring {
s: s
runes: 0
@ -681,7 +683,7 @@ fn (s string) at(idx int) byte {
return s.str[idx]
}
fn (u ustring) at(idx int) string {
pub fn (u ustring) at(idx int) string {
return u.substr(idx, idx + 1)
}
@ -696,11 +698,11 @@ fn abs(a int) int {
return -a
}
fn (c byte) is_digit() bool {
pub fn (c byte) is_digit() bool {
return c >= `0` && c <= `9`
}
fn (c byte) is_letter() bool {
pub fn (c byte) is_letter() bool {
return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`)
}
@ -716,7 +718,7 @@ fn (arr[]string) free() {
}
// all_before('23:34:45.234', '.') == '23:34:45'
fn (s string) all_before(dot string) string {
pub fn (s string) all_before(dot string) string {
pos := s.index(dot)
if pos == -1 {
return s
@ -724,7 +726,7 @@ fn (s string) all_before(dot string) string {
return s.left(pos)
}
fn (s string) all_before_last(dot string) string {
pub fn (s string) all_before_last(dot string) string {
pos := s.last_index(dot)
if pos == -1 {
return s
@ -732,7 +734,7 @@ fn (s string) all_before_last(dot string) string {
return s.left(pos)
}
fn (s string) all_after(dot string) string {
pub fn (s string) all_after(dot string) string {
pos := s.last_index(dot)
if pos == -1 {
return s
@ -776,11 +778,11 @@ pub fn (a[]string) join(del string) string {
return res
}
fn (s[]string) join_lines() string {
pub fn (s[]string) join_lines() string {
return s.join('\n')
}
fn (s string) reverse() string {
pub fn (s string) reverse() string {
mut res := string {
len: s.len
str: malloc(s.len + 1)
@ -795,7 +797,7 @@ fn (s string) reverse() string {
// 'hello'.limit(2) => 'he'
// 'hi'.limit(10) => 'hi'
fn (s string) limit(max int) string {
pub fn (s string) limit(max int) string {
u := s.ustring()
if u.len <= max {
return s
@ -804,13 +806,13 @@ fn (s string) limit(max int) string {
}
// TODO is_white_space()
fn (c byte) is_white() bool {
pub fn (c byte) is_white() bool {
i := int(c)
return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r`
}
// TODO move this to strings.repeat()
fn repeat_char(c byte, n int) string {
pub fn repeat_char(c byte, n int) string {
if n <= 0 {
return ''
}

View File

@ -9,31 +9,31 @@ struct StringBuilder {
len int
}
fn new_string_builder(initial_size int) StringBuilder {
pub fn new_string_builder(initial_size int) StringBuilder {
return StringBuilder {
buf: new_array(0, initial_size, sizeof(byte))
}
}
fn (b mut StringBuilder) write(s string) {
pub fn (b mut StringBuilder) write(s string) {
b.buf._push_many(s.str, s.len)
b.len += s.len
}
fn (b mut StringBuilder) writeln(s string) {
pub fn (b mut StringBuilder) writeln(s string) {
b.buf._push_many(s.str, s.len)
b.buf << `\n`
b.len += s.len + 1
}
fn (b StringBuilder) str() string {
pub fn (b StringBuilder) str() string {
return tos(b.buf.data, b.len)
}
fn (b StringBuilder) cut(n int) {
pub fn (b StringBuilder) cut(n int) {
b.len -= n
}
fn (b mut StringBuilder) free() {
pub fn (b mut StringBuilder) free() {
C.free(b.buf.data)
}

View File

@ -5,7 +5,7 @@
fn test_add() {
mut a := 'a'
a += 'b'
assert a.eq('ab')
assert a==('ab')
a = 'a'
for i := 1; i < 1000; i++ {
a += 'b'
@ -29,7 +29,7 @@ fn test_between() {
fn test_compare() {
a := 'Music'
b := 'src'
assert b.ge(a)
assert b>=(a)
}
fn test_lt() {
@ -39,12 +39,12 @@ fn test_lt() {
d := 'b'
e := 'aa'
f := 'ab'
assert a.lt(b)
assert b.lt(c) == false
assert c.lt(d)
assert d.lt(e) == false
assert c.lt(e)
assert e.lt(f)
assert a<(b)
assert !(b<c)
assert c<(d)
assert !(d<e)
assert c<(e)
assert e<(f)
}
fn test_ge() {
@ -53,11 +53,11 @@ fn test_ge() {
c := 'ab'
d := 'abc'
e := 'aaa'
assert b.ge(a)
assert c.ge(b)
assert d.ge(c)
assert c.ge(d) == false
assert e.ge(a)
assert b>=(a)
assert c>=(b)
assert d>=(c)
assert !(c>=d)
assert e>=(a)
}
fn test_compare_strings() {
@ -150,13 +150,13 @@ fn test_clone() {
fn test_replace() {
a := 'hello man!'
mut b := a.replace('man', 'world')
assert b.eq('hello world!')
assert b==('hello world!')
b = b.replace('!', '')
assert b.eq('hello world')
assert b==('hello world')
b = b.replace('h', 'H')
assert b.eq('Hello world')
assert b==('Hello world')
b = b.replace('kek', 'lul')
assert b.eq('Hello world')
assert b==('Hello world')
s := 'hey man how are you'
assert s.replace('man ', '') == 'hey how are you'
lol := 'lol lol lol'

View File

@ -4,7 +4,7 @@
module builtin
fn (s string) is_utf8() int {
pub fn (s string) is_utf8() int {
faulty_bytes := 0
len := s.len
i := 0
@ -250,7 +250,7 @@ fn (s string) runes() []string {
*/
// Convert utf32 to utf8
// utf32 == Codepoint
fn utf32_to_str(code u32) string {
pub fn utf32_to_str(code u32) string {
// println('code = $code')
buffer := malloc(5)
# if (code <= 0x7F) {
@ -282,7 +282,7 @@ fn utf32_to_str(code u32) string {
}
// TODO copypasta
fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
// println('code = $code')
# char* buffer = buf;
# if (code <= 0x7F) {
@ -314,7 +314,7 @@ fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
}
// Convert utf8 to utf32
fn (_rune string) utf32_code() int {
pub fn (_rune string) utf32_code() int {
// println('utf 32 of $rune len=$rune.len')
if _rune.len == 0 {
return 0

View File

@ -9,6 +9,7 @@ v.c:
test: v
find .. -name '*_test.v' -print0 | xargs -0 -n1 ./v
echo "Building V examples..."
find ../examples -name '*.v' -print0 | xargs -0 -n1 ./v
clean:

View File

@ -493,7 +493,8 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
}
fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type string) {
if !f.is_public && !f.is_c && f.pkg != p.pkg && f.pkg != 'builtin' {
//if !f.is_public && !f.is_c && f.pkg != p.pkg && f.pkg != 'builtin' {
if !f.is_public && !f.is_c && !p.is_test && f.pkg != p.pkg {
p.error('function `$f.name` is private')
}
p.calling_c = f.is_c

View File

@ -1163,7 +1163,7 @@ fn (p mut Parser) bool_expression() string {
fn (p mut Parser) bterm() string {
ph := p.cgen.add_placeholder()
mut typ = p.expression()
is_str := typ.eq('string')
is_str := typ=='string'
tok := p.tok
// if tok in [ EQ, GT, LT, LE, GE, NE] {
if tok == EQ || tok == GT || tok == LT || tok == LE || tok == GE || tok == NE {
@ -1762,7 +1762,7 @@ fn (p mut Parser) expression() string {
p.cgen('/* expr start*/')
ph := p.cgen.add_placeholder()
mut typ := p.term()
is_str := typ.eq('string')
is_str := typ=='string'
// a << b ==> array2_push(&a, b)
if p.tok == LEFT_SHIFT {
if typ.contains('array_') {

View File

@ -442,7 +442,7 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool {
return true
}
// Todo void* allows everything right now
if got.eq('void*') || expected.eq('void*') {
if got=='void*' || expected=='void*' {
// if !p.builtin_pkg {
if p.is_play {
return false
@ -451,17 +451,17 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool {
}
// TODO only allow numeric consts to be assigned to bytes, and
// throw an error if they are bigger than 255
if got.eq('int') && expected.eq('byte') {
if got=='int' && expected=='byte' {
return true
}
if got.eq('byteptr') && expected.eq('byte*') {
if got=='byteptr' && expected=='byte*' {
return true
}
if got.eq('int') && expected.eq('byte*') {
if got=='int' && expected=='byte*' {
return true
}
// byteptr += int
if got.eq('int') && expected.eq('byteptr') {
if got=='int' && expected=='byteptr' {
return true
}
if got == 'Option' && expected.starts_with('Option_') {
@ -487,7 +487,7 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool {
// return true
// }
// Allow pointer arithmetic
if expected.eq('void*') && got.eq('int') {
if expected=='void*' && got=='int' {
return true
}
}

View File

@ -21,7 +21,7 @@ fn display_help() {
fn option_parser() bool {
help := options{'--help', '-h'}
for i := 0; i < os.args.len; i++ {
if compare_strings(os.args[i], help.long_opt) == 0 || compare_strings(os.args[i], help.short_opt) == 0 {
if os.args[i]== help.long_opt || os.args[i]== help.short_opt {
display_help()
return true
}
@ -116,7 +116,7 @@ fn is_broke(money int) bool {
quit := options{'yes', 'y'}
println('You\'ve $money V. Do you want to quit the casino with your winnings? (y/n)')
line := os.get_line().trim_space().to_lower()
if compare_strings(line, quit.long_opt) == 0 || compare_strings(line, quit.short_opt) == 0 {
if line== quit.long_opt || line== quit.short_opt {
return false
}
}

View File

@ -507,7 +507,7 @@ fn (ctx &GG) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
for j := 0; j < ctx.utf_runes.len; j++ {
rune_j := ctx.utf_runes[j]
// if string_eq(ctx.utf_runes[j], rune) {
if rune_j.eq(_rune) {
if rune_j==_rune {
ch = ctx.utf_chars[j]
break
}

View File

@ -136,7 +136,7 @@ fn json_parse(s string) *C.cJSON {
// json_string := json_print(encode_User(user))
fn json_print(json *C.cJSON) string {
s := C.cJSON_PrintUnformatted(json)
return tos(s, _strlen(s))
return tos(s, C.strlen(s))
}
// / cjson wrappers