User Guide
Advanced
Trace

Trace

Trace is a distinctive feature of CPLib, which can record the inclusion relationship of variables when they are read in. Through this feature, CPLib can provide a read-in stack trace when an error occurs during variable reading, or convert the input file into a JSON format that is easy to parse.

Introduction

The principle of Trace is to maintain a stack (or a tree at the same time) composed of the inclusion relationship of variables when using cplib::var::Reader::read to read variables. When a variable is about to be read in, the current line and column position, byte sequence number, variable name, and other information of the input stream are pushed onto the stack (or added as a leaf node to the current node in the tree). When the variable reading is completed, it is popped off the stack (or backtracked to the parent node in the tree).

CPLib has two forms of trace: trace stack and trace tree, corresponding to the stack and tree respectively. Among them, the trace stack only contains basic information about the variables, while the trace tree allows additional JSON tags to be added to the nodes to describe additional information.

JSON Tag

You can add JSON tags to the nodes of the trace tree to describe more detailed information. A JSON tag is a mapping from a string key name to any JSON value supported by CPLib.

When implementing custom types (such as FnVar or ExtVar), you can call in.attach_json_tag(key, value) to customize a key-value pair of additional information (where in is the current Reader being read). The key should not be repeated, otherwise the later defined one will overwrite the earlier one.

The built-in variable read-in templates (except cplib::var::Separator) in CPLib will add a key #t at the end of the variable reading to indicate the type of the variable. If the read-in type is a basic type or a string, an additional key #v will be added to indicate the value read-in. The variable read-in templates and the corresponding values of #t are as follows:

Var#t
Inti
Floatf
StrictFloatsf
YesNoyn
Strings
Linel
Vecv
Matm
Pairp
Tuplet
FnVarF
ExtVarE

#hidden is a special key, and if this key (regardless of the value) exists in the JSON tag of a node, the nodes in the subtree of the current node will be ignored when encoded as JSON. The variable read-in template cplib::var::Separator will add #hidden to the current node when the reading is completed.

⚠️

Key names starting with # are all considered reserved or have special purposes by CPLib. It is best not to use special prefixes when customizing additional information.

Interface

The interfaces related to trace in CPLib are as follows.

cplib::var::Reader::TraceLevel

cplib::var::Reader::TraceLevel represents the trace enablement level of the Reader, with three possible values:

  • NONE (0): Completely disable trace.
  • STACK_ONLY (1): Only enable trace stack.
  • FULL (2): Enable both trace stack and trace tree.

In the default case of using DefaultInitializer, the inf reader in validator mode has a FULL level, while the Reader in other modes has a STACK_ONLY level.

You can use the CPLIB_VAR_READER_TRACE_LEVEL_MAX macro to set the maximum trace level used by the DefaultInitializer. The specific method is to add the command line argument -DCPLIB_VAR_READER_TRACE_LEVEL_MAX={int} at compile time, or define #define CPLIB_VAR_READER_TRACE_LEVEL_MAX {int} before #include "cplib.h".

You can use the cplib::var::Reader::get_trace_level() method to get the trace level of the Reader.

cplib::var::Reader::Trace

Contains the basic information of a variable:

  • var_name: The name of the variable.
  • pos.line: The line number when the reading started, numbered from 0.
  • pos.col: The column number when the reading started, numbered from 0.
  • pos.byte: The byte sequence number when the reading started, numbered from 0.
  • byte_length: The byte length of the original content corresponding to the variable. Specifically, for variables that have not finished reading, this is 0.

It provides two functions, to_json_incomplete and to_json_complete, to encode its own content into JSON, which are suitable for variables that have not finished reading and those that have finished reading, respectively. Among them, to_json_incomplete will export all fields except byte_length using the original name; while to_json_complete will only export the three fields var_name, byte_num, and byte_length, and they will be renamed to n, b, and l respectively to avoid generating too long JSON.

cplib::var::Reader::TraceStack

Records the read-in stack of the current variable, or can also be seen as the chain from the root (not included) to the current node (included) of the read-in tree.

It provides three methods, to_json(), to_plain_text_lines(), and to_colored_text_lines(), to convert it to the corresponding format.

For Readers with STACK_ONLY or higher level enabled, you can use the cplib::var::Reader::get_trace_stack() method to get the trace stack of the currently read-in variable.

cplib::var::Reader::TraceTreeNode

Represents a node in the trace tree.

The trace field records the basic information of the variable in the cplib::var::Reader::Trace type, and the json_tag field records the additional information of the variable.

It provides the get_children() method to get the child nodes of the current node, and the get_parent() method to get the parent node of the current node, which returns nullptr if it does not exist.

It also provides the to_json() method to convert its subtree to JSON.

For Readers with the FULL level enabled, you can use the cplib::var::Reader::get_trace_tree() method to get the root node of the trace tree for all variables read-in by that Reader. The Trace variable name of the root node is <root>.