Skip to content

Commit

Permalink
c:script增加lang=java支持
Browse files Browse the repository at this point in the history
  • Loading branch information
entropy-cloud committed Sep 23, 2024
1 parent 15b2e09 commit 161c2cc
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 4 deletions.
24 changes: 24 additions & 0 deletions docs/dev-guide/xlang/xpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,30 @@ XPL内置的标签提供了判断、循环、导入、宏处理等基本功能
</c:script>
```

XLang平台内置了`lang=java`支持, 通过args指定从上下文中获取哪些变量,在脚本代码中可以直接访问这些变量。

```xml
<c:unit>
<c:script>
let x = 1;
let y = 2;
</c:script>

<c:script lang="java" args="x:int,y:int" returnType="int">
return x + y;
</c:script>
</c:unit>
```

可以通过ScriptCompilerRegistry注册更多的脚本引擎支持。脚本引擎接口如下:
```java
public interface IScriptCompiler {
IEvalFunction compile(SourceLocation loc, String text,
List<? extends IFunctionArgument> args, IGenericType returnType,
IXLangCompileScope scope);
}
```

### 编译期

* `<c:import>`
Expand Down
5 changes: 5 additions & 0 deletions nop-xlang/src/main/java/io/nop/xlang/XLangErrors.java
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ public interface XLangErrors {
ErrorCode ERR_XPL_SCRIPT_NOT_ALLOW_CHILD = define("nop.err.xlang.xpl.script-not-allow-child",
"script标签不允许包含子节点,只能是文本内容");

ErrorCode ERR_XPL_EVAL_NOT_ALLOW_CHILD = define("nop.err.xlang.xpl.eval-not-allow-child",
"eval标签不允许包含子节点,只能是文本内容");

ErrorCode ERR_XPL_EVAL_INVALID_LANG = define("nop.err.xlang.xpl.eval-invalid-lang","eval节点的lang属性不合法:{lang}", ARG_LANG);

ErrorCode ERR_XPL_NOT_ALLOW_OUTPUT = define("nop.err.xlang.xpl.not-allow-output",
"xpl的当前输出模式为[{outputMode}],不允许输出文本内容", ARG_OUTPUT_MODE);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.nop.xlang.expr;

import io.nop.api.core.util.SourceLocation;
import io.nop.commons.text.tokenizer.TextScanner;
import io.nop.core.reflect.impl.FunctionArgument;
import io.nop.core.type.IGenericType;
import io.nop.core.type.IRawTypeResolver;
import io.nop.core.type.parse.GenericTypeParser;

import java.util.ArrayList;
import java.util.List;

public class ArgDeclarationsParser {
private GenericTypeParser typeParser = new GenericTypeParser();

public ArgDeclarationsParser rawTypeResolver(IRawTypeResolver rawTypeResolver) {
this.typeParser.rawTypeResolver(rawTypeResolver);
return this;
}

public List<FunctionArgument> parseArgDeclarations(SourceLocation loc, String text) {
TextScanner sc = TextScanner.fromString(loc, text);
List<FunctionArgument> args = argDeclarations(sc);
sc.checkEnd();
return args;
}

public List<FunctionArgument> argDeclarations(TextScanner sc) {
List<FunctionArgument> exprs = new ArrayList<>();
do {
FunctionArgument x = argDeclaration(sc);
exprs.add(x);
} while (sc.tryMatch(','));
return exprs;
}

FunctionArgument argDeclaration(TextScanner sc) {
// SourceLocation loc = sc.location();
String name = sc.nextJavaVar();
boolean nullable = false;
if (sc.tryMatch('?'))
nullable = true;
sc.match(':');
IGenericType type = typeParser.parseGenericType(sc);

FunctionArgument ret = new FunctionArgument();
ret.setType(type);
ret.setName(name);
ret.setNullable(nullable);
return ret;
}
}
15 changes: 15 additions & 0 deletions nop-xlang/src/main/java/io/nop/xlang/xdsl/XDslParseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
import io.nop.core.reflect.IFunctionModel;
import io.nop.core.reflect.ReflectionManager;
import io.nop.core.reflect.bean.IBeanModel;
import io.nop.core.reflect.impl.FunctionArgument;
import io.nop.core.type.IGenericType;
import io.nop.core.type.IRawTypeResolver;
import io.nop.core.type.parse.GenericTypeParser;
import io.nop.xlang.XLangConstants;
import io.nop.xlang.expr.ArgDeclarationsParser;
import io.nop.xlang.xdef.XDefTypeDecl;
import io.nop.xlang.xdef.parse.XDefTypeDeclParser;
import io.nop.xlang.xdsl.json.DslModelToXNodeTransformer;
Expand Down Expand Up @@ -293,6 +295,19 @@ public static IGenericType parseAttrGenericType(XNode node, String attrName, IRa
}
}

public static List<FunctionArgument> parseAttrArgs(XNode node, String attrName, IRawTypeResolver resolver) {
String text = node.attrText(attrName);
if (text == null)
return null;

SourceLocation loc = node.attrLoc(attrName);
try {
return new ArgDeclarationsParser().rawTypeResolver(resolver).parseArgDeclarations(loc, text);
} catch (Exception e) {
throw newAttrError(ERR_XDSL_ATTR_NOT_VALID_GENERIC_TYPE, node, attrName).cause(e);
}
}

public static IGenericType parseGenericType(SourceLocation loc, String text, IRawTypeResolver resolver) {
GenericTypeParser parser = new GenericTypeParser();
if (resolver != null)
Expand Down
3 changes: 3 additions & 0 deletions nop-xlang/src/main/java/io/nop/xlang/xpl/IXplCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.nop.core.lang.xml.XNode;
import io.nop.core.reflect.IFunctionArgument;
import io.nop.core.type.IGenericType;
import io.nop.core.type.IRawTypeResolver;
import io.nop.xlang.api.IXLangCompileScope;
import io.nop.xlang.ast.Expression;
import io.nop.xlang.expr.IXLangExprParser;
Expand Down Expand Up @@ -40,4 +41,6 @@ IEvalFunction compileScript(SourceLocation loc, String lang, String source,
IGenericType returnType,
IXLangCompileScope scope);

IRawTypeResolver getRawTypeResolver();

}
3 changes: 3 additions & 0 deletions nop-xlang/src/main/java/io/nop/xlang/xpl/XplConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ public interface XplConstants {

String LANG_NAME = "lang";

String ARGS_NAME = "args";
String RETURN_TYPE_NAME = "returnType";

String FROM_NAME = "from";
String AS_NAME = "as";
String CLASS_NAME = "class";
Expand Down
13 changes: 13 additions & 0 deletions nop-xlang/src/main/java/io/nop/xlang/xpl/impl/XplCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import io.nop.core.lang.json.JsonTool;
import io.nop.core.lang.xml.XNode;
import io.nop.core.reflect.IFunctionArgument;
import io.nop.core.reflect.impl.DefaultClassResolver;
import io.nop.core.type.IGenericType;
import io.nop.core.type.IRawTypeResolver;
import io.nop.xlang.XLangConstants;
import io.nop.xlang.api.IXLangCompileScope;
import io.nop.xlang.ast.Expression;
Expand Down Expand Up @@ -92,6 +94,17 @@
public class XplCompiler extends XLangExprParser implements IXplCompiler {
static final Logger LOG = LoggerFactory.getLogger(XplCompiler.class);

private IRawTypeResolver rawTypeResolver = DefaultClassResolver.INSTANCE;

@Override
public IRawTypeResolver getRawTypeResolver() {
return rawTypeResolver;
}

public void setRawTypeResolver(IRawTypeResolver rawTypeResolver) {
this.rawTypeResolver = rawTypeResolver;
}

@Override
public Expression parseTag(XNode node, IXLangCompileScope scope) {
XLangParseBuffer buf = new XLangParseBuffer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class InternalTagCompilers {
registerTagCompiler("c:print", PrintTagCompiler.INSTANCE);
registerTagCompiler("c:return", ReturnTagCompiler.INSTANCE);
registerTagCompiler("c:script", ScriptTagCompiler.INSTANCE);
//registerTagCompiler("c:eval", EvalTagCompiler.INSTANCE);
registerTagCompiler("c:throw", ThrowTagCompiler.INSTANCE);
registerTagCompiler("c:try", TryTagCompiler.INSTANCE);
registerTagCompiler("c:unit", UnitTagCompiler.INSTANCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,38 @@
import io.nop.commons.util.StringHelper;
import io.nop.core.lang.eval.IEvalFunction;
import io.nop.core.lang.xml.XNode;
import io.nop.core.reflect.IFunctionArgument;
import io.nop.core.reflect.impl.FunctionArgument;
import io.nop.core.reflect.impl.FunctionModel;
import io.nop.core.type.PredefinedGenericTypes;
import io.nop.core.type.IGenericType;
import io.nop.xlang.api.IXLangCompileScope;
import io.nop.xlang.ast.CallExpression;
import io.nop.xlang.ast.Expression;
import io.nop.xlang.ast.Identifier;
import io.nop.xlang.ast.Literal;
import io.nop.xlang.ast.Program;
import io.nop.xlang.ast.definition.ResolvedFuncDefinition;
import io.nop.xlang.xdsl.XDslParseHelper;
import io.nop.xlang.xpl.IXplCompiler;
import io.nop.xlang.xpl.IXplTagCompiler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static io.nop.xlang.XLangErrors.ARG_NODE;
import static io.nop.xlang.XLangErrors.ERR_XPL_SCRIPT_NOT_ALLOW_CHILD;
import static io.nop.xlang.xpl.XplConstants.ARGS_NAME;
import static io.nop.xlang.xpl.XplConstants.LANG_NAME;
import static io.nop.xlang.xpl.XplConstants.RETURN_TYPE_NAME;
import static io.nop.xlang.xpl.utils.XplParseHelper.checkArgNames;
import static io.nop.xlang.xpl.utils.XplParseHelper.getAttrLiteral;

public class ScriptTagCompiler implements IXplTagCompiler {
public static ScriptTagCompiler INSTANCE = new ScriptTagCompiler();

static final List<String> ATTR_NAMES = Arrays.asList(LANG_NAME);
static final List<String> ATTR_NAMES = Arrays.asList(LANG_NAME, ARGS_NAME, RETURN_TYPE_NAME);

@Override
public Expression parseTag(XNode node, IXplCompiler cp, IXLangCompileScope scope) {
Expand All @@ -62,8 +68,14 @@ public Expression parseTag(XNode node, IXplCompiler cp, IXLangCompileScope scope
}
}

IGenericType genericType = XDslParseHelper.parseAttrGenericType(node, RETURN_TYPE_NAME, cp.getRawTypeResolver());

List<FunctionArgument> args = XDslParseHelper.parseAttrArgs(node, ARGS_NAME, cp.getRawTypeResolver());
if (args == null)
args = Collections.emptyList();

IEvalFunction func = cp.compileScript(node.content().getLocation(), lang, source,
Collections.emptyList(), PredefinedGenericTypes.ANY_TYPE, scope);
args, genericType, scope);
if (func == null)
return null;

Expand All @@ -75,12 +87,19 @@ public Expression parseTag(XNode node, IXplCompiler cp, IXLangCompileScope scope
funcModel.setName("<c:script>");
funcModel.setLocation(node.getLocation());
funcModel.setInvoker(func);
funcModel.setArgs(args);

ResolvedFuncDefinition def = new ResolvedFuncDefinition(funcModel);
id.setResolvedDefinition(def);
expr.setCallee(id);

expr.setArguments(Collections.emptyList());

List<Expression> argExprs = new ArrayList<>(args.size());
for (IFunctionArgument arg : args) {
argExprs.add(Identifier.valueOf(node.getLocation(), arg.getName()));
}
expr.setArguments(argExprs);

return expr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 1. 通过lang指定java语言

````xpl
<c:unit>
<c:script>
let x = 1;
let y = 2;
</c:script>

<c:script lang="java" args="x:int,y:int" returnType="int">
return x + y;
</c:script>


</c:unit>
````

* return: 3

0 comments on commit 161c2cc

Please sign in to comment.