use of lucee.transformer.bytecode.statement.udf.Function in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method closurePart.
@Override
protected final Function closurePart(ExprData data, String id, int access, int modifier, String rtnType, Position line, boolean closure) throws TemplateException {
Body body = new FunctionBody(data.factory);
Function func = closure ? new Closure(data.root, id, access, modifier, rtnType, body, line, null) : new FunctionImpl(data.root, id, access, modifier, rtnType, body, line, null);
comments(data);
if (!data.srcCode.forwardIfCurrent('('))
throw new TemplateException(data.srcCode, "invalid syntax in function head, missing begin [(]");
// arguments
ArrayList<Argument> args = getScriptFunctionArguments(data);
for (Argument arg : args) {
func.addArgument(arg.getName(), arg.getType(), arg.getRequired(), arg.getDefaultValue(), arg.isPassByReference(), arg.getDisplayName(), arg.getHint(), arg.getMetaData());
}
// end )
comments(data);
if (!data.srcCode.forwardIfCurrent(')'))
throw new TemplateException(data.srcCode, "invalid syntax in function head, missing ending [)]");
// doc comment
if (data.docComment != null) {
func.setHint(data.factory, data.docComment.getHint());
// params
/*Map<String, Attribute> params = data.docComment.getParams();
Iterator<Attribute> it = params.values().iterator();
Attribute attr;
String name;
while(it.hasNext()){
attr=it.next();
name=attr.getName();
}*/
func.setMetaData(data.docComment.getParams());
data.docComment = null;
}
comments(data);
// attributes
Attribute[] attrs = attributes(null, null, data, SEMI_BLOCK, data.factory.EMPTY(), Boolean.TRUE, null, false, NO_ATTR_SEP, true);
for (int i = 0; i < attrs.length; i++) {
func.addAttribute(attrs[i]);
}
// body
boolean oldInsideFunction = data.insideFunction;
data.insideFunction = true;
try {
// ex block
statement(data, body, CTX_FUNCTION);
} finally {
data.insideFunction = oldInsideFunction;
}
func.setEnd(data.srcCode.getPosition());
if (closure)
comments(data);
return func;
}
use of lucee.transformer.bytecode.statement.udf.Function in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method funcStatement.
/**
* Liest ein function Statement ein.
* <br />
* EBNF:<br />
* <code>identifier spaces "(" spaces identifier spaces {"," spaces identifier spaces} ")" spaces block;</code>
* @return function Statement
* @throws TemplateException
*/
private final Statement funcStatement(ExprData data, Body parent) throws TemplateException {
int pos = data.srcCode.getPos();
// read 5 tokens (returntype,access modifier,"abstract|final|static","function", function name)
String str = variableDec(data, false);
// if there is no token at all we have no function
if (str == null) {
data.srcCode.setPos(pos);
return null;
}
comments(data);
String[] tokens = new String[] { str, null, null, null, null };
tokens[1] = variableDec(data, false);
comments(data);
if (tokens[1] != null) {
tokens[2] = variableDec(data, false);
comments(data);
if (tokens[2] != null) {
tokens[3] = variableDec(data, false);
comments(data);
if (tokens[3] != null) {
tokens[4] = identifier(data, false);
comments(data);
}
}
}
// function name
String functionName = null;
for (int i = tokens.length - 1; i >= 0; i--) {
// first from right is the function name
if (tokens[i] != null) {
functionName = tokens[i];
tokens[i] = null;
break;
}
}
if (functionName == null || functionName.indexOf(',') != -1 || functionName.indexOf('[') != -1) {
data.srcCode.setPos(pos);
return null;
}
// throw new TemplateException(data.srcCode, "invalid syntax");
String returnType = null;
// search for "function"
boolean hasOthers = false, first = true;
for (int i = tokens.length - 1; i >= 0; i--) {
if ("function".equalsIgnoreCase(tokens[i])) {
// if it is the first "function" (from right) and we had already something else, the syntax is broken!
if (hasOthers && first)
throw new TemplateException(data.srcCode, "invalid syntax");
else // we already have a return type,so this is the 3th "function"!
if (returnType != null)
throw new TemplateException(data.srcCode, "invalid syntax");
else if (!first)
returnType = tokens[i];
first = false;
tokens[i] = null;
} else if (tokens[i] != null) {
hasOthers = true;
}
}
// no "function" found
if (first) {
data.srcCode.setPos(pos);
return null;
}
// access modifier
int _access, access = -1;
for (int i = 0; i < tokens.length; i++) {
if (tokens[i] != null && (_access = ComponentUtil.toIntAccess(tokens[i], -1)) != -1) {
// we already have an access modifier
if (access != -1) {
// we already have a return type
if (returnType != null)
throw new TemplateException(data.srcCode, "invalid syntax");
returnType = tokens[i];
} else
access = _access;
tokens[i] = null;
}
}
// no access defined
if (access == -1)
access = Component.ACCESS_PUBLIC;
// Non access modifier
int _modifier, modifier = Component.MODIFIER_NONE;
boolean isStatic = false;
for (int i = 0; i < tokens.length; i++) {
if (tokens[i] != null) {
_modifier = ComponentUtil.toModifier(tokens[i], Component.MODIFIER_NONE, Component.MODIFIER_NONE);
// abstract|final
if (_modifier != Component.MODIFIER_NONE) {
// we already have an Non access modifier
if (modifier != Component.MODIFIER_NONE || isStatic) {
// we already have a return type
if (returnType != null)
throw new TemplateException(data.srcCode, "invalid syntax");
returnType = tokens[i];
} else
modifier = _modifier;
tokens[i] = null;
} else // static
if (tokens[i].equalsIgnoreCase("static")) {
// we already have an Non access modifier
if (modifier != Component.MODIFIER_NONE || isStatic) {
// we already have a return type
if (returnType != null)
throw new TemplateException(data.srcCode, "invalid syntax");
returnType = tokens[i];
} else
isStatic = true;
tokens[i] = null;
}
}
}
// return type
for (int i = 0; i < tokens.length; i++) {
if (tokens[i] != null) {
if (returnType != null)
throw new TemplateException(data.srcCode, "invalid syntax");
returnType = tokens[i];
}
}
Position line = data.srcCode.getPosition();
// Name
if (!data.isCFC && !data.isInterface) {
FunctionLibFunction flf = getFLF(data, functionName);
try {
if (flf != null && flf.getFunctionClassDefinition().getClazz() != CFFunction.class) {
PageSource ps = null;
if (data.srcCode instanceof PageSourceCode) {
ps = ((PageSourceCode) data.srcCode).getPageSource();
}
String path = null;
if (ps != null) {
path = ps.getDisplayPath();
path = path.replace('\\', '/');
}
if (// TODO make better
path == null || path.indexOf("/library/function/") == -1)
throw new TemplateException(data.srcCode, "The name [" + functionName + "] is already used by a built in Function");
}
} catch (Throwable t) {
ExceptionUtil.rethrowIfNecessary(t);
throw new PageRuntimeException(Caster.toPageException(t));
}
}
Function res = closurePart(data, functionName, access, modifier, returnType, line, false);
if (isStatic) {
if (data.context == CTX_INTERFACE)
throw new TemplateException(data.srcCode, "static functions are not allowed within the interface body");
TagOther tag = createStaticTag(data, res.getStart());
tag.getBody().addStatement(res);
return tag;
}
return res;
}
Aggregations