Giter Site home page Giter Site logo

killme2008 / aviatorscript Goto Github PK

View Code? Open in Web Editor NEW
4.3K 171.0 817.0 12.81 MB

A high performance scripting language hosted on the JVM.

Home Page: http://fnil.net/aviator/

Java 99.72% Shell 0.28%
java scripting-language jvm-languages aviatorscript expression-evaluator programming-language

aviatorscript's Introduction

AviatorScript

Build Status Maven Central

📖 English Documentation | 📖 中文文档


AviatorScript 是一门高性能、轻量级寄宿于 JVM (包括 Android 平台)之上的脚本语言。

It's not a game, it's a programming language. Please refrain from sending me any more unsolicited emails.RTFM

特性介绍

  1. 支持数字、字符串、正则表达式、布尔值、正则表达式等基本类型,完整支持所有 Java 运算符及优先级等。
  2. 函数是一等公民,支持闭包和函数式编程
  3. 内置 bigint/decimal 类型用于大整数和高精度运算,支持运算符重载得以让这些类型使用普通的算术运算符 +-*/ 参与运算。
  4. 完整的脚本语法支持,包括多行数据、条件语句、循环语句、词法作用域和异常处理等。
  5. 函数式编程结合 Sequence 抽象,便捷处理任何集合。
  6. 轻量化的模块系统
  7. 多种方式,方便地调用 Java 方法,完整支持 Java 脚本 API(方便从 Java 调用脚本)。
  8. 丰富的定制选项,可作为安全的语言沙箱和全功能语言使用。
  9. 动态编译和执行、轻量化、高性能,ASM 模式下通过直接将脚本编译成 JVM 字节码,解释模式可运行于 Android 等非标 Java 平台。
  10. 支持编译结果序列化,方便缓存加速等。支持执行超时设置,避免破坏性脚本耗尽资源。

使用场景包括:

  1. 规则判断及规则引擎
  2. 公式计算
  3. 动态脚本控制
  4. 集合数据 ELT 等 ……

推荐使用版本 5.2.6 及以上

News

  • 5.4.3,增加安全沙箱一键启用方法以及修复 bug 等。
  • 5.4.2,增加 getFunctionNames 方法用于获取函数列表以及设置求值超时时间等。
  • 5.4.1,修复递归函数无法工作的 bug,修复函数无法序列化的 bug 等。

Dependency

<dependency>
  <groupId>com.googlecode.aviator</groupId>
  <artifactId>aviator</artifactId>
  <version>{version}</version>
</dependency>

可以在 search.maven.org 查看可用的版本。

快速开始

  1. 下载 aviator shell 到某个目录(最好是在系统的 PATH 环境变量内),比如 ~/bin/aviator:
$ wget https://raw.githubusercontent.com/killme2008/aviator/master/bin/aviator
$ chmod u+x aviator
  1. 执行 aviator 命令,将自动下载最新文档版本 aviator jar 到 ~/.aviatorscript 下的安装目录并运行:
$ aviator
Downloading AviatorScript now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   153  100   153    0     0    111      0  0:00:01  0:00:01 --:--:--   111
100 1373k  100 1373k    0     0   689k      0  0:00:01  0:00:01 --:--:--  689k
Usage: java com.googlecode.aviator.Main [file] [args]
     : java com.googlecode.aviator.Main -e [script]
     : java com.googlecode.aviator.Main -v
  1. 将下面这个脚本保存为文件 hello.av:
p("Hello, AviatorScript!");

let a = tuple(1, 2, 3, 4, 5);

p("sum of a is: " + reduce(a, +, 0));

let date = new java.util.Date();
p("The year is: "+ getYear(date));
p("The month is: #{getMonth(date)}");

一个更复杂的计算器例子(求值算术表达式字符串)参见calculator.av

  1. 执行脚本:
$ aviator hello.av
Hello, AviatorScript!
sum of a is: 15
The year is: 120
The month is: 3

更详细的请阅读用户指南

Links

aviatorscript's People

Contributors

aliiohs avatar danght avatar dqinyuan avatar dugenkui03 avatar einverne avatar fanofxiaofeng avatar guoqiwen8 avatar h123r avatar human-user avatar jiudc avatar killme2008 avatar m-razavi avatar nesuk avatar oldratlee avatar qiukeren avatar shuailung avatar xcorail avatar xixingya avatar yanchangyou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aviatorscript's Issues

