Skip to content

Commit 77ee664

Browse files
authored
Merge pull request #7 from sravanioleti/fix/issue-6-cli-loops
Implement multi-line REPL for loops (Fixes #6).
2 parents 1b4d395 + 4b3fd0d commit 77ee664

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

cli_loop_proof.gola

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bolte thak i [0] -> [2] [i++] :
2+
kemon achis i

main.go

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func (i *Interpreter) Execute(line string) {
2525
line = strings.TrimSpace(line[:idx])
2626
}
2727
// Normalize spacing around '=' so "x=x+5" also works
28-
line = strings.ReplaceAll(line, "=", " = ")
28+
line = normalizeEquals(line)
2929

3030
tokens := strings.Fields(line)
3131
if len(tokens) == 0 {
@@ -100,8 +100,9 @@ func (i *Interpreter) Execute(line string) {
100100
}
101101
varName := tokens[2]
102102
fmt.Printf(`Value bolo %s er =>: `, varName)
103-
var input string
104-
fmt.Scanln(&input)
103+
reader := bufio.NewReader(os.Stdin)
104+
inp, _ := reader.ReadString('\n')
105+
input := strings.TrimSpace(inp)
105106

106107
// Handle string input properly (strip the quotes if present)
107108
if strings.HasPrefix(input, "\"") && strings.HasSuffix(input, "\"") {
@@ -158,6 +159,33 @@ func (i *Interpreter) Execute(line string) {
158159
}
159160
}
160161

162+
// normalizeEquals inserts spaces around standalone '=' but leaves
163+
// '==', '!=', '>=', '<=', '+=', '-=' etc. intact.
164+
func normalizeEquals(s string) string {
165+
var b strings.Builder
166+
for i := 0; i < len(s); i++ {
167+
c := s[i]
168+
if c == '=' {
169+
var prev, next byte
170+
if i > 0 {
171+
prev = s[i-1]
172+
}
173+
if i+1 < len(s) {
174+
next = s[i+1]
175+
}
176+
// if equals is part of a multi-char operator, keep as-is
177+
if prev == '=' || prev == '!' || prev == '<' || prev == '>' || prev == '+' || prev == '-' || next == '=' || next == '+' || next == '-' {
178+
b.WriteByte('=')
179+
} else {
180+
b.WriteString(" = ")
181+
}
182+
} else {
183+
b.WriteByte(c)
184+
}
185+
}
186+
return b.String()
187+
}
188+
161189
func (i *Interpreter) evaluateExpression(tokens []string) (int, error) {
162190
if len(tokens) == 0 {
163191
return 0, fmt.Errorf("invalid expression")
@@ -261,8 +289,8 @@ func (i *Interpreter) getValue(token string) (int, error) {
261289
// body: single-line loop body (e.g., "kemon achis i")
262290
func (i *Interpreter) ExecuteLoop(header, body string) {
263291
header = strings.TrimSpace(header)
264-
if strings.HasSuffix(header, ":") {
265-
header = strings.TrimSuffix(header, ":")
292+
if strings.HasSuffix(strings.TrimSpace(header), ":") {
293+
header = strings.TrimSuffix(strings.TrimSpace(header), ":")
266294
}
267295

268296
// expected format: bolte thak <iter> [<start>] -> [<end>] [<incr>]
@@ -412,12 +440,50 @@ func main() {
412440
interpreter := NewInterpreter()
413441
for {
414442
fmt.Print(">> ")
415-
scanner.Scan()
443+
if !scanner.Scan() {
444+
// EOF or error: exit REPL
445+
break
446+
}
416447
line := scanner.Text()
417-
if strings.TrimSpace(line) == "exit" {
448+
lineTrim := strings.TrimSpace(line)
449+
if lineTrim == "exit" {
418450
break
419451
}
452+
453+
// If user entered a loop header in REPL, read the loop body from the next non-empty line
454+
// This mirrors file-mode behavior (file-mode reads the next line as the body).
455+
if strings.HasPrefix(lineTrim, "bolte thak") {
456+
// Prompt the user to enter the loop body (continuation prompt)
457+
var body string
458+
for {
459+
fmt.Print("... ")
460+
if !scanner.Scan() {
461+
// EOF or error while reading body; abort loop read
462+
fmt.Println("bhul hoye gelo vai check kor ekbar: unexpected EOF while reading loop body")
463+
body = ""
464+
break
465+
}
466+
body = scanner.Text()
467+
// skip blank lines or comment-only lines until we get a real body line
468+
if strings.TrimSpace(body) == "" || strings.HasPrefix(strings.TrimSpace(body), "//") {
469+
// keep prompting for the body
470+
continue
471+
}
472+
break
473+
}
474+
if strings.TrimSpace(body) == "" {
475+
// if we couldn't get a valid body, warn and continue
476+
fmt.Println("bhul hoye gelo vai check kor ekbar: loop header but no body")
477+
continue
478+
}
479+
// call the same function as file-mode uses
480+
interpreter.ExecuteLoop(lineTrim, body)
481+
continue
482+
}
483+
484+
// not a loop header — normal single-line execution
420485
interpreter.Execute(line)
421486
}
487+
422488
fmt.Println("Jay Shree Ram Bhai!")
423489
}

0 commit comments

Comments
 (0)