docs: public FEELFnResult<Object> evaluate(EvaluationContext ctx, Object[] params) {
          if ( decisionRules.isEmpty() ) {
              return FEELFnResult.ofError(new FEELEventBase(Severity.WARN, "Decision table is empty", null));
          }
          
          Object[] actualInputs = resolveActualInputs( ctx, feel );
  
          Either<FEELEvent, Object> actualInputMatch = actualInputsMatchInputValues( ctx, actualInputs );
          if ( actualInputMatch.isLeft() ) {
              return actualInputMatch.cata( e -> FEELFnResult.ofError(e), e -> FEELFnResult.ofError(null) );
          }
  
          List<DTDecisionRule> matches = findMatches( ctx, actualInputs );
          if( !matches.isEmpty() ) {
              List<Object> results = evaluateResults( ctx, feel, actualInputs, matches );
              Map<Integer, String> msgs = checkResults( ctx, matches, results );
              if( msgs.isEmpty() ) {
                  Object result = hitPolicy.getDti().dti( ctx, this, matches, results );
                  return FEELFnResult.ofResult( result );
              } else {
                  List<Integer> offending = msgs.keySet().stream().collect( Collectors.toList());
                  return FEELFnResult.ofError( new HitPolicyViolationEvent(
                          Severity.ERROR,
                          "Errors found evaluating decision table '"+getName()+"': \n"+(msgs.values().stream().collect( Collectors.joining( "\n" ) )),
                          name,
                          offending ) );
              }
          } else {
              // check if there is a default value set for the outputs
              if( hasDefaultValues ) {
                  Object result = defaultToOutput( ctx, feel );
                  return FEELFnResult.ofResult( result );
              } else {
                  if( hitPolicy.getDefaultValue() != null ) {
                      return FEELFnResult.ofResult( hitPolicy.getDefaultValue() );
                  }
                  return FEELFnResult.ofError( new HitPolicyViolationEvent(
                                                      Severity.WARN,
                                                      "No rule matched for decision table '" + name + "' and no default values were defined. Setting result to null.",
                                                      name,
                                                      Collections.EMPTY_LIST ) );
              }
          }
      }