Hi, 能补充一下变量的命名文档吗?

我发现,变量的命名,可以包含数字,下划线,中英文等,甚至少量的物殊符号,比如包含$这个变量名称是支持的,但是包含#的变量名称是不支持的,但是我知道我列举的肯定是不全的,所以我很需要一份文档来参考,希望作者考虑下,能不能加下这个文档说明,谢谢。

长时间运行性能会下降

我们现在在生产环境中使用发现,程序在运行较长时间之后,同样的公式,响应时间会变的越来越慢,下面贴出来我们使用的测试代码片段

issue.zip

PS: GC方面未见明显异常

list里面放map,从list的map里取数据解析表达式报异常

    Map<String, Object> map = new HashMap<String, Object>();
    List<Map<String, Object>> sublist = new ArrayList<Map<String, Object>>();
    HashMap<String,Object> sublistmap=new HashMap<String, Object>();
    sublistmap.put("data", "2");
    sublist.add(sublistmap);
    map.put("sublist", sublist);
    HashMap<String, Object> env = new HashMap<String, Object>();
    env.put("mmap", map);
    System.out.println(AviatorEvaluator.execute("mmap.sublist[0].data", env));

Exception in thread "main" com.googlecode.aviator.exception.ExpressionSyntaxErrorException: Syntax error:illegal expression at 16, current token: [type='Number',lexeme='.',index=15]
at com.googlecode.aviator.parser.ExpressionParser.reportSyntaxError(ExpressionParser.java:622)

咨询下Execute expression error这种异常的抛出场景

升级3.2后莫名的出现这个问题,web服务重启也没做任何改动又恢复了,不知道这种异常是在什么场景下会抛出来。

com.googlecode.aviator.exception.ExpressionRuntimeException: Execute expression error
Caused by: java.lang.NoClassDefFoundError: Script_1514466240951_0
at Script_1514466240951_0/136757698.execute0(Unknown Source) ~[na:na]
at com.googlecode.aviator.ClassExpression.execute(ClassExpression.java:49) ~[aviator-3.2.0.jar:na]
... 17 common frames omitted
Caused by: java.lang.ClassNotFoundException: Script_1514466240951_0
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333) ~[catalina.jar:8.0.44]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167) ~[catalina.jar:8.0.44]
... 19 common frames omitted

关于类型的问题

  1. 为什么不加一个integer类型, 这个大家可能更常用, 更习惯. 虽然Long已经可以实现相关的内容了.
  2. 参数加入json对象的支持, 现在这种数据类型也比较常用.
  3. string相关的函数中没有考虑到null的情况, 能否用common-lang中的函数代替. 或者我改好后提request.

有打算支持运算符重载吗

目前在用这个表达式引擎来实现一些excel函数,"&"这个运算符在excel里面是表示内容拼接,我是通过改源码的方式来实现的,如果可以提供运算符重载就很方便了

map操作取值时的问题

public void testMap() {
    Map mmap = new HashMap<>();
    mmap.put("a", "1");
    mmap.put("b", "2");
    mmap.put("c", "3");
    mmap.put("100", "1001");

    Map<String, Object> env = new HashMap<String, Object>();
    env.put("map", mmap);

    // collect
    logger.info("☆☆☆ result = {}", AviatorEvaluator.execute("map.a", env));
    // error
    logger.info("☆☆☆ result = {}", AviatorEvaluator.execute("map.100", env));
}

JRockit 6中不支持Long.compare (AviatorLong.java)

JRockit 6中不支持Long.compare (AviatorLong.java)

Exception in thread "Main Thread" com.googlecode.aviator.exception.ExpressionRuntimeException: Execute expression error
at com.googlecode.aviator.ClassExpression.execute(ClassExpression.java:59)
at com.etone.project.ebars.engine.MonitortRunner.main(MonitortRunner.java:105)
Caused by: java.lang.NoSuchMethodError: java/lang/Long.compare(JJ)I
at com.googlecode.aviator.runtime.type.AviatorLong.innerCompare(AviatorLong.java:83)
at com.googlecode.aviator.runtime.type.AviatorNumber.compare(AviatorNumber.java:219)
at Script_1377485712923_0.execute0(Unknown Source)
at com.googlecode.aviator.ClassExpression.execute(ClassExpression.java:53)

