Add typed Kotlin string interop helpers

ober

1770928170e3c3e0b209ca0c0e949d62971d8dbb

diff --git a/docs/typed-kotlin.md b/docs/typed-kotlin.md
index cf0a221..8e6f652 100644
--- a/docs/typed-kotlin.md
+++ b/docs/typed-kotlin.md
@@ -30,6 +30,8 @@ JVM-sized numeric and array helpers are explicit typed forms:
 - `(float32 value)` narrows any numeric value to Kotlin `Float`.
 - `(int32 value)` narrows any numeric value to Kotlin `Int`.
 - `(int32->string value)` converts a Kotlin `Int` interop value to `String`.
+- `(string-take text count)` lowers to Kotlin `String.take`.
+- `(string-pad-start text width char)` lowers to Kotlin `String.padStart`.
 - `(float-array value ...)` produces a Kotlin `FloatArray`; each value must be
   `Float32`.
 - `(float-array-ref array index)` reads a `Float32` from a `FloatArray` at an
diff --git a/lib/jerboa/typed/checker.ss b/lib/jerboa/typed/checker.ss
index 83d619d..0a163a6 100644
--- a/lib/jerboa/typed/checker.ss
+++ b/lib/jerboa/typed/checker.ss
@@ -400,6 +400,12 @@
       (cons 'int32->string
             (make-typed-call-sig (list 'Int32) 'String '()
               'jvm-to-string '()))
+      (cons 'string-take
+            (make-typed-call-sig (list 'String 'Int32) 'String '()
+              'jvm-string-take '()))
+      (cons 'string-pad-start
+            (make-typed-call-sig (list 'String 'Int32 'Char) 'String '()
+              'jvm-string-pad-start '()))
       ;; crypto primitives — FFI to vetted RustCrypto crates, never reimplemented.
       ;; Each carries kind 'crypto-prim and an info `prim` the emitter dispatches
       ;; on; the Rust block they emit references the crate (sha2/hmac/hkdf) that
diff --git a/lib/jerboa/typed/kotlin/lower.ss b/lib/jerboa/typed/kotlin/lower.ss
index a7897c3..fb13e7e 100644
--- a/lib/jerboa/typed/kotlin/lower.ss
+++ b/lib/jerboa/typed/kotlin/lower.ss
@@ -222,6 +222,10 @@
            (make-kt-member-call (car args) 'toInt '()))]
         [(jvm-to-string)
          (make-kt-member-call (car args) 'toString '())]
+        [(jvm-string-take)
+         (make-kt-member-call (car args) 'take (cdr args))]
+        [(jvm-string-pad-start)
+         (make-kt-member-call (car args) 'padStart (cdr args))]
         [(jvm-float-array)
          (make-kt-call (kt-name1 'floatArrayOf) args)]
         [(jvm-float-array-ref)
diff --git a/tests/test-typed-kotlin.ss b/tests/test-typed-kotlin.ss
index 2c45209..96e1aa7 100644
--- a/tests/test-typed-kotlin.ss
+++ b/tests/test-typed-kotlin.ss
@@ -221,17 +221,21 @@
      (type Int32)
      (def (sourceKey (sourceSha1 : String) (page : Int32) (dpi : Int32)) : String
        (string-append
-         sourceSha1
+         (string-take sourceSha1 (int32 16))
          (string-append
            "-p"
            (string-append
-             (int32->string page)
+             (string-pad-start (int32->string page) (int32 4) #\0)
              (string-append "-d" (int32->string dpi))))))))
 
 (define key-kotlin (typed-library-form->kotlin-string key-form))
 
 (test-contains "Int32 to string lowers to Kotlin toString" key-kotlin
   "page.toString()")
+(test-contains "String take lowers to Kotlin take" key-kotlin
+  "sourceSha1.take(16)")
+(test-contains "String padStart lowers to Kotlin padStart" key-kotlin
+  "page.toString().padStart(4, '0')")
 
 (printf "typed-kotlin tests: ~a passed, ~a failed~%" pass fail)
 (when (> fail 0) (exit 1))