;; lib/go/std/strconv.sx — Go's `strconv` package, v0 subset. (define go-strconv-itoa ;; Itoa(n) → string. Real Go returns the decimal representation. (fn (args) (cond (not (= (len args) 1)) (list :eval-error :strconv-itoa-arity (len args)) :else (let ((n (first args))) (cond (not (number? n)) (list :eval-error :strconv-itoa-not-number n) :else (str n)))))) (define go-strconv-atoi ;; Atoi(s) → (int, error). v0 returns just the int on success or ;; an :eval-error on failure (multi-return is a later refinement). (fn (args) (cond (not (= (len args) 1)) (list :eval-error :strconv-atoi-arity (len args)) :else (let ((s (first args))) (cond (not (string? s)) (list :eval-error :strconv-atoi-not-string s) (= (len s) 0) (list :eval-error :strconv-atoi-empty) :else (go-strconv-parse-int s 0 (= (nth s 0) "-") 0)))))) (define go-strconv-parse-int ;; Parse a (possibly signed) base-10 integer literal. Stops on the ;; first non-digit char and returns the parsed prefix, or :eval-error ;; if no digits were consumed. (fn (s start neg acc) (let ((i (cond (= start 0) (cond neg 1 :else 0) :else start))) (cond (>= i (len s)) (cond (= (cond neg (- i 1) :else i) 0) (list :eval-error :strconv-atoi-no-digits s) :else (cond neg (- 0 acc) :else acc)) :else (let ((d (go-strconv-digit (nth s i)))) (cond (< d 0) (cond (= (cond neg (- i 1) :else i) 0) (list :eval-error :strconv-atoi-no-digits s) :else (cond neg (- 0 acc) :else acc)) :else (go-strconv-parse-int s (+ i 1) neg (+ (* acc 10) d)))))))) (define go-strconv-digit (fn (c) (cond (= c "0") 0 (= c "1") 1 (= c "2") 2 (= c "3") 3 (= c "4") 4 (= c "5") 5 (= c "6") 6 (= c "7") 7 (= c "8") 8 (= c "9") 9 :else -1))) (define go-std-strconv (list :go-package "strconv" (list (list "Itoa" (list :go-builtin-fn go-strconv-itoa)) (list "Atoi" (list :go-builtin-fn go-strconv-atoi)))))