balanceTypesInMathExpression = expression => {
  // find the heaviest type in the expression
  const type = expression.params.reduce((acc, { type: childType }) => {
    // The way we do that is by scanning the top-level nodes in our expression
    if (typeWeight(acc) < typeWeight(childType)) {
      return childType;
    }

    return acc;
  }, expression.type);

  // iterate again, this time, patching any lighter types
  const params = expression.params.map(paramNode => {
    if (
      paramNode.type != null &&
      typeWeight(paramNode.type) !== typeWeight(type)
    ) {
      // Convert constants to the desired type directly
      if (paramNode.Type === Syntax.Constant) {
        return extendNode(
          {
            type,
          },
          paramNode
        );
      }

      return extendNode(
        {
          type,
          value: paramNode.value,
          Type: Syntax.TypeCast,
          meta: {
            [TYPE_CAST]: { to: type, from: paramNode.type },
          },
          params: [paramNode],
        },
        paramNode
      );
    }

    return paramNode;
  });

  return {
    ...expression,
    params,
    type,
  };
}
Core language plugin

The parsers in here very closely mirror the underlying WebAssembly structure
and are used as the core language for every feature built on top.

@flow