example/ivy: make ivy as a separate module, and update to use AndroidX

golang.org/x/mobile/example/ivy module specifies dependency on
golang.org/x/mobile and robpike.io/ivy versions.

- Updated to use AndroidX and target API level 30 to meet
the current Google Play policies
https://support.google.com/googleplay/android-developer/answer/9859152?visit_id=637402646062706504-1797308153&rd=1#targetsdk&zippy=%2Ctarget-api-level-requirements-for-play-console
- Updated demo.ivy script (copied from 66c48de6eb/demo/demo.ivy)
- Added example/ivy/android/README.md

Change-Id: Ie613ecdba4c3d77b5c45ef8a792fba6ee8a2c5cf
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/356729
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Cherry Mui <cherryyz@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Hana (Hyang-Ah) Kim 2021-10-16 15:12:49 -04:00 committed by Hyang-Ah Hana Kim
parent 122ae57121
commit eb3c0abee2
14 changed files with 189 additions and 43 deletions

4
.gitignore vendored
View File

@ -5,9 +5,13 @@ last-change
*.framework
*.xcframework
*.aar
*.jar
*.iml
.idea
.gradle
*.properties
example/ivy/**/build/
example/ivy/android/gradle/
# Xcode configuration files.
*.xcworkspace

View File

@ -1,8 +0,0 @@
Ivy Android app
Run
$ gomobile bind -o app/ivy.aar robpike.io/ivy/mobile
and import this project in Android Studio. If you prefer the command
line, use gradle to build directly.

View File

