Lower typed Kotlin return statements
ober
d8411d7cb83e3606bf11b4426042360829284ae0
--- a/lib/jerboa/typed/checker.ss +++ b/lib/jerboa/typed/checker.ss @@ -3199,6 +3199,10 @@ (append cond-errors body-errors))))] [(break continue) (values moved '())] + [(return) + (if (= (length args) 1) + (check-ownership-expression (car args) env moved) + (values moved '()))] [(try) (if (= (length args) 2) (let ([catch-form (expr-value (cadr args))]) @@ -3389,6 +3393,31 @@ exception-ir)) (append exception-errors result-type-errors)))))])) + (def (infer-return args env type-names expr) + (cond + [(null? args) + (values + (make-typed-ir-return + 'Unit + (expr-source expr) + (make-typed-ir-lit 'Unit (expr-source expr) '())) + '())] + [(= (length args) 1) + (let-values ([(value-ir value-errors) + (infer-expression (car args) env type-names)]) + (values + (and value-ir + (make-typed-ir-return + 'Unit + (expr-source expr) + value-ir)) + value-errors))] + [else + (values #f + (list (error-at expr 'bad-return + "return expects zero or one expression" + expr)))])) + (def (infer-try args env type-names expr) (cond [(not (= (length args) 2)) @@ -3522,6 +3551,8 @@ (list (error-at expr 'bad-continue "continue expects no operands" expr))))] + [(return) + (infer-return args env type-names expr)] [(throw) (infer-throw args env type-names expr)] [(try) --- a/lib/jerboa/typed/core.ss +++ b/lib/jerboa/typed/core.ss @@ -62,6 +62,10 @@ make-typed-ir-continue typed-ir-continue-type typed-ir-continue-source + typed-ir-return? + make-typed-ir-return + typed-ir-return-type typed-ir-return-source typed-ir-return-expr + typed-ir-throw? make-typed-ir-throw typed-ir-throw-type typed-ir-throw-source @@ -147,6 +151,7 @@ (defstruct typed-ir-while (type source test body)) (defstruct typed-ir-break (type source)) (defstruct typed-ir-continue (type source)) + (defstruct typed-ir-return (type source expr)) (defstruct typed-ir-throw (type source exception)) (defstruct typed-ir-try (type source body catch-name catch-type catch-body)) (defstruct typed-ir-lambda (type source params body)) @@ -277,6 +282,7 @@ (typed-ir-while? x) (typed-ir-break? x) (typed-ir-continue? x) + (typed-ir-return? x) (typed-ir-throw? x) (typed-ir-try? x) (typed-ir-lambda? x) @@ -298,6 +304,7 @@ [(typed-ir-while? node) (typed-ir-while-type node)] [(typed-ir-break? node) (typed-ir-break-type node)] [(typed-ir-continue? node) (typed-ir-continue-type node)] + [(typed-ir-return? node) (typed-ir-return-type node)] [(typed-ir-throw? node) (typed-ir-throw-type node)] [(typed-ir-try? node) (typed-ir-try-type node)] [(typed-ir-lambda? node) (typed-ir-lambda-type node)] @@ -320,6 +327,7 @@ [(typed-ir-while? node) (typed-ir-while-source node)] [(typed-ir-break? node) (typed-ir-break-source node)] [(typed-ir-continue? node) (typed-ir-continue-source node)] + [(typed-ir-return? node) (typed-ir-return-source node)] [(typed-ir-throw? node) (typed-ir-throw-source node)] [(typed-ir-try? node) (typed-ir-try-source node)] [(typed-ir-lambda? node) (typed-ir-lambda-source node)] --- a/lib/jerboa/typed/kotlin/lower.ss +++ b/lib/jerboa/typed/kotlin/lower.ss @@ -854,6 +854,10 @@ (make-kt-break)] [(typed-ir-continue? ir) (make-kt-continue)] + [(typed-ir-return? ir) + (make-kt-block + (list (make-kt-return (lower-expr (typed-ir-return-expr ir)))) + (make-kt-lit 'Unit '()))] [(typed-ir-throw? ir) (make-kt-throw (lower-expr (typed-ir-throw-exception ir)))] [(typed-ir-try? ir) @@ -918,6 +922,8 @@ (make-kt-while (lower-expr (typed-ir-while-test ir)) (lower-unit-statements (typed-ir-while-body ir))))] + [(typed-ir-return? ir) + (list (make-kt-return (lower-expr (typed-ir-return-expr ir))))] [(and (typed-ir-call? ir) (eq? (typed-ir-call-kind ir) 'record-setter)) (list (lower-record-setter-statement ir))] --- a/tests/test-typed-checker.ss +++ b/tests/test-typed-checker.ss @@ -2016,6 +2016,28 @@ (int32 1))))) '(while-body-type-mismatch)) +(test "return expression typechecks in sequence" + (error-kinds + '(typed-library (control return-ok) + (export f) + (type Int32) + (def (f (ready : Bool)) : Bool + (begin + (if ready + (return #t) + (begin)) + #f)))) + '()) + +(test "return rejects too many operands" + (error-kinds + '(typed-library (control return-bad) + (export f) + (type Int32) + (def (f) : Unit + (return (int32 1) (int32 2))))) + '(bad-return)) + (printf "~%Typed checker: ~a passed, ~a failed~%" pass fail) (when (> fail 0) (exit 1)) --- a/tests/test-typed-kotlin.ss +++ b/tests/test-typed-kotlin.ss @@ -1502,6 +1502,20 @@ (def (ready) : Bool (densityReady density))))) +(define return-form + '(typed-library (sample typed returns) + (export guarded) + (type Int32) + (def (guarded (ready : Bool)) : Bool + (begin + (if ready + (return #t) + (begin)) + #f)))) + +(define return-kotlin + (typed-library-form->kotlin-string return-form)) + (define class-declaration-kotlin (typed-library-form->kotlin-string class-declaration-form)) @@ -1520,6 +1534,9 @@ (test-contains "typed class declaration lowers method modifiers" class-declaration-kotlin "override fun performClick(): Boolean {\n return run {\n bindSelf(this)\n super.performClick()\n true\n}") +(test-contains "typed return lowers to Kotlin return statement" + return-kotlin + "return true") (printf "typed-kotlin tests: ~a passed, ~a failed~%" pass fail) (when (> fail 0) (exit 1))