preExecute method
Implementation
@override
FunctionCallPreExecutionResult? preExecute(DartBlockArbiter arbiter) {
final DartBlockFunction? customFunction = arbiter.retrieveCustomFunction(
customFunctionName,
);
if (customFunction == null) {
throw UndefinedCustomFunctionException(customFunctionName);
}
if (customFunction.parameters.length != arguments.length) {
throw CustomFunctionArgumentsCountException(
customFunctionName,
customFunction.parameters.length,
arguments.length,
);
}
List<VariableDeclarationStatement> parameterDeclarations = [];
for (var (idx, argument) in arguments.indexed) {
/// Get the concrete value in the preExecute step, as the variable scope
/// (Environment) has not yet changed.
final concreteValue = argument.getValue(arbiter);
final expectedParameter = customFunction.parameters[idx];
final (isCorrectType, givenWrongType) = arbiter
.verifyDataTypeOfConcreteValue(
expectedParameter.dataType,
concreteValue,
);
if (isCorrectType) {
/// Re-convert the concrete value back to a wrapper NeoValue object,
/// based on the expected data type of the corresponding function parameter.
DartBlockValue? passedValue;
if (concreteValue != null) {
switch (expectedParameter.dataType) {
case DartBlockDataType.integerType:
case DartBlockDataType.doubleType:
if (concreteValue is num) {
passedValue = DartBlockAlgebraicExpression.fromConstant(
concreteValue,
);
}
break;
case DartBlockDataType.booleanType:
if (concreteValue is bool) {
passedValue = DartBlockBooleanExpression.fromConstant(
concreteValue,
);
}
break;
case DartBlockDataType.stringType:
if (concreteValue is String) {
passedValue = DartBlockConcatenationValue.init([
DartBlockStringValue.init(concreteValue),
]);
}
break;
}
}
parameterDeclarations.add(
VariableDeclarationStatement.init(
expectedParameter.name,
expectedParameter.dataType,
/// Do NOT use argument here, as it will cause issues in certain cases, e.g.,
/// if the value contains a NeoVariable which only exists in the current
/// variable scope. Remember that the variable scope changes to a new,
/// isolated one after preExecute, hence, we use passedValue here.
passedValue,
),
);
} else {
throw CustomFunctionMissingArgumentException(
customFunctionName,
expectedParameter,
idx,
givenWrongType!,
);
}
}
return FunctionCallPreExecutionResult(
customFunction,
parameterDeclarations,
);
}