AviatorString类compare方法报空指针异常

AviatorString类的compare方法未考虑this.lexeme为null以及otherString.lexeme为null的情况。这导致以下两种不符合预期的case

  • 空指针异常
  • 如果this.lexeme 为null,与NIL做比较时会错误的返回1,预期值应该是0
    可能导致空指针异常的代码有以下两处
  return this.lexeme.compareTo(otherString.lexeme); 
  return this.lexeme.compareTo(String.valueOf(otherJavaValue));

该代码在this.lexeme为null,或者otherString.lexeme为null时,均会抛出空指针异常。

下面是我用到的测试case

public class StringGetFromJsonMapFunction extends AbstractFunction {

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        //blablala
       //始终返回null
        return new AviatorString(null);
    }

    @Override
    public String getName() {
        return "string.getFromJsonMap";
    }
}

进行如下测试

@Test
    public void testNullPointerException() {
        String exp = "string.getFromJsonMap(mapJson, key) == 'abc'";
        Map<String, Object> env = Maps.newHashMap();
        env.put("mapJson", "{\"key1\":\"value1\", \"key2\":\"value2\"}");
        env.put("key", "key3");  
       //预期返回false,实际上却抛出了空指针异常。
        assertEquals(false, (Boolean)AviatorEvaluator.execute(exp, env));
    }

 @Test
    public void testNil() {
        String exp = "string.getFromJsonMap(mapJson, key) == nil";
        Map<String, Object> env = Maps.newHashMap();
        env.put("mapJson", "{\"key1\":\"value1\", \"key2\":\"value2\"}");
        env.put("key", "key3");  
        //预期返回true,实际上却返回false。
        assertEquals(true, (Boolean)AviatorEvaluator.execute(exp, env));
    }

附AviatorString的compare方法源码 (Aviator 3.0.0版本)

 public int compare(AviatorObject other, Map<String, Object> env) {
        if (this == other) {
            return 0;
        }
        switch (other.getAviatorType()) {
        case String:
            AviatorString otherString = (AviatorString) other;
            return this.lexeme.compareTo(otherString.lexeme);   //可能抛出空指针
        case JavaType:
            AviatorJavaType javaType = (AviatorJavaType) other;
            final Object otherJavaValue = javaType.getValue(env);
            if (otherJavaValue == null) {
                return 1;
            }
            if(TypeUtils.isString(otherJavaValue)) {
                return this.lexeme.compareTo(String.valueOf(otherJavaValue)); //可能抛出空指针
            }
            else if (otherJavaValue instanceof Date) {
                return this.tryCompareDate((Date) otherJavaValue);
            }
            else {
                throw new ExpressionRuntimeException("Could not compare " + this + " with " + other);
            }
        case Nil:  
            return 1;  //该分支未考虑this.lexeme为null的情况
        default:
            throw new ExpressionRuntimeException("Could not compare " + this + " with " + other);
        }
    }

不知道我的理解是否正确,麻烦看一下这个问题,谢谢。

list过滤

你好,aviator如何对list进行过滤?如:

class Foo{
     private int i;
     private String m;
gettersetter……
}
List<Foo> list = new ArrayList<>();
list.add(new Foo(1,"m"));
list.add(new Foo(2,"n"));
list.add(new Foo(3,"n"));

//需要筛选出list中,i>2 && m=="n" 的list集合?

谢谢!

科学计数法的问题

1)AviatorEvaluator.execute("4E8_1.0/3E9_1.0");
0.13333333333333333

2)AviatorEvaluator.execute("1E9_1.0/2E10_1.0");
5.0E7--- 这个有问题

3)AviatorEvaluator.execute("1000000000_1.0/20000000000_1.0");
0.05

科学计数法达到一定级别的就报错了(2,3其实表达的数字是一样的)!不知道是不是bug

调用超过20个参数的自定义函数抛出NoSuchMethodError

我自定义的函数GetFirstNonNullFunction类如下:


package com.meituan.rc.zeus.aviator.function;

import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorString;

import java.util.Map;

