call method

A call of builtin, its arguments checked by count, width and unit.

Implementation

Expression call(ExpressionBuiltin builtin, ExpressionToken token) {
  final parts = arguments();
  if (parts.length != builtin.arity) {
    fail(
      '${builtin.name} takes ${builtin.arity} arguments and was given '
      '${parts.length}.',
      where: token,
    );
  }
  var width = 1;
  for (final part in parts) {
    if (!part.type.isNumeric) {
      fail(
        '${builtin.name} takes numbers, not a ${part.type}.',
        where: token,
      );
    }
    if (part.type.components > width) width = part.type.components;
  }
  for (final part in parts) {
    final components = part.type.components;
    if (components != width && !(builtin.componentWise && components == 1)) {
      fail(
        '${builtin.name} was given a ${part.type} beside a '
        '${ExpressionType.numeric[width]}.',
        where: token,
      );
    }
  }
  final dimension =
      builtin.dimension(parts) ??
      fail(
        '${builtin.name} ${builtin.units}, and was given '
        '${parts.map((part) => part.type).join(', ')}.',
        where: token,
      );
  final resultWidth = builtin.resultComponents ?? width;
  return ExpressionCall(
    builtin,
    parts,
    ExpressionType.numeric[resultWidth]!.withDimension(dimension),
  );
}