Skip to content

Commit 4e3c95c

Browse files
committed
chore: Extend the string object to format code.
Strings now can be formatted using the `"Jina langu ni {0}".badilisha('Nuru')`. Sucessor to <#93> Instead of using a function, just do it on the string level. Signed-off-by: Gekko Wrld <gekkowrld@gmail.com>
1 parent f8d1a7d commit 4e3c95c

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

object/strings.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package object
22

33
import (
4+
"fmt"
45
"hash/fnv"
6+
"strconv"
57
"strings"
68
)
79

@@ -39,6 +41,8 @@ func (s *String) Method(method string, args []Object) Object {
3941
return s.lower(args)
4042
case "gawa":
4143
return s.split(args)
44+
case "badilisha":
45+
return s.format(args)
4246
default:
4347
return newError("Samahani, kiendesha hiki hakitumiki na tungo (Neno)")
4448
}
@@ -81,3 +85,112 @@ func (s *String) split(args []Object) Object {
8185
}
8286
return &Array{Elements: elements}
8387
}
88+
89+
func (s *String) format(args []Object) Object {
90+
value, err := formatStr(s.Value, args)
91+
92+
if err != nil {
93+
return newError(err.Error())
94+
}
95+
96+
return &String{Value: value}
97+
}
98+
99+
// Format the string like "Hello {0}", jina ...
100+
func formatStr(format string, options []Object) (string, error) {
101+
var str strings.Builder
102+
var val strings.Builder
103+
var check_val bool
104+
var opts_len int = len(options)
105+
106+
// This is to enable escaping the {} braces if you want them included
107+
var escapeChar bool
108+
109+
type optM struct {
110+
val bool
111+
obj Object
112+
}
113+
114+
var optionsMap = make(map[int]optM, opts_len)
115+
116+
// convert the options into a map (may not be the most efficient but we are not going fast)
117+
for i, optm := range options {
118+
optionsMap[i] = optM{val: false, obj: optm}
119+
}
120+
121+
// Now go through the format string and do the replacement(s)
122+
// this has approx time complexity of O(n) (bestest case)
123+
for _, opt := range format {
124+
125+
if !escapeChar && opt == '\\' {
126+
escapeChar = true
127+
continue
128+
}
129+
130+
if opt == '{' && !escapeChar {
131+
check_val = true
132+
continue
133+
}
134+
135+
if escapeChar {
136+
if opt != '{' && opt != '}' {
137+
str.WriteRune('\\')
138+
}
139+
escapeChar = false
140+
}
141+
142+
if check_val && opt == '}' {
143+
vstr := strings.TrimSpace(val.String()) // remove accidental spaces
144+
145+
// check the value and try to convert to int
146+
arrv, err := strconv.Atoi(vstr)
147+
if err != nil {
148+
// return non-cryptic go errors
149+
return "", fmt.Errorf(fmt.Sprintf("Ulichopeana si NAMBA, jaribu tena: `%s'", vstr))
150+
}
151+
152+
oVal, exists := optionsMap[arrv]
153+
154+
if !exists {
155+
return "", fmt.Errorf(fmt.Sprintf("Nambari ya chaguo unalolitaka %d ni kubwa kuliko ulizopeana (%d)", arrv, opts_len))
156+
}
157+
158+
str.WriteString(oVal.obj.Inspect())
159+
// may be innefficient
160+
optionsMap[arrv] = optM{val: true, obj: oVal.obj}
161+
162+
check_val = false
163+
val.Reset()
164+
continue
165+
}
166+
167+
if check_val {
168+
val.WriteRune(opt)
169+
continue
170+
}
171+
172+
str.WriteRune(opt)
173+
}
174+
175+
// A check if they never closed the formatting braces e.g '{0'
176+
if check_val {
177+
return "", fmt.Errorf(fmt.Sprintf("Haukufunga '{', tuliokota kabla ya kufika mwisho `%s'", val.String()))
178+
}
179+
180+
// Another innefficient loop
181+
for _, v := range optionsMap {
182+
if !v.val {
183+
return "", fmt.Errorf(fmt.Sprintf("Ulipeana hili chaguo (%s) {%s} lakini haukutumia", v.obj.Inspect(), v.obj.Type()))
184+
}
185+
}
186+
187+
// !start
188+
// Here we can talk about wtf just happened
189+
// 3 loops to do just formatting, formatting for codes sake.
190+
// it can be done in 2 loops, the last one is just to confirm that you didn't forget anything.
191+
// this is not required but a nice syntatic sugar, we are not here for speed, so ergonomics matter instead of speed
192+
// finally we can say we are slower than python!, what an achievement
193+
// done!
194+
195+
return str.String(), nil
196+
}

0 commit comments

Comments
 (0)