public class GetFirstNonNullFunction extends AbstractFunction {

private AviatorObject firstNonNull(Map<String, Object> env, AviatorObject... args) {
    if (args != null) {
        for (AviatorObject arg : args) {
            if (arg.getValue(env) != null) {
                return arg;
            }
        }
    }
    return new AviatorString(null);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
    return firstNonNull(env, arg1, arg2);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {
    return firstNonNull(env, arg1, arg2, arg3);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4) {
    return firstNonNull(env, arg1, arg2, arg3, arg4);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19, AviatorObject arg20) {
    return firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20);
}

@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19, AviatorObject arg20, AviatorObject... args) {
    AviatorObject result = firstNonNull(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20);
    if (result.getValue(env) != null) {
        return result;
    } else {
        return firstNonNull(env, args);
    }
}

@Override
public String getName() {
    return "getFirstNonNull";
}

}



但在执行表达式调用时发现超过20个参数时,无论如何都会返回null,调试发现在ClassExpression类中execute方法调用execute0(env)时抛出了NoSuchMethodError,经查看ASMCodeGenerator类中的方法:

    
    @Override
    private String getInvokeMethodDesc(int paramCount) {
        StringBuilder sb = new StringBuilder("(Ljava/util/Map;");
        for (int i = 0; i < paramCount; i++) {
            sb.append("Lcom/googlecode/aviator/runtime/type/AviatorObject;");
        }
        sb.append(")Lcom/googlecode/aviator/runtime/type/AviatorObject;");
        return sb.toString();
    }


    @Override
    public void onMethodInvoke(Token lookhead) {
        final MethodMetaData methodMetaData = this.methodMetaDataStack.pop();
        final int parameterCount = methodMetaData.parameterCount;
        this.mv.visitMethodInsn(INVOKEINTERFACE, "com/googlecode/aviator/runtime/type/AviatorFunction", "call",
            this.getInvokeMethodDesc(parameterCount));

        this.popOperand(); // method object
        this.popOperand(); // env map
        // pop operands
        for (int i = 0; i < parameterCount; i++) {
            this.popOperand();
        }
        // push result
        this.pushOperand(0);
    }
    

发现在getInvokeMethodDesc方法中并未有对参数超过20个时做额外处理转化为数组的代码,因此猜测(当然只是猜测)您是否忽略了参数超过了20个参数时对于反射调用可变参数时的处理,如果是这样,请问能不能支持一下这个特性?(长篇大论了些,请见谅!!!)

Hi, 编译问题

String str = "a==3+3";
这个编译为什么能通过呢?感觉不是正常的逻辑啊!计算的时候才报错,我觉得是不是编译的时候就不能通过吧

集合访问问题

举个例子:
public class Order{
private List subOrders;
}
public class SubOrder{
private String subOrderId;
}
如果表达式是:order. subOrders可以拿到一个List对象
但是我如果要想获取subOrderId时,表达式如:order.subOrders.subOrderId
这个Aviator无法解析,因为Aviator认为subOrderId是List的属性,
请问,如果想实现上述的问题,Aviator是否支持,表达式该如何描述?
谢谢

为什么BigDecimal优先级比Double低呢?

Double的精度不是很低吗?
例:“2 * 2.33 * 2.44”,看了下源码,通过'.'这个,自动转double,没有设置按统一的Bigdecimal来计算的吗?我知道可以设置成这样"2 * 2.33M * 2.44M", 但数字在字符串中常常是未知的,但是我想要的结果都是通过BigDecimal计算的结果,Double计算的不精确。

现在我的解决方案是把把有的数字都提取出来,再加上“M”,再拼接回去,再计算
我看了下你的源码?没有发现可以统一设置的入口,这真得很让人郁闷,JEP提供这些功能,可以统一设置。

或许我说得是不对的,希望作者回复,看有没有更好的解决方案

访问list集合中对象的属性抛异常

Map<String, Object> env = new HashMap<String, Object>();
env.put("users", users);
    Object execute3 = AviatorEvaluator.execute("users[0].name",env);其中 users 是list对象。

如果底层用的是commons-beanutils实现的是支持的,我测试过,代码如下:Object indexedProperty = PropertyUtils.getNestedProperty(users, "[0].age");System.out.println(indexedProperty);结果成功输出 第一个元素中年龄age的属性值。所以,大神这个bug是可以修复的,赶紧修复一下吧。哈哈