@ -0,0 +1,42 @@
## Ivy Big Number Calculator (Android)
[Ivy (robpike.io/ivy)](https://robpike.io/ivy) is an interpreter for an APL-like language written in Go.
This repository hosts a minimal Android project used for its [Android version](https://play.google.com/store/apps/details?id=org.golang.ivy&hl=en_US&gl=US).
### How to build
Requirements
- Go 1.17 or newer
- Android SDK
- Android NDK
- `golang.org/x/mobile/cmd/gomobile`
The `gomobile` command uses `ANDROID_HOME` and `ANDROID_NDK_HOME` environment variables.
```
export ANDROID_HOME=/path/to/sdk-directory
export ANDROID_NDK_HOME=/path/to/ndk-directory
```
Note: Both ANDROID_SDK_ROOT and ANDROID_NDK_HOME are deprecated in Android tooling, but `gomobile` still uses it. In many cases, `ANDROID_HOME` corresponds to the new [`ANDROID_SDK_ROOT`](https://developer.android.com/studio/command-line/variables). If you installed NDK using [Android Studio's SDK manager](https://developer.android.com/studio/projects/install-ndk#default-version), use the `$ANDROID_SDK_ROOT/ndk/<ndk-version>/` directory as `ANDROID_NDK_HOME` (where `<ndk-version>` is the NDK version you want to use when compiling `robpike.io/ivy` for Android.
(TODO: update `gomobile` to work with modern Android layout)
From this directory, run:
```sh
go install golang.org/x/mobile/cmd/gomobile@latest
go install golang.org/x/mobile/cmd/gobind@latest
# Make sure `gomobile` and `gobind` is in your `PATH`.
gomobile bind -o app/ivy.aar robpike.io/ivy/mobile
```
Open this directory from Android Studio, and build.
`robpike.io/ivy` and `golang.org/x/mobile` are required dependencies of this main module. In order to update them:
```
go get -d golang.org/x/mobile@latest
go get -d robpike.io/ivy/mobile
go mod tidy
```

View File

@ -1,17 +1,11 @@
apply plugin: 'com.android.application'
repositories {
flatDir {
dirs '.'
}
}
android {
compileSdkVersion 23
compileSdkVersion 30
defaultConfig {
applicationId 'org.golang.ivy'
minSdkVersion 15
targetSdkVersion 23
targetSdkVersion 30
versionCode 3
versionName '1.0.2'
}
@ -26,6 +20,6 @@ android {
}
dependencies {
implementation 'com.android.support:appcompat-v7:23.3.0'
implementation (name:'ivy', ext:'aar')
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation files('ivy.aar')
}

View File

@ -16,14 +16,16 @@
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:theme="@style/IvyAppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysVisible">
android:windowSoftInputMode="adjustResize|stateAlwaysVisible"
android:fullBackupContent="true">
<activity
android:name=".MainActivity"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:windowSoftInputMode="adjustResize|stateUnchanged|stateAlwaysVisible"
android:configChanges="orientation|screenSize">
android:configChanges="orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

62
example/ivy/android/app/src/main/assets/demo.ivy Executable file → Normal file
View File

@ -1,4 +1,5 @@
# This is ivy. Type a newline to advance to each new step. Type one now.
# This is a demo of ivy. Type a newline to advance to each new step. Type one now.
# At any time, type the word "quit" or EOF to end the demo and return to ivy.
# Each step in the demo is one line of input followed by some output from ivy. Type a newline now to see.
2+2
# The first line you see above (2+2) is input; the next (4) is output from a running ivy.
@ -24,7 +25,7 @@
1/3 ** 2 # We'll see non-integral exponents later.
# Even when a number is input in floating notation, it is still an exact rational number inside.
1.2
# In fact, ivy is a "bignum" calculator that can handle huge numbers and rationals made of huge numers.
# In fact, ivy is a "bignum" calculator that can handle huge numbers and rationals made of huge numbers.
1e10 # Still an integer.
1e100 # Still an integer.
1e10/3 # Not an integer, but an exact rational.
@ -42,11 +43,13 @@ code '💩' # char's inverse, the value of given character, here printed in
# Vectors are written and displayed with spaces between the elements.
1 2 3
1 4/3 5/3 (2+1/3)
# Note that without the parens this becomes (1 4/3 5/3 2)+1/3
1 4/3 5/3 2+1/3
# Vectors of characters print without quotes or spaces.
'h' 'e' 'l' 'l' 'o'
# This is a nicer way to write 'h' 'e' 'l' 'l' 'o'. It means the same.
'hello'
# Arithmetic works on vectors.
# Arithmetic works elementwise on vectors.
1 2 3 + 4 5 6
# Arithmetic between scalar and vector also works, either way.
23 + 1 2 3
@ -78,13 +81,13 @@ iota 15
*/iota 100
# Type this: */iota 10000
# That printed using floating-point notation for manageability but it is still an integer inside.
# max and min are binary operators that do the obvious. (Use semicolons to separate expresssions.)
# max and min are binary operators that do the obvious. (Use semicolons to separate expressions.)
3 max 7; 'is max and'; 3 min 7; 'is min'
# Like all binary arithmetic operators, max applies elementwise.
2 3 4 max 4 3 2
# Reduce using max to find maxmimum element in vector.
# Reduce using max to find maximum element in vector.
max/2 34 42 233 2 2 521 14 1 4 1 55 133
# Ivy allows multidimensional arrays. The shape operator binary rho builds them.
# Ivy allows multidimensional arrays. The binary shape operator, rho, builds them.
# Dimension (which may be a vector) on the left, data on the right.
5 rho 1
5 5 rho 1
@ -113,6 +116,8 @@ x**10
# That's a letter 'o', dot, star.
# Any operator works; here is how to make an identity matrix.
x = iota 5; x o.== x
# Assignment is an operator, so you can save an intermediate expression.
x o.== x = iota 5
# Random numbers: Use a unary ? to roll an n-sided die from 1 to n.
?100
?100
@ -144,7 +149,7 @@ x = ?10 rho 6; x
2**64
2**iota 64
-1+2**63
# Settings are made and queried with a leading right paren. )help lists the settings
# Settings are made and queried with a leading right paren. )help helps with settings and other commands.
)help
# Use )base to switch input and output to base 16.
)base 16
@ -155,8 +160,9 @@ _
(2**40)-1 # The largest 64-bit number base 16.
)obase 10 # Output base 10, input base still 16.
)base
-1+2**63 # The largest 63-bit number base 10.
-1+2**64 # The largest 64-bit number base 10.
# The largest 63-bit number base 10.
-1+2**40 # The largest 64-bit number base 10.
-1+2**3F # The largest 63-bit number base 10.
# Go back to base 10 input and output.
)base 10
# Rationals can be very big too.
@ -188,21 +194,21 @@ e**1e6
log e**1e6
log e**1e8
log 1e1000000 # Yes, that is 10 to the millionth power.
# Transcendentals. (The low bits aren't always quite right...)
# Transcendentals. (The low bit isn't always right...)
sin pi/2
cos .25*pi * -1 + iota 9
log iota 6
# Successive approximations to e. (We force the calculation to use float using the "float" unary operator. Why?)
(float 1+10**-iota 9) ** 10**iota 9
# Default precision is 256 bits of mantissa. We can go up to 10000.
)prec 3000 # Units are bits, not digits.
)prec 3350 # Units are bits, not digits. 2 log 10 == 3.321. Add a few more bits for floating point errors.
e
)format '%.1000g' # Units are digits. (Sorry for the inconsistency.)
e
pi
sqrt 2
e**1e6
log e**1e6 # Only 904 good digits; the log algorithm is numerically weak. (Ideas welcome.)
log e**1e6
(2**1e3)/(3**1e2)
# User-defined operators are declared as unary or binary (or both). This one computes the (unary) average.
op avg x = (+/x)/rho x
@ -218,12 +224,40 @@ op popcount n = +/n base 2
popcount 7
popcount 1e6
popcount 1e100
# Here is one to sum the digits. The unary operator text turns its argument into text, like Sprintf.
# Here is one to sum the digits. The unary operator text turns its argument into text, like sprintf.
op sumdigits x = t = text x; +/(code (t in '0123456789') sel t) - code '0'
# Break it down: The sel operator selects from the right based on the non-zero elements in the left.
# The in operator generates a selector by choosing only the bytes that are ASCII digits.
sumdigits 99
sumdigits iota 10
sumdigits '23 skidoo' # Note: It counts only the digits.
# The binary text operator takes a format string (% optional) on the left and formats the value.
'%x' text 1234
# We can use this for another version of popcount: %b is binary.
op popcount n = +/'1' == '%b' text n
popcount 7
popcount 1e6
popcount 1e100
# A classic (expensive!) algorithm to count primes.
op primes N = (not T in T o.* T) sel T = 1 drop iota N
# The assignment to T gives 2..N. We use outer product to build an array of all products.
# Then we find all elements of T that appear in the product matrix, invert that, and select from the original.
primes 100
# A final trick.
# The binary ? operator "deals": x?y selects at random x distinct integers from 1..y inclusive.
5?10
# We can use this to shuffle a deck of cards. The suits are ♠♡♣♢, the values
# A234567890JQK (using 0 for 10, for simplicity).
# Create the deck using outer product with the ravel operator:
"A234567890JQK" o., "♠♡♣♢"
# To shuffle it, ravel into into a vector and index that by 1 through 52, shuffled.
(, "A234567890JQK" o., "♠♡♣♢")[52?52]
# There is no looping construct in ivy, but there is a conditional evaluator.
# Within a user-defined operator, one can write a condition expression
# using a binary operator, ":". If the left-hand operand is true (integer non-zero),
# the user-defined operator will return the right-hand operand as its
# result; otherwise execution continues.
op a gcd b = a == b: a; a > b: b gcd a-b; a gcd b-a
1562 gcd !11
# That's it! Have fun.
# For more information visit https://godoc.org/robpike.io/ivy
# For more information visit https://pkg.go.dev/robpike.io/ivy

