Kotlin Multiplatform runtime infix expressions evaluator.

Overview

Kotlin multiplatform expressions evaluator

This is a kotlin multiplatform runtime infix expressions evaluator.

Overview

Operators

The library supports the following operators and special symbols:

  • +, -, *, / - mathematical operators
  • % - modulo. Returns the remainder of a division, after one number is divided by another
  • ^ - exponentiation. a^b means a raised to the power of b
  • &&, ||, ! - logical 'and', 'or', 'not' operators
  • ==, != - equality operators
  • <, >, <=, >= - comparison operators
  • a ? b : c - ternary operator

Constants

The library supports the following constants:

  • pi - PI
  • e - e
  • any custom constants.

Functions

The library supports the following functions:

Variables

Any symbols other than constants and function calls are resolved as variables during evaluation.

How to get

Gradle

Kotlin DSL

repositories {
    maven("https://maven.pkg.github.com/murzagalin/multiplatform-expressions-evaluator")
}

dependencies {
    implementation("com.github.murzagalin:multiplatform-expressions-evaluator:0.9.1")
}

Groovy

repositories {
    maven {
        url = uri("https://maven.pkg.github.com/murzagalin/multiplatform-expressions-evaluator")
    }
}

dependencies {
    implementation "com.github.murzagalin:multiplatform-expressions-evaluator:0.9.1"
}

Kotlin

Usage

1 && var", mapOf("x" to 3, "var" to true) ) //variables evaluator.evaluateDouble( "1 + x + y", mapOf("x" to 3, "y" to 4) ) //functions evaluator.evaluateDouble( "sin(x)^2+cos(x)^2", mapOf("x" to 2.0) ) //constants evaluator.evaluateDouble("cos(pi)") evaluator.evaluateDouble("ln(e^3)") ">
import com.github.murzagalin.evaluator.Evaluator

val evaluator = Evaluator()

//numeric values
evaluator.evaluateDouble("23 + 0.123 * (124 / -60.124)")

//boolean values
evaluator.evaluateBoolean(
    "x > 1 && var",
    mapOf("x" to 3, "var" to true)
)

//variables
evaluator.evaluateDouble(
    "1 + x + y",
    mapOf("x" to 3, "y" to 4)
)

//functions
evaluator.evaluateDouble(
    "sin(x)^2+cos(x)^2",
    mapOf("x" to 2.0)
)

//constants
evaluator.evaluateDouble("cos(pi)")
evaluator.evaluateDouble("ln(e^3)")

Custom functions

The library supports custom functions with any number of arguments. Supported argument and return types are Double and Boolean

Functions with constant number of arguments

For the example I will explain how to create a function that represents the general form of normal distribution probability density function: img.png

The function will have the following syntax: normal_dist(x, m, sigma). The parameter m is the mean of the distribution, while the parameter sigma is its standard deviation.

We define a function which is named "normal_dist" and has 3 arguments:

import com.github.murzagalin.evaluator.Function

object NormalDist : Function("normal_dist", 3) {
    override fun invoke(vararg args: Any): Any {
        val x = args.getAsDouble(0) { "$name argument must be a number" }
        val m = args.getAsDouble(1) { "$name mean must be a number" }
        val sigma = args.getAsDouble(2) { "$name sigma must be a number" }

        return 1.0 / sigma / sqrt(2 * PI) * exp(-1.0 / 2.0 * ((x - m) / sigma).pow(2))
    }
}

Note: the library checks if the number of arguments in an expression is equal to 3, otherwise it throws an exception. But you have to check the types of the arguments by yourself. Functions getAsDouble(index, lazyMessage) and getAsBoolean(index, lazyMessage) return an element at position index, and throw IllegalArgumentException with the message returned from lazyMessage if it has a wrong type

Then we add this function to the evaluator:

import com.github.murzagalin.evaluator.DefaultFunctions
import com.github.murzagalin.evaluator.Evaluator

fun main() {
    val evaluator = Evaluator(functions = DefaultFunctions.ALL + NormalDist)
    print(evaluator.evaluateDouble("normal_dist(12, 9, 3)"))
}

Functions with variable number of arguments

The process of creating functions with variable number of arguments is pretty much the same. The difference is how we define the function.

As an example I will create a function mult(a1, a2, ..., an) which is defined as a1 * a2 * ... * an:

acc * (x as Double) } } } ">
object Mult: Function("mult", 2..Int.MAX_VALUE) {
    override fun invoke(vararg args: Any): Any {
        require(args.all { it is Double }) { "$name function requires all arguments to be numbers" }

        return args.fold(1.0) { acc, x -> acc * (x as Double) }
    }
}