获取集合中的对象属性异常

final Map<String, Object> env = new HashMap<String, Object>();
List ary = new ArrayList<>();
ary.add(new Dto());
env.put("lst", ary);
AviatorEvaluator.execute("#lst[0].name", env);

com.googlecode.aviator.exception.ExpressionSyntaxErrorException: Syntax error:illegal expression at 12, current token: [type='Number',lexeme='.',index=11]

自定义函数中有变量,变量如何传入?

我想问函数的 overtime 变量在表达式中怎么写呢?

public class TestAviator {

    public static void main(String[] args) {

        AviatorEvaluator.addFunction(new OrderOvertime());

        Map<String, Object> env = new HashMap<>(16);
        env.put("overtime", 10);

        boolean result = (boolean) AviatorEvaluator.exec("ORDER_OVERTIME(overtime) || false", env);
        System.out.println(result);
    }
}
public class OrderOvertime extends AbstractFunction {

    @Override
    public String getName() {
        return "ORDER_OVERTIME";
    }

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {

        Number overtime = FunctionUtils.getNumberValue(arg1, env);

        return AviatorBoolean.valueOf(overtime.intValue() > 5);
    }
}

aviator可否支持设置变量前后缀,支持mybatis那样的语法?

在使用时,发现有个语法上的小纠结。
比如我想用mybatis的map文件那样的语法。一堆字符串混合着#{变量名},这种语法比较易用。
而且一看就知道哪个是变量。
但是aviator的语法是类似java那样的语法。需要写很多单引号拼接字符串。
aviator可否支持设置变量前后缀,支持mybatis那样的语法?
假如不支持的话,我想到的办法是,自己做一层转换。
按mybatis语法配置。把函数和变量名都写到#{}里。然后执行表达式前,把#{替换成'+,把}替换成+'。去掉头尾孤立的多余符号。

数组 取值问题