View File

@ -9,7 +9,6 @@ package org.golang.ivy;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@ -17,6 +16,8 @@ import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
/*
* Handles About menu item.
*/

View File

@ -10,11 +10,12 @@ package org.golang.ivy;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
import mobile.Mobile;
/*
@ -37,12 +38,11 @@ public class Help extends AppCompatActivity {
}
});
webView.getSettings().setDefaultTextEncodingName("utf-8");
// org.golang.ivy.Mobile was generated
// using gomobile bind -javapkg=org.golang.ivy robpike.io/ivy/mobile.
// mobile.Mobile was generated using gomobile bind robpike.io/ivy/mobile.
String helpMsg = Mobile.help();
// loadData has a rendering bug: https://code.google.com/p/android/issues/detail?id=6965
webView.loadDataWithBaseURL("http://godoc.org/robpike.io/ivy", helpMsg, "text/html", "UTF-8", null);
webView.loadDataWithBaseURL("http://pkg.go.dev/robpike.io/ivy", helpMsg, "text/html", "UTF-8", null);
webView.setBackgroundColor(getResources().getColor(R.color.body));
}

View File

@ -12,7 +12,6 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@ -28,10 +27,13 @@ import android.widget.ImageButton;
import android.widget.ScrollView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// This is in ivy.aar.
import mobile.Mobile;
/*

View File

@ -2,17 +2,16 @@
buildscript {
repositories {
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
classpath 'com.android.tools.build:gradle:7.0.3'
}
}
allprojects {
repositories {
google()
jcenter()
}
}

7
example/ivy/doc.go Normal file
View File

@ -0,0 +1,7 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This is an empty package.
// We have this package to convince this is buildable and go mod tidy can work.
package dummy

15
example/ivy/go.mod Normal file
View File

@ -0,0 +1,15 @@
module golang.org/x/mobile/example/ivy
go 1.17
require (
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7
robpike.io/ivy v0.1.4
)
require (
golang.org/x/mod v0.4.2 // indirect
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
golang.org/x/tools v0.1.2 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)

40
example/ivy/go.sum Normal file
View File

@ -0,0 +1,40 @@
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 h1:CyFUjc175y/mbMjxe+WdqI72jguLyjQChKCDe9mfTvg=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
robpike.io/ivy v0.1.4 h1:H61eItFW1TGNhq02v9UFDz+x5z4GkC3PNjJUVyizWb8=
robpike.io/ivy v0.1.4/go.mod h1:6B/DGaft5rvYiF7MgCTiZAAvH5W7vtu0eS2BW77updo=

14
example/ivy/tools.go Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ignore
package dummy
// This is a dummy go file to add required module dependencies to go.mod.
import (
_ "golang.org/x/mobile/bind"
_ "robpike.io/ivy"
)