Note: we define minimum and maximum number of arguments as a range. It is also possible to define them separately: Function("mult", 2, Int.MAX_VALUE)

Then we add this function to the evaluator:

import com.github.murzagalin.evaluator.DefaultFunctions
import com.github.murzagalin.evaluator.Evaluator

fun main() {
    val evaluator = Evaluator(functions = DefaultFunctions.ALL + Mult)
    print(evaluator.evaluateDouble("mult(2, 3, 4)"))
}

Custom constants

The library supports custom constants. For the example I will show you how to add a golden ratio constant. We will define the constant named phi with the value 1.6180339887:

import com.github.murzagalin.evaluator.Constant
import com.github.murzagalin.evaluator.DefaultConstants
import com.github.murzagalin.evaluator.Evaluator

fun main() {
    val PHI = Constant("phi", 1.6180339887)
    val evaluator = Evaluator(constants = DefaultConstants.ALL + PHI)
    print(evaluator.evaluateDouble("x * phi", mapOf("x" to 2)))
}

Expressions preprocessing

By default, the library does the following steps to evaluate an expression:

  1. Tokenizing - splitting the expression into a list of units (operations, numbers, constants, function calls, etc.)
  2. Converting the expression from infix to postifx notation.
  3. Evaluating the postfix expression.

In case you have an expression with variables, it might make sense to preprocess the expression (do steps 1 and 2 in advance) to improve the performance:

import com.github.murzagalin.evaluator.Evaluator

fun main() {
    val evaluator = Evaluator()
    
    //step 1 and 2
    val preprocessedExpression = evaluator.preprocessExpression("1 + x + y^2")
    
    //step 3
    val result = evaluator.evaluateDouble(preprocessedExpression, mapOf("x" to 2, "y" to 4))
}

JVM

TBD

JS

TBD

IOS

TBD

License

This library is available for free under Apache 2.0 license.

Copyright (c) 2021 Azamat Murzagalin.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
Kotlin multiplatform library template.

template-kmp-library Kotlin multiplatform library template. Has a baseline setup for a multiplatform library supporting all kotlin targets except andr

BuildConfig for Kotlin Multiplatform Project

BuildKonfig BuildConfig for Kotlin Multiplatform Project. It currently supports embedding values from gradle file. Table Of Contents Motivation Usage

Kotlin multiplatform benchmarking toolkit

NOTE: Starting from version 0.3.0 of the library: The library runtime is published to Maven Central and no longer published to Bintray. The Gradle plu

Gradle plugin for simplify Kotlin Multiplatform mobile configurations
Gradle plugin for simplify Kotlin Multiplatform mobile configurations

Mobile Multiplatform gradle plugin This is a Gradle plugin for simple setup of Kotlin Multiplatform mobile Gradle modules. Setup buildSrc/build.gradle

Generic AST parsing library for kotlin multiplatform

kotlinx.ast kotlinx.ast is a generic AST (Abstract Syntax Tree) parsing library, Kotlin is currently the only supported language. The library is desig

KaMP Kit by Touchlab is a collection of code and tools designed to get your mobile team started quickly with Kotlin Multiplatform.
KaMP Kit by Touchlab is a collection of code and tools designed to get your mobile team started quickly with Kotlin Multiplatform.

KaMP Kit Welcome to the KaMP Kit! About Goal The goal of the KaMP Kit is to facilitate your evaluation of Kotlin Multiplatform (aka KMP). It is a coll

Kotlin Multiplatform Mobile App Template

KMMT : Kotlin Multiplatform Mobile Template Kotlin Multiplatform Mobile Development Simplified KMMT is a KMM based project template designed to simpli

GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform sample
GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform sample

GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform sample

Playground for learning Kotlin Multiplatform Mobile
Playground for learning Kotlin Multiplatform Mobile

This is a playground for learning KMP (KMM Plugin for android studio). Requirements Android Studio Canary 8 Architecture Thanks https://twitter.com/jo