我有如下map 对象
{
"E": {
"F": [
{
"H": 1,
"J": {
"A": 12
}
}
}
想取值 E.F[0].H 语法错误,
请问不支持数组map的嵌套取值吗?

支持if-else

是否有计划支持复杂的表达式如 if-else 语句?
因为多层级的三元表达式用起来复杂且并不直观

支持返回全路径变量

调用 Expression.getVariableNames(), 返回的的是变量的第一层。
如下:

   
    // BaseExpression.java

    private List varNames;

    public BaseExpression(List varNames) {
        super();
        LinkedHashSet tmp = new LinkedHashSet(varNames.size());
        // process nested names
        for (String name : varNames) {
            if (name.contains(".")) {
                name = name.substring(0, name.indexOf("."));
            }
            tmp.add(name);
        }
        this.varNames = new ArrayList(tmp);
    }

能否增加一个类似 List varFullNames; 的成员,返回变量的全路径?
主要是这样一种场景(业务员编辑业务规则公式),
1、前端业务员进行公示编辑时候,可以通过 AviatorEvaluator.compile(String expression) 来告诉他公式编写是否正确,公式中用到了哪些变量。
2、然后前端业务员可以对变量进行赋值,通过 AviatorEvaluator.execute(String expression, Map<String, Object> env) 来测试公式。

转义字符使用问题

需要返回:"你好',
这是我的表达式:AviatorEvaluator.execute("'"你好''"),运行是报错的,请问如果需要返回多个特殊的字符应该怎么写

How to make functions local in multi-threading environment

I want to use aviator in a multi-threading environment. Each thread uses aviator to evaluate expressions. But the AviatorEvaluator.addFunction() is a static method. So it is global and will influence all threads. But I only want each thread to specify its own functions. Can you make addFunction() a local method, like an instance method?

建议做表达式缓存

功能的确很强大,只是效率上低了一丢丢,10000次计算a+b*c平均每次在200ms左右,生产环境下还是慢了些。。。simpleEL快太多了

禁用语法糖功能

能否增加一个禁用语法糖的配置选项。比如说在编译表达式替换变量时,变量字符串如果本来就包括'.', '*'这样的关键字时,又不合适去掉的时候,就按照语法糖解析了。

计算公式中,一个是数据,一个是 字符串,计算会抛异常

"8161 == PCV3-8" ,运行时,发现8161是数据,会走数字类型,但是比较值是字符串时报错。

问题点:
if (otherValue instanceof Number) {
return this.innerCompare(AviatorNumber.valueOf(otherValue));
} else {
throw new ExpressionRuntimeException("Could not compare " + this + " with " + other);
}

在使用调试模式文件输出时候无法输出文件

try {
AviatorEvaluator.setTraceOutputStream(new FileOutputStream(new File("aviator.log")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}

    AviatorEvaluator.setOption(Options.TRACE_EVAL, true);

AviatorEvaluator.execute

然后我发现文件中没有相应的数据,我看了下代码
OperationRuntime.java
public static void printTrace(String msg) {
System.out.println("[Aviator TRACE] " + msg);
}
是否应该替换outputString 而不是System.out.println("[Aviator TRACE] " + msg);

过时的类无法卸载了。

测试了下,调用clearExpressionCache,清理后,应该用了加载器,这些丢弃的类都无法卸载呢。
类加载器是不是应该不要用一个,直接在生在字节码的时候NEW一个临时加载器,这样就可以卸载了。

Double类型,<有bug

`package com.zork.streaming

import java.util

import com.googlecode.aviator.{AviatorEvaluator, Expression}

/**

  • Created by sinmes on 16/9/21.
    */
    object Test {
    var expressList:scala.collection.mutable.MutableList[util.HashMap[String, AnyRef]] = _

    def getresult(env: util.HashMap[String, AnyRef]): scala.collection.mutable.MutableList[util.HashMap[String, AnyRef]] = {

    val list = new scala.collection.mutable.MutableList[util.HashMap[String, AnyRef]]
    for (temp <- expressList){
    if ("true".equals(temp.get("expression").asInstanceOf[Expression].execute(env).toString)) {
    val maptmp = new util.HashMapString, AnyRef
    maptmp.put("event", env.toString)
    maptmp.put("info", temp.toString)
    list += maptmp
    }
    }
    list
    }

    def compileExpression (expressionsstr : String) {
    expressList = new scala.collection.mutable.MutableList[util.HashMap[String, AnyRef]]
    val exstrArray = expressionsstr.split(":")
    for (str <- exstrArray) {
    var map = new util.HashMapString, AnyRef
    map.put("expression", AviatorEvaluator.compile(str))
    map.put("alarminfo", str)
    expressList += map
    }
    }

    def main(args: Array[String]): Unit = {
    val a = Test
    a.compileExpression("idea_exe_CpuUsage<1110")
    val c = new util.HashMapString, AnyRef
    c.put("idea_exe_CpuUsage111", "17.00000".toDouble.asInstanceOf[AnyRef])
    c.put("timestamp","1474423160")
    c.put("IP", "10.176.3.6")
    c.put("hostname", "hl")
    c.put("SystemType", "WindowsComputer")
    val d = a.getresult(c)
    d.foreach(e => {
    val itr = e.entrySet().iterator()
    while (itr.hasNext){
    val tmp = itr.next()
    println(tmp.getKey+":"+tmp.getValue)
    }
    })
    }
    }
    `

输出结果是:
event:{timestamp=1474423160, idea_exe_CpuUsage111=17.0, IP=10.176.3.6, hostname=hl, SystemType=WindowsComputer}
info:{expression=Script_1474599424448_0@606145c5, alarminfo=idea_exe_CpuUsage<1110}

表达式中有函数,context中无参数 报错

String s = "timeHourRange(e1_startTime,0,13)";
Map< String, Object > context = new HashMap<>();
AviatorEvaluator.compile( expression, true ).execute( context );// expected false,actuall exception

这样执行就会抛异常,是因为没有e1_startTime参数 Caused by: java.lang.NullPointerException: There is no string namede1_startTime,这样的情况我想返回false,应该怎么做到呢?急急急啊

可以提供形如 var in [1, 2, 3]这样的表达式吗?

目前提供了基本的逻辑运算符, 但在实际使用中经常有这种场景:

 判断某个变量是否在某个常量集合中, 如果能提供类似python的 in 算符就很好了。否则还需要把常量作为变量,再通过include才能实现 。

或者还有其他简便的方法我没看到?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.