use of org.beetl.core.statement.nat.NativeMethodNode in project beetl2.0 by javamonkey.
the class AntlrProgramBuilder method parseNativeCallExpression.
protected NativeCallExpression parseNativeCallExpression(NativeCallContext ncc) {
NativeCallExpression nativeExp = null;
List<ParseTree> list = ncc.children;
// nativeCall: nativeVarRefChain (nativeMethod|nativeArray| PERIOD nativeVarRefChain)*;
NativeVarRefChainContext first = (NativeVarRefChainContext) list.get(0);
List<TerminalNode> ids = first.Identifier();
StringBuilder clsSb = new StringBuilder();
// 是类静态调用还是实例调用
boolean isCls = false;
int i = 0;
for (; i < ids.size(); i++) {
String text = ids.get(i).getText();
char c = text.charAt(0);
if (c >= 'A' && c <= 'Z') {
clsSb.append(text);
isCls = true;
break;
} else {
clsSb.append(text).append(".");
}
}
ClassNode clsNode = null;
InstanceNode insNode = null;
if (isCls) {
clsNode = new ClassNode(clsSb.toString());
// 指向下一个属性或者静态方法
i++;
} else {
// 变量的属性引用,回到第一个,构造一个变量
String varName = ids.get(0).getText();
VarRef ref = new VarRef(new VarAttribute[0], false, null, this.getBTToken(varName, ncc.start.getLine()));
this.pbCtx.setVarPosition(varName, ref);
insNode = new InstanceNode(ref);
i = 1;
}
List<NativeNode> nativeList = new ArrayList<NativeNode>();
for (int j = i; j < ids.size(); j++) {
// 剩下的是属性
NativeAtrributeNode attribute = new NativeAtrributeNode(ids.get(j).getText());
nativeList.add(attribute);
}
for (int z = 1; z < list.size(); z++) {
ParseTree tree = list.get(z);
if (tree instanceof NativeMethodContext) {
NativeMethodContext methodCtx = (NativeMethodContext) tree;
NativeMethodNode methodNode = null;
String method = null;
NativeNode lastNode = nativeList.get(nativeList.size() - 1);
if (lastNode instanceof NativeAtrributeNode) {
method = ((NativeAtrributeNode) lastNode).attribute;
//
nativeList.remove(nativeList.size() - 1);
} else {
String msg = null;
if (lastNode instanceof NativeArrayNode) {
msg = "[]()";
} else {
msg = "()()";
}
BeetlException ex = new BeetlException(BeetlException.PARSER_NATIVE_ERROR, msg);
ex.pushToken(this.getBTToken(methodCtx.getStart()));
throw ex;
}
// 解析参数
List<ExpressionContext> expCtxList = methodCtx.expression();
Expression[] exp = this.parseExpressionCtxList(expCtxList);
methodNode = new NativeMethodNode(method, exp);
nativeList.add(methodNode);
} else if (tree instanceof NativeArrayContext) {
ExpressionContext expCtx = ((NativeArrayContext) tree).expression();
Expression exp = this.parseExpress(expCtx);
NativeArrayNode arrayNode = new NativeArrayNode(exp);
nativeList.add(arrayNode);
} else if (tree instanceof NativeVarRefChainContext) {
List<TerminalNode> nodes = ((NativeVarRefChainContext) tree).Identifier();
for (TerminalNode node : nodes) {
NativeAtrributeNode attributeNode = new NativeAtrributeNode(node.getText());
nativeList.add(attributeNode);
}
} else {
// 其他节点,这段语法写的不好,造成解析困难,但先这样了
continue;
}
}
NativeNode[] chain = nativeList.toArray(new NativeNode[0]);
if (clsNode != null) {
nativeExp = new NativeCallExpression(clsNode, chain, this.getBTToken(ncc.start));
} else {
nativeExp = new NativeCallExpression(insNode, chain, this.getBTToken(ncc.start));
}
return nativeExp;
}
use of org.beetl.core.statement.nat.NativeMethodNode in project beetl2.0 by javamonkey.
the class NativeCallExpression method infer.
@Override
public void infer(InferContext inferCtx) {
Type type = null;
if (insNode != null) {
insNode.ref.infer(inferCtx);
type = insNode.ref.type.copy();
} else {
Class cls = inferCtx.gt.loadClassBySimpleName(this.clsNode.cls);
if (cls == null) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "该类不存在");
be.pushToken(GrammarToken.createToken(clsNode.cls, token.line));
throw be;
}
type = new Type(cls);
}
for (NativeNode node : chain) {
if (type.cls == Object.class) {
this.type = type;
// 以后生成代码有问题
return;
}
if (node instanceof NativeAtrributeNode) {
String attr = ((NativeAtrributeNode) node).attribute;
try {
Field f = type.cls.getField(attr);
Class c = f.getType();
type.cls = c;
} catch (SecurityException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无法访问属性", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
} catch (NoSuchFieldException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无此属性", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
}
} else if (node instanceof NativeArrayNode) {
if (!type.cls.isArray()) {
BeetlException be = new BeetlException(BeetlException.ARRAY_TYPE_ERROR);
// 最好是把上一个字符显示出来
be.pushToken(GrammarToken.createToken("[]", token.line));
throw be;
}
type.cls = type.cls.getComponentType();
} else if (node instanceof NativeMethodNode) {
NativeMethodNode methodNode = (NativeMethodNode) node;
String method = methodNode.method;
Expression[] expList = methodNode.paras;
Class[] argTypes = expList.length == 0 ? ObjectUtil.EMPTY_CLASS_ARRAY : new Class[expList.length];
for (int i = 0; i < expList.length; i++) {
expList[i].infer(inferCtx);
argTypes[i] = expList[i].type.cls;
}
try {
ObjectMethodMatchConf conf = ObjectUtil.findMethod(type.cls, method, argTypes);
if (conf == null) {
type.cls = Object.class;
} else {
type.cls = conf.method.getReturnType();
}
} catch (SecurityException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用方法");
be.pushToken(GrammarToken.createToken(method, token.line));
throw be;
}
}
}
this.type = type;
}
use of org.beetl.core.statement.nat.NativeMethodNode in project beetl2.0 by javamonkey.
the class NativeCallExpression method evaluate.
public Object evaluate(Context ctx) {
Class targetCls = null;
Object targetObj = null;
NativeNode lastNode = null;
if (insNode != null) {
targetObj = insNode.ref.evaluate(ctx);
if (targetObj != null) {
targetCls = targetObj.getClass();
}
lastNode = insNode;
} else {
targetCls = ctx.gt.loadClassBySimpleName(this.clsNode.cls);
if (targetCls == null) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "该类不存在");
be.pushToken(GrammarToken.createToken(clsNode.cls, token.line));
throw be;
}
lastNode = clsNode;
}
for (NativeNode node : chain) {
if (node instanceof NativeAtrributeNode) {
String attr = ((NativeAtrributeNode) node).attribute;
try {
checkNull(targetCls, lastNode);
Field f = targetCls.getField(attr);
if (!Modifier.isStatic(f.getModifiers())) {
checkNull(targetObj, lastNode);
}
targetObj = f.get(targetObj);
targetCls = f.getType();
} catch (SecurityException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用属性", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
} catch (NoSuchFieldException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无此属性", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
} catch (IllegalArgumentException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "访问属性出错", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
} catch (IllegalAccessException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "访问属性出错", e);
be.pushToken(GrammarToken.createToken(attr, token.line));
throw be;
}
} else if (node instanceof NativeArrayNode) {
checkNull(targetCls, lastNode);
if (!targetCls.isArray()) {
BeetlException be = new BeetlException(BeetlException.ARRAY_TYPE_ERROR);
// 最好是把上一个字符显示出来
be.pushToken(GrammarToken.createToken("[]", token.line));
throw be;
}
Expression exp = ((NativeArrayNode) node).exp;
Object value = exp.evaluate(ctx);
if (value instanceof Number) {
int index = ((Number) value).intValue();
targetObj = ((Object[]) targetObj)[index];
if (targetObj != null) {
targetCls = targetObj.getClass();
} else {
// todo or component of array
targetCls = null;
}
} else {
BeetlException be = new BeetlException(BeetlException.ARRAY_INDEX_ERROR, "数组指针必须是Number类型");
be.pushToken(GrammarToken.createToken("[]", token.line));
throw be;
}
} else if (node instanceof NativeMethodNode) {
NativeMethodNode methodNode = (NativeMethodNode) node;
String method = methodNode.method;
Expression[] expList = methodNode.paras;
this.checkPermit(ctx, targetCls, targetObj, method);
Object[] args = expList.length == 0 ? ObjectUtil.EMPTY_OBJECT_ARRAY : new Object[expList.length];
Class[] parameterType = new Class[args.length];
for (int i = 0; i < expList.length; i++) {
args[i] = expList[i].evaluate(ctx);
parameterType[i] = args[i] == null ? null : args[i].getClass();
}
this.checkNull(targetCls, lastNode);
ObjectMethodMatchConf mf = ObjectUtil.findMethod(targetCls, method, parameterType);
if (mf == null) {
BeetlException ex = new BeetlException(BeetlParserException.NATIVE_CALL_INVALID, "根据参数未找到匹配的方法" + method + BeetlUtil.getParameterDescription(parameterType));
ex.pushToken(GrammarToken.createToken(lastNode.getName(), token.line));
throw ex;
}
if (targetObj == null && !Modifier.isStatic(mf.method.getModifiers())) {
BeetlException ex = new BeetlException(BeetlException.NULL);
ex.pushToken(GrammarToken.createToken(lastNode.getName(), token.line));
throw ex;
}
try {
targetObj = ObjectUtil.invoke(targetObj, mf, args);
if (targetObj != null) {
targetCls = targetObj.getClass();
} else {
targetCls = null;
}
} catch (SecurityException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "不能调用方法", e);
be.pushToken(GrammarToken.createToken(method, token.line));
throw be;
} catch (IllegalArgumentException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "错误的参数", e);
be.pushToken(GrammarToken.createToken(method, token.line));
throw be;
} catch (IllegalAccessException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "无法访问方法", e);
be.pushToken(GrammarToken.createToken(method, token.line));
throw be;
} catch (InvocationTargetException e) {
BeetlException be = new BeetlException(BeetlException.NATIVE_CALL_EXCEPTION, "内部调用报错", e.getTargetException());
be.pushToken(GrammarToken.createToken(method, token.line));
throw be;
}
}
lastNode = node;
}
return targetObj;
}
Aggregations