/cl-kotlin-generator

convert s-expressions to kotlin (works for some examples)

Primary LanguageCommon Lisp

Goal

The purpose of this Lisp package is to bring the power of Common Lisp macros to Android development.

This is the eigth in a series of code generators.

  • https://github.com/plops/cl-cpp-generator I tried this generator with C/C++/ISPC/OpenCL/Cuda. It was my first attempt. The largest project with this is a firmware for a microcontroller. The difficult part is to get placement of semicolons right. I’m not terribly happy with the current solution. People don’t like that every function call has to be explicitly stated as such. Initially I thought it would help me to add function parameter completion in emacs. But I never figured out how to do that and in later code generators I simplified the lisp syntax.
  • https://github.com/plops/cl-ada-generator (abandoned) I always wanted to have a VHDL code generator and thought that ADA would be a good target to support a similar language. Unfortunately ADA and VHDL have a lot of syntactic constructs which I find difficult to express in Lisp semantics that I can remember. So I stopped working in this direction.
  • https://github.com/plops/cl-py-generator At a new job I generated LOTS of python code (75k lines) with this generator. The difficult part was to get indents right. It works really well. I should backport some features from cl-golang-generator: Variable type declaration, when, unless, unitary - and unitary /, logior, logand, incf, decf.
  • https://github.com/plops/cl-js-generator I played around with webrtc and webgl in the browser. I used parenscript before and I really like the way it upholds lisp semantics (every expression returns a value). However, the generated javascript can be difficult to read (and compare to s-expressions). For this project my goal was to have a very minimal mapping from s-expressions to javascript. Turns out converting lisp to javascript is very straightforward.
  • https://github.com/plops/cl-wolfram-generator (abandoned) At some point I was able to download a wolfram language license. I think this language is very close to Lisp. I tried some code generation but the free license would only work on one computer which is not how I work.
  • https://github.com/plops/cl-yasm-golang (abandoned for now, FIXME I accidentally called this golang and not generator). I was playing with the idea to program bare to the metal with either LLVM IR or amd64 assembly. Some prototyping indicated that this has extra challenges that can’t be easily addressed in my ‘single-function-code-generator’ approach. These are distributing variables on registers, memory handling. Also I’m not sure how much or if I could immediatly profit from existing tooling if I dump assembly or machine code.
  • https://github.com/plops/cl-golang-generator I used this to learn a bit of Go. I implemented quite a few examples of the Golang Programming book. In particular I like how straight forward it was to add common lisp type declarations. I’m very happy with how this experiment turned out. Golang is an expressive, simple language. Implementing the code generator was much faster than my C generator (because I don’t have to think about semicolons). Distributing the binaries is much easier than Python code. They are however so large (>20Mb) that I wonder if writing Common Lisp directly wouldn’t be the better approach.

Examples

comment
01define layout in xml for a few buttons and some kotlin handlers (based on Big Nerd Ranch quiz_activity)
02open opengles context and draw dark red background
03read sensors and compute device orientation
04read out camera images, also ask for permission
05render script
06grpc, also uses reactivex to form http connection
07store gps nmea messages in a temporary file
08store key in secure container
09write compressed data into file (streaming)
10write compressed and encrypted stream to file
_02try composable jetpack and keyword arguments (documentation isn’t good enough yet)
_03try android tv app with opengl (currently i have difficulty to get the boilerplate working)

How to run

  • Note: I realize that having to install the code in /home/martin/stage is not acceptable for other users. I haven’t decided how to handle directories, though. So far absolute paths seemed the easiest solution for now.
  • install sbcl, quicklisp and emacs
  • install android studio and android sdk
mkdir -p /home/martin/stage
cd /home/martin/stage
git pull https://github.com/plops/cl-kotlin-generator
ln -s /home/martin/stage/cl-kotlin-generator ~/quicklisp/local-projects

Developing the first example

The project was created in Android Studio 3.6 Canary 5. Older versions will not open it.

Directory structure

  • an android project consists of a lot of different files
  • currently the lisp code generates kotlin and xml files. these are required to implement the logic and layout of the gui

