use of lucee.transformer.bytecode.statement.Argument in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method getScriptFunctionArguments.
@Override
public ArrayList<Argument> getScriptFunctionArguments(ExprData data) throws TemplateException {
// arguments
LitBoolean passByRef;
Expression displayName;
Expression hint;
Map<String, Attribute> meta;
String _name;
ArrayList<Argument> result = new ArrayList<Argument>();
do {
comments(data);
// finish
if (data.srcCode.isCurrent(')'))
break;
// attribute
// name
// String idName=identifier(data,false,true);
boolean required = false;
String idName = variableDec(data, false);
// required
if ("required".equalsIgnoreCase(idName)) {
comments(data);
String idName2 = variableDec(data, false);
if (idName2 != null) {
idName = idName2;
required = true;
}
if (idName == null)
throw new TemplateException(data.srcCode, "invalid argument definition");
}
String typeName = "any";
if (idName == null)
throw new TemplateException(data.srcCode, "invalid argument definition");
comments(data);
if (!data.srcCode.isCurrent(')') && !data.srcCode.isCurrent('=') && !data.srcCode.isCurrent(':') && !data.srcCode.isCurrent(',')) {
typeName = idName.toLowerCase();
// MUST was upper case before, is this a problem?
idName = identifier(data, false);
} else if (idName.indexOf('.') != -1 || idName.indexOf('[') != -1) {
throw new TemplateException(data.srcCode, "invalid argument name [" + idName + "] definition");
}
if (idName == null)
throw new TemplateException(data.srcCode, "invalid argument definition");
comments(data);
Expression defaultValue;
if (data.srcCode.isCurrent('=') || data.srcCode.isCurrent(':')) {
data.srcCode.next();
comments(data);
defaultValue = expression(data);
} else
defaultValue = null;
// assign meta data defined in doc comment
passByRef = data.factory.TRUE();
displayName = data.factory.EMPTY();
hint = data.factory.EMPTY();
meta = null;
if (data.docComment != null) {
Map<String, Attribute> params = data.docComment.getParams();
Attribute[] attrs = params.values().toArray(new Attribute[params.size()]);
Attribute attr;
String name;
for (int i = 0; i < attrs.length; i++) {
attr = attrs[i];
name = attr.getName();
// hint
if (idName.equalsIgnoreCase(name) || name.equalsIgnoreCase(idName + ".hint")) {
hint = data.factory.toExprString(attr.getValue());
params.remove(name);
}
// meta
if (StringUtil.startsWithIgnoreCase(name, idName + ".")) {
if (name.length() > idName.length() + 1) {
if (meta == null)
meta = new HashMap<String, Attribute>();
_name = name.substring(idName.length() + 1);
meta.put(_name, new Attribute(attr.isDynamicType(), _name, attr.getValue(), attr.getType()));
}
params.remove(name);
}
}
}
// argument attributes
Attribute[] _attrs = attributes(null, null, data, COMMA_ENDBRACKED, data.factory.EMPTY(), Boolean.TRUE, null, false, NO_ATTR_SEP, true);
Attribute _attr;
if (!ArrayUtil.isEmpty(_attrs)) {
if (meta == null)
meta = new HashMap<String, Attribute>();
for (int i = 0; i < _attrs.length; i++) {
_attr = _attrs[i];
meta.put(_attr.getName(), _attr);
}
}
result.add(new Argument(data.factory.createLitString(idName), data.factory.createLitString(typeName), data.factory.createLitBoolean(required), defaultValue, passByRef, displayName, hint, meta));
comments(data);
} while (data.srcCode.forwardIfCurrent(','));
return result;
}
use of lucee.transformer.bytecode.statement.Argument in project Lucee by lucee.
the class Function method createArguments.
private final void createArguments(BytecodeContext bc) throws TransformerException {
GeneratorAdapter ga = bc.getAdapter();
ga.push(arguments.size());
ga.newArray(FUNCTION_ARGUMENT);
Argument arg;
for (int i = 0; i < arguments.size(); i++) {
arg = arguments.get(i);
boolean canHaveKey = Factory.canRegisterKey(arg.getName());
// CHECK if default values
// type
ExprString _strType = arg.getType();
short _type = CFTypes.TYPE_UNKNOW;
if (_strType instanceof LitString) {
_type = CFTypes.toShortStrict(((LitString) _strType).getString(), CFTypes.TYPE_UNKNOW);
}
boolean useType = !canHaveKey || _type != CFTypes.TYPE_ANY;
// boolean useStrType=useType && (_type==CFTypes.TYPE_UNDEFINED || _type==CFTypes.TYPE_UNKNOW || CFTypes.toString(_type, null)==null);
// required
ExprBoolean _req = arg.getRequired();
boolean useReq = !canHaveKey || toBoolean(_req, null) != Boolean.FALSE;
// default-type
Expression _def = arg.getDefaultValueType(bc.getFactory());
boolean useDef = !canHaveKey || toInt(_def, -1) != FunctionArgument.DEFAULT_TYPE_NULL;
// pass by reference
ExprBoolean _pass = arg.isPassByReference();
boolean usePass = !canHaveKey || toBoolean(_pass, null) != Boolean.TRUE;
// display-hint
ExprString _dsp = arg.getDisplayName();
boolean useDsp = !canHaveKey || !isLiteralEmptyString(_dsp);
// hint
ExprString _hint = arg.getHint();
boolean useHint = !canHaveKey || !isLiteralEmptyString(_hint);
// meta
Map _meta = arg.getMetaData();
boolean useMeta = !canHaveKey || (_meta != null && !_meta.isEmpty());
int functionIndex = 7;
if (!useMeta) {
functionIndex--;
if (!useHint) {
functionIndex--;
if (!useDsp) {
functionIndex--;
if (!usePass) {
functionIndex--;
if (!useDef) {
functionIndex--;
if (!useReq) {
functionIndex--;
if (!useType) {
functionIndex--;
}
}
}
}
}
}
}
// write out arguments
ga.dup();
ga.push(i);
// new FunctionArgument(...)
ga.newInstance(canHaveKey && functionIndex < INIT_FAI_KEY_LIGHT.length ? FUNCTION_ARGUMENT_LIGHT : FUNCTION_ARGUMENT_IMPL);
ga.dup();
// name
bc.getFactory().registerKey(bc, arg.getName(), false);
// type
if (functionIndex >= INIT_FAI_KEY.length - 7) {
_strType.writeOut(bc, Expression.MODE_REF);
bc.getAdapter().push(_type);
}
// required
if (functionIndex >= INIT_FAI_KEY.length - 6)
_req.writeOut(bc, Expression.MODE_VALUE);
// default value
if (functionIndex >= INIT_FAI_KEY.length - 5)
_def.writeOut(bc, Expression.MODE_VALUE);
// pass by reference
if (functionIndex >= INIT_FAI_KEY.length - 4)
_pass.writeOut(bc, Expression.MODE_VALUE);
// display-name
if (functionIndex >= INIT_FAI_KEY.length - 3)
_dsp.writeOut(bc, Expression.MODE_REF);
// hint
if (functionIndex >= INIT_FAI_KEY.length - 2)
_hint.writeOut(bc, Expression.MODE_REF);
// meta
if (functionIndex == INIT_FAI_KEY.length - 1)
Page.createMetaDataStruct(bc, _meta, null);
if (functionIndex < INIT_FAI_KEY_LIGHT.length)
ga.invokeConstructor(FUNCTION_ARGUMENT_LIGHT, INIT_FAI_KEY[functionIndex]);
else
ga.invokeConstructor(FUNCTION_ARGUMENT_IMPL, INIT_FAI_KEY[functionIndex]);
ga.visitInsn(Opcodes.AASTORE);
}
}
use of lucee.transformer.bytecode.statement.Argument in project Lucee by lucee.
the class SourceLastModifiedClassAdapter method writeOutFunctionDefaultValueInnerInner.
private void writeOutFunctionDefaultValueInnerInner(BytecodeContext bc, Function function) throws TransformerException {
GeneratorAdapter adapter = bc.getAdapter();
List<Argument> args = function.getArguments();
if (args.size() == 0) {
adapter.loadArg(DEFAULT_VALUE);
adapter.returnValue();
return;
}
Iterator<Argument> it = args.iterator();
Argument arg;
ConditionVisitor cv = new ConditionVisitor();
DecisionIntVisitor div;
cv.visitBefore();
int count = 0;
while (it.hasNext()) {
arg = it.next();
cv.visitWhenBeforeExpr();
div = new DecisionIntVisitor();
div.visitBegin();
adapter.loadArg(2);
div.visitEQ();
adapter.push(count++);
div.visitEnd(bc);
cv.visitWhenAfterExprBeforeBody(bc);
Expression defaultValue = arg.getDefaultValue();
if (defaultValue != null) {
/*if(defaultValue instanceof Null) {
adapter.invokeStatic(NULL, GET_INSTANCE);
}
else*/
defaultValue.writeOut(bc, Expression.MODE_REF);
} else
adapter.loadArg(DEFAULT_VALUE);
// adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
cv.visitWhenAfterBody(bc);
}
cv.visitOtherviseBeforeBody();
// adapter.visitInsn(ACONST_NULL);
// adapter.returnValue();
cv.visitOtherviseAfterBody();
cv.visitAfter(bc);
}
use of lucee.transformer.bytecode.statement.Argument in project Lucee by lucee.
the class AbstrCFMLScriptTransformer method lambdaPart.
@Override
protected final Function lambdaPart(ExprData data, String id, int access, int modifier, String rtnType, Position line, ArrayList<Argument> args) throws TemplateException {
Body body = new FunctionBody(data.factory);
Function func = new Lambda(data.root, id, access, modifier, rtnType, body, line, null);
// new FunctionImpl(data.page,id,access,rtnType,body,line,null);
comments(data);
// add arguments
for (Argument arg : args) {
func.addArgument(arg.getName(), arg.getType(), arg.getRequired(), arg.getDefaultValue(), arg.isPassByReference(), arg.getDisplayName(), arg.getHint(), arg.getMetaData());
}
comments(data);
// body
boolean oldInsideFunction = data.insideFunction;
data.insideFunction = true;
try {
if (data.srcCode.isCurrent('{')) {
statement(data, body, CTX_FUNCTION);
} else {
if (data.srcCode.forwardIfCurrent("return ")) {
comments(data);
}
// ex block
short prior = data.context;
data.context = CTX_FUNCTION;
comments(data);
Expression expr = expression(data);
// checkSemiColonLineFeed( data, true ,true );
Return rtn = new Return(expr, line, data.srcCode.getPosition());
body.addStatement(rtn);
data.docComment = null;
data.context = prior;
}
} finally {
data.insideFunction = oldInsideFunction;
}
/*try {
// ex block
statement(data,body,CTX_FUNCTION);
}
finally{
data.insideFunction=oldInsideFunction;
}*/
func.setEnd(data.srcCode.getPosition());
comments(data);
return func;
}
use of lucee.transformer.bytecode.statement.Argument 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;
}
Aggregations