Skip to content

Commit c8c8663

Browse files
committed
extract string query and search member methods
1 parent 228bb12 commit c8c8663

2 files changed

Lines changed: 251 additions & 236 deletions

File tree

vibes/execution_members_string.go

Lines changed: 2 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -2,248 +2,14 @@ package vibes
22

33
import (
44
"fmt"
5-
"regexp"
65
"strings"
76
"unicode"
87
)
98

109
func stringMember(str Value, property string) (Value, error) {
1110
switch property {
12-
case "size":
13-
return NewAutoBuiltin("string.size", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
14-
if len(args) > 0 {
15-
return NewNil(), fmt.Errorf("string.size does not take arguments")
16-
}
17-
return NewInt(int64(len([]rune(receiver.String())))), nil
18-
}), nil
19-
case "length":
20-
return NewAutoBuiltin("string.length", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
21-
if len(args) > 0 {
22-
return NewNil(), fmt.Errorf("string.length does not take arguments")
23-
}
24-
return NewInt(int64(len([]rune(receiver.String())))), nil
25-
}), nil
26-
case "bytesize":
27-
return NewAutoBuiltin("string.bytesize", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
28-
if len(args) > 0 {
29-
return NewNil(), fmt.Errorf("string.bytesize does not take arguments")
30-
}
31-
return NewInt(int64(len(receiver.String()))), nil
32-
}), nil
33-
case "ord":
34-
return NewAutoBuiltin("string.ord", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
35-
if len(args) > 0 {
36-
return NewNil(), fmt.Errorf("string.ord does not take arguments")
37-
}
38-
runes := []rune(receiver.String())
39-
if len(runes) == 0 {
40-
return NewNil(), fmt.Errorf("string.ord requires non-empty string")
41-
}
42-
return NewInt(int64(runes[0])), nil
43-
}), nil
44-
case "chr":
45-
return NewAutoBuiltin("string.chr", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
46-
if len(args) > 0 {
47-
return NewNil(), fmt.Errorf("string.chr does not take arguments")
48-
}
49-
runes := []rune(receiver.String())
50-
if len(runes) == 0 {
51-
return NewNil(), nil
52-
}
53-
return NewString(string(runes[0])), nil
54-
}), nil
55-
case "empty?":
56-
return NewAutoBuiltin("string.empty?", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
57-
if len(args) > 0 {
58-
return NewNil(), fmt.Errorf("string.empty? does not take arguments")
59-
}
60-
return NewBool(len(receiver.String()) == 0), nil
61-
}), nil
62-
case "clear":
63-
return NewAutoBuiltin("string.clear", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
64-
if len(args) > 0 {
65-
return NewNil(), fmt.Errorf("string.clear does not take arguments")
66-
}
67-
return NewString(""), nil
68-
}), nil
69-
case "concat":
70-
return NewAutoBuiltin("string.concat", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
71-
var b strings.Builder
72-
b.WriteString(receiver.String())
73-
for _, arg := range args {
74-
if arg.Kind() != KindString {
75-
return NewNil(), fmt.Errorf("string.concat expects string arguments")
76-
}
77-
b.WriteString(arg.String())
78-
}
79-
return NewString(b.String()), nil
80-
}), nil
81-
case "replace":
82-
return NewAutoBuiltin("string.replace", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
83-
if len(args) != 1 {
84-
return NewNil(), fmt.Errorf("string.replace expects exactly one replacement")
85-
}
86-
if args[0].Kind() != KindString {
87-
return NewNil(), fmt.Errorf("string.replace replacement must be string")
88-
}
89-
return NewString(args[0].String()), nil
90-
}), nil
91-
case "start_with?":
92-
return NewAutoBuiltin("string.start_with?", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
93-
if len(args) != 1 {
94-
return NewNil(), fmt.Errorf("string.start_with? expects exactly one prefix")
95-
}
96-
if args[0].Kind() != KindString {
97-
return NewNil(), fmt.Errorf("string.start_with? prefix must be string")
98-
}
99-
return NewBool(strings.HasPrefix(receiver.String(), args[0].String())), nil
100-
}), nil
101-
case "end_with?":
102-
return NewAutoBuiltin("string.end_with?", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
103-
if len(args) != 1 {
104-
return NewNil(), fmt.Errorf("string.end_with? expects exactly one suffix")
105-
}
106-
if args[0].Kind() != KindString {
107-
return NewNil(), fmt.Errorf("string.end_with? suffix must be string")
108-
}
109-
return NewBool(strings.HasSuffix(receiver.String(), args[0].String())), nil
110-
}), nil
111-
case "include?":
112-
return NewAutoBuiltin("string.include?", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
113-
if len(args) != 1 {
114-
return NewNil(), fmt.Errorf("string.include? expects exactly one substring")
115-
}
116-
if args[0].Kind() != KindString {
117-
return NewNil(), fmt.Errorf("string.include? substring must be string")
118-
}
119-
return NewBool(strings.Contains(receiver.String(), args[0].String())), nil
120-
}), nil
121-
case "match":
122-
return NewAutoBuiltin("string.match", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
123-
if len(kwargs) > 0 {
124-
return NewNil(), fmt.Errorf("string.match does not take keyword arguments")
125-
}
126-
if len(args) != 1 {
127-
return NewNil(), fmt.Errorf("string.match expects exactly one pattern")
128-
}
129-
if args[0].Kind() != KindString {
130-
return NewNil(), fmt.Errorf("string.match pattern must be string")
131-
}
132-
pattern := args[0].String()
133-
re, err := regexp.Compile(pattern)
134-
if err != nil {
135-
return NewNil(), fmt.Errorf("string.match invalid regex: %v", err)
136-
}
137-
text := receiver.String()
138-
indices := re.FindStringSubmatchIndex(text)
139-
if indices == nil {
140-
return NewNil(), nil
141-
}
142-
values := make([]Value, len(indices)/2)
143-
for i := range values {
144-
start := indices[i*2]
145-
end := indices[i*2+1]
146-
if start < 0 || end < 0 {
147-
values[i] = NewNil()
148-
continue
149-
}
150-
values[i] = NewString(text[start:end])
151-
}
152-
return NewArray(values), nil
153-
}), nil
154-
case "scan":
155-
return NewAutoBuiltin("string.scan", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
156-
if len(kwargs) > 0 {
157-
return NewNil(), fmt.Errorf("string.scan does not take keyword arguments")
158-
}
159-
if len(args) != 1 {
160-
return NewNil(), fmt.Errorf("string.scan expects exactly one pattern")
161-
}
162-
if args[0].Kind() != KindString {
163-
return NewNil(), fmt.Errorf("string.scan pattern must be string")
164-
}
165-
pattern := args[0].String()
166-
re, err := regexp.Compile(pattern)
167-
if err != nil {
168-
return NewNil(), fmt.Errorf("string.scan invalid regex: %v", err)
169-
}
170-
matches := re.FindAllString(receiver.String(), -1)
171-
values := make([]Value, len(matches))
172-
for i, m := range matches {
173-
values[i] = NewString(m)
174-
}
175-
return NewArray(values), nil
176-
}), nil
177-
case "index":
178-
return NewAutoBuiltin("string.index", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
179-
if len(args) < 1 || len(args) > 2 {
180-
return NewNil(), fmt.Errorf("string.index expects substring and optional offset")
181-
}
182-
if args[0].Kind() != KindString {
183-
return NewNil(), fmt.Errorf("string.index substring must be string")
184-
}
185-
offset := 0
186-
if len(args) == 2 {
187-
i, err := valueToInt(args[1])
188-
if err != nil || i < 0 {
189-
return NewNil(), fmt.Errorf("string.index offset must be non-negative integer")
190-
}
191-
offset = i
192-
}
193-
index := stringRuneIndex(receiver.String(), args[0].String(), offset)
194-
if index < 0 {
195-
return NewNil(), nil
196-
}
197-
return NewInt(int64(index)), nil
198-
}), nil
199-
case "rindex":
200-
return NewAutoBuiltin("string.rindex", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
201-
if len(args) < 1 || len(args) > 2 {
202-
return NewNil(), fmt.Errorf("string.rindex expects substring and optional offset")
203-
}
204-
if args[0].Kind() != KindString {
205-
return NewNil(), fmt.Errorf("string.rindex substring must be string")
206-
}
207-
offset := len([]rune(receiver.String()))
208-
if len(args) == 2 {
209-
i, err := valueToInt(args[1])
210-
if err != nil || i < 0 {
211-
return NewNil(), fmt.Errorf("string.rindex offset must be non-negative integer")
212-
}
213-
offset = i
214-
}
215-
index := stringRuneRIndex(receiver.String(), args[0].String(), offset)
216-
if index < 0 {
217-
return NewNil(), nil
218-
}
219-
return NewInt(int64(index)), nil
220-
}), nil
221-
case "slice":
222-
return NewAutoBuiltin("string.slice", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
223-
if len(args) < 1 || len(args) > 2 {
224-
return NewNil(), fmt.Errorf("string.slice expects index and optional length")
225-
}
226-
start, err := valueToInt(args[0])
227-
if err != nil {
228-
return NewNil(), fmt.Errorf("string.slice index must be integer")
229-
}
230-
runes := []rune(receiver.String())
231-
if len(args) == 1 {
232-
if start < 0 || start >= len(runes) {
233-
return NewNil(), nil
234-
}
235-
return NewString(string(runes[start])), nil
236-
}
237-
length, err := valueToInt(args[1])
238-
if err != nil {
239-
return NewNil(), fmt.Errorf("string.slice length must be integer")
240-
}
241-
substr, ok := stringRuneSlice(receiver.String(), start, length)
242-
if !ok {
243-
return NewNil(), nil
244-
}
245-
return NewString(substr), nil
246-
}), nil
11+
case "size", "length", "bytesize", "ord", "chr", "empty?", "clear", "concat", "replace", "start_with?", "end_with?", "include?", "match", "scan", "index", "rindex", "slice":
12+
return stringMemberQuery(property)
24713
case "strip":
24814
return NewAutoBuiltin("string.strip", func(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {
24915
if len(args) > 0 {

0 commit comments

Comments
 (0)