Lower typed JVM list access to Kotlin
ober
609a5ad5bd9934bf11121218e2e15603ce0c77f8
--- a/lib/jerboa/typed/checker.ss +++ b/lib/jerboa/typed/checker.ss @@ -1548,6 +1548,70 @@ (list (cons 'index idx-name)))) (append size-errors body-errors type-errors)))))])) + (def (list-like-inner-type type) + (and (pair? type) + (memq (car type) '(List Vector MutableList)) + (cadr type))) + + (def (infer-list-size args env type-names expr) + (if (not (= (length args) 1)) + (values #f (bad-constructor-arity expr 'list-size 1 args)) + (let-values ([(list-ir errors) + (infer-expression (car args) env type-names)]) + (let* ([list-type (ir-type list-ir)] + [inner-type (list-like-inner-type list-type)] + [type-errors + (if inner-type + '() + (list (make-check-error 'argument-type-mismatch + "list-size expects a List, Vector, or MutableList value" + expr + (expr-source (car args)))))] + [ok? (and list-ir (null? errors) (null? type-errors))]) + (values + (and ok? + (make-typed-ir-call 'Int32 (expr-source expr) + 'jvm-list-size 'list-size (list list-ir) + (list (cons 'inner-type inner-type)))) + (append errors type-errors)))))) + + (def (infer-list-ref args env type-names expr) + (if (not (= (length args) 2)) + (values #f (bad-constructor-arity expr 'list-ref 2 args)) + (let-values ([(arg-irs errors) (infer-args args env type-names)]) + (let* ([types (ir-list-types arg-irs)] + [list-type (car types)] + [index-type (cadr types)] + [inner-type (list-like-inner-type list-type)] + [type-errors + (append + (if inner-type + '() + (list + (make-check-error + 'argument-type-mismatch + "list-ref expects a List, Vector, or MutableList value" + expr + (and (pair? args) (expr-source (car args)))))) + (if (eq? index-type 'Int32) + '() + (list + (make-check-error + 'argument-type-mismatch + "list-ref index must be Int32" + (list 'list-ref 'Int32 index-type) + (and (pair? (cdr args)) + (expr-source (cadr args)))))))] + [ok? (and (all-irs-valid? arg-irs) + (null? errors) + (null? type-errors))]) + (values + (and ok? + (make-typed-ir-call inner-type (expr-source expr) + 'jvm-list-ref 'list-ref arg-irs + (list (cons 'inner-type inner-type)))) + (append errors type-errors)))))) + (def (infer-make-bytevector args env type-names expr) ;; (make-bytevector size) or (make-bytevector size fill). Size and fill are ;; numeric; the result is a fresh Bytes buffer. A missing fill defaults to a @@ -2042,6 +2106,10 @@ (infer-float-array args env type-names expr)] [(int-array-build) (infer-int-array-build args env type-names expr)] + [(list-size) + (infer-list-size args env type-names expr)] + [(list-ref) + (infer-list-ref args env type-names expr)] [(bytes-build) (infer-bytes-build args env type-names expr)] [(option-some) --- a/lib/jerboa/typed/core.ss +++ b/lib/jerboa/typed/core.ss @@ -131,6 +131,8 @@ exact->inexact log2 debug-string + jvm-list-size + jvm-list-ref record-ctor record-pred record-accessor --- a/lib/jerboa/typed/kotlin/lower.ss +++ b/lib/jerboa/typed/kotlin/lower.ss @@ -302,6 +302,10 @@ (make-kt-lambda (list (info-ref info 'index 'index)) (cadr args))))] + [(jvm-list-size) + (make-kt-member-get (car args) 'size)] + [(jvm-list-ref) + (make-kt-index-get (car args) (cadr args))] [(jvm-boolean-array-ref) (make-kt-index-get (car args) (cadr args))] [(jvm-boolean-array-length) @@ -389,8 +393,8 @@ (list (make-kt-assign (kt-name1 acc-name) - (lower-expr (typed-ir-for-fold-body ir))))))) - (kt-name1 acc-name))) + (lower-expr (typed-ir-for-fold-body ir)))))) + (kt-name1 acc-name)))) (def (lower-expr ir) (cond --- a/tests/test-typed-kotlin.ss +++ b/tests/test-typed-kotlin.ss @@ -474,6 +474,57 @@ int-array-build-kotlin "IntArray(items.size, { index -> (items[index] + 1) })") +(define list-form + '(typed-library (sample typed lists) + (export make-Cell Cell? Cell-x listCount firstX secondName) + (type Int32) + (type Float32) + (record Cell + ((x : Float32) + (name : String))) + (def (listCount (cells : (List Cell))) : Int32 + (list-size cells)) + (def (firstX (cells : (MutableList Cell))) : Float32 + (Cell-x (list-ref cells (int32 0)))) + (def (secondName (cells : (List Cell))) : String + (Cell-name (list-ref cells (int32 1)))))) + +(define list-kotlin (typed-library-form->kotlin-string list-form)) + +(test-contains "List size lowers to Kotlin size" + list-kotlin + "fun listCount(cells: List<Cell>): Int") +(test-contains "List size returns member property" + list-kotlin + "return cells.size") +(test-contains "MutableList ref lowers to Kotlin indexing" + list-kotlin + "return cells[0].x") +(test-contains "List ref preserves element type" + list-kotlin + "return cells[1].name") + +(define fold-form + '(typed-library (sample typed fold) + (export sumTo) + (type Int32) + (def (sumTo (end : Int32)) : Int32 + (for/fold ((total (int32 0))) + ((i (in-range (int32 0) end))) + (+ total i))))) + +(define fold-kotlin (typed-library-form->kotlin-string fold-form)) + +(test-contains "for/fold lowers to Kotlin run block" + fold-kotlin + "return run {") +(test-contains "for/fold lowers Kotlin range loop" + fold-kotlin + "for (i in 0 until end)") +(test-contains "for/fold returns accumulator result" + fold-kotlin + "total\n}") + (define note-form '(typed-library (sample typed notes) (export appendNote)