FirstGame/app/src/main/java/com/example/firstgame/MainActivity.kt FirstGame/app/src/main/res/layout/activity_main.xml FirstGame/app/src/main/res/layout/content_main.xml FirstGame/app/src/main/res/values/strings.xml

  • https://stackoverflow.com/questions/20801042/how-to-create-android-project-with-gradle-from-command-line
  • apparently it used to be possible to create an android project from the command line
  • for now each lisp example overwrites files in a single android project. that works for me but has the drawback that the different expanded examples can’t be viewed in the repo.
  • gradle files are written in groovy language syntax. currently i don’t generate them from lisp. unfortunately that means that two gradle files and the gradle.properties need to be edited to make the examples run
  • the proto file for the grpc example is also stored directly in the repo. ideally i would want to generate this from lisp as well

XML generation

Formatting

  • use ktlint for kotlin and xmllint for xml
  • the formatter coming with android studio seems to be a joke:

$ time ~/Downloads/android-studio/bin/format.sh -r . Android Studio 3.6 Canary 5, build AI-191.7479.19.36.5721125 Formatter Formatting /home/martin/stage/cl-kotlin-generator/examples/01_quiz/QuizActivity/app/src/main/java/com/example/quizactivity/QuizActivity.kt…OK Formatting /home/martin/stage/cl-kotlin-generator/examples/01_quiz/QuizActivity/app/src/main/res/layout/QuizActivity.xml…OK

2 file(s) formatted.

real 0m16.501s user 0m46.403s sys 0m1.469s

  • it requires 16 seconds and i can’t run it when a android-studio session is running
  • the formatted files look nice, though
  • perhaps there is a way to keep the java process running to prevent a startup time. i haven’t found anything

Open Code in Android Studio

  • select Open Existing Project and navigate to examples/01_quiz/QuizActivity

Test code on Phone

  • switch phone into developer mode
  • enable remote debug in phone
  • run `adb connect 192.168.1.135:5555` in android studio terminal
  • press run-> run app (only works sometimes)
  • build -> build bundels / apk -> build apks
  • install apk manually: `adb install -r /home/martin/stage/cl-kotlin-generator/examples/01_quiz/QuizActivity/app/build/outputs/apk/debug/app-debug.apk`

Discussion of the first example

  • I’m quite happy that a single file (examples/01_quiz/gen.lisp) with less than 100 lines can define a minimal app. This is a good starting point for more experiments.
  • I’m not happy that I had to import a bunch of files that were automatically generated by android studio. Looking into the APK I don’t think there is a way around this. The APK contains animations and icons that are perhaps required.
  • I assume it will be straightforward to regenerate the project with the wizard of future Android studio versions. Hopefully changes stay small so that I can use xml and kt files that are generated by Common Lisp.

Continue

  • store state when android activity changes
  • i learned that pressing the back button destroys an activity while the home button keeps it alive
  • Analyze->Inspect Code

Android Resources Validation activity_main.xml Cannot resolve symbol ‘@+id/textview’ Cannot resolve symbol ‘@+id/false_button’ Cannot resolve symbol ‘@+id/textview’ Cannot resolve symbol ‘@+id/true_button’

File storage

  • example 07 writes nmea gps messages into a file
130|libra:/data/data/com.example.quizactivity/cache # tail -f gps_nmea_log.csv
  • when the apk is overwritten the file stays
  • when the app is in the background it continues writing
  • when the apk is uninstalled the file might be deleted. i haven’t tested this

References

References (Library Books)

Android Cookbook 2017 O’Reilly

  • to dennis ritchie
  • where to catch exceptions
  • opengl spinning cube
  • looks all a bit dated, no kotlin

Big Nerd Ranch Guide 2017

  • laying out ui
  • MVC
  • running on device
  • debugging
  • example crime reporting app, seems give quite a broad overview
  • communication with intents
  • ui fragment
  • implicit intents
  • background service
  • material design
  • no kotlin, no opengl

RenderScript parallel computing on Android, the easy way