Add Kotlin anonymous object AST support

ober

f4b32f4149e32626e98c21eb890dd082e53fcb1b

diff --git a/lib/jerboa/typed/kotlin/ast.ss b/lib/jerboa/typed/kotlin/ast.ss
index 496b1f4..099fca6 100644
--- a/lib/jerboa/typed/kotlin/ast.ss
+++ b/lib/jerboa/typed/kotlin/ast.ss
@@ -27,7 +27,8 @@
     kt-class-annotations
 
     kt-function? make-kt-function
-    kt-function-visibility kt-function-name kt-function-params
+    kt-function-visibility kt-function-modifiers
+    kt-function-name kt-function-params
     kt-function-return-type kt-function-body kt-function-annotations
 
     kt-property? make-kt-property
@@ -72,6 +73,9 @@
     kt-lambda? make-kt-lambda
     kt-lambda-params kt-lambda-body
 
+    kt-object-expr? make-kt-object-expr
+    kt-object-expr-super-types kt-object-expr-body
+
     kt-binary? make-kt-binary
     kt-binary-op kt-binary-left kt-binary-right
 
@@ -112,7 +116,7 @@
   (defstruct kt-class
     (kind visibility name params super-types body annotations))
   (defstruct kt-function
-    (visibility name params return-type body annotations))
+    (visibility modifiers name params return-type body annotations))
   (defstruct kt-property
     (visibility mutable? name type init annotations))
 
@@ -131,6 +135,7 @@
   (defstruct kt-member-get (target name))
   (defstruct kt-index-get (target index))
   (defstruct kt-lambda (params body))
+  (defstruct kt-object-expr (super-types body))
   (defstruct kt-binary (op left right))
   (defstruct kt-unary (op expr))
   (defstruct kt-if (test then else))
diff --git a/lib/jerboa/typed/kotlin/lower.ss b/lib/jerboa/typed/kotlin/lower.ss
index 9f8a6fe..02e2fcd 100644
--- a/lib/jerboa/typed/kotlin/lower.ss
+++ b/lib/jerboa/typed/kotlin/lower.ss
@@ -868,6 +868,7 @@
         (error 'lower-def "missing elaborated IR for typed definition" (typed-def-name def)))
       (make-kt-function
         #f
+        '()
         (typed-def-name def)
         (map lower-param (typed-def-params def))
         (typed-type->kotlin-type (typed-def-return-type def))
diff --git a/lib/jerboa/typed/kotlin/print.ss b/lib/jerboa/typed/kotlin/print.ss
index e59e4d9..62626dd 100644
--- a/lib/jerboa/typed/kotlin/print.ss
+++ b/lib/jerboa/typed/kotlin/print.ss
@@ -231,6 +231,7 @@
         (kt-if? expr)
         (kt-block? expr)
         (kt-when? expr)
+        (kt-object-expr? expr)
         (kt-lambda? expr)))
 
   (def (kotlin-member-target->string expr)
@@ -280,6 +281,22 @@
            " -> "
            (kotlin-expr->string (kt-lambda-body expr))
            " }"))]
+      [(kt-object-expr? expr)
+       (emit-to-string
+         (lambda (port)
+           (display "object" port)
+           (let ([supers (kt-object-expr-super-types expr)])
+             (unless (null? supers)
+               (display " : " port)
+               (display (join-strings (map kotlin-type->string supers) ", ") port)))
+           (display " {" port)
+           (newline port)
+           (for-each
+             (lambda (decl)
+               (write-declaration port 1 decl)
+               (newline port))
+             (kt-object-expr-body expr))
+           (display "}" port)))]
       [(kt-binary? expr)
        (parenthesize
          (string-append
@@ -407,12 +424,26 @@
         (string-append " : "
                        (join-strings (map kotlin-type->string supers) ", ")))))
 
+  (def (kotlin-modifier->string modifier)
+    (cond
+      [(symbol? modifier) (symbol->string modifier)]
+      [(string? modifier) modifier]
+      [else (error 'kotlin-modifier->string "unsupported Kotlin modifier" modifier)]))
+
+  (def (modifier-prefix modifiers)
+    (if (null? modifiers)
+      ""
+      (string-append
+        (join-strings (map kotlin-modifier->string modifiers) " ")
+        " ")))
+
   (def (write-function port indent fn)
     (for-each (lambda (line) (write-line port indent line))
               (annotation-lines (kt-function-annotations fn)))
     (write-line port indent
       (string-append
         (visibility-prefix (kt-function-visibility fn))
+        (modifier-prefix (kt-function-modifiers fn))
         "fun "
         (kotlin-symbol-name (kt-function-name fn))
         "("
diff --git a/tests/test-typed-kotlin.ss b/tests/test-typed-kotlin.ss
index bb5b6e2..991acf1 100644
--- a/tests/test-typed-kotlin.ss
+++ b/tests/test-typed-kotlin.ss
@@ -77,6 +77,7 @@
     (list
       (make-kt-function
         #f
+        '()
         'add-one
         (list (make-kt-param 'x (make-kt-type 'ULong #f '()) #f #f #f #f))
         (make-kt-type 'ULong #f '())
@@ -87,6 +88,30 @@
               (make-kt-lit 'Nat 1))))
         '()))))
 
+(test "anonymous object expression printer"
+  (kotlin-expr->string
+    (make-kt-object-expr
+      (list (make-kt-type 'TextWatcher #f '()))
+      (list
+        (make-kt-function
+          #f
+          '(override)
+          'afterTextChanged
+          (list (make-kt-param
+                  's
+                  (make-kt-type 'Editable #t '())
+                  #f #f #f #f))
+          (make-kt-type 'Unit #f '())
+          (list (make-kt-expr-stmt (make-kt-lit 'Unit '())))
+          '()))))
+  (string-append
+    "object : TextWatcher {\n"
+    "    override fun afterTextChanged(s: Editable?): Unit {\n"
+    "        Unit\n"
+    "    }\n"
+    "\n"
+    "}"))
+
 (define ast-file-text
   (string-append
     "// Generated by Jerboa's typed Kotlin backend. Do not edit.\n\n"