code: func primitiveEquals(i *interpreter, trace TraceElement, x, y value) (value, error) {
  	if x.getType() != y.getType() {
  		return makeValueBoolean(false), nil
  	}
  	switch left := x.(type) {
  	case *valueBoolean:
  		right, err := i.getBoolean(y, trace)
  		if err != nil {
  			return nil, err
  		}
  		return makeValueBoolean(left.value == right.value), nil
  	case *valueNumber:
  		right, err := i.getNumber(y, trace)
  		if err != nil {
  			return nil, err
  		}
  		return makeValueBoolean(left.value == right.value), nil
  	case *valueString:
  		right, err := i.getString(y, trace)
  		if err != nil {
  			return nil, err
  		}
  		return makeValueBoolean(stringEqual(left, right)), nil
  	case *valueNull:
  		return makeValueBoolean(true), nil
  	case *valueFunction:
  		return nil, i.Error("Cannot test equality of functions", trace)
  	default:
  		return nil, i.Error(
  			"primitiveEquals operates on primitive types, got "+x.getType().name,
  			trace,
  		)
  	}
  }
docs: // TODO(sbarzowski) since we have a builtin implementation of equals it's no longer really
  // needed and we should deprecate it eventually