Step 5: Add Evaluator struct with env, Define, FuncCall support; backward-compat Eval preserved
diff --git a/repl/repl.go b/repl/repl.go
index bc14567..6a86a2e 100644
--- a/repl/repl.go
+++ b/repl/repl.go
@@ -7,6 +7,7 @@
"math"
"strings"
+ "matheval/ast"
"matheval/evaluator"
"matheval/lexer"
"matheval/parser"
@@ -17,6 +18,7 @@
// Run starts the read-eval-print loop, reading from r and writing to w.
func Run(r io.Reader, w io.Writer) {
scanner := bufio.NewScanner(r)
+ ev := evaluator.New()
fmt.Fprint(w, prompt)
for scanner.Scan() {
@@ -26,32 +28,40 @@
continue
}
- result, err := evalLine(line)
+ tokens, err := lexer.Tokenize(line)
if err != nil {
fmt.Fprintf(w, "error: %s\n", err)
- } else {
- fmt.Fprintln(w, formatResult(result))
+ fmt.Fprint(w, prompt)
+ continue
+ }
+
+ stmt, err := parser.ParseLine(tokens)
+ if err != nil {
+ fmt.Fprintf(w, "error: %s\n", err)
+ fmt.Fprint(w, prompt)
+ continue
+ }
+
+ switch s := stmt.(type) {
+ case *ast.FuncDef:
+ if err := ev.Define(s); err != nil {
+ fmt.Fprintf(w, "error: %s\n", err)
+ } else {
+ fmt.Fprintf(w, "defined %s\n", s.Name)
+ }
+ case *ast.ExprStmt:
+ result, err := ev.Eval(s.Expr, nil)
+ if err != nil {
+ fmt.Fprintf(w, "error: %s\n", err)
+ } else {
+ fmt.Fprintln(w, formatResult(result))
+ }
}
fmt.Fprint(w, prompt)
}
}
-// evalLine tokenizes, parses, and evaluates a single expression string.
-func evalLine(line string) (float64, error) {
- tokens, err := lexer.Tokenize(line)
- if err != nil {
- return 0, err
- }
-
- tree, err := parser.Parse(tokens)
- if err != nil {
- return 0, err
- }
-
- return evaluator.Eval(tree)
-}
-
// formatResult formats a float64 for display.
// Whole numbers are printed without decimal points.
func formatResult(val float64) string {