// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)

////////////////////////////////
//~ rjf: Built-In View Rules
//
// @view_rule_info
//
// NOTE(rjf): View rules are subtle in that they may impact any subset of the
// eval visualization pipeline. The "array" view rule, for example, functions
// by tweaking the type of an eval from `X *` to `X (*)[N]` (where N is
// computed from whatever expression is specified by the view rule). The "list"
// view rule, on the other hand, does not require any changes to the actual
// eval nor its type - instead, it follows an alternative path in constructing
// "viz blocks", and then constructing "viz rows" from those blocks. Compare
// these to the simpler 'dec', 'bin', or 'oct' rules, which simply tweak the
// radix used when stringizing numbers, which is something that only occurs in
// single-line eval stringization building.
//
// As such, each view rule specification has a mask, which determines which
// stages it may be used for. For a given view rule specification, if the bit
// corresponding to a particular eval stage is set, then that view rule spec-
// -ification also includes a hook which can be called from that stage.
//
// Below is a list of the stages in the eval visualization pipeline, as well as
// abbreviations which are used in the tables.
//
// expr resolution, "xp" -> provides a chance for a view rule to make
//                          modifications to expression trees that it is
//                          applied to
//
// viz block prod, "vb"  -> given a resolved eval, produce a list of non-
//                          windowed "viz blocks", which correspond to one or
//                          many contiguous rows in a watch-window-style UI.
//                          one level of expanded struct members, with no sub-
//                          expansions, would be one viz block. if one of those
//                          members - in the middle - were expanded too, then
//                          it would require three viz blocks - one for the
//                          members before the sub-expansion, one for the
//                          sub expansion members, and one for the members
//                          after, and so on. this is done recursively.
//
// viz row prod, "vr"    -> given a list of viz blocks, a windowed list of viz
//                          rows may be produced. each of these rows has info
//                          for building actual UI in e.g. a watch window -
//                          whether or not the row can be expanded, whether or
//                          not the row's value can be edited, what the edit-
//                          able string is for a row, what the display string
//                          is for a row, what the expression string is for a
//                          row, what the type is for a row, and so on.
//                          
// line stringize, "ls"  -> this is the stage used to produce display strings
//                          in the "viz row prod" stage, as well as basically
//                          any time UI needs to display the result of an eval
//                          in a single line. this also occurs recursively,
//                          descending into members & elements as needed,
//                          constrained by # of available pixels and font size
//                          and so on.
//
// row ui build, "ru"    -> finally, after the previous stages are completed,
//                          ui can finally be built according to all of the
//                          per-row information produced. this is the stage
//                          where view rules can insert their own arbitrary ui
//                          on a per-row basis.
//
// view ui build, "vu"   -> view rules which want to supply more sophisticated
//                          visualizers have the ability to provide full
//                          arbitrary UI hooks, which can either be produced
//                          in a minified form via watch views, or via a
//                          standalone tab.
//
// A few other bits are included for various ways in which a view rule may be
// applied throughout the eval visualization pipeline. A list follows:
//
// inherited, "ih"       -> is this view rule included, or not included, in
//                          child expansions?
//
// expandable, "ex"      -> does this view rule force the ability to expand
//                          an expression, even if traditional analysis of type
//                          info would not allow expansion?
//
// Not all of these stages are specified at this layer, however, since the
// "df_core" layer is for the non-graphical core debugger features. So the
// information pertaining to the eval visualization pipeline stages which
// do require graphical subsystems (e.g. UI, fonts, rendering) are specified
// in the "df_gfx" layer.
//
// For any view rules in this layer which also have graphical features, they
// are specified in both tables under the same name.

@table(coverage_check  name  name_lower  string          ih  ex  xr  xe  vb                display_name                  docs    schema                                                         description)
EV_ViewRuleTable:
{
  {x  Default    default     "default"                    -   -   -   x   x                 "Default"                     -       ""                                                             ""                                                                                                                                                                           }
  {x  Array      array       "array"                      -   -   x   -   -                 "Array"                       x       "x:{expr}"                                                     "Specifies that a pointer points to N elements, rather than only 1."                                                                                                         }
  {x  Slice      slice       "slice"                      -   -   x   -   -                 "Slice"                       x       ""                                                             "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer."                                             }
  {x  ByteSwap   bswap       "bswap"                      x   -   x   -   -                 "Byte Swap"                   x       ""                                                             "Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed."                                                                    }
  {x  Cast       cast        "cast"                       -   -   x   -   -                 "Cast"                        x       "x:{type}"                                                     "Specifies that the expression to which the view rule is applied should be casted to the provided type."                                                                     }
  {x  Only       only        "only"                       x   -   x   -   -                 "Only"                        x       ""                                                             "Specifies that only the provided member names should be shown in user-defined-type expansions."                                                                             }
  {x  Omit       omit        "omit"                       x   -   x   -   -                 "Omit"                        x       ""                                                             "Specifies that the provided member names should not be shown in user-defined-type expansions."                                                                              }
  {x  Bin        bin         "bin"                        x   -   -   -   -                 "Display In Binary"           x       ""                                                             "Specifies that all numeric values should be shown in base 2 (binary)."                                                                                                      }
  {x  Oct        oct         "oct"                        x   -   -   -   -                 "Display In Octal"            x       ""                                                             "Specifies that all numeric values should be shown in base 8 (octal)."                                                                                                       }
  {x  Dec        dec         "dec"                        x   -   -   -   -                 "Display In Decimal"          x       ""                                                             "Specifies that all numeric values should be shown in base 10 (decimal)."                                                                                                    }
  {x  Hex        hex         "hex"                        x   -   -   -   -                 "Display In Hexadecimal"      x       ""                                                             "Specifies that all numeric values should be shown in base 16 (hexadecimal)."                                                                                                }
}

@enum EV_ViewRuleKind:
{
  @expand(EV_ViewRuleTable a) `$(a.name)`,
  COUNT,
}

@gen
{
  @expand(EV_ViewRuleTable a) `$(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`;
  @expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
  @expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
  @expand(EV_ViewRuleTable a) `$(a.vb == "x" -> "EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(" .. a.name_lower .. ");")`;
}

@data(EV_ViewRuleInfo) @c_file ev_builtin_view_rule_info_table:
{
  @expand(EV_ViewRuleTable a)
    ```{str8_lit_comp("$(a.string)"), (EV_ViewRuleInfoFlag_Inherited*$(a.ih == "x"))|(EV_ViewRuleInfoFlag_Expandable*$(a.ex == "x")), $(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.xr != "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil)"), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity), $(a.vb == "x" -> "EV_VIEW_RULE_BLOCK_PROD_FUNCTION_NAME("..a.name_lower..")") $(a.vb != "x" -> 0), }```;
}