Comments
  • Expressions Evaluator package requires authentication

    Expressions Evaluator package requires authentication

    Hi again @murzagalin!

    After trying to add your library to my kotlin multiplatform project, the gradle build failed with an error. So I tried to setup a new empty test project (via the project wizard of Android Studio) to verify that my configuration is not responsible for the error.

    I tested with a new Kotlin Multiplatform Library and a Kotlin Multiplatform App project. In both cases, I added your library as suggested in the README.

        repositories {
            maven {
                url = uri("https://maven.pkg.github.com/murzagalin/multiplatform-expressions-evaluator")
            }
        }
    
        sourceSets {
            val commonMain by getting {
                dependencies {
                    implementation("com.github.murzagalin:multiplatform-expressions-evaluator:0.11.0")
                }
            }
            // other stuff ...
        }
    

    Building the project gives the following error in both cases

    Could not GET 'https://maven.pkg.github.com/murzagalin/multiplatform-expressions-evaluator/com/github/murzagalin/multiplatform-expressions-evaluator/0.11.0/multiplatform-expressions-evaluator-0.11.0.pom'. Received status code 401 from server: Unauthorized
    Disable Gradle 'offline mode' and sync project
    

    Manually trying to access https://maven.pkg.github.com/murzagalin/multiplatform-expressions-evaluator/com/github/murzagalin/multiplatform-expressions-evaluator/0.11.0/multiplatform-expressions-evaluator-0.11.0.pom also requires authentication.

    It appears that the Github Package is private. Is that intended, or is it possible to make it publicly accessible without authentication?

    opened by flixlo 13
  • Distribution via Maven Central

    Distribution via Maven Central

    Hi @murzagalin!

    At the moment, multiplatform-expressions-evaluator is distributed via Github Packages. The fact, that Github Packages requires authentication to fetch dependencies makes the setup kinda cumbersome. For example, in a team of multiple developers working on the same project, each developer needs to manually configure the authentication credentials. Also, if you want to use CI & CD it requires additional configuration for the credentials.

    That's why I'd highly recommend to upload the library to the Maven Central Repository. This would also make it easier for other developers to use your library, because it drastically simplifies the setup process.

    opened by flixlo 5
  • Adding iOS support for kotlin multiplatform mobile apps

    Adding iOS support for kotlin multiplatform mobile apps

    Hi @murzagalin!

    I’m developing a kotlin multiplatform mobile app for Android and iOS and would like to use your library. Unfortunately, the multiplatform-expression-evaluator does not support iOS targets.

    That’s why I created this pull request, which adds the iOS support to the library. I tested the PR with my app and successfully executed the expression parser on both platforms: Android and iOS.

    Thanks for your feedback!

    opened by flixlo 3
Releases(0.15.0)
Owner
Azamat Murzagalin
Azamat Murzagalin
This is a Kotlin multiplatform template project used to generate and deploy a natively compiled AWS lambda function using the custom runtime.

Overview This is a Kotlin multiplatform template project used to generate and deploy a natively compiled AWS Lambda function using a custom runtime. U

Greg Steckman 5 Jun 25, 2022
🍼Debug Bottle is an Android runtime debug / develop tools written using kotlin language.

???? 中文 / ???? 日本語 / ???? English ?? Debug Bottle An Android debug / develop tools written using Kotlin language. All the features in Debug bottle are

Yuriel Arlencloyn 846 Nov 14, 2022
An experimental tool for building console UI in Kotlin using the Jetpack Compose compiler/runtime

An experimental tool for building console UI in Kotlin using the Jetpack Compose compiler/runtime

Jake Wharton 1.4k Dec 28, 2022
Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in Kotlin with Jetpack Compose and a backed in Kotlin hosted on AppEngine.

Conferences4Hall Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in K

Gérard Paligot 98 Dec 15, 2022
Opinionated Redux-like implementation backed by Kotlin Coroutines and Kotlin Multiplatform Mobile

CoRed CoRed is Redux-like implementation that maintains the benefits of Redux's core idea without the boilerplate. No more action types, action creato

Kittinun Vantasin 28 Dec 10, 2022
An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.

An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile. 项目架构主要分为原生系统层、Android/iOS业务SDK层、KMM SDK层、KMM业务逻辑SDK层、iOS sdkfra

libill 4 Nov 20, 2022
A Bluetooth kotlin multiplatform "Cross-Platform" library for iOS and Android

Blue-Falcon A Bluetooth "Cross Platform" Kotlin Multiplatform library for iOS, Android, MacOS, Raspberry Pi and Javascript. Bluetooth in general has t

Andrew Reed 220 Dec 28, 2022
Mobile client for official Nextcloud News App written as Kotlin Multiplatform Project

Newsout Android and iOS mobile client for Nextcloud news App. The Android client is already available to download in the Play Store. F-Droid and Apple

Simon Schubert 118 Oct 3, 2022
Kotlin Multiplatform Application to show Crypto Coins

This is the codebase of Crypto currency Tracking Kotlin Multiplatform App. Components Shared Components Ktor (Network Client) SQL Delight (Local DB) A

Aman Bansal 10 Oct 31, 2022
Dependency Injection library for Kotlin Multiplatform, support iOS and Android

Multiplatform-DI library for Kotlin Multiplatform Lightweight dependency injection framework for Kotlin Multiplatform application Dependency injection

Anna Zharkova 32 Nov 